From 733993a651c71f7e2198d505960d6bbd31e0e107 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 18 Nov 2017 11:22:02 -0500 Subject: Move everything to sway/old/ --- common/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'common') diff --git a/common/log.c b/common/log.c index 6dc9d743..c47b4eea 100644 --- a/common/log.c +++ b/common/log.c @@ -9,7 +9,6 @@ #include #include #include "log.h" -#include "sway.h" #include "readline.h" static int colored = 1; @@ -117,6 +116,7 @@ void _sway_log(const char *filename, int line, log_importance_t verbosity, const va_end(args); } +void sway_terminate(int code); void _sway_abort(const char *filename, int line, const char* format, ...) { va_list args; -- cgit v1.2.3 From 977c1f6a30b9ef21be363ec9fca1d9044b2905c6 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Thu, 23 Nov 2017 00:23:37 +0100 Subject: common/util: replace WLC_BIT_MOD_* by WLR_MODIFIER_* This removes the last wlc/wlc.h include actually in use --- common/util.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'common') diff --git a/common/util.c b/common/util.c index d6369853..83981160 100644 --- a/common/util.c +++ b/common/util.c @@ -8,8 +8,8 @@ #include #include #include -#include #include +#include #include "log.h" #include "readline.h" #include "util.h" @@ -29,16 +29,16 @@ static struct modifier_key { char *name; uint32_t mod; } modifiers[] = { - { XKB_MOD_NAME_SHIFT, WLC_BIT_MOD_SHIFT }, - { XKB_MOD_NAME_CAPS, WLC_BIT_MOD_CAPS }, - { XKB_MOD_NAME_CTRL, WLC_BIT_MOD_CTRL }, - { "Ctrl", WLC_BIT_MOD_CTRL }, - { XKB_MOD_NAME_ALT, WLC_BIT_MOD_ALT }, - { "Alt", WLC_BIT_MOD_ALT }, - { XKB_MOD_NAME_NUM, WLC_BIT_MOD_MOD2 }, - { "Mod3", WLC_BIT_MOD_MOD3 }, - { XKB_MOD_NAME_LOGO, WLC_BIT_MOD_LOGO }, - { "Mod5", WLC_BIT_MOD_MOD5 }, + { XKB_MOD_NAME_SHIFT, WLR_MODIFIER_SHIFT }, + { XKB_MOD_NAME_CAPS, WLR_MODIFIER_CAPS }, + { XKB_MOD_NAME_CTRL, WLR_MODIFIER_CTRL }, + { "Ctrl", WLR_MODIFIER_CTRL }, + { XKB_MOD_NAME_ALT, WLR_MODIFIER_ALT }, + { "Alt", WLR_MODIFIER_ALT }, + { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, + { "Mod3", WLR_MODIFIER_MOD3 }, + { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, + { "Mod5", WLR_MODIFIER_MOD5 }, }; uint32_t get_modifier_mask_by_name(const char *name) { -- cgit v1.2.3 From 88cc7e31781a0d42bdd4f9eee646c02ff03857c4 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 03:39:27 -0500 Subject: use meson subdirectories --- common/meson.build | 8 ++++++++ meson.build | 35 ++--------------------------------- sway/meson.build | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 33 deletions(-) create mode 100644 common/meson.build create mode 100644 sway/meson.build (limited to 'common') diff --git a/common/meson.build b/common/meson.build new file mode 100644 index 00000000..ca1f1752 --- /dev/null +++ b/common/meson.build @@ -0,0 +1,8 @@ +sway_common = files( + 'log.c', + 'list.c', + 'util.c', + 'stringop.c', + 'readline.c', + 'ipc-client.c' +) diff --git a/meson.build b/meson.build index 06eed97f..a28e1097 100644 --- a/meson.build +++ b/meson.build @@ -30,37 +30,6 @@ add_project_arguments('-DSWAY_VERSION="5"', language: 'c') sway_inc = include_directories('include') -sway_sources = [ - 'sway/main.c', - 'sway/server.c', - 'sway/commands.c', - 'sway/commands/exit.c', - 'sway/ipc-json.c', - 'sway/ipc-server.c', - 'sway/desktop/output.c', - 'sway/desktop/xdg_shell_v6.c', - 'sway/tree/container.c', - 'sway/tree/layout.c', - 'sway/tree/workspace.c', - 'common/log.c', - 'common/list.c', - 'common/stringop.c', - 'common/readline.c', - 'common/ipc-client.c', -] +subdir('common') +subdir('sway') -sway_deps = [ - pixman, - wayland_server, - jsonc, - wlroots, - libcap, - math, -] - -executable( - 'sway', - sway_sources, - include_directories: [sway_inc], - dependencies: sway_deps -) diff --git a/sway/meson.build b/sway/meson.build new file mode 100644 index 00000000..1f17ed31 --- /dev/null +++ b/sway/meson.build @@ -0,0 +1,29 @@ +sway_sources = sway_common + files( + 'main.c', + 'server.c', + 'commands.c', + 'commands/exit.c', + 'ipc-json.c', + 'ipc-server.c', + 'desktop/output.c', + 'desktop/xdg_shell_v6.c', + 'tree/container.c', + 'tree/layout.c', + 'tree/workspace.c', +) + +sway_deps = [ + pixman, + wayland_server, + jsonc, + wlroots, + libcap, + math, +] + +executable( + 'sway', + sway_sources, + include_directories: [sway_inc], + dependencies: sway_deps +) -- cgit v1.2.3 From cc310cffb0bf4cd2333be26a2ae16848655a306b Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 06:25:13 -0500 Subject: meson: common static library --- common/meson.build | 17 ++++++++++------- sway/meson.build | 5 +++-- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/meson.build b/common/meson.build index ca1f1752..3a4282ad 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,8 +1,11 @@ -sway_common = files( - 'log.c', - 'list.c', - 'util.c', - 'stringop.c', - 'readline.c', - 'ipc-client.c' +lib_sway_common = static_library('sway-common', + files( + 'log.c', + 'list.c', + 'util.c', + 'stringop.c', + 'readline.c', + 'ipc-client.c' + ), + include_directories: sway_inc ) diff --git a/sway/meson.build b/sway/meson.build index 1f17ed31..b02506c8 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -1,4 +1,4 @@ -sway_sources = sway_common + files( +sway_sources = files( 'main.c', 'server.c', 'commands.c', @@ -25,5 +25,6 @@ executable( 'sway', sway_sources, include_directories: [sway_inc], - dependencies: sway_deps + dependencies: sway_deps, + link_with: [lib_sway_common] ) -- cgit v1.2.3 From 517af37cc9a9f7b5efa3e22d7021aab691c80244 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 30 Nov 2017 11:54:01 -0500 Subject: remove relevant CMakeLists.txt --- CMakeLists.txt | 165 ----------------------------------------- common/CMakeLists.txt | 15 ---- completions/zsh/CMakeLists.txt | 4 - sway/CMakeLists.txt | 96 ------------------------ swaymsg/CMakeLists.txt | 23 ------ 5 files changed, 303 deletions(-) delete mode 100644 CMakeLists.txt delete mode 100644 common/CMakeLists.txt delete mode 100644 completions/zsh/CMakeLists.txt delete mode 100644 sway/CMakeLists.txt delete mode 100644 swaymsg/CMakeLists.txt (limited to 'common') diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 9580e15d..00000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,165 +0,0 @@ -cmake_minimum_required(VERSION 3.1.0) - -project(sway C) - -add_compile_options(-g) -set(CMAKE_C_STANDARD 99) -set(CMAKE_C_EXTENSIONS OFF) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) -add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Werror) - -# Add Address Sanitiezed build type -set(CMAKE_C_FLAGS_ASAN - "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address -fno-omit-frame-pointer" - CACHE STRING "Flags used by the C compiler during address sanitizer builds." - FORCE ) -mark_as_advanced( - CMAKE_C_FLAGS_ASAN - CMAKE_EXE_LINKER_FLAGS_DEBUG - CMAKE_SHARED_LINKER_FLAGS_DEBUG - ) - -list(INSERT CMAKE_MODULE_PATH 0 - ${CMAKE_CURRENT_SOURCE_DIR}/CMake - ) - -if (VERSION) - add_definitions(-DSWAY_VERSION=\"${VERSION}\") -else() - execute_process( - COMMAND git describe --always --tags - OUTPUT_VARIABLE GIT_COMMIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - execute_process( - COMMAND git rev-parse --abbrev-ref HEAD - OUTPUT_VARIABLE GIT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - - string(TIMESTAMP CURRENT_DATE "%Y-%m-%d" UTC) - add_definitions("-DSWAY_VERSION=\"${GIT_COMMIT_HASH} (${CURRENT_DATE}, branch \\\"${GIT_BRANCH}\\\")\"") -endif() - -option(enable-swaylock "Enables the swaylock utility" YES) -option(enable-swaybg "Enables the wallpaper utility" YES) -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") - -if (LD_LIBRARY_PATH) - add_definitions(-D_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}") -endif() - -find_package(JsonC 0.12.1 REQUIRED) -find_package(PCRE REQUIRED) -find_package(Wlroots REQUIRED) -find_package(Wayland REQUIRED) -find_package(XKBCommon REQUIRED) -find_package(Cairo REQUIRED) -find_package(Pango REQUIRED) -find_package(GdkPixbuf) -find_package(PAM) -find_package(DBus 1.10) - -find_package(LibInput 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) -endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - -include(FeatureSummary) -include(Manpage) -include(GNUInstallDirs) - -if (enable-gdk-pixbuf) - if (GDK_PIXBUF_FOUND) - set(WITH_GDK_PIXBUF YES) - add_definitions(-DWITH_GDK_PIXBUF) - else() - message(WARNING "gdk-pixbuf required but not found, only png images supported.") - endif() -else() - message(STATUS "Building without gdk-pixbuf, only png images supported.") -endif() - -if (enable-tray) - if (DBUS_FOUND) - set(ENABLE_TRAY TRUE) - 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) -add_subdirectory(common) -add_subdirectory(wayland) - -add_subdirectory(sway) -if(enable-swaybg) - if(CAIRO_FOUND AND PANGO_FOUND) - # TODO WLR - #add_subdirectory(swaybg) - else() - message(WARNING "Not building swaybg - cairo, and pango are required.") - endif() -endif() -if(enable-swaymsg) - add_subdirectory(swaymsg) -endif() -if(enable-swaygrab) - # TODO WLR - #add_subdirectory(swaygrab) -endif() -if(enable-swaybar) - if(CAIRO_FOUND AND PANGO_FOUND) - # TODO WLR - #add_subdirectory(swaybar) - else() - message(WARNING "Not building swaybar - cairo, and pango are required.") - endif() -endif() -if(enable-swaylock) - if(CAIRO_FOUND AND PANGO_FOUND AND PAM_FOUND) - # TODO WLR - #add_subdirectory(swaylock) - else() - message(WARNING "Not building swaylock - cairo, pango, and PAM are required.") - endif() -endif() -if(zsh-completions) - add_subdirectory(completions/zsh) -endif() -install( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/sway.desktop - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/wayland-sessions - COMPONENT data - ) - -if(default-wallpaper) - install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/assets/ - DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/backgrounds/sway - COMPONENT data - FILES_MATCHING PATTERN "*Wallpaper*" - ) -endif() - -feature_summary(WHAT ALL) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt deleted file mode 100644 index 4fa71f3a..00000000 --- a/common/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -include_directories( - ${WLC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} -) - -add_library(sway-common STATIC - ipc-client.c - list.c - log.c - util.c - readline.c - stringop.c -) - -target_link_libraries(sway-common m) diff --git a/completions/zsh/CMakeLists.txt b/completions/zsh/CMakeLists.txt deleted file mode 100644 index 62c85090..00000000 --- a/completions/zsh/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -install( - FILES _sway _swaymsg _swaygrab _swaylock - DESTINATION ${CMAKE_INSTALL_FULL_DATAROOTDIR}/zsh/site-functions/ -) diff --git a/sway/CMakeLists.txt b/sway/CMakeLists.txt deleted file mode 100644 index 274fcc4a..00000000 --- a/sway/CMakeLists.txt +++ /dev/null @@ -1,96 +0,0 @@ -include_directories( - ${PROTOCOLS_INCLUDE_DIRS} - ${WLR_INCLUDE_DIRS} - ${PCRE_INCLUDE_DIRS} - ${JSONC_INCLUDE_DIRS} - ${XKBCOMMON_INCLUDE_DIRS} - ${LIBINPUT_INCLUDE_DIRS} - ${CAIRO_INCLUDE_DIRS} - ${PANGO_INCLUDE_DIRS} - ${WAYLAND_INCLUDE_DIR} -) - -add_executable(sway - desktop/output.c - desktop/xdg_shell_v6.c - - commands.c - commands/exit.c - - tree/container.c - tree/layout.c - tree/workspace.c - - base64.c - main.c - server.c - ipc-json.c - ipc-server.c -) - -add_definitions( - -DSYSCONFDIR="${CMAKE_INSTALL_FULL_SYSCONFDIR}" -) - -target_link_libraries(sway - sway-common - sway-protocols - sway-wayland - ${WLR_LIBRARIES} - ${XKBCOMMON_LIBRARIES} - ${PCRE_LIBRARIES} - ${JSONC_LIBRARIES} - ${WAYLAND_SERVER_LIBRARIES} - ${LIBINPUT_LIBRARIES} - ${PANGO_LIBRARIES} - ${JSONC_LIBRARIES} - m -) - -if (CMAKE_SYSTEM_NAME STREQUAL Linux) - target_link_libraries(sway cap) -endif (CMAKE_SYSTEM_NAME STREQUAL Linux) - -install( - TARGETS sway - RUNTIME - DESTINATION bin - COMPONENT runtime -) - -add_custom_target(configs ALL) - -function(add_config name source destination) - add_custom_command( - OUTPUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} - COMMAND sed -r - 's?__PREFIX__?${CMAKE_INSTALL_PREFIX}?g\; s?__SYSCONFDIR__?${CMAKE_INSTALL_FULL_SYSCONFDIR}?g\; s?__DATADIR__?${CMAKE_INSTALL_FULL_DATADIR}?g' - ${PROJECT_SOURCE_DIR}/${source}.in > ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} - DEPENDS ${PROJECT_SOURCE_DIR}/${source}.in - COMMENT "Generating config file ${source}" - ) - - install( - FILES ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name} - DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}/${destination} - COMPONENT configuration - ) - - add_custom_target(config-${name} DEPENDS ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${name}) - add_dependencies(configs config-${name}) -endfunction() - -add_config(config config sway) -add_config(00-defaults security.d/00-defaults sway/security.d) - -if (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - add_config(10-freebsd security.d/10-freebsd sway/security.d) -endif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD) - -if (A2X_FOUND) - add_manpage(sway 1) - add_manpage(sway 5) - add_manpage(sway-input 5) - add_manpage(sway-bar 5) - add_manpage(sway-security 7) -endif() diff --git a/swaymsg/CMakeLists.txt b/swaymsg/CMakeLists.txt deleted file mode 100644 index b428a409..00000000 --- a/swaymsg/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -add_executable(swaymsg - main.c -) - -include_directories( - ${JSONC_INCLUDE_DIRS} -) - -target_link_libraries(swaymsg - sway-common - ${JSONC_LIBRARIES} -) - -install( - TARGETS swaymsg - RUNTIME - DESTINATION bin - COMPONENT runtime -) - -if (A2X_FOUND) - add_manpage(swaymsg 1) -endif() -- cgit v1.2.3 From f9413adde7ada3b5132435604a7db37971d4cf45 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 19 Dec 2017 08:06:23 +0100 Subject: build: add wlroots dependency to common It is required for include path if wlroots is not built in standard path, but found through pkg-config --- common/meson.build | 1 + 1 file changed, 1 insertion(+) (limited to 'common') diff --git a/common/meson.build b/common/meson.build index 3a4282ad..abe0cdcf 100644 --- a/common/meson.build +++ b/common/meson.build @@ -7,5 +7,6 @@ lib_sway_common = static_library('sway-common', 'readline.c', 'ipc-client.c' ), + dependencies: [ wlroots ], include_directories: sway_inc ) -- cgit v1.2.3 From 67985e903188a464e602d04f9ed218bd397f5ab1 Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Jan 2018 22:32:51 +0100 Subject: sway: change all sway_log to wlr_log --- common/ipc-client.c | 2 +- common/readline.c | 4 +-- common/util.c | 2 +- include/log.h | 25 +-------------- sway/commands.c | 12 +++---- sway/commands/bind.c | 8 ++--- sway/commands/exec.c | 2 +- sway/commands/exec_always.c | 8 ++--- sway/commands/input.c | 2 +- sway/commands/input/click_method.c | 2 +- sway/commands/input/events.c | 2 +- sway/commands/input/tap.c | 4 +-- sway/commands/input/xkb_layout.c | 4 +-- sway/commands/input/xkb_model.c | 4 +-- sway/commands/input/xkb_options.c | 4 +-- sway/commands/input/xkb_rules.c | 4 +-- sway/commands/input/xkb_variant.c | 4 +-- sway/commands/output.c | 8 ++--- sway/commands/seat.c | 2 +- sway/commands/set.c | 2 +- sway/config.c | 66 +++++++++++++++++++------------------- sway/config/input.c | 6 ++-- sway/config/output.c | 16 ++++----- sway/config/seat.c | 6 ++-- sway/desktop/output.c | 4 +-- sway/desktop/wl_shell.c | 2 +- sway/desktop/xdg_shell_v6.c | 2 +- sway/desktop/xwayland.c | 2 +- sway/input/cursor.c | 12 +++---- sway/input/input-manager.c | 36 ++++++++++----------- sway/input/keyboard.c | 6 ++-- sway/input/seat.c | 8 ++--- sway/ipc-server.c | 50 ++++++++++++++--------------- sway/tree/container.c | 14 ++++---- sway/tree/layout.c | 20 ++++++------ sway/tree/workspace.c | 2 +- 36 files changed, 167 insertions(+), 190 deletions(-) (limited to 'common') diff --git a/common/ipc-client.c b/common/ipc-client.c index 1ab6627b..582c5e86 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -79,7 +79,7 @@ struct ipc_response *ipc_recv_response(int socketfd) { error_2: free(response); error_1: - sway_log(L_ERROR, "Unable to allocate memory for IPC response"); + wlr_log(L_ERROR, "Unable to allocate memory for IPC response"); return NULL; } diff --git a/common/readline.c b/common/readline.c index cc40a2cc..ed5801de 100644 --- a/common/readline.c +++ b/common/readline.c @@ -8,7 +8,7 @@ char *read_line(FILE *file) { char *string = malloc(size); char lastChar = '\0'; if (!string) { - sway_log(L_ERROR, "Unable to allocate memory for read_line"); + wlr_log(L_ERROR, "Unable to allocate memory for read_line"); return NULL; } while (1) { @@ -29,7 +29,7 @@ char *read_line(FILE *file) { char *new_string = realloc(string, size *= 2); if (!new_string) { free(string); - sway_log(L_ERROR, "Unable to allocate memory for read_line"); + wlr_log(L_ERROR, "Unable to allocate memory for read_line"); return NULL; } string = new_string; diff --git a/common/util.c b/common/util.c index 83981160..fb7f9454 100644 --- a/common/util.c +++ b/common/util.c @@ -113,7 +113,7 @@ uint32_t parse_color(const char *color) { int len = strlen(color); if (len != 6 && len != 8) { - sway_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); + wlr_log(L_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); return 0xFFFFFFFF; } uint32_t res = (uint32_t)strtoul(color, NULL, 16); diff --git a/include/log.h b/include/log.h index a1e33fa2..646776f5 100644 --- a/include/log.h +++ b/include/log.h @@ -1,22 +1,7 @@ #ifndef _SWAY_LOG_H #define _SWAY_LOG_H #include - -typedef enum { - L_SILENT = 0, - L_ERROR = 1, - L_INFO = 2, - L_DEBUG = 3, -} log_importance_t; - -void init_log(log_importance_t verbosity); -void set_log_level(log_importance_t verbosity); -log_importance_t get_log_level(void); -void reset_log_level(void); -// returns whether debug logging is on after switching. -bool toggle_debug_logging(void); -void sway_log_colors(int mode); -void sway_log_errno(log_importance_t verbosity, char* format, ...) __attribute__((format(printf,2,3))); +#include void _sway_abort(const char *filename, int line, const char* format, ...) __attribute__((format(printf,3,4))); #define sway_abort(FMT, ...) \ @@ -26,14 +11,6 @@ bool _sway_assert(bool condition, const char *filename, int line, const char* fo #define sway_assert(COND, FMT, ...) \ _sway_assert(COND, __FILE__, __LINE__, "%s:" FMT, __PRETTY_FUNCTION__, ##__VA_ARGS__) -void _sway_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) __attribute__((format(printf,4,5))); - -#define sway_log(VERBOSITY, FMT, ...) \ - _sway_log(__FILE__, __LINE__, VERBOSITY, FMT, ##__VA_ARGS__) - -#define sway_vlog(VERBOSITY, FMT, VA_ARGS) \ - _sway_vlog(__FILE__, __LINE__, VERBOSITY, FMT, VA_ARGS) - void error_handler(int sig); #endif diff --git a/sway/commands.c b/sway/commands.c index f01329db..1005cf68 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -176,7 +176,7 @@ static struct cmd_handler seat_handlers[] = { static struct cmd_handler *find_handler(char *line, enum cmd_status block) { struct cmd_handler d = { .command=line }; struct cmd_handler *res = NULL; - sway_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); + wlr_log(L_DEBUG, "find_handler(%s) %d", line, block == CMD_BLOCK_SEAT); if (block == CMD_BLOCK_INPUT) { res = bsearch(&d, input_handlers, @@ -215,10 +215,10 @@ struct cmd_results *handle_command(char *_exec) { cmd = argsep(&cmdlist, ","); cmd += strspn(cmd, whitespace); if (strcmp(cmd, "") == 0) { - sway_log(L_INFO, "Ignoring empty command."); + wlr_log(L_INFO, "Ignoring empty command."); continue; } - sway_log(L_INFO, "Handling command '%s'", cmd); + wlr_log(L_INFO, "Handling command '%s'", cmd); //TODO better handling of argv int argc; char **argv = split_args(cmd, &argc); @@ -276,7 +276,7 @@ struct cmd_results *config_command(char *exec, enum cmd_status block) { goto cleanup; } - sway_log(L_INFO, "handling config command '%s'", exec); + wlr_log(L_INFO, "handling config command '%s'", exec); // Endblock if (**argv == '}') { results = cmd_results_new(CMD_BLOCK_END, NULL, NULL); @@ -380,7 +380,7 @@ struct cmd_results *config_commands_command(char *exec) { } policy->context = context; - sway_log(L_INFO, "Set command policy for %s to %d", + wlr_log(L_INFO, "Set command policy for %s to %d", policy->command, policy->context); results = cmd_results_new(CMD_SUCCESS, NULL, NULL); @@ -394,7 +394,7 @@ struct cmd_results *cmd_results_new(enum cmd_status status, const char *input, const char *format, ...) { struct cmd_results *results = malloc(sizeof(struct cmd_results)); if (!results) { - sway_log(L_ERROR, "Unable to allocate command results"); + wlr_log(L_ERROR, "Unable to allocate command results"); return NULL; } results->status = status; diff --git a/sway/commands/bind.c b/sway/commands/bind.c index 79121404..cbabb07b 100644 --- a/sway/commands/bind.c +++ b/sway/commands/bind.c @@ -145,7 +145,7 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { for (int i = 0; i < mode_bindings->length; ++i) { struct sway_binding *config_binding = mode_bindings->items[i]; if (binding_key_compare(binding, config_binding)) { - sway_log(L_DEBUG, "overwriting old binding with command '%s'", + wlr_log(L_DEBUG, "overwriting old binding with command '%s'", config_binding->command); free_sway_binding(config_binding); mode_bindings->items[i] = binding; @@ -157,7 +157,7 @@ struct cmd_results *cmd_bindsym(int argc, char **argv) { list_add(mode_bindings, binding); } - sway_log(L_DEBUG, "bindsym - Bound %s to command %s", + wlr_log(L_DEBUG, "bindsym - Bound %s to command %s", argv[0], binding->command); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -227,7 +227,7 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { for (int i = 0; i < mode_bindings->length; ++i) { struct sway_binding *config_binding = mode_bindings->items[i]; if (binding_key_compare(binding, config_binding)) { - sway_log(L_DEBUG, "overwriting old binding with command '%s'", + wlr_log(L_DEBUG, "overwriting old binding with command '%s'", config_binding->command); free_sway_binding(config_binding); mode_bindings->items[i] = binding; @@ -239,7 +239,7 @@ struct cmd_results *cmd_bindcode(int argc, char **argv) { list_add(mode_bindings, binding); } - sway_log(L_DEBUG, "bindcode - Bound %s to command %s", + wlr_log(L_DEBUG, "bindcode - Bound %s to command %s", argv[0], binding->command); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/exec.c b/sway/commands/exec.c index fbbc4941..363d5bef 100644 --- a/sway/commands/exec.c +++ b/sway/commands/exec.c @@ -8,7 +8,7 @@ struct cmd_results *cmd_exec(int argc, char **argv) { if (!config->active) return cmd_results_new(CMD_DEFER, "exec", NULL); if (config->reloading) { char *args = join_args(argv, argc); - sway_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); + wlr_log(L_DEBUG, "Ignoring 'exec %s' due to reload", args); free(args); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/exec_always.c b/sway/commands/exec_always.c index 9527a487..61870c51 100644 --- a/sway/commands/exec_always.c +++ b/sway/commands/exec_always.c @@ -20,7 +20,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { char *tmp = NULL; if (strcmp((char*)*argv, "--no-startup-id") == 0) { - sway_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); + wlr_log(L_INFO, "exec switch '--no-startup-id' not supported, ignored."); if ((error = checkarg(argc - 1, "exec_always", EXPECTED_MORE_THAN, 0))) { return error; } @@ -35,11 +35,11 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { strncpy(cmd, tmp, sizeof(cmd)); cmd[sizeof(cmd) - 1] = 0; free(tmp); - sway_log(L_DEBUG, "Executing %s", cmd); + wlr_log(L_DEBUG, "Executing %s", cmd); int fd[2]; if (pipe(fd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for fork"); + wlr_log(L_ERROR, "Unable to create pipe for fork"); } pid_t pid; @@ -75,7 +75,7 @@ struct cmd_results *cmd_exec_always(int argc, char **argv) { // cleanup child process wait(0); if (*child > 0) { - sway_log(L_DEBUG, "Child process created with pid %d", *child); + wlr_log(L_DEBUG, "Child process created with pid %d", *child); // TODO: add PID to active workspace } else { free(child); diff --git a/sway/commands/input.c b/sway/commands/input.c index edf45e4c..5ea39f62 100644 --- a/sway/commands/input.c +++ b/sway/commands/input.c @@ -12,7 +12,7 @@ struct cmd_results *cmd_input(int argc, char **argv) { if (config->reading && strcmp("{", argv[1]) == 0) { current_input_config = new_input_config(argv[0]); - sway_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "entering input block: %s", current_input_config->identifier); return cmd_results_new(CMD_BLOCK_INPUT, NULL, NULL); } diff --git a/sway/commands/input/click_method.c b/sway/commands/input/click_method.c index dcf64c1a..22eb15f7 100644 --- a/sway/commands/input/click_method.c +++ b/sway/commands/input/click_method.c @@ -6,7 +6,7 @@ #include "log.h" struct cmd_results *input_cmd_click_method(int argc, char **argv) { - sway_log(L_DEBUG, "click_method for device: %d %s", + wlr_log(L_DEBUG, "click_method for device: %d %s", current_input_config==NULL, current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "click_method", EXPECTED_AT_LEAST, 1))) { diff --git a/sway/commands/input/events.c b/sway/commands/input/events.c index 8a74c11e..a1bfbacd 100644 --- a/sway/commands/input/events.c +++ b/sway/commands/input/events.c @@ -6,7 +6,7 @@ #include "log.h" struct cmd_results *input_cmd_events(int argc, char **argv) { - sway_log(L_DEBUG, "events for device: %s", + wlr_log(L_DEBUG, "events for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "events", EXPECTED_AT_LEAST, 1))) { diff --git a/sway/commands/input/tap.c b/sway/commands/input/tap.c index 8547c0cd..ecab9a5b 100644 --- a/sway/commands/input/tap.c +++ b/sway/commands/input/tap.c @@ -6,7 +6,7 @@ #include "log.h" struct cmd_results *input_cmd_tap(int argc, char **argv) { - sway_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "tap for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "tap", EXPECTED_AT_LEAST, 1))) { return error; @@ -26,7 +26,7 @@ struct cmd_results *input_cmd_tap(int argc, char **argv) { "Expected 'tap '"); } - sway_log(L_DEBUG, "apply-tap for device: %s", + wlr_log(L_DEBUG, "apply-tap for device: %s", current_input_config->identifier); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/input/xkb_layout.c b/sway/commands/input/xkb_layout.c index a25d3850..25db1a33 100644 --- a/sway/commands/input/xkb_layout.c +++ b/sway/commands/input/xkb_layout.c @@ -5,7 +5,7 @@ #include "log.h" struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { - sway_log(L_DEBUG, "xkb layout for device: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "xkb layout for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_layout", EXPECTED_EQUAL_TO, 1))) { return error; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_layout(int argc, char **argv) { new_config->xkb_layout = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", + wlr_log(L_DEBUG, "apply-xkb_layout for device: %s layout: %s", current_input_config->identifier, new_config->xkb_layout); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/input/xkb_model.c b/sway/commands/input/xkb_model.c index 9729e869..819b796b 100644 --- a/sway/commands/input/xkb_model.c +++ b/sway/commands/input/xkb_model.c @@ -5,7 +5,7 @@ #include "log.h" struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { - sway_log(L_DEBUG, "xkb model for device: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "xkb model for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_model", EXPECTED_EQUAL_TO, 1))) { return error; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_model(int argc, char **argv) { new_config->xkb_model = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", + wlr_log(L_DEBUG, "apply-xkb_model for device: %s model: %s", current_input_config->identifier, new_config->xkb_model); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/input/xkb_options.c b/sway/commands/input/xkb_options.c index 504849cc..ff5f83ec 100644 --- a/sway/commands/input/xkb_options.c +++ b/sway/commands/input/xkb_options.c @@ -5,7 +5,7 @@ #include "log.h" struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { - sway_log(L_DEBUG, "xkb options for device: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "xkb options for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_options", EXPECTED_EQUAL_TO, 1))) { return error; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_options(int argc, char **argv) { new_config->xkb_options = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", + wlr_log(L_DEBUG, "apply-xkb_options for device: %s options: %s", current_input_config->identifier, new_config->xkb_options); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/input/xkb_rules.c b/sway/commands/input/xkb_rules.c index db7d8abe..aafe0003 100644 --- a/sway/commands/input/xkb_rules.c +++ b/sway/commands/input/xkb_rules.c @@ -5,7 +5,7 @@ #include "log.h" struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { - sway_log(L_DEBUG, "xkb rules for device: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "xkb rules for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_rules", EXPECTED_EQUAL_TO, 1))) { return error; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_rules(int argc, char **argv) { new_config->xkb_rules = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", + wlr_log(L_DEBUG, "apply-xkb_rules for device: %s rules: %s", current_input_config->identifier, new_config->xkb_rules); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/input/xkb_variant.c b/sway/commands/input/xkb_variant.c index 855e6abc..89a61fdc 100644 --- a/sway/commands/input/xkb_variant.c +++ b/sway/commands/input/xkb_variant.c @@ -5,7 +5,7 @@ #include "log.h" struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { - sway_log(L_DEBUG, "xkb variant for device: %s", current_input_config->identifier); + wlr_log(L_DEBUG, "xkb variant for device: %s", current_input_config->identifier); struct cmd_results *error = NULL; if ((error = checkarg(argc, "xkb_variant", EXPECTED_EQUAL_TO, 1))) { return error; @@ -18,7 +18,7 @@ struct cmd_results *input_cmd_xkb_variant(int argc, char **argv) { new_config->xkb_variant = strdup(argv[0]); - sway_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", + wlr_log(L_DEBUG, "apply-xkb_variant for device: %s variant: %s", current_input_config->identifier, new_config->xkb_variant); apply_input_config(new_config); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/output.c b/sway/commands/output.c index 8c0fa63c..e747eb4e 100644 --- a/sway/commands/output.c +++ b/sway/commands/output.c @@ -203,12 +203,12 @@ static struct cmd_results *cmd_output_background(struct output_config *output, if (src) { sprintf(src, "%s/%s", conf_path, p.we_wordv[0]); } else { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Unable to allocate background source"); } free(conf); } else { - sway_log(L_ERROR, "Unable to allocate background source"); + wlr_log(L_ERROR, "Unable to allocate background source"); } } if (!src || access(src, F_OK) == -1) { @@ -238,7 +238,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { struct output_config *output = new_output_config(argv[0]); if (!output) { - sway_log(L_ERROR, "Failed to allocate output config"); + wlr_log(L_ERROR, "Failed to allocate output config"); return NULL; } @@ -284,7 +284,7 @@ struct cmd_results *cmd_output(int argc, char **argv) { list_add(config->output_configs, output); } - sway_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " + wlr_log(L_DEBUG, "Config stored for output %s (enabled: %d) (%dx%d@%fHz " "position %d,%d scale %f transform %d) (bg %s %s)", output->name, output->enabled, output->width, output->height, output->refresh_rate, output->x, output->y, output->scale, diff --git a/sway/commands/seat.c b/sway/commands/seat.c index 155bc510..6284002b 100644 --- a/sway/commands/seat.c +++ b/sway/commands/seat.c @@ -12,7 +12,7 @@ struct cmd_results *cmd_seat(int argc, char **argv) { if (config->reading && strcmp("{", argv[1]) == 0) { current_seat_config = new_seat_config(argv[0]); - sway_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); + wlr_log(L_DEBUG, "entering seat block: %s", current_seat_config->name); return cmd_results_new(CMD_BLOCK_SEAT, NULL, NULL); } diff --git a/sway/commands/set.c b/sway/commands/set.c index dcd928ba..856c73e7 100644 --- a/sway/commands/set.c +++ b/sway/commands/set.c @@ -33,7 +33,7 @@ struct cmd_results *cmd_set(int argc, char **argv) { } if (argv[0][0] != '$') { - sway_log(L_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); + wlr_log(L_INFO, "Warning: variable '%s' doesn't start with $", argv[0]); size_t size = snprintf(NULL, 0, "$%s", argv[0]); tmp = malloc(size + 1); diff --git a/sway/config.c b/sway/config.c index e0a93e19..5ec45b17 100644 --- a/sway/config.c +++ b/sway/config.c @@ -232,12 +232,12 @@ static char *get_config_path(void) { char *home = getenv("HOME"); char *config_home = malloc(strlen(home) + strlen("/.config") + 1); if (!config_home) { - sway_log(L_ERROR, "Unable to allocate $HOME/.config"); + wlr_log(L_ERROR, "Unable to allocate $HOME/.config"); } else { strcpy(config_home, home); strcat(config_home, "/.config"); setenv("XDG_CONFIG_HOME", config_home, 1); - sway_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); + wlr_log(L_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); free(config_home); } } @@ -263,7 +263,7 @@ static char *get_config_path(void) { const char *current_config_path; static bool load_config(const char *path, struct sway_config *config) { - sway_log(L_INFO, "Loading config from %s", path); + wlr_log(L_INFO, "Loading config from %s", path); current_config_path = path; struct stat sb; @@ -272,13 +272,13 @@ static bool load_config(const char *path, struct sway_config *config) { } if (path == NULL) { - sway_log(L_ERROR, "Unable to find a config file!"); + wlr_log(L_ERROR, "Unable to find a config file!"); return false; } FILE *f = fopen(path, "r"); if (!f) { - sway_log(L_ERROR, "Unable to open %s for reading", path); + wlr_log(L_ERROR, "Unable to open %s for reading", path); return false; } @@ -286,7 +286,7 @@ static bool load_config(const char *path, struct sway_config *config) { fclose(f); if (!config_load_success) { - sway_log(L_ERROR, "Error(s) loading config!"); + wlr_log(L_ERROR, "Error(s) loading config!"); } current_config_path = NULL; @@ -313,7 +313,7 @@ bool load_main_config(const char *file, bool is_active) { config_defaults(config); if (is_active) { - sway_log(L_DEBUG, "Performing configuration file reload"); + wlr_log(L_DEBUG, "Performing configuration file reload"); config->reloading = true; config->active = true; } @@ -327,7 +327,7 @@ bool load_main_config(const char *file, bool is_active) { bool success = true; DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); if (!dir) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "%s does not exist, sway will have no security configuration" " and will probably be broken", SYSCONFDIR "/sway/security.d"); } else { @@ -356,7 +356,7 @@ bool load_main_config(const char *file, bool is_active) { if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Refusing to load %s - it must be owned by root " "and mode 644 or 444", _path); success = false; @@ -398,7 +398,7 @@ static bool load_include_config(const char *path, const char *parent_dir, len = len + strlen(parent_dir) + 2; full_path = malloc(len * sizeof(char)); if (!full_path) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Unable to allocate full path to included config"); return false; } @@ -409,7 +409,7 @@ static bool load_include_config(const char *path, const char *parent_dir, free(full_path); if (real_path == NULL) { - sway_log(L_DEBUG, "%s not found.", path); + wlr_log(L_DEBUG, "%s not found.", path); return false; } @@ -418,7 +418,7 @@ static bool load_include_config(const char *path, const char *parent_dir, for (j = 0; j < config->config_chain->length; ++j) { char *old_path = config->config_chain->items[j]; if (strcmp(real_path, old_path) == 0) { - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "%s already included once, won't be included again.", real_path); free(real_path); @@ -472,7 +472,7 @@ bool load_include_configs(const char *path, struct sway_config *config) { // restore wd if (chdir(wd) < 0) { free(wd); - sway_log(L_ERROR, "failed to restore working directory"); + wlr_log(L_ERROR, "failed to restore working directory"); return false; } @@ -508,13 +508,13 @@ bool read_config(FILE *file, struct sway_config *config) { switch(res->status) { case CMD_FAILURE: case CMD_INVALID: - sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, + wlr_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, res->error, config->current_config); success = false; break; case CMD_DEFER: - sway_log(L_DEBUG, "Deferring command `%s'", line); + wlr_log(L_DEBUG, "Deferring command `%s'", line); list_add(config->cmd_queue, strdup(line)); break; @@ -522,7 +522,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_MODE; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -530,7 +530,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_INPUT; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -538,7 +538,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_SEAT; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -546,7 +546,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_BAR; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -554,7 +554,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_BAR) { block = CMD_BLOCK_BAR_COLORS; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -562,7 +562,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_COMMANDS; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -570,7 +570,7 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_END) { block = CMD_BLOCK_IPC; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; @@ -578,59 +578,59 @@ bool read_config(FILE *file, struct sway_config *config) { if (block == CMD_BLOCK_IPC) { block = CMD_BLOCK_IPC_EVENTS; } else { - sway_log(L_ERROR, "Invalid block '%s'", line); + wlr_log(L_ERROR, "Invalid block '%s'", line); } break; case CMD_BLOCK_END: switch(block) { case CMD_BLOCK_MODE: - sway_log(L_DEBUG, "End of mode block"); + wlr_log(L_DEBUG, "End of mode block"); config->current_mode = config->modes->items[0]; block = CMD_BLOCK_END; break; case CMD_BLOCK_INPUT: - sway_log(L_DEBUG, "End of input block"); + wlr_log(L_DEBUG, "End of input block"); free_input_config(current_input_config); current_input_config = NULL; block = CMD_BLOCK_END; break; case CMD_BLOCK_SEAT: - sway_log(L_DEBUG, "End of seat block"); + wlr_log(L_DEBUG, "End of seat block"); current_seat_config = NULL; block = CMD_BLOCK_END; break; case CMD_BLOCK_BAR: - sway_log(L_DEBUG, "End of bar block"); + wlr_log(L_DEBUG, "End of bar block"); config->current_bar = NULL; block = CMD_BLOCK_END; break; case CMD_BLOCK_BAR_COLORS: - sway_log(L_DEBUG, "End of bar colors block"); + wlr_log(L_DEBUG, "End of bar colors block"); block = CMD_BLOCK_BAR; break; case CMD_BLOCK_COMMANDS: - sway_log(L_DEBUG, "End of commands block"); + wlr_log(L_DEBUG, "End of commands block"); block = CMD_BLOCK_END; break; case CMD_BLOCK_IPC: - sway_log(L_DEBUG, "End of IPC block"); + wlr_log(L_DEBUG, "End of IPC block"); block = CMD_BLOCK_END; break; case CMD_BLOCK_IPC_EVENTS: - sway_log(L_DEBUG, "End of IPC events block"); + wlr_log(L_DEBUG, "End of IPC events block"); block = CMD_BLOCK_IPC; break; case CMD_BLOCK_END: - sway_log(L_ERROR, "Unmatched }"); + wlr_log(L_ERROR, "Unmatched }"); break; default:; @@ -663,7 +663,7 @@ char *do_var_replacement(char *str) { int vvlen = strlen(var->value); char *newstr = malloc(strlen(str) - vnlen + vvlen + 1); if (!newstr) { - sway_log(L_ERROR, + wlr_log(L_ERROR, "Unable to allocate replacement " "during variable expansion"); break; diff --git a/sway/config/input.c b/sway/config/input.c index 6f8d31f7..96181302 100644 --- a/sway/config/input.c +++ b/sway/config/input.c @@ -8,13 +8,13 @@ struct input_config *new_input_config(const char* identifier) { struct input_config *input = calloc(1, sizeof(struct input_config)); if (!input) { - sway_log(L_DEBUG, "Unable to allocate input config"); + wlr_log(L_DEBUG, "Unable to allocate input config"); return NULL; } - sway_log(L_DEBUG, "new_input_config(%s)", identifier); + wlr_log(L_DEBUG, "new_input_config(%s)", identifier); if (!(input->identifier = strdup(identifier))) { free(input); - sway_log(L_DEBUG, "Unable to allocate input config"); + wlr_log(L_DEBUG, "Unable to allocate input config"); return NULL; } diff --git a/sway/config/output.c b/sway/config/output.c index e798a20e..69e883f1 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -84,7 +84,7 @@ static void set_mode(struct wlr_output *output, int width, int height, float refresh_rate) { int mhz = (int)(refresh_rate * 1000); if (wl_list_empty(&output->modes)) { - sway_log(L_DEBUG, "Assigning custom mode to %s", output->name); + wlr_log(L_DEBUG, "Assigning custom mode to %s", output->name); wlr_output_set_custom_mode(output, width, height, mhz); return; } @@ -100,9 +100,9 @@ static void set_mode(struct wlr_output *output, int width, int height, } } if (!best) { - sway_log(L_ERROR, "Configured mode for %s not available", output->name); + wlr_log(L_ERROR, "Configured mode for %s not available", output->name); } else { - sway_log(L_DEBUG, "Assigning configured mode to %s", output->name); + wlr_log(L_DEBUG, "Assigning configured mode to %s", output->name); wlr_output_set_mode(output, best); } } @@ -119,22 +119,22 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { } if (oc && oc->width > 0 && oc->height > 0) { - sway_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, + wlr_log(L_DEBUG, "Set %s mode to %dx%d (%f GHz)", oc->name, oc->width, oc->height, oc->refresh_rate); set_mode(wlr_output, oc->width, oc->height, oc->refresh_rate); } if (oc && oc->scale > 0) { - sway_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); + wlr_log(L_DEBUG, "Set %s scale to %f", oc->name, oc->scale); wlr_output_set_scale(wlr_output, oc->scale); } if (oc && oc->transform >= 0) { - sway_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); + wlr_log(L_DEBUG, "Set %s transform to %d", oc->name, oc->transform); wlr_output_set_transform(wlr_output, oc->transform); } // Find position for it if (oc && (oc->x != -1 || oc->y != -1)) { - sway_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); + wlr_log(L_DEBUG, "Set %s position to %d, %d", oc->name, oc->x, oc->y); wlr_output_layout_add(root_container.sway_root->output_layout, wlr_output, oc->x, oc->y); } else { @@ -165,7 +165,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { terminate_swaybg(output->bg_pid); } - sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); + wlr_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); size_t bufsize = 12; char output_id[bufsize]; diff --git a/sway/config/seat.c b/sway/config/seat.c index 113139e8..03cc6d4e 100644 --- a/sway/config/seat.c +++ b/sway/config/seat.c @@ -7,11 +7,11 @@ struct seat_config *new_seat_config(const char* name) { struct seat_config *seat = calloc(1, sizeof(struct seat_config)); if (!seat) { - sway_log(L_DEBUG, "Unable to allocate seat config"); + wlr_log(L_DEBUG, "Unable to allocate seat config"); return NULL; } - sway_log(L_DEBUG, "new_seat_config(%s)", name); + wlr_log(L_DEBUG, "new_seat_config(%s)", name); seat->name = strdup(name); if (!sway_assert(seat->name, "could not allocate name for seat")) { free(seat); @@ -34,7 +34,7 @@ struct seat_attachment_config *seat_attachment_config_new() { struct seat_attachment_config *attachment = calloc(1, sizeof(struct seat_attachment_config)); if (!attachment) { - sway_log(L_DEBUG, "cannot allocate attachment config"); + wlr_log(L_DEBUG, "cannot allocate attachment config"); return NULL; } return attachment; diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 3b87c2e7..2b428c30 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -110,7 +110,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { void output_add_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_add); struct wlr_output *wlr_output = data; - sway_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); + wlr_log(L_DEBUG, "New output %p: %s", wlr_output, wlr_output->name); struct sway_output *output = calloc(1, sizeof(struct sway_output)); if (!output) { @@ -140,7 +140,7 @@ void output_add_notify(struct wl_listener *listener, void *data) { void output_remove_notify(struct wl_listener *listener, void *data) { struct sway_server *server = wl_container_of(listener, server, output_remove); struct wlr_output *wlr_output = data; - sway_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); + wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); swayc_t *output_container = NULL; for (int i = 0 ; i < root_container.children->length; ++i) { diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index a7bb8eb5..345a1398 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c @@ -82,7 +82,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", + wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", shell_surface->title, shell_surface->class); wlr_wl_shell_surface_ping(shell_surface); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 5ff19f7e..df48345c 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -88,7 +88,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", + wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", xdg_surface->title, xdg_surface->app_id); wlr_xdg_surface_v6_ping(xdg_surface); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 42e82c64..43bb2e00 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -124,7 +124,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", + wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", xsurface->title, xsurface->class); struct sway_xwayland_surface *sway_surface = diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 3b5cfce5..c51b59f9 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -85,35 +85,35 @@ static void handle_touch_down(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); struct wlr_event_touch_down *event = data; - sway_log(L_DEBUG, "TODO: handle touch down event: %p", event); + wlr_log(L_DEBUG, "TODO: handle touch down event: %p", event); } static void handle_touch_up(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); struct wlr_event_touch_up *event = data; - sway_log(L_DEBUG, "TODO: handle touch up event: %p", event); + wlr_log(L_DEBUG, "TODO: handle touch up event: %p", event); } static void handle_touch_motion(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_motion); struct wlr_event_touch_motion *event = data; - sway_log(L_DEBUG, "TODO: handle touch motion event: %p", event); + wlr_log(L_DEBUG, "TODO: handle touch motion event: %p", event); } static void handle_tool_axis(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); struct wlr_event_tablet_tool_axis *event = data; - sway_log(L_DEBUG, "TODO: handle tool axis event: %p", event); + wlr_log(L_DEBUG, "TODO: handle tool axis event: %p", event); } static void handle_tool_tip(struct wl_listener *listener, void *data) { struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); struct wlr_event_tablet_tool_tip *event = data; - sway_log(L_DEBUG, "TODO: handle tool tip event: %p", event); + wlr_log(L_DEBUG, "TODO: handle tool tip event: %p", event); } static void handle_request_set_cursor(struct wl_listener *listener, @@ -121,7 +121,7 @@ static void handle_request_set_cursor(struct wl_listener *listener, struct sway_cursor *cursor = wl_container_of(listener, cursor, request_set_cursor); struct wlr_seat_pointer_request_set_cursor_event *event = data; - sway_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); + wlr_log(L_DEBUG, "TODO: handle request set cursor event: %p", event); } struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index 128a818a..26cf5035 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -52,7 +52,7 @@ static char *get_device_identifier(struct wlr_input_device *device) { int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1; char *identifier = malloc(len); if (!identifier) { - sway_log(L_ERROR, "Unable to allocate unique input device name"); + wlr_log(L_ERROR, "Unable to allocate unique input device name"); return NULL; } @@ -93,60 +93,60 @@ static void sway_input_manager_libinput_config_pointer(struct sway_input_device } libinput_device = wlr_libinput_get_device_handle(wlr_device); - sway_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); + wlr_log(L_DEBUG, "sway_input_manager_libinput_config_pointer(%s)", ic->identifier); if (ic->accel_profile != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_profile(%d)", ic->identifier, ic->accel_profile); libinput_device_config_accel_set_profile(libinput_device, ic->accel_profile); } if (ic->click_method != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) click_set_method(%d)", ic->identifier, ic->click_method); libinput_device_config_click_set_method(libinput_device, ic->click_method); } if (ic->drag_lock != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_drag_lock_enabled(%d)", ic->identifier, ic->click_method); libinput_device_config_tap_set_drag_lock_enabled(libinput_device, ic->drag_lock); } if (ic->dwt != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) dwt_set_enabled(%d)", ic->identifier, ic->dwt); libinput_device_config_dwt_set_enabled(libinput_device, ic->dwt); } if (ic->left_handed != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) left_handed_set_enabled(%d)", ic->identifier, ic->left_handed); libinput_device_config_left_handed_set(libinput_device, ic->left_handed); } if (ic->middle_emulation != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) middle_emulation_set_enabled(%d)", ic->identifier, ic->middle_emulation); libinput_device_config_middle_emulation_set_enabled(libinput_device, ic->middle_emulation); } if (ic->natural_scroll != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) natural_scroll_set_enabled(%d)", ic->identifier, ic->natural_scroll); libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, ic->natural_scroll); } if (ic->pointer_accel != FLT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) accel_set_speed(%f)", ic->identifier, ic->pointer_accel); libinput_device_config_accel_set_speed(libinput_device, ic->pointer_accel); } if (ic->scroll_method != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) scroll_set_method(%d)", ic->identifier, ic->scroll_method); libinput_device_config_scroll_set_method(libinput_device, ic->scroll_method); } if (ic->send_events != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) send_events_set_mode(%d)", ic->identifier, ic->send_events); libinput_device_config_send_events_set_mode(libinput_device, ic->send_events); } if (ic->tap != INT_MIN) { - sway_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", + wlr_log(L_DEBUG, "libinput_config_pointer(%s) tap_set_enabled(%d)", ic->identifier, ic->tap); libinput_device_config_tap_set_enabled(libinput_device, ic->tap); } @@ -167,7 +167,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { input_device->identifier = get_device_identifier(device); wl_list_insert(&input->devices, &input_device->link); - sway_log(L_DEBUG, "adding device: '%s'", + wlr_log(L_DEBUG, "adding device: '%s'", input_device->identifier); // find config @@ -185,7 +185,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { struct sway_seat *seat = NULL; if (!input_has_seat_configuration(input)) { - sway_log(L_DEBUG, "no seat configuration, using default seat"); + wlr_log(L_DEBUG, "no seat configuration, using default seat"); seat = input_manager_get_seat(input, default_seat); sway_seat_add_device(seat, input_device); return; @@ -213,7 +213,7 @@ static void input_add_notify(struct wl_listener *listener, void *data) { } if (!added) { - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "device '%s' is not configured on any seats", input_device->identifier); } @@ -231,7 +231,7 @@ static void input_remove_notify(struct wl_listener *listener, void *data) { return; } - sway_log(L_DEBUG, "removing device: '%s'", + wlr_log(L_DEBUG, "removing device: '%s'", input_device->identifier); struct sway_seat *seat = NULL; @@ -309,7 +309,7 @@ void sway_input_manager_apply_input_config(struct sway_input_manager *input, void sway_input_manager_apply_seat_config(struct sway_input_manager *input, struct seat_config *seat_config) { - sway_log(L_DEBUG, "applying new seat config for seat %s", + wlr_log(L_DEBUG, "applying new seat config for seat %s", seat_config->name); struct sway_seat *seat = input_manager_get_seat(input, seat_config->name); if (!seat) { diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c index c2bb2578..e7539c48 100644 --- a/sway/input/keyboard.c +++ b/sway/input/keyboard.c @@ -90,11 +90,11 @@ static bool binding_matches_key_state(struct sway_binding *binding, } static void binding_execute_command(struct sway_binding *binding) { - sway_log(L_DEBUG, "running command for binding: %s", + wlr_log(L_DEBUG, "running command for binding: %s", binding->command); struct cmd_results *results = handle_command(binding->command); if (results->status != CMD_SUCCESS) { - sway_log(L_DEBUG, "could not run command for binding: %s", + wlr_log(L_DEBUG, "could not run command for binding: %s", binding->command); } free_cmd_results(results); @@ -467,7 +467,7 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) { xkb_keymap_new_from_names(context, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { - sway_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); + wlr_log(L_DEBUG, "cannot configure keyboard: keymap does not exist"); xkb_context_unref(context); return; } diff --git a/sway/input/seat.c b/sway/input/seat.c index 9a6a667b..268486ab 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -112,7 +112,7 @@ void sway_seat_configure_device(struct sway_seat *seat, case WLR_INPUT_DEVICE_TOUCH: case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_TOOL: - sway_log(L_DEBUG, "TODO: configure other devices"); + wlr_log(L_DEBUG, "TODO: configure other devices"); break; } } @@ -127,11 +127,11 @@ void sway_seat_add_device(struct sway_seat *seat, struct sway_seat_device *seat_device = calloc(1, sizeof(struct sway_seat_device)); if (!seat_device) { - sway_log(L_DEBUG, "could not allocate seat device"); + wlr_log(L_DEBUG, "could not allocate seat device"); return; } - sway_log(L_DEBUG, "adding device %s to seat %s", + wlr_log(L_DEBUG, "adding device %s to seat %s", input_device->identifier, seat->wlr_seat->name); seat_device->sway_seat = seat; @@ -150,7 +150,7 @@ void sway_seat_remove_device(struct sway_seat *seat, return; } - sway_log(L_DEBUG, "removing device %s from seat %s", + wlr_log(L_DEBUG, "removing device %s from seat %s", input_device->identifier, seat->wlr_seat->name); seat_device_destroy(seat_device); diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 046e40a8..d2dd881f 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -125,32 +125,32 @@ struct sockaddr_un *ipc_user_sockaddr(void) { int ipc_handle_connection(int fd, uint32_t mask, void *data) { (void) fd; struct sway_server *server = data; - sway_log(L_DEBUG, "Event on IPC listening socket"); + wlr_log(L_DEBUG, "Event on IPC listening socket"); assert(mask == WL_EVENT_READABLE); int client_fd = accept(ipc_socket, NULL, NULL); if (client_fd == -1) { - sway_log_errno(L_ERROR, "Unable to accept IPC client connection"); + wlr_log_errno(L_ERROR, "Unable to accept IPC client connection"); return 0; } int flags; if ((flags = fcntl(client_fd, F_GETFD)) == -1 || fcntl(client_fd, F_SETFD, flags|FD_CLOEXEC) == -1) { - sway_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); + wlr_log_errno(L_ERROR, "Unable to set CLOEXEC on IPC client socket"); close(client_fd); return 0; } if ((flags = fcntl(client_fd, F_GETFL)) == -1 || fcntl(client_fd, F_SETFL, flags|O_NONBLOCK) == -1) { - sway_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); + wlr_log_errno(L_ERROR, "Unable to set NONBLOCK on IPC client socket"); close(client_fd); return 0; } struct ipc_client *client = malloc(sizeof(struct ipc_client)); if (!client) { - sway_log(L_ERROR, "Unable to allocate ipc client"); + wlr_log(L_ERROR, "Unable to allocate ipc client"); close(client_fd); return 0; } @@ -166,12 +166,12 @@ int ipc_handle_connection(int fd, uint32_t mask, void *data) { client->write_buffer_len = 0; client->write_buffer = malloc(client->write_buffer_size); if (!client->write_buffer) { - sway_log(L_ERROR, "Unable to allocate ipc client write buffer"); + wlr_log(L_ERROR, "Unable to allocate ipc client write buffer"); close(client_fd); return 0; } - sway_log(L_DEBUG, "New client: fd %d", client_fd); + wlr_log(L_DEBUG, "New client: fd %d", client_fd); list_add(ipc_client_list, client); return 0; } @@ -182,22 +182,22 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WL_EVENT_ERROR) { - sway_log(L_ERROR, "IPC Client socket error, removing client"); + wlr_log(L_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WL_EVENT_HANGUP) { - sway_log(L_DEBUG, "Client %d hung up", client->fd); + wlr_log(L_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; } - sway_log(L_DEBUG, "Client %d readable", client->fd); + wlr_log(L_DEBUG, "Client %d readable", client->fd); int read_available; if (ioctl(client_fd, FIONREAD, &read_available) == -1) { - sway_log_errno(L_INFO, "Unable to read IPC socket buffer size"); + wlr_log_errno(L_INFO, "Unable to read IPC socket buffer size"); ipc_client_disconnect(client); return 0; } @@ -219,13 +219,13 @@ int ipc_client_handle_readable(int client_fd, uint32_t mask, void *data) { // Should be fully available, because read_available >= ipc_header_size ssize_t received = recv(client_fd, buf, ipc_header_size, 0); if (received == -1) { - sway_log_errno(L_INFO, "Unable to receive header from IPC client"); + wlr_log_errno(L_INFO, "Unable to receive header from IPC client"); ipc_client_disconnect(client); return 0; } if (memcmp(buf, ipc_magic, sizeof(ipc_magic)) != 0) { - sway_log(L_DEBUG, "IPC header check failed"); + wlr_log(L_DEBUG, "IPC header check failed"); ipc_client_disconnect(client); return 0; } @@ -244,13 +244,13 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { struct ipc_client *client = data; if (mask & WL_EVENT_ERROR) { - sway_log(L_ERROR, "IPC Client socket error, removing client"); + wlr_log(L_ERROR, "IPC Client socket error, removing client"); ipc_client_disconnect(client); return 0; } if (mask & WL_EVENT_HANGUP) { - sway_log(L_DEBUG, "Client %d hung up", client->fd); + wlr_log(L_DEBUG, "Client %d hung up", client->fd); ipc_client_disconnect(client); return 0; } @@ -259,14 +259,14 @@ int ipc_client_handle_writable(int client_fd, uint32_t mask, void *data) { return 0; } - sway_log(L_DEBUG, "Client %d writable", client->fd); + wlr_log(L_DEBUG, "Client %d writable", client->fd); ssize_t written = write(client->fd, client->write_buffer, client->write_buffer_len); if (written == -1 && errno == EAGAIN) { return 0; } else if (written == -1) { - sway_log_errno(L_INFO, "Unable to send data from queue to IPC client"); + wlr_log_errno(L_INFO, "Unable to send data from queue to IPC client"); ipc_client_disconnect(client); return 0; } @@ -291,7 +291,7 @@ void ipc_client_disconnect(struct ipc_client *client) { shutdown(client->fd, SHUT_RDWR); } - sway_log(L_INFO, "IPC Client %d disconnected", client->fd); + wlr_log(L_INFO, "IPC Client %d disconnected", client->fd); wl_event_source_remove(client->event_source); if (client->writable_event_source) { wl_event_source_remove(client->writable_event_source); @@ -313,7 +313,7 @@ void ipc_client_handle_command(struct ipc_client *client) { char *buf = malloc(client->payload_length + 1); if (!buf) { - sway_log_errno(L_INFO, "Unable to allocate IPC payload"); + wlr_log_errno(L_INFO, "Unable to allocate IPC payload"); ipc_client_disconnect(client); return; } @@ -322,7 +322,7 @@ void ipc_client_handle_command(struct ipc_client *client) { ssize_t received = recv(client->fd, buf, client->payload_length, 0); if (received == -1) { - sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); + wlr_log_errno(L_INFO, "Unable to receive payload from IPC client"); ipc_client_disconnect(client); free(buf); return; @@ -393,12 +393,12 @@ void ipc_client_handle_command(struct ipc_client *client) { } default: - sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); + wlr_log(L_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; } ipc_send_reply(client, error_denied, (uint32_t)strlen(error_denied)); - sway_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); + wlr_log(L_DEBUG, "Denied IPC client access to %i", client->current_command); exit_cleanup: client->payload_length = 0; @@ -422,14 +422,14 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay } if (client->write_buffer_size > 4e6) { // 4 MB - sway_log(L_ERROR, "Client write buffer too big, disconnecting client"); + wlr_log(L_ERROR, "Client write buffer too big, disconnecting client"); ipc_client_disconnect(client); return false; } char *new_buffer = realloc(client->write_buffer, client->write_buffer_size); if (!new_buffer) { - sway_log(L_ERROR, "Unable to reallocate ipc client write buffer"); + wlr_log(L_ERROR, "Unable to reallocate ipc client write buffer"); ipc_client_disconnect(client); return false; } @@ -446,6 +446,6 @@ bool ipc_send_reply(struct ipc_client *client, const char *payload, uint32_t pay ipc_client_handle_writable, client); } - sway_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); + wlr_log(L_DEBUG, "Added IPC reply to client %d queue: %s", client->fd, payload); return true; } diff --git a/sway/tree/container.c b/sway/tree/container.c index c5574275..31ec2ce5 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -92,11 +92,11 @@ swayc_t *new_output(struct sway_output *sway_output) { if (strcasecmp(name, cur->name) == 0 || strcasecmp(identifier, cur->name) == 0) { - sway_log(L_DEBUG, "Matched output config for %s", name); + wlr_log(L_DEBUG, "Matched output config for %s", name); oc = cur; } if (strcasecmp("*", cur->name) == 0) { - sway_log(L_DEBUG, "Matched wildcard output config for %s", name); + wlr_log(L_DEBUG, "Matched wildcard output config for %s", name); all = cur; } @@ -126,7 +126,7 @@ swayc_t *new_output(struct sway_output *sway_output) { // Create workspace char *ws_name = workspace_next_name(output->name); - sway_log(L_DEBUG, "Creating default workspace %s", ws_name); + wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); new_workspace(output, ws_name); free(ws_name); return output; @@ -136,7 +136,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { if (!sway_assert(output, "new_workspace called with null output")) { return NULL; } - sway_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); + wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name); swayc_t *workspace = new_swayc(C_WORKSPACE); workspace->x = output->x; @@ -159,7 +159,7 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { } const char *title = sway_view->iface.get_prop(sway_view, VIEW_PROP_TITLE); swayc_t *swayc = new_swayc(C_VIEW); - sway_log(L_DEBUG, "Adding new view %p:%s to container %p %d", + wlr_log(L_DEBUG, "Adding new view %p:%s to container %p %d", swayc, title, sibling, sibling ? sibling->type : 0); // Setup values swayc->sway_view = sway_view; @@ -200,7 +200,7 @@ swayc_t *destroy_output(swayc_t *output) { } } - sway_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); + wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); free_swayc(output); return &root_container; @@ -210,7 +210,7 @@ swayc_t *destroy_view(swayc_t *view) { if (!sway_assert(view, "null view passed to destroy_view")) { return NULL; } - sway_log(L_DEBUG, "Destroying view '%s'", view->name); + wlr_log(L_DEBUG, "Destroying view '%s'", view->name); swayc_t *parent = view->parent; free_swayc(view); diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 4bcf0e2f..13b8a395 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -59,7 +59,7 @@ void init_layout(void) { } void add_child(swayc_t *parent, swayc_t *child) { - sway_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", + wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, child->width, child->height, parent, parent->type, parent->width, parent->height); list_add(parent->children, child); @@ -145,7 +145,7 @@ void arrange_windows(swayc_t *container, double width, double height) { width = floor(width); height = floor(height); - sway_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, + wlr_log(L_DEBUG, "Arranging layout for %p %s %fx%f+%f,%f", container, container->name, container->width, container->height, container->x, container->y); @@ -155,7 +155,7 @@ void arrange_windows(swayc_t *container, double width, double height) { // TODO: wlr_output_layout probably for (i = 0; i < container->children->length; ++i) { swayc_t *output = container->children->items[i]; - sway_log(L_DEBUG, "Arranging output '%s' at %f,%f", + wlr_log(L_DEBUG, "Arranging output '%s' at %f,%f", output->name, output->x, output->y); arrange_windows(output, -1, -1); } @@ -181,7 +181,7 @@ void arrange_windows(swayc_t *container, double width, double height) { container->height = output->height; container->x = x; container->y = y; - sway_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", + wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", container->name, container->x, container->y); } // children are properly handled below @@ -192,7 +192,7 @@ void arrange_windows(swayc_t *container, double width, double height) { container->height = height; container->sway_view->iface.set_size(container->sway_view, container->width, container->height); - sway_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", + wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", container->width, container->height, container->x, container->y); } @@ -215,7 +215,7 @@ void arrange_windows(swayc_t *container, double width, double height) { container->children->length); break; default: - sway_log(L_DEBUG, "TODO: arrange layout type %d", container->layout); + wlr_log(L_DEBUG, "TODO: arrange layout type %d", container->layout); apply_horiz_layout(container, x, y, width, height, 0, container->children->length); break; @@ -244,10 +244,10 @@ static void apply_horiz_layout(swayc_t *container, // Resize windows double child_x = x; if (scale > 0.1) { - sway_log(L_DEBUG, "Arranging %p horizontally", container); + wlr_log(L_DEBUG, "Arranging %p horizontally", container); for (int i = start; i < end; ++i) { swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, width, scale); child->sway_view->iface.set_position(child->sway_view, child_x, y); @@ -294,10 +294,10 @@ void apply_vert_layout(swayc_t *container, // Resize double child_y = y; if (scale > 0.1) { - sway_log(L_DEBUG, "Arranging %p vertically", container); + wlr_log(L_DEBUG, "Arranging %p vertically", container); for (i = start; i < end; ++i) { swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, + wlr_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %f by %f)", child, child->type, height, scale); child->sway_view->iface.set_position(child->sway_view, x, child_y); diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index e8ed4102..c37a873c 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -11,7 +11,7 @@ void next_name_map(swayc_t *ws, void *data) { } char *workspace_next_name(const char *output_name) { - sway_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", + wlr_log(L_DEBUG, "Workspace: Generating new workspace name for output %s", output_name); int count = 0; next_name_map(&root_container, &count); -- cgit v1.2.3 From d4ddfec32e15fd1f47568f1b82eacc27cda5266a Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Fri, 5 Jan 2018 23:36:32 +0100 Subject: common/log: finish removing most log functions Keep sway_abort and sway_assert and convert them to use wlr_log functions --- common/log.c | 149 ++-------------------------------------------------------- include/log.h | 8 ++-- 2 files changed, 8 insertions(+), 149 deletions(-) (limited to 'common') diff --git a/common/log.c b/common/log.c index c47b4eea..2cc7289c 100644 --- a/common/log.c +++ b/common/log.c @@ -1,167 +1,26 @@ -#define _POSIX_C_SOURCE 199506L -#include -#include #include #include -#include #include -#include -#include -#include #include "log.h" -#include "readline.h" - -static int colored = 1; -static log_importance_t loglevel_default = L_ERROR; -static log_importance_t v = L_SILENT; - -static const char *verbosity_colors[] = { - [L_SILENT] = "", - [L_ERROR ] = "\x1B[1;31m", - [L_INFO ] = "\x1B[1;34m", - [L_DEBUG ] = "\x1B[1;30m", -}; -static const char verbosity_chars[] = { - [L_SILENT] = '\0', - [L_ERROR ] = 'E', - [L_INFO ] = 'I', - [L_DEBUG ] = 'D', -}; - -void init_log(log_importance_t verbosity) { - if (verbosity != L_DEBUG) { - // command "debuglog" needs to know the user specified log level when - // turning off debug logging. - loglevel_default = verbosity; - } - v = verbosity; -} - -void set_log_level(log_importance_t verbosity) { - v = verbosity; -} - -log_importance_t get_log_level(void) { - return v; -} - -void reset_log_level(void) { - v = loglevel_default; -} - -bool toggle_debug_logging(void) { - v = (v == L_DEBUG) ? loglevel_default : L_DEBUG; - return (v == L_DEBUG); -} - -void sway_log_colors(int mode) { - colored = (mode == 1) ? 1 : 0; -} - -void _sway_vlog(const char *filename, int line, log_importance_t verbosity, - const char *format, va_list args) { - if (verbosity <= v) { - // prefix the time to the log message - static struct tm result; - static time_t t; - static struct tm *tm_info; - char buffer[26]; - - unsigned int c = verbosity; - if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) { - c = sizeof(verbosity_colors) / sizeof(char *) - 1; - } - - // First, if not printing color, show the log level - if (!(colored && isatty(STDERR_FILENO)) && c != L_SILENT) { - fprintf(stderr, "%c: ", verbosity_chars[c]); - } - - // get current time - t = time(NULL); - // convert time to local time (determined by the locale) - tm_info = localtime_r(&t, &result); - // generate time prefix - strftime(buffer, sizeof(buffer), "%x %X - ", tm_info); - fprintf(stderr, "%s", buffer); - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "%s", verbosity_colors[c]); - } - - if (filename && line) { - const char *file = filename + strlen(filename); - while (file != filename && *file != '/') { - --file; - } - if (*file == '/') { - ++file; - } - fprintf(stderr, "[%s:%d] ", file, line); - } - - vfprintf(stderr, format, args); - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "\x1B[0m"); - } - fprintf(stderr, "\n"); - } -} - -void _sway_log(const char *filename, int line, log_importance_t verbosity, const char* format, ...) { - va_list args; - va_start(args, format); - _sway_vlog(filename, line, verbosity, format, args); - va_end(args); -} void sway_terminate(int code); -void _sway_abort(const char *filename, int line, const char* format, ...) { +void _sway_abort(const char *format, ...) { va_list args; va_start(args, format); - _sway_vlog(filename, line, L_ERROR, format, args); + _wlr_vlog(L_ERROR, format, args); va_end(args); sway_terminate(EXIT_FAILURE); } -void sway_log_errno(log_importance_t verbosity, char* format, ...) { - if (verbosity <= v) { - unsigned int c = verbosity; - if (c > sizeof(verbosity_colors) / sizeof(char *) - 1) { - c = sizeof(verbosity_colors) / sizeof(char *) - 1; - } - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "%s", verbosity_colors[c]); - } else if (c != L_SILENT) { - fprintf(stderr, "%c: ", verbosity_chars[c]); - } - - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - - fprintf(stderr, ": "); - fprintf(stderr, "%s", strerror(errno)); - - if (colored && isatty(STDERR_FILENO)) { - fprintf(stderr, "\x1B[0m"); - } - fprintf(stderr, "\n"); - } -} - -bool _sway_assert(bool condition, const char *filename, int line, const char* format, ...) { +bool _sway_assert(bool condition, const char *format, ...) { if (condition) { return true; } va_list args; va_start(args, format); - _sway_vlog(filename, line, L_ERROR, format, args); + _wlr_vlog(L_ERROR, format, args); va_end(args); #ifndef NDEBUG diff --git a/include/log.h b/include/log.h index 646776f5..350a59ef 100644 --- a/include/log.h +++ b/include/log.h @@ -3,13 +3,13 @@ #include #include -void _sway_abort(const char *filename, int line, const char* format, ...) __attribute__((format(printf,3,4))); +void _sway_abort(const char *filename, ...) ATTRIB_PRINTF(1, 2); #define sway_abort(FMT, ...) \ - _sway_abort(__FILE__, __LINE__, FMT, ##__VA_ARGS__) + _sway_abort("[%s:%d] " FMT, _strip_path(__FILE__), __LINE__, ##__VA_ARGS__) -bool _sway_assert(bool condition, const char *filename, int line, const char* format, ...) __attribute__((format(printf,4,5))); +bool _sway_assert(bool condition, const char* format, ...) ATTRIB_PRINTF(2, 3); #define sway_assert(COND, FMT, ...) \ - _sway_assert(COND, __FILE__, __LINE__, "%s:" FMT, __PRETTY_FUNCTION__, ##__VA_ARGS__) + _sway_assert(COND, "[%s:%d] %s:" FMT, _strip_path(__FILE__), __LINE__, __PRETTY_FUNCTION__, ##__VA_ARGS__) void error_handler(int sig); -- cgit v1.2.3 From 632bb948b7ffbb08a6e965dabf88347afd0a1fa8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 27 Mar 2018 15:25:25 -0400 Subject: Add solid-color rendering to swaybg --- client/buffer-pool.c | 123 +++++++++++++++++++++++++++++++++ client/meson.build | 21 ++++++ common/cairo.c | 127 ++++++++++++++++++++++++++++++++++ common/meson.build | 21 ++++-- include/buffer_pool.h | 21 ++++++ include/cairo.h | 18 +++++ meson.build | 8 +++ protocols/meson.build | 18 +---- swaybg/main.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++ swaybg/meson.build | 18 ++++- wayland/buffers.c | 27 +++----- 11 files changed, 550 insertions(+), 39 deletions(-) create mode 100644 client/buffer-pool.c create mode 100644 client/meson.build create mode 100644 common/cairo.c create mode 100644 include/buffer_pool.h create mode 100644 include/cairo.h (limited to 'common') diff --git a/client/buffer-pool.c b/client/buffer-pool.c new file mode 100644 index 00000000..26d0f7e5 --- /dev/null +++ b/client/buffer-pool.c @@ -0,0 +1,123 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "buffer_pool.h" + +static int create_pool_file(size_t size, char **name) { + static const char template[] = "sway-client-XXXXXX"; + const char *path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + return -1; + } + + int ts = (path[strlen(path) - 1] == '/'); + + *name = malloc( + strlen(template) + + strlen(path) + + (ts ? 0 : 1) + 1); + sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); + + int fd = mkstemp(*name); + + if (fd < 0) { + return -1; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void buffer_release(void *data, struct wl_buffer *wl_buffer) { + struct pool_buffer *buffer = data; + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = buffer_release +}; + +static struct pool_buffer *create_buffer(struct wl_shm *shm, + struct pool_buffer *buf, int32_t width, int32_t height, + uint32_t format) { + uint32_t stride = width * 4; + uint32_t size = stride * height; + + char *name; + int fd = create_pool_file(size, &name); + assert(fd); + void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buf->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, stride, format); + wl_shm_pool_destroy(pool); + close(fd); + unlink(name); + free(name); + fd = -1; + + buf->width = width; + buf->height = height; + buf->surface = cairo_image_surface_create_for_data(data, + CAIRO_FORMAT_ARGB32, width, height, stride); + buf->cairo = cairo_create(buf->surface); + buf->pango = pango_cairo_create_context(buf->cairo); + + wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); + return buf; +} + +static void destroy_buffer(struct pool_buffer *buffer) { + if (buffer->buffer) { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->cairo) { + cairo_destroy(buffer->cairo); + } + if (buffer->surface) { + cairo_surface_destroy(buffer->surface); + } + if (buffer->pango) { + g_object_unref(buffer->pango); + } + memset(buffer, 0, sizeof(struct pool_buffer)); +} + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { + struct pool_buffer *buffer = NULL; + + for (size_t i = 0; i < 2; ++i) { + if (pool[i].busy) { + continue; + } + buffer = &pool[i]; + } + + if (!buffer) { + return NULL; + } + + if (buffer->width != width || buffer->height != height) { + destroy_buffer(buffer); + } + + if (!buffer->buffer) { + if (!create_buffer(shm, buffer, width, height, + WL_SHM_FORMAT_ARGB8888)) { + return NULL; + } + } + return buffer; +} diff --git a/client/meson.build b/client/meson.build new file mode 100644 index 00000000..597899ce --- /dev/null +++ b/client/meson.build @@ -0,0 +1,21 @@ +deps = [ + cairo, + pango, + pangocairo, + wlroots, + wayland_client, +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + +lib_sway_client = static_library( + 'sway-client', + files( + 'buffer-pool.c', + ), + dependencies: deps, + link_with: [lib_sway_common], + include_directories: sway_inc +) diff --git a/common/cairo.c b/common/cairo.c new file mode 100644 index 00000000..c6bd0da9 --- /dev/null +++ b/common/cairo.c @@ -0,0 +1,127 @@ +#include +#include +#include "cairo.h" +#ifdef WITH_GDK_PIXBUF +#include +#endif + +void cairo_set_source_u32(cairo_t *cairo, uint32_t color) { + cairo_set_source_rgba(cairo, + (color >> (3*8) & 0xFF) / 255.0, + (color >> (2*8) & 0xFF) / 255.0, + (color >> (1*8) & 0xFF) / 255.0, + (color >> (0*8) & 0xFF) / 255.0); +} + +cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, + int width, int height) { + int image_width = cairo_image_surface_get_width(image); + int image_height = cairo_image_surface_get_height(image); + + cairo_surface_t *new = + cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo_t *cairo = cairo_create(new); + cairo_scale(cairo, (double)width / image_width, + (double)height / image_height); + cairo_set_source_surface(cairo, image, 0, 0); + + cairo_paint(cairo); + cairo_destroy(cairo); + return new; +} + +#ifdef WITH_GDK_PIXBUF +cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { + int chan = gdk_pixbuf_get_n_channels(gdkbuf); + if (chan < 3) { + return NULL; + } + + const guint8* gdkpix = gdk_pixbuf_read_pixels(gdkbuf); + if (!gdkpix) { + return NULL; + } + gint w = gdk_pixbuf_get_width(gdkbuf); + gint h = gdk_pixbuf_get_height(gdkbuf); + int stride = gdk_pixbuf_get_rowstride(gdkbuf); + + cairo_format_t fmt = (chan == 3) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32; + cairo_surface_t * cs = cairo_image_surface_create (fmt, w, h); + cairo_surface_flush (cs); + if ( !cs || cairo_surface_status(cs) != CAIRO_STATUS_SUCCESS) { + return NULL; + } + + int cstride = cairo_image_surface_get_stride(cs); + unsigned char * cpix = cairo_image_surface_get_data(cs); + + if (chan == 3) { + int i; + for (i = h; i; --i) { + const guint8 *gp = gdkpix; + unsigned char *cp = cpix; + const guint8* end = gp + 3*w; + while (gp < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + cp[0] = gp[2]; + cp[1] = gp[1]; + cp[2] = gp[0]; +#else + cp[1] = gp[0]; + cp[2] = gp[1]; + cp[3] = gp[2]; +#endif + gp += 3; + cp += 4; + } + gdkpix += stride; + cpix += cstride; + } + } else { + /* premul-color = alpha/255 * color/255 * 255 = (alpha*color)/255 + * (z/255) = z/256 * 256/255 = z/256 (1 + 1/255) + * = z/256 + (z/256)/255 = (z + z/255)/256 + * # recurse once + * = (z + (z + z/255)/256)/256 + * = (z + z/256 + z/256/255) / 256 + * # only use 16bit uint operations, loose some precision, + * # result is floored. + * -> (z + z>>8)>>8 + * # add 0x80/255 = 0.5 to convert floor to round + * => (z+0x80 + (z+0x80)>>8 ) >> 8 + * ------ + * tested as equal to lround(z/255.0) for uint z in [0..0xfe02] + */ +#define PREMUL_ALPHA(x,a,b,z) \ + G_STMT_START { z = a * b + 0x80; x = (z + (z >> 8)) >> 8; } \ + G_STMT_END + int i; + for (i = h; i; --i) { + const guint8 *gp = gdkpix; + unsigned char *cp = cpix; + const guint8* end = gp + 4*w; + guint z1, z2, z3; + while (gp < end) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + PREMUL_ALPHA(cp[0], gp[2], gp[3], z1); + PREMUL_ALPHA(cp[1], gp[1], gp[3], z2); + PREMUL_ALPHA(cp[2], gp[0], gp[3], z3); + cp[3] = gp[3]; +#else + PREMUL_ALPHA(cp[1], gp[0], gp[3], z1); + PREMUL_ALPHA(cp[2], gp[1], gp[3], z2); + PREMUL_ALPHA(cp[3], gp[2], gp[3], z3); + cp[0] = gp[3]; +#endif + gp += 4; + cp += 4; + } + gdkpix += stride; + cpix += cstride; + } +#undef PREMUL_ALPHA + } + cairo_surface_mark_dirty(cs); + return cs; +} +#endif //WITH_GDK_PIXBUF diff --git a/common/meson.build b/common/meson.build index abe0cdcf..01736ca6 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,12 +1,23 @@ -lib_sway_common = static_library('sway-common', +deps = [ + cairo, + wlroots +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + +lib_sway_common = static_library( + 'sway-common', files( + 'cairo.c', + 'ipc-client.c', 'log.c', 'list.c', - 'util.c', - 'stringop.c', 'readline.c', - 'ipc-client.c' + 'stringop.c', + 'util.c' ), - dependencies: [ wlroots ], + dependencies: deps, include_directories: sway_inc ) diff --git a/include/buffer_pool.h b/include/buffer_pool.h new file mode 100644 index 00000000..cdebd64d --- /dev/null +++ b/include/buffer_pool.h @@ -0,0 +1,21 @@ +#ifndef _SWAY_BUFFERS_H +#define _SWAY_BUFFERS_H +#include +#include +#include +#include +#include + +struct pool_buffer { + struct wl_buffer *buffer; + cairo_surface_t *surface; + cairo_t *cairo; + PangoContext *pango; + uint32_t width, height; + bool busy; +}; + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height); + +#endif diff --git a/include/cairo.h b/include/cairo.h new file mode 100644 index 00000000..f5f474d7 --- /dev/null +++ b/include/cairo.h @@ -0,0 +1,18 @@ +#ifndef _SWAY_CAIRO_H +#define _SWAY_CAIRO_H +#include +#include + +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 + +cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( + const GdkPixbuf *gdkbuf); +#endif //WITH_GDK_PIXBUF + +#endif diff --git a/meson.build b/meson.build index 622769a3..0c35b0e5 100644 --- a/meson.build +++ b/meson.build @@ -27,7 +27,10 @@ wayland_client = dependency('wayland-client') wayland_egl = dependency('wayland-egl') wayland_protos = dependency('wayland-protocols') xkbcommon = dependency('xkbcommon') +cairo = dependency('cairo') pango = dependency('pango') +pangocairo = dependency('pangocairo') +gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) pixman = dependency('pixman-1') libcap = dependency('libcap') libinput = dependency('libinput') @@ -35,6 +38,10 @@ math = cc.find_library('m') git = find_program('git', required: false) a2x = find_program('a2x', required: false) +if gdk_pixbuf.found() + add_project_arguments('-DWITH_GDK_PIXBUF', language : 'c') +endif + if a2x.found() mandir = get_option('mandir') man_files = [ @@ -89,6 +96,7 @@ subdir('protocols') subdir('common') subdir('sway') subdir('swaymsg') +subdir('client') subdir('swaybg') config = configuration_data() diff --git a/protocols/meson.build b/protocols/meson.build index 73a6fda5..1fda600e 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -2,12 +2,6 @@ wl_protocol_dir = wayland_protos.get_pkgconfig_variable('pkgdatadir') wayland_scanner = find_program('wayland-scanner') -wayland_scanner_server = generator( - wayland_scanner, - output: '@BASENAME@-protocol.h', - arguments: ['server-header', '@INPUT@', '@OUTPUT@'], -) - wayland_scanner_code = generator( wayland_scanner, output: '@BASENAME@-protocol.c', @@ -20,10 +14,9 @@ wayland_scanner_client = generator( arguments: ['client-header', '@INPUT@', '@OUTPUT@'], ) -protocols = [] - -client_protocols = [ - 'wlr-layer-shell-unstable-v1.xml', +protocols = [ + [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'], + ['wlr-layer-shell-unstable-v1.xml'] ] wl_protos_src = [] @@ -32,11 +25,6 @@ wl_protos_headers = [] foreach p : protocols xml = join_paths(p) wl_protos_src += wayland_scanner_code.process(xml) - wl_protos_headers += wayland_scanner_server.process(xml) -endforeach - -foreach p : client_protocols - xml = join_paths(p) wl_protos_headers += wayland_scanner_client.process(xml) endforeach diff --git a/swaybg/main.c b/swaybg/main.c index 94e98228..4473869b 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -6,6 +6,10 @@ #include #include #include +#include "buffer_pool.h" +#include "cairo.h" +#include "util.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" enum scaling_mode { SCALING_MODE_STRETCH, @@ -13,6 +17,31 @@ enum scaling_mode { SCALING_MODE_FIT, SCALING_MODE_CENTER, SCALING_MODE_TILE, + SCALING_MODE_SOLID_COLOR, +}; + +struct swaybg_args { + int output_idx; + const char *path; + enum scaling_mode mode; +}; + +struct swaybg_state { + const struct swaybg_args *args; + + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; + + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + + bool run_display; + uint32_t width, height; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; }; bool is_valid_color(const char *color) { @@ -33,7 +62,165 @@ bool is_valid_color(const char *color) { return true; } +static void render_frame(struct swaybg_state *state) { + if (!state->run_display) { + return; + } + + state->current_buffer = get_next_buffer(state->shm, + state->buffers, state->width, state->height); + cairo_t *cairo = state->current_buffer->cairo; + + switch (state->args->mode) { + case SCALING_MODE_SOLID_COLOR: + cairo_set_source_u32(cairo, parse_color(state->args->path)); + cairo_paint(cairo); + break; + default: + exit(1); + break; + } + + wl_surface_attach(state->surface, state->current_buffer->buffer, 0, 0); + wl_surface_damage(state->surface, 0, 0, state->width, state->height); + wl_surface_commit(state->surface); +} + +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaybg_state *state = data; + state->width = width; + state->height = height; + render_frame(state); + zwlr_layer_surface_v1_ack_configure(surface, serial); +} + +static void layer_surface_closed(void *data, + struct zwlr_layer_surface_v1 *surface) { + struct swaybg_state *state = data; + zwlr_layer_surface_v1_destroy(state->layer_surface); + wl_surface_destroy(state->surface); + state->run_display = false; +} + +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct swaybg_state *state = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + state->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + static int output_idx = 0; + if (output_idx == state->args->output_idx) { + state->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + } + output_idx++; + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + state->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); + } +} + +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares +} + +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; + int main(int argc, const char **argv) { + struct swaybg_args args = {0}; + struct swaybg_state state = {0}; + state.args = &args; wlr_log_init(L_DEBUG, NULL); + + if (argc != 4) { + wlr_log(L_ERROR, "Do not run this program manually. " + "See man 5 sway and look for output options."); + return 1; + } + args.output_idx = atoi(argv[1]); + args.path = argv[2]; + args.mode = atoi(argv[3]); + + args.mode = SCALING_MODE_STRETCH; + if (strcmp(argv[3], "stretch") == 0) { + args.mode = SCALING_MODE_STRETCH; + } else if (strcmp(argv[3], "fill") == 0) { + args.mode = SCALING_MODE_FILL; + } else if (strcmp(argv[3], "fit") == 0) { + args.mode = SCALING_MODE_FIT; + } else if (strcmp(argv[3], "center") == 0) { + args.mode = SCALING_MODE_CENTER; + } else if (strcmp(argv[3], "tile") == 0) { + args.mode = SCALING_MODE_TILE; + } else if (strcmp(argv[3], "solid_color") == 0) { + args.mode = SCALING_MODE_SOLID_COLOR; + } else { + wlr_log(L_ERROR, "Unsupported scaling mode: %s", argv[3]); + return 1; + } + + state.display = wl_display_connect(NULL); + if (!state.display) { + wlr_log(L_ERROR, "Failed to create display\n"); + return 1; + } + + struct wl_registry *registry = wl_display_get_registry(state.display); + wl_registry_add_listener(registry, ®istry_listener, &state); + wl_display_roundtrip(state.display); + + if (!state.compositor) { + wlr_log(L_DEBUG, "wl-compositor not available"); + return 1; + } + if (!state.layer_shell) { + wlr_log(L_ERROR, "layer-shell not available"); + return 1; + } + + state.surface = wl_compositor_create_surface(state.compositor); + if (!state.surface) { + wlr_log(L_ERROR, "failed to create wl_surface"); + return 1; + } + + state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state.layer_shell, state.surface, state.output, + ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); + if (!state.layer_surface) { + wlr_log(L_ERROR, "failed to create zwlr_layer_surface"); + return 1; + } + zwlr_layer_surface_v1_set_size(state.layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(state.layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_add_listener(state.layer_surface, + &layer_surface_listener, &state); + wl_surface_commit(state.surface); + wl_display_roundtrip(state.display); + + state.run_display = true; + render_frame(&state); + while (wl_display_dispatch(state.display) != -1 && state.run_display) { + // This space intentionally left blank + } return 0; } diff --git a/swaybg/meson.build b/swaybg/meson.build index 47315023..7f5d6bd1 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build @@ -1,8 +1,22 @@ +deps = [ + cairo, + jsonc, + math, + pango, + pangocairo, + sway_protos, + wayland_client, +] + +if gdk_pixbuf.found() + deps += [gdk_pixbuf] +endif + executable( 'swaybg', 'main.c', include_directories: [sway_inc], - dependencies: [wayland_client, sway_protos, jsonc, wlroots], - link_with: [lib_sway_common], + dependencies: deps, + link_with: [lib_sway_common, lib_sway_client], install: true ) diff --git a/wayland/buffers.c b/wayland/buffers.c index e9780997..3b809e6f 100644 --- a/wayland/buffers.c +++ b/wayland/buffers.c @@ -50,11 +50,8 @@ static const struct wl_buffer_listener buffer_listener = { .release = buffer_release }; -static struct buffer *create_buffer(struct window *window, struct buffer *buf, - int32_t width, int32_t height, int32_t scale, uint32_t format) { - - width *= scale; - height *= scale; +static struct buffer *create_buffer(struct wl_shm *shm, struct buffer *buf, + int32_t width, int32_t height, uint32_t format) { uint32_t stride = width * 4; uint32_t size = stride * height; @@ -65,7 +62,7 @@ static struct buffer *create_buffer(struct window *window, struct buffer *buf, return NULL; // never reached } void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - struct wl_shm_pool *pool = wl_shm_create_pool(window->registry->shm, fd, size); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); buf->buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, format); wl_shm_pool_destroy(pool); @@ -101,34 +98,30 @@ static void destroy_buffer(struct buffer *buffer) { memset(buffer, 0, sizeof(struct buffer)); } -struct buffer *get_next_buffer(struct window *window) { +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[2], uint32_t width, uint32_t height) { struct buffer *buffer = NULL; - int i; - for (i = 0; i < 2; ++i) { - if (window->buffers[i].busy) { + for (size_t i = 0; i < sizeof(pool) / sizeof(pool[0]); ++i) { + if (buffers[i].busy) { continue; } - buffer = &window->buffers[i]; + buffer = &buffers[i]; } if (!buffer) { return NULL; } - if (buffer->width != window->width || buffer->height != window->height) { + if (buffer->width != width || buffer->height != height) { destroy_buffer(buffer); } if (!buffer->buffer) { - if (!create_buffer(window, buffer, - window->width, window->height, window->scale, + if (!create_buffer(shm, buffer, width, height, WL_SHM_FORMAT_ARGB8888)) { return NULL; } } - - window->cairo = buffer->cairo; - window->buffer = buffer; return buffer; } -- cgit v1.2.3 From d39bda76c4007c42452a81883fefc671b816a74b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 12:21:50 -0400 Subject: Address review comments --- client/buffer-pool.c | 123 ------------------------------------------------- client/meson.build | 23 ++++------ client/pool-buffer.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/cairo.c | 6 +-- include/buffer_pool.h | 21 --------- include/cairo.h | 3 +- include/meson.build | 1 + include/pool-buffer.h | 21 +++++++++ meson.build | 5 +- swaybg/main.c | 44 ++++++------------ swaybg/meson.build | 36 +++++++-------- 11 files changed, 193 insertions(+), 214 deletions(-) delete mode 100644 client/buffer-pool.c create mode 100644 client/pool-buffer.c delete mode 100644 include/buffer_pool.h create mode 100644 include/meson.build create mode 100644 include/pool-buffer.h (limited to 'common') diff --git a/client/buffer-pool.c b/client/buffer-pool.c deleted file mode 100644 index 7f673ae9..00000000 --- a/client/buffer-pool.c +++ /dev/null @@ -1,123 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "buffer_pool.h" - -static int create_pool_file(size_t size, char **name) { - static const char template[] = "sway-client-XXXXXX"; - const char *path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - return -1; - } - - int ts = (path[strlen(path) - 1] == '/'); - - *name = malloc( - strlen(template) + - strlen(path) + - (ts ? 0 : 1) + 1); - sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); - - int fd = mkstemp(*name); - - if (fd < 0) { - return -1; - } - - if (ftruncate(fd, size) < 0) { - close(fd); - return -1; - } - - return fd; -} - -static void buffer_release(void *data, struct wl_buffer *wl_buffer) { - struct pool_buffer *buffer = data; - buffer->busy = false; -} - -static const struct wl_buffer_listener buffer_listener = { - .release = buffer_release -}; - -static struct pool_buffer *create_buffer(struct wl_shm *shm, - struct pool_buffer *buf, int32_t width, int32_t height, - uint32_t format) { - uint32_t stride = width * 4; - uint32_t size = stride * height; - - char *name; - int fd = create_pool_file(size, &name); - assert(fd); - void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); - buf->buffer = wl_shm_pool_create_buffer(pool, 0, - width, height, stride, format); - wl_shm_pool_destroy(pool); - close(fd); - unlink(name); - free(name); - fd = -1; - - buf->width = width; - buf->height = height; - buf->surface = cairo_image_surface_create_for_data(data, - CAIRO_FORMAT_ARGB32, width, height, stride); - buf->cairo = cairo_create(buf->surface); - buf->pango = pango_cairo_create_context(buf->cairo); - - wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); - return buf; -} - -static void destroy_buffer(struct pool_buffer *buffer) { - if (buffer->buffer) { - wl_buffer_destroy(buffer->buffer); - } - if (buffer->cairo) { - cairo_destroy(buffer->cairo); - } - if (buffer->surface) { - cairo_surface_destroy(buffer->surface); - } - if (buffer->pango) { - g_object_unref(buffer->pango); - } - memset(buffer, 0, sizeof(struct pool_buffer)); -} - -struct pool_buffer *get_next_buffer(struct wl_shm *shm, - struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { - struct pool_buffer *buffer = NULL; - - for (size_t i = 0; i < 2; ++i) { - if (pool[i].busy) { - continue; - } - buffer = &pool[i]; - } - - if (!buffer) { - return NULL; - } - - if (buffer->width != width || buffer->height != height) { - destroy_buffer(buffer); - } - - if (!buffer->buffer) { - if (!create_buffer(shm, buffer, width, height, - WL_SHM_FORMAT_ARGB8888)) { - return NULL; - } - } - return buffer; -} diff --git a/client/meson.build b/client/meson.build index 597899ce..2bdda457 100644 --- a/client/meson.build +++ b/client/meson.build @@ -1,21 +1,16 @@ -deps = [ - cairo, - pango, - pangocairo, - wlroots, - wayland_client, -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - lib_sway_client = static_library( 'sway-client', files( - 'buffer-pool.c', + 'pool-buffer.c', ), - dependencies: deps, + dependencies: [ + cairo, + gdk_pixbuf, + pango, + pangocairo, + wlroots, + wayland_client, + ], link_with: [lib_sway_common], include_directories: sway_inc ) diff --git a/client/pool-buffer.c b/client/pool-buffer.c new file mode 100644 index 00000000..93cfcfc5 --- /dev/null +++ b/client/pool-buffer.c @@ -0,0 +1,124 @@ +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "pool-buffer.h" + +static int create_pool_file(size_t size, char **name) { + static const char template[] = "sway-client-XXXXXX"; + const char *path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + return -1; + } + + int ts = (path[strlen(path) - 1] == '/'); + + *name = malloc( + strlen(template) + + strlen(path) + + (ts ? 0 : 1) + 1); + sprintf(*name, "%s%s%s", path, ts ? "" : "/", template); + + int fd = mkstemp(*name); + + if (fd < 0) { + return -1; + } + + if (ftruncate(fd, size) < 0) { + close(fd); + return -1; + } + + return fd; +} + +static void buffer_release(void *data, struct wl_buffer *wl_buffer) { + struct pool_buffer *buffer = data; + buffer->busy = false; +} + +static const struct wl_buffer_listener buffer_listener = { + .release = buffer_release +}; + +static struct pool_buffer *create_buffer(struct wl_shm *shm, + struct pool_buffer *buf, int32_t width, int32_t height, + uint32_t format) { + uint32_t stride = width * 4; + uint32_t size = stride * height; + + char *name; + int fd = create_pool_file(size, &name); + assert(fd); + void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buf->buffer = wl_shm_pool_create_buffer(pool, 0, + width, height, stride, format); + wl_shm_pool_destroy(pool); + close(fd); + unlink(name); + free(name); + fd = -1; + + buf->width = width; + buf->height = height; + buf->surface = cairo_image_surface_create_for_data(data, + CAIRO_FORMAT_ARGB32, width, height, stride); + buf->cairo = cairo_create(buf->surface); + buf->pango = pango_cairo_create_context(buf->cairo); + + wl_buffer_add_listener(buf->buffer, &buffer_listener, buf); + return buf; +} + +static void destroy_buffer(struct pool_buffer *buffer) { + if (buffer->buffer) { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->cairo) { + cairo_destroy(buffer->cairo); + } + if (buffer->surface) { + cairo_surface_destroy(buffer->surface); + } + if (buffer->pango) { + g_object_unref(buffer->pango); + } + memset(buffer, 0, sizeof(struct pool_buffer)); +} + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height) { + struct pool_buffer *buffer = NULL; + + for (size_t i = 0; i < 2; ++i) { + if (pool[i].busy) { + continue; + } + buffer = &pool[i]; + } + + if (!buffer) { + return NULL; + } + + if (buffer->width != width || buffer->height != height) { + destroy_buffer(buffer); + } + + if (!buffer->buffer) { + if (!create_buffer(shm, buffer, width, height, + WL_SHM_FORMAT_ARGB8888)) { + return NULL; + } + } + return buffer; +} diff --git a/common/cairo.c b/common/cairo.c index c6bd0da9..c267c77c 100644 --- a/common/cairo.c +++ b/common/cairo.c @@ -1,7 +1,7 @@ #include #include #include "cairo.h" -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF #include #endif @@ -30,7 +30,7 @@ cairo_surface_t *cairo_image_surface_scale(cairo_surface_t *image, return new; } -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdkbuf) { int chan = gdk_pixbuf_get_n_channels(gdkbuf); if (chan < 3) { @@ -124,4 +124,4 @@ cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf(const GdkPixbuf *gdk cairo_surface_mark_dirty(cs); return cs; } -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF diff --git a/include/buffer_pool.h b/include/buffer_pool.h deleted file mode 100644 index cdebd64d..00000000 --- a/include/buffer_pool.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _SWAY_BUFFERS_H -#define _SWAY_BUFFERS_H -#include -#include -#include -#include -#include - -struct pool_buffer { - struct wl_buffer *buffer; - cairo_surface_t *surface; - cairo_t *cairo; - PangoContext *pango; - uint32_t width, height; - bool busy; -}; - -struct pool_buffer *get_next_buffer(struct wl_shm *shm, - struct pool_buffer pool[static 2], uint32_t width, uint32_t height); - -#endif diff --git a/include/cairo.h b/include/cairo.h index f5f474d7..31672705 100644 --- a/include/cairo.h +++ b/include/cairo.h @@ -8,7 +8,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 "config.h" +#ifdef HAVE_GDK_PIXBUF #include cairo_surface_t* gdk_cairo_image_surface_create_from_pixbuf( diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 00000000..65ed027a --- /dev/null +++ b/include/meson.build @@ -0,0 +1 @@ +configure_file(output: 'config.h', configuration: conf_data) diff --git a/include/pool-buffer.h b/include/pool-buffer.h new file mode 100644 index 00000000..cdebd64d --- /dev/null +++ b/include/pool-buffer.h @@ -0,0 +1,21 @@ +#ifndef _SWAY_BUFFERS_H +#define _SWAY_BUFFERS_H +#include +#include +#include +#include +#include + +struct pool_buffer { + struct wl_buffer *buffer; + cairo_surface_t *surface; + cairo_t *cairo; + PangoContext *pango; + uint32_t width, height; + bool busy; +}; + +struct pool_buffer *get_next_buffer(struct wl_shm *shm, + struct pool_buffer pool[static 2], uint32_t width, uint32_t height); + +#endif diff --git a/meson.build b/meson.build index 0c35b0e5..b681f43a 100644 --- a/meson.build +++ b/meson.build @@ -38,8 +38,10 @@ math = cc.find_library('m') git = find_program('git', required: false) a2x = find_program('a2x', required: false) +conf_data = configuration_data() + if gdk_pixbuf.found() - add_project_arguments('-DWITH_GDK_PIXBUF', language : 'c') + conf_data.set('HAVE_GDK_PIXBUF', true) endif if a2x.found() @@ -92,6 +94,7 @@ add_project_arguments('-DSWAY_VERSION=@0@'.format(version), language: 'c') sway_inc = include_directories('include') +subdir('include') subdir('protocols') subdir('common') subdir('sway') diff --git a/swaybg/main.c b/swaybg/main.c index 62ddec6c..f431526c 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,7 +7,7 @@ #include #include #include -#include "buffer_pool.h" +#include "pool-buffer.h" #include "cairo.h" #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -127,7 +128,7 @@ static void render_image(struct swaybg_state *state) { break; } case BACKGROUND_MODE_SOLID_COLOR: - // Should never happen + assert(0); break; } cairo_paint(cairo); @@ -158,7 +159,7 @@ static bool prepare_context(struct swaybg_state *state) { state->context.color = parse_color(state->args->path); return is_valid_color(state->args->path); } -#ifdef WITH_GDK_PIXBUF +#ifdef HAVE_GDK_PIXBUF GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err); if (!pixbuf) { @@ -170,17 +171,17 @@ static bool prepare_context(struct swaybg_state *state) { #else state->context.image = cairo_image_surface_create_from_png( state->args->path); -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF if (!state->context.image) { wlr_log(L_ERROR, "Failed to read background image."); return false; } if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) { wlr_log(L_ERROR, "Failed to read background image: %s." -#ifndef WITH_GDK_PIXBUF +#ifndef HAVE_GDK_PIXBUF "\nSway was compiled without gdk_pixbuf support, so only" "\nPNG images can be loaded. This is the likely cause." -#endif //WITH_GDK_PIXBUF +#endif //HAVE_GDK_PIXBUF , cairo_status_to_string( cairo_surface_status(state->context.image))); return false; @@ -256,7 +257,6 @@ int main(int argc, const char **argv) { } args.output_idx = atoi(argv[1]); args.path = argv[2]; - args.mode = atoi(argv[3]); args.mode = BACKGROUND_MODE_STRETCH; if (strcmp(argv[3], "stretch") == 0) { @@ -280,38 +280,20 @@ int main(int argc, const char **argv) { return 1; } - state.display = wl_display_connect(NULL); - if (!state.display) { - wlr_log(L_ERROR, "Failed to create display\n"); - return 1; - } + assert(state.display = wl_display_connect(NULL)); struct wl_registry *registry = wl_display_get_registry(state.display); wl_registry_add_listener(registry, ®istry_listener, &state); wl_display_roundtrip(state.display); + assert(state.compositor && state.layer_shell && state.output && state.shm); - if (!state.compositor) { - wlr_log(L_DEBUG, "wl-compositor not available"); - return 1; - } - if (!state.layer_shell) { - wlr_log(L_ERROR, "layer-shell not available"); - return 1; - } - - state.surface = wl_compositor_create_surface(state.compositor); - if (!state.surface) { - wlr_log(L_ERROR, "failed to create wl_surface"); - return 1; - } + assert(state.surface = wl_compositor_create_surface(state.compositor)); state.layer_surface = zwlr_layer_shell_v1_get_layer_surface( state.layer_shell, state.surface, state.output, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper"); - if (!state.layer_surface) { - wlr_log(L_ERROR, "failed to create zwlr_layer_surface"); - return 1; - } + assert(state.layer_surface); + zwlr_layer_surface_v1_set_size(state.layer_surface, 0, 0); zwlr_layer_surface_v1_set_anchor(state.layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | @@ -320,10 +302,10 @@ int main(int argc, const char **argv) { ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); zwlr_layer_surface_v1_add_listener(state.layer_surface, &layer_surface_listener, &state); + state.run_display = true; wl_surface_commit(state.surface); wl_display_roundtrip(state.display); - state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } diff --git a/swaybg/meson.build b/swaybg/meson.build index 7f5d6bd1..5e10f3c7 100644 --- a/swaybg/meson.build +++ b/swaybg/meson.build @@ -1,22 +1,18 @@ -deps = [ - cairo, - jsonc, - math, - pango, - pangocairo, - sway_protos, - wayland_client, -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - executable( - 'swaybg', - 'main.c', - include_directories: [sway_inc], - dependencies: deps, - link_with: [lib_sway_common, lib_sway_client], - install: true + 'swaybg', + 'main.c', + include_directories: [sway_inc], + dependencies: [ + cairo, + gdk_pixbuf, + jsonc, + math, + pango, + pangocairo, + sway_protos, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true ) -- cgit v1.2.3 From 382e8af418a7e1b8cf93d3398509b93c6874cb0d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 21:21:36 -0400 Subject: Allow sway IPC clients to fall back to i3 socket --- common/ipc-client.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/ipc-client.c b/common/ipc-client.c index 582c5e86..117e9910 100644 --- a/common/ipc-client.c +++ b/common/ipc-client.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 2 +#define _POSIX_C_SOURCE 200809L #include #include #include @@ -14,13 +14,31 @@ static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; static const size_t ipc_header_size = sizeof(ipc_magic)+8; char *get_socketpath(void) { - FILE *fp = popen("sway --get-socketpath", "r"); - if (!fp) { - return NULL; + const char *swaysock = getenv("SWAYSOCK"); + if (swaysock) { + return strdup(swaysock); } - char *line = read_line(fp); - pclose(fp); - return line; + FILE *fp = popen("sway --get-socketpath 2>/dev/null", "r"); + if (fp) { + char *line = read_line(fp); + pclose(fp); + if (line && *line) { + return line; + } + } + const char *i3sock = getenv("I3SOCK"); + if (i3sock) { + return strdup(i3sock); + } + fp = popen("i3 --get-socketpath 2>/dev/null", "r"); + if (fp) { + char *line = read_line(fp); + pclose(fp); + if (line && *line) { + return line; + } + } + return NULL; } int ipc_open_socket(const char *socket_path) { -- cgit v1.2.3 From cab1352801b62d1b8a12ca1c995cb24445ce4bc9 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 28 Mar 2018 23:04:20 -0400 Subject: Start port of swaybar to layer shell This starts up the event loop and wayland display and shims out the basic top level rendering concepts. Also includes some changes to incorporate pango into the 1.x codebase properly. --- common/meson.build | 3 + common/pango.c | 67 ++++++ include/pango.h | 16 ++ include/sway/config.h | 7 +- include/swaybar/bar.h | 89 +++----- include/swaybar/config.h | 43 +--- include/swaybar/event_loop.h | 4 +- include/swaybar/ipc.h | 22 +- include/swaybar/render.h | 22 +- meson.build | 3 + swaybar/bar.c | 444 ++++++++---------------------------- swaybar/config.c | 37 ++- swaybar/event_loop.c | 10 +- swaybar/ipc.c | 410 --------------------------------- swaybar/main.c | 33 ++- swaybar/meson.build | 25 ++ swaybar/render.c | 388 ++++--------------------------- swaybar/status_line.c | 530 ------------------------------------------- swaybar/tray/dbus.c | 197 ---------------- swaybar/tray/icon.c | 400 -------------------------------- swaybar/tray/sni.c | 481 --------------------------------------- swaybar/tray/sni_watcher.c | 497 ---------------------------------------- swaybar/tray/tray.c | 398 -------------------------------- 23 files changed, 342 insertions(+), 3784 deletions(-) create mode 100644 common/pango.c create mode 100644 include/pango.h delete mode 100644 swaybar/ipc.c create mode 100644 swaybar/meson.build delete mode 100644 swaybar/status_line.c delete mode 100644 swaybar/tray/dbus.c delete mode 100644 swaybar/tray/icon.c delete mode 100644 swaybar/tray/sni.c delete mode 100644 swaybar/tray/sni_watcher.c delete mode 100644 swaybar/tray/tray.c (limited to 'common') diff --git a/common/meson.build b/common/meson.build index 01736ca6..4ad47077 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,5 +1,7 @@ deps = [ cairo, + pango, + pangocairo, wlroots ] @@ -14,6 +16,7 @@ lib_sway_common = static_library( 'ipc-client.c', 'log.c', 'list.c', + 'pango.c', 'readline.c', 'stringop.c', 'util.c' diff --git a/common/pango.c b/common/pango.c new file mode 100644 index 00000000..212d96cf --- /dev/null +++ b/common/pango.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, + const char *text, int32_t scale, bool markup) { + PangoLayout *layout = pango_cairo_create_layout(cairo); + PangoAttrList *attrs; + if (markup) { + char *buf; + pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL); + pango_layout_set_markup(layout, buf, -1); + free(buf); + } else { + attrs = pango_attr_list_new(); + pango_layout_set_text(layout, text, -1); + } + pango_attr_list_insert(attrs, pango_attr_scale_new(scale)); + PangoFontDescription *desc = pango_font_description_from_string(font); + pango_layout_set_font_description(layout, desc); + pango_layout_set_single_paragraph_mode(layout, 1); + pango_layout_set_attributes(layout, attrs); + pango_attr_list_unref(attrs); + pango_font_description_free(desc); + return layout; +} + +void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, + int32_t scale, bool markup, const char *fmt, ...) { + char *buf = malloc(2048); + + va_list args; + va_start(args, fmt); + if (vsnprintf(buf, 2048, fmt, args) >= 2048) { + strcpy(buf, "[buffer overflow]"); + } + va_end(args); + + PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); + pango_cairo_update_layout(cairo, layout); + pango_layout_get_pixel_size(layout, width, height); + g_object_unref(layout); + free(buf); +} + +void pango_printf(cairo_t *cairo, const char *font, + int32_t scale, bool markup, const char *fmt, ...) { + char *buf = malloc(2048); + + va_list args; + va_start(args, fmt); + if (vsnprintf(buf, 2048, fmt, args) >= 2048) { + strcpy(buf, "[buffer overflow]"); + } + va_end(args); + + PangoLayout *layout = get_pango_layout(cairo, font, buf, scale, markup); + pango_cairo_update_layout(cairo, layout); + pango_cairo_show_layout(cairo, layout); + g_object_unref(layout); + free(buf); +} diff --git a/include/pango.h b/include/pango.h new file mode 100644 index 00000000..f6325f28 --- /dev/null +++ b/include/pango.h @@ -0,0 +1,16 @@ +#ifndef _SWAY_PANGO_H +#define _SWAY_PANGO_H +#include +#include +#include +#include +#include + +PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, + const char *text, int32_t scale, bool markup); +void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, + int32_t scale, bool markup, const char *fmt, ...); +void pango_printf(cairo_t *cairo, const char *font, + int32_t scale, bool markup, const char *fmt, ...); + +#endif diff --git a/include/sway/config.h b/include/sway/config.h index 48a8b0ab..8c9e04de 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -1,17 +1,16 @@ #ifndef _SWAY_CONFIG_H #define _SWAY_CONFIG_H - #define PID_WORKSPACE_TIMEOUT 60 - #include #include #include +#include #include #include -#include #include "list.h" #include "layout.h" #include "container.h" +#include "wlr-layer-shell-unstable-v1-protocol.h" /** * Describes a variable created via the `set` command. @@ -152,7 +151,7 @@ struct bar_config { char *id; uint32_t modifier; list_t *outputs; - //enum desktop_shell_panel_position position; // TODO + char *position; list_t *bindings; char *status_command; bool pango_markup; diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 50d36e76..3ae8c0b3 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -1,72 +1,45 @@ #ifndef _SWAYBAR_BAR_H #define _SWAYBAR_BAR_H - -#include "client/registry.h" -#include "client/window.h" +#include +#include "pool-buffer.h" #include "list.h" -struct bar { - struct config *config; - struct status_line *status; - list_t *outputs; - struct output *focused_output; +struct swaybar_config; +struct swaybar_output; +struct swaybar_workspace; + +struct swaybar { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; - int ipc_event_socketfd; - int ipc_socketfd; - int status_read_fd; - int status_write_fd; - pid_t status_command_pid; + struct swaybar_config *config; + struct swaybar_output *focused_output; + + struct wl_list outputs; }; -struct output { - struct window *window; - struct registry *registry; - list_t *workspaces; -#ifdef ENABLE_TRAY - list_t *items; -#endif +struct swaybar_output { + struct wl_list link; + struct swaybar *bar; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + char *name; int idx; bool focused; -}; -struct workspace { - int num; - char *name; - bool focused; - bool visible; - bool urgent; + uint32_t width, height; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; }; -/** Global bar state */ -extern struct bar swaybar; +void bar_setup(struct swaybar *bar, + const char *socket_path, + const char *bar_id); +void bar_run(struct swaybar *bar); +void bar_teardown(struct swaybar *bar); -/** True if sway needs to render */ -extern bool dirty; - -/** - * Setup bar. - */ -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id); - -/** - * Create new output struct from name. - */ -struct output *new_output(const char *name); - -/** - * Bar mainloop. - */ -void bar_run(struct bar *bar); - -/** - * free workspace list. - */ -void free_workspaces(list_t *workspaces); - -/** - * Teardown bar. - */ -void bar_teardown(struct bar *bar); - -#endif /* _SWAYBAR_BAR_H */ +#endif diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 651f0ee3..1bfe4843 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -1,9 +1,7 @@ #ifndef _SWAYBAR_CONFIG_H #define _SWAYBAR_CONFIG_H - -#include #include - +#include #include "list.h" #include "util.h" @@ -19,10 +17,10 @@ struct box_colors { /** * Swaybar config. */ -struct config { +struct swaybar_config { char *status_command; bool pango_markup; - uint32_t position; + uint32_t position; // zwlr_layer_surface_v1_anchor char *font; char *sep_symbol; char *mode; @@ -32,18 +30,6 @@ struct config { bool workspace_buttons; 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 { @@ -63,24 +49,7 @@ struct config { } colors; }; -/** - * Parse position top|bottom|left|right. - */ -uint32_t parse_position(const char *position); - -/** - * Parse font. - */ -char *parse_font(const char *font); - -/** - * Initialize default sway config. - */ -struct config *init_config(); - -/** - * Free config struct. - */ -void free_config(struct config *config); +struct swaybar_config *init_config(); +void free_config(struct swaybar_config *config); -#endif /* _SWAYBAR_CONFIG_H */ +#endif diff --git a/include/swaybar/event_loop.h b/include/swaybar/event_loop.h index a0cde07f..99f6ed36 100644 --- a/include/swaybar/event_loop.h +++ b/include/swaybar/event_loop.h @@ -1,6 +1,5 @@ #ifndef _SWAYBAR_EVENT_LOOP_H #define _SWAYBAR_EVENT_LOOP_H - #include #include @@ -23,4 +22,5 @@ bool remove_timer(timer_t timer); void event_loop_poll(); void init_event_loop(); -#endif /*_SWAYBAR_EVENT_LOOP_H */ + +#endif diff --git a/include/swaybar/ipc.h b/include/swaybar/ipc.h index c11931d0..57a1b925 100644 --- a/include/swaybar/ipc.h +++ b/include/swaybar/ipc.h @@ -1,23 +1,9 @@ #ifndef _SWAYBAR_IPC_H #define _SWAYBAR_IPC_H +#include "swaybar/bar.h" -#include "bar.h" - -/** - * Initialize ipc connection to sway and get sway state, outputs, bar_config. - */ -void ipc_bar_init(struct bar *bar, const char *bar_id); - -/** - * Handle ipc event from sway. - */ -bool handle_ipc_event(struct bar *bar); - - -/** - * Send workspace command to sway - */ +void ipc_bar_init(struct swaybar *bar, const char *bar_id); +bool handle_ipc_event(struct swaybar *bar); void ipc_send_workspace_command(const char *workspace_name); -#endif /* _SWAYBAR_IPC_H */ - +#endif diff --git a/include/swaybar/render.h b/include/swaybar/render.h index 114f43f4..071e2298 100644 --- a/include/swaybar/render.h +++ b/include/swaybar/render.h @@ -1,22 +1,10 @@ #ifndef _SWAYBAR_RENDER_H #define _SWAYBAR_RENDER_H -#include "config.h" -#include "bar.h" +struct swaybar; +struct swaybar_output; +struct swaybar_config; -/** - * Render swaybar. - */ -void render(struct output *output, struct config *config, struct status_line *line); +void render_frame(struct swaybar *bar, struct swaybar_output *output); -/** - * Set window height and modify internal spacing accordingly. - */ -void set_window_height(struct window *window, int height); - -/** - * Compute the size of a workspace name - */ -void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height); - -#endif /* _SWAYBAR_RENDER_H */ +#endif diff --git a/meson.build b/meson.build index b681f43a..49824b30 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,7 @@ pixman = dependency('pixman-1') libcap = dependency('libcap') libinput = dependency('libinput') math = cc.find_library('m') +rt = cc.find_library('rt') git = find_program('git', required: false) a2x = find_program('a2x', required: false) @@ -99,8 +100,10 @@ subdir('protocols') subdir('common') subdir('sway') subdir('swaymsg') + subdir('client') subdir('swaybg') +subdir('swaybar') config = configuration_data() config.set('sysconfdir', join_paths(prefix, sysconfdir)) diff --git a/swaybar/bar.c b/swaybar/bar.c index f12923a8..e1d594b4 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -1,390 +1,146 @@ #define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include #include -#include #include -#include -#include #include -#include -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif -#ifdef ENABLE_TRAY -#include -#include "swaybar/tray/sni_watcher.h" -#include "swaybar/tray/tray.h" -#include "swaybar/tray/sni.h" -#endif -#include "swaybar/ipc.h" +#include +#include +#include #include "swaybar/render.h" #include "swaybar/config.h" -#include "swaybar/status_line.h" #include "swaybar/event_loop.h" #include "swaybar/bar.h" -#include "ipc-client.h" #include "list.h" -#include "log.h" +#include "pango.h" +#include "pool-buffer.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" -static void bar_init(struct bar *bar) { +static void bar_init(struct swaybar *bar) { bar->config = init_config(); - bar->status = init_status_line(); - bar->outputs = create_list(); + wl_list_init(&bar->outputs); } -static void spawn_status_cmd_proc(struct bar *bar) { - if (bar->config->status_command) { - int pipe_read_fd[2]; - int pipe_write_fd[2]; - - if (pipe(pipe_read_fd) != 0) { - sway_log(L_ERROR, "Unable to create pipes for status_command fork"); - return; - } - if (pipe(pipe_write_fd) != 0) { - sway_log(L_ERROR, "Unable to create pipe for status_command fork (write)"); - close(pipe_read_fd[0]); - close(pipe_read_fd[1]); - return; - } - - bar->status_command_pid = fork(); - if (bar->status_command_pid == 0) { - close(pipe_read_fd[0]); - dup2(pipe_read_fd[1], STDOUT_FILENO); - close(pipe_read_fd[1]); - - dup2(pipe_write_fd[0], STDIN_FILENO); - close(pipe_write_fd[0]); - close(pipe_write_fd[1]); - - char *const cmd[] = { - "sh", - "-c", - bar->config->status_command, - NULL, - }; - execvp(cmd[0], cmd); - return; - } - - close(pipe_read_fd[1]); - bar->status_read_fd = pipe_read_fd[0]; - fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK); - - close(pipe_write_fd[0]); - bar->status_write_fd = pipe_write_fd[1]; - fcntl(bar->status_write_fd, F_SETFL, O_NONBLOCK); - } -} - -struct output *new_output(const char *name) { - struct output *output = malloc(sizeof(struct output)); +struct swaybar_output *new_output(const char *name) { + struct swaybar_output *output = malloc(sizeof(struct swaybar_output)); output->name = strdup(name); - output->window = NULL; - output->registry = NULL; - output->workspaces = create_list(); -#ifdef ENABLE_TRAY - output->items = create_list(); -#endif return output; } -static void mouse_button_notify(struct window *window, int x, int y, - uint32_t button, uint32_t state_w) { - sway_log(L_DEBUG, "Mouse button %d clicked at %d %d %d", button, x, y, state_w); - if (!state_w) { - return; - } - - struct output *clicked_output = NULL; - for (int i = 0; i < swaybar.outputs->length; i++) { - struct output *output = swaybar.outputs->items[i]; - if (window == output->window) { - clicked_output = output; - break; - } - } - - if (!sway_assert(clicked_output != NULL, "Got pointer event for non-existing output")) { - return; - } - - double button_x = 0.5; - for (int i = 0; i < clicked_output->workspaces->length; i++) { - struct workspace *workspace = clicked_output->workspaces->items[i]; - int button_width, button_height; - - workspace_button_size(window, workspace->name, &button_width, &button_height); - - button_x += button_width; - if (x <= button_x) { - ipc_send_workspace_command(workspace->name); - break; - } - } - - switch (button) { - case BTN_LEFT: - status_line_mouse_event(&swaybar, x, y, 1); - break; - case BTN_MIDDLE: - status_line_mouse_event(&swaybar, x, y, 2); - break; - case BTN_RIGHT: - status_line_mouse_event(&swaybar, x, y, 3); - break; - } - -#ifdef ENABLE_TRAY - tray_mouse_event(clicked_output, x, y, button, state_w); -#endif - +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaybar_output *output = data; + output->width = width; + output->height = height; + zwlr_layer_surface_v1_ack_configure(surface, serial); + render_frame(output->bar, output); } -static void mouse_scroll_notify(struct window *window, enum scroll_direction direction) { - sway_log(L_DEBUG, "Mouse wheel scrolled %s", direction == SCROLL_UP ? "up" : "down"); - - // If there are status blocks and click_events are enabled - // check if the position is within the status area and if so - // tell the status line to output the event and skip workspace - // switching below. - int num_blocks = swaybar.status->block_line->length; - if (swaybar.status->click_events && num_blocks > 0) { - struct status_block *first_block = swaybar.status->block_line->items[0]; - int x = window->pointer_input.last_x; - int y = window->pointer_input.last_y; - if (x > first_block->x) { - if (direction == SCROLL_UP) { - status_line_mouse_event(&swaybar, x, y, 4); - } else { - status_line_mouse_event(&swaybar, x, y, 5); - } - return; - } - } +static void layer_surface_closed(void *_output, + struct zwlr_layer_surface_v1 *surface) { + // TODO: Deal with hotplugging + struct swaybar_output *output = output; + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_destroy(output->surface); +} - if (!swaybar.config->wrap_scroll) { - // Find output this window lives on - int i; - struct output *output = NULL; - for (i = 0; i < swaybar.outputs->length; ++i) { - output = swaybar.outputs->items[i]; - if (output->window == window) { - break; - } - } - if (!sway_assert(i != swaybar.outputs->length, "Unknown window in scroll event")) { - return; - } - int focused = -1; - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - if (ws->focused) { - focused = i; - break; - } - } - if (!sway_assert(focused != -1, "Scroll wheel event received on inactive output")) { - return; - } - if ((focused == 0 && direction == SCROLL_UP) || - (focused == output->workspaces->length - 1 && direction == SCROLL_DOWN)) { - // Do not wrap - return; - } +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct swaybar *bar = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + bar->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + bar->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + static int idx = 0; + struct swaybar_output *output = + calloc(1, sizeof(struct swaybar_output)); + output->bar = bar; + output->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + output->idx = idx++; + wl_list_insert(&bar->outputs, &output->link); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + bar->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); } +} - const char *workspace_name = direction == SCROLL_UP ? "prev_on_output" : "next_on_output"; - ipc_send_workspace_command(workspace_name); +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares } -void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { - /* initialize bar with default values */ - bar_init(bar); +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; - /* Initialize event loop lists */ +void bar_setup(struct swaybar *bar, + const char *socket_path, const char *bar_id) { + bar_init(bar); init_event_loop(); - /* connect to sway ipc */ - bar->ipc_socketfd = ipc_open_socket(socket_path); - bar->ipc_event_socketfd = ipc_open_socket(socket_path); - - ipc_bar_init(bar, bar_id); - - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *bar_output = bar->outputs->items[i]; - - bar_output->registry = registry_poll(); - - if (!bar_output->registry->desktop_shell) { - sway_abort("swaybar requires the compositor to support the desktop-shell extension."); - } - - struct output_state *output = bar_output->registry->outputs->items[bar_output->idx]; - - bar_output->window = window_setup(bar_output->registry, - output->width / output->scale, 30, output->scale, false); - if (!bar_output->window) { - sway_abort("Failed to create window."); - } - desktop_shell_set_panel(bar_output->registry->desktop_shell, - output->output, bar_output->window->surface); - desktop_shell_set_panel_position(bar_output->registry->desktop_shell, + assert(bar->display = wl_display_connect(NULL)); + + struct wl_registry *registry = wl_display_get_registry(bar->display); + wl_registry_add_listener(registry, ®istry_listener, bar); + wl_display_roundtrip(bar->display); + assert(bar->compositor && bar->layer_shell && bar->shm); + + // TODO: we might not necessarily be meant to do all of the outputs + struct swaybar_output *output; + wl_list_for_each(output, &bar->outputs, link) { + assert(output->surface = wl_compositor_create_surface(bar->compositor)); + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + bar->layer_shell, output->surface, output->output, + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); + assert(output->layer_surface); + zwlr_layer_surface_v1_add_listener(output->layer_surface, + &layer_surface_listener, output); + zwlr_layer_surface_v1_set_anchor(output->layer_surface, bar->config->position); - - window_make_shell(bar_output->window); - - /* set font */ - bar_output->window->font = bar->config->font; - - /* set mouse event callbacks */ - bar_output->window->pointer_input.notify_button = mouse_button_notify; - bar_output->window->pointer_input.notify_scroll = mouse_scroll_notify; - - /* set window height */ - set_window_height(bar_output->window, bar->config->height); + render_frame(bar, output); } - /* spawn status command */ - spawn_status_cmd_proc(bar); - -#ifdef ENABLE_TRAY - init_tray(bar); -#endif } -bool dirty = true; - -static void respond_ipc(int fd, short mask, void *_bar) { - struct bar *bar = (struct bar *)_bar; - sway_log(L_DEBUG, "Got IPC event."); - dirty = handle_ipc_event(bar); -} - -static void respond_command(int fd, short mask, void *_bar) { - struct bar *bar = (struct bar *)_bar; - dirty = handle_status_line(bar); -} - -static void respond_output(int fd, short mask, void *_output) { - struct output *output = (struct output *)_output; - if (wl_display_dispatch(output->registry->display) == -1) { - sway_log(L_ERROR, "failed to dispatch wl: %d", errno); +static void display_in(int fd, short mask, void *_bar) { + struct swaybar *bar = (struct swaybar *)_bar; + if (wl_display_dispatch(bar->display) == -1) { + wlr_log(L_ERROR, "failed to dispatch wl: %d", errno); } } -void bar_run(struct bar *bar) { - add_event(bar->ipc_event_socketfd, POLLIN, respond_ipc, bar); - add_event(bar->status_read_fd, POLLIN, respond_command, bar); - - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - add_event(wl_display_get_fd(output->registry->display), - POLLIN, respond_output, output); - } - +void bar_run(struct swaybar *bar) { + add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar); while (1) { - if (dirty) { - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - if (window_prerender(output->window) && output->window->cairo) { - render(output, bar->config, bar->status); - window_render(output->window); - wl_display_flush(output->registry->display); - } - } - } - - dirty = false; - event_loop_poll(); -#ifdef ENABLE_TRAY - dispatch_dbus(); -#endif } } -void free_workspaces(list_t *workspaces) { - int i; - for (i = 0; i < workspaces->length; ++i) { - struct workspace *ws = workspaces->items[i]; - free(ws->name); - free(ws); +static void free_outputs(struct wl_list *list) { + struct swaybar_output *output, *tmp; + wl_list_for_each_safe(output, tmp, list, link) { + wl_list_remove(&output->link); + free(output->name); + free(output); } - list_free(workspaces); } -static void free_output(struct output *output) { - window_teardown(output->window); - if (output->registry) { - registry_teardown(output->registry); - } - - free(output->name); - - if (output->workspaces) { - free_workspaces(output->workspaces); - } - - free(output); -} - -static void free_outputs(list_t *outputs) { - int i; - for (i = 0; i < outputs->length; ++i) { - free_output(outputs->items[i]); - } - list_free(outputs); -} - -static void terminate_status_command(pid_t pid) { - if (pid) { - // terminate status_command process - int ret = kill(pid, SIGTERM); - if (ret != 0) { - sway_log(L_ERROR, "Unable to terminate status_command [pid: %d]", pid); - } else { - int status; - waitpid(pid, &status, 0); - } - } -} - -void bar_teardown(struct bar *bar) { +void bar_teardown(struct swaybar *bar) { + free_outputs(&bar->outputs); if (bar->config) { free_config(bar->config); } - - if (bar->outputs) { - free_outputs(bar->outputs); - } - - if (bar->status) { - free_status_line(bar->status); - } - - /* close sockets/pipes */ - if (bar->status_read_fd) { - close(bar->status_read_fd); - } - - if (bar->status_write_fd) { - close(bar->status_write_fd); - } - - if (bar->ipc_socketfd) { - close(bar->ipc_socketfd); - } - - if (bar->ipc_event_socketfd) { - close(bar->ipc_event_socketfd); - } - - /* terminate status command process */ - terminate_status_command(bar->status_command_pid); } diff --git a/swaybar/config.c b/swaybar/config.c index 8fe552f2..0c2b57e0 100644 --- a/swaybar/config.c +++ b/swaybar/config.c @@ -1,21 +1,24 @@ #define _XOPEN_SOURCE 500 #include #include -#include "wayland-desktop-shell-client-protocol.h" -#include "log.h" #include "swaybar/config.h" +#include "wlr-layer-shell-unstable-v1-client-protocol.h" uint32_t parse_position(const char *position) { + uint32_t horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + uint32_t vert = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; if (strcmp("top", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_TOP; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | horiz; } else if (strcmp("bottom", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_BOTTOM; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | horiz; } else if (strcmp("left", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_LEFT; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | vert; } else if (strcmp("right", position) == 0) { - return DESKTOP_SHELL_PANEL_POSITION_RIGHT; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | vert; } else { - return DESKTOP_SHELL_PANEL_POSITION_BOTTOM; + return ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | horiz; } } @@ -30,11 +33,11 @@ char *parse_font(const char *font) { return new_font; } -struct config *init_config() { - struct config *config = calloc(1, sizeof(struct config)); +struct swaybar_config *init_config() { + struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); config->status_command = NULL; config->pango_markup = false; - config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; + config->position = parse_position("bottom"); config->font = strdup("monospace 10"); config->mode = NULL; config->sep_symbol = NULL; @@ -48,18 +51,6 @@ struct config *init_config() { /* height */ config->height = 0; -#ifdef ENABLE_TRAY - config->tray_output = NULL; - config->icon_theme = NULL; - config->tray_padding = 2; - /** - * These constants are used by wayland and are defined in - * linux/input-event-codes.h - */ - config->activate_button = 0x110; /* BTN_LEFT */ - config->context_button = 0x111; /* BTN_RIGHT */ -#endif - /* colors */ config->colors.background = 0x000000FF; config->colors.statusline = 0xFFFFFFFF; @@ -88,7 +79,7 @@ struct config *init_config() { return config; } -void free_config(struct config *config) { +void free_config(struct swaybar_config *config) { free(config->status_command); free(config->font); free(config->mode); diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c index 0d1be1da..748372ed 100644 --- a/swaybar/event_loop.c +++ b/swaybar/event_loop.c @@ -4,19 +4,18 @@ #include #include #include -#include "swaybar/bar.h" +#include #include "swaybar/event_loop.h" #include "list.h" -#include "log.h" struct event_item { - void(*cb)(int fd, short mask, void *data); + void (*cb)(int fd, short mask, void *data); void *data; }; struct timer_item { timer_t timer; - void(*cb)(timer_t timer, void *data); + void (*cb)(timer_t timer, void *data); void *data; }; @@ -138,7 +137,8 @@ void event_loop_poll() { void init_event_loop() { event_loop.fds.length = 0; event_loop.fds.capacity = 10; - event_loop.fds.items = malloc(event_loop.fds.capacity * sizeof(struct pollfd)); + event_loop.fds.items = malloc( + event_loop.fds.capacity * sizeof(struct pollfd)); event_loop.items = create_list(); event_loop.timers = create_list(); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c deleted file mode 100644 index 93d1219c..00000000 --- a/swaybar/ipc.c +++ /dev/null @@ -1,410 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include "swaybar/config.h" -#include "swaybar/ipc.h" -#include "ipc-client.h" -#include "list.h" -#include "log.h" - -void ipc_send_workspace_command(const char *workspace_name) { - uint32_t size = strlen("workspace \"\"") + strlen(workspace_name) + 1; - - char command[size]; - sprintf(command, "workspace \"%s\"", workspace_name); - - ipc_single_command(swaybar.ipc_socketfd, IPC_COMMAND, command, &size); -} - -static void ipc_parse_config(struct config *config, const char *payload) { - json_object *bar_config = json_tokener_parse(payload); - json_object *markup, *mode, *hidden_bar, *position, *status_command; - json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; - json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; -#ifdef ENABLE_TRAY - json_object *tray_output, *icon_theme, *tray_padding, *activate_button, *context_button; - json_object *secondary_button; - json_object_object_get_ex(bar_config, "tray_output", &tray_output); - json_object_object_get_ex(bar_config, "icon_theme", &icon_theme); - json_object_object_get_ex(bar_config, "tray_padding", &tray_padding); - json_object_object_get_ex(bar_config, "activate_button", &activate_button); - json_object_object_get_ex(bar_config, "context_button", &context_button); - json_object_object_get_ex(bar_config, "secondary_button", &secondary_button); -#endif - json_object_object_get_ex(bar_config, "mode", &mode); - json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); - json_object_object_get_ex(bar_config, "position", &position); - json_object_object_get_ex(bar_config, "status_command", &status_command); - json_object_object_get_ex(bar_config, "font", &font); - json_object_object_get_ex(bar_config, "bar_height", &bar_height); - json_object_object_get_ex(bar_config, "wrap_scroll", &wrap_scroll); - json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons); - json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers); - json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator); - json_object_object_get_ex(bar_config, "verbose", &verbose); - json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); - json_object_object_get_ex(bar_config, "colors", &colors); - json_object_object_get_ex(bar_config, "outputs", &outputs); - json_object_object_get_ex(bar_config, "pango_markup", &markup); - - if (status_command) { - free(config->status_command); - config->status_command = strdup(json_object_get_string(status_command)); - } - - if (position) { - config->position = parse_position(json_object_get_string(position)); - } - - if (font) { - free(config->font); - config->font = parse_font(json_object_get_string(font)); - } - - if (sep_symbol) { - free(config->sep_symbol); - config->sep_symbol = strdup(json_object_get_string(sep_symbol)); - } - - if (strip_workspace_numbers) { - config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers); - } - - if (binding_mode_indicator) { - config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); - } - - if (wrap_scroll) { - config->wrap_scroll = json_object_get_boolean(wrap_scroll); - } - - if (workspace_buttons) { - config->workspace_buttons = json_object_get_boolean(workspace_buttons); - } - - if (bar_height) { - config->height = json_object_get_int(bar_height); - } - - if (markup) { - config->pango_markup = json_object_get_boolean(markup); - } - -#ifdef ENABLE_TRAY - if (tray_output) { - free(config->tray_output); - config->tray_output = strdup(json_object_get_string(tray_output)); - } - - if (icon_theme) { - free(config->icon_theme); - config->icon_theme = strdup(json_object_get_string(icon_theme)); - } - - if (tray_padding) { - config->tray_padding = json_object_get_int(tray_padding); - } - - if (activate_button) { - config->activate_button = json_object_get_int(activate_button); - } - - if (context_button) { - config->context_button = json_object_get_int(context_button); - } - - if (secondary_button) { - config->secondary_button = json_object_get_int(secondary_button); - } -#endif - - // free previous outputs list - int i; - for (i = 0; i < config->outputs->length; ++i) { - free(config->outputs->items[i]); - } - list_free(config->outputs); - config->outputs = create_list(); - - if (outputs) { - int length = json_object_array_length(outputs); - json_object *output; - const char *output_str; - for (i = 0; i < length; ++i) { - output = json_object_array_get_idx(outputs, i); - output_str = json_object_get_string(output); - if (strcmp("*", output_str) == 0) { - config->all_outputs = true; - break; - } - list_add(config->outputs, strdup(output_str)); - } - } else { - config->all_outputs = true; - } - - if (colors) { - json_object *background, *statusline, *separator; - json_object *focused_background, *focused_statusline, *focused_separator; - json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; - json_object *inactive_workspace_border, *inactive_workspace_bg, *inactive_workspace_text; - json_object *active_workspace_border, *active_workspace_bg, *active_workspace_text; - json_object *urgent_workspace_border, *urgent_workspace_bg, *urgent_workspace_text; - json_object *binding_mode_border, *binding_mode_bg, *binding_mode_text; - json_object_object_get_ex(colors, "background", &background); - json_object_object_get_ex(colors, "statusline", &statusline); - json_object_object_get_ex(colors, "separator", &separator); - json_object_object_get_ex(colors, "focused_background", &focused_background); - json_object_object_get_ex(colors, "focused_statusline", &focused_statusline); - json_object_object_get_ex(colors, "focused_separator", &focused_separator); - json_object_object_get_ex(colors, "focused_workspace_border", &focused_workspace_border); - json_object_object_get_ex(colors, "focused_workspace_bg", &focused_workspace_bg); - json_object_object_get_ex(colors, "focused_workspace_text", &focused_workspace_text); - json_object_object_get_ex(colors, "active_workspace_border", &active_workspace_border); - json_object_object_get_ex(colors, "active_workspace_bg", &active_workspace_bg); - json_object_object_get_ex(colors, "active_workspace_text", &active_workspace_text); - json_object_object_get_ex(colors, "inactive_workspace_border", &inactive_workspace_border); - json_object_object_get_ex(colors, "inactive_workspace_bg", &inactive_workspace_bg); - json_object_object_get_ex(colors, "inactive_workspace_text", &inactive_workspace_text); - json_object_object_get_ex(colors, "urgent_workspace_border", &urgent_workspace_border); - json_object_object_get_ex(colors, "urgent_workspace_bg", &urgent_workspace_bg); - json_object_object_get_ex(colors, "urgent_workspace_text", &urgent_workspace_text); - json_object_object_get_ex(colors, "binding_mode_border", &binding_mode_border); - json_object_object_get_ex(colors, "binding_mode_bg", &binding_mode_bg); - json_object_object_get_ex(colors, "binding_mode_text", &binding_mode_text); - if (background) { - config->colors.background = parse_color(json_object_get_string(background)); - } - - if (statusline) { - config->colors.statusline = parse_color(json_object_get_string(statusline)); - } - - if (separator) { - config->colors.separator = parse_color(json_object_get_string(separator)); - } - - if (focused_background) { - config->colors.focused_background = parse_color(json_object_get_string(focused_background)); - } - - if (focused_statusline) { - config->colors.focused_statusline = parse_color(json_object_get_string(focused_statusline)); - } - - if (focused_separator) { - config->colors.focused_separator = parse_color(json_object_get_string(focused_separator)); - } - - if (focused_workspace_border) { - config->colors.focused_workspace.border = parse_color(json_object_get_string(focused_workspace_border)); - } - - if (focused_workspace_bg) { - config->colors.focused_workspace.background = parse_color(json_object_get_string(focused_workspace_bg)); - } - - if (focused_workspace_text) { - config->colors.focused_workspace.text = parse_color(json_object_get_string(focused_workspace_text)); - } - - if (active_workspace_border) { - config->colors.active_workspace.border = parse_color(json_object_get_string(active_workspace_border)); - } - - if (active_workspace_bg) { - config->colors.active_workspace.background = parse_color(json_object_get_string(active_workspace_bg)); - } - - if (active_workspace_text) { - config->colors.active_workspace.text = parse_color(json_object_get_string(active_workspace_text)); - } - - if (inactive_workspace_border) { - config->colors.inactive_workspace.border = parse_color(json_object_get_string(inactive_workspace_border)); - } - - if (inactive_workspace_bg) { - config->colors.inactive_workspace.background = parse_color(json_object_get_string(inactive_workspace_bg)); - } - - if (inactive_workspace_text) { - config->colors.inactive_workspace.text = parse_color(json_object_get_string(inactive_workspace_text)); - } - - if (binding_mode_border) { - config->colors.binding_mode.border = parse_color(json_object_get_string(binding_mode_border)); - } - - if (binding_mode_bg) { - config->colors.binding_mode.background = parse_color(json_object_get_string(binding_mode_bg)); - } - - if (binding_mode_text) { - config->colors.binding_mode.text = parse_color(json_object_get_string(binding_mode_text)); - } - } - - json_object_put(bar_config); -} - -static void ipc_update_workspaces(struct bar *bar) { - int i; - for (i = 0; i < bar->outputs->length; ++i) { - struct output *output = bar->outputs->items[i]; - if (output->workspaces) { - free_workspaces(output->workspaces); - } - output->workspaces = create_list(); - } - - uint32_t len = 0; - char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); - json_object *results = json_tokener_parse(res); - if (!results) { - free(res); - return; - } - - int length = json_object_array_length(results); - json_object *ws_json; - json_object *num, *name, *visible, *focused, *out, *urgent; - for (i = 0; i < length; ++i) { - ws_json = json_object_array_get_idx(results, i); - - json_object_object_get_ex(ws_json, "num", &num); - json_object_object_get_ex(ws_json, "name", &name); - json_object_object_get_ex(ws_json, "visible", &visible); - json_object_object_get_ex(ws_json, "focused", &focused); - json_object_object_get_ex(ws_json, "output", &out); - json_object_object_get_ex(ws_json, "urgent", &urgent); - - int j; - for (j = 0; j < bar->outputs->length; ++j) { - struct output *output = bar->outputs->items[j]; - if (strcmp(json_object_get_string(out), output->name) == 0) { - struct workspace *ws = malloc(sizeof(struct workspace)); - ws->num = json_object_get_int(num); - ws->name = strdup(json_object_get_string(name)); - ws->visible = json_object_get_boolean(visible); - ws->focused = json_object_get_boolean(focused); - if (ws->focused) { - if (bar->focused_output) { - bar->focused_output->focused = false; - } - bar->focused_output = output; - output->focused = true; - } - ws->urgent = json_object_get_boolean(urgent); - list_add(output->workspaces, ws); - } - } - } - - json_object_put(results); - free(res); -} - -void ipc_bar_init(struct bar *bar, const char *bar_id) { - // Get bar config - uint32_t len = strlen(bar_id); - char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); - - ipc_parse_config(bar->config, res); - free(res); - - // Get outputs - len = 0; - res = ipc_single_command(bar->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len); - json_object *outputs = json_tokener_parse(res); - int i; - int length = json_object_array_length(outputs); - json_object *output, *output_name, *output_active; - const char *name; - bool active; - for (i = 0; i < length; ++i) { - output = json_object_array_get_idx(outputs, i); - json_object_object_get_ex(output, "name", &output_name); - json_object_object_get_ex(output, "active", &output_active); - name = json_object_get_string(output_name); - active = json_object_get_boolean(output_active); - if (!active) { - continue; - } - - bool use_output = false; - if (bar->config->all_outputs) { - use_output = true; - } else { - int j = 0; - for (j = 0; j < bar->config->outputs->length; ++j) { - const char *conf_name = bar->config->outputs->items[j]; - if (strcasecmp(name, conf_name) == 0) { - use_output = true; - break; - } - } - } - - if (!use_output) { - continue; - } - - // add bar to the output - struct output *bar_output = new_output(name); - bar_output->idx = i; - list_add(bar->outputs, bar_output); - } - free(res); - json_object_put(outputs); - - const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; - len = strlen(subscribe_json); - res = ipc_single_command(bar->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); - free(res); - - ipc_update_workspaces(bar); -} - -bool handle_ipc_event(struct bar *bar) { - struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); - if (!resp) { - return false; - } - switch (resp->type) { - case IPC_EVENT_WORKSPACE: - ipc_update_workspaces(bar); - break; - case IPC_EVENT_MODE: { - json_object *result = json_tokener_parse(resp->payload); - if (!result) { - free_ipc_response(resp); - sway_log(L_ERROR, "failed to parse payload as json"); - return false; - } - json_object *json_change; - if (json_object_object_get_ex(result, "change", &json_change)) { - const char *change = json_object_get_string(json_change); - - free(bar->config->mode); - if (strcmp(change, "default") == 0) { - bar->config->mode = NULL; - } else { - bar->config->mode = strdup(change); - } - } else { - sway_log(L_ERROR, "failed to parse response"); - } - - json_object_put(result); - break; - } - default: - free_ipc_response(resp); - return false; - } - - free_ipc_response(resp); - return true; -} diff --git a/swaybar/main.c b/swaybar/main.c index 0abd0755..c897e1c9 100644 --- a/swaybar/main.c +++ b/swaybar/main.c @@ -4,21 +4,20 @@ #include #include #include +#include #include "swaybar/bar.h" #include "ipc-client.h" -#include "log.h" -/* global bar state */ -struct bar swaybar; +static struct swaybar swaybar; -void sway_terminate(int exit_code) { +void sig_handler(int signal) { bar_teardown(&swaybar); - exit(exit_code); + exit(0); } -void sig_handler(int signal) { +void sway_terminate(int code) { bar_teardown(&swaybar); - exit(0); + exit(code); } int main(int argc, char **argv) { @@ -75,20 +74,23 @@ int main(int argc, char **argv) { } } - if (!bar_id) { - sway_abort("No bar_id passed. Provide --bar_id or let sway start swaybar"); - } - if (debug) { - init_log(L_DEBUG); + wlr_log_init(L_DEBUG, NULL); } else { - init_log(L_ERROR); + wlr_log_init(L_ERROR, NULL); + } + + if (!bar_id) { + wlr_log(L_ERROR, "No bar_id passed. " + "Provide --bar_id or let sway start swaybar"); + return 1; } if (!socket_path) { socket_path = get_socketpath(); if (!socket_path) { - sway_abort("Unable to retrieve socket path"); + wlr_log(L_ERROR, "Unable to retrieve socket path"); + return 1; } } @@ -100,9 +102,6 @@ int main(int argc, char **argv) { free(bar_id); bar_run(&swaybar); - - // gracefully shutdown swaybar and status_command bar_teardown(&swaybar); - return 0; } diff --git a/swaybar/meson.build b/swaybar/meson.build new file mode 100644 index 00000000..fd87e51d --- /dev/null +++ b/swaybar/meson.build @@ -0,0 +1,25 @@ +executable( + 'swaybar', + [ + 'bar.c', + 'config.c', + 'event_loop.c', + 'main.c', + 'render.c', + ], + include_directories: [sway_inc], + dependencies: [ + cairo, + client_protos, + gdk_pixbuf, + jsonc, + math, + pango, + pangocairo, + rt, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true +) diff --git a/swaybar/render.c b/swaybar/render.c index 6fc09078..2eaa0195 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,367 +1,63 @@ #include #include #include - -#include "client/cairo.h" -#include "client/pango.h" -#include "client/window.h" +#include +#include "cairo.h" +#include "pango.h" +#include "pool-buffer.h" +#include "swaybar/bar.h" #include "swaybar/config.h" -#include "swaybar/status_line.h" #include "swaybar/render.h" -#ifdef ENABLE_TRAY -#include "swaybar/tray/tray.h" -#include "swaybar/tray/sni.h" -#endif -#include "log.h" - - -/* internal spacing */ -static int margin = 3; -static int ws_horizontal_padding = 5; -static double ws_vertical_padding = 1.5; -static int ws_spacing = 1; - -/** - * Renders a sharp line of any width and height. - * - * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0 - * if the line has a width/height of one pixel, respectively. - */ -static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) { - cairo_set_source_u32(cairo, color); - - if (width > 1 && height > 1) { - cairo_rectangle(cairo, x, y, width, height); - cairo_fill(cairo); - } else { - if (width == 1) { - x += 0.5; - height += y; - width = x; - } - - if (height == 1) { - y += 0.5; - width += x; - height = y; - } - - cairo_move_to(cairo, x, y); - cairo_set_line_width(cairo, 1.0); - cairo_line_to(cairo, width, height); - cairo_stroke(cairo); - } -} - -static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge, bool is_focused) { - int width, height, sep_width; - get_text_size(window->cairo, window->font, &width, &height, - window->scale, block->markup, "%s", block->full_text); - - int textwidth = width; - double block_width = width; - - if (width < block->min_width) { - width = block->min_width; - } - - *x -= width; - - if (block->border != 0 && block->border_left > 0) { - *x -= (block->border_left + margin); - block_width += block->border_left + margin; - } - - if (block->border != 0 && block->border_right > 0) { - *x -= (block->border_right + margin); - block_width += block->border_right + margin; - } - - // Add separator - if (!edge) { - if (config->sep_symbol) { - get_text_size(window->cairo, window->font, &sep_width, &height, - window->scale, false, "%s", config->sep_symbol); - if (sep_width > block->separator_block_width) { - block->separator_block_width = sep_width + margin * 2; - } - } - - *x -= block->separator_block_width; - } else { - *x -= margin; - } - - double pos = *x; - - block->x = (int)pos; - block->width = (int)block_width; - - // render background - if (block->background != 0x0) { - cairo_set_source_u32(window->cairo, block->background); - cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, (window->height * window->scale) - 2); - cairo_fill(window->cairo); - } - - // render top border - if (block->border != 0 && block->border_top > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block_width, - block->border_top); - } - - // render bottom border - if (block->border != 0 && block->border_bottom > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - (window->height * window->scale) - 1 - block->border_bottom, - block_width, - block->border_bottom); - } - - // render left border - if (block->border != 0 && block->border_left > 0) { - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block->border_left, - (window->height * window->scale) - 2); - - pos += block->border_left + margin; - } - - // render text - double offset = 0; - - if (strncmp(block->align, "left", 5) == 0) { - offset = pos; - } else if (strncmp(block->align, "right", 5) == 0) { - offset = pos + width - textwidth; - } else if (strncmp(block->align, "center", 6) == 0) { - offset = pos + (width - textwidth) / 2; - } - - cairo_move_to(window->cairo, offset, margin); - cairo_set_source_u32(window->cairo, block->color); - pango_printf(window->cairo, window->font, window->scale, - block->markup, "%s", block->full_text); - - pos += width; +#include "wlr-layer-shell-unstable-v1-client-protocol.h" - // render right border - if (block->border != 0 && block->border_right > 0) { - pos += margin; - - render_sharp_line(window->cairo, block->border, - pos - 0.5, - 1, - block->border_right, - (window->height * window->scale) - 2); - - pos += block->border_right; - } - - // render separator - if (!edge && block->separator) { - if (is_focused) { - cairo_set_source_u32(window->cairo, config->colors.focused_separator); - } else { - cairo_set_source_u32(window->cairo, config->colors.separator); - } - if (config->sep_symbol) { - offset = pos + (block->separator_block_width - sep_width) / 2; - cairo_move_to(window->cairo, offset, margin); - pango_printf(window->cairo, window->font, window->scale, - false, "%s", config->sep_symbol); - } else { - cairo_set_line_width(window->cairo, 1); - cairo_move_to(window->cairo, pos + block->separator_block_width/2, - margin); - cairo_line_to(window->cairo, pos + block->separator_block_width/2, - (window->height * window->scale) - margin); - cairo_stroke(window->cairo); - } - } +static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, + struct swaybar_output *output) { + struct swaybar_config *config = bar->config; -} - -static const char *strip_workspace_name(bool strip_num, const char *ws_name) { - bool strip = false; - int i; - - if (strip_num) { - int len = strlen(ws_name); - for (i = 0; i < len; ++i) { - if (!('0' <= ws_name[i] && ws_name[i] <= '9')) { - if (':' == ws_name[i] && i < len-1 && i > 0) { - strip = true; - ++i; - } - break; - } - } - } - - if (strip) { - return ws_name + i; - } - - return ws_name; -} - -void workspace_button_size(struct window *window, const char *workspace_name, int *width, int *height) { - const char *stripped_name = strip_workspace_name(swaybar.config->strip_workspace_numbers, workspace_name); - - get_text_size(window->cairo, window->font, width, height, - window->scale, true, "%s", stripped_name); - *width += 2 * ws_horizontal_padding; - *height += 2 * ws_vertical_padding; -} - -static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) { - const char *stripped_name = strip_workspace_name(config->strip_workspace_numbers, ws->name); - - struct box_colors box_colors; - if (ws->urgent) { - box_colors = config->colors.urgent_workspace; - } else if (ws->focused) { - box_colors = config->colors.focused_workspace; - } else if (ws->visible) { - box_colors = config->colors.active_workspace; - } else { - box_colors = config->colors.inactive_workspace; - } - - int width, height; - workspace_button_size(window, stripped_name, &width, &height); - - // background - cairo_set_source_u32(window->cairo, box_colors.background); - cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); - cairo_fill(window->cairo); - - // border - cairo_set_source_u32(window->cairo, box_colors.border); - cairo_rectangle(window->cairo, *x, 1.5, width - 1, height); - cairo_stroke(window->cairo); - - // text - cairo_set_source_u32(window->cairo, box_colors.text); - cairo_move_to(window->cairo, (int)*x + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, window->scale, - true, "%s", stripped_name); - - *x += width + ws_spacing; -} - -static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) { - int width, height; - get_text_size(window->cairo, window->font, &width, &height, - window->scale, false, "%s", config->mode); - - // background - cairo_set_source_u32(window->cairo, config->colors.binding_mode.background); - cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_fill(window->cairo); - - // border - cairo_set_source_u32(window->cairo, config->colors.binding_mode.border); - cairo_rectangle(window->cairo, pos, 1.5, width + ws_horizontal_padding * 2 - 1, - height + ws_vertical_padding * 2); - cairo_stroke(window->cairo); - - // text - cairo_set_source_u32(window->cairo, config->colors.binding_mode.text); - cairo_move_to(window->cairo, (int)pos + ws_horizontal_padding, margin); - pango_printf(window->cairo, window->font, window->scale, - false, "%s", config->mode); -} - -void render(struct output *output, struct config *config, struct status_line *line) { - int i; - - struct window *window = output->window; - cairo_t *cairo = window->cairo; - bool is_focused = output->focused; - - // Clear cairo_save(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); cairo_paint(cairo); cairo_restore(cairo); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); - - // Background - if (is_focused) { + if (output->focused) { cairo_set_source_u32(cairo, config->colors.focused_background); } else { cairo_set_source_u32(cairo, config->colors.background); } cairo_paint(cairo); -#ifdef ENABLE_TRAY - uint32_t tray_width = tray_render(output, config); -#else - const uint32_t tray_width = window->width * window->scale; -#endif - - // Command output - if (is_focused) { - cairo_set_source_u32(cairo, config->colors.focused_statusline); + // TODO: use actual height + return 20; +} + +void render_frame(struct swaybar *bar, + struct swaybar_output *output) { + cairo_surface_t *recorder = cairo_recording_surface_create( + CAIRO_CONTENT_COLOR_ALPHA, NULL); + cairo_t *cairo = cairo_create(recorder); + uint32_t height = render_to_cairo(cairo, bar, output); + if (height != output->height) { + // Reconfigure surface + zwlr_layer_surface_v1_set_size( + output->layer_surface, 0, height); + // TODO: this could infinite loop if the compositor assigns us a + // different height than what we asked for + wl_surface_commit(output->surface); + wl_display_roundtrip(bar->display); } else { - cairo_set_source_u32(cairo, config->colors.statusline); - } - - int width, height; - - if (line->protocol == TEXT) { - get_text_size(window->cairo, window->font, &width, &height, - window->scale, config->pango_markup, "%s", line->text_line); - cairo_move_to(cairo, tray_width - margin - width, margin); - pango_printf(window->cairo, window->font, window->scale, - config->pango_markup, "%s", line->text_line); - } else if (line->protocol == I3BAR && line->block_line) { - double pos = tray_width - 0.5; - bool edge = true; - for (i = line->block_line->length - 1; i >= 0; --i) { - struct status_block *block = line->block_line->items[i]; - if (block->full_text && block->full_text[0]) { - render_block(window, config, block, &pos, edge, is_focused); - edge = false; - } - } - } - - cairo_set_line_width(cairo, 1.0); - double x = 0.5; - - // Workspaces - if (config->workspace_buttons) { - for (i = 0; i < output->workspaces->length; ++i) { - struct workspace *ws = output->workspaces->items[i]; - render_workspace_button(window, config, ws, &x); - } - } - - // binding mode indicator - if (config->mode && config->binding_mode_indicator) { - render_binding_mode_indicator(window, config, x); - } -} - -void set_window_height(struct window *window, int height) { - int text_width, text_height; - get_text_size(window->cairo, window->font, - &text_width, &text_height, window->scale, false, - "Test string for measuring purposes"); - if (height > 0) { - margin = (height - text_height) / 2; - ws_vertical_padding = margin - 1.5; - } - window->height = (text_height + margin * 2) / window->scale; + // Replay recording into shm and send it off + output->current_buffer = get_next_buffer(bar->shm, + output->buffers, output->width, output->height); + cairo_t *shm = output->current_buffer->cairo; + cairo_set_source_surface(shm, recorder, 0.0, 0.0); + cairo_paint(shm); + wl_surface_attach(output->surface, + output->current_buffer->buffer, 0, 0); + wl_surface_damage(output->surface, 0, 0, output->width, output->height); + wl_surface_commit(output->surface); + wl_display_roundtrip(bar->display); + } + cairo_surface_destroy(recorder); + cairo_destroy(cairo); } diff --git a/swaybar/status_line.c b/swaybar/status_line.c deleted file mode 100644 index 87e90caf..00000000 --- a/swaybar/status_line.c +++ /dev/null @@ -1,530 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include - -#include "swaybar/config.h" -#include "swaybar/status_line.h" -#include "log.h" -#include "util.h" - -#define I3JSON_MAXDEPTH 4 -#define I3JSON_UNKNOWN 0 -#define I3JSON_ARRAY 1 -#define I3JSON_STRING 2 - -struct { - int bufsize; - char *buffer; - char *line_start; - char *parserpos; - bool escape; - int depth; - int bar[I3JSON_MAXDEPTH+1]; -} i3json_state = { 0, NULL, NULL, NULL, false, 0, { I3JSON_UNKNOWN } }; - -static char line[1024]; -static char line_rest[1024]; - -static char event_buff[1024]; - -static void free_status_block(void *item) { - if (!item) { - return; - } - struct status_block *sb = (struct status_block*)item; - if (sb->full_text) { - free(sb->full_text); - } - if (sb->short_text) { - free(sb->short_text); - } - if (sb->align) { - free(sb->align); - } - if (sb->name) { - free(sb->name); - } - if (sb->instance) { - free(sb->instance); - } - free(sb); -} - -static void parse_json(struct bar *bar, const char *text) { - json_object *results = json_tokener_parse(text); - if (!results) { - sway_log(L_DEBUG, "Failed to parse json"); - return; - } - - if (json_object_array_length(results) < 1) { - return; - } - - if (bar->status->block_line) { - list_foreach(bar->status->block_line, free_status_block); - list_free(bar->status->block_line); - } - - bar->status->block_line = create_list(); - - int i; - for (i = 0; i < json_object_array_length(results); ++i) { - json_object *full_text, *short_text, *color, *min_width, *align, *urgent; - json_object *name, *instance, *separator, *separator_block_width; - json_object *background, *border, *border_top, *border_bottom; - json_object *border_left, *border_right, *markup; - - json_object *json = json_object_array_get_idx(results, i); - if (!json) { - continue; - } - - json_object_object_get_ex(json, "full_text", &full_text); - json_object_object_get_ex(json, "short_text", &short_text); - json_object_object_get_ex(json, "color", &color); - json_object_object_get_ex(json, "min_width", &min_width); - json_object_object_get_ex(json, "align", &align); - json_object_object_get_ex(json, "urgent", &urgent); - json_object_object_get_ex(json, "name", &name); - json_object_object_get_ex(json, "instance", &instance); - json_object_object_get_ex(json, "markup", &markup); - json_object_object_get_ex(json, "separator", &separator); - json_object_object_get_ex(json, "separator_block_width", &separator_block_width); - json_object_object_get_ex(json, "background", &background); - json_object_object_get_ex(json, "border", &border); - json_object_object_get_ex(json, "border_top", &border_top); - json_object_object_get_ex(json, "border_bottom", &border_bottom); - json_object_object_get_ex(json, "border_left", &border_left); - json_object_object_get_ex(json, "border_right", &border_right); - - struct status_block *new = calloc(1, sizeof(struct status_block)); - - if (full_text) { - new->full_text = strdup(json_object_get_string(full_text)); - } - - if (short_text) { - new->short_text = strdup(json_object_get_string(short_text)); - } - - if (color) { - new->color = parse_color(json_object_get_string(color)); - } else { - new->color = bar->config->colors.statusline; - } - - if (min_width) { - json_type type = json_object_get_type(min_width); - if (type == json_type_int) { - new->min_width = json_object_get_int(min_width); - } else if (type == json_type_string) { - /* the width will be calculated when rendering */ - new->min_width = 0; - } - } - - if (align) { - new->align = strdup(json_object_get_string(align)); - } else { - new->align = strdup("left"); - } - - if (urgent) { - new->urgent = json_object_get_int(urgent); - } - - if (name) { - new->name = strdup(json_object_get_string(name)); - } - - if (instance) { - new->instance = strdup(json_object_get_string(instance)); - } - - if (markup) { - new->markup = false; - const char *markup_str = json_object_get_string(markup); - if (strcmp(markup_str, "pango") == 0) { - new->markup = true; - } - } - - if (separator) { - new->separator = json_object_get_int(separator); - } else { - new->separator = true; // i3bar spec - } - - if (separator_block_width) { - new->separator_block_width = json_object_get_int(separator_block_width); - } else { - new->separator_block_width = 9; // i3bar spec - } - - // Airblader features - if (background) { - new->background = parse_color(json_object_get_string(background)); - } else { - new->background = 0x0; // transparent - } - - if (border) { - new->border = parse_color(json_object_get_string(border)); - } else { - new->border = 0x0; // transparent - } - - if (border_top) { - new->border_top = json_object_get_int(border_top); - } else { - new->border_top = 1; - } - - if (border_bottom) { - new->border_bottom = json_object_get_int(border_bottom); - } else { - new->border_bottom = 1; - } - - if (border_left) { - new->border_left = json_object_get_int(border_left); - } else { - new->border_left = 1; - } - - if (border_right) { - new->border_right = json_object_get_int(border_right); - } else { - new->border_right = 1; - } - - list_add(bar->status->block_line, new); - } - - json_object_put(results); -} - -// continue parsing from last parserpos -static int i3json_parse(struct bar *bar) { - char *c = i3json_state.parserpos; - int handled = 0; - while (*c) { - if (i3json_state.bar[i3json_state.depth] == I3JSON_STRING) { - if (!i3json_state.escape && *c == '"') { - --i3json_state.depth; - } - i3json_state.escape = !i3json_state.escape && *c == '\\'; - } else { - switch (*c) { - case '[': - ++i3json_state.depth; - if (i3json_state.depth > I3JSON_MAXDEPTH) { - sway_abort("JSON too deep"); - } - i3json_state.bar[i3json_state.depth] = I3JSON_ARRAY; - if (i3json_state.depth == 2) { - i3json_state.line_start = c; - } - break; - case ']': - if (i3json_state.bar[i3json_state.depth] != I3JSON_ARRAY) { - sway_abort("JSON malformed"); - } - --i3json_state.depth; - if (i3json_state.depth == 1) { - // c[1] is valid since c[0] != '\0' - char p = c[1]; - c[1] = '\0'; - parse_json(bar, i3json_state.line_start); - c[1] = p; - ++handled; - i3json_state.line_start = c+1; - } - break; - case '"': - ++i3json_state.depth; - if (i3json_state.depth > I3JSON_MAXDEPTH) { - sway_abort("JSON too deep"); - } - i3json_state.bar[i3json_state.depth] = I3JSON_STRING; - break; - } - } - ++c; - } - i3json_state.parserpos = c; - return handled; -} - -// Read line from file descriptor, only show the line tail if it is too long. -// In non-blocking mode treat "no more data" as a linebreak. -// If data after a line break has been read, return it in rest. -// If rest is non-empty, then use that as the start of the next line. -static int read_line_tail(int fd, char *buf, int nbyte, char *rest) { - if (fd < 0 || !buf || !nbyte) { - return -1; - } - int l; - char *buffer = malloc(nbyte*2+1); - char *readpos = buffer; - char *lf; - // prepend old data to new line if necessary - if (rest) { - l = strlen(rest); - if (l > nbyte) { - strcpy(buffer, rest + l - nbyte); - readpos += nbyte; - } else if (l) { - strcpy(buffer, rest); - readpos += l; - } - } - // read until a linefeed is found or no more data is available - while ((l = read(fd, readpos, nbyte)) > 0) { - readpos[l] = '\0'; - lf = strchr(readpos, '\n'); - if (lf) { - // linefeed found, replace with \0 - *lf = '\0'; - // give data from the end of the line, try to fill the buffer - if (lf-buffer > nbyte) { - strcpy(buf, lf - nbyte + 1); - } else { - strcpy(buf, buffer); - } - // we may have read data from the next line, save it to rest - if (rest) { - rest[0] = '\0'; - strcpy(rest, lf + 1); - } - free(buffer); - return strlen(buf); - } else { - // no linefeed found, slide data back. - int overflow = readpos - buffer + l - nbyte; - if (overflow > 0) { - memmove(buffer, buffer + overflow , nbyte + 1); - } - } - } - if (l < 0) { - free(buffer); - return l; - } - readpos[l]='\0'; - if (rest) { - rest[0] = '\0'; - } - if (nbyte < readpos - buffer + l - 1) { - memcpy(buf, readpos - nbyte + l + 1, nbyte); - } else { - strncpy(buf, buffer, nbyte); - } - buf[nbyte-1] = '\0'; - free(buffer); - return strlen(buf); -} - -// make sure that enough buffer space is available starting from parserpos -static void i3json_ensure_free(int min_free) { - int _step = 10240; - int r = min_free % _step; - if (r) { - min_free += _step - r; - } - if (!i3json_state.buffer) { - i3json_state.buffer = malloc(min_free); - i3json_state.bufsize = min_free; - i3json_state.parserpos = i3json_state.buffer; - } else { - int len = 0; - int pos = 0; - if (i3json_state.line_start) { - len = strlen(i3json_state.line_start); - pos = i3json_state.parserpos - i3json_state.line_start; - if (i3json_state.line_start != i3json_state.buffer) { - memmove(i3json_state.buffer, i3json_state.line_start, len+1); - } - } else { - len = strlen(i3json_state.buffer); - } - if (i3json_state.bufsize < len+min_free) { - i3json_state.bufsize += min_free; - if (i3json_state.bufsize > 1024000) { - sway_abort("Status line json too long or malformed."); - } - i3json_state.buffer = realloc(i3json_state.buffer, i3json_state.bufsize); - if (!i3json_state.buffer) { - sway_abort("Could not allocate json buffer"); - } - } - if (i3json_state.line_start) { - i3json_state.line_start = i3json_state.buffer; - i3json_state.parserpos = i3json_state.buffer + pos; - } else { - i3json_state.parserpos = i3json_state.buffer; - } - } - if (!i3json_state.buffer) { - sway_abort("Could not allocate buffer."); - } -} - -// append data and parse it. -static int i3json_handle_data(struct bar *bar, char *data) { - int len = strlen(data); - i3json_ensure_free(len); - strcpy(i3json_state.parserpos, data); - return i3json_parse(bar); -} - -// read data from fd and parse it. -static int i3json_handle_fd(struct bar *bar) { - i3json_ensure_free(10240); - // get fresh data at the end of the buffer - int readlen = read(bar->status_read_fd, i3json_state.parserpos, 10239); - if (readlen < 0) { - return readlen; - } - i3json_state.parserpos[readlen] = '\0'; - return i3json_parse(bar); -} - -bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button) { - sway_log(L_DEBUG, "status_line_mouse_event."); - if (!bar->status->click_events) { - sway_log(L_DEBUG, "click_events are not enabled."); - return false; - } - - if (bar->status->protocol == I3BAR) { - sway_log(L_DEBUG, "Sending click event."); - - // find clicked block - struct status_block *clicked_block = NULL; - struct status_block *current_block = NULL; - int num_blocks = bar->status->block_line->length; - - if (num_blocks == 0) { - return false; - } else { - current_block = bar->status->block_line->items[0]; - if (x < current_block->x) { - return false; - } - } - - for (int i = 0; i < num_blocks; i++) { - current_block = bar->status->block_line->items[i]; - if (x < (current_block->x + current_block->width)) { - clicked_block = current_block; - break; - } - } - - if (!clicked_block || !clicked_block->name) { - return false; - } - - // event example {"name":"capture","instance":"label","button":1,"x":3431,"y":18} - - struct json_object *event_json = json_object_new_object(); - json_object_object_add(event_json, "name", json_object_new_string(clicked_block->name)); - if (clicked_block->instance) { - json_object_object_add(event_json, "instance", json_object_new_string(clicked_block->instance)); - } - json_object_object_add(event_json, "button", json_object_new_int(button)); - json_object_object_add(event_json, "x", json_object_new_int(x)); - json_object_object_add(event_json, "y", json_object_new_int(y)); - - int len = snprintf(event_buff, sizeof(event_buff), "%s\n", json_object_to_json_string(event_json)); - - json_object_put(event_json); - - if (len <= (int)sizeof(event_buff)) { // if not truncated - write(bar->status_write_fd, event_buff, len); - return true; - } - } - - return false; -} - -bool handle_status_line(struct bar *bar) { - bool dirty = false; - - switch (bar->status->protocol) { - case I3BAR: - sway_log(L_DEBUG, "Got i3bar protocol."); - if (i3json_handle_fd(bar) > 0) { - dirty = true; - } - break; - case TEXT: - sway_log(L_DEBUG, "Got text protocol."); - read_line_tail(bar->status_read_fd, line, sizeof(line), line_rest); - dirty = true; - bar->status->text_line = line; - break; - case UNDEF: - sway_log(L_DEBUG, "Detecting protocol..."); - if (read_line_tail(bar->status_read_fd, line, sizeof(line), line_rest) < 0) { - break; - } - dirty = true; - bar->status->text_line = line; - bar->status->protocol = TEXT; - if (line[0] == '{') { - // detect i3bar json protocol - json_object *proto = json_tokener_parse(line); - if (proto) { - - json_object *version; - if (json_object_object_get_ex(proto, "version", &version) - && json_object_get_int(version) == 1 - ) { - sway_log(L_DEBUG, "Switched to i3bar protocol."); - bar->status->protocol = I3BAR; - } - - json_object *click_events; - if (json_object_object_get_ex(proto, "click_events", &click_events) - && json_object_get_boolean(click_events)) { - - sway_log(L_DEBUG, "Enabling click events."); - bar->status->click_events = true; - - const char *events_array = "[\n"; - write(bar->status_write_fd, events_array, strlen(events_array)); - } - - i3json_handle_data(bar, line_rest); - - json_object_put(proto); - } - } - break; - } - - return dirty; -} - -struct status_line *init_status_line() { - struct status_line *line = malloc(sizeof(struct status_line)); - line->block_line = create_list(); - line->text_line = NULL; - line->protocol = UNDEF; - line->click_events = false; - - return line; -} - -void free_status_line(struct status_line *line) { - if (line->block_line) { - list_foreach(line->block_line, free_status_block); - list_free(line->block_line); - } -} diff --git a/swaybar/tray/dbus.c b/swaybar/tray/dbus.c deleted file mode 100644 index 8e719fd9..00000000 --- a/swaybar/tray/dbus.c +++ /dev/null @@ -1,197 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/dbus.h" -#include "swaybar/event_loop.h" -#include "log.h" - -DBusConnection *conn = NULL; - -static void dispatch_watch(int fd, short mask, void *data) { - sway_log(L_DEBUG, "Dispatching watch"); - DBusWatch *watch = data; - - if (!dbus_watch_get_enabled(watch)) { - return; - } - - uint32_t flags = 0; - - if (mask & POLLIN) { - flags |= DBUS_WATCH_READABLE; - } if (mask & POLLOUT) { - flags |= DBUS_WATCH_WRITABLE; - } if (mask & POLLHUP) { - flags |= DBUS_WATCH_HANGUP; - } if (mask & POLLERR) { - flags |= DBUS_WATCH_ERROR; - } - - dbus_watch_handle(watch, flags); -} - -static dbus_bool_t add_watch(DBusWatch *watch, void *_data) { - if (!dbus_watch_get_enabled(watch)) { - // Watch should not be polled - return TRUE; - } - - short mask = 0; - uint32_t flags = dbus_watch_get_flags(watch); - - if (flags & DBUS_WATCH_READABLE) { - mask |= POLLIN; - } if (flags & DBUS_WATCH_WRITABLE) { - mask |= POLLOUT; - } - - int fd = dbus_watch_get_unix_fd(watch); - - sway_log(L_DEBUG, "Adding DBus watch fd: %d", fd); - add_event(fd, mask, dispatch_watch, watch); - - return TRUE; -} - -static void remove_watch(DBusWatch *watch, void *_data) { - int fd = dbus_watch_get_unix_fd(watch); - - remove_event(fd); -} - -static void dispatch_timeout(timer_t timer, void *data) { - sway_log(L_DEBUG, "Dispatching DBus timeout"); - DBusTimeout *timeout = data; - - if (dbus_timeout_get_enabled(timeout)) { - dbus_timeout_handle(timeout); - } -} - -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *_data) { - if (!dbus_timeout_get_enabled(timeout)) { - return TRUE; - } - - timer_t *timer = malloc(sizeof(timer_t)); - if (!timer) { - sway_log(L_ERROR, "Cannot allocate memory"); - return FALSE; - } - struct sigevent ev = { - .sigev_notify = SIGEV_NONE, - }; - - if (timer_create(CLOCK_MONOTONIC, &ev, timer)) { - sway_log(L_ERROR, "Could not create DBus timer"); - return FALSE; - } - - int interval = dbus_timeout_get_interval(timeout); - int interval_sec = interval / 1000; - int interval_msec = (interval_sec * 1000) - interval; - - struct timespec period = { - (time_t) interval_sec, - ((long) interval_msec) * 1000 * 1000, - }; - struct itimerspec time = { - period, - period, - }; - - timer_settime(*timer, 0, &time, NULL); - - dbus_timeout_set_data(timeout, timer, NULL); - - sway_log(L_DEBUG, "Adding DBus timeout. Interval: %ds %dms", interval_sec, interval_msec); - add_timer(*timer, dispatch_timeout, timeout); - - return TRUE; -} -static void remove_timeout(DBusTimeout *timeout, void *_data) { - timer_t *timer = (timer_t *) dbus_timeout_get_data(timeout); - sway_log(L_DEBUG, "Removing DBus timeout."); - - if (timer) { - remove_timer(*timer); - timer_delete(*timer); - free(timer); - } -} - -static bool should_dispatch = true; - -static void dispatch_status(DBusConnection *connection, DBusDispatchStatus new_status, - void *_data) { - if (new_status == DBUS_DISPATCH_DATA_REMAINS) { - should_dispatch = true; - } -} - -/* Public functions below */ - -void dispatch_dbus() { - if (!should_dispatch || !conn) { - return; - } - - DBusDispatchStatus status; - - do { - status = dbus_connection_dispatch(conn); - } while (status == DBUS_DISPATCH_DATA_REMAINS); - - if (status != DBUS_DISPATCH_COMPLETE) { - sway_log(L_ERROR, "Cannot dispatch dbus events: %d", status); - } - - should_dispatch = false; -} - -int dbus_init() { - DBusError error; - dbus_error_init(&error); - - conn = dbus_bus_get(DBUS_BUS_SESSION, &error); - if (conn == NULL) { - sway_log(L_INFO, "Compiled with dbus support, but unable to connect to dbus"); - sway_log(L_INFO, "swaybar will be unable to display tray icons."); - return -1; - } - - dbus_connection_set_exit_on_disconnect(conn, FALSE); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "Cannot get bus connection: %s\n", error.message); - conn = NULL; - return -1; - } - - sway_log(L_INFO, "Unique name: %s\n", dbus_bus_get_unique_name(conn)); - - // Will be called if dispatch status changes - dbus_connection_set_dispatch_status_function(conn, dispatch_status, NULL, NULL); - - if (!dbus_connection_set_watch_functions(conn, add_watch, remove_watch, - NULL, NULL, NULL)) { - dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); - sway_log(L_ERROR, "Failed to activate DBUS watch functions"); - return -1; - } - - if (!dbus_connection_set_timeout_functions(conn, add_timeout, remove_timeout, - NULL, NULL, NULL)) { - dbus_connection_set_watch_functions(conn, NULL, NULL, NULL, NULL, NULL); - dbus_connection_set_timeout_functions(conn, NULL, NULL, NULL, NULL, NULL); - sway_log(L_ERROR, "Failed to activate DBUS timeout functions"); - return -1; - } - - return 0; -} diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c deleted file mode 100644 index c146bf32..00000000 --- a/swaybar/tray/icon.c +++ /dev/null @@ -1,400 +0,0 @@ -#define _XOPEN_SOURCE 700 -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/icon.h" -#include "swaybar/bar.h" -#include "swaybar/config.h" -#include "stringop.h" -#include "log.h" - -/** - * REVIEW: - * This file repeats lots of "costly" operations that are the same for every - * icon. It's possible to create a dictionary or some other structure to cache - * these, though it may complicate things somewhat. - * - * Also parsing (index.theme) is currently pretty messy, so that could be made - * much better as well. Over all, things work, but are not optimal. - */ - -/* Finds all themes that the given theme inherits */ -static list_t *find_inherits(const char *theme_dir) { - const char inherits[] = "Inherits"; - const char index_name[] = "index.theme"; - list_t *themes = create_list(); - FILE *index = NULL; - char *path = malloc(strlen(theme_dir) + sizeof(index_name)); - if (!path) { - goto fail; - } - if (!themes) { - goto fail; - } - - strcpy(path, theme_dir); - strcat(path, index_name); - - index = fopen(path, "r"); - if (!index) { - goto fail; - } - - char *buf = NULL; - size_t n = 0; - while (!feof(index) && getline(&buf, &n, index) != -1) { - if (n <= sizeof(inherits) + 1) { - continue; - } - if (strncmp(inherits, buf, sizeof(inherits) - 1) == 0) { - char *themestr = buf + sizeof(inherits); - themes = split_string(themestr, ","); - break; - } - } - free(buf); - -fail: - free(path); - if (index) { - fclose(index); - } - return themes; -} - -static bool isdir(const char *path) { - struct stat statbuf; - if (stat(path, &statbuf) != -1) { - if (S_ISDIR(statbuf.st_mode)) { - return true; - } - } - return false; - -} - -/** - * Returns the directory of a given theme if it exists. - * The returned pointer must be freed. - */ -static char *find_theme_dir(const char *theme) { - char *basedir; - char *icon_dir; - - if (!theme) { - return NULL; - } - - if (!(icon_dir = malloc(1024))) { - sway_log(L_ERROR, "Out of memory!"); - goto fail; - } - - if ((basedir = getenv("HOME"))) { - if (snprintf(icon_dir, 1024, "%s/.icons/%s", basedir, theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - // XXX perhaps just goto trying in /usr/share? This - // shouldn't happen anyway, but might with a long global - goto fail; - } - - if (isdir(icon_dir)) { - return icon_dir; - } - } - - if ((basedir = getenv("XDG_DATA_DIRS"))) { - if (snprintf(icon_dir, 1024, "%s/icons/%s", basedir, theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - // ditto - goto fail; - } - - if (isdir(icon_dir)) { - return icon_dir; - } - } - - // Spec says use "/usr/share/pixmaps/", but I see everything in - // "/usr/share/icons/" look it both, I suppose. - if (snprintf(icon_dir, 1024, "/usr/share/pixmaps/%s", theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - goto fail; - } - if (isdir(icon_dir)) { - return icon_dir; - } - - if (snprintf(icon_dir, 1024, "/usr/share/icons/%s", theme) >= 1024) { - sway_log(L_ERROR, "Path too long to render"); - goto fail; - } - if (isdir(icon_dir)) { - return icon_dir; - } - -fail: - free(icon_dir); - sway_log(L_ERROR, "Could not find dir for theme: %s", theme); - return NULL; -} - -/** - * Returns all theme dirs needed to be looked in for an icon. - * Does not check for duplicates - */ -static list_t *find_all_theme_dirs(const char *theme) { - list_t *dirs = create_list(); - if (!dirs) { - return NULL; - } - char *dir = find_theme_dir(theme); - if (dir) { - list_add(dirs, dir); - list_t *inherits = find_inherits(dir); - list_cat(dirs, inherits); - list_free(inherits); - } - dir = find_theme_dir("hicolor"); - if (dir) { - list_add(dirs, dir); - } - - return dirs; -} - -struct subdir { - int size; - char name[]; -}; - -static int subdir_str_cmp(const void *_subdir, const void *_str) { - const struct subdir *subdir = _subdir; - const char *str = _str; - return strcmp(subdir->name, str); -} -/** - * Helper to find_subdirs. Acts similar to `split_string(subdirs, ",")` but - * generates a list of struct subdirs - */ -static list_t *split_subdirs(char *subdir_str) { - list_t *subdir_list = create_list(); - char *copy = strdup(subdir_str); - if (!subdir_list || !copy) { - list_free(subdir_list); - free(copy); - return NULL; - } - - char *token; - token = strtok(copy, ","); - while(token) { - int len = strlen(token) + 1; - struct subdir *subdir = - malloc(sizeof(struct subdir) + sizeof(char [len])); - if (!subdir) { - // Return what we have - return subdir_list; - } - subdir->size = 0; - strcpy(subdir->name, token); - - list_add(subdir_list, subdir); - - token = strtok(NULL, ","); - } - free(copy); - - return subdir_list; -} -/** - * Returns a list of all subdirectories of a theme. - * Take note: the subdir names are all relative to `theme_dir` and must be - * combined with it to form a valid directory. - * - * Each member of the list is of type (struct subdir *) this struct contains - * the name of the subdir, along with size information. These must be freed - * bye the caller. - * - * This currently ignores min and max sizes of icons. - */ -static list_t* find_theme_subdirs(const char *theme_dir) { - const char index_name[] = "/index.theme"; - list_t *dirs = NULL; - char *path = malloc(strlen(theme_dir) + sizeof(index_name)); - FILE *index = NULL; - if (!path) { - sway_log(L_ERROR, "Failed to allocate memory"); - goto fail; - } - - strcpy(path, theme_dir); - strcat(path, index_name); - - index = fopen(path, "r"); - if (!index) { - sway_log(L_ERROR, "Could not open file: %s", path); - goto fail; - } - - char *buf = NULL; - size_t n = 0; - const char directories[] = "Directories"; - while (!feof(index) && getline(&buf, &n, index) != -1) { - if (n <= sizeof(directories) + 1) { - continue; - } - if (strncmp(directories, buf, sizeof(directories) - 1) == 0) { - char *dirstr = buf + sizeof(directories); - dirs = split_subdirs(dirstr); - break; - } - } - // Now, find the size of each dir - struct subdir *current_subdir = NULL; - const char size[] = "Size"; - while (!feof(index) && getline(&buf, &n, index) != -1) { - if (buf[0] == '[') { - int len = strlen(buf); - if (buf[len-1] == '\n') { - len--; - } - // replace ']' - buf[len-1] = '\0'; - - int index; - if ((index = list_seq_find(dirs, subdir_str_cmp, buf+1)) != -1) { - current_subdir = (dirs->items[index]); - } - } - - if (strncmp(size, buf, sizeof(size) - 1) == 0) { - if (current_subdir) { - current_subdir->size = atoi(buf + sizeof(size)); - } - } - } - free(buf); -fail: - free(path); - if (index) { - fclose(index); - } - return dirs; -} - -/* Returns the file of an icon given its name and size */ -static char *find_icon_file(const char *name, int size) { - int namelen = strlen(name); - list_t *dirs = find_all_theme_dirs(swaybar.config->icon_theme); - if (!dirs) { - return NULL; - } - int min_size_diff = INT_MAX; - char *current_file = NULL; - - for (int i = 0; i < dirs->length; ++i) { - char *dir = dirs->items[i]; - list_t *subdirs = find_theme_subdirs(dir); - - if (!subdirs) { - continue; - } - - for (int i = 0; i < subdirs->length; ++i) { - struct subdir *subdir = subdirs->items[i]; - - // Only use an unsized if we don't already have a - // canidate this should probably change to allow svgs - if (!subdir->size && current_file) { - continue; - } - - int size_diff = abs(size - subdir->size); - - if (size_diff >= min_size_diff) { - continue; - } - - char *path = malloc(strlen(subdir->name) + strlen(dir) + 2); - - strcpy(path, dir); - path[strlen(dir)] = '/'; - strcpy(path + strlen(dir) + 1, subdir->name); - - DIR *icons = opendir(path); - if (!icons) { - free(path); - continue; - } - - struct dirent *direntry; - while ((direntry = readdir(icons)) != NULL) { - int len = strlen(direntry->d_name); - if (len <= namelen + 2) { //must have some ext - continue; - } - if (strncmp(direntry->d_name, name, namelen) == 0) { - char *ext = direntry->d_name + namelen + 1; -#ifdef WITH_GDK_PIXBUF - if (strcmp(ext, "png") == 0 || - strcmp(ext, "xpm") == 0 || - strcmp(ext, "svg") == 0) { -#else - if (strcmp(ext, "png") == 0) { -#endif - free(current_file); - char *icon_path = malloc(strlen(path) + len + 2); - - strcpy(icon_path, path); - icon_path[strlen(path)] = '/'; - strcpy(icon_path + strlen(path) + 1, direntry->d_name); - current_file = icon_path; - min_size_diff = size_diff; - } - } - } - free(path); - closedir(icons); - } - free_flat_list(subdirs); - } - free_flat_list(dirs); - - return current_file; -} - -cairo_surface_t *find_icon(const char *name, int size) { - char *image_path = find_icon_file(name, size); - if (image_path == NULL) { - return NULL; - } - - cairo_surface_t *image = NULL; -#ifdef WITH_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); - if (!pixbuf) { - sway_log(L_ERROR, "Failed to load icon image: %s", err->message); - } - image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - // TODO make svg work? cairo supports it. maybe remove gdk alltogether - image = cairo_image_surface_create_from_png(image_path); -#endif //WITH_GDK_PIXBUF - if (!image) { - sway_log(L_ERROR, "Could not read icon image"); - return NULL; - } - - free(image_path); - return image; -} diff --git a/swaybar/tray/sni.c b/swaybar/tray/sni.c deleted file mode 100644 index c9d00657..00000000 --- a/swaybar/tray/sni.c +++ /dev/null @@ -1,481 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/dbus.h" -#include "swaybar/tray/sni.h" -#include "swaybar/tray/icon.h" -#include "swaybar/bar.h" -#include "client/cairo.h" -#include "log.h" - -// Not sure what this is but cairo needs it. -static const cairo_user_data_key_t cairo_user_data_key; - -struct sni_icon_ref *sni_icon_ref_create(struct StatusNotifierItem *item, - int height) { - struct sni_icon_ref *sni_ref = malloc(sizeof(struct sni_icon_ref)); - if (!sni_ref) { - return NULL; - } - sni_ref->icon = cairo_image_surface_scale(item->image, height, height); - sni_ref->ref = item; - - return sni_ref; -} - -void sni_icon_ref_free(struct sni_icon_ref *sni_ref) { - if (!sni_ref) { - return; - } - cairo_surface_destroy(sni_ref->icon); - free(sni_ref); -} - -/* Gets the pixmap of an icon */ -static void reply_icon(DBusPendingCall *pending, void *_data) { - struct StatusNotifierItem *item = _data; - - DBusMessage *reply = dbus_pending_call_steal_reply(pending); - - if (!reply) { - sway_log(L_ERROR, "Did not get reply"); - goto bail; - } - - int message_type = dbus_message_get_type(reply); - - if (message_type == DBUS_MESSAGE_TYPE_ERROR) { - char *msg; - - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &msg, - DBUS_TYPE_INVALID); - - sway_log(L_ERROR, "Message is error: %s", msg); - goto bail; - } - - DBusMessageIter iter; - DBusMessageIter variant; /* v[a(iiay)] */ - DBusMessageIter array; /* a(iiay) */ - DBusMessageIter d_struct; /* (iiay) */ - DBusMessageIter icon; /* ay */ - - dbus_message_iter_init(reply, &iter); - - // Each if here checks the types above before recursing - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"v\", is \"%s\"", - dbus_message_iter_get_signature(&iter)); - goto bail; - } - dbus_message_iter_recurse(&iter, &variant); - - if (strcmp("a(iiay)", dbus_message_iter_get_signature(&variant)) != 0) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"a(iiay)\", is \"%s\"", - dbus_message_iter_get_signature(&variant)); - goto bail; - } - - if (dbus_message_iter_get_element_count(&variant) == 0) { - // Can't recurse if there are no items - sway_log(L_INFO, "Item has no icon"); - goto bail; - } - dbus_message_iter_recurse(&variant, &array); - - dbus_message_iter_recurse(&array, &d_struct); - - int width; - dbus_message_iter_get_basic(&d_struct, &width); - dbus_message_iter_next(&d_struct); - - int height; - dbus_message_iter_get_basic(&d_struct, &height); - dbus_message_iter_next(&d_struct); - - int len = dbus_message_iter_get_element_count(&d_struct); - - if (!len) { - sway_log(L_ERROR, "No icon data"); - goto bail; - } - - // Also implies len % 4 == 0, useful below - if (len != width * height * 4) { - sway_log(L_ERROR, "Incorrect array size passed"); - goto bail; - } - - dbus_message_iter_recurse(&d_struct, &icon); - - int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); - // FIXME support a variable stride - // (works on my machine though for all tested widths) - if (!sway_assert(stride == width * 4, "Stride must be equal to byte length")) { - goto bail; - } - - // Data is by reference, no need to free - uint8_t *message_data; - dbus_message_iter_get_fixed_array(&icon, &message_data, &len); - - uint8_t *image_data = malloc(stride * height); - if (!image_data) { - sway_log(L_ERROR, "Could not allocate memory for icon"); - goto bail; - } - - // Transform from network byte order to host byte order - // Assumptions are safe because the equality above - uint32_t *network = (uint32_t *) message_data; - uint32_t *host = (uint32_t *)image_data; - for (int i = 0; i < width * height; ++i) { - host[i] = ntohl(network[i]); - } - - cairo_surface_t *image = cairo_image_surface_create_for_data( - image_data, CAIRO_FORMAT_ARGB32, - width, height, stride); - - if (image) { - if (item->image) { - cairo_surface_destroy(item->image); - } - item->image = image; - // Free the image data on surface destruction - cairo_surface_set_user_data(image, - &cairo_user_data_key, - image_data, - free); - item->dirty = true; - dirty = true; - - dbus_message_unref(reply); - dbus_pending_call_unref(pending); - return; - } else { - sway_log(L_ERROR, "Could not create image surface"); - free(image_data); - } - -bail: - if (reply) { - dbus_message_unref(reply); - } - dbus_pending_call_unref(pending); - sway_log(L_ERROR, "Could not get icon from item"); - return; -} -static void send_icon_msg(struct StatusNotifierItem *item) { - DBusPendingCall *pending; - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - "org.freedesktop.DBus.Properties", - "Get"); - const char *iface; - if (item->kde_special_snowflake) { - iface = "org.kde.StatusNotifierItem"; - } else { - iface = "org.freedesktop.StatusNotifierItem"; - } - const char *prop = "IconPixmap"; - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_STRING, &prop, - DBUS_TYPE_INVALID); - - bool status = - dbus_connection_send_with_reply(conn, message, &pending, -1); - - dbus_message_unref(message); - - if (!(pending || status)) { - sway_log(L_ERROR, "Could not get item icon"); - return; - } - - dbus_pending_call_set_notify(pending, reply_icon, item, NULL); -} - -/* Get an icon by its name */ -static void reply_icon_name(DBusPendingCall *pending, void *_data) { - struct StatusNotifierItem *item = _data; - - DBusMessage *reply = dbus_pending_call_steal_reply(pending); - - if (!reply) { - sway_log(L_INFO, "Got no icon name reply from item"); - goto bail; - } - - int message_type = dbus_message_get_type(reply); - - if (message_type == DBUS_MESSAGE_TYPE_ERROR) { - char *msg; - - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &msg, - DBUS_TYPE_INVALID); - - sway_log(L_INFO, "Could not get icon name: %s", msg); - goto bail; - } - - DBusMessageIter iter; /* v[s] */ - DBusMessageIter variant; /* s */ - - dbus_message_iter_init(reply, &iter); - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"v\", is \"%s\"", - dbus_message_iter_get_signature(&iter)); - goto bail; - } - dbus_message_iter_recurse(&iter, &variant); - - - if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_STRING) { - sway_log(L_ERROR, "Relpy type incorrect"); - sway_log(L_ERROR, "Should be \"s\", is \"%s\"", - dbus_message_iter_get_signature(&iter)); - goto bail; - } - - char *icon_name; - dbus_message_iter_get_basic(&variant, &icon_name); - - cairo_surface_t *image = find_icon(icon_name, 256); - - if (image) { - sway_log(L_DEBUG, "Icon for %s found with size %d", icon_name, - cairo_image_surface_get_width(image)); - if (item->image) { - cairo_surface_destroy(item->image); - } - item->image = image; - item->dirty = true; - dirty = true; - - dbus_message_unref(reply); - dbus_pending_call_unref(pending); - return; - } - -bail: - if (reply) { - dbus_message_unref(reply); - } - dbus_pending_call_unref(pending); - // Now try the pixmap - send_icon_msg(item); - return; -} -static void send_icon_name_msg(struct StatusNotifierItem *item) { - DBusPendingCall *pending; - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - "org.freedesktop.DBus.Properties", - "Get"); - const char *iface; - if (item->kde_special_snowflake) { - iface = "org.kde.StatusNotifierItem"; - } else { - iface = "org.freedesktop.StatusNotifierItem"; - } - const char *prop = "IconName"; - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_STRING, &prop, - DBUS_TYPE_INVALID); - - bool status = - dbus_connection_send_with_reply(conn, message, &pending, -1); - - dbus_message_unref(message); - - if (!(pending || status)) { - sway_log(L_ERROR, "Could not get item icon name"); - return; - } - - dbus_pending_call_set_notify(pending, reply_icon_name, item, NULL); -} - -void get_icon(struct StatusNotifierItem *item) { - send_icon_name_msg(item); -} - -void sni_activate(struct StatusNotifierItem *item, uint32_t x, uint32_t y) { - const char *iface = - (item->kde_special_snowflake ? "org.kde.StatusNotifierItem" - : "org.freedesktop.StatusNotifierItem"); - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - iface, - "Activate"); - - dbus_message_append_args(message, - DBUS_TYPE_INT32, &x, - DBUS_TYPE_INT32, &y, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} - -void sni_context_menu(struct StatusNotifierItem *item, uint32_t x, uint32_t y) { - const char *iface = - (item->kde_special_snowflake ? "org.kde.StatusNotifierItem" - : "org.freedesktop.StatusNotifierItem"); - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - iface, - "ContextMenu"); - - dbus_message_append_args(message, - DBUS_TYPE_INT32, &x, - DBUS_TYPE_INT32, &y, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} -void sni_secondary(struct StatusNotifierItem *item, uint32_t x, uint32_t y) { - const char *iface = - (item->kde_special_snowflake ? "org.kde.StatusNotifierItem" - : "org.freedesktop.StatusNotifierItem"); - DBusMessage *message = dbus_message_new_method_call( - item->name, - "/StatusNotifierItem", - iface, - "SecondaryActivate"); - - dbus_message_append_args(message, - DBUS_TYPE_INT32, &x, - DBUS_TYPE_INT32, &y, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} - -static void get_unique_name(struct StatusNotifierItem *item) { - // I think that we're fine being sync here becaues the message is - // directly to the message bus. Could be async though. - DBusMessage *message = dbus_message_new_method_call( - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "GetNameOwner"); - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &item->name, - DBUS_TYPE_INVALID); - - DBusMessage *reply = dbus_connection_send_with_reply_and_block( - conn, message, -1, NULL); - - dbus_message_unref(message); - - if (!reply) { - sway_log(L_ERROR, "Could not get unique name for item: %s", - item->name); - return; - } - - char *unique_name; - if (!dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &unique_name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing method args"); - } else { - if (item->unique_name) { - free(item->unique_name); - } - item->unique_name = strdup(unique_name); - } - - dbus_message_unref(reply); -} - -struct StatusNotifierItem *sni_create(const char *name) { - // Make sure `name` is well formed - if (!dbus_validate_bus_name(name, NULL)) { - sway_log(L_INFO, "Name (%s) is not a bus name. We cannot create an item.", name); - return NULL; - } - - struct StatusNotifierItem *item = malloc(sizeof(struct StatusNotifierItem)); - item->name = strdup(name); - item->unique_name = NULL; - item->image = NULL; - item->dirty = false; - - // If it doesn't use this name then assume that it uses the KDE spec - // This is because xembed-sni-proxy uses neither "org.freedesktop" nor - // "org.kde" and just gives us the items "unique name" - // - // We could use this to our advantage and fill out the "unique name" - // field with the given name if it is neither freedesktop or kde, but - // that's makes us rely on KDE hackyness which is bad practice - const char freedesktop_name[] = "org.freedesktop"; - if (strncmp(name, freedesktop_name, sizeof(freedesktop_name) - 1) != 0) { - item->kde_special_snowflake = true; - } else { - item->kde_special_snowflake = false; - } - - get_icon(item); - - get_unique_name(item); - - return item; -} -/* Return 0 if `item` has a name of `str` */ -int sni_str_cmp(const void *_item, const void *_str) { - const struct StatusNotifierItem *item = _item; - const char *str = _str; - - return strcmp(item->name, str); -} -/* Returns 0 if `item` has a unique name of `str` */ -int sni_uniq_cmp(const void *_item, const void *_str) { - const struct StatusNotifierItem *item = _item; - const char *str = _str; - - if (!item->unique_name) { - return false; - } - return strcmp(item->unique_name, str); -} -void sni_free(struct StatusNotifierItem *item) { - if (!item) { - return; - } - free(item->name); - if (item->unique_name) { - free(item->unique_name); - } - if (item->image) { - cairo_surface_destroy(item->image); - } - free(item); -} diff --git a/swaybar/tray/sni_watcher.c b/swaybar/tray/sni_watcher.c deleted file mode 100644 index 86453e70..00000000 --- a/swaybar/tray/sni_watcher.c +++ /dev/null @@ -1,497 +0,0 @@ -#define _XOPEN_SOURCE 500 -#include -#include -#include -#include -#include -#include -#include "swaybar/tray/dbus.h" -#include "list.h" -#include "log.h" - -static list_t *items = NULL; -static list_t *hosts = NULL; - -/** - * Describes the function of the StatusNotifierWatcher - * See https://freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierWatcher/ - * - * We also implement KDE's special snowflake protocol, it's like this but with - * all occurrences 'freedesktop' replaced with 'kde'. There is no KDE introspect. - */ -static const char *interface_xml = - "" - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - -static void host_registered_signal(DBusConnection *connection) { - // Send one signal for each protocol - DBusMessage *signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierHostRegistered"); - - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); - - - signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.kde.StatusNotifierWatcher", - "StatusNotifierHostRegistered"); - - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); -} -static void item_registered_signal(DBusConnection *connection, const char *name) { - DBusMessage *signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemRegistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); - - signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.kde.StatusNotifierWatcher", - "StatusNotifierItemRegistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); -} -static void item_unregistered_signal(DBusConnection *connection, const char *name) { - DBusMessage *signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemUnregistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); - - signal = dbus_message_new_signal( - "/StatusNotifierWatcher", - "org.kde.StatusNotifierWatcher", - "StatusNotifierItemUnregistered"); - dbus_message_append_args(signal, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, signal, NULL); - dbus_message_unref(signal); -} - -static void respond_to_introspect(DBusConnection *connection, DBusMessage *request) { - DBusMessage *reply; - - reply = dbus_message_new_method_return(request); - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &interface_xml, - DBUS_TYPE_INVALID); - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); -} - -static void register_item(DBusConnection *connection, DBusMessage *message) { - DBusError error; - char *name; - - dbus_error_init(&error); - if (!dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); - } - - sway_log(L_INFO, "RegisterStatusNotifierItem called with \"%s\"\n", name); - - // Don't add duplicate or not real item - if (!dbus_validate_bus_name(name, NULL)) { - sway_log(L_INFO, "This item is not valid, we cannot keep track of it."); - return; - } - - if (list_seq_find(items, (int (*)(const void *, const void *))strcmp, name) != -1) { - return; - } - if (!dbus_bus_name_has_owner(connection, name, &error)) { - return; - } - - list_add(items, strdup(name)); - item_registered_signal(connection, name); - - // It's silly, but xembedsniproxy wants a reply for this function - DBusMessage *reply = dbus_message_new_method_return(message); - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); -} - -static void register_host(DBusConnection *connection, DBusMessage *message) { - DBusError error; - char *name; - - dbus_error_init(&error); - if (!dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing method args: %s\n", error.message); - } - - sway_log(L_INFO, "RegisterStatusNotifierHost called with \"%s\"\n", name); - - // Don't add duplicate or not real host - if (!dbus_validate_bus_name(name, NULL)) { - sway_log(L_INFO, "This item is not valid, we cannot keep track of it."); - return; - } - - - if (list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name) != -1) { - return; - } - if (!dbus_bus_name_has_owner(connection, name, &error)) { - return; - } - - list_add(hosts, strdup(name)); - host_registered_signal(connection); -} - -static void get_property(DBusConnection *connection, DBusMessage *message) { - DBusError error; - char *interface; - char *property; - - dbus_error_init(&error); - if (!dbus_message_get_args(message, &error, - DBUS_TYPE_STRING, &interface, - DBUS_TYPE_STRING, &property, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error parsing prop args: %s\n", error.message); - return; - } - - if (strcmp(property, "RegisteredStatusNotifierItems") == 0) { - sway_log(L_INFO, "Replying with items\n"); - DBusMessage *reply; - reply = dbus_message_new_method_return(message); - DBusMessageIter iter; - DBusMessageIter sub; - DBusMessageIter subsub; - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, - "as", &sub); - dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, - "s", &subsub); - - for (int i = 0; i < items->length; ++i) { - dbus_message_iter_append_basic(&subsub, - DBUS_TYPE_STRING, &items->items[i]); - } - - dbus_message_iter_close_container(&sub, &subsub); - dbus_message_iter_close_container(&iter, &sub); - - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } else if (strcmp(property, "IsStatusNotifierHostRegistered") == 0) { - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter sub; - int registered = (hosts == NULL || hosts->length == 0) ? 0 : 1; - - reply = dbus_message_new_method_return(message); - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, - "b", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_BOOLEAN, ®istered); - - dbus_message_iter_close_container(&iter, &sub); - - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } else if (strcmp(property, "ProtocolVersion") == 0) { - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter sub; - const int version = 0; - - reply = dbus_message_new_method_return(message); - - dbus_message_iter_init_append(reply, &iter); - - dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, - "i", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_INT32, &version); - - dbus_message_iter_close_container(&iter, &sub); - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } -} - -static void set_property(DBusConnection *connection, DBusMessage *message) { - // All properties are read only and we don't allow new properties - return; -} - -static void get_all(DBusConnection *connection, DBusMessage *message) { - DBusMessage *reply; - reply = dbus_message_new_method_return(message); - DBusMessageIter iter; /* a{v} */ - DBusMessageIter arr; - DBusMessageIter dict; - DBusMessageIter sub; - DBusMessageIter subsub; - int registered = (hosts == NULL || hosts->length == 0) ? 0 : 1; - const int version = 0; - const char *prop; - - // Could clean this up with a function for each prop - dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - "{sv}", &arr); - - prop = "RegisteredStatusNotifierItems"; - dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, - NULL, &dict); - dbus_message_iter_append_basic(&dict, - DBUS_TYPE_STRING, &prop); - dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, - "as", &sub); - dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, - "s", &subsub); - for (int i = 0; i < items->length; ++i) { - dbus_message_iter_append_basic(&subsub, - DBUS_TYPE_STRING, &items->items[i]); - } - dbus_message_iter_close_container(&sub, &subsub); - dbus_message_iter_close_container(&dict, &sub); - dbus_message_iter_close_container(&arr, &dict); - - prop = "IsStatusNotifierHostRegistered"; - dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, - NULL, &dict); - dbus_message_iter_append_basic(&dict, - DBUS_TYPE_STRING, &prop); - dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, - "b", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_BOOLEAN, ®istered); - dbus_message_iter_close_container(&dict, &sub); - dbus_message_iter_close_container(&arr, &dict); - - prop = "ProtocolVersion"; - dbus_message_iter_open_container(&arr, DBUS_TYPE_DICT_ENTRY, - NULL, &dict); - dbus_message_iter_append_basic(&dict, - DBUS_TYPE_STRING, &prop); - dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, - "i", &sub); - dbus_message_iter_append_basic(&sub, - DBUS_TYPE_INT32, &version); - dbus_message_iter_close_container(&dict, &sub); - dbus_message_iter_close_container(&arr, &dict); - - dbus_message_iter_close_container(&iter, &arr); - - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); -} - -static DBusHandlerResult message_handler(DBusConnection *connection, - DBusMessage *message, void *data) { - const char *interface_name = dbus_message_get_interface(message); - const char *member_name = dbus_message_get_member(message); - - // In order of the xml above - if (strcmp(interface_name, "org.freedesktop.DBus.Introspectable") == 0 && - strcmp(member_name, "Introspect") == 0) { - // We don't have an introspect for KDE - respond_to_introspect(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(interface_name, "org.freedesktop.DBus.Properties") == 0) { - if (strcmp(member_name, "Get") == 0) { - get_property(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(member_name, "Set") == 0) { - set_property(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(member_name, "GetAll") == 0) { - get_all(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - } else if (strcmp(interface_name, "org.freedesktop.StatusNotifierWatcher") == 0 || - strcmp(interface_name, "org.kde.StatusNotifierWatcher") == 0) { - if (strcmp(member_name, "RegisterStatusNotifierItem") == 0) { - register_item(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else if (strcmp(member_name, "RegisterStatusNotifierHost") == 0) { - register_host(connection, message); - return DBUS_HANDLER_RESULT_HANDLED; - } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static DBusHandlerResult signal_handler(DBusConnection *connection, - DBusMessage *message, void *_data) { - if (dbus_message_is_signal(message, "org.freedesktop.DBus", "NameOwnerChanged")) { - // Only eat the message if it is name that we are watching - const char *name; - const char *old_owner; - const char *new_owner; - int index; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_STRING, &old_owner, - DBUS_TYPE_STRING, &new_owner, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error getting LostName args"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - if (strcmp(new_owner, "") != 0) { - // Name is not lost - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - if ((index = list_seq_find(items, (int (*)(const void *, const void *))strcmp, name)) != -1) { - sway_log(L_INFO, "Status Notifier Item lost %s", name); - free(items->items[index]); - list_del(items, index); - item_unregistered_signal(connection, name); - - return DBUS_HANDLER_RESULT_HANDLED; - } - if ((index = list_seq_find(hosts, (int (*)(const void *, const void *))strcmp, name)) != -1) { - sway_log(L_INFO, "Status Notifier Host lost %s", name); - free(hosts->items[index]); - list_del(hosts, index); - - return DBUS_HANDLER_RESULT_HANDLED; - } - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static const DBusObjectPathVTable vtable = { - .message_function = message_handler, - .unregister_function = NULL, -}; - -int init_sni_watcher() { - DBusError error; - dbus_error_init(&error); - if (!conn) { - sway_log(L_ERROR, "Connection is null, cannot initiate StatusNotifierWatcher"); - return -1; - } - - items = create_list(); - hosts = create_list(); - - int status = dbus_bus_request_name(conn, "org.freedesktop.StatusNotifierWatcher", - DBUS_NAME_FLAG_REPLACE_EXISTING, - &error); - if (status == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - sway_log(L_DEBUG, "Got watcher name"); - } else if (status == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) { - sway_log(L_INFO, "Could not get watcher name, it may start later"); - } - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus err getting watcher name: %s\n", error.message); - return -1; - } - - status = dbus_bus_request_name(conn, "org.kde.StatusNotifierWatcher", - DBUS_NAME_FLAG_REPLACE_EXISTING, - &error); - if (status == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - sway_log(L_DEBUG, "Got kde watcher name"); - } else if (status == DBUS_REQUEST_NAME_REPLY_IN_QUEUE) { - sway_log(L_INFO, "Could not get kde watcher name, it may start later"); - } - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus err getting kde watcher name: %s\n", error.message); - return -1; - } - - dbus_connection_try_register_object_path(conn, - "/StatusNotifierWatcher", - &vtable, NULL, &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err: %s\n", error.message); - return -1; - } - - dbus_bus_add_match(conn, - "type='signal',\ - sender='org.freedesktop.DBus',\ - interface='org.freedesktop.DBus',\ - member='NameOwnerChanged'", - &error); - - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "DBus error getting match args: %s", error.message); - } - - dbus_connection_add_filter(conn, signal_handler, NULL, NULL); - return 0; -} diff --git a/swaybar/tray/tray.c b/swaybar/tray/tray.c deleted file mode 100644 index 91c3af06..00000000 --- a/swaybar/tray/tray.c +++ /dev/null @@ -1,398 +0,0 @@ -#define _XOPEN_SOURCE 700 -#include -#include -#include -#include -#include -#include "swaybar/bar.h" -#include "swaybar/tray/tray.h" -#include "swaybar/tray/dbus.h" -#include "swaybar/tray/sni.h" -#include "swaybar/tray/sni_watcher.h" -#include "swaybar/bar.h" -#include "swaybar/config.h" -#include "list.h" -#include "log.h" - -struct tray *tray; - -static void register_host(char *name) { - DBusMessage *message; - - message = dbus_message_new_method_call( - "org.freedesktop.StatusNotifierWatcher", - "/StatusNotifierWatcher", - "org.freedesktop.StatusNotifierWatcher", - "RegisterStatusNotifierHost"); - if (!message) { - sway_log(L_ERROR, "Cannot allocate dbus method call"); - return; - } - - dbus_message_append_args(message, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); - - dbus_connection_send(conn, message, NULL); - - dbus_message_unref(message); -} - -static void get_items_reply(DBusPendingCall *pending, void *_data) { - DBusMessage *reply = dbus_pending_call_steal_reply(pending); - - if (!reply) { - sway_log(L_ERROR, "Got no items reply from sni watcher"); - goto bail; - } - - int message_type = dbus_message_get_type(reply); - - if (message_type == DBUS_MESSAGE_TYPE_ERROR) { - char *msg; - - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &msg, - DBUS_TYPE_INVALID); - - sway_log(L_ERROR, "Message is error: %s", msg); - goto bail; - } - - DBusMessageIter iter; - DBusMessageIter variant; - DBusMessageIter array; - - dbus_message_iter_init(reply, &iter); - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) { - sway_log(L_ERROR, "Replyed with wrong type, not v(as)"); - goto bail; - } - dbus_message_iter_recurse(&iter, &variant); - if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(&variant) != DBUS_TYPE_STRING) { - sway_log(L_ERROR, "Replyed with wrong type, not v(as)"); - goto bail; - } - - // Clear list - list_foreach(tray->items, (void (*)(void *))sni_free); - list_free(tray->items); - tray->items = create_list(); - - // O(n) function, could be faster dynamically reading values - int len = dbus_message_iter_get_element_count(&variant); - - dbus_message_iter_recurse(&variant, &array); - for (int i = 0; i < len; i++) { - const char *name; - dbus_message_iter_get_basic(&array, &name); - - struct StatusNotifierItem *item = sni_create(name); - - if (item) { - sway_log(L_DEBUG, "Item registered with host: %s", name); - list_add(tray->items, item); - dirty = true; - } - } - -bail: - dbus_message_unref(reply); - dbus_pending_call_unref(pending); - return; -} -static void get_items() { - DBusPendingCall *pending; - DBusMessage *message = dbus_message_new_method_call( - "org.freedesktop.StatusNotifierWatcher", - "/StatusNotifierWatcher", - "org.freedesktop.DBus.Properties", - "Get"); - - const char *iface = "org.freedesktop.StatusNotifierWatcher"; - const char *prop = "RegisteredStatusNotifierItems"; - dbus_message_append_args(message, - DBUS_TYPE_STRING, &iface, - DBUS_TYPE_STRING, &prop, - DBUS_TYPE_INVALID); - - bool status = - dbus_connection_send_with_reply(conn, message, &pending, -1); - dbus_message_unref(message); - - if (!(pending || status)) { - sway_log(L_ERROR, "Could not get items"); - return; - } - - dbus_pending_call_set_notify(pending, get_items_reply, NULL, NULL); -} - -static DBusHandlerResult signal_handler(DBusConnection *connection, - DBusMessage *message, void *_data) { - if (dbus_message_is_signal(message, "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemRegistered")) { - const char *name; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error getting StatusNotifierItemRegistered args"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - if (list_seq_find(tray->items, sni_str_cmp, name) == -1) { - struct StatusNotifierItem *item = sni_create(name); - - if (item) { - list_add(tray->items, item); - dirty = true; - } - } - - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal(message, "org.freedesktop.StatusNotifierWatcher", - "StatusNotifierItemUnregistered")) { - const char *name; - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) { - sway_log(L_ERROR, "Error getting StatusNotifierItemUnregistered args"); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } - - int index; - if ((index = list_seq_find(tray->items, sni_str_cmp, name)) != -1) { - sni_free(tray->items->items[index]); - list_del(tray->items, index); - dirty = true; - } else { - // If it's not in our list, then our list is incorrect. - // Fetch all items again - sway_log(L_INFO, "Host item list incorrect, refreshing"); - get_items(); - } - - return DBUS_HANDLER_RESULT_HANDLED; - } else if (dbus_message_is_signal(message, "org.freedesktop.StatusNotifierItem", - "NewIcon") || dbus_message_is_signal(message, - "org.kde.StatusNotifierItem", "NewIcon")) { - const char *name; - int index; - struct StatusNotifierItem *item; - - name = dbus_message_get_sender(message); - if ((index = list_seq_find(tray->items, sni_uniq_cmp, name)) != -1) { - item = tray->items->items[index]; - sway_log(L_INFO, "NewIcon signal from item %s", item->name); - get_icon(item); - } - - return DBUS_HANDLER_RESULT_HANDLED; - } - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static int init_host() { - tray = (struct tray *)malloc(sizeof(tray)); - - tray->items = create_list(); - - DBusError error; - dbus_error_init(&error); - char *name = NULL; - if (!conn) { - sway_log(L_ERROR, "Connection is null, cannot init SNI host"); - goto err; - } - name = calloc(sizeof(char), 256); - - if (!name) { - sway_log(L_ERROR, "Cannot allocate name"); - goto err; - } - - pid_t pid = getpid(); - if (snprintf(name, 256, "org.freedesktop.StatusNotifierHost-%d", pid) - >= 256) { - sway_log(L_ERROR, "Cannot get host name because string is too short." - "This should not happen"); - goto err; - } - - // We want to be the sole owner of this name - if (dbus_bus_request_name(conn, name, DBUS_NAME_FLAG_DO_NOT_QUEUE, - &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - sway_log(L_ERROR, "Cannot get host name and start the tray"); - goto err; - } - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "Dbus err getting host name: %s\n", error.message); - goto err; - } - sway_log(L_DEBUG, "Got host name"); - - register_host(name); - - get_items(); - - // Perhaps use addmatch helper functions like wlc does? - dbus_bus_add_match(conn, - "type='signal',\ - sender='org.freedesktop.StatusNotifierWatcher',\ - member='StatusNotifierItemRegistered'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err: %s", error.message); - goto err; - } - dbus_bus_add_match(conn, - "type='signal',\ - sender='org.freedesktop.StatusNotifierWatcher',\ - member='StatusNotifierItemUnregistered'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err: %s", error.message); - return -1; - } - - // SNI matches - dbus_bus_add_match(conn, - "type='signal',\ - interface='org.freedesktop.StatusNotifierItem',\ - member='NewIcon'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err %s", error.message); - goto err; - } - dbus_bus_add_match(conn, - "type='signal',\ - interface='org.kde.StatusNotifierItem',\ - member='NewIcon'", - &error); - if (dbus_error_is_set(&error)) { - sway_log(L_ERROR, "dbus_err %s", error.message); - goto err; - } - - dbus_connection_add_filter(conn, signal_handler, NULL, NULL); - - free(name); - return 0; - -err: - // TODO better handle errors - free(name); - return -1; -} - -void tray_mouse_event(struct output *output, int x, int y, - uint32_t button, uint32_t state) { - - struct window *window = output->window; - uint32_t tray_padding = swaybar.config->tray_padding; - int tray_width = window->width * window->scale; - - for (int i = 0; i < output->items->length; ++i) { - struct sni_icon_ref *item = - output->items->items[i]; - int icon_width = cairo_image_surface_get_width(item->icon); - - tray_width -= tray_padding; - if (x <= tray_width && x >= tray_width - icon_width) { - if (button == swaybar.config->activate_button) { - sni_activate(item->ref, x, y); - } else if (button == swaybar.config->context_button) { - sni_context_menu(item->ref, x, y); - } else if (button == swaybar.config->secondary_button) { - sni_secondary(item->ref, x, y); - } - break; - } - tray_width -= icon_width; - } -} - -uint32_t tray_render(struct output *output, struct config *config) { - struct window *window = output->window; - cairo_t *cairo = window->cairo; - - // Tray icons - uint32_t tray_padding = config->tray_padding; - uint32_t tray_width = window->width * window->scale; - const int item_size = (window->height * window->scale) - (2 * tray_padding); - - if (item_size < 0) { - // Can't render items if the padding is too large - return tray_width; - } - - if (config->tray_output && strcmp(config->tray_output, output->name) != 0) { - return tray_width; - } - - for (int i = 0; i < tray->items->length; ++i) { - struct StatusNotifierItem *item = - tray->items->items[i]; - if (!item->image) { - continue; - } - - struct sni_icon_ref *render_item = NULL; - int j; - for (j = i; j < output->items->length; ++j) { - struct sni_icon_ref *ref = - output->items->items[j]; - if (ref->ref == item) { - render_item = ref; - break; - } else { - sni_icon_ref_free(ref); - list_del(output->items, j); - } - } - - if (!render_item) { - render_item = sni_icon_ref_create(item, item_size); - list_add(output->items, render_item); - } else if (item->dirty) { - // item needs re-render - sni_icon_ref_free(render_item); - output->items->items[j] = render_item = - sni_icon_ref_create(item, item_size); - } - - tray_width -= tray_padding; - tray_width -= item_size; - - cairo_operator_t op = cairo_get_operator(cairo); - cairo_set_operator(cairo, CAIRO_OPERATOR_OVER); - cairo_set_source_surface(cairo, render_item->icon, tray_width, tray_padding); - cairo_rectangle(cairo, tray_width, tray_padding, item_size, item_size); - cairo_fill(cairo); - cairo_set_operator(cairo, op); - - item->dirty = false; - } - - - if (tray_width != window->width * window->scale) { - tray_width -= tray_padding; - } - - return tray_width; -} - -void init_tray(struct bar *bar) { - if (!bar->config->tray_output || strcmp(bar->config->tray_output, "none") != 0) { - /* Connect to the D-Bus */ - dbus_init(); - - /* Start the SNI watcher */ - init_sni_watcher(); - - /* Start the SNI host */ - init_host(); - } -} -- cgit v1.2.3 From 849c3515abff7033dbd4723fd7328cb07af74222 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 29 Mar 2018 21:54:08 -0400 Subject: Use statically allocated text buffer --- common/pango.c | 6 ++---- sway/commands/bar.c | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'common') diff --git a/common/pango.c b/common/pango.c index 212d96cf..2ae7883c 100644 --- a/common/pango.c +++ b/common/pango.c @@ -32,7 +32,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, int32_t scale, bool markup, const char *fmt, ...) { - char *buf = malloc(2048); + static char buf[2048]; va_list args; va_start(args, fmt); @@ -45,12 +45,11 @@ void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, pango_cairo_update_layout(cairo, layout); pango_layout_get_pixel_size(layout, width, height); g_object_unref(layout); - free(buf); } void pango_printf(cairo_t *cairo, const char *font, int32_t scale, bool markup, const char *fmt, ...) { - char *buf = malloc(2048); + static char buf[2048]; va_list args; va_start(args, fmt); @@ -63,5 +62,4 @@ void pango_printf(cairo_t *cairo, const char *font, pango_cairo_update_layout(cairo, layout); pango_cairo_show_layout(cairo, layout); g_object_unref(layout); - free(buf); } diff --git a/sway/commands/bar.c b/sway/commands/bar.c index 548106b3..ff111163 100644 --- a/sway/commands/bar.c +++ b/sway/commands/bar.c @@ -36,15 +36,15 @@ struct cmd_results *cmd_bar(int argc, char **argv) { } // set bar id - int i; - for (i = 0; i < config->bars->length; ++i) { + for (int i = 0; i < config->bars->length; ++i) { if (bar == config->bars->items[i]) { const int len = 5 + numlen(i); // "bar-" + i + \0 bar->id = malloc(len * sizeof(char)); if (bar->id) { snprintf(bar->id, len, "bar-%d", i); } else { - return cmd_results_new(CMD_FAILURE, "bar", "Unable to allocate bar ID"); + return cmd_results_new(CMD_FAILURE, + "bar", "Unable to allocate bar ID"); } break; } -- cgit v1.2.3 From c507727ad240b978c6e09e3aa9238080ca9a1c81 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 11:53:56 -0400 Subject: Fix use-after-free with block hotspots --- common/pango.c | 9 ++++++++- sway/tree/layout.c | 4 ++-- swaybar/i3bar.c | 4 +--- swaybar/render.c | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) (limited to 'common') diff --git a/common/pango.c b/common/pango.c index 2ae7883c..658d2876 100644 --- a/common/pango.c +++ b/common/pango.c @@ -6,6 +6,7 @@ #include #include #include +#include "log.h" PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, int32_t scale, bool markup) { @@ -13,7 +14,13 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, PangoAttrList *attrs; if (markup) { char *buf; - pango_parse_markup(text, -1, 0, &attrs, &buf, NULL, NULL); + GError *error = NULL; + if (!sway_assert(pango_parse_markup( + text, -1, 0, &attrs, &buf, NULL, &error), + "pango_parse_markup '%s' -> error %s", text, + error ? error->message : NULL)) { + return NULL; + } pango_layout_set_markup(layout, buf, -1); free(buf); } else { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index ce0682dc..e8363660 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -248,8 +248,8 @@ void arrange_windows(struct sway_container *container, struct wlr_box *area = &output->sway_output->usable_area; wlr_log(L_DEBUG, "Usable area for ws: %dx%d@%d,%d", area->width, area->height, area->x, area->y); - container->width = area->width; - container->height = area->height; + container->width = width = area->width; + container->height = height = area->height; container->x = x = area->x; container->y = y = area->y; wlr_log(L_DEBUG, "Arranging workspace '%s' at %f, %f", diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 5e98c4aa..46459e24 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -30,9 +30,7 @@ static bool i3bar_parse_json(struct status_line *status, const char *text) { status_error(status, "[failed to parse i3bar json]"); return false; } - if (json_object_array_length(results) < 1) { - return true; - } + wlr_log(L_DEBUG, "Got i3bar json: '%s'", text); for (size_t i = 0; i < json_object_array_length(results); ++i) { json_object *full_text, *short_text, *color, *min_width, *align, *urgent; json_object *name, *instance, *separator, *separator_block_width; diff --git a/swaybar/render.c b/swaybar/render.c index a5039a2e..a62e1d01 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -153,7 +153,7 @@ static uint32_t render_status_block(cairo_t *cairo, hotspot->width = width; hotspot->height = height; hotspot->callback = block_hotspot_callback; - hotspot->destroy = free; + hotspot->destroy = NULL; hotspot->data = block; wl_list_insert(&output->hotspots, &hotspot->link); @@ -227,9 +227,9 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, struct swaybar_config *config, struct swaybar_output *output, struct status_line *status, bool focused, double *x, uint32_t width, uint32_t height) { - struct i3bar_block *block; uint32_t max_height = 0; bool edge = true; + struct i3bar_block *block; wl_list_for_each_reverse(block, &status->blocks, link) { uint32_t h = render_status_block(cairo, config, output, block, x, height, focused, edge); @@ -376,6 +376,7 @@ static uint32_t render_workspace_button(cairo_t *cairo, static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar *bar, struct swaybar_output *output) { struct swaybar_config *config = bar->config; + wlr_log(L_DEBUG, "output %p", output); cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); if (output->focused) { -- cgit v1.2.3 From a28730edee1896242012f80fd0e63e7966652e02 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 21:57:13 -0400 Subject: Move swaybg background rendering into common/ swaylock will use it too --- common/background-image.c | 100 +++++++++++++++++++++++++++++++++++++++ common/meson.build | 20 ++++---- include/background-image.h | 19 ++++++++ swaybg/main.c | 113 +++------------------------------------------ 4 files changed, 133 insertions(+), 119 deletions(-) create mode 100644 common/background-image.c create mode 100644 include/background-image.h (limited to 'common') diff --git a/common/background-image.c b/common/background-image.c new file mode 100644 index 00000000..2988c2e2 --- /dev/null +++ b/common/background-image.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include "background-image.h" +#include "cairo.h" + +cairo_surface_t *load_background_image(const char *path) { + cairo_surface_t *image; +#ifdef HAVE_GDK_PIXBUF + GError *err = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); + if (!pixbuf) { + wlr_log(L_ERROR, "Failed to load background image."); + return false; + } + image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); + g_object_unref(pixbuf); +#else + image = cairo_image_surface_create_from_png(path); +#endif //HAVE_GDK_PIXBUF + if (!image) { + wlr_log(L_ERROR, "Failed to read background image."); + return NULL; + } + if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { + wlr_log(L_ERROR, "Failed to read background image: %s." +#ifndef HAVE_GDK_PIXBUF + "\nSway was compiled without gdk_pixbuf support, so only" + "\nPNG images can be loaded. This is the likely cause." +#endif //HAVE_GDK_PIXBUF + , cairo_status_to_string(cairo_surface_status(image))); + return NULL; + } + return image; +} + +void render_background_image(cairo_t *cairo, cairo_surface_t *image, + enum background_mode mode, int buffer_width, int buffer_height, + int buffer_scale) { + double width = cairo_image_surface_get_width(image); + double height = cairo_image_surface_get_height(image); + + switch (mode) { + case BACKGROUND_MODE_STRETCH: + cairo_scale(cairo, + (double)buffer_width / width, + (double)buffer_height / height); + cairo_set_source_surface(cairo, image, 0, 0); + break; + case BACKGROUND_MODE_FILL: { + double window_ratio = (double)buffer_width / buffer_height; + double bg_ratio = width / height; + + if (window_ratio > bg_ratio) { + double scale = (double)buffer_width / width; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + 0, (double)buffer_height / 2 / scale - height / 2); + } else { + double scale = (double)buffer_height / height; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + (double)buffer_width / 2 / scale - width / 2, 0); + } + break; + } + case BACKGROUND_MODE_FIT: { + double window_ratio = (double)buffer_width / buffer_height; + double bg_ratio = width / height; + + if (window_ratio > bg_ratio) { + double scale = (double)buffer_height / height; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + (double)buffer_width / 2 / scale - width / 2, 0); + } else { + double scale = (double)buffer_width / width; + cairo_scale(cairo, scale, scale); + cairo_set_source_surface(cairo, image, + 0, (double)buffer_height / 2 / scale - height / 2); + } + break; + } + case BACKGROUND_MODE_CENTER: + cairo_set_source_surface(cairo, image, + (double)buffer_width / 2 - width / 2, + (double)buffer_height / 2 - height / 2); + break; + case BACKGROUND_MODE_TILE: { + cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); + cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); + cairo_set_source(cairo, pattern); + break; + } + case BACKGROUND_MODE_SOLID_COLOR: + assert(0); + break; + } + cairo_paint(cairo); +} diff --git a/common/meson.build b/common/meson.build index 4ad47077..851e7bbf 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,17 +1,7 @@ -deps = [ - cairo, - pango, - pangocairo, - wlroots -] - -if gdk_pixbuf.found() - deps += [gdk_pixbuf] -endif - lib_sway_common = static_library( 'sway-common', files( + 'background-image.c', 'cairo.c', 'ipc-client.c', 'log.c', @@ -21,6 +11,12 @@ lib_sway_common = static_library( 'stringop.c', 'util.c' ), - dependencies: deps, + dependencies: [ + cairo, + gdk_pixbuf, + pango, + pangocairo, + wlroots + ], include_directories: sway_inc ) diff --git a/include/background-image.h b/include/background-image.h new file mode 100644 index 00000000..e160e63d --- /dev/null +++ b/include/background-image.h @@ -0,0 +1,19 @@ +#ifndef _SWAY_BACKGROUND_IMAGE_H +#define _SWAY_BACKGROUND_IMAGE_H +#include "cairo.h" + +enum background_mode { + BACKGROUND_MODE_STRETCH, + BACKGROUND_MODE_FILL, + BACKGROUND_MODE_FIT, + BACKGROUND_MODE_CENTER, + BACKGROUND_MODE_TILE, + BACKGROUND_MODE_SOLID_COLOR, +}; + +cairo_surface_t *load_background_image(const char *path); +void render_background_image(cairo_t *cairo, cairo_surface_t *image, + enum background_mode mode, int buffer_width, int buffer_height, + int buffer_scale); + +#endif diff --git a/swaybg/main.c b/swaybg/main.c index c282a707..ffefcd08 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -7,20 +7,12 @@ #include #include #include +#include "background-image.h" #include "pool-buffer.h" #include "cairo.h" #include "util.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" -enum background_mode { - BACKGROUND_MODE_STRETCH, - BACKGROUND_MODE_FILL, - BACKGROUND_MODE_FIT, - BACKGROUND_MODE_CENTER, - BACKGROUND_MODE_TILE, - BACKGROUND_MODE_SOLID_COLOR, -}; - struct swaybg_args { int output_idx; const char *path; @@ -71,85 +63,16 @@ bool is_valid_color(const char *color) { return true; } -static void render_image(struct swaybg_state *state) { - cairo_t *cairo = state->current_buffer->cairo; - cairo_surface_t *image = state->context.image; - double width = cairo_image_surface_get_width(image); - double height = cairo_image_surface_get_height(image); - int buffer_width = state->width * state->scale; - int buffer_height = state->height * state->scale; - - switch (state->args->mode) { - case BACKGROUND_MODE_STRETCH: - cairo_scale(cairo, (double)buffer_width / width, - (double)buffer_height / height); - cairo_set_source_surface(cairo, image, 0, 0); - break; - case BACKGROUND_MODE_FILL: { - double window_ratio = (double)buffer_width / buffer_height; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double)buffer_width / width; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - 0, (double)buffer_height / 2 / scale - height / 2); - } else { - double scale = (double)buffer_height / height; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 / scale - width / 2, 0); - } - break; - } - case BACKGROUND_MODE_FIT: { - double window_ratio = (double)buffer_width / buffer_height; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double)buffer_height / height; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 / scale - width / 2, 0); - } else { - double scale = (double)buffer_width / width; - cairo_scale(cairo, scale, scale); - cairo_set_source_surface(cairo, image, - 0, (double)buffer_height / 2 / scale - height / 2); - } - break; - } - case BACKGROUND_MODE_CENTER: - cairo_set_source_surface(cairo, image, - (double)buffer_width / 2 - width / 2, - (double)buffer_height / 2 - height / 2); - break; - case BACKGROUND_MODE_TILE: { - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source(cairo, pattern); - break; - } - case BACKGROUND_MODE_SOLID_COLOR: - assert(0); - break; - } - cairo_paint(cairo); -} - static void render_frame(struct swaybg_state *state) { state->current_buffer = get_next_buffer(state->shm, state->buffers, state->width * state->scale, state->height * state->scale); cairo_t *cairo = state->current_buffer->cairo; - - switch (state->args->mode) { - case BACKGROUND_MODE_SOLID_COLOR: + if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->context.color); cairo_paint(cairo); - break; - default: - render_image(state); - break; + } else { + render_background_image(cairo, state->context.image, + state->args->mode, state->width, state->height, state->scale); } wl_surface_set_buffer_scale(state->surface, state->scale); @@ -163,31 +86,7 @@ static bool prepare_context(struct swaybg_state *state) { state->context.color = parse_color(state->args->path); return is_valid_color(state->args->path); } -#ifdef HAVE_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(state->args->path, &err); - if (!pixbuf) { - wlr_log(L_ERROR, "Failed to load background image."); - return false; - } - state->context.image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - state->context.image = cairo_image_surface_create_from_png( - state->args->path); -#endif //HAVE_GDK_PIXBUF - if (!state->context.image) { - wlr_log(L_ERROR, "Failed to read background image."); - return false; - } - if (cairo_surface_status(state->context.image) != CAIRO_STATUS_SUCCESS) { - wlr_log(L_ERROR, "Failed to read background image: %s." -#ifndef HAVE_GDK_PIXBUF - "\nSway was compiled without gdk_pixbuf support, so only" - "\nPNG images can be loaded. This is the likely cause." -#endif //HAVE_GDK_PIXBUF - , cairo_status_to_string( - cairo_surface_status(state->context.image))); + if (!(state->context.image = load_background_image(state->args->path))) { return false; } return true; -- cgit v1.2.3 From b32bf595aeae7f8ac68354e45a80c0438374ec17 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 2 Apr 2018 22:48:13 -0400 Subject: Initial swaylock port --- common/background-image.c | 22 +- include/background-image.h | 5 +- meson.build | 2 + swaybg/main.c | 28 +- swaylock/main.c | 952 ++++++++++++--------------------------------- swaylock/meson.build | 18 + 6 files changed, 298 insertions(+), 729 deletions(-) create mode 100644 swaylock/meson.build (limited to 'common') diff --git a/common/background-image.c b/common/background-image.c index 2988c2e2..1a6c0df0 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -4,6 +4,24 @@ #include "background-image.h" #include "cairo.h" +enum background_mode parse_background_mode(const char *mode) { + if (strcmp(mode, "stretch") == 0) { + return BACKGROUND_MODE_STRETCH; + } else if (strcmp(mode, "fill") == 0) { + return BACKGROUND_MODE_FILL; + } else if (strcmp(mode, "fit") == 0) { + return BACKGROUND_MODE_FIT; + } else if (strcmp(mode, "center") == 0) { + return BACKGROUND_MODE_CENTER; + } else if (strcmp(mode, "tile") == 0) { + return BACKGROUND_MODE_TILE; + } else if (strcmp(mode, "solid_color") == 0) { + return BACKGROUND_MODE_SOLID_COLOR; + } + wlr_log(L_ERROR, "Unsupported background mode: %s", mode); + return BACKGROUND_MODE_INVALID; +} + cairo_surface_t *load_background_image(const char *path) { cairo_surface_t *image; #ifdef HAVE_GDK_PIXBUF @@ -35,8 +53,7 @@ cairo_surface_t *load_background_image(const char *path) { } void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height, - int buffer_scale) { + enum background_mode mode, int buffer_width, int buffer_height) { double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); @@ -93,6 +110,7 @@ void render_background_image(cairo_t *cairo, cairo_surface_t *image, break; } case BACKGROUND_MODE_SOLID_COLOR: + case BACKGROUND_MODE_INVALID: assert(0); break; } diff --git a/include/background-image.h b/include/background-image.h index e160e63d..15935ffd 100644 --- a/include/background-image.h +++ b/include/background-image.h @@ -9,11 +9,12 @@ enum background_mode { BACKGROUND_MODE_CENTER, BACKGROUND_MODE_TILE, BACKGROUND_MODE_SOLID_COLOR, + BACKGROUND_MODE_INVALID, }; +enum background_mode parse_background_mode(const char *mode); cairo_surface_t *load_background_image(const char *path); void render_background_image(cairo_t *cairo, cairo_surface_t *image, - enum background_mode mode, int buffer_width, int buffer_height, - int buffer_scale); + enum background_mode mode, int buffer_width, int buffer_height); #endif diff --git a/meson.build b/meson.build index 01788fd9..d02a446b 100644 --- a/meson.build +++ b/meson.build @@ -35,6 +35,7 @@ gdk_pixbuf = dependency('gdk-pixbuf-2.0', required: false) pixman = dependency('pixman-1') libcap = dependency('libcap') libinput = dependency('libinput') +libpam = cc.find_library('libpam') math = cc.find_library('m') rt = cc.find_library('rt') git = find_program('git', required: false) @@ -105,6 +106,7 @@ subdir('swaymsg') subdir('client') subdir('swaybg') subdir('swaybar') +subdir('swaylock') config = configuration_data() config.set('sysconfdir', join_paths(prefix, sysconfdir)) diff --git a/swaybg/main.c b/swaybg/main.c index ffefcd08..679b8c20 100644 --- a/swaybg/main.c +++ b/swaybg/main.c @@ -64,15 +64,17 @@ bool is_valid_color(const char *color) { } static void render_frame(struct swaybg_state *state) { - state->current_buffer = get_next_buffer(state->shm, state->buffers, - state->width * state->scale, state->height * state->scale); + int buffer_width = state->width * state->scale, + buffer_height = state->height * state->scale; + state->current_buffer = get_next_buffer(state->shm, + state->buffers, buffer_width, buffer_height); cairo_t *cairo = state->current_buffer->cairo; if (state->args->mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->context.color); cairo_paint(cairo); } else { render_background_image(cairo, state->context.image, - state->args->mode, state->width, state->height, state->scale); + state->args->mode, buffer_width, buffer_height); } wl_surface_set_buffer_scale(state->surface, state->scale); @@ -193,24 +195,10 @@ int main(int argc, const char **argv) { args.output_idx = atoi(argv[1]); args.path = argv[2]; - args.mode = BACKGROUND_MODE_STRETCH; - if (strcmp(argv[3], "stretch") == 0) { - args.mode = BACKGROUND_MODE_STRETCH; - } else if (strcmp(argv[3], "fill") == 0) { - args.mode = BACKGROUND_MODE_FILL; - } else if (strcmp(argv[3], "fit") == 0) { - args.mode = BACKGROUND_MODE_FIT; - } else if (strcmp(argv[3], "center") == 0) { - args.mode = BACKGROUND_MODE_CENTER; - } else if (strcmp(argv[3], "tile") == 0) { - args.mode = BACKGROUND_MODE_TILE; - } else if (strcmp(argv[3], "solid_color") == 0) { - args.mode = BACKGROUND_MODE_SOLID_COLOR; - } else { - wlr_log(L_ERROR, "Unsupported background mode: %s", argv[3]); + args.mode = parse_background_mode(argv[3]); + if (args.mode == BACKGROUND_MODE_INVALID) { return 1; } - if (!prepare_context(&state)) { return 1; } @@ -244,10 +232,10 @@ int main(int argc, const char **argv) { zwlr_layer_surface_v1_set_exclusive_zone(state.layer_surface, -1); zwlr_layer_surface_v1_add_listener(state.layer_surface, &layer_surface_listener, &state); - state.run_display = true; wl_surface_commit(state.surface); wl_display_roundtrip(state.display); + state.run_display = true; while (wl_display_dispatch(state.display) != -1 && state.run_display) { // This space intentionally left blank } diff --git a/swaylock/main.c b/swaylock/main.c index c2615951..8673694d 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -1,387 +1,235 @@ -#define _XOPEN_SOURCE 500 -#include "wayland-swaylock-client-protocol.h" -#include -#include -#include -#include +#define _XOPEN_SOURCE 700 +#define _POSIX_C_SOURCE 200112L +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include +#include +#include #include -#include "client/window.h" -#include "client/registry.h" -#include "client/cairo.h" -#include "swaylock/swaylock.h" -#include "ipc-client.h" -#include "log.h" +#include +#include +#include "background-image.h" +#include "pool-buffer.h" +#include "cairo.h" #include "util.h" - -struct registry *registry; -struct render_data render_data; -struct lock_config *config; -bool show_indicator = true; - -void wl_dispatch_events() { - wl_display_flush(registry->display); - if (wl_display_dispatch(registry->display) == -1) { - sway_log(L_ERROR, "failed to run wl_display_dispatch"); - exit(1); +#include "wlr-layer-shell-unstable-v1-client-protocol.h" + +struct swaylock_args { + uint32_t color; + enum background_mode mode; + bool show_indicator; +}; + +struct swaylock_state { + struct wl_display *display; + struct wl_compositor *compositor; + struct zwlr_layer_shell_v1 *layer_shell; + struct wl_shm *shm; + struct wl_list contexts; + struct swaylock_args args; + bool run_display; +}; + +struct swaylock_context { + cairo_surface_t *image; + struct swaylock_state *state; + struct wl_output *output; + struct wl_surface *surface; + struct zwlr_layer_surface_v1 *layer_surface; + struct pool_buffer buffers[2]; + struct pool_buffer *current_buffer; + uint32_t width, height; + struct wl_list link; +}; + +static void daemonize() { + if (fork() == 0) { + int devnull = open("/dev/null", O_RDWR); + dup2(STDOUT_FILENO, devnull); + dup2(STDERR_FILENO, devnull); + chdir("/"); + } else { + exit(0); } } -void sigalarm_handler(int sig) { - signal(SIGALRM, SIG_IGN); - // Hide typing indicator - render_data.auth_state = AUTH_STATE_IDLE; - render(&render_data, config); - wl_display_flush(registry->display); - signal(SIGALRM, sigalarm_handler); -} - -void sway_terminate(int exit_code) { - int i; - for (i = 0; i < render_data.surfaces->length; ++i) { - struct window *window = render_data.surfaces->items[i]; - window_teardown(window); - } - list_free(render_data.surfaces); - if (registry) { - registry_teardown(registry); +static void render_frame(struct swaylock_context *context) { + struct swaylock_state *state = context->state; + context->current_buffer = get_next_buffer(state->shm, + context->buffers, context->width, context->height); + cairo_t *cairo = context->current_buffer->cairo; + if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { + cairo_set_source_u32(cairo, state->args.color); + cairo_paint(cairo); + } else { + render_background_image(cairo, context->image, + state->args.mode, context->width, context->height); } - exit(exit_code); + wl_surface_attach(context->surface, context->current_buffer->buffer, 0, 0); + wl_surface_damage(context->surface, 0, 0, context->width, context->height); + wl_surface_commit(context->surface); } -char *password; -int password_size; -enum line_source line_source = LINE_SOURCE_DEFAULT; - -struct lock_config *init_config() { - struct lock_config *config = calloc(1, sizeof(struct lock_config)); - - config->font = strdup("sans-serif"); - config->colors.text = 0x000000FF; - - config->colors.line = 0x000000FF; - config->colors.separator = 0x000000FF; - - config->colors.input_cursor = 0x33DB00FF; - config->colors.backspace_cursor = 0xDB3300FF; - - config->colors.normal.inner_ring = 0x000000BF; - config->colors.normal.outer_ring = 0x337D00FF; - - config->colors.validating.inner_ring = 0x0072FFBF; - config->colors.validating.outer_ring = 0x3300FAFF; - - config->colors.invalid.inner_ring = 0xFA0000BF; - config->colors.invalid.outer_ring = 0x7D3300FF; - - config->radius = 50; - config->thickness = 10; - - return config; +static void layer_surface_configure(void *data, + struct zwlr_layer_surface_v1 *surface, + uint32_t serial, uint32_t width, uint32_t height) { + struct swaylock_context *context = data; + context->width = width; + context->height = height; + zwlr_layer_surface_v1_ack_configure(surface, serial); + render_frame(context); } -void free_config(struct lock_config *config) { - free(config->font); - free(config); +static void layer_surface_closed(void *data, + struct zwlr_layer_surface_v1 *surface) { + struct swaylock_context *context = data; + zwlr_layer_surface_v1_destroy(context->layer_surface); + wl_surface_destroy(context->surface); + context->state->run_display = false; } -int function_conversation(int num_msg, const struct pam_message **msg, - struct pam_response **resp, void *appdata_ptr) { - - const char* msg_style_names[] = { - NULL, - "PAM_PROMPT_ECHO_OFF", - "PAM_PROMPT_ECHO_ON", - "PAM_ERROR_MSG", - "PAM_TEXT_INFO", - }; +struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed, +}; - /* PAM expects an array of responses, one for each message */ - struct pam_response *pam_reply = calloc(num_msg, sizeof(struct pam_response)); - *resp = pam_reply; - - for(int i=0; imsg_style], - msg[i]->msg); - - switch (msg[i]->msg_style) { - case PAM_PROMPT_ECHO_OFF: - case PAM_PROMPT_ECHO_ON: - pam_reply[i].resp = password; - break; +static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface, + wl_fixed_t surface_x, wl_fixed_t surface_y) { + wl_pointer_set_cursor(wl_pointer, serial, NULL, 0, 0); +} - case PAM_ERROR_MSG: - case PAM_TEXT_INFO: - break; - } - } +static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, struct wl_surface *surface) { + // Who cares +} - return PAM_SUCCESS; +static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, + uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { + // Who cares } -/** - * Note: PAM will free() 'password' during the process - */ -bool verify_password() { - struct passwd *passwd = getpwuid(getuid()); - char *username = passwd->pw_name; - - const struct pam_conv local_conversation = { function_conversation, NULL }; - pam_handle_t *local_auth_handle = NULL; - int pam_err; - if ((pam_err = pam_start("swaylock", username, &local_conversation, &local_auth_handle)) != PAM_SUCCESS) { - sway_abort("PAM returned %d\n", pam_err); - } - if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { - return false; - } - if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { - return false; - } - return true; +static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, + uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + // Who cares } -void notify_key(enum wl_keyboard_key_state state, xkb_keysym_t sym, uint32_t code, uint32_t codepoint) { - int redraw_screen = 0; - char *password_realloc; - int i; +static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis, wl_fixed_t value) { + // Who cares +} - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - switch (sym) { - case XKB_KEY_KP_Enter: - case XKB_KEY_Return: - render_data.auth_state = AUTH_STATE_VALIDATING; +static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { + // Who cares +} - render(&render_data, config); - // Make sure our render call will actually be displayed on the screen - wl_dispatch_events(); +static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, + uint32_t axis_source) { + // Who cares +} - if (verify_password()) { - exit(0); - } +static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, + uint32_t time, uint32_t axis) { + // Who cares +} - render_data.auth_state = AUTH_STATE_INVALID; - redraw_screen = 1; +static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, + uint32_t axis, int32_t discrete) { + // Who cares +} - password_size = 1024; - password = malloc(password_size); - password[0] = '\0'; - break; - case XKB_KEY_BackSpace: - i = strlen(password); - if (i > 0) { - password[i - 1] = '\0'; - render_data.auth_state = AUTH_STATE_BACKSPACE; - redraw_screen = 1; - } - break; - case XKB_KEY_Control_L: - case XKB_KEY_Control_R: - case XKB_KEY_Shift_L: - case XKB_KEY_Shift_R: - case XKB_KEY_Caps_Lock: - case XKB_KEY_Shift_Lock: - case XKB_KEY_Meta_L: - case XKB_KEY_Meta_R: - case XKB_KEY_Alt_L: - case XKB_KEY_Alt_R: - case XKB_KEY_Super_L: - case XKB_KEY_Super_R: - case XKB_KEY_Hyper_L: - case XKB_KEY_Hyper_R: - break; // don't draw screen on modifier keys - case XKB_KEY_Escape: - case XKB_KEY_u: - case XKB_KEY_U: - // clear password buffer on ctrl-u (or escape for i3lock compatibility) - if (sym == XKB_KEY_Escape || xkb_state_mod_name_is_active(registry->input->xkb.state, - XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) { - render_data.auth_state = AUTH_STATE_BACKSPACE; - redraw_screen = 1; - - password_size = 1024; - free(password); - password = malloc(password_size); - password[0] = '\0'; - break; - } - /* fallthrough */ - default: - render_data.auth_state = AUTH_STATE_INPUT; - redraw_screen = 1; - i = strlen(password); - if (i + 1 == password_size) { - password_size += 1024; - password_realloc = realloc(password, password_size); - // reset password if realloc fails. - if (password_realloc == NULL) { - password_size = 1024; - free(password); - password = malloc(password_size); - password[0] = '\0'; - break; - } else { - password = password_realloc; - } - } - password[i] = (char)codepoint; - password[i + 1] = '\0'; - break; - } - if (redraw_screen) { - render(&render_data, config); - wl_dispatch_events(); - // Hide the indicator after a couple of seconds - alarm(5); - } +struct wl_pointer_listener pointer_listener = { + .enter = wl_pointer_enter, + .leave = wl_pointer_leave, + .motion = wl_pointer_motion, + .button = wl_pointer_button, + .axis = wl_pointer_axis, + .frame = wl_pointer_frame, + .axis_source = wl_pointer_axis_source, + .axis_stop = wl_pointer_axis_stop, + .axis_discrete = wl_pointer_axis_discrete, +}; + +static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, + enum wl_seat_capability caps) { + if ((caps & WL_SEAT_CAPABILITY_POINTER)) { + struct wl_pointer *pointer = wl_seat_get_pointer(wl_seat); + wl_pointer_add_listener(pointer, &pointer_listener, NULL); } } -void render_color(struct window *window, uint32_t color) { - cairo_set_source_u32(window->cairo, color); - cairo_paint(window->cairo); +static void seat_handle_name(void *data, struct wl_seat *wl_seat, + const char *name) { + // Who cares } -void render_image(struct window *window, cairo_surface_t *image, enum scaling_mode scaling_mode) { - double width = cairo_image_surface_get_width(image); - double height = cairo_image_surface_get_height(image); - int wwidth = window->width * window->scale; - int wheight = window->height * window->scale; - - switch (scaling_mode) { - case SCALING_MODE_STRETCH: - cairo_scale(window->cairo, - (double) wwidth / width, - (double) wheight / height); - cairo_set_source_surface(window->cairo, image, 0, 0); - break; - case SCALING_MODE_FILL: - { - double window_ratio = (double) wwidth / wheight; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double) wwidth / width; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - 0, - (double) wheight/2 / scale - height/2); - } else { - double scale = (double) wheight / height; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 / scale - width/2, - 0); - } - break; - } - case SCALING_MODE_FIT: - { - double window_ratio = (double) wwidth / wheight; - double bg_ratio = width / height; - - if (window_ratio > bg_ratio) { - double scale = (double) wheight / height; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 / scale - width/2, - 0); - } else { - double scale = (double) wwidth / width; - cairo_scale(window->cairo, scale, scale); - cairo_set_source_surface(window->cairo, image, - 0, - (double) wheight/2 / scale - height/2); - } - break; - } - case SCALING_MODE_CENTER: - cairo_set_source_surface(window->cairo, image, - (double) wwidth/2 - width/2, - (double) wheight/2 - height/2); - break; - case SCALING_MODE_TILE: - { - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); - cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); - cairo_set_source(window->cairo, pattern); - break; - } +const struct wl_seat_listener seat_listener = { + .capabilities = seat_handle_capabilities, + .name = seat_handle_name, +}; + +static void handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) { + struct swaylock_state *state = data; + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->compositor = wl_registry_bind(registry, name, + &wl_compositor_interface, 1); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + state->shm = wl_registry_bind(registry, name, + &wl_shm_interface, 1); + } else if (strcmp(interface, wl_seat_interface.name) == 0) { + struct wl_seat *seat = wl_registry_bind( + registry, name, &wl_seat_interface, 1); + wl_seat_add_listener(seat, &seat_listener, NULL); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + state->layer_shell = wl_registry_bind( + registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + struct swaylock_context *context = + calloc(1, sizeof(struct swaylock_context)); + context->state = state; + context->output = wl_registry_bind(registry, name, + &wl_output_interface, 1); + wl_list_insert(&state->contexts, &context->link); } +} - cairo_paint(window->cairo); +static void handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + // who cares } -cairo_surface_t *load_image(char *image_path) { - cairo_surface_t *image = NULL; +static const struct wl_registry_listener registry_listener = { + .global = handle_global, + .global_remove = handle_global_remove, +}; -#ifdef WITH_GDK_PIXBUF - GError *err = NULL; - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); - if (!pixbuf) { - sway_abort("Failed to load background image: %s", err->message); - } - image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); - g_object_unref(pixbuf); -#else - image = cairo_image_surface_create_from_png(image_path); -#endif //WITH_GDK_PIXBUF - if (!image) { - sway_abort("Failed to read background image."); - } +static struct swaylock_state state; - return image; +static void sigalarm_handler(int sig) { + signal(SIGALRM, SIG_IGN); + // TODO: Hide typing indicator + signal(SIGALRM, sigalarm_handler); } int main(int argc, char **argv) { - const char *scaling_mode_str = "fit", *socket_path = NULL; - int i; - void *images = NULL; - config = init_config(); - - render_data.num_images = 0; - render_data.color_set = 0; - render_data.color = 0xFFFFFFFF; - render_data.auth_state = AUTH_STATE_IDLE; - - init_log(L_INFO); - // Install SIGALARM handler (for hiding the typing indicator) signal(SIGALRM, sigalarm_handler); static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"color", required_argument, NULL, 'c'}, {"image", required_argument, NULL, 'i'}, - {"scaling", required_argument, NULL, 0}, + {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, {"socket", required_argument, NULL, 'p'}, {"no-unlock-indicator", no_argument, NULL, 'u'}, {"daemonize", no_argument, NULL, 'f'}, - {"font", required_argument, NULL, 0}, - {"line-uses-ring", no_argument, NULL, 'r'}, - {"line-uses-inside", no_argument, NULL, 's'}, - {"textcolor", required_argument, NULL, 0}, - {"insidevercolor", required_argument, NULL, 0}, - {"insidewrongcolor", required_argument, NULL, 0}, - {"insidecolor", required_argument, NULL, 0}, - {"ringvercolor", required_argument, NULL, 0}, - {"ringwrongcolor", required_argument, NULL, 0}, - {"ringcolor", required_argument, NULL, 0}, - {"linecolor", required_argument, NULL, 0}, - {"separatorcolor", required_argument, NULL, 0}, - {"keyhlcolor", required_argument, NULL, 0}, - {"bshlcolor", required_argument, NULL, 0}, - {"indicator-radius", required_argument, NULL, 0}, - {"indicator-thickness", required_argument, NULL, 0}, {0, 0, 0, 0} }; @@ -390,415 +238,109 @@ int main(int argc, char **argv) { "\n" " -h, --help Show help message and quit.\n" " -c, --color Turn the screen into the given color instead of white.\n" - " --scaling Scaling mode: stretch, fill, fit, center, tile.\n" + " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" " -t, --tiling Same as --scaling=tile.\n" " -v, --version Show the version number and quit.\n" " -i, --image [:] Display the given image.\n" " -u, --no-unlock-indicator Disable the unlock indicator.\n" - " -f, --daemonize Detach from the controlling terminal.\n" - " --socket Use the specified socket.\n" - " For more information see `man swaylock`\n"; - + " -f, --daemonize Detach from the controlling terminal.\n" + " --socket Use the specified socket.\n"; - registry = registry_poll(); + struct swaylock_args args = { + .mode = BACKGROUND_MODE_SOLID_COLOR, + .color = 0xFFFFFFFF, + .show_indicator = true, + }; + state.args = args; + wlr_log_init(L_DEBUG, NULL); int c; while (1) { int option_index = 0; - c = getopt_long(argc, argv, "hc:i:srtvuf", long_options, &option_index); + c = getopt_long(argc, argv, "hc:i:s:tvuf", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 'c': - { - render_data.color = parse_color(optarg); - render_data.color_set = 1; + case 'c': { + state.args.color = parse_color(optarg); + state.args.mode = BACKGROUND_MODE_SOLID_COLOR; break; } case 'i': - { - char *image_path = strchr(optarg, ':'); - if (image_path == NULL) { - if (render_data.num_images == 0) { - // Provided image without output - render_data.image = load_image(optarg); - render_data.num_images = -1; - } else { - sway_log(L_ERROR, "output must be defined for all --images or no --images"); - exit(EXIT_FAILURE); - } - } else { - // Provided image for all outputs - if (render_data.num_images == 0) { - images = calloc(registry->outputs->length, sizeof(char*) * 2); - } else if (render_data.num_images == -1) { - sway_log(L_ERROR, "output must be defined for all --images or no --images"); - exit(EXIT_FAILURE); - } - - image_path[0] = '\0'; - ((char**) images)[render_data.num_images * 2] = optarg; - ((char**) images)[render_data.num_images++ * 2 + 1] = ++image_path; + // TODO + return 1; + case 's': + state.args.mode = parse_background_mode(optarg); + if (state.args.mode == BACKGROUND_MODE_INVALID) { + return 1; } break; - } case 't': - scaling_mode_str = "tile"; - break; - case 'p': - socket_path = optarg; + // TODO break; case 'v': - fprintf(stdout, "swaylock version " SWAY_VERSION "\n"); - exit(EXIT_SUCCESS); - break; +#if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE + fprintf(stdout, "swaylock version %s (%s, branch \"%s\")\n", + SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); +#else + fprintf(stdout, "version unknown\n"); +#endif + return 0; case 'u': - show_indicator = false; - break; - case 'f': { - pid_t t = fork(); - if (t == -1) { - sway_log(L_ERROR, "daemon call failed"); - exit(EXIT_FAILURE); - } else if (t > 0) { - exit(0); - } + state.args.show_indicator = false; break; - } - case 'r': - if (line_source != LINE_SOURCE_DEFAULT) { - sway_log(L_ERROR, "line source options conflict"); - exit(EXIT_FAILURE); - } - line_source = LINE_SOURCE_RING; - break; - case 's': - if (line_source != LINE_SOURCE_DEFAULT) { - sway_log(L_ERROR, "line source options conflict"); - exit(EXIT_FAILURE); - } - line_source = LINE_SOURCE_INSIDE; - break; - case 0: - if (strcmp(long_options[option_index].name, "font") == 0) { - free(config->font); - config->font = strdup(optarg); - } else if (strcmp(long_options[option_index].name, "scaling") == 0) { - scaling_mode_str = optarg; - } else if (strcmp(long_options[option_index].name, "textcolor") == 0) { - config->colors.text = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "insidevercolor") == 0) { - config->colors.validating.inner_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "insidewrongcolor") == 0) { - config->colors.invalid.inner_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "insidecolor") == 0) { - config->colors.normal.inner_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "ringvercolor") == 0) { - config->colors.validating.outer_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "ringwrongcolor") == 0) { - config->colors.invalid.outer_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "ringcolor") == 0) { - config->colors.normal.outer_ring = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "linecolor") == 0) { - config->colors.line = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "separatorcolor") == 0) { - config->colors.separator = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "keyhlcolor") == 0) { - config->colors.input_cursor = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "bshlcolor") == 0) { - config->colors.backspace_cursor = parse_color(optarg); - } else if (strcmp(long_options[option_index].name, "indicator-radius") == 0) { - config->radius = atoi(optarg); - } else if (strcmp(long_options[option_index].name, "indicator-thickness") == 0) { - config->thickness = atoi(optarg); - } + case 'f': + daemonize(); break; default: fprintf(stderr, "%s", usage); - exit(EXIT_FAILURE); + return 1; } } - render_data.scaling_mode = SCALING_MODE_STRETCH; - if (strcmp(scaling_mode_str, "stretch") == 0) { - render_data.scaling_mode = SCALING_MODE_STRETCH; - } else if (strcmp(scaling_mode_str, "fill") == 0) { - render_data.scaling_mode = SCALING_MODE_FILL; - } else if (strcmp(scaling_mode_str, "fit") == 0) { - render_data.scaling_mode = SCALING_MODE_FIT; - } else if (strcmp(scaling_mode_str, "center") == 0) { - render_data.scaling_mode = SCALING_MODE_CENTER; - } else if (strcmp(scaling_mode_str, "tile") == 0) { - render_data.scaling_mode = SCALING_MODE_TILE; - } else { - sway_abort("Unsupported scaling mode: %s", scaling_mode_str); - } - - password_size = 1024; - password = malloc(password_size); - password[0] = '\0'; - render_data.surfaces = create_list(); - if (!socket_path) { - socket_path = get_socketpath(); - if (!socket_path) { - sway_abort("Unable to retrieve socket path"); - } - } - - if (!registry) { - sway_abort("Unable to connect to wayland compositor"); - } - - if (!registry->swaylock) { - sway_abort("swaylock requires the compositor to support the swaylock extension."); - } + wl_list_init(&state.contexts); - if (registry->pointer) { - // We don't want swaylock to have a pointer - wl_pointer_destroy(registry->pointer); - registry->pointer = NULL; - } - - for (i = 0; i < registry->outputs->length; ++i) { - struct output_state *output = registry->outputs->items[i]; - struct window *window = window_setup(registry, - output->width, output->height, output->scale, true); - if (!window) { - sway_abort("Failed to create surfaces."); - } - list_add(render_data.surfaces, window); - } - - registry->input->notify = notify_key; - - // Different background for the output - if (render_data.num_images >= 1) { - char **displays_paths = images; - render_data.images = calloc(registry->outputs->length, sizeof(cairo_surface_t*)); - - int socketfd = ipc_open_socket(socket_path); - uint32_t len = 0; - char *outputs = ipc_single_command(socketfd, IPC_GET_OUTPUTS, "", &len); - struct json_object *json_outputs = json_tokener_parse(outputs); - - for (i = 0; i < registry->outputs->length; ++i) { - if (displays_paths[i * 2] != NULL) { - for (int j = 0;; ++j) { - if (j >= json_object_array_length(json_outputs)) { - sway_log(L_ERROR, "%s is not an extant output", displays_paths[i * 2]); - exit(EXIT_FAILURE); - } - - struct json_object *dsp_name, *at_j = json_object_array_get_idx(json_outputs, j); - if (!json_object_object_get_ex(at_j, "name", &dsp_name)) { - sway_abort("output doesn't have a name field"); - } - if (!strcmp(displays_paths[i * 2], json_object_get_string(dsp_name))) { - render_data.images[j] = load_image(displays_paths[i * 2 + 1]); - break; - } - } - } - } + assert(state.display = wl_display_connect(NULL)); - json_object_put(json_outputs); - close(socketfd); - free(displays_paths); - } + struct wl_registry *registry = wl_display_get_registry(state.display); + wl_registry_add_listener(registry, ®istry_listener, &state); + wl_display_roundtrip(state.display); + assert(state.compositor && state.layer_shell && state.shm); - render(&render_data, config); - bool locked = false; - while (wl_display_dispatch(registry->display) != -1) { - if (!locked) { - for (i = 0; i < registry->outputs->length; ++i) { - struct output_state *output = registry->outputs->items[i]; - struct window *window = render_data.surfaces->items[i]; - lock_set_lock_surface(registry->swaylock, output->output, window->surface); - } - locked = true; - } + if (wl_list_empty(&state.contexts)) { + wlr_log(L_DEBUG, "Exiting - no outputs to show on."); + return 0; } - // Free surfaces - if (render_data.num_images == -1) { - cairo_surface_destroy(render_data.image); - } else if (render_data.num_images >= 1) { - for (i = 0; i < registry->outputs->length; ++i) { - if (render_data.images[i] != NULL) { - cairo_surface_destroy(render_data.images[i]); - } - } - free(render_data.images); + struct swaylock_context *context; + wl_list_for_each(context, &state.contexts, link) { + assert(context->surface = + wl_compositor_create_surface(state.compositor)); + + context->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state.layer_shell, context->surface, context->output, + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); + assert(context->layer_surface); + + zwlr_layer_surface_v1_set_size(context->layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(context->layer_surface, + ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | + ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | + ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); + zwlr_layer_surface_v1_set_exclusive_zone(context->layer_surface, -1); + zwlr_layer_surface_v1_set_keyboard_interactivity( + context->layer_surface, true); + zwlr_layer_surface_v1_add_listener(context->layer_surface, + &layer_surface_listener, context); + wl_surface_commit(context->surface); + wl_display_roundtrip(state.display); } - for (i = 0; i < render_data.surfaces->length; ++i) { - struct window *window = render_data.surfaces->items[i]; - window_teardown(window); + state.run_display = true; + while (wl_display_dispatch(state.display) != -1 && state.run_display) { + // This space intentionally left blank } - list_free(render_data.surfaces); - registry_teardown(registry); - - free_config(config); - return 0; } - -void render(struct render_data *render_data, struct lock_config *config) { - int i; - for (i = 0; i < render_data->surfaces->length; ++i) { - sway_log(L_DEBUG, "Render surface %d of %d", i, render_data->surfaces->length); - struct window *window = render_data->surfaces->items[i]; - if (!window_prerender(window) || !window->cairo) { - continue; - } - int wwidth = window->width * window->scale; - int wheight = window->height * window->scale; - - cairo_save(window->cairo); - cairo_set_operator(window->cairo, CAIRO_OPERATOR_CLEAR); - cairo_paint(window->cairo); - cairo_restore(window->cairo); - - // Reset the transformation matrix - cairo_identity_matrix(window->cairo); - - if (render_data->num_images == 0 || render_data->color_set) { - render_color(window, render_data->color); - } - - if (render_data->num_images == -1) { - // One background for all - render_image(window, render_data->image, render_data->scaling_mode); - } else if (render_data->num_images >= 1) { - // Different backgrounds - if (render_data->images[i] != NULL) { - render_image(window, render_data->images[i], render_data->scaling_mode); - } - } - - // Reset the transformation matrix again - cairo_identity_matrix(window->cairo); - - // Draw specific values (copied from i3) - const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; - const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; - - // Add visual indicator - if (show_indicator && render_data->auth_state != AUTH_STATE_IDLE) { - // Draw circle - cairo_set_line_width(window->cairo, config->thickness); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, 0, 2 * M_PI); - switch (render_data->auth_state) { - case AUTH_STATE_INPUT: - case AUTH_STATE_BACKSPACE: { - cairo_set_source_u32(window->cairo, config->colors.normal.inner_ring); - cairo_fill_preserve(window->cairo); - cairo_set_source_u32(window->cairo, config->colors.normal.outer_ring); - cairo_stroke(window->cairo); - } break; - case AUTH_STATE_VALIDATING: { - cairo_set_source_u32(window->cairo, config->colors.validating.inner_ring); - cairo_fill_preserve(window->cairo); - cairo_set_source_u32(window->cairo, config->colors.validating.outer_ring); - cairo_stroke(window->cairo); - } break; - case AUTH_STATE_INVALID: { - cairo_set_source_u32(window->cairo, config->colors.invalid.inner_ring); - cairo_fill_preserve(window->cairo); - cairo_set_source_u32(window->cairo, config->colors.invalid.outer_ring); - cairo_stroke(window->cairo); - } break; - default: break; - } - - // Draw a message - char *text = NULL; - cairo_set_source_u32(window->cairo, config->colors.text); - cairo_select_font_face(window->cairo, config->font, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - cairo_set_font_size(window->cairo, config->radius/3.0f); - switch (render_data->auth_state) { - case AUTH_STATE_VALIDATING: - text = "verifying"; - break; - case AUTH_STATE_INVALID: - text = "wrong"; - break; - default: break; - } - - if (text) { - cairo_text_extents_t extents; - double x, y; - - cairo_text_extents(window->cairo, text, &extents); - x = wwidth/2 - ((extents.width/2) + extents.x_bearing); - y = wheight/2 - ((extents.height/2) + extents.y_bearing); - - cairo_move_to(window->cairo, x, y); - cairo_show_text(window->cairo, text); - cairo_close_path(window->cairo); - cairo_new_sub_path(window->cairo); - } - - // Typing indicator: Highlight random part on keypress - if (render_data->auth_state == AUTH_STATE_INPUT || render_data->auth_state == AUTH_STATE_BACKSPACE) { - static double highlight_start = 0; - highlight_start += (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_RANGE); - if (render_data->auth_state == AUTH_STATE_INPUT) { - cairo_set_source_u32(window->cairo, config->colors.input_cursor); - } else { - cairo_set_source_u32(window->cairo, config->colors.backspace_cursor); - } - cairo_stroke(window->cairo); - - // Draw borders - cairo_set_source_u32(window->cairo, config->colors.separator); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start, highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); - cairo_stroke(window->cairo); - - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius, highlight_start + TYPE_INDICATOR_RANGE, (highlight_start + TYPE_INDICATOR_RANGE) + TYPE_INDICATOR_BORDER_THICKNESS); - cairo_stroke(window->cairo); - } - - switch(line_source) { - case LINE_SOURCE_RING: - switch(render_data->auth_state) { - case AUTH_STATE_VALIDATING: - cairo_set_source_u32(window->cairo, config->colors.validating.outer_ring); - break; - case AUTH_STATE_INVALID: - cairo_set_source_u32(window->cairo, config->colors.invalid.outer_ring); - break; - default: - cairo_set_source_u32(window->cairo, config->colors.normal.outer_ring); - } - break; - case LINE_SOURCE_INSIDE: - switch(render_data->auth_state) { - case AUTH_STATE_VALIDATING: - cairo_set_source_u32(window->cairo, config->colors.validating.inner_ring); - break; - case AUTH_STATE_INVALID: - cairo_set_source_u32(window->cairo, config->colors.invalid.inner_ring); - break; - default: - cairo_set_source_u32(window->cairo, config->colors.normal.inner_ring); - break; - } - break; - default: - cairo_set_source_u32(window->cairo, config->colors.line); - break; - } - // Draw inner + outer border of the circle - cairo_set_line_width(window->cairo, 2.0); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius - config->thickness/2, 0, 2*M_PI); - cairo_stroke(window->cairo); - cairo_arc(window->cairo, wwidth/2, wheight/2, config->radius + config->thickness/2, 0, 2*M_PI); - cairo_stroke(window->cairo); - } - window_render(window); - } -} diff --git a/swaylock/meson.build b/swaylock/meson.build new file mode 100644 index 00000000..5b886ded --- /dev/null +++ b/swaylock/meson.build @@ -0,0 +1,18 @@ +executable( + 'swaylock', + 'main.c', + include_directories: [sway_inc], + dependencies: [ + cairo, + client_protos, + gdk_pixbuf, + libpam, + math, + pango, + pangocairo, + wayland_client, + wlroots, + ], + link_with: [lib_sway_common, lib_sway_client], + install: true +) -- cgit v1.2.3 From 066143adef7adc6e76e43e1990db2f75fe984b42 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 14:31:30 -0400 Subject: Add password buffer, refactor rendering/surfaces --- common/meson.build | 1 + common/unicode.c | 101 ++++++++++++++++++++++++++++++++++++++++++++ include/swaylock/swaylock.h | 15 ++++++- include/unicode.h | 33 +++++++++++++++ swaylock/main.c | 79 ++++++++++++++-------------------- swaylock/meson.build | 2 + swaylock/password.c | 57 +++++++++++++++++++++++++ swaylock/render.c | 21 +++++++++ swaylock/seat.c | 4 +- 9 files changed, 262 insertions(+), 51 deletions(-) create mode 100644 common/unicode.c create mode 100644 include/unicode.h create mode 100644 swaylock/password.c create mode 100644 swaylock/render.c (limited to 'common') diff --git a/common/meson.build b/common/meson.build index 851e7bbf..44a29508 100644 --- a/common/meson.build +++ b/common/meson.build @@ -9,6 +9,7 @@ lib_sway_common = static_library( 'pango.c', 'readline.c', 'stringop.c', + 'unicode.c', 'util.c' ), dependencies: [ diff --git a/common/unicode.c b/common/unicode.c new file mode 100644 index 00000000..38a9b48e --- /dev/null +++ b/common/unicode.c @@ -0,0 +1,101 @@ +#include +#include +#include "unicode.h" + +size_t utf8_chsize(uint32_t ch) { + if (ch < 0x80) { + return 1; + } else if (ch < 0x800) { + return 2; + } else if (ch < 0x10000) { + return 3; + } + return 4; +} + +static const uint8_t masks[] = { + 0x7F, + 0x1F, + 0x0F, + 0x07, + 0x03, + 0x01 +}; + +uint32_t utf8_decode(const char **char_str) { + uint8_t **s = (uint8_t **)char_str; + + uint32_t cp = 0; + if (**s < 128) { + // shortcut + cp = **s; + ++*s; + return cp; + } + int size = utf8_size((char *)*s); + if (size == -1) { + ++*s; + return UTF8_INVALID; + } + uint8_t mask = masks[size - 1]; + cp = **s & mask; + ++*s; + while (--size) { + cp <<= 6; + cp |= **s & 0x3f; + ++*s; + } + return cp; +} + +size_t utf8_encode(char *str, uint32_t ch) { + size_t len = 0; + uint8_t first; + + if (ch < 0x80) { + first = 0; + len = 1; + } else if (ch < 0x800) { + first = 0xc0; + len = 2; + } else if (ch < 0x10000) { + first = 0xe0; + len = 3; + } else { + first = 0xf0; + len = 4; + } + + for (size_t i = len - 1; i > 0; --i) { + str[i] = (ch & 0x3f) | 0x80; + ch >>= 6; + } + + str[0] = ch | first; + return len; +} + + +static const struct { + uint8_t mask; + uint8_t result; + int octets; +} sizes[] = { + { 0x80, 0x00, 1 }, + { 0xE0, 0xC0, 2 }, + { 0xF0, 0xE0, 3 }, + { 0xF8, 0xF0, 4 }, + { 0xFC, 0xF8, 5 }, + { 0xFE, 0xF8, 6 }, + { 0x80, 0x80, -1 }, +}; + +int utf8_size(const char *s) { + uint8_t c = (uint8_t)*s; + for (size_t i = 0; i < sizeof(sizes) / 2; ++i) { + if ((c & sizes[i].mask) == sizes[i].result) { + return sizes[i].octets; + } + } + return -1; +} diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index e2673aae..f3b0b58b 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -15,18 +15,25 @@ struct swaylock_args { bool show_indicator; }; +struct swaylock_password { + size_t size; + size_t len; + char *buffer; +}; + struct swaylock_state { struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; struct wl_shm *shm; - struct wl_list contexts; + struct wl_list surfaces; struct swaylock_args args; + struct swaylock_password password; struct swaylock_xkb xkb; bool run_display; }; -struct swaylock_context { +struct swaylock_surface { cairo_surface_t *image; struct swaylock_state *state; struct wl_output *output; @@ -38,4 +45,8 @@ struct swaylock_context { struct wl_list link; }; +void swaylock_handle_key(struct swaylock_state *state, + xkb_keysym_t keysym, uint32_t codepoint); +void render_frame(struct swaylock_surface *surface); + #endif diff --git a/include/unicode.h b/include/unicode.h new file mode 100644 index 00000000..e2ee9588 --- /dev/null +++ b/include/unicode.h @@ -0,0 +1,33 @@ +#ifndef _SWAY_UNICODE_H +#define _SWAY_UNICODE_H +#include +#include + +// Technically UTF-8 supports up to 6 byte codepoints, but Unicode itself +// doesn't really bother with more than 4. +#define UTF8_MAX_SIZE 4 + +#define UTF8_INVALID 0x80 + +/** + * Grabs the next UTF-8 character and advances the string pointer + */ +uint32_t utf8_decode(const char **str); + +/** + * Encodes a character as UTF-8 and returns the length of that character. + */ +size_t utf8_encode(char *str, uint32_t ch); + +/** + * Returns the size of the next UTF-8 character + */ +int utf8_size(const char *str); + +/** + * Returns the size of a UTF-8 character + */ +size_t utf8_chsize(uint32_t ch); + +#endif + diff --git a/swaylock/main.c b/swaylock/main.c index 7602e47e..c8fdc2f4 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -32,39 +32,22 @@ static void daemonize() { } } -static void render_frame(struct swaylock_context *context) { - struct swaylock_state *state = context->state; - context->current_buffer = get_next_buffer(state->shm, - context->buffers, context->width, context->height); - cairo_t *cairo = context->current_buffer->cairo; - if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { - cairo_set_source_u32(cairo, state->args.color); - cairo_paint(cairo); - } else { - render_background_image(cairo, context->image, - state->args.mode, context->width, context->height); - } - wl_surface_attach(context->surface, context->current_buffer->buffer, 0, 0); - wl_surface_damage(context->surface, 0, 0, context->width, context->height); - wl_surface_commit(context->surface); -} - static void layer_surface_configure(void *data, - struct zwlr_layer_surface_v1 *surface, + struct zwlr_layer_surface_v1 *layer_surface, uint32_t serial, uint32_t width, uint32_t height) { - struct swaylock_context *context = data; - context->width = width; - context->height = height; - zwlr_layer_surface_v1_ack_configure(surface, serial); - render_frame(context); + struct swaylock_surface *surface = data; + surface->width = width; + surface->height = height; + zwlr_layer_surface_v1_ack_configure(layer_surface, serial); + render_frame(surface); } static void layer_surface_closed(void *data, - struct zwlr_layer_surface_v1 *surface) { - struct swaylock_context *context = data; - zwlr_layer_surface_v1_destroy(context->layer_surface); - wl_surface_destroy(context->surface); - context->state->run_display = false; + struct zwlr_layer_surface_v1 *layer_surface) { + struct swaylock_surface *surface = data; + zwlr_layer_surface_v1_destroy(surface->layer_surface); + wl_surface_destroy(surface->surface); + surface->state->run_display = false; } static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { @@ -89,12 +72,12 @@ static void handle_global(void *data, struct wl_registry *registry, state->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); } else if (strcmp(interface, wl_output_interface.name) == 0) { - struct swaylock_context *context = - calloc(1, sizeof(struct swaylock_context)); - context->state = state; - context->output = wl_registry_bind(registry, name, + struct swaylock_surface *surface = + calloc(1, sizeof(struct swaylock_surface)); + surface->state = state; + surface->output = wl_registry_bind(registry, name, &wl_output_interface, 1); - wl_list_insert(&state->contexts, &context->link); + wl_list_insert(&state->surfaces, &surface->link); } } @@ -198,7 +181,7 @@ int main(int argc, char **argv) { } } - wl_list_init(&state.contexts); + wl_list_init(&state.surfaces); state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(state.display = wl_display_connect(NULL)); @@ -207,33 +190,33 @@ int main(int argc, char **argv) { wl_display_roundtrip(state.display); assert(state.compositor && state.layer_shell && state.shm); - if (wl_list_empty(&state.contexts)) { + if (wl_list_empty(&state.surfaces)) { wlr_log(L_DEBUG, "Exiting - no outputs to show on."); return 0; } - struct swaylock_context *context; - wl_list_for_each(context, &state.contexts, link) { - assert(context->surface = + struct swaylock_surface *surface; + wl_list_for_each(surface, &state.surfaces, link) { + assert(surface->surface = wl_compositor_create_surface(state.compositor)); - context->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - state.layer_shell, context->surface, context->output, + surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + state.layer_shell, surface->surface, surface->output, ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen"); - assert(context->layer_surface); + assert(surface->layer_surface); - zwlr_layer_surface_v1_set_size(context->layer_surface, 0, 0); - zwlr_layer_surface_v1_set_anchor(context->layer_surface, + zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0); + zwlr_layer_surface_v1_set_anchor(surface->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); - zwlr_layer_surface_v1_set_exclusive_zone(context->layer_surface, -1); + zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1); zwlr_layer_surface_v1_set_keyboard_interactivity( - context->layer_surface, true); - zwlr_layer_surface_v1_add_listener(context->layer_surface, - &layer_surface_listener, context); - wl_surface_commit(context->surface); + surface->layer_surface, true); + zwlr_layer_surface_v1_add_listener(surface->layer_surface, + &layer_surface_listener, surface); + wl_surface_commit(surface->surface); wl_display_roundtrip(state.display); } diff --git a/swaylock/meson.build b/swaylock/meson.build index 2a1f029a..3cde47a4 100644 --- a/swaylock/meson.build +++ b/swaylock/meson.build @@ -1,6 +1,8 @@ executable( 'swaylock', [ 'main.c', + 'password.c', + 'render.c', 'seat.c' ], include_directories: [sway_inc], diff --git a/swaylock/password.c b/swaylock/password.c new file mode 100644 index 00000000..da67205d --- /dev/null +++ b/swaylock/password.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include "swaylock/swaylock.h" +#include "swaylock/seat.h" +#include "unicode.h" + +static void backspace(struct swaylock_password *pw) { + if (pw->len != 0) { + pw->buffer[--pw->len] = 0; + } +} + +static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { + if (!pw->buffer) { + pw->size = 8; + if (!(pw->buffer = malloc(pw->size))) { + // TODO: Display error + return; + } + pw->buffer[0] = 0; + } + size_t utf8_size = utf8_chsize(codepoint); + if (pw->len + utf8_size + 1 >= pw->size) { + size_t size = pw->size * 2; + char *buffer = realloc(pw->buffer, size); + if (!buffer) { + // TODO: Display error + return; + } + pw->size = size; + pw->buffer = buffer; + } + utf8_encode(&pw->buffer[pw->len], codepoint); + pw->buffer[pw->len + utf8_size] = 0; + pw->len += utf8_size; +} + +void swaylock_handle_key(struct swaylock_state *state, + xkb_keysym_t keysym, uint32_t codepoint) { + switch (keysym) { + case XKB_KEY_KP_Enter: /* fallthrough */ + case XKB_KEY_Return: + // TODO: Attempt password + break; + case XKB_KEY_BackSpace: + backspace(&state->password); + break; + default: + if (codepoint) { + append_ch(&state->password, codepoint); + } + break; + } +} diff --git a/swaylock/render.c b/swaylock/render.c new file mode 100644 index 00000000..8fc47281 --- /dev/null +++ b/swaylock/render.c @@ -0,0 +1,21 @@ +#include +#include "cairo.h" +#include "background-image.h" +#include "swaylock/swaylock.h" + +void render_frame(struct swaylock_surface *surface) { + struct swaylock_state *state = surface->state; + surface->current_buffer = get_next_buffer(state->shm, + surface->buffers, surface->width, surface->height); + cairo_t *cairo = surface->current_buffer->cairo; + if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { + cairo_set_source_u32(cairo, state->args.color); + cairo_paint(cairo); + } else { + render_background_image(cairo, surface->image, + state->args.mode, surface->width, surface->height); + } + wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); + wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); + wl_surface_commit(surface->surface); +} diff --git a/swaylock/seat.c b/swaylock/seat.c index 522200f2..6c46bb41 100644 --- a/swaylock/seat.c +++ b/swaylock/seat.c @@ -73,7 +73,9 @@ static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ? key + 8 : 0; uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode); - wlr_log(L_DEBUG, "%c %d", codepoint, sym); + if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED) { + swaylock_handle_key(state, sym, codepoint); + } } static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, -- cgit v1.2.3 From d053acbed6fea0f73eb79ac800c1342f8afadeb8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Tue, 3 Apr 2018 15:04:31 -0400 Subject: R E N D E R I N G --- common/background-image.c | 3 +- include/swaylock/swaylock.h | 10 ++++ swaylock/main.c | 14 +++-- swaylock/password.c | 20 ++++++-- swaylock/render.c | 121 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 159 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/background-image.c b/common/background-image.c index 1a6c0df0..e5fb4433 100644 --- a/common/background-image.c +++ b/common/background-image.c @@ -28,7 +28,8 @@ cairo_surface_t *load_background_image(const char *path) { GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); if (!pixbuf) { - wlr_log(L_ERROR, "Failed to load background image."); + wlr_log(L_ERROR, "Failed to load background image (%s).", + err->message); return false; } image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); diff --git a/include/swaylock/swaylock.h b/include/swaylock/swaylock.h index f3b0b58b..ddca633d 100644 --- a/include/swaylock/swaylock.h +++ b/include/swaylock/swaylock.h @@ -9,6 +9,14 @@ #include "swaylock/seat.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h" +enum auth_state { + AUTH_STATE_IDLE, + AUTH_STATE_INPUT, + AUTH_STATE_BACKSPACE, + AUTH_STATE_VALIDATING, + AUTH_STATE_INVALID, +}; + struct swaylock_args { uint32_t color; enum background_mode mode; @@ -30,6 +38,7 @@ struct swaylock_state { struct swaylock_args args; struct swaylock_password password; struct swaylock_xkb xkb; + enum auth_state auth_state; bool run_display; }; @@ -48,5 +57,6 @@ struct swaylock_surface { void swaylock_handle_key(struct swaylock_state *state, xkb_keysym_t keysym, uint32_t codepoint); void render_frame(struct swaylock_surface *surface); +void render_frames(struct swaylock_state *state); #endif diff --git a/swaylock/main.c b/swaylock/main.c index c8fdc2f4..ce337e24 100644 --- a/swaylock/main.c +++ b/swaylock/main.c @@ -133,6 +133,7 @@ int main(int argc, char **argv) { .color = 0xFFFFFFFF, .show_indicator = true, }; + cairo_surface_t *background_image = NULL; state.args = args; wlr_log_init(L_DEBUG, NULL); @@ -150,8 +151,13 @@ int main(int argc, char **argv) { break; } case 'i': - // TODO - return 1; + // TODO: Multiple background images (bleh) + background_image = load_background_image(optarg); + if (!background_image) { + return 1; + } + state.args.mode = BACKGROUND_MODE_FILL; + break; case 's': state.args.mode = parse_background_mode(optarg); if (state.args.mode == BACKGROUND_MODE_INVALID) { @@ -159,7 +165,7 @@ int main(int argc, char **argv) { } break; case 't': - // TODO + state.args.mode = BACKGROUND_MODE_TILE; break; case 'v': #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE @@ -197,6 +203,8 @@ int main(int argc, char **argv) { struct swaylock_surface *surface; wl_list_for_each(surface, &state.surfaces, link) { + surface->image = background_image; + assert(surface->surface = wl_compositor_create_surface(state.compositor)); diff --git a/swaylock/password.c b/swaylock/password.c index 9af7fe16..2bdf151f 100644 --- a/swaylock/password.c +++ b/swaylock/password.c @@ -50,21 +50,23 @@ static bool attempt_password(struct swaylock_password *pw) { wlr_log(L_ERROR, "pam_end failed"); goto fail; } - // PAM freed this + // PAM frees this pw->buffer = NULL; pw->len = pw->size = 0; return true; fail: - // PAM freed this + // PAM frees this pw->buffer = NULL; pw->len = pw->size = 0; return false; } -static void backspace(struct swaylock_password *pw) { +static bool backspace(struct swaylock_password *pw) { if (pw->len != 0) { pw->buffer[--pw->len] = 0; + return true; } + return false; } static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { @@ -97,17 +99,27 @@ void swaylock_handle_key(struct swaylock_state *state, switch (keysym) { case XKB_KEY_KP_Enter: /* fallthrough */ case XKB_KEY_Return: + state->auth_state = AUTH_STATE_VALIDATING; + render_frames(state); if (attempt_password(&state->password)) { exit(0); } + state->auth_state = AUTH_STATE_INVALID; + render_frames(state); break; case XKB_KEY_BackSpace: - backspace(&state->password); + if (backspace(&state->password)) { + state->auth_state = AUTH_STATE_BACKSPACE; + render_frames(state); + } break; default: if (codepoint) { append_ch(&state->password, codepoint); + state->auth_state = AUTH_STATE_INPUT; + render_frames(state); } break; } + // TODO: Expire state in a few seconds } diff --git a/swaylock/render.c b/swaylock/render.c index 8fc47281..90db71e3 100644 --- a/swaylock/render.c +++ b/swaylock/render.c @@ -1,21 +1,140 @@ #include +#include #include "cairo.h" #include "background-image.h" #include "swaylock/swaylock.h" +#define M_PI 3.14159265358979323846 + void render_frame(struct swaylock_surface *surface) { struct swaylock_state *state = surface->state; surface->current_buffer = get_next_buffer(state->shm, surface->buffers, surface->width, surface->height); cairo_t *cairo = surface->current_buffer->cairo; + cairo_identity_matrix(cairo); if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { cairo_set_source_u32(cairo, state->args.color); cairo_paint(cairo); } else { + // TODO: hidpi render_background_image(cairo, surface->image, - state->args.mode, surface->width, surface->height); + state->args.mode, surface->width, surface->height, 1); + } + cairo_identity_matrix(cairo); + + const int ARC_RADIUS = 50; + const int ARC_THICKNESS = 10; + const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; + const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; + if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { + // Draw circle + cairo_set_line_width(cairo, ARC_THICKNESS); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, 0, 2 * M_PI); + switch (state->auth_state) { + case AUTH_STATE_INPUT: + case AUTH_STATE_BACKSPACE: { + cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 51.0 / 255, 125.0 / 255, 0); + cairo_stroke(cairo); + } break; + case AUTH_STATE_VALIDATING: { + cairo_set_source_rgba(cairo, 0, 114.0 / 255, 255.0 / 255, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 51.0 / 255, 0, 250.0 / 255); + cairo_stroke(cairo); + } break; + case AUTH_STATE_INVALID: { + cairo_set_source_rgba(cairo, 250.0 / 255, 0, 0, 0.75); + cairo_fill_preserve(cairo); + cairo_set_source_rgb(cairo, 125.0 / 255, 51.0 / 255, 0); + cairo_stroke(cairo); + } break; + default: break; + } + + // Draw a message + char *text = NULL; + cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_select_font_face(cairo, "sans-serif", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size(cairo, ARC_RADIUS / 3.0f); + switch (state->auth_state) { + case AUTH_STATE_VALIDATING: + text = "verifying"; + break; + case AUTH_STATE_INVALID: + text = "wrong"; + break; + default: break; + } + + if (text) { + cairo_text_extents_t extents; + double x, y; + cairo_text_extents(cairo, text, &extents); + x = (surface->width / 2) - + (extents.width / 2 + extents.x_bearing); + y = (surface->height / 2) - + (extents.height / 2 + extents.y_bearing); + + cairo_move_to(cairo, x, y); + cairo_show_text(cairo, text); + cairo_close_path(cairo); + cairo_new_sub_path(cairo); + } + + // Typing indicator: Highlight random part on keypress + if (state->auth_state == AUTH_STATE_INPUT + || state->auth_state == AUTH_STATE_BACKSPACE) { + static double highlight_start = 0; + highlight_start += + (rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, highlight_start, + highlight_start + TYPE_INDICATOR_RANGE); + if (state->auth_state == AUTH_STATE_INPUT) { + cairo_set_source_rgb(cairo, 51.0 / 255, 219.0 / 255, 0); + } else { + cairo_set_source_rgb(cairo, 219.0 / 255, 51.0 / 255, 0); + } + cairo_stroke(cairo); + + // Draw borders + cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, highlight_start, + highlight_start + TYPE_INDICATOR_BORDER_THICKNESS); + cairo_stroke(cairo); + + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS, highlight_start + TYPE_INDICATOR_RANGE, + highlight_start + TYPE_INDICATOR_RANGE + + TYPE_INDICATOR_BORDER_THICKNESS); + cairo_stroke(cairo); + } + + // Draw inner + outer border of the circle + cairo_set_source_rgb(cairo, 0, 0, 0); + cairo_set_line_width(cairo, 2.0); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS - ARC_THICKNESS / 2, 0, 2 * M_PI); + cairo_stroke(cairo); + cairo_arc(cairo, surface->width / 2, surface->height / 2, + ARC_RADIUS + ARC_THICKNESS / 2, 0, 2 * M_PI); + cairo_stroke(cairo); } + wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); wl_surface_commit(surface->surface); + wl_display_roundtrip(state->display); +} + +void render_frames(struct swaylock_state *state) { + struct swaylock_surface *surface; + wl_list_for_each(surface, &state->surfaces, link) { + render_frame(surface); + } } -- cgit v1.2.3