From e7411abc88f22b0d91d82cbcac9fbb18d76269b5 Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 20 Jul 2025 00:13:29 +0300 Subject: [PATCH 01/21] feat: language widget implementation --- meson.build | 1 + proto/wayfire-shell-unstable-v2.xml | 26 +++++++ src/panel/meson.build | 3 +- src/panel/panel.cpp | 16 +++- src/panel/panel.hpp | 3 +- src/panel/widgets/language.cpp | 112 ++++++++++++++++++++++++++++ src/panel/widgets/language.hpp | 39 ++++++++++ src/util/wf-shell-app.cpp | 26 ++++++- src/util/wf-shell-app.hpp | 18 ++++- wf-shell.ini.example | 2 +- 10 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 src/panel/widgets/language.cpp create mode 100644 src/panel/widgets/language.hpp diff --git a/meson.build b/meson.build index 147c4e35..96347a6d 100644 --- a/meson.build +++ b/meson.build @@ -22,6 +22,7 @@ gtklayershell = dependency('gtk-layer-shell-0', version: '>= 0.6', fallback: [' libpulse = dependency('libpulse', required : get_option('pulse')) dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4') libgvc = subproject('gvc', default_options: ['static=true'], required : get_option('pulse')) +xkbregistry = dependency('xkbregistry') if get_option('wayland-logout') == true wayland_logout = subproject('wayland-logout') diff --git a/proto/wayfire-shell-unstable-v2.xml b/proto/wayfire-shell-unstable-v2.xml index a6d1d9d9..505297ce 100644 --- a/proto/wayfire-shell-unstable-v2.xml +++ b/proto/wayfire-shell-unstable-v2.xml @@ -19,6 +19,11 @@ + + + + + @@ -127,4 +132,25 @@ + + + + + + + + + Emmited on layout change and after manager is created, indicating active layout. + + + + + + + Array of available layout names + + + + + diff --git a/src/panel/meson.build b/src/panel/meson.build index 0a511c76..5f5754d1 100644 --- a/src/panel/meson.build +++ b/src/panel/meson.build @@ -2,6 +2,7 @@ widget_sources = ['widgets/battery.cpp', 'widgets/menu.cpp', 'widgets/clock.cpp', 'widgets/command-output.cpp', + 'widgets/language.cpp', 'widgets/launchers.cpp', 'widgets/network.cpp', 'widgets/spacing.cpp', @@ -17,7 +18,7 @@ widget_sources = ['widgets/battery.cpp', 'widgets/tray/item.cpp', 'widgets/tray/host.cpp'] -deps = [gtkmm, wayland_client, libutil, wf_protos, wfconfig, gtklayershell, dbusmenu_gtk] +deps = [gtkmm, wayland_client, libutil, wf_protos, wfconfig, gtklayershell, dbusmenu_gtk, xkbregistry] if libpulse.found() widget_sources += 'widgets/volume.cpp' diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 566dd517..693ec0f7 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -16,8 +15,10 @@ #include "panel.hpp" #include "../util/gtk-utils.hpp" +#include "wf-shell-app.hpp" #include "widgets/battery.hpp" #include "widgets/command-output.hpp" +#include "widgets/language.hpp" #include "widgets/menu.hpp" #include "widgets/clock.hpp" #include "widgets/launchers.hpp" @@ -36,6 +37,7 @@ class WayfirePanel::impl { std::unique_ptr window; + ShellManager shell_manager; Gtk::HBox content_box; Gtk::HBox left_box, center_box, right_box; @@ -226,6 +228,11 @@ class WayfirePanel::impl return Widget(new WfCommandOutputButtons()); } + if (name == "language") + { + return Widget(new WayfireLanguage(shell_manager->get_kbdlayout_manager())); + } + if (auto pixel = widget_with_value(name, "spacing")) { return Widget(new WayfireSpacing(*pixel)); @@ -313,7 +320,7 @@ class WayfirePanel::impl } public: - impl(WayfireOutput *output) : output(output) + impl(WayfireOutput *output, ShellManager shell_manager) : shell_manager(shell_manager), output(output) { create_window(); } @@ -347,8 +354,9 @@ class WayfirePanel::impl } }; -WayfirePanel::WayfirePanel(WayfireOutput *output) : pimpl(new impl(output)) +WayfirePanel::WayfirePanel(WayfireOutput *output, ShellManager shell_manager) : pimpl(new impl(output, shell_manager)) {} + wl_surface*WayfirePanel::get_wl_surface() { return pimpl->get_wl_surface(); @@ -437,7 +445,7 @@ void WayfirePanelApp::add_css_file(std::string file, int priority) void WayfirePanelApp::handle_new_output(WayfireOutput *output) { priv->panels[output] = std::unique_ptr( - new WayfirePanel(output)); + new WayfirePanel(output, this->wf_shell_manager)); } WayfirePanel*WayfirePanelApp::panel_for_wl_output(wl_output *output) diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp index c20f94b9..a17b1b66 100644 --- a/src/panel/panel.hpp +++ b/src/panel/panel.hpp @@ -6,12 +6,13 @@ #include #include +#include "libutil.a.p/wayfire-shell-unstable-v2-client-protocol.h" #include "wf-shell-app.hpp" class WayfirePanel { public: - WayfirePanel(WayfireOutput *output); + WayfirePanel(WayfireOutput *output, ShellManager shell_manager); wl_surface *get_wl_surface(); Gtk::Window& get_window(); diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp new file mode 100644 index 00000000..17454b64 --- /dev/null +++ b/src/panel/widgets/language.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include "language.hpp" +#include "gtkmm/button.h" +#include "libutil.a.p/wayfire-shell-unstable-v2-client-protocol.h" +#include "sigc++/functors/mem_fun.h" + +void WayfireLanguage::init(Gtk::HBox *container) +{ + // button = std::make_unique("panel"); + + button.get_style_context()->add_class("language"); + button.add(label); + button.get_style_context()->add_class("flat"); + button.get_style_context()->remove_class("activated"); + button.signal_clicked().connect_notify(sigc::mem_fun(this, &WayfireLanguage::next_language)); + button.show(); + label.show(); + + update_label(); + + container->pack_start(button, false, false); +} + +bool WayfireLanguage::update_label() +{ + if (current_language >= available.size()) { + return false; + } + + label.set_text(available[current_language].ID); + return true; +} + +static void keyboard_lang_manager_current_layout(void *data, struct zwf_keyboard_lang_manager_v2 *keyboard_lang_manager, const uint32_t id) +{ + auto wf_language = (WayfireLanguage*)data; + wf_language->set_current(id); + wf_language->update_label(); +} + +static void keyboard_lang_manager_available_layouts(void *data, struct zwf_keyboard_lang_manager_v2 *keyboard_lang_manager, wl_array *layouts) +{ + std::vector languages; + std::map names; + char *elem = (char *) layouts->data; + uint32_t index = 0; + while (elem < (char *) layouts->data + layouts->size) { + names[std::string(elem)] = index; + languages.push_back(Language{ + .Name = elem, + .ID = "", + }); + size_t length = strlen(elem) + 1; + elem += length; + index++; + } + + auto context = rxkb_context_new(RXKB_CONTEXT_NO_FLAGS); + rxkb_context_parse_default_ruleset(context); + auto rlayout = rxkb_layout_first(context); + for (; rlayout != NULL; rlayout = rxkb_layout_next(rlayout)) { + auto descr = rxkb_layout_get_description(rlayout); + auto name = names.find(descr); + if (name != names.end()) { + languages[name->second].ID = rxkb_layout_get_brief(rlayout); + } + } + + auto wf_language = (WayfireLanguage*)data; + wf_language->set_available(languages); +} + +static zwf_keyboard_lang_manager_v2_listener listener = { + .current_layout = keyboard_lang_manager_current_layout, + .available_layouts = keyboard_lang_manager_available_layouts, +}; + + +void WayfireLanguage::set_current(uint32_t index) +{ + current_language = index; +} + +void WayfireLanguage::set_available(std::vector languages) +{ + available = languages; +} + +void WayfireLanguage::next_language() +{ + uint32_t next = current_language + 1; + if (next >= available.size()) + { + next = 0; + } + + zwf_keyboard_lang_manager_v2_set_layout(keyboard_lang_manager, next); +} + +WayfireLanguage::WayfireLanguage(zwf_keyboard_lang_manager_v2 *keyboard_lang_manager): keyboard_lang_manager(keyboard_lang_manager) +{ + zwf_keyboard_lang_manager_v2_add_listener(keyboard_lang_manager, &listener, this); +} + +WayfireLanguage::~WayfireLanguage() +{} diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp new file mode 100644 index 00000000..1a91790f --- /dev/null +++ b/src/panel/widgets/language.hpp @@ -0,0 +1,39 @@ +#ifndef WIDGETS_LANGUAGE_HPP +#define WIDGETS_LANGUAGE_HPP + +#include "../widget.hpp" +#include "gtkmm/button.h" +#include "wayfire-shell-unstable-v2-client-protocol.h" +#include +#include +#include +#include +#include +// #include "wayfire-shell-unstable-v2-client-protocol.h" + +struct Language +{ + std::string Name; + std::string ID; +}; + +class WayfireLanguage : public WayfireWidget +{ + Gtk::Label label; + Gtk::Button button; + + zwf_keyboard_lang_manager_v2 *keyboard_lang_manager; + uint32_t current_language; + std::vector available; + + public: + void init(Gtk::HBox *container) override; + bool update_label(); + void set_current(uint32_t index); + void set_available(std::vector languages); + void next_language(); + WayfireLanguage(zwf_keyboard_lang_manager_v2 *kbdlayout_manager); + ~WayfireLanguage(); +}; + +#endif /* end of include guard: WIDGETS_LANGUAGE_HPP */ diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index 7eee3f0a..b68cba06 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -1,4 +1,5 @@ #include "wf-shell-app.hpp" +#include "wayfire-shell-unstable-v2-client-protocol.h" #include #include #include @@ -125,8 +126,9 @@ static void registry_add_object(void *data, struct wl_registry *registry, auto app = static_cast(data); if (strcmp(interface, zwf_shell_manager_v2_interface.name) == 0) { - app->wf_shell_manager = (zwf_shell_manager_v2*)wl_registry_bind(registry, name, + auto shell_manager = (zwf_shell_manager_v2*)wl_registry_bind(registry, name, &zwf_shell_manager_v2_interface, std::min(version, 2u)); + app->wf_shell_manager = std::make_shared(shell_manager); } } @@ -247,15 +249,15 @@ void WayfireShellApp::run() /* -------------------------- WayfireOutput --------------------------------- */ WayfireOutput::WayfireOutput(const GMonitor& monitor, - zwf_shell_manager_v2 *zwf_manager) + ShellManager shell_manager) { this->monitor = monitor; this->wo = gdk_wayland_monitor_get_wl_output(monitor->gobj()); - if (zwf_manager) + if (shell_manager) { this->output = - zwf_shell_manager_v2_get_wf_output(zwf_manager, this->wo); + shell_manager->get_wf_output(this->wo); } else { this->output = nullptr; @@ -274,3 +276,19 @@ sigc::signal WayfireOutput::toggle_menu_signal() { return m_toggle_menu_signal; } + +/* -------------------------- WayfireOutput --------------------------------- */ +WayfireShellManager::WayfireShellManager(zwf_shell_manager_v2 *shell_manager) +{ + this->wf_shell_manager = shell_manager; +} + +zwf_output_v2* WayfireShellManager::get_wf_output(wl_output *output) +{ + return zwf_shell_manager_v2_get_wf_output(this->wf_shell_manager, output); +} + +zwf_keyboard_lang_manager_v2* WayfireShellManager::get_kbdlayout_manager() +{ + return zwf_shell_manager_v2_get_wf_keyboard_lang_manager(this->wf_shell_manager); +} \ No newline at end of file diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index 90f2f2b1..b82511c0 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -1,6 +1,7 @@ #ifndef WF_SHELL_APP_HPP #define WF_SHELL_APP_HPP +#include #include #include #include @@ -11,6 +12,10 @@ #include "wayfire-shell-unstable-v2-client-protocol.h" using GMonitor = Glib::RefPtr; + +struct WayfireShellManager; +using ShellManager = std::shared_ptr; + /** * Represents a single output */ @@ -22,10 +27,19 @@ struct WayfireOutput sigc::signal toggle_menu_signal(); sigc::signal m_toggle_menu_signal; - WayfireOutput(const GMonitor& monitor, zwf_shell_manager_v2 *zwf_manager); + WayfireOutput(const GMonitor& monitor, ShellManager shell_manager); ~WayfireOutput(); }; +struct WayfireShellManager +{ + WayfireShellManager(zwf_shell_manager_v2 *wf_shell_manager); + zwf_output_v2* get_wf_output(wl_output* output); + zwf_keyboard_lang_manager_v2* get_kbdlayout_manager(); + private: + zwf_shell_manager_v2 *wf_shell_manager; +}; + /** * A basic shell application. * @@ -65,7 +79,7 @@ class WayfireShellApp int inotify_fd; int inotify_css_fd; wf::config::config_manager_t config; - zwf_shell_manager_v2 *wf_shell_manager = nullptr; + ShellManager wf_shell_manager; WayfireShellApp(int argc, char **argv); virtual ~WayfireShellApp(); diff --git a/wf-shell.ini.example b/wf-shell.ini.example index d381b4cf..5ac56363 100644 --- a/wf-shell.ini.example +++ b/wf-shell.ini.example @@ -18,7 +18,7 @@ randomize = 0 # Special widgets are "spacing" and "separator" widgets, they can be used to add padding everywhere on the panel # To use them, just append the amount of pixels you want as a padding # to the word "spacing" or "separator" and use it as a plugin -widgets_left = menu spacing4 launchers window-list +widgets_left = menu spacing4 language spacing4 launchers window-list widgets_center = none widgets_right = command-output tray notifications volume network battery clock From 496f77f8880752d41bf783327c3a2a1f72f78405 Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 20 Jul 2025 02:19:08 +0300 Subject: [PATCH 02/21] chore: shell manager method name fix --- src/panel/panel.cpp | 2 +- src/util/wf-shell-app.cpp | 4 ++-- src/util/wf-shell-app.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 693ec0f7..8f4e7364 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -230,7 +230,7 @@ class WayfirePanel::impl if (name == "language") { - return Widget(new WayfireLanguage(shell_manager->get_kbdlayout_manager())); + return Widget(new WayfireLanguage(shell_manager->get_keyboard_land_manager())); } if (auto pixel = widget_with_value(name, "spacing")) diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index b68cba06..c5e2359c 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -277,7 +277,7 @@ sigc::signal WayfireOutput::toggle_menu_signal() return m_toggle_menu_signal; } -/* -------------------------- WayfireOutput --------------------------------- */ +/* -------------------------- WayfireShellManager --------------------------------- */ WayfireShellManager::WayfireShellManager(zwf_shell_manager_v2 *shell_manager) { this->wf_shell_manager = shell_manager; @@ -288,7 +288,7 @@ zwf_output_v2* WayfireShellManager::get_wf_output(wl_output *output) return zwf_shell_manager_v2_get_wf_output(this->wf_shell_manager, output); } -zwf_keyboard_lang_manager_v2* WayfireShellManager::get_kbdlayout_manager() +zwf_keyboard_lang_manager_v2* WayfireShellManager::get_keyboard_land_manager() { return zwf_shell_manager_v2_get_wf_keyboard_lang_manager(this->wf_shell_manager); } \ No newline at end of file diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index b82511c0..24ba7362 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -35,7 +35,7 @@ struct WayfireShellManager { WayfireShellManager(zwf_shell_manager_v2 *wf_shell_manager); zwf_output_v2* get_wf_output(wl_output* output); - zwf_keyboard_lang_manager_v2* get_kbdlayout_manager(); + zwf_keyboard_lang_manager_v2* get_keyboard_land_manager(); private: zwf_shell_manager_v2 *wf_shell_manager; }; From 53e0f5384ae139483638da771e0455f884e0502b Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 20 Jul 2025 02:22:16 +0300 Subject: [PATCH 03/21] chore: fix misspell --- src/panel/panel.cpp | 2 +- src/util/wf-shell-app.cpp | 2 +- src/util/wf-shell-app.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 8f4e7364..046f1f50 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -230,7 +230,7 @@ class WayfirePanel::impl if (name == "language") { - return Widget(new WayfireLanguage(shell_manager->get_keyboard_land_manager())); + return Widget(new WayfireLanguage(shell_manager->get_keyboard_lang_manager())); } if (auto pixel = widget_with_value(name, "spacing")) diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index c5e2359c..2a02ce8b 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -288,7 +288,7 @@ zwf_output_v2* WayfireShellManager::get_wf_output(wl_output *output) return zwf_shell_manager_v2_get_wf_output(this->wf_shell_manager, output); } -zwf_keyboard_lang_manager_v2* WayfireShellManager::get_keyboard_land_manager() +zwf_keyboard_lang_manager_v2* WayfireShellManager::get_keyboard_lang_manager() { return zwf_shell_manager_v2_get_wf_keyboard_lang_manager(this->wf_shell_manager); } \ No newline at end of file diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index 24ba7362..417e5538 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -35,7 +35,7 @@ struct WayfireShellManager { WayfireShellManager(zwf_shell_manager_v2 *wf_shell_manager); zwf_output_v2* get_wf_output(wl_output* output); - zwf_keyboard_lang_manager_v2* get_keyboard_land_manager(); + zwf_keyboard_lang_manager_v2* get_keyboard_lang_manager(); private: zwf_shell_manager_v2 *wf_shell_manager; }; From 2f1113ee7e11e12c456098b66e56ab220232db37 Mon Sep 17 00:00:00 2001 From: WShad Date: Wed, 30 Jul 2025 01:05:09 +0300 Subject: [PATCH 04/21] feat: IPC, language widget on IPC --- data/css/default.css | 12 +++ meson.build | 1 + src/panel/panel.cpp | 13 +-- src/panel/panel.hpp | 4 +- src/panel/widgets/language.cpp | 111 +++++++++---------- src/panel/widgets/language.hpp | 22 ++-- src/util/meson.build | 4 +- src/util/wf-ipc.cpp | 188 +++++++++++++++++++++++++++++++++ src/util/wf-ipc.hpp | 43 ++++++++ src/util/wf-shell-app.cpp | 29 ++--- src/util/wf-shell-app.hpp | 20 +--- 11 files changed, 330 insertions(+), 117 deletions(-) create mode 100644 src/util/wf-ipc.cpp create mode 100644 src/util/wf-ipc.hpp diff --git a/data/css/default.css b/data/css/default.css index fb09b080..448c6021 100644 --- a/data/css/default.css +++ b/data/css/default.css @@ -59,4 +59,16 @@ .wf-panel .command-output.icon-bottom label { padding-bottom: 5px; +} + +.wf-panel .language { + min-width: 48px; +} + +.wf-panel .language label { + background-color: #24283B; + padding: 5px; + margin: 5px; + border-radius: 3px; + color: #41A6B5; } \ No newline at end of file diff --git a/meson.build b/meson.build index 96347a6d..ed55e61d 100644 --- a/meson.build +++ b/meson.build @@ -23,6 +23,7 @@ libpulse = dependency('libpulse', required : get_option('pulse')) dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4') libgvc = subproject('gvc', default_options: ['static=true'], required : get_option('pulse')) xkbregistry = dependency('xkbregistry') +json = dependency('nlohmann_json') if get_option('wayland-logout') == true wayland_logout = subproject('wayland-logout') diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 046f1f50..17003aa4 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -15,7 +16,7 @@ #include "panel.hpp" #include "../util/gtk-utils.hpp" -#include "wf-shell-app.hpp" +#include "wf-ipc.hpp" #include "widgets/battery.hpp" #include "widgets/command-output.hpp" #include "widgets/language.hpp" @@ -37,7 +38,7 @@ class WayfirePanel::impl { std::unique_ptr window; - ShellManager shell_manager; + std::shared_ptr ipc; Gtk::HBox content_box; Gtk::HBox left_box, center_box, right_box; @@ -230,7 +231,7 @@ class WayfirePanel::impl if (name == "language") { - return Widget(new WayfireLanguage(shell_manager->get_keyboard_lang_manager())); + return Widget(new WayfireLanguage(ipc)); } if (auto pixel = widget_with_value(name, "spacing")) @@ -320,7 +321,7 @@ class WayfirePanel::impl } public: - impl(WayfireOutput *output, ShellManager shell_manager) : shell_manager(shell_manager), output(output) + impl(WayfireOutput *output, std::shared_ptr ipc) : ipc(ipc), output(output) { create_window(); } @@ -354,7 +355,7 @@ class WayfirePanel::impl } }; -WayfirePanel::WayfirePanel(WayfireOutput *output, ShellManager shell_manager) : pimpl(new impl(output, shell_manager)) +WayfirePanel::WayfirePanel(WayfireOutput *output, std::shared_ptr ipc) : pimpl(new impl(output, ipc)) {} wl_surface*WayfirePanel::get_wl_surface() @@ -445,7 +446,7 @@ void WayfirePanelApp::add_css_file(std::string file, int priority) void WayfirePanelApp::handle_new_output(WayfireOutput *output) { priv->panels[output] = std::unique_ptr( - new WayfirePanel(output, this->wf_shell_manager)); + new WayfirePanel(output, ipc)); } WayfirePanel*WayfirePanelApp::panel_for_wl_output(wl_output *output) diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp index a17b1b66..2375fba5 100644 --- a/src/panel/panel.hpp +++ b/src/panel/panel.hpp @@ -6,13 +6,13 @@ #include #include -#include "libutil.a.p/wayfire-shell-unstable-v2-client-protocol.h" +#include "wf-ipc.hpp" #include "wf-shell-app.hpp" class WayfirePanel { public: - WayfirePanel(WayfireOutput *output, ShellManager shell_manager); + WayfirePanel(WayfireOutput *output, std::shared_ptr ipc); wl_surface *get_wl_surface(); Gtk::Window& get_window(); diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index 17454b64..e9ef286d 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -1,7 +1,8 @@ +#include #include #include -#include #include +#include #include #include #include @@ -10,55 +11,62 @@ #include "libutil.a.p/wayfire-shell-unstable-v2-client-protocol.h" #include "sigc++/functors/mem_fun.h" -void WayfireLanguage::init(Gtk::HBox *container) -{ - // button = std::make_unique("panel"); - +void WayfireLanguage::init(Gtk::HBox *container) { button.get_style_context()->add_class("language"); button.add(label); button.get_style_context()->add_class("flat"); button.get_style_context()->remove_class("activated"); - button.signal_clicked().connect_notify(sigc::mem_fun(this, &WayfireLanguage::next_language)); + button.signal_clicked().connect_notify(sigc::mem_fun(this, &WayfireLanguage::next_layout)); button.show(); label.show(); - update_label(); + ipc->subscribe(this, {"keyboard-modifier-state-changed"}); + ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=](nlohmann::json data) { + set_available(data["possible-layouts"]); + set_current(data["layout-index"]); + }); container->pack_start(button, false, false); } -bool WayfireLanguage::update_label() -{ - if (current_language >= available.size()) { - return false; +void WayfireLanguage::on_event(nlohmann::json data) { + if (data["event"] == "keyboard-modifier-state-changed") { + if (available_layouts.size() == 0) { + set_available(data["state"]["possible-layouts"]); + } + + auto state_layout = data["state"]["layout-index"]; + if (state_layout != current_layout) { + current_layout = state_layout; + set_current(state_layout); + } } +} - label.set_text(available[current_language].ID); +bool WayfireLanguage::update_label() { + if (current_layout >= available_layouts.size()) { + return false; + } + label.set_text(available_layouts[current_layout].ID); return true; } -static void keyboard_lang_manager_current_layout(void *data, struct zwf_keyboard_lang_manager_v2 *keyboard_lang_manager, const uint32_t id) -{ - auto wf_language = (WayfireLanguage*)data; - wf_language->set_current(id); - wf_language->update_label(); +void WayfireLanguage::set_current(uint32_t index) { + current_layout = index; + update_label(); } -static void keyboard_lang_manager_available_layouts(void *data, struct zwf_keyboard_lang_manager_v2 *keyboard_lang_manager, wl_array *layouts) -{ - std::vector languages; +void WayfireLanguage::set_available(nlohmann::json layouts) { + std::vector layouts_available; std::map names; - char *elem = (char *) layouts->data; - uint32_t index = 0; - while (elem < (char *) layouts->data + layouts->size) { - names[std::string(elem)] = index; - languages.push_back(Language{ - .Name = elem, + + for(size_t i = 0; i < layouts.size(); i++) { + auto elem = layouts[i]; + names[elem] = i; + layouts_available.push_back(Layout{ + .Name = (std::string)elem, .ID = "", }); - size_t length = strlen(elem) + 1; - elem += length; - index++; } auto context = rxkb_context_new(RXKB_CONTEXT_NO_FLAGS); @@ -68,45 +76,30 @@ static void keyboard_lang_manager_available_layouts(void *data, struct zwf_keybo auto descr = rxkb_layout_get_description(rlayout); auto name = names.find(descr); if (name != names.end()) { - languages[name->second].ID = rxkb_layout_get_brief(rlayout); + layouts_available[name->second].ID = rxkb_layout_get_brief(rlayout); } } - auto wf_language = (WayfireLanguage*)data; - wf_language->set_available(languages); -} - -static zwf_keyboard_lang_manager_v2_listener listener = { - .current_layout = keyboard_lang_manager_current_layout, - .available_layouts = keyboard_lang_manager_available_layouts, -}; - - -void WayfireLanguage::set_current(uint32_t index) -{ - current_language = index; -} - -void WayfireLanguage::set_available(std::vector languages) -{ - available = languages; + available_layouts = layouts_available; + update_label(); } -void WayfireLanguage::next_language() -{ - uint32_t next = current_language + 1; - if (next >= available.size()) +void WayfireLanguage::next_layout() { + uint32_t next = current_layout + 1; + if (next >= available_layouts.size()) { next = 0; } - zwf_keyboard_lang_manager_v2_set_layout(keyboard_lang_manager, next); -} - -WayfireLanguage::WayfireLanguage(zwf_keyboard_lang_manager_v2 *keyboard_lang_manager): keyboard_lang_manager(keyboard_lang_manager) -{ - zwf_keyboard_lang_manager_v2_add_listener(keyboard_lang_manager, &listener, this); + nlohmann::json message; + message["method"] = "wayfire/set-keyboard-state"; + message["layout-index"] = next; + ipc->send(message.dump()); } -WayfireLanguage::~WayfireLanguage() +WayfireLanguage::WayfireLanguage(std::shared_ptr ipc): ipc(ipc) {} + +WayfireLanguage::~WayfireLanguage() { + ipc->unsubscribe(this); +} diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp index 1a91790f..7e248666 100644 --- a/src/panel/widgets/language.hpp +++ b/src/panel/widgets/language.hpp @@ -3,36 +3,38 @@ #include "../widget.hpp" #include "gtkmm/button.h" -#include "wayfire-shell-unstable-v2-client-protocol.h" +#include "wf-ipc.hpp" #include #include #include +#include +#include #include #include -// #include "wayfire-shell-unstable-v2-client-protocol.h" -struct Language +struct Layout { std::string Name; std::string ID; }; -class WayfireLanguage : public WayfireWidget +class WayfireLanguage : public WayfireWidget, public IIPCSubscriber { Gtk::Label label; Gtk::Button button; - zwf_keyboard_lang_manager_v2 *keyboard_lang_manager; - uint32_t current_language; - std::vector available; + std::shared_ptr ipc; + uint32_t current_layout; + std::vector available_layouts; public: void init(Gtk::HBox *container) override; + void on_event(nlohmann::json data) override; bool update_label(); void set_current(uint32_t index); - void set_available(std::vector languages); - void next_language(); - WayfireLanguage(zwf_keyboard_lang_manager_v2 *kbdlayout_manager); + void set_available(nlohmann::json layouts); + void next_layout(); + WayfireLanguage(std::shared_ptr ipc); ~WayfireLanguage(); }; diff --git a/src/util/meson.build b/src/util/meson.build index 056f79db..855024a2 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -1,5 +1,5 @@ -util = static_library('util', ['gtk-utils.cpp', 'wf-shell-app.cpp', 'wf-autohide-window.cpp', 'wf-popover.cpp'], - dependencies: [wf_protos, wayland_client, gtkmm, wfconfig, libinotify, gtklayershell]) +util = static_library('util', ['gtk-utils.cpp', 'wf-shell-app.cpp', 'wf-autohide-window.cpp', 'wf-popover.cpp', 'wf-ipc.cpp'], + dependencies: [wf_protos, wayland_client, gtkmm, wfconfig, libinotify, gtklayershell, json]) util_includes = include_directories('.') libutil = declare_dependency( diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp new file mode 100644 index 00000000..3e8e831c --- /dev/null +++ b/src/util/wf-ipc.cpp @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wf-ipc.hpp" +#include "glibmm/iochannel.h" +#include "glibmm/main.h" +#include "sigc++/functors/mem_fun.h" + +WayfireIPC::WayfireIPC(): socket_fd(-1) +{ + connect(); + + auto connection = Glib::signal_io().connect( + sigc::mem_fun(this, &WayfireIPC::receive), socket_fd, Glib::IO_IN + ); +} + +WayfireIPC::~WayfireIPC() +{ + disconnect(); +} + +void WayfireIPC::connect() +{ + const char* socket_path = getenv("WAYFIRE_SOCKET"); + if (socket_path == nullptr) + { + throw std::runtime_error("Wayfire socket not found"); + } + + socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (socket_fd == -1) + { + throw std::runtime_error("Wayfire socket create error"); + } + + if (fcntl(socket_fd, F_SETFL, O_NONBLOCK) == -1) + { + throw std::runtime_error("Wayfire socket set flag error"); + } + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + + if (strlen(socket_path) >= sizeof(addr.sun_path)) + { + throw std::runtime_error("Wayfire socket path too long"); + } + + strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); + if (::connect(socket_fd, (sockaddr*)&addr, sizeof(addr)) == -1) + { + throw std::runtime_error("Wayfire socket connect error"); + } +} + +void WayfireIPC::disconnect() +{ + if (socket_fd != -1) + { + close(socket_fd); + socket_fd = -1; + } +} + +void WayfireIPC::send(const std::string& message) +{ + send_message(message); + response_handlers.push(std::nullopt); +} + +void WayfireIPC::send(const std::string& message, response_handler cb) +{ + send_message(message); + response_handlers.push(cb); +} + +void WayfireIPC::send_message(const std::string& message) +{ + size_t sent = 0; + while (sent < message.size()) { + uint32_t length = message.size(); + auto all_data = std::string((char*)&length, 4); + all_data += message; + ssize_t res = ::send(socket_fd, all_data.data() + sent, + all_data.size() - sent, MSG_NOSIGNAL); + if (res == -1) { + throw std::system_error(errno, std::system_category(), "send failed"); + } + + sent += res; + } +} + +bool WayfireIPC::receive(Glib::IOCondition cond) +{ + uint32_t length; + ssize_t received = ::recv(socket_fd, &length, 4, 0); + if (received == -1) { + throw std::system_error(errno, std::system_category(), "recv failed"); + } + if (received == 0) { + throw std::runtime_error("Connection closed by peer"); + } + + std::string buf(length + 1, 0); + received = ::recv(socket_fd, &buf[0], length, 0); + if (received == -1) { + throw std::system_error(errno, std::system_category(), "recv failed"); + } + if (received == 0) { + throw std::runtime_error("Connection closed by peer"); + } + + auto message = nlohmann::json::parse(buf); + + if (message.contains("event")) { + for (auto subscriber : subscribers) { + subscriber->on_event(message); + } + + if (subscriptions.find(message["event"]) != subscriptions.end()) { + for (auto sub : subscriptions[message["event"]]) { + sub->on_event(message); + } + } + } else { + auto handler = response_handlers.front(); + response_handlers.pop(); + if (handler.has_value()) { + handler.value()(message); + } + } + + return true; +} + +void WayfireIPC::subscribe_all(IIPCSubscriber* subscriber) +{ + subscribers.insert(subscriber); + + nlohmann::json new_subs; + new_subs["method"] = "window-rules/events/watch"; + send(new_subs.dump()); +} + +void WayfireIPC::subscribe(IIPCSubscriber* subscriber, const std::vector& events) +{ + nlohmann::json new_subs; + new_subs["method"] = "window-rules/events/watch"; + new_subs["events"] = nlohmann::json::array(); + + for (auto event : events) { + if (subscriptions.find(event) == subscriptions.end()) { + new_subs["events"].push_back(event); + subscriptions[event] = std::set(); + } + + subscriptions[event].insert(subscriber); + } + + if (new_subs["events"].size() > 0) { + send(new_subs.dump()); + } +} + +void WayfireIPC::unsubscribe(IIPCSubscriber* subscriber) +{ + subscribers.erase(subscriber); + + for (auto& [_, subs] : subscriptions) { + subs.erase(subscriber); + } +} + diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp new file mode 100644 index 00000000..98d33032 --- /dev/null +++ b/src/util/wf-ipc.hpp @@ -0,0 +1,43 @@ +#ifndef WF_IPC_HPP +#define WF_IPC_HPP + +#include "glibmm/iochannel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class IIPCSubscriber { + public: + virtual void on_event(nlohmann::json) = 0; +}; + +using response_handler = std::function; + +class WayfireIPC +{ + int socket_fd; + std::queue> response_handlers; + std::set subscribers; + std::unordered_map> subscriptions; + + void connect(); + void disconnect(); + void send_message(const std::string& message); + bool receive(Glib::IOCondition cond); + public: + void send(const std::string& message); + void send(const std::string& message, response_handler); + void subscribe(IIPCSubscriber* subscriber, const std::vector& events); + void subscribe_all(IIPCSubscriber* subscriber); + void unsubscribe(IIPCSubscriber* subscriber); + WayfireIPC(); + ~WayfireIPC(); +}; + +#endif // WF_IPC_HPP \ No newline at end of file diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index 2a02ce8b..759881a7 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -1,5 +1,5 @@ #include "wf-shell-app.hpp" -#include "wayfire-shell-unstable-v2-client-protocol.h" +#include "wf-ipc.hpp" #include #include #include @@ -126,9 +126,8 @@ static void registry_add_object(void *data, struct wl_registry *registry, auto app = static_cast(data); if (strcmp(interface, zwf_shell_manager_v2_interface.name) == 0) { - auto shell_manager = (zwf_shell_manager_v2*)wl_registry_bind(registry, name, + app->wf_shell_manager = (zwf_shell_manager_v2*)wl_registry_bind(registry, name, &zwf_shell_manager_v2_interface, std::min(version, 2u)); - app->wf_shell_manager = std::make_shared(shell_manager); } } @@ -156,6 +155,8 @@ void WayfireShellApp::on_activate() std::exit(-1); } + ipc = std::make_shared(); + wl_registry *registry = wl_display_get_registry(wl_display); wl_registry_add_listener(registry, ®istry_listener, this); wl_display_roundtrip(wl_display); @@ -249,15 +250,15 @@ void WayfireShellApp::run() /* -------------------------- WayfireOutput --------------------------------- */ WayfireOutput::WayfireOutput(const GMonitor& monitor, - ShellManager shell_manager) + zwf_shell_manager_v2 *zwf_manager) { this->monitor = monitor; this->wo = gdk_wayland_monitor_get_wl_output(monitor->gobj()); - if (shell_manager) + if (zwf_manager) { this->output = - shell_manager->get_wf_output(this->wo); + zwf_shell_manager_v2_get_wf_output(zwf_manager, this->wo); } else { this->output = nullptr; @@ -275,20 +276,4 @@ WayfireOutput::~WayfireOutput() sigc::signal WayfireOutput::toggle_menu_signal() { return m_toggle_menu_signal; -} - -/* -------------------------- WayfireShellManager --------------------------------- */ -WayfireShellManager::WayfireShellManager(zwf_shell_manager_v2 *shell_manager) -{ - this->wf_shell_manager = shell_manager; -} - -zwf_output_v2* WayfireShellManager::get_wf_output(wl_output *output) -{ - return zwf_shell_manager_v2_get_wf_output(this->wf_shell_manager, output); -} - -zwf_keyboard_lang_manager_v2* WayfireShellManager::get_keyboard_lang_manager() -{ - return zwf_shell_manager_v2_get_wf_keyboard_lang_manager(this->wf_shell_manager); } \ No newline at end of file diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index 417e5538..b51f8762 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -1,8 +1,6 @@ #ifndef WF_SHELL_APP_HPP #define WF_SHELL_APP_HPP -#include -#include #include #include @@ -10,12 +8,10 @@ #include #include "wayfire-shell-unstable-v2-client-protocol.h" +#include "wf-ipc.hpp" using GMonitor = Glib::RefPtr; -struct WayfireShellManager; -using ShellManager = std::shared_ptr; - /** * Represents a single output */ @@ -27,19 +23,10 @@ struct WayfireOutput sigc::signal toggle_menu_signal(); sigc::signal m_toggle_menu_signal; - WayfireOutput(const GMonitor& monitor, ShellManager shell_manager); + WayfireOutput(const GMonitor& monitor, zwf_shell_manager_v2 *zwf_manager); ~WayfireOutput(); }; -struct WayfireShellManager -{ - WayfireShellManager(zwf_shell_manager_v2 *wf_shell_manager); - zwf_output_v2* get_wf_output(wl_output* output); - zwf_keyboard_lang_manager_v2* get_keyboard_lang_manager(); - private: - zwf_shell_manager_v2 *wf_shell_manager; -}; - /** * A basic shell application. * @@ -79,7 +66,8 @@ class WayfireShellApp int inotify_fd; int inotify_css_fd; wf::config::config_manager_t config; - ShellManager wf_shell_manager; + zwf_shell_manager_v2 *wf_shell_manager = nullptr; + std::shared_ptr ipc = nullptr; WayfireShellApp(int argc, char **argv); virtual ~WayfireShellApp(); From 219248fb76e90ea17a36c8017d66602e6f45c536 Mon Sep 17 00:00:00 2001 From: WShad Date: Wed, 30 Jul 2025 01:12:45 +0300 Subject: [PATCH 05/21] chore: discard wf-shell proto changes --- proto/wayfire-shell-unstable-v2.xml | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/proto/wayfire-shell-unstable-v2.xml b/proto/wayfire-shell-unstable-v2.xml index 505297ce..a6d1d9d9 100644 --- a/proto/wayfire-shell-unstable-v2.xml +++ b/proto/wayfire-shell-unstable-v2.xml @@ -19,11 +19,6 @@ - - - - - @@ -132,25 +127,4 @@ - - - - - - - - - Emmited on layout change and after manager is created, indicating active layout. - - - - - - - Array of available layout names - - - - - From 5ae10f71e7e01bf56949696217711b3d89bcfcb2 Mon Sep 17 00:00:00 2001 From: WShad Date: Wed, 30 Jul 2025 01:24:29 +0300 Subject: [PATCH 06/21] refactor: removed shared ptr --- src/panel/panel.cpp | 6 +++--- src/panel/panel.hpp | 2 +- src/panel/widgets/language.cpp | 2 +- src/panel/widgets/language.hpp | 5 ++--- src/util/wf-shell-app.cpp | 6 ++++-- src/util/wf-shell-app.hpp | 2 +- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 17003aa4..48fdb581 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -38,7 +38,7 @@ class WayfirePanel::impl { std::unique_ptr window; - std::shared_ptr ipc; + WayfireIPC* ipc; Gtk::HBox content_box; Gtk::HBox left_box, center_box, right_box; @@ -321,7 +321,7 @@ class WayfirePanel::impl } public: - impl(WayfireOutput *output, std::shared_ptr ipc) : ipc(ipc), output(output) + impl(WayfireOutput *output, WayfireIPC *ipc) : ipc(ipc), output(output) { create_window(); } @@ -355,7 +355,7 @@ class WayfirePanel::impl } }; -WayfirePanel::WayfirePanel(WayfireOutput *output, std::shared_ptr ipc) : pimpl(new impl(output, ipc)) +WayfirePanel::WayfirePanel(WayfireOutput *output, WayfireIPC *ipc) : pimpl(new impl(output, ipc)) {} wl_surface*WayfirePanel::get_wl_surface() diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp index 2375fba5..1f658d36 100644 --- a/src/panel/panel.hpp +++ b/src/panel/panel.hpp @@ -12,7 +12,7 @@ class WayfirePanel { public: - WayfirePanel(WayfireOutput *output, std::shared_ptr ipc); + WayfirePanel(WayfireOutput *output, WayfireIPC *ipc); wl_surface *get_wl_surface(); Gtk::Window& get_window(); diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index e9ef286d..bf0615bc 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -97,7 +97,7 @@ void WayfireLanguage::next_layout() { ipc->send(message.dump()); } -WayfireLanguage::WayfireLanguage(std::shared_ptr ipc): ipc(ipc) +WayfireLanguage::WayfireLanguage(WayfireIPC *ipc): ipc(ipc) {} WayfireLanguage::~WayfireLanguage() { diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp index 7e248666..825a0def 100644 --- a/src/panel/widgets/language.hpp +++ b/src/panel/widgets/language.hpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -23,7 +22,7 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber Gtk::Label label; Gtk::Button button; - std::shared_ptr ipc; + WayfireIPC *ipc; uint32_t current_layout; std::vector available_layouts; @@ -34,7 +33,7 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber void set_current(uint32_t index); void set_available(nlohmann::json layouts); void next_layout(); - WayfireLanguage(std::shared_ptr ipc); + WayfireLanguage(WayfireIPC *ipc); ~WayfireLanguage(); }; diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index 759881a7..cdd96b3c 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -155,7 +155,7 @@ void WayfireShellApp::on_activate() std::exit(-1); } - ipc = std::make_shared(); + ipc = new WayfireIPC(); wl_registry *registry = wl_display_get_registry(wl_display); wl_registry_add_listener(registry, ®istry_listener, this); @@ -235,7 +235,9 @@ WayfireShellApp::WayfireShellApp(int argc, char **argv) } WayfireShellApp::~WayfireShellApp() -{} +{ + delete ipc; +} std::unique_ptr WayfireShellApp::instance; WayfireShellApp& WayfireShellApp::get() diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index b51f8762..2c4fe94d 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -67,7 +67,7 @@ class WayfireShellApp int inotify_css_fd; wf::config::config_manager_t config; zwf_shell_manager_v2 *wf_shell_manager = nullptr; - std::shared_ptr ipc = nullptr; + WayfireIPC *ipc = nullptr; WayfireShellApp(int argc, char **argv); virtual ~WayfireShellApp(); From 5d61aaa29c0272dc26e95dbbc82bfcdf9ab5a56c Mon Sep 17 00:00:00 2001 From: WShad Date: Wed, 30 Jul 2025 01:31:23 +0300 Subject: [PATCH 07/21] chore: include removed --- src/panel/widgets/language.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index bf0615bc..98bfbae5 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -8,7 +8,6 @@ #include #include "language.hpp" #include "gtkmm/button.h" -#include "libutil.a.p/wayfire-shell-unstable-v2-client-protocol.h" #include "sigc++/functors/mem_fun.h" void WayfireLanguage::init(Gtk::HBox *container) { From 505f46651e2f747a845489ebf3e8bc4916286d04 Mon Sep 17 00:00:00 2001 From: WShad Date: Thu, 31 Jul 2025 23:34:31 +0300 Subject: [PATCH 08/21] fix: IPC message data --- src/panel/widgets/language.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index 98bfbae5..72e2b9a1 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -92,7 +92,8 @@ void WayfireLanguage::next_layout() { nlohmann::json message; message["method"] = "wayfire/set-keyboard-state"; - message["layout-index"] = next; + message["data"] = nlohmann::json::object(); + message["data"]["layout-index"] = next; ipc->send(message.dump()); } From 2bccb6208c1b96c99e367cbd30d2576e19105f3d Mon Sep 17 00:00:00 2001 From: WShad Date: Fri, 1 Aug 2025 13:24:14 +0300 Subject: [PATCH 09/21] fix: recv interrupt, retry --- src/util/wf-ipc.cpp | 22 ++++++++++++++-------- src/util/wf-ipc.hpp | 2 ++ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index 3e8e831c..f96555ec 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -107,23 +107,29 @@ void WayfireIPC::send_message(const std::string& message) bool WayfireIPC::receive(Glib::IOCondition cond) { - uint32_t length; - ssize_t received = ::recv(socket_fd, &length, 4, 0); - if (received == -1) { - throw std::system_error(errno, std::system_category(), "recv failed"); - } - if (received == 0) { - throw std::runtime_error("Connection closed by peer"); + ssize_t received = 0; + + if (!length_received) + { + received = ::recv(socket_fd, &length, 4, 0); + if (received == -1) { + return true; + } + if (received == 0) { + throw std::runtime_error("Connection closed by peer"); + } } + length_received = true; std::string buf(length + 1, 0); received = ::recv(socket_fd, &buf[0], length, 0); if (received == -1) { - throw std::system_error(errno, std::system_category(), "recv failed"); + return true; } if (received == 0) { throw std::runtime_error("Connection closed by peer"); } + length_received = false; auto message = nlohmann::json::parse(buf); diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index 98d33032..4580db38 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -25,6 +25,8 @@ class WayfireIPC std::queue> response_handlers; std::set subscribers; std::unordered_map> subscriptions; + bool length_received = false; + uint32_t length; void connect(); void disconnect(); From 9e97c5c9d9fd2f3616016ca9e8a468d9314a3400 Mon Sep 17 00:00:00 2001 From: WShad Date: Fri, 14 Nov 2025 14:34:00 +0300 Subject: [PATCH 10/21] GLIBed IPC + shared manager,, yyjson --- meson.build | 10 +- src/panel/panel.cpp | 12 +- src/panel/panel.hpp | 2 +- src/panel/widgets/language.cpp | 80 ++- src/panel/widgets/language.hpp | 14 +- src/util/json.cpp | 679 +++++++++++++++++++ src/util/json.hpp | 168 +++++ src/util/meson.build | 5 +- src/util/wf-ipc.cpp | 290 ++++++--- src/util/wf-ipc.hpp | 76 ++- src/util/wf-shell-app.cpp | 6 +- src/util/wf-shell-app.hpp | 3 +- subprojects/yyjson.wrap | 5 + uncrustify.ini | 1108 ++++++++++++++++++++++++++++++++ 14 files changed, 2288 insertions(+), 170 deletions(-) create mode 100644 src/util/json.cpp create mode 100644 src/util/json.hpp create mode 100644 subprojects/yyjson.wrap create mode 100644 uncrustify.ini diff --git a/meson.build b/meson.build index ed55e61d..c24dea0d 100644 --- a/meson.build +++ b/meson.build @@ -23,7 +23,15 @@ libpulse = dependency('libpulse', required : get_option('pulse')) dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4') libgvc = subproject('gvc', default_options: ['static=true'], required : get_option('pulse')) xkbregistry = dependency('xkbregistry') -json = dependency('nlohmann_json') +json = dependency('yyjson', required: false) + +if not json.found() + cmake = import('cmake') + cmake_opts = cmake.subproject_options() + cmake_opts.add_cmake_defines({'CMAKE_POSITION_INDEPENDENT_CODE': true}) + sub_proj = cmake.subproject('yyjson', options: cmake_opts) + json = sub_proj.dependency('yyjson') +endif if get_option('wayland-logout') == true wayland_logout = subproject('wayland-logout') diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 48fdb581..a117b38d 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -38,7 +38,7 @@ class WayfirePanel::impl { std::unique_ptr window; - WayfireIPC* ipc; + std::shared_ptr ipc_manager; Gtk::HBox content_box; Gtk::HBox left_box, center_box, right_box; @@ -211,7 +211,7 @@ class WayfirePanel::impl if (name == "window-list") { - return Widget(new WayfireWindowList(output)); + return Widget(new WayfireWindowList(output, ipc_manager->get_IPC())); } if (name == "notifications") @@ -231,7 +231,7 @@ class WayfirePanel::impl if (name == "language") { - return Widget(new WayfireLanguage(ipc)); + return Widget(new WayfireLanguage(ipc_manager->get_IPC())); } if (auto pixel = widget_with_value(name, "spacing")) @@ -321,7 +321,7 @@ class WayfirePanel::impl } public: - impl(WayfireOutput *output, WayfireIPC *ipc) : ipc(ipc), output(output) + impl(WayfireOutput *output, std::shared_ptr ipc) : ipc_manager(ipc), output(output) { create_window(); } @@ -355,7 +355,7 @@ class WayfirePanel::impl } }; -WayfirePanel::WayfirePanel(WayfireOutput *output, WayfireIPC *ipc) : pimpl(new impl(output, ipc)) +WayfirePanel::WayfirePanel(WayfireOutput *output, std::shared_ptr ipc_manager) : pimpl(new impl(output, ipc_manager)) {} wl_surface*WayfirePanel::get_wl_surface() @@ -446,7 +446,7 @@ void WayfirePanelApp::add_css_file(std::string file, int priority) void WayfirePanelApp::handle_new_output(WayfireOutput *output) { priv->panels[output] = std::unique_ptr( - new WayfirePanel(output, ipc)); + new WayfirePanel(output, ipc_manager)); } WayfirePanel*WayfirePanelApp::panel_for_wl_output(wl_output *output) diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp index 1f658d36..d7b4d79c 100644 --- a/src/panel/panel.hpp +++ b/src/panel/panel.hpp @@ -12,7 +12,7 @@ class WayfirePanel { public: - WayfirePanel(WayfireOutput *output, WayfireIPC *ipc); + WayfirePanel(WayfireOutput *output, std::shared_ptr ipc); wl_surface *get_wl_surface(); Gtk::Window& get_window(); diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index 72e2b9a1..e6995902 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -1,16 +1,20 @@ #include #include #include +#include #include -#include +#include "json.hpp" +#include #include #include +#include #include #include "language.hpp" #include "gtkmm/button.h" #include "sigc++/functors/mem_fun.h" -void WayfireLanguage::init(Gtk::HBox *container) { +void WayfireLanguage::init(Gtk::HBox *container) +{ button.get_style_context()->add_class("language"); button.add(label); button.get_style_context()->add_class("flat"); @@ -20,61 +24,79 @@ void WayfireLanguage::init(Gtk::HBox *container) { label.show(); ipc->subscribe(this, {"keyboard-modifier-state-changed"}); - ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=](nlohmann::json data) { + ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (json_t data) + { set_available(data["possible-layouts"]); - set_current(data["layout-index"]); + set_current(data["layout-index"]); }); container->pack_start(button, false, false); } -void WayfireLanguage::on_event(nlohmann::json data) { - if (data["event"] == "keyboard-modifier-state-changed") { - if (available_layouts.size() == 0) { - set_available(data["state"]["possible-layouts"]); - } +void WayfireLanguage::on_event(json_t data) +{ + try { + if (data["event"].as_string() == "keyboard-modifier-state-changed") + { + if (available_layouts.size() == 0) + { + set_available(data["state"]["possible-layouts"]); + } - auto state_layout = data["state"]["layout-index"]; - if (state_layout != current_layout) { - current_layout = state_layout; - set_current(state_layout); + auto state_layout = data["state"]["layout-index"].as_uint(); + if (state_layout != current_layout) + { + current_layout = state_layout; + set_current(state_layout); + } } + } catch (const JSONException& e) + { + LOGE("Handle event JSON error: ", e.what()); } } -bool WayfireLanguage::update_label() { - if (current_layout >= available_layouts.size()) { +bool WayfireLanguage::update_label() +{ + if (current_layout >= available_layouts.size()) + { return false; } + label.set_text(available_layouts[current_layout].ID); return true; } -void WayfireLanguage::set_current(uint32_t index) { +void WayfireLanguage::set_current(uint32_t index) +{ current_layout = index; update_label(); } -void WayfireLanguage::set_available(nlohmann::json layouts) { +void WayfireLanguage::set_available(json_t layouts) +{ std::vector layouts_available; std::map names; - for(size_t i = 0; i < layouts.size(); i++) { + for (size_t i = 0; i < layouts.size(); i++) + { auto elem = layouts[i]; names[elem] = i; layouts_available.push_back(Layout{ .Name = (std::string)elem, - .ID = "", + .ID = "", }); } auto context = rxkb_context_new(RXKB_CONTEXT_NO_FLAGS); rxkb_context_parse_default_ruleset(context); auto rlayout = rxkb_layout_first(context); - for (; rlayout != NULL; rlayout = rxkb_layout_next(rlayout)) { + for (; rlayout != NULL; rlayout = rxkb_layout_next(rlayout)) + { auto descr = rxkb_layout_get_description(rlayout); - auto name = names.find(descr); - if (name != names.end()) { + auto name = names.find(descr); + if (name != names.end()) + { layouts_available[name->second].ID = rxkb_layout_get_brief(rlayout); } } @@ -83,23 +105,25 @@ void WayfireLanguage::set_available(nlohmann::json layouts) { update_label(); } -void WayfireLanguage::next_layout() { +void WayfireLanguage::next_layout() +{ uint32_t next = current_layout + 1; if (next >= available_layouts.size()) { next = 0; } - nlohmann::json message; + json_t message; message["method"] = "wayfire/set-keyboard-state"; - message["data"] = nlohmann::json::object(); + message["data"] = json_t(); message["data"]["layout-index"] = next; - ipc->send(message.dump()); + ipc->send(message.serialize()); } -WayfireLanguage::WayfireLanguage(WayfireIPC *ipc): ipc(ipc) +WayfireLanguage::WayfireLanguage(std::shared_ptr ipc) : ipc(ipc) {} -WayfireLanguage::~WayfireLanguage() { +WayfireLanguage::~WayfireLanguage() +{ ipc->unsubscribe(this); } diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp index 825a0def..7223643e 100644 --- a/src/panel/widgets/language.hpp +++ b/src/panel/widgets/language.hpp @@ -7,14 +7,14 @@ #include #include #include -#include +#include "json.hpp" #include #include struct Layout { - std::string Name; - std::string ID; + std::string Name; + std::string ID; }; class WayfireLanguage : public WayfireWidget, public IIPCSubscriber @@ -22,18 +22,18 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber Gtk::Label label; Gtk::Button button; - WayfireIPC *ipc; + std::shared_ptr ipc; uint32_t current_layout; std::vector available_layouts; public: void init(Gtk::HBox *container) override; - void on_event(nlohmann::json data) override; + void on_event(json_t data) override; bool update_label(); void set_current(uint32_t index); - void set_available(nlohmann::json layouts); + void set_available(json_t layouts); void next_layout(); - WayfireLanguage(WayfireIPC *ipc); + WayfireLanguage(std::shared_ptr ipc); ~WayfireLanguage(); }; diff --git a/src/util/json.cpp b/src/util/json.cpp new file mode 100644 index 00000000..6c5b67d8 --- /dev/null +++ b/src/util/json.cpp @@ -0,0 +1,679 @@ +#include "json.hpp" +#include +#include +#include +#include +#include +#include + +bool json_reference_t::is_array() const +{ + return yyjson_mut_is_arr(v); +} + +json_reference_t json_reference_t::operator [](const size_t& idx) const +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + if (size() < idx) + { + throw JSONException("Index out of bounds"); + } + + return json_reference_t{doc, yyjson_mut_arr_get(v, idx)}; +} + +void json_reference_t::append(const json_reference_t& elem) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_append(v, yyjson_mut_val_mut_copy(doc, elem.v)); +} + +void json_reference_t::append(int value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_int(doc, v, value); +} + +void json_reference_t::append(unsigned int value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_uint(doc, v, value); +} + +void json_reference_t::append(int64_t value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_sint(doc, v, value); +} + +void json_reference_t::append(uint64_t value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_uint(doc, v, value); +} + +void json_reference_t::append(double value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_real(doc, v, value); +} + +void json_reference_t::append(bool value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_bool(doc, v, value); +} + +void json_reference_t::append(const std::string_view& value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_strncpy(doc, v, value.data(), value.size()); +} + +void json_reference_t::append(const char *value) +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + yyjson_mut_arr_add_strcpy(doc, v, value); +} + +size_t json_reference_t::size() const +{ + if (!is_array()) + { + throw JSONException("Not an array"); + } + + return yyjson_mut_arr_size(v); +} + +bool json_reference_t::has_member(const std::string_view& key) const +{ + return is_object() && (yyjson_mut_obj_getn(v, key.data(), key.size()) != NULL); +} + +bool json_reference_t::is_object() const +{ + return yyjson_mut_is_obj(v); +} + +bool json_reference_t::is_null() const +{ + return yyjson_mut_is_null(v); +} + +json_reference_t json_reference_t::operator [](const char *key) const +{ + return this->operator [](std::string_view{key}); +} + +json_reference_t json_reference_t::operator [](const std::string_view& key) const +{ + if (!(is_object() || is_null())) + { + throw JSONException("Trying to access into JSON value that is not an object!"); + } + + if (is_null()) + { + yyjson_mut_set_obj(v); + } + + auto ptr = yyjson_mut_obj_getn(v, key.data(), key.size()); + if (ptr != NULL) + { + return json_reference_t{doc, ptr}; + } + + auto key_yy = yyjson_mut_strncpy(doc, key.data(), key.size()); + auto value = yyjson_mut_null(doc); + + yyjson_mut_obj_add(v, key_yy, value); + return json_reference_t{doc, value}; +} + +std::vector json_reference_t::get_member_names() const +{ + std::vector members; + yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(v); + while (yyjson_mut_obj_iter_has_next(&iter)) + { + auto key = yyjson_mut_obj_iter_next(&iter); + members.push_back(yyjson_mut_get_str(key)); + } + + return members; +} + +static void copy_yyjson(yyjson_mut_doc *dst_doc, yyjson_mut_val *dst, yyjson_mut_val *src) +{ + if (yyjson_mut_is_null(src)) + { + yyjson_mut_set_null(dst); + return; + } + + if (yyjson_mut_is_bool(src)) + { + yyjson_mut_set_bool(dst, yyjson_mut_get_bool(src)); + return; + } + + if (yyjson_mut_is_sint(src)) + { + yyjson_mut_set_sint(dst, yyjson_mut_get_sint(src)); + return; + } + + if (yyjson_mut_is_uint(src)) + { + yyjson_mut_set_uint(dst, yyjson_mut_get_uint(src)); + return; + } + + if (yyjson_mut_is_real(src)) + { + yyjson_mut_set_real(dst, yyjson_mut_get_real(src)); + return; + } + + if (yyjson_mut_is_str(src)) + { + // copy ownership of string to dst_doc + auto val = yyjson_mut_val_mut_copy(dst_doc, src); + yyjson_mut_set_str(dst, yyjson_mut_get_str(val)); + return; + } + + if (yyjson_mut_is_arr(src)) + { + yyjson_mut_set_arr(dst); + yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(src); + while (yyjson_mut_arr_iter_has_next(&iter)) + { + auto elem = yyjson_mut_arr_iter_next(&iter); + elem = yyjson_mut_val_mut_copy(dst_doc, elem); + yyjson_mut_arr_append(dst, elem); + } + + return; + } + + if (yyjson_mut_is_obj(src)) + { + yyjson_mut_set_obj(dst); + yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(src); + while (yyjson_mut_obj_iter_has_next(&iter)) + { + auto key = yyjson_mut_obj_iter_next(&iter); + auto value = yyjson_mut_obj_iter_get_val(key); + // Copy ownership to our doc + key = yyjson_mut_val_mut_copy(dst_doc, key); + value = yyjson_mut_val_mut_copy(dst_doc, value); + yyjson_mut_obj_add(dst, key, value); + } + + return; + } + + throw JSONException("Unsupported JSON type?"); +} + +json_reference_t& json_reference_t::operator =(const json_reference_t& other) +{ + copy_yyjson(doc, v, other.v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const json_reference_t&& other) +{ + // FIXME: maybe we can check whether the docs are the same or something to make this faster? + copy_yyjson(doc, v, other.v); + return *this; +} + +// --------------------------------------- Basic data types support ------------------------------------------ +json_reference_t& json_reference_t::operator =(const int& v) +{ + yyjson_mut_set_sint(this->v, v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const uint& v) +{ + yyjson_mut_set_uint(this->v, v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const int64_t& v) +{ + yyjson_mut_set_sint(this->v, v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const uint64_t& v) +{ + yyjson_mut_set_uint(this->v, v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const bool& v) +{ + yyjson_mut_set_bool(this->v, v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const double& v) +{ + yyjson_mut_set_real(this->v, v); + return *this; +} + +json_reference_t& json_reference_t::operator =(const std::string_view& v) +{ + // copy ownership of string to doc + auto our_v = yyjson_mut_strncpy(doc, v.data(), v.size()); + yyjson_mut_set_str(this->v, yyjson_mut_get_str(our_v)); + return *this; +} + +json_reference_t& json_reference_t::operator =(const char *v) +{ + // copy ownership of string to doc + auto our_v = yyjson_mut_strcpy(doc, v); + yyjson_mut_set_str(this->v, yyjson_mut_get_str(our_v)); + return *this; +} + +bool json_reference_t::is_int() const +{ + if (yyjson_mut_is_sint(v)) + { + return (std::numeric_limits::min() <= yyjson_mut_get_sint(v)) && + (yyjson_mut_get_sint(v) <= std::numeric_limits::max()); + } + + if (yyjson_mut_is_uint(v)) + { + return (yyjson_mut_get_uint(v) <= std::numeric_limits::max()); + } + + return false; +} + +json_reference_t::operator int() const +{ + if (!is_int()) + { + throw JSONException("Not an int"); + } + + return yyjson_mut_get_int(v); +} + +int json_reference_t::as_int() const +{ + if (!is_int()) + { + throw JSONException("Not an int"); + } + + return (int)(*this); +} + +bool json_reference_t::is_int64() const +{ + if (yyjson_mut_is_uint(v)) + { + return yyjson_mut_get_uint(v) <= std::numeric_limits::max(); + } + + return yyjson_mut_is_sint(v); +} + +json_reference_t::operator int64_t() const +{ + if (!is_int64()) + { + throw JSONException("Not an int64"); + } + + if (yyjson_mut_is_uint(v)) + { + return yyjson_mut_get_uint(v); + } else + { + return yyjson_mut_get_sint(v); + } +} + +int64_t json_reference_t::as_int64() const +{ + if (!is_int64()) + { + throw JSONException("Not an int64"); + } + + return (int64_t)(*this); +} + +bool json_reference_t::is_uint() const +{ + return yyjson_mut_is_uint(v) && + (yyjson_mut_get_uint(v) <= std::numeric_limits::max()); +} + +json_reference_t::operator uint() const +{ + if (!is_uint()) + { + throw JSONException("Not an uint"); + } + + return yyjson_mut_get_uint(v); +} + +unsigned int json_reference_t::as_uint() const +{ + if (!is_uint()) + { + throw JSONException("Not an uint"); + } + + return (unsigned int)(*this); +} + +bool json_reference_t::is_uint64() const +{ + return yyjson_mut_is_uint(v); +} + +json_reference_t::operator uint64_t() const +{ + if (!is_uint64()) + { + throw JSONException("Not an uint64"); + } + + return yyjson_mut_get_uint(v); +} + +uint64_t json_reference_t::as_uint64() const +{ + if (!is_uint64()) + { + throw JSONException("Not an uint64"); + } + + return (uint64_t)(*this); +} + +bool json_reference_t::is_bool() const +{ + return yyjson_mut_is_bool(v); +} + +json_reference_t::operator bool() const +{ + if (!is_bool()) + { + throw JSONException("Not a bool"); + } + + return yyjson_mut_get_bool(v); +} + +bool json_reference_t::as_bool() const +{ + if (!is_bool()) + { + throw JSONException("Not a bool"); + } + + return (bool)(*this); +} + +bool json_reference_t::is_double() const +{ + return yyjson_mut_is_num(v); +} + +json_reference_t::operator double() const +{ + if (!is_double()) + { + throw JSONException("Not a double"); + } + + return yyjson_mut_get_num(v); +} + +double json_reference_t::as_double() const +{ + if (!is_double()) + { + throw JSONException("Not a double"); + } + + return (double)(*this); +} + +bool json_reference_t::is_string() const +{ + return yyjson_mut_is_str(v); +} + +json_reference_t::operator std::string() const +{ + if (!is_string()) + { + throw JSONException("Not a string"); + } + + return std::string(yyjson_mut_get_str(v)); +} + +std::string json_reference_t::as_string() const +{ + if (!is_string()) + { + throw JSONException("Not a string"); + } + + return (std::string)*this; +} + +void json_t::init() +{ + this->doc = yyjson_mut_doc_new(NULL); + this->v = yyjson_mut_null(this->doc); + yyjson_mut_doc_set_root(doc, v); +} + +json_t::json_t() +{ + init(); +} + +json_t::~json_t() +{ + yyjson_mut_doc_free(doc); +} + +json_t::json_t(const json_reference_t& ref) : json_t() +{ + copy_yyjson(doc, this->v, ref.get_raw_value()); +} + +json_t::json_t(yyjson_mut_doc *doc) +{ + this->doc = doc; + this->v = yyjson_mut_doc_get_root(this->doc); +} + +json_t::json_t(const json_t& other) : json_reference_t() +{ + *this = other; +} + +json_t& json_t::operator =(const json_t& other) +{ + if (this != &other) + { + yyjson_mut_doc_free(doc); + init(); + copy_yyjson(doc, this->v, other.v); + } + + return *this; +} + +json_t::json_t(json_t&& other) +{ + *this = std::move(other); +} + +json_t& json_t::operator =(json_t&& other) +{ + if (this != &other) + { + yyjson_mut_doc_free(doc); + this->doc = other.doc; + this->v = other.v; + + other.doc = NULL; + other.v = NULL; + } + + return *this; +} + +json_t::json_t(int v) : json_t() +{ + *this = v; +} + +json_t::json_t(unsigned v) : json_t() +{ + *this = v; +} + +json_t::json_t(int64_t v) : json_t() +{ + *this = v; +} + +json_t::json_t(uint64_t v) : json_t() +{ + *this = v; +} + +json_t::json_t(double v) : json_t() +{ + *this = v; +} + +json_t::json_t(const std::string_view& v) : json_t() +{ + *this = v; +} + +json_t::json_t(const char *v) : json_t() +{ + *this = v; +} + +json_t::json_t(bool v) : json_t() +{ + *this = v; +} + +json_t json_t::array() +{ + json_t r; + yyjson_mut_set_arr(r.v); + return r; +} + +json_t json_t::null() +{ + json_t r; + yyjson_mut_set_null(r.v); + return r; +} + +std::optional json_t::parse_string(const std::string_view& source, + json_t& result) +{ + yyjson_read_err error; + auto doc = yyjson_read_opts((char*)source.data(), source.length(), 0, NULL, &error); + + if (!doc) + { + return std::string("Failed to parse JSON, error ") + + std::to_string(error.code) + ": " + error.msg + std::string("(at offset ") + + std::to_string(error.pos) + ")"; + } + + result = json_t{yyjson_doc_mut_copy(doc, NULL)}; + yyjson_doc_free(doc); + return std::nullopt; +} + +void json_t::map_serialized(std::function callback) const +{ + size_t len; + char *result = yyjson_mut_write(this->doc, 0, &len); + callback(result, len); + free(result); +} + +std::string json_t::serialize() const +{ + std::string result; + map_serialized([&] (const char *source, size_t length) + { + result.append(source, length); + }); + + return result; +} diff --git a/src/util/json.hpp b/src/util/json.hpp new file mode 100644 index 00000000..4e83cb8d --- /dev/null +++ b/src/util/json.hpp @@ -0,0 +1,168 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { + struct yyjson_mut_val; + struct yyjson_mut_doc; +}; + +class JSONException : public std::exception +{ + public: + std::string msg; + + JSONException(std::string msg) : msg(msg) + {} + + const char * what() const noexcept override + { + return msg.c_str(); + } +}; + +/** + * A temporary non-owning reference to a JSON value. + */ +class json_t; +class json_reference_t +{ + public: + // ------------------------------------------- Array support --------------------------------------------- + bool is_array() const; + json_reference_t operator [](const size_t& idx) const; + void append(const json_reference_t& elem); + void append(int value); + void append(unsigned int value); + void append(int64_t value); + void append(uint64_t value); + void append(double value); + void append(bool value); + void append(const std::string_view& value); + void append(const char *value); + size_t size() const; + + // ------------------------------------------- Object support -------------------------------------------- + bool has_member(const std::string_view& key) const; + bool is_object() const; + bool is_null() const; + json_reference_t operator [](const char *key) const; + json_reference_t operator [](const std::string_view& key) const; + std::vector get_member_names() const; + json_reference_t& operator =(const json_reference_t& v); + json_reference_t& operator =(const json_reference_t&& other); + + // ------------------------------------- Basic data types support ---------------------------------------- + json_reference_t& operator =(const int& v); + json_reference_t& operator =(const unsigned int& v); + json_reference_t& operator =(const int64_t& v); + json_reference_t& operator =(const uint64_t& v); + json_reference_t& operator =(const bool& v); + json_reference_t& operator =(const double& v); + json_reference_t& operator =(const std::string_view& v); + json_reference_t& operator =(const char *v); + + bool is_int() const; + operator int() const; + int as_int() const; + bool is_int64() const; + operator int64_t() const; + int64_t as_int64() const; + bool is_uint() const; + operator unsigned int() const; + unsigned int as_uint() const; + bool is_uint64() const; + operator uint64_t() const; + uint64_t as_uint64() const; + bool is_bool() const; + operator bool() const; + bool as_bool() const; + bool is_double() const; + operator double() const; + double as_double() const; + bool is_string() const; + operator std::string() const; + std::string as_string() const; + + yyjson_mut_val *get_raw_value() const + { + return v; + } + + yyjson_mut_doc *get_raw_doc() const + { + return doc; + } + + private: + friend class json_t; + json_reference_t() + {} + json_reference_t(yyjson_mut_doc *doc, yyjson_mut_val *val) : doc(doc), v(val) + {} + + yyjson_mut_doc *doc = NULL; + yyjson_mut_val *v = NULL; + + // Non-copyable, non-moveable. + json_reference_t(const json_reference_t& other) = delete; + json_reference_t(const json_reference_t&& other) = delete; +}; + +class json_t final : public json_reference_t +{ + public: + json_t(); + json_t(const json_reference_t& ref); + json_t(const json_t& other); + json_t(yyjson_mut_doc *doc); + ~json_t(); + + json_t& operator =(const json_t& other); + json_t(json_t&& other); + json_t& operator =(json_t&& other); + + json_t(int v); + json_t(unsigned int v); + json_t(int64_t v); + json_t(uint64_t v); + json_t(double v); + json_t(const std::string_view& v); + json_t(const char *v); + json_t(bool v); + + static json_t array(); + static json_t null(); + + /** + * Parse the given source as a JSON document. + * + * @result Where to store the parsed document on success. + * @return On failure, an error message describing the problem with the JSON source will be returned. + * Otherwise, the function will return std::nullopt. + */ + static std::optional parse_string(const std::string_view& source, + json_t& result); + + /** + * Serialize the JSON document and handle it using the provided callback. + * + * Note that the source string will be freed afterwards, so if the caller needs the data for longer, they + * need to make a copy of it. + */ + void map_serialized(std::function callback) const; + + /** + * Get a JSON string representation of the document. + */ + std::string serialize() const; + + private: + void init(); +}; diff --git a/src/util/meson.build b/src/util/meson.build index 855024a2..26a45649 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -1,5 +1,6 @@ -util = static_library('util', ['gtk-utils.cpp', 'wf-shell-app.cpp', 'wf-autohide-window.cpp', 'wf-popover.cpp', 'wf-ipc.cpp'], - dependencies: [wf_protos, wayland_client, gtkmm, wfconfig, libinotify, gtklayershell, json]) +util = static_library('util', ['gtk-utils.cpp', 'wf-shell-app.cpp', 'wf-autohide-window.cpp', 'wf-popover.cpp', + 'json.cpp', 'wf-ipc.cpp'], + dependencies: [wayfire, wf_protos, wayland_client, gtkmm, wfconfig, libinotify, gtklayershell, json]) util_includes = include_directories('.') libutil = declare_dependency( diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index f96555ec..76e55950 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -3,28 +3,37 @@ #include #include #include -#include +#include #include #include #include +#include #include #include #include #include #include +#include #include "wf-ipc.hpp" +#include "giomm/error.h" +#include "giomm/socketclient.h" +#include "giomm/unixsocketaddress.h" +#include "glibconfig.h" +#include "glibmm/error.h" #include "glibmm/iochannel.h" #include "glibmm/main.h" +#include "json.hpp" #include "sigc++/functors/mem_fun.h" -WayfireIPC::WayfireIPC(): socket_fd(-1) +WayfireIPC::WayfireIPC() { connect(); - auto connection = Glib::signal_io().connect( - sigc::mem_fun(this, &WayfireIPC::receive), socket_fd, Glib::IO_IN - ); + sig_connection = Glib::signal_io().connect( + sigc::mem_fun(this, &WayfireIPC::receive), + connection->get_socket()->get_fd(), + Glib::IO_IN); } WayfireIPC::~WayfireIPC() @@ -34,46 +43,26 @@ WayfireIPC::~WayfireIPC() void WayfireIPC::connect() { - const char* socket_path = getenv("WAYFIRE_SOCKET"); + const char *socket_path = getenv("WAYFIRE_SOCKET"); if (socket_path == nullptr) { throw std::runtime_error("Wayfire socket not found"); } - socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (socket_fd == -1) - { - throw std::runtime_error("Wayfire socket create error"); - } - - if (fcntl(socket_fd, F_SETFL, O_NONBLOCK) == -1) - { - throw std::runtime_error("Wayfire socket set flag error"); - } - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - - if (strlen(socket_path) >= sizeof(addr.sun_path)) - { - throw std::runtime_error("Wayfire socket path too long"); - } - - strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1); - if (::connect(socket_fd, (sockaddr*)&addr, sizeof(addr)) == -1) - { - throw std::runtime_error("Wayfire socket connect error"); - } + auto client = Gio::SocketClient::create(); + auto address = Gio::UnixSocketAddress::create(socket_path); + connection = client->connect(address); + connection->get_socket()->set_blocking(false); + output = connection->get_output_stream(); + input = connection->get_input_stream(); } void WayfireIPC::disconnect() { - if (socket_fd != -1) - { - close(socket_fd); - socket_fd = -1; - } + sig_connection.disconnect(); + input->close(); + output->close(); + connection->close(); } void WayfireIPC::send(const std::string& message) @@ -90,105 +79,218 @@ void WayfireIPC::send(const std::string& message, response_handler cb) void WayfireIPC::send_message(const std::string& message) { - size_t sent = 0; - while (sent < message.size()) { - uint32_t length = message.size(); - auto all_data = std::string((char*)&length, 4); - all_data += message; - ssize_t res = ::send(socket_fd, all_data.data() + sent, - all_data.size() - sent, MSG_NOSIGNAL); - if (res == -1) { - throw std::system_error(errno, std::system_category(), "send failed"); - } + if (output->has_pending()) + { + write_queue.push(message); + write_next(); + return; + } + + // Shortcut: stream is not busy, no queue needed + write_stream(message); +} - sent += res; +void WayfireIPC::write_next() +{ + if (writing) + { + return; } + + writing = true; + sig_connection = Glib::signal_io().connect( + sigc::mem_fun(this, &WayfireIPC::send_queue), + connection->get_socket()->get_fd(), + Glib::IO_OUT); } -bool WayfireIPC::receive(Glib::IOCondition cond) +void WayfireIPC::write_stream(const std::string& message) { - ssize_t received = 0; + try { + writing = true; + uint32_t length = message.size(); + auto all_data = std::make_shared((char*)&length, 4); + *all_data += message; + output->write_all_async(all_data->data(), all_data->size(), + [this, all_data] (Glib::RefPtr& result) + { + try { + gsize written; + auto success = output->write_all_finish(result, written); + if (!success) + { + LOGE("Write failed. Bytes written: ", written); + } - if (!length_received) + this->writing = false; + write_next(); + } catch (const Glib::Error& e) + { + LOGE("Write failed: ", e.what()); + } + }); + } catch (const Gio::Error& e) { - received = ::recv(socket_fd, &length, 4, 0); - if (received == -1) { - return true; - } - if (received == 0) { - throw std::runtime_error("Connection closed by peer"); - } + LOGE("GIO Error: ", e.what()); } - length_received = true; +} - std::string buf(length + 1, 0); - received = ::recv(socket_fd, &buf[0], length, 0); - if (received == -1) { - return true; - } - if (received == 0) { - throw std::runtime_error("Connection closed by peer"); +bool WayfireIPC::send_queue(Glib::IOCondition cond) +{ + if (write_queue.empty()) + { + writing = false; + return false; } - length_received = false; - auto message = nlohmann::json::parse(buf); + auto message = write_queue.front(); + write_queue.pop(); - if (message.contains("event")) { - for (auto subscriber : subscribers) { - subscriber->on_event(message); - } + write_stream(message); + return false; +} - if (subscriptions.find(message["event"]) != subscriptions.end()) { - for (auto sub : subscriptions[message["event"]]) { - sub->on_event(message); +bool WayfireIPC::receive(Glib::IOCondition cond) +{ + try { + ssize_t received = 0; + + while (connection->get_socket()->get_available_bytes() > 0) + { + received = input->read(&length, 4); + if (received == -1) + { + LOGE("Receive message length failed"); + return false; + } + + if (received == 0) + { + LOGE("Disconnected"); + return false; + } + + std::string buf(length, 0); + received = input->read(&buf[0], length); + if (received == -1) + { + LOGE("Receive message body failed"); + return false; + } + + if (received == 0) + { + LOGE("Disconnected"); + return false; + } + + json_t message; + auto err = json_t::parse_string(buf, message); + if (err.has_value()) + { + LOGE("Parse error: ", err.value(), " message: ", buf, " length: ", buf.length()); + return false; + } + + if (message.has_member("event")) + { + for (auto subscriber : subscribers) + { + subscriber->on_event(message); + } + + if (subscriptions.find(message["event"]) != subscriptions.end()) + { + for (auto sub : subscriptions[message["event"]]) + { + sub->on_event(message); + } + } + } else + { + auto handler = response_handlers.front(); + response_handlers.pop(); + if (handler.has_value()) + { + handler.value()(message); + } } } - } else { - auto handler = response_handlers.front(); - response_handlers.pop(); - if (handler.has_value()) { - handler.value()(message); - } + } catch (const Gio::Error& e) + { + LOGE("GIO Error: ", e.what()); + return false; + } catch (const JSONException& e) + { + LOGE("JSON error: ", e.what()); } - + return true; } -void WayfireIPC::subscribe_all(IIPCSubscriber* subscriber) +void WayfireIPC::subscribe_all(IIPCSubscriber *subscriber) { subscribers.insert(subscriber); - nlohmann::json new_subs; + json_t new_subs; new_subs["method"] = "window-rules/events/watch"; - send(new_subs.dump()); + send(new_subs.serialize()); } -void WayfireIPC::subscribe(IIPCSubscriber* subscriber, const std::vector& events) +void WayfireIPC::subscribe(IIPCSubscriber *subscriber, const std::vector& events) { - nlohmann::json new_subs; + json_t new_subs; new_subs["method"] = "window-rules/events/watch"; - new_subs["events"] = nlohmann::json::array(); + new_subs["events"] = json_t::array(); - for (auto event : events) { - if (subscriptions.find(event) == subscriptions.end()) { - new_subs["events"].push_back(event); + for (auto event : events) + { + if (subscriptions.find(event) == subscriptions.end()) + { + new_subs["events"].append(event); subscriptions[event] = std::set(); } subscriptions[event].insert(subscriber); } - if (new_subs["events"].size() > 0) { - send(new_subs.dump()); + if (new_subs["events"].size() > 0) + { + send(new_subs.serialize()); } } -void WayfireIPC::unsubscribe(IIPCSubscriber* subscriber) +void WayfireIPC::unsubscribe(IIPCSubscriber *subscriber) { subscribers.erase(subscriber); - for (auto& [_, subs] : subscriptions) { + for (auto& [_, subs] : subscriptions) + { subs.erase(subscriber); } } +// WayfireIPCManager +std::shared_ptr WayfireIPCManager::get_IPC() +{ + if (ipc == nullptr) + { + ipc = new WayfireIPC(); + } + + counter++; + return std::shared_ptr(ipc, [this] (WayfireIPC*) + { + release(); + }); +} + +void WayfireIPCManager::release() +{ + counter--; + if (counter == 0) + { + delete ipc; + ipc = nullptr; + } +} diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index 4580db38..1903916e 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -1,45 +1,69 @@ #ifndef WF_IPC_HPP #define WF_IPC_HPP +#include "gio/gio.h" +#include "giomm/outputstream.h" +#include "giomm/socketconnection.h" #include "glibmm/iochannel.h" +#include "glibmm/refptr.h" +#include "json.hpp" +#include "sigc++/connection.h" #include -#include +#include #include #include #include #include -#include #include #include -class IIPCSubscriber { - public: - virtual void on_event(nlohmann::json) = 0; +class IIPCSubscriber +{ + public: + virtual void on_event(json_t) = 0; }; -using response_handler = std::function; +using response_handler = std::function; class WayfireIPC { - int socket_fd; - std::queue> response_handlers; - std::set subscribers; - std::unordered_map> subscriptions; - bool length_received = false; - uint32_t length; - - void connect(); - void disconnect(); - void send_message(const std::string& message); - bool receive(Glib::IOCondition cond); - public: - void send(const std::string& message); - void send(const std::string& message, response_handler); - void subscribe(IIPCSubscriber* subscriber, const std::vector& events); - void subscribe_all(IIPCSubscriber* subscriber); - void unsubscribe(IIPCSubscriber* subscriber); - WayfireIPC(); - ~WayfireIPC(); + std::queue> response_handlers; + std::set subscribers; + std::unordered_map> subscriptions; + uint32_t length; + sigc::connection sig_connection; + Glib::RefPtr connection; + Glib::RefPtr input; + Glib::RefPtr output; + std::queue write_queue; + bool writing = false; + + void connect(); + void disconnect(); + void send_message(const std::string& message); + bool send_queue(Glib::IOCondition cond); + bool receive(Glib::IOCondition cond); + void write_stream(const std::string& message); + void write_next(); + + public: + void send(const std::string& message); + void send(const std::string& message, response_handler); + void subscribe(IIPCSubscriber *subscriber, const std::vector& events); + void subscribe_all(IIPCSubscriber *subscriber); + void unsubscribe(IIPCSubscriber *subscriber); + WayfireIPC(); + ~WayfireIPC(); +}; + +class WayfireIPCManager +{ + uint counter = 0; + WayfireIPC *ipc = nullptr; + void release(); + + public: + std::shared_ptr get_IPC(); }; -#endif // WF_IPC_HPP \ No newline at end of file +#endif // WF_IPC_HPP diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index cdd96b3c..0677be3b 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -155,7 +155,7 @@ void WayfireShellApp::on_activate() std::exit(-1); } - ipc = new WayfireIPC(); + ipc_manager = std::make_shared(); wl_registry *registry = wl_display_get_registry(wl_display); wl_registry_add_listener(registry, ®istry_listener, this); @@ -235,9 +235,7 @@ WayfireShellApp::WayfireShellApp(int argc, char **argv) } WayfireShellApp::~WayfireShellApp() -{ - delete ipc; -} +{} std::unique_ptr WayfireShellApp::instance; WayfireShellApp& WayfireShellApp::get() diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index 2c4fe94d..d926b2bb 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -1,6 +1,7 @@ #ifndef WF_SHELL_APP_HPP #define WF_SHELL_APP_HPP +#include #include #include @@ -67,7 +68,7 @@ class WayfireShellApp int inotify_css_fd; wf::config::config_manager_t config; zwf_shell_manager_v2 *wf_shell_manager = nullptr; - WayfireIPC *ipc = nullptr; + std::shared_ptr ipc_manager; WayfireShellApp(int argc, char **argv); virtual ~WayfireShellApp(); diff --git a/subprojects/yyjson.wrap b/subprojects/yyjson.wrap new file mode 100644 index 00000000..3bf85901 --- /dev/null +++ b/subprojects/yyjson.wrap @@ -0,0 +1,5 @@ +[wrap-git] +url = https://github.com/ibireme/yyjson.git +revision = HEAD +depth = 1 +method = cmake diff --git a/uncrustify.ini b/uncrustify.ini new file mode 100644 index 00000000..04c55fb7 --- /dev/null +++ b/uncrustify.ini @@ -0,0 +1,1108 @@ +# Uncrustify_d-0.71.0-21-d4da2b0f + +# +# General options +# + +# The type of line endings. +# +# Default: auto +newlines = auto # lf/crlf/cr/auto + +# The original size of tabs in the input. +# +# Default: 8 +input_tab_size = 4 # unsigned number + +# The size of tabs in the output (only used if align_with_tabs=true). +# +# Default: 8 +output_tab_size = 4 # unsigned number + +# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). +# +# Default: 92 +string_escape_char = 92 # unsigned number + +# Alternate string escape char (usually only used for Pawn). +# Only works right before the quote char. +string_escape_char2 = 0 # unsigned number + +# Replace tab characters found in string literals with the escape sequence \t +# instead. +string_replace_tab_chars = true # true/false + +# Allow interpreting '>=' and '>>=' as part of a template in code like +# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. +# Improvements to template detection may make this option obsolete. +tok_split_gte = false # true/false + +# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multiline macros) +disable_processing_nl_cont = false # true/false + +# Specify the marker used in comments to disable processing of part of the +# file. +# The comment should be used alone in one line. +# +# Default: *INDENT-OFF* +disable_processing_cmt = " *INDENT-OFF*" # string + +# Specify the marker used in comments to (re)enable processing in a file. +# The comment should be used alone in one line. +# +# Default: *INDENT-ON* +enable_processing_cmt = " *INDENT-ON*" # string + +# Enable parsing of digraphs. +enable_digraphs = false # true/false + +# Add or remove the UTF-8 BOM (recommend 'remove'). +utf8_bom = ignore # ignore/add/remove/force + +# If the file contains bytes with values between 128 and 255, but is not +# UTF-8, then output as UTF-8. +utf8_byte = false # true/false + +# Force the output encoding to UTF-8. +utf8_force = false # true/false + +# Add or remove space between 'do' and '{'. +sp_do_brace_open = force # ignore/add/remove/force + +# Add or remove space between '}' and 'while'. +sp_brace_close_while = force # ignore/add/remove/force + +# Add or remove space between 'while' and '('. +sp_while_paren_open = force # ignore/add/remove/force + +# +# Spacing options +# + +# Add or remove space around non-assignment symbolic operators ('+', '/', '%', +# '<<', and so forth). +sp_arith = force # ignore/add/remove/force + +# Add or remove space around assignment operator '=', '+=', etc. +sp_assign = force # ignore/add/remove/force + +# Add or remove space around '=' in C++11 lambda capture specifications. +# +# Overrides sp_assign. +sp_cpp_lambda_assign = remove # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda when +# an argument list is present, as in '[] (int x){ ... }'. +sp_cpp_lambda_square_paren = force # ignore/add/remove/force + +# Add or remove space after the capture specification of a C++11 lambda with +# no argument list is present, as in '[] { ... }'. +sp_cpp_lambda_square_brace = force # ignore/add/remove/force + +# Add or remove space after the argument list of a C++11 lambda, as in +# '[](int x) { ... }'. +sp_cpp_lambda_paren_brace = force # ignore/add/remove/force + +# Add or remove space in 'NS_ENUM ('. +sp_enum_paren = ignore # ignore/add/remove/force + +# Add or remove space around assignment '=' in enum. +sp_enum_assign = add # ignore/add/remove/force + +# Add or remove space around assignment ':' in enum. +sp_enum_colon = force # ignore/add/remove/force + +# Add or remove space around boolean operators '&&' and '||'. +sp_bool = force # ignore/add/remove/force + +# Add or remove space around compare operator '<', '>', '==', etc. +sp_compare = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')'. +sp_inside_paren = remove # ignore/add/remove/force + +# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. +sp_paren_paren = remove # ignore/add/remove/force + +# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. +sp_cparen_oparen = remove # ignore/add/remove/force + +# Add or remove space between ')' and '{'. +sp_paren_brace = add # ignore/add/remove/force + +# Add or remove space between nested braces, i.e. '{{' vs '{ {'. +sp_brace_brace = remove # ignore/add/remove/force + +# Add or remove space before pointer star '*'. +sp_before_ptr_star = force # ignore/add/remove/force + +# Add or remove space between pointer stars '*'. +sp_between_ptr_star = remove # ignore/add/remove/force + +# Add or remove space after pointer star '*', if followed by a word. +# +# Overrides sp_type_func. +sp_after_ptr_star = remove # ignore/add/remove/force + +# Add or remove space before pointer star '*' that isn't followed by a +# variable name. If set to ignore, sp_before_ptr_star is used instead. +sp_before_unnamed_ptr_star = remove # ignore/add/remove/force + +# Add or remove space before a pointer star '*', if followed by a function +# prototype or function definition. +sp_before_ptr_star_func = force # ignore/add/remove/force + +# Add or remove space before a reference sign '&'. +sp_before_byref = ignore # ignore/add/remove/force + +# Add or remove space after reference sign '&', if followed by a word. +# +# Overrides sp_type_func. +sp_after_byref = force # ignore/add/remove/force + +# Add or remove space before a reference sign '&', if followed by a function +# prototype or function definition. +sp_before_byref_func = remove # ignore/add/remove/force + +# Add or remove space between 'decltype(...)' and word. +sp_after_decltype = force # ignore/add/remove/force + +# Add or remove space before '<'. +sp_before_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<' and '>'. +sp_inside_angle = remove # ignore/add/remove/force + +# Add or remove space inside '<>'. +sp_inside_angle_empty = remove # ignore/add/remove/force + +# Add or remove space between '>' and ':'. +sp_angle_colon = force # ignore/add/remove/force + +# Add or remove space after '>'. +sp_after_angle = force # ignore/add/remove/force + +# Add or remove space between '>' and '(' as found in 'new List(foo);'. +sp_angle_paren = remove # ignore/add/remove/force + +# Add or remove space between '>' and '()' as found in 'new List();'. +sp_angle_paren_empty = remove # ignore/add/remove/force + +# Add or remove space between '>' and a word as in 'List m;' or +# 'template static ...'. +sp_angle_word = force # ignore/add/remove/force + +# Add or remove space between '>' and '>' in '>>' (template stuff). +# +# Default: add +sp_angle_shift = remove # ignore/add/remove/force + +# (C++11) Permit removal of the space between '>>' in 'foo >'. Note +# that sp_angle_shift cannot remove the space without this option. +sp_permit_cpp11_shift = true # true/false + +# Add or remove space before '(' of control statements ('if', 'for', 'switch', +# 'while', etc.). +sp_before_sparen = force # ignore/add/remove/force + +# Add or remove space inside '(' and ')' of control statements. +sp_inside_sparen = remove # ignore/add/remove/force + +# Add or remove space between ')' and '{' of of control statements. +sp_sparen_brace = force # ignore/add/remove/force + +# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. +sp_special_semi = remove # ignore/add/remove/force + +# Add or remove space before ';' in non-empty 'for' statements. +sp_before_semi_for = remove # ignore/add/remove/force + +# Add or remove space before a semicolon of an empty part of a for statement. +sp_before_semi_for_empty = remove # ignore/add/remove/force + +# Add or remove space after ';', except when followed by a comment. +# +# Default: add +sp_after_semi = remove # ignore/add/remove/force + +# Add or remove space after ';' in non-empty 'for' statements. +# +# Default: force +sp_after_semi_for = force # ignore/add/remove/force + +# Add or remove space after the final semicolon of an empty part of a for +# statement, as in 'for ( ; ; )'. +sp_after_semi_for_empty = remove # ignore/add/remove/force + +# Add or remove space before '[' (except '[]'). +sp_before_square = remove # ignore/add/remove/force + +# Add or remove space before '[' for a variable definition. +# +# Default: remove +sp_before_vardef_square = remove # ignore/add/remove/force + +# Add or remove space before '[]'. +sp_before_squares = remove # ignore/add/remove/force + +# Add or remove space before C++17 structured bindings. +sp_cpp_before_struct_binding = force # ignore/add/remove/force + +# Add or remove space inside a non-empty '[' and ']'. +sp_inside_square = remove # ignore/add/remove/force + +# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. +sp_after_comma = force # ignore/add/remove/force + +# Add or remove space before the variadic '...' when preceded by a +# non-punctuator. +sp_before_ellipsis = remove # ignore/add/remove/force + +# Add or remove space between a type and '...'. +sp_type_ellipsis = remove # ignore/add/remove/force + +# Add or remove space between ')' and '...'. +sp_paren_ellipsis = remove # ignore/add/remove/force + +# Add or remove space between ')' and a qualifier such as 'const'. +sp_paren_qualifier = force # ignore/add/remove/force + +# Add or remove space between ')' and 'noexcept'. +sp_paren_noexcept = force # ignore/add/remove/force + +# Add or remove space after class ':'. +sp_after_class_colon = force # ignore/add/remove/force + +# Add or remove space before class ':'. +sp_before_class_colon = force # ignore/add/remove/force + +# Add or remove space after class constructor ':'. +sp_after_constr_colon = force # ignore/add/remove/force + +# Add or remove space before class constructor ':'. +sp_before_constr_colon = force # ignore/add/remove/force + +# Add or remove space between 'operator' and operator sign. +sp_after_operator = force # ignore/add/remove/force + +# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or +# '(int)a' vs. '(int) a'. +sp_after_cast = remove # ignore/add/remove/force + +# Add or remove spaces inside cast parentheses. +sp_inside_paren_cast = remove # ignore/add/remove/force + +# Add or remove space between the type and open parenthesis in a C++ cast, +# i.e. 'int(exp)' vs. 'int (exp)'. +sp_cpp_cast_paren = remove # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '('. +sp_sizeof_paren = remove # ignore/add/remove/force + +# Add or remove space between 'sizeof' and '...'. +sp_sizeof_ellipsis = remove # ignore/add/remove/force + +# Add or remove space between 'sizeof...' and '('. +sp_sizeof_ellipsis_paren = remove # ignore/add/remove/force + +# Add or remove space between 'decltype' and '('. +sp_decltype_paren = remove # ignore/add/remove/force + +# Add or remove space after open brace in an unnamed temporary +# direct-list-initialization. +sp_after_type_brace_init_lst_open = remove # ignore/add/remove/force + +# Add or remove space before close brace in an unnamed temporary +# direct-list-initialization. +sp_before_type_brace_init_lst_close = remove # ignore/add/remove/force + +# Add or remove space inside '{}'. +sp_inside_braces_empty = remove # ignore/add/remove/force + +# Add or remove space around trailing return operator '->'. +sp_trailing_return = force # ignore/add/remove/force + +# Add or remove space between type and open brace of an unnamed temporary +# direct-list-initialization. +sp_type_brace_init_lst = remove # ignore/add/remove/force + +# Add or remove space between function name and '(' on function declaration. +sp_func_proto_paren = remove # ignore/add/remove/force + +# Add or remove space between function name and '()' on function declaration +# without parameters. +sp_func_proto_paren_empty = remove # ignore/add/remove/force + +# Add or remove space between function name and '(' with a typedef specifier. +sp_func_type_paren = remove # ignore/add/remove/force + +# Add or remove space between alias name and '(' of a non-pointer function type typedef. +sp_func_def_paren = remove # ignore/add/remove/force + +# Add or remove space between function name and '()' on function definition +# without parameters. +sp_func_def_paren_empty = remove # ignore/add/remove/force + +# Add or remove space inside empty function '()'. +# Overrides sp_after_angle unless use_sp_after_angle_always is set to true. +sp_inside_fparens = remove # ignore/add/remove/force + +# Add or remove space inside function '(' and ')'. +sp_inside_fparen = remove # ignore/add/remove/force + +# Add or remove space inside the first parentheses in a function type, as in +# 'void (*x)(...)'. +sp_inside_tparen = remove # ignore/add/remove/force + +# Add or remove space between ']' and '(' when part of a function call. +sp_square_fparen = remove # ignore/add/remove/force + +# Add or remove space between ')' and '{' of function. +sp_fparen_brace = force # ignore/add/remove/force + +# Add or remove space between function name and '(' on function calls. +sp_func_call_paren = remove # ignore/add/remove/force + +# Add or remove space between a constructor/destructor and the open +# parenthesis. +sp_func_class_paren = remove # ignore/add/remove/force + +# Add or remove space between a constructor without parameters or destructor +# and '()'. +sp_func_class_paren_empty = remove # ignore/add/remove/force + +# Add or remove space between 'return' and '('. +sp_return_paren = force # ignore/add/remove/force + +# Add or remove space between 'return' and '{'. +sp_return_brace = force # ignore/add/remove/force + +# Add or remove space between '__attribute__' and '('. +sp_attribute_paren = remove # ignore/add/remove/force + +# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. +sp_defined_paren = force # ignore/add/remove/force + +# Add or remove space between 'throw' and '(' in 'throw (something)'. +sp_throw_paren = force # ignore/add/remove/force + +# Add or remove space between 'throw' and anything other than '(' as in +# '@throw [...];'. +sp_after_throw = force # ignore/add/remove/force + +# Add or remove space between 'catch' and '(' in 'catch (something) { }'. +# If set to ignore, sp_before_sparen is used. +sp_catch_paren = force # ignore/add/remove/force + +# Add or remove space between a macro function ')' and its definition. +sp_macro_func = add # ignore/add/remove/force + +# Add or remove space between 'else' and '{' if on the same line. +sp_else_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'else' if on the same line. +sp_brace_else = force # ignore/add/remove/force + +# Add or remove space between '}' and the name of a typedef on the same line. +sp_brace_typedef = force # ignore/add/remove/force + +# Add or remove space before the '{' of a 'catch' statement, if the '{' and +# 'catch' are on the same line, as in 'catch (decl) {'. +sp_catch_brace = force # ignore/add/remove/force + +# Add or remove space between '}' and 'catch' if on the same line. +sp_brace_catch = force # ignore/add/remove/force + +# Add or remove space between 'try' and '{' if on the same line. +sp_try_brace = force # ignore/add/remove/force + +# Add or remove space between a variable and '{' for C++ uniform +# initialization. +sp_word_brace_init_lst = remove # ignore/add/remove/force + +# Add or remove space before the '::' operator. +sp_before_dc = remove # ignore/add/remove/force + +# Add or remove space after the '::' operator. +sp_after_dc = remove # ignore/add/remove/force + +# Add or remove space before a backslash-newline at the end of a line. +# +# Default: add +sp_before_nl_cont = add # ignore/add/remove/force + +# Add or remove space around the ':' in 'b ? t : f'. +sp_cond_colon = force # ignore/add/remove/force + +# Add or remove space around the '?' in 'b ? t : f'. +sp_cond_question = force # ignore/add/remove/force + +# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' +# and ':'. +# +# Overrides all other sp_cond_* options. +sp_cond_ternary_short = remove # ignore/add/remove/force + +# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make +# sense here. +sp_case_label = force # ignore/add/remove/force + +# Add or remove space after ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_after_for_colon = force # ignore/add/remove/force + +# Add or remove space before ':' in a Java/C++11 range-based 'for', +# as in 'for (Type var : expr)'. +sp_before_for_colon = force # ignore/add/remove/force + +# Add or remove space after the opening of a C++ comment, +# i.e. '// A' vs. '//A'. +sp_cmt_cpp_start = force # ignore/add/remove/force + +# Add or remove space between #else or #endif and a trailing comment. +sp_endif_cmt = force # ignore/add/remove/force + +# Add or remove space after 'new', 'delete' and 'delete[]'. +sp_after_new = force # ignore/add/remove/force + +# Add or remove space between 'new' and '(' in 'new()'. +sp_between_new_paren = remove # ignore/add/remove/force + +# Add or remove space between ')' and type in 'new(foo) BAR'. +sp_after_newop_paren = force # ignore/add/remove/force + +# Add or remove space inside parenthesis of the new operator +# as in 'new(foo) BAR'. +sp_inside_newop_paren = remove # ignore/add/remove/force + +# Add or remove space before a trailing or embedded comment. +sp_before_tr_cmt = force # ignore/add/remove/force + +# Number of spaces before a trailing or embedded comment. +sp_num_before_tr_cmt = 1 # unsigned number + +# +# Indenting options +# + +# The number of columns to indent per level. Usually 2, 3, 4, or 8. +# +# Default: 8 +indent_columns = 4 # unsigned number + +# The continuation indent. If non-zero, this overrides the indent of '(', '[' +# and '=' continuation indents. Negative values are OK; negative value is +# absolute and not increased for each '(' or '[' level. +# +# For FreeBSD, this is set to 4. +indent_continue = 0 # number + +# How to use tabs when indenting code. +# +# 0: Spaces only +# 1: Indent with tabs to brace level, align with spaces (default) +# 2: Indent and align with tabs, using spaces when not on a tabstop +# +# Default: 1 +indent_with_tabs = 0 # unsigned number + +# Whether to indent strings broken by '\' so that they line up. +indent_align_string = true # true/false + +# Whether the 'extern "C"' body is indented. +indent_extern = true # true/false + +# Whether the 'class' body is indented. +indent_class = true # true/false + +# Whether to indent the stuff after a leading base class colon. +indent_class_colon = false # true/false + +# Whether to indent based on a class colon instead of the stuff after the +# colon. Requires indent_class_colon=true. +indent_class_on_colon = true # true/false + +# Whether to indent the stuff after a leading class initializer colon. +indent_constr_colon = false # true/false + +# Virtual indent from the ':' for member initializers. +# +# Default: 2 +indent_ctor_init_leading = 2 # unsigned number + +# Whether to indent continued variable declarations instead of aligning. +indent_var_def_cont = true # true/false + +# Whether to indent continued function call parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_call_param = true # true/false + +# Whether to indent continued function definition parameters one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_def_param = true # true/false + +# Whether to indent continued function call prototype one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_proto_param = true # true/false + +# Whether to indent continued function call declaration one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_class_param = true # true/false + +# Whether to indent continued class variable constructors one indent level, +# rather than aligning parameters under the open parenthesis. +indent_func_ctor_var_param = true # true/false + +# Whether to indent continued template parameter list one indent level, +# rather than aligning parameters under the open parenthesis. +indent_template_param = true # true/false + +# Whether lines broken at '.' or '->' should be indented by a single indent. +# The indent_member option will not be effective if this is set to true. +indent_member_single = true # true/false + +# Whether to indent trailing single line ('//') comments relative to the code +# instead of trying to keep the same absolute column. +indent_relative_single_line_comments = true # true/false + +# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. +indent_switch_case = 0 # unsigned number + +# Spaces to shift the 'case' line, without affecting any other lines. +# Usually 0. +indent_case_shift = 2 # unsigned number + +# How to indent access specifiers that are followed by a +# colon. +# +# >0: Absolute column where 1 is the leftmost column +# <=0: Subtract from brace indent +# +# Default: 1 +indent_access_spec = -2 # number + +# How to indent a close parenthesis after a newline. +# +# 0: Indent to body level (default) +# 1: Align under the open parenthesis +# 2: Indent to the brace level +indent_paren_close = 2 # unsigned number + +# Whether to align continued statements at the '='. If false or if the '=' is +# followed by a newline, the next line is indent one tab. +# +# Default: true +indent_align_assign = false # true/false + +# Whether to align continued statements at the '('. If false or the '(' is +# followed by a newline, the next line indent is one tab. +# +# Default: true +indent_align_paren = false # true/false + +# How to indent after a brace followed by another token (not a newline). +# true: indent all contained lines to match the token +# false: indent all contained lines to match the brace +# +# Default: true +indent_token_after_brace = false # true/false + +# Whether to indent the body of a C++11 lambda. +indent_cpp_lambda_body = false # true/false +# +# +# Newline adding and removing options +# + +# Whether to collapse empty blocks between '{' and '}'. +nl_collapse_empty_body = true # true/false + +# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. +nl_assign_leave_one_liners = true # true/false + +# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. +nl_cpp_lambda_leave_one_liners = true # true/false + +# Add or remove newlines at the start of the file. +nl_start_of_file = remove # ignore/add/remove/force + +# Add or remove newline at the end of the file. +nl_end_of_file = force # ignore/add/remove/force + +# The minimum number of newlines at the end of the file (only used if +# nl_end_of_file is 'add' or 'force'). +nl_end_of_file_min = 1 # unsigned number + +# Add or remove newline between '=' and '{'. +nl_assign_brace = remove # ignore/add/remove/force + +# Add or remove newline between a function call's ')' and '{', as in +# 'list_for_each(item, &list) { }'. +nl_fcall_brace = force # ignore/add/remove/force + +# Add or remove newline between 'enum' and '{'. +nl_enum_brace = force # ignore/add/remove/force + +# Add or remove newline between 'enum' and 'class'. +nl_enum_class = remove # ignore/add/remove/force + +# Add or remove newline between 'enum class' and the identifier. +nl_enum_class_identifier = remove # ignore/add/remove/force + +# Add or remove newline between 'enum class' type and ':'. +nl_enum_identifier_colon = remove # ignore/add/remove/force + +# Add or remove newline between 'struct and '{'. +nl_struct_brace = force # ignore/add/remove/force + +# Add or remove newline between 'union' and '{'. +nl_union_brace = force # ignore/add/remove/force + +# Add or remove newline between 'if' and '{'. +nl_if_brace = force # ignore/add/remove/force + +# Add or remove newline between '}' and 'else'. +nl_brace_else = remove # ignore/add/remove/force + +# Add or remove newline between 'else if' and '{'. If set to ignore, +# nl_if_brace is used instead. +nl_elseif_brace = force # ignore/add/remove/force + +# Add or remove newline between 'else' and '{'. +nl_else_brace = force # ignore/add/remove/force + +# Add or remove newline between 'else' and 'if'. +nl_else_if = remove # ignore/add/remove/force + +# Add or remove newline before '{' opening brace +nl_before_opening_brace_func_class_def = force # ignore/add/remove/force + +# Add or remove newline before 'if'/'else if' closing parenthesis. +nl_before_if_closing_paren = remove # ignore/add/remove/force + +# Add or remove newline between 'try' and '{'. +nl_try_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'for' and '{'. +nl_for_brace = force # ignore/add/remove/force + +# Add or remove newline before the '{' of a 'catch' statement, as in +# 'catch (decl) {'. +nl_catch_brace = force # ignore/add/remove/force + +# Add or remove newline between '}' and 'catch'. +nl_brace_catch = remove # ignore/add/remove/force + +# Add or remove newline between '}' and ')' in a function invocation. +nl_brace_fparen = remove # ignore/add/remove/force + +# Add or remove newline between 'while' and '{'. +nl_while_brace = force # ignore/add/remove/force + +# Add or remove newline between two open or close braces. Due to general +# newline/brace handling, REMOVE may not work. +nl_brace_brace = remove # ignore/add/remove/force + +# Add or remove newline between 'do' and '{'. +nl_do_brace = remove # ignore/add/remove/force + +# Add or remove newline between '}' and 'while' of 'do' statement. +nl_brace_while = remove # ignore/add/remove/force + +# Add or remove newline between 'switch' and '{'. +nl_switch_brace = force # ignore/add/remove/force + +# Force a newline in a define after the macro name for multi-line defines. +nl_multi_line_define = true # true/false + +# Whether to add a newline before 'case', and a blank line before a 'case' +# statement that follows a ';' or '}'. +nl_before_case = true # true/false + +# Whether to add a newline after a 'case' statement. +nl_after_case = true # true/false + +# Add or remove newline between 'namespace' and '{'. +nl_namespace_brace = true # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template class. +nl_template_class = force # ignore/add/remove/force + +# Add or remove newline after 'template<...>' of a template function. +nl_template_func = force # ignore/add/remove/force + +# Add or remove newline between 'class' and '{'. +nl_class_brace = force # ignore/add/remove/force + +# Add or remove newline before first element, after comma, and after last +# element, in 'enum'. +nl_enum_own_lines = force # ignore/add/remove/force + +# Add or remove newline between return type and function name in a function +# definition. +# might be modified by nl_func_leave_one_liners +nl_func_type_name = remove # ignore/add/remove/force + +# Add or remove newline between class specification and '::' +# in 'void A::f() { }'. Only appears in separate member implementation (does +# not appear with in-line implementation). +nl_func_class_scope = remove # ignore/add/remove/force + +# Add or remove newline between function scope and name, as in +# 'void A :: f() { }'. +nl_func_scope_name = remove # ignore/add/remove/force + +# Add or remove newline between return type and function name in a prototype. +nl_func_proto_type_name = remove # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# declaration. +nl_func_paren = remove # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# definition. +nl_func_def_paren = remove # ignore/add/remove/force + +# Add or remove newline between a function name and the opening '(' in the +# call. +nl_func_call_paren = remove # ignore/add/remove/force + +# Add or remove newline after each ',' in a function declaration. +nl_func_decl_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function definition. +nl_func_def_args = ignore # ignore/add/remove/force + +# Add or remove newline after each ',' in a function call. +nl_func_call_args = ignore # ignore/add/remove/force + +# Add or remove newline before the ')' in a function declaration. +nl_func_decl_end = remove # ignore/add/remove/force + +# Add or remove newline before the ')' in a function definition. +nl_func_def_end = remove # ignore/add/remove/force + +# Add or remove newline between '()' in a function declaration. +nl_func_decl_empty = remove # ignore/add/remove/force + +# Add or remove newline between '()' in a function definition. +nl_func_def_empty = remove # ignore/add/remove/force + +# Add or remove newline between '()' in a function call. +nl_func_call_empty = remove # ignore/add/remove/force + +# Whether to add a newline before ')' in a function call. +nl_func_call_end = remove # ignore/add/remove/force + +# Add or remove newline between function signature and '{'. +nl_fdef_brace = true # ignore/add/remove/force + +# Add or remove newline between C++11 lambda signature and '{'. +nl_cpp_ldef_brace = add # ignore/add/remove/force + +# Whether to add a newline after semicolons, except in 'for' statements. +nl_after_semicolon = true # true/false + +# Whether to add a newline after '{'. This also adds a newline before the +# matching '}'. +nl_after_brace_open = true # true/false + +# Whether to add a newline between the open brace and a trailing single-line +# comment. Requires nl_after_brace_open=true. +nl_after_brace_open_cmt = true # true/false + +# Whether to add a newline after '}'. Does not apply if followed by a +# necessary ';'. +nl_after_brace_close = true # true/false + +# Whether to add a newline after a virtual brace close, +# as in 'if (foo) a++; return;'. +nl_after_vbrace_close = true # true/false + +# Add or remove newline between the close brace and identifier, +# as in 'struct { int a; } b;'. Affects enumerations, unions and +# structures. If set to ignore, uses nl_after_brace_close. +nl_brace_struct_var = remove # ignore/add/remove/force + +# Add or remove blank line after 'if' statement. Add/Force work only if the +# next token is not a closing brace. +nl_after_if = force # ignore/add/remove/force + +# Add or remove blank line after 'for' statement. +nl_after_for = force # ignore/add/remove/force + +# Add or remove blank line after 'while' statement. +nl_after_while = force # ignore/add/remove/force + +# Add or remove blank line after 'switch' statement. +nl_after_switch = force # ignore/add/remove/force + +# Add or remove blank line after 'do/while' statement. +nl_after_do = force # ignore/add/remove/force + +# Whether to put a blank line before 'return' statements, unless after an open +# brace. +nl_before_return = false # true/false + +# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. +# (Lower priority than eat_blanks_before_close_brace.) +nl_ds_struct_enum_close_brace = true # true/false + + +# Blank line options +# + +# The maximum number of consecutive newlines (3 = 2 blank lines). +nl_max = 0 # unsigned number + +# The maximum number of consecutive newlines in a function. +nl_max_blank_in_func = 2 # unsigned number + +# The number of newlines after '}' of a multi-line function body. +nl_after_func_body = 2 # unsigned number + +# The number of newlines after '}' of a multi-line function body in a class +# declaration. Also affects class constructors/destructors. +# +# Overrides nl_after_func_body. +nl_after_func_body_class = 2 # unsigned number + +# The number of newlines after '}' or ';' of a struct/enum/union definition. +nl_after_struct = 2 # unsigned number + +# The number of newlines after '}' or ';' of a class definition. +nl_after_class = 2 # unsigned number + +# The number of newlines after '}' of a namespace. +nl_after_namespace = 2 # unsigned number + +# The number of newlines before an access specifier label. This also includes +# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count +# if after a brace open. +# +# 0: No change (default). +nl_before_access_spec = 2 # unsigned number + +# The number of newlines after a try-catch-finally block that isn't followed +# by a brace close. +# +# 0: No change (default). +nl_after_try_catch_finally = 2 # unsigned number + +# Whether to remove blank lines after '{'. +eat_blanks_after_open_brace = true # true/false + +# Whether to remove blank lines before '}'. +eat_blanks_before_close_brace = true # true/false + +# +# Positioning options +# + +# The position of arithmetic operators in wrapped expressions. +pos_arith = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of assignment in wrapped expressions. Do not affect '=' +# followed by '{'. +pos_assign = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of Boolean operators in wrapped expressions. +pos_bool = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of comparison operators in wrapped expressions. +pos_compare = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of conditional operators, as in the '?' and ':' of +# 'expr ? stmt : stmt', in wrapped expressions. +pos_conditional = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in wrapped expressions. +pos_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in enum entries. +pos_enum_comma = trail_force # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the base class list if there is more than one +# line. Affects nl_class_init_args. +pos_class_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of the comma in the constructor initialization list. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. +pos_constr_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of trailing/leading class colon, between class and base class +# list. Affects nl_class_colon. +pos_class_colon = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# The position of colons between constructor and member initialization. +# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. +pos_constr_colon = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force + +# +# Code alignment options (not left column spaces/tabs) +# + +# The span for aligning on '=' in assignments. +# +# 0: Don't align (default). +align_assign_span = 1 # unsigned number +align_assign_thresh = -4 # number + +align_enum_equ_span = 4 # unsigned number +align_enum_equ_thresh = -20 # number + +align_number_right = true # true/false +# +# Line splitting options +# + +# Try to limit code width to N columns. +code_width = 110 # unsigned number + +# Whether to fully split long 'for' statements at semi-colons. +ls_for_split_full = true # true/false + +# Whether to fully split long function prototypes/calls at commas. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_func_split_full = false # true/false + +# Whether to split lines as close to code_width as possible and ignore some +# groupings. +# The option ls_code_width has priority over the option ls_func_split_full. +ls_code_width = false # true/false + +# +# Comment modification options +# + +# Try to wrap comments at N columns. +cmt_width = 110 # unsigned number + +# How to reflow comments. +# +# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) +# 1: No touching at all +# 2: Full reflow +cmt_reflow_mode = 2 # unsigned number + +# Whether to convert all tabs to spaces in comments. If false, tabs in +# comments are left alone, unless used for indenting. +cmt_convert_tab_to_spaces = true # true/false + +# Whether to group c-comments that look like they are in a block. +cmt_c_group = true # true/false + +# Whether to put a star on subsequent comment lines. +cmt_star_cont = true # true/false + +# Whether to put an empty '/*' on the first line of the combined c-comment. +cmt_c_nl_start = true # true/false + +# Whether to add a newline before the closing '*/' of the combined c-comment. +cmt_c_nl_end = true # true/false + +# The number of spaces to insert at the start of subsequent comment lines. +cmt_sp_before_star_cont = 0 # unsigned number + +# The number of spaces to insert after the star on subsequent comment lines. +cmt_sp_after_star_cont = 1 # unsigned number + +# +# Code modifying options (non-whitespace) +# + +# Add or remove braces on a single-line 'do' statement. +mod_full_brace_do = force # ignore/add/remove/force + +# Add or remove braces on a single-line 'for' statement. +mod_full_brace_for = force # ignore/add/remove/force + +# (Pawn) Add or remove braces on a single-line function definition. +mod_full_brace_function = force # ignore/add/remove/force + +# Add or remove braces on a single-line 'if' statement. Braces will not be +# removed if the braced statement contains an 'else'. +mod_full_brace_if = force # ignore/add/remove/force + +# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. +# If true, mod_full_brace_if_chain will only remove braces from an 'if' that +# does not have an 'else if' or 'else'. +mod_full_brace_if_chain_only = true # true/false + +# Add or remove braces on single-line 'while' statement. +mod_full_brace_while = force # ignore/add/remove/force + +# Whether to fully parenthesize Boolean expressions in 'while' and 'if' +# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. +mod_full_paren_if_bool = true # true/false + +# Whether to remove superfluous semicolons. +mod_remove_extra_semicolon = true # true/false + +# If an #ifdef body exceeds the specified number of newlines and doesn't have +# a comment after the #endif, a comment will be added. +mod_add_long_ifdef_endif_comment = 0 # unsigned number + +# If an #ifdef or #else body exceeds the specified number of newlines and +# doesn't have a comment after the #else, a comment will be added. +mod_add_long_ifdef_else_comment = 0 # unsigned number + +# Whether to remove a void 'return;' that appears as the last statement in a +# function. +mod_remove_empty_return = false # true/false + +# Add or remove the comma after the last value of an enumeration. +mod_enum_last_comma = force # ignore/add/remove/force + +# +# Preprocessor options +# + +# Add or remove indentation of preprocessor directives inside #if blocks +# at brace level 0 (file-level). +pp_indent = add # ignore/add/remove/force +pp_indent_count = 4 + +# Whether to indent the code between #if, #else and #endif. +pp_if_indent_code = false # true/false + +# Use or Do not Use options +# + +# true: indent_func_call_param will be used (default) +# false: indent_func_call_param will NOT be used +# +# Default: true +use_indent_func_call_param = true # true/false + +# The value of the indentation for a continuation line is calculated +# differently if the statement is: +# - a declaration: your case with QString fileName ... +# - an assignment: your case with pSettings = new QSettings( ... +# +# At the second case the indentation value might be used twice: +# - at the assignment +# - at the function call (if present) +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indent_continue will be used only once +# false: indent_continue will be used every time (default) +use_indent_continue_only_once = true # true/false + +# The value might be used twice: +# - at the assignment +# - at the opening brace +# +# To prevent the double use of the indentation value, use this option with the +# value 'true'. +# +# true: indentation will be used only once +# false: indentation will be used every time (default) +indent_cpp_lambda_only_once = true # true/false + +# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the +# historic behavior, but is probably not the desired behavior, so this is off +# by default. +use_sp_after_angle_always = false # true/false From 3b9aeefb6ed65f2d7966de51b06a26807fa5888f Mon Sep 17 00:00:00 2001 From: WShad Date: Fri, 14 Nov 2025 15:41:47 +0300 Subject: [PATCH 11/21] fix: update to GTK4, deps --- src/panel/panel.cpp | 2 +- src/panel/widgets/language.cpp | 10 ++++------ src/panel/widgets/language.hpp | 4 ++-- src/util/json.cpp | 2 -- src/util/wf-ipc.cpp | 5 +++-- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 4c5a2124..93e5ae12 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -170,7 +170,7 @@ class WayfirePanel::impl if (name == "window-list") { - return Widget(new WayfireWindowList(output, ipc_manager->get_IPC())); + return Widget(new WayfireWindowList(output)); } if (name == "notifications") diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index e6995902..c925e72a 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -13,15 +13,13 @@ #include "gtkmm/button.h" #include "sigc++/functors/mem_fun.h" -void WayfireLanguage::init(Gtk::HBox *container) +void WayfireLanguage::init(Gtk::Box *container) { button.get_style_context()->add_class("language"); - button.add(label); button.get_style_context()->add_class("flat"); button.get_style_context()->remove_class("activated"); - button.signal_clicked().connect_notify(sigc::mem_fun(this, &WayfireLanguage::next_layout)); + button.signal_clicked().connect(sigc::mem_fun(*this, &WayfireLanguage::next_layout)); button.show(); - label.show(); ipc->subscribe(this, {"keyboard-modifier-state-changed"}); ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (json_t data) @@ -30,7 +28,7 @@ void WayfireLanguage::init(Gtk::HBox *container) set_current(data["layout-index"]); }); - container->pack_start(button, false, false); + container->append(button); } void WayfireLanguage::on_event(json_t data) @@ -63,7 +61,7 @@ bool WayfireLanguage::update_label() return false; } - label.set_text(available_layouts[current_layout].ID); + button.set_label(available_layouts[current_layout].ID); return true; } diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp index 7223643e..b2899077 100644 --- a/src/panel/widgets/language.hpp +++ b/src/panel/widgets/language.hpp @@ -19,7 +19,7 @@ struct Layout class WayfireLanguage : public WayfireWidget, public IIPCSubscriber { - Gtk::Label label; + // Gtk::Label label; Gtk::Button button; std::shared_ptr ipc; @@ -27,7 +27,7 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber std::vector available_layouts; public: - void init(Gtk::HBox *container) override; + void init(Gtk::Box *container); void on_event(json_t data) override; bool update_label(); void set_current(uint32_t index); diff --git a/src/util/json.cpp b/src/util/json.cpp index 6c5b67d8..948c1401 100644 --- a/src/util/json.cpp +++ b/src/util/json.cpp @@ -1,8 +1,6 @@ #include "json.hpp" #include #include -#include -#include #include #include diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index 76e55950..a3a25edc 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +32,7 @@ WayfireIPC::WayfireIPC() connect(); sig_connection = Glib::signal_io().connect( - sigc::mem_fun(this, &WayfireIPC::receive), + sigc::mem_fun(*this, &WayfireIPC::receive), connection->get_socket()->get_fd(), Glib::IO_IN); } @@ -99,7 +100,7 @@ void WayfireIPC::write_next() writing = true; sig_connection = Glib::signal_io().connect( - sigc::mem_fun(this, &WayfireIPC::send_queue), + sigc::mem_fun(*this, &WayfireIPC::send_queue), connection->get_socket()->get_fd(), Glib::IO_OUT); } From c36628922f9001cd23077926a3f31ad972db8213 Mon Sep 17 00:00:00 2001 From: WShad Date: Fri, 14 Nov 2025 15:45:30 +0300 Subject: [PATCH 12/21] remove uncrustify --- uncrustify.ini | 1108 ------------------------------------------------ 1 file changed, 1108 deletions(-) delete mode 100644 uncrustify.ini diff --git a/uncrustify.ini b/uncrustify.ini deleted file mode 100644 index 04c55fb7..00000000 --- a/uncrustify.ini +++ /dev/null @@ -1,1108 +0,0 @@ -# Uncrustify_d-0.71.0-21-d4da2b0f - -# -# General options -# - -# The type of line endings. -# -# Default: auto -newlines = auto # lf/crlf/cr/auto - -# The original size of tabs in the input. -# -# Default: 8 -input_tab_size = 4 # unsigned number - -# The size of tabs in the output (only used if align_with_tabs=true). -# -# Default: 8 -output_tab_size = 4 # unsigned number - -# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). -# -# Default: 92 -string_escape_char = 92 # unsigned number - -# Alternate string escape char (usually only used for Pawn). -# Only works right before the quote char. -string_escape_char2 = 0 # unsigned number - -# Replace tab characters found in string literals with the escape sequence \t -# instead. -string_replace_tab_chars = true # true/false - -# Allow interpreting '>=' and '>>=' as part of a template in code like -# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. -# Improvements to template detection may make this option obsolete. -tok_split_gte = false # true/false - -# Disable formatting of NL_CONT ('\\n') ended lines (e.g. multiline macros) -disable_processing_nl_cont = false # true/false - -# Specify the marker used in comments to disable processing of part of the -# file. -# The comment should be used alone in one line. -# -# Default: *INDENT-OFF* -disable_processing_cmt = " *INDENT-OFF*" # string - -# Specify the marker used in comments to (re)enable processing in a file. -# The comment should be used alone in one line. -# -# Default: *INDENT-ON* -enable_processing_cmt = " *INDENT-ON*" # string - -# Enable parsing of digraphs. -enable_digraphs = false # true/false - -# Add or remove the UTF-8 BOM (recommend 'remove'). -utf8_bom = ignore # ignore/add/remove/force - -# If the file contains bytes with values between 128 and 255, but is not -# UTF-8, then output as UTF-8. -utf8_byte = false # true/false - -# Force the output encoding to UTF-8. -utf8_force = false # true/false - -# Add or remove space between 'do' and '{'. -sp_do_brace_open = force # ignore/add/remove/force - -# Add or remove space between '}' and 'while'. -sp_brace_close_while = force # ignore/add/remove/force - -# Add or remove space between 'while' and '('. -sp_while_paren_open = force # ignore/add/remove/force - -# -# Spacing options -# - -# Add or remove space around non-assignment symbolic operators ('+', '/', '%', -# '<<', and so forth). -sp_arith = force # ignore/add/remove/force - -# Add or remove space around assignment operator '=', '+=', etc. -sp_assign = force # ignore/add/remove/force - -# Add or remove space around '=' in C++11 lambda capture specifications. -# -# Overrides sp_assign. -sp_cpp_lambda_assign = remove # ignore/add/remove/force - -# Add or remove space after the capture specification of a C++11 lambda when -# an argument list is present, as in '[] (int x){ ... }'. -sp_cpp_lambda_square_paren = force # ignore/add/remove/force - -# Add or remove space after the capture specification of a C++11 lambda with -# no argument list is present, as in '[] { ... }'. -sp_cpp_lambda_square_brace = force # ignore/add/remove/force - -# Add or remove space after the argument list of a C++11 lambda, as in -# '[](int x) { ... }'. -sp_cpp_lambda_paren_brace = force # ignore/add/remove/force - -# Add or remove space in 'NS_ENUM ('. -sp_enum_paren = ignore # ignore/add/remove/force - -# Add or remove space around assignment '=' in enum. -sp_enum_assign = add # ignore/add/remove/force - -# Add or remove space around assignment ':' in enum. -sp_enum_colon = force # ignore/add/remove/force - -# Add or remove space around boolean operators '&&' and '||'. -sp_bool = force # ignore/add/remove/force - -# Add or remove space around compare operator '<', '>', '==', etc. -sp_compare = force # ignore/add/remove/force - -# Add or remove space inside '(' and ')'. -sp_inside_paren = remove # ignore/add/remove/force - -# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. -sp_paren_paren = remove # ignore/add/remove/force - -# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. -sp_cparen_oparen = remove # ignore/add/remove/force - -# Add or remove space between ')' and '{'. -sp_paren_brace = add # ignore/add/remove/force - -# Add or remove space between nested braces, i.e. '{{' vs '{ {'. -sp_brace_brace = remove # ignore/add/remove/force - -# Add or remove space before pointer star '*'. -sp_before_ptr_star = force # ignore/add/remove/force - -# Add or remove space between pointer stars '*'. -sp_between_ptr_star = remove # ignore/add/remove/force - -# Add or remove space after pointer star '*', if followed by a word. -# -# Overrides sp_type_func. -sp_after_ptr_star = remove # ignore/add/remove/force - -# Add or remove space before pointer star '*' that isn't followed by a -# variable name. If set to ignore, sp_before_ptr_star is used instead. -sp_before_unnamed_ptr_star = remove # ignore/add/remove/force - -# Add or remove space before a pointer star '*', if followed by a function -# prototype or function definition. -sp_before_ptr_star_func = force # ignore/add/remove/force - -# Add or remove space before a reference sign '&'. -sp_before_byref = ignore # ignore/add/remove/force - -# Add or remove space after reference sign '&', if followed by a word. -# -# Overrides sp_type_func. -sp_after_byref = force # ignore/add/remove/force - -# Add or remove space before a reference sign '&', if followed by a function -# prototype or function definition. -sp_before_byref_func = remove # ignore/add/remove/force - -# Add or remove space between 'decltype(...)' and word. -sp_after_decltype = force # ignore/add/remove/force - -# Add or remove space before '<'. -sp_before_angle = remove # ignore/add/remove/force - -# Add or remove space inside '<' and '>'. -sp_inside_angle = remove # ignore/add/remove/force - -# Add or remove space inside '<>'. -sp_inside_angle_empty = remove # ignore/add/remove/force - -# Add or remove space between '>' and ':'. -sp_angle_colon = force # ignore/add/remove/force - -# Add or remove space after '>'. -sp_after_angle = force # ignore/add/remove/force - -# Add or remove space between '>' and '(' as found in 'new List(foo);'. -sp_angle_paren = remove # ignore/add/remove/force - -# Add or remove space between '>' and '()' as found in 'new List();'. -sp_angle_paren_empty = remove # ignore/add/remove/force - -# Add or remove space between '>' and a word as in 'List m;' or -# 'template static ...'. -sp_angle_word = force # ignore/add/remove/force - -# Add or remove space between '>' and '>' in '>>' (template stuff). -# -# Default: add -sp_angle_shift = remove # ignore/add/remove/force - -# (C++11) Permit removal of the space between '>>' in 'foo >'. Note -# that sp_angle_shift cannot remove the space without this option. -sp_permit_cpp11_shift = true # true/false - -# Add or remove space before '(' of control statements ('if', 'for', 'switch', -# 'while', etc.). -sp_before_sparen = force # ignore/add/remove/force - -# Add or remove space inside '(' and ')' of control statements. -sp_inside_sparen = remove # ignore/add/remove/force - -# Add or remove space between ')' and '{' of of control statements. -sp_sparen_brace = force # ignore/add/remove/force - -# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. -sp_special_semi = remove # ignore/add/remove/force - -# Add or remove space before ';' in non-empty 'for' statements. -sp_before_semi_for = remove # ignore/add/remove/force - -# Add or remove space before a semicolon of an empty part of a for statement. -sp_before_semi_for_empty = remove # ignore/add/remove/force - -# Add or remove space after ';', except when followed by a comment. -# -# Default: add -sp_after_semi = remove # ignore/add/remove/force - -# Add or remove space after ';' in non-empty 'for' statements. -# -# Default: force -sp_after_semi_for = force # ignore/add/remove/force - -# Add or remove space after the final semicolon of an empty part of a for -# statement, as in 'for ( ; ; )'. -sp_after_semi_for_empty = remove # ignore/add/remove/force - -# Add or remove space before '[' (except '[]'). -sp_before_square = remove # ignore/add/remove/force - -# Add or remove space before '[' for a variable definition. -# -# Default: remove -sp_before_vardef_square = remove # ignore/add/remove/force - -# Add or remove space before '[]'. -sp_before_squares = remove # ignore/add/remove/force - -# Add or remove space before C++17 structured bindings. -sp_cpp_before_struct_binding = force # ignore/add/remove/force - -# Add or remove space inside a non-empty '[' and ']'. -sp_inside_square = remove # ignore/add/remove/force - -# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. -sp_after_comma = force # ignore/add/remove/force - -# Add or remove space before the variadic '...' when preceded by a -# non-punctuator. -sp_before_ellipsis = remove # ignore/add/remove/force - -# Add or remove space between a type and '...'. -sp_type_ellipsis = remove # ignore/add/remove/force - -# Add or remove space between ')' and '...'. -sp_paren_ellipsis = remove # ignore/add/remove/force - -# Add or remove space between ')' and a qualifier such as 'const'. -sp_paren_qualifier = force # ignore/add/remove/force - -# Add or remove space between ')' and 'noexcept'. -sp_paren_noexcept = force # ignore/add/remove/force - -# Add or remove space after class ':'. -sp_after_class_colon = force # ignore/add/remove/force - -# Add or remove space before class ':'. -sp_before_class_colon = force # ignore/add/remove/force - -# Add or remove space after class constructor ':'. -sp_after_constr_colon = force # ignore/add/remove/force - -# Add or remove space before class constructor ':'. -sp_before_constr_colon = force # ignore/add/remove/force - -# Add or remove space between 'operator' and operator sign. -sp_after_operator = force # ignore/add/remove/force - -# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or -# '(int)a' vs. '(int) a'. -sp_after_cast = remove # ignore/add/remove/force - -# Add or remove spaces inside cast parentheses. -sp_inside_paren_cast = remove # ignore/add/remove/force - -# Add or remove space between the type and open parenthesis in a C++ cast, -# i.e. 'int(exp)' vs. 'int (exp)'. -sp_cpp_cast_paren = remove # ignore/add/remove/force - -# Add or remove space between 'sizeof' and '('. -sp_sizeof_paren = remove # ignore/add/remove/force - -# Add or remove space between 'sizeof' and '...'. -sp_sizeof_ellipsis = remove # ignore/add/remove/force - -# Add or remove space between 'sizeof...' and '('. -sp_sizeof_ellipsis_paren = remove # ignore/add/remove/force - -# Add or remove space between 'decltype' and '('. -sp_decltype_paren = remove # ignore/add/remove/force - -# Add or remove space after open brace in an unnamed temporary -# direct-list-initialization. -sp_after_type_brace_init_lst_open = remove # ignore/add/remove/force - -# Add or remove space before close brace in an unnamed temporary -# direct-list-initialization. -sp_before_type_brace_init_lst_close = remove # ignore/add/remove/force - -# Add or remove space inside '{}'. -sp_inside_braces_empty = remove # ignore/add/remove/force - -# Add or remove space around trailing return operator '->'. -sp_trailing_return = force # ignore/add/remove/force - -# Add or remove space between type and open brace of an unnamed temporary -# direct-list-initialization. -sp_type_brace_init_lst = remove # ignore/add/remove/force - -# Add or remove space between function name and '(' on function declaration. -sp_func_proto_paren = remove # ignore/add/remove/force - -# Add or remove space between function name and '()' on function declaration -# without parameters. -sp_func_proto_paren_empty = remove # ignore/add/remove/force - -# Add or remove space between function name and '(' with a typedef specifier. -sp_func_type_paren = remove # ignore/add/remove/force - -# Add or remove space between alias name and '(' of a non-pointer function type typedef. -sp_func_def_paren = remove # ignore/add/remove/force - -# Add or remove space between function name and '()' on function definition -# without parameters. -sp_func_def_paren_empty = remove # ignore/add/remove/force - -# Add or remove space inside empty function '()'. -# Overrides sp_after_angle unless use_sp_after_angle_always is set to true. -sp_inside_fparens = remove # ignore/add/remove/force - -# Add or remove space inside function '(' and ')'. -sp_inside_fparen = remove # ignore/add/remove/force - -# Add or remove space inside the first parentheses in a function type, as in -# 'void (*x)(...)'. -sp_inside_tparen = remove # ignore/add/remove/force - -# Add or remove space between ']' and '(' when part of a function call. -sp_square_fparen = remove # ignore/add/remove/force - -# Add or remove space between ')' and '{' of function. -sp_fparen_brace = force # ignore/add/remove/force - -# Add or remove space between function name and '(' on function calls. -sp_func_call_paren = remove # ignore/add/remove/force - -# Add or remove space between a constructor/destructor and the open -# parenthesis. -sp_func_class_paren = remove # ignore/add/remove/force - -# Add or remove space between a constructor without parameters or destructor -# and '()'. -sp_func_class_paren_empty = remove # ignore/add/remove/force - -# Add or remove space between 'return' and '('. -sp_return_paren = force # ignore/add/remove/force - -# Add or remove space between 'return' and '{'. -sp_return_brace = force # ignore/add/remove/force - -# Add or remove space between '__attribute__' and '('. -sp_attribute_paren = remove # ignore/add/remove/force - -# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. -sp_defined_paren = force # ignore/add/remove/force - -# Add or remove space between 'throw' and '(' in 'throw (something)'. -sp_throw_paren = force # ignore/add/remove/force - -# Add or remove space between 'throw' and anything other than '(' as in -# '@throw [...];'. -sp_after_throw = force # ignore/add/remove/force - -# Add or remove space between 'catch' and '(' in 'catch (something) { }'. -# If set to ignore, sp_before_sparen is used. -sp_catch_paren = force # ignore/add/remove/force - -# Add or remove space between a macro function ')' and its definition. -sp_macro_func = add # ignore/add/remove/force - -# Add or remove space between 'else' and '{' if on the same line. -sp_else_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'else' if on the same line. -sp_brace_else = force # ignore/add/remove/force - -# Add or remove space between '}' and the name of a typedef on the same line. -sp_brace_typedef = force # ignore/add/remove/force - -# Add or remove space before the '{' of a 'catch' statement, if the '{' and -# 'catch' are on the same line, as in 'catch (decl) {'. -sp_catch_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'catch' if on the same line. -sp_brace_catch = force # ignore/add/remove/force - -# Add or remove space between 'try' and '{' if on the same line. -sp_try_brace = force # ignore/add/remove/force - -# Add or remove space between a variable and '{' for C++ uniform -# initialization. -sp_word_brace_init_lst = remove # ignore/add/remove/force - -# Add or remove space before the '::' operator. -sp_before_dc = remove # ignore/add/remove/force - -# Add or remove space after the '::' operator. -sp_after_dc = remove # ignore/add/remove/force - -# Add or remove space before a backslash-newline at the end of a line. -# -# Default: add -sp_before_nl_cont = add # ignore/add/remove/force - -# Add or remove space around the ':' in 'b ? t : f'. -sp_cond_colon = force # ignore/add/remove/force - -# Add or remove space around the '?' in 'b ? t : f'. -sp_cond_question = force # ignore/add/remove/force - -# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' -# and ':'. -# -# Overrides all other sp_cond_* options. -sp_cond_ternary_short = remove # ignore/add/remove/force - -# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make -# sense here. -sp_case_label = force # ignore/add/remove/force - -# Add or remove space after ':' in a Java/C++11 range-based 'for', -# as in 'for (Type var : expr)'. -sp_after_for_colon = force # ignore/add/remove/force - -# Add or remove space before ':' in a Java/C++11 range-based 'for', -# as in 'for (Type var : expr)'. -sp_before_for_colon = force # ignore/add/remove/force - -# Add or remove space after the opening of a C++ comment, -# i.e. '// A' vs. '//A'. -sp_cmt_cpp_start = force # ignore/add/remove/force - -# Add or remove space between #else or #endif and a trailing comment. -sp_endif_cmt = force # ignore/add/remove/force - -# Add or remove space after 'new', 'delete' and 'delete[]'. -sp_after_new = force # ignore/add/remove/force - -# Add or remove space between 'new' and '(' in 'new()'. -sp_between_new_paren = remove # ignore/add/remove/force - -# Add or remove space between ')' and type in 'new(foo) BAR'. -sp_after_newop_paren = force # ignore/add/remove/force - -# Add or remove space inside parenthesis of the new operator -# as in 'new(foo) BAR'. -sp_inside_newop_paren = remove # ignore/add/remove/force - -# Add or remove space before a trailing or embedded comment. -sp_before_tr_cmt = force # ignore/add/remove/force - -# Number of spaces before a trailing or embedded comment. -sp_num_before_tr_cmt = 1 # unsigned number - -# -# Indenting options -# - -# The number of columns to indent per level. Usually 2, 3, 4, or 8. -# -# Default: 8 -indent_columns = 4 # unsigned number - -# The continuation indent. If non-zero, this overrides the indent of '(', '[' -# and '=' continuation indents. Negative values are OK; negative value is -# absolute and not increased for each '(' or '[' level. -# -# For FreeBSD, this is set to 4. -indent_continue = 0 # number - -# How to use tabs when indenting code. -# -# 0: Spaces only -# 1: Indent with tabs to brace level, align with spaces (default) -# 2: Indent and align with tabs, using spaces when not on a tabstop -# -# Default: 1 -indent_with_tabs = 0 # unsigned number - -# Whether to indent strings broken by '\' so that they line up. -indent_align_string = true # true/false - -# Whether the 'extern "C"' body is indented. -indent_extern = true # true/false - -# Whether the 'class' body is indented. -indent_class = true # true/false - -# Whether to indent the stuff after a leading base class colon. -indent_class_colon = false # true/false - -# Whether to indent based on a class colon instead of the stuff after the -# colon. Requires indent_class_colon=true. -indent_class_on_colon = true # true/false - -# Whether to indent the stuff after a leading class initializer colon. -indent_constr_colon = false # true/false - -# Virtual indent from the ':' for member initializers. -# -# Default: 2 -indent_ctor_init_leading = 2 # unsigned number - -# Whether to indent continued variable declarations instead of aligning. -indent_var_def_cont = true # true/false - -# Whether to indent continued function call parameters one indent level, -# rather than aligning parameters under the open parenthesis. -indent_func_call_param = true # true/false - -# Whether to indent continued function definition parameters one indent level, -# rather than aligning parameters under the open parenthesis. -indent_func_def_param = true # true/false - -# Whether to indent continued function call prototype one indent level, -# rather than aligning parameters under the open parenthesis. -indent_func_proto_param = true # true/false - -# Whether to indent continued function call declaration one indent level, -# rather than aligning parameters under the open parenthesis. -indent_func_class_param = true # true/false - -# Whether to indent continued class variable constructors one indent level, -# rather than aligning parameters under the open parenthesis. -indent_func_ctor_var_param = true # true/false - -# Whether to indent continued template parameter list one indent level, -# rather than aligning parameters under the open parenthesis. -indent_template_param = true # true/false - -# Whether lines broken at '.' or '->' should be indented by a single indent. -# The indent_member option will not be effective if this is set to true. -indent_member_single = true # true/false - -# Whether to indent trailing single line ('//') comments relative to the code -# instead of trying to keep the same absolute column. -indent_relative_single_line_comments = true # true/false - -# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. -indent_switch_case = 0 # unsigned number - -# Spaces to shift the 'case' line, without affecting any other lines. -# Usually 0. -indent_case_shift = 2 # unsigned number - -# How to indent access specifiers that are followed by a -# colon. -# -# >0: Absolute column where 1 is the leftmost column -# <=0: Subtract from brace indent -# -# Default: 1 -indent_access_spec = -2 # number - -# How to indent a close parenthesis after a newline. -# -# 0: Indent to body level (default) -# 1: Align under the open parenthesis -# 2: Indent to the brace level -indent_paren_close = 2 # unsigned number - -# Whether to align continued statements at the '='. If false or if the '=' is -# followed by a newline, the next line is indent one tab. -# -# Default: true -indent_align_assign = false # true/false - -# Whether to align continued statements at the '('. If false or the '(' is -# followed by a newline, the next line indent is one tab. -# -# Default: true -indent_align_paren = false # true/false - -# How to indent after a brace followed by another token (not a newline). -# true: indent all contained lines to match the token -# false: indent all contained lines to match the brace -# -# Default: true -indent_token_after_brace = false # true/false - -# Whether to indent the body of a C++11 lambda. -indent_cpp_lambda_body = false # true/false -# -# -# Newline adding and removing options -# - -# Whether to collapse empty blocks between '{' and '}'. -nl_collapse_empty_body = true # true/false - -# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. -nl_assign_leave_one_liners = true # true/false - -# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. -nl_cpp_lambda_leave_one_liners = true # true/false - -# Add or remove newlines at the start of the file. -nl_start_of_file = remove # ignore/add/remove/force - -# Add or remove newline at the end of the file. -nl_end_of_file = force # ignore/add/remove/force - -# The minimum number of newlines at the end of the file (only used if -# nl_end_of_file is 'add' or 'force'). -nl_end_of_file_min = 1 # unsigned number - -# Add or remove newline between '=' and '{'. -nl_assign_brace = remove # ignore/add/remove/force - -# Add or remove newline between a function call's ')' and '{', as in -# 'list_for_each(item, &list) { }'. -nl_fcall_brace = force # ignore/add/remove/force - -# Add or remove newline between 'enum' and '{'. -nl_enum_brace = force # ignore/add/remove/force - -# Add or remove newline between 'enum' and 'class'. -nl_enum_class = remove # ignore/add/remove/force - -# Add or remove newline between 'enum class' and the identifier. -nl_enum_class_identifier = remove # ignore/add/remove/force - -# Add or remove newline between 'enum class' type and ':'. -nl_enum_identifier_colon = remove # ignore/add/remove/force - -# Add or remove newline between 'struct and '{'. -nl_struct_brace = force # ignore/add/remove/force - -# Add or remove newline between 'union' and '{'. -nl_union_brace = force # ignore/add/remove/force - -# Add or remove newline between 'if' and '{'. -nl_if_brace = force # ignore/add/remove/force - -# Add or remove newline between '}' and 'else'. -nl_brace_else = remove # ignore/add/remove/force - -# Add or remove newline between 'else if' and '{'. If set to ignore, -# nl_if_brace is used instead. -nl_elseif_brace = force # ignore/add/remove/force - -# Add or remove newline between 'else' and '{'. -nl_else_brace = force # ignore/add/remove/force - -# Add or remove newline between 'else' and 'if'. -nl_else_if = remove # ignore/add/remove/force - -# Add or remove newline before '{' opening brace -nl_before_opening_brace_func_class_def = force # ignore/add/remove/force - -# Add or remove newline before 'if'/'else if' closing parenthesis. -nl_before_if_closing_paren = remove # ignore/add/remove/force - -# Add or remove newline between 'try' and '{'. -nl_try_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'for' and '{'. -nl_for_brace = force # ignore/add/remove/force - -# Add or remove newline before the '{' of a 'catch' statement, as in -# 'catch (decl) {'. -nl_catch_brace = force # ignore/add/remove/force - -# Add or remove newline between '}' and 'catch'. -nl_brace_catch = remove # ignore/add/remove/force - -# Add or remove newline between '}' and ')' in a function invocation. -nl_brace_fparen = remove # ignore/add/remove/force - -# Add or remove newline between 'while' and '{'. -nl_while_brace = force # ignore/add/remove/force - -# Add or remove newline between two open or close braces. Due to general -# newline/brace handling, REMOVE may not work. -nl_brace_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'do' and '{'. -nl_do_brace = remove # ignore/add/remove/force - -# Add or remove newline between '}' and 'while' of 'do' statement. -nl_brace_while = remove # ignore/add/remove/force - -# Add or remove newline between 'switch' and '{'. -nl_switch_brace = force # ignore/add/remove/force - -# Force a newline in a define after the macro name for multi-line defines. -nl_multi_line_define = true # true/false - -# Whether to add a newline before 'case', and a blank line before a 'case' -# statement that follows a ';' or '}'. -nl_before_case = true # true/false - -# Whether to add a newline after a 'case' statement. -nl_after_case = true # true/false - -# Add or remove newline between 'namespace' and '{'. -nl_namespace_brace = true # ignore/add/remove/force - -# Add or remove newline after 'template<...>' of a template class. -nl_template_class = force # ignore/add/remove/force - -# Add or remove newline after 'template<...>' of a template function. -nl_template_func = force # ignore/add/remove/force - -# Add or remove newline between 'class' and '{'. -nl_class_brace = force # ignore/add/remove/force - -# Add or remove newline before first element, after comma, and after last -# element, in 'enum'. -nl_enum_own_lines = force # ignore/add/remove/force - -# Add or remove newline between return type and function name in a function -# definition. -# might be modified by nl_func_leave_one_liners -nl_func_type_name = remove # ignore/add/remove/force - -# Add or remove newline between class specification and '::' -# in 'void A::f() { }'. Only appears in separate member implementation (does -# not appear with in-line implementation). -nl_func_class_scope = remove # ignore/add/remove/force - -# Add or remove newline between function scope and name, as in -# 'void A :: f() { }'. -nl_func_scope_name = remove # ignore/add/remove/force - -# Add or remove newline between return type and function name in a prototype. -nl_func_proto_type_name = remove # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the -# declaration. -nl_func_paren = remove # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the -# definition. -nl_func_def_paren = remove # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the -# call. -nl_func_call_paren = remove # ignore/add/remove/force - -# Add or remove newline after each ',' in a function declaration. -nl_func_decl_args = ignore # ignore/add/remove/force - -# Add or remove newline after each ',' in a function definition. -nl_func_def_args = ignore # ignore/add/remove/force - -# Add or remove newline after each ',' in a function call. -nl_func_call_args = ignore # ignore/add/remove/force - -# Add or remove newline before the ')' in a function declaration. -nl_func_decl_end = remove # ignore/add/remove/force - -# Add or remove newline before the ')' in a function definition. -nl_func_def_end = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function declaration. -nl_func_decl_empty = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function definition. -nl_func_def_empty = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function call. -nl_func_call_empty = remove # ignore/add/remove/force - -# Whether to add a newline before ')' in a function call. -nl_func_call_end = remove # ignore/add/remove/force - -# Add or remove newline between function signature and '{'. -nl_fdef_brace = true # ignore/add/remove/force - -# Add or remove newline between C++11 lambda signature and '{'. -nl_cpp_ldef_brace = add # ignore/add/remove/force - -# Whether to add a newline after semicolons, except in 'for' statements. -nl_after_semicolon = true # true/false - -# Whether to add a newline after '{'. This also adds a newline before the -# matching '}'. -nl_after_brace_open = true # true/false - -# Whether to add a newline between the open brace and a trailing single-line -# comment. Requires nl_after_brace_open=true. -nl_after_brace_open_cmt = true # true/false - -# Whether to add a newline after '}'. Does not apply if followed by a -# necessary ';'. -nl_after_brace_close = true # true/false - -# Whether to add a newline after a virtual brace close, -# as in 'if (foo) a++; return;'. -nl_after_vbrace_close = true # true/false - -# Add or remove newline between the close brace and identifier, -# as in 'struct { int a; } b;'. Affects enumerations, unions and -# structures. If set to ignore, uses nl_after_brace_close. -nl_brace_struct_var = remove # ignore/add/remove/force - -# Add or remove blank line after 'if' statement. Add/Force work only if the -# next token is not a closing brace. -nl_after_if = force # ignore/add/remove/force - -# Add or remove blank line after 'for' statement. -nl_after_for = force # ignore/add/remove/force - -# Add or remove blank line after 'while' statement. -nl_after_while = force # ignore/add/remove/force - -# Add or remove blank line after 'switch' statement. -nl_after_switch = force # ignore/add/remove/force - -# Add or remove blank line after 'do/while' statement. -nl_after_do = force # ignore/add/remove/force - -# Whether to put a blank line before 'return' statements, unless after an open -# brace. -nl_before_return = false # true/false - -# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. -# (Lower priority than eat_blanks_before_close_brace.) -nl_ds_struct_enum_close_brace = true # true/false - - -# Blank line options -# - -# The maximum number of consecutive newlines (3 = 2 blank lines). -nl_max = 0 # unsigned number - -# The maximum number of consecutive newlines in a function. -nl_max_blank_in_func = 2 # unsigned number - -# The number of newlines after '}' of a multi-line function body. -nl_after_func_body = 2 # unsigned number - -# The number of newlines after '}' of a multi-line function body in a class -# declaration. Also affects class constructors/destructors. -# -# Overrides nl_after_func_body. -nl_after_func_body_class = 2 # unsigned number - -# The number of newlines after '}' or ';' of a struct/enum/union definition. -nl_after_struct = 2 # unsigned number - -# The number of newlines after '}' or ';' of a class definition. -nl_after_class = 2 # unsigned number - -# The number of newlines after '}' of a namespace. -nl_after_namespace = 2 # unsigned number - -# The number of newlines before an access specifier label. This also includes -# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count -# if after a brace open. -# -# 0: No change (default). -nl_before_access_spec = 2 # unsigned number - -# The number of newlines after a try-catch-finally block that isn't followed -# by a brace close. -# -# 0: No change (default). -nl_after_try_catch_finally = 2 # unsigned number - -# Whether to remove blank lines after '{'. -eat_blanks_after_open_brace = true # true/false - -# Whether to remove blank lines before '}'. -eat_blanks_before_close_brace = true # true/false - -# -# Positioning options -# - -# The position of arithmetic operators in wrapped expressions. -pos_arith = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of assignment in wrapped expressions. Do not affect '=' -# followed by '{'. -pos_assign = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of Boolean operators in wrapped expressions. -pos_bool = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of comparison operators in wrapped expressions. -pos_compare = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of conditional operators, as in the '?' and ':' of -# 'expr ? stmt : stmt', in wrapped expressions. -pos_conditional = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in wrapped expressions. -pos_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in enum entries. -pos_enum_comma = trail_force # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in the base class list if there is more than one -# line. Affects nl_class_init_args. -pos_class_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in the constructor initialization list. -# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. -pos_constr_comma = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of trailing/leading class colon, between class and base class -# list. Affects nl_class_colon. -pos_class_colon = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of colons between constructor and member initialization. -# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. -pos_constr_colon = trail # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# -# Code alignment options (not left column spaces/tabs) -# - -# The span for aligning on '=' in assignments. -# -# 0: Don't align (default). -align_assign_span = 1 # unsigned number -align_assign_thresh = -4 # number - -align_enum_equ_span = 4 # unsigned number -align_enum_equ_thresh = -20 # number - -align_number_right = true # true/false -# -# Line splitting options -# - -# Try to limit code width to N columns. -code_width = 110 # unsigned number - -# Whether to fully split long 'for' statements at semi-colons. -ls_for_split_full = true # true/false - -# Whether to fully split long function prototypes/calls at commas. -# The option ls_code_width has priority over the option ls_func_split_full. -ls_func_split_full = false # true/false - -# Whether to split lines as close to code_width as possible and ignore some -# groupings. -# The option ls_code_width has priority over the option ls_func_split_full. -ls_code_width = false # true/false - -# -# Comment modification options -# - -# Try to wrap comments at N columns. -cmt_width = 110 # unsigned number - -# How to reflow comments. -# -# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) -# 1: No touching at all -# 2: Full reflow -cmt_reflow_mode = 2 # unsigned number - -# Whether to convert all tabs to spaces in comments. If false, tabs in -# comments are left alone, unless used for indenting. -cmt_convert_tab_to_spaces = true # true/false - -# Whether to group c-comments that look like they are in a block. -cmt_c_group = true # true/false - -# Whether to put a star on subsequent comment lines. -cmt_star_cont = true # true/false - -# Whether to put an empty '/*' on the first line of the combined c-comment. -cmt_c_nl_start = true # true/false - -# Whether to add a newline before the closing '*/' of the combined c-comment. -cmt_c_nl_end = true # true/false - -# The number of spaces to insert at the start of subsequent comment lines. -cmt_sp_before_star_cont = 0 # unsigned number - -# The number of spaces to insert after the star on subsequent comment lines. -cmt_sp_after_star_cont = 1 # unsigned number - -# -# Code modifying options (non-whitespace) -# - -# Add or remove braces on a single-line 'do' statement. -mod_full_brace_do = force # ignore/add/remove/force - -# Add or remove braces on a single-line 'for' statement. -mod_full_brace_for = force # ignore/add/remove/force - -# (Pawn) Add or remove braces on a single-line function definition. -mod_full_brace_function = force # ignore/add/remove/force - -# Add or remove braces on a single-line 'if' statement. Braces will not be -# removed if the braced statement contains an 'else'. -mod_full_brace_if = force # ignore/add/remove/force - -# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. -# If true, mod_full_brace_if_chain will only remove braces from an 'if' that -# does not have an 'else if' or 'else'. -mod_full_brace_if_chain_only = true # true/false - -# Add or remove braces on single-line 'while' statement. -mod_full_brace_while = force # ignore/add/remove/force - -# Whether to fully parenthesize Boolean expressions in 'while' and 'if' -# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. -mod_full_paren_if_bool = true # true/false - -# Whether to remove superfluous semicolons. -mod_remove_extra_semicolon = true # true/false - -# If an #ifdef body exceeds the specified number of newlines and doesn't have -# a comment after the #endif, a comment will be added. -mod_add_long_ifdef_endif_comment = 0 # unsigned number - -# If an #ifdef or #else body exceeds the specified number of newlines and -# doesn't have a comment after the #else, a comment will be added. -mod_add_long_ifdef_else_comment = 0 # unsigned number - -# Whether to remove a void 'return;' that appears as the last statement in a -# function. -mod_remove_empty_return = false # true/false - -# Add or remove the comma after the last value of an enumeration. -mod_enum_last_comma = force # ignore/add/remove/force - -# -# Preprocessor options -# - -# Add or remove indentation of preprocessor directives inside #if blocks -# at brace level 0 (file-level). -pp_indent = add # ignore/add/remove/force -pp_indent_count = 4 - -# Whether to indent the code between #if, #else and #endif. -pp_if_indent_code = false # true/false - -# Use or Do not Use options -# - -# true: indent_func_call_param will be used (default) -# false: indent_func_call_param will NOT be used -# -# Default: true -use_indent_func_call_param = true # true/false - -# The value of the indentation for a continuation line is calculated -# differently if the statement is: -# - a declaration: your case with QString fileName ... -# - an assignment: your case with pSettings = new QSettings( ... -# -# At the second case the indentation value might be used twice: -# - at the assignment -# - at the function call (if present) -# -# To prevent the double use of the indentation value, use this option with the -# value 'true'. -# -# true: indent_continue will be used only once -# false: indent_continue will be used every time (default) -use_indent_continue_only_once = true # true/false - -# The value might be used twice: -# - at the assignment -# - at the opening brace -# -# To prevent the double use of the indentation value, use this option with the -# value 'true'. -# -# true: indentation will be used only once -# false: indentation will be used every time (default) -indent_cpp_lambda_only_once = true # true/false - -# Whether sp_after_angle takes precedence over sp_inside_fparen. This was the -# historic behavior, but is probably not the desired behavior, so this is off -# by default. -use_sp_after_angle_always = false # true/false From bf6e25d9bfd636293eae99f5d0494353ae7905fa Mon Sep 17 00:00:00 2001 From: WShad Date: Sat, 15 Nov 2025 10:19:22 +0300 Subject: [PATCH 13/21] migrate to wf-json --- .gitmodules | 3 + meson.build | 10 +- src/panel/widgets/language.cpp | 38 +- src/panel/widgets/language.hpp | 6 +- src/util/json.cpp | 677 --------------------------------- src/util/json.hpp | 168 -------- src/util/meson.build | 1 - src/util/wf-ipc.cpp | 14 +- src/util/wf-ipc.hpp | 6 +- subprojects/wf-json | 1 + subprojects/yyjson.wrap | 5 - 11 files changed, 32 insertions(+), 897 deletions(-) delete mode 100644 src/util/json.cpp delete mode 100644 src/util/json.hpp create mode 160000 subprojects/wf-json delete mode 100644 subprojects/yyjson.wrap diff --git a/.gitmodules b/.gitmodules index 0e49778e..1644112b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "subprojects/gtk4-layer-shell"] path = subprojects/gtk4-layer-shell url = https://github.com/wmww/gtk4-layer-shell.git +[submodule "subprojects/wf-json"] + path = subprojects/wf-json + url = https://github.com/WayfireWM/wf-json diff --git a/meson.build b/meson.build index a32c6351..f50bcee9 100644 --- a/meson.build +++ b/meson.build @@ -24,15 +24,7 @@ libpulse = dependency('libpulse', required: get_option('pulse')) dbusmenu_gtk = dependency('dbusmenu-glib-0.4') libgvc = subproject('gvc', default_options: ['static=true'], required: get_option('pulse')) xkbregistry = dependency('xkbregistry') -json = dependency('yyjson', required: false) - -if not json.found() - cmake = import('cmake') - cmake_opts = cmake.subproject_options() - cmake_opts.add_cmake_defines({'CMAKE_POSITION_INDEPENDENT_CODE': true}) - sub_proj = cmake.subproject('yyjson', options: cmake_opts) - json = sub_proj.dependency('yyjson') -endif +json = subproject('wf-json').get_variable('wfjson') if get_option('wayland-logout') == true wayland_logout = subproject('wayland-logout') diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index c925e72a..35dc094e 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -3,7 +3,6 @@ #include #include #include -#include "json.hpp" #include #include #include @@ -22,7 +21,7 @@ void WayfireLanguage::init(Gtk::Box *container) button.show(); ipc->subscribe(this, {"keyboard-modifier-state-changed"}); - ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (json_t data) + ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (wf::json_t data) { set_available(data["possible-layouts"]); set_current(data["layout-index"]); @@ -31,26 +30,21 @@ void WayfireLanguage::init(Gtk::Box *container) container->append(button); } -void WayfireLanguage::on_event(json_t data) +void WayfireLanguage::on_event(wf::json_t data) { - try { - if (data["event"].as_string() == "keyboard-modifier-state-changed") + if (data["event"].as_string() == "keyboard-modifier-state-changed") + { + if (available_layouts.size() == 0) { - if (available_layouts.size() == 0) - { - set_available(data["state"]["possible-layouts"]); - } - - auto state_layout = data["state"]["layout-index"].as_uint(); - if (state_layout != current_layout) - { - current_layout = state_layout; - set_current(state_layout); - } + set_available(data["state"]["possible-layouts"]); + } + + auto state_layout = data["state"]["layout-index"].as_uint(); + if (state_layout != current_layout) + { + current_layout = state_layout; + set_current(state_layout); } - } catch (const JSONException& e) - { - LOGE("Handle event JSON error: ", e.what()); } } @@ -71,7 +65,7 @@ void WayfireLanguage::set_current(uint32_t index) update_label(); } -void WayfireLanguage::set_available(json_t layouts) +void WayfireLanguage::set_available(wf::json_t layouts) { std::vector layouts_available; std::map names; @@ -111,9 +105,9 @@ void WayfireLanguage::next_layout() next = 0; } - json_t message; + wf::json_t message; message["method"] = "wayfire/set-keyboard-state"; - message["data"] = json_t(); + message["data"] = wf::json_t(); message["data"]["layout-index"] = next; ipc->send(message.serialize()); } diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp index b2899077..bdbe5b8f 100644 --- a/src/panel/widgets/language.hpp +++ b/src/panel/widgets/language.hpp @@ -7,7 +7,7 @@ #include #include #include -#include "json.hpp" +#include #include #include @@ -28,10 +28,10 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber public: void init(Gtk::Box *container); - void on_event(json_t data) override; + void on_event(wf::json_t data) override; bool update_label(); void set_current(uint32_t index); - void set_available(json_t layouts); + void set_available(wf::json_t layouts); void next_layout(); WayfireLanguage(std::shared_ptr ipc); ~WayfireLanguage(); diff --git a/src/util/json.cpp b/src/util/json.cpp deleted file mode 100644 index 948c1401..00000000 --- a/src/util/json.cpp +++ /dev/null @@ -1,677 +0,0 @@ -#include "json.hpp" -#include -#include -#include -#include - -bool json_reference_t::is_array() const -{ - return yyjson_mut_is_arr(v); -} - -json_reference_t json_reference_t::operator [](const size_t& idx) const -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - if (size() < idx) - { - throw JSONException("Index out of bounds"); - } - - return json_reference_t{doc, yyjson_mut_arr_get(v, idx)}; -} - -void json_reference_t::append(const json_reference_t& elem) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_append(v, yyjson_mut_val_mut_copy(doc, elem.v)); -} - -void json_reference_t::append(int value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_int(doc, v, value); -} - -void json_reference_t::append(unsigned int value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_uint(doc, v, value); -} - -void json_reference_t::append(int64_t value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_sint(doc, v, value); -} - -void json_reference_t::append(uint64_t value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_uint(doc, v, value); -} - -void json_reference_t::append(double value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_real(doc, v, value); -} - -void json_reference_t::append(bool value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_bool(doc, v, value); -} - -void json_reference_t::append(const std::string_view& value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_strncpy(doc, v, value.data(), value.size()); -} - -void json_reference_t::append(const char *value) -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - yyjson_mut_arr_add_strcpy(doc, v, value); -} - -size_t json_reference_t::size() const -{ - if (!is_array()) - { - throw JSONException("Not an array"); - } - - return yyjson_mut_arr_size(v); -} - -bool json_reference_t::has_member(const std::string_view& key) const -{ - return is_object() && (yyjson_mut_obj_getn(v, key.data(), key.size()) != NULL); -} - -bool json_reference_t::is_object() const -{ - return yyjson_mut_is_obj(v); -} - -bool json_reference_t::is_null() const -{ - return yyjson_mut_is_null(v); -} - -json_reference_t json_reference_t::operator [](const char *key) const -{ - return this->operator [](std::string_view{key}); -} - -json_reference_t json_reference_t::operator [](const std::string_view& key) const -{ - if (!(is_object() || is_null())) - { - throw JSONException("Trying to access into JSON value that is not an object!"); - } - - if (is_null()) - { - yyjson_mut_set_obj(v); - } - - auto ptr = yyjson_mut_obj_getn(v, key.data(), key.size()); - if (ptr != NULL) - { - return json_reference_t{doc, ptr}; - } - - auto key_yy = yyjson_mut_strncpy(doc, key.data(), key.size()); - auto value = yyjson_mut_null(doc); - - yyjson_mut_obj_add(v, key_yy, value); - return json_reference_t{doc, value}; -} - -std::vector json_reference_t::get_member_names() const -{ - std::vector members; - yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(v); - while (yyjson_mut_obj_iter_has_next(&iter)) - { - auto key = yyjson_mut_obj_iter_next(&iter); - members.push_back(yyjson_mut_get_str(key)); - } - - return members; -} - -static void copy_yyjson(yyjson_mut_doc *dst_doc, yyjson_mut_val *dst, yyjson_mut_val *src) -{ - if (yyjson_mut_is_null(src)) - { - yyjson_mut_set_null(dst); - return; - } - - if (yyjson_mut_is_bool(src)) - { - yyjson_mut_set_bool(dst, yyjson_mut_get_bool(src)); - return; - } - - if (yyjson_mut_is_sint(src)) - { - yyjson_mut_set_sint(dst, yyjson_mut_get_sint(src)); - return; - } - - if (yyjson_mut_is_uint(src)) - { - yyjson_mut_set_uint(dst, yyjson_mut_get_uint(src)); - return; - } - - if (yyjson_mut_is_real(src)) - { - yyjson_mut_set_real(dst, yyjson_mut_get_real(src)); - return; - } - - if (yyjson_mut_is_str(src)) - { - // copy ownership of string to dst_doc - auto val = yyjson_mut_val_mut_copy(dst_doc, src); - yyjson_mut_set_str(dst, yyjson_mut_get_str(val)); - return; - } - - if (yyjson_mut_is_arr(src)) - { - yyjson_mut_set_arr(dst); - yyjson_mut_arr_iter iter = yyjson_mut_arr_iter_with(src); - while (yyjson_mut_arr_iter_has_next(&iter)) - { - auto elem = yyjson_mut_arr_iter_next(&iter); - elem = yyjson_mut_val_mut_copy(dst_doc, elem); - yyjson_mut_arr_append(dst, elem); - } - - return; - } - - if (yyjson_mut_is_obj(src)) - { - yyjson_mut_set_obj(dst); - yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(src); - while (yyjson_mut_obj_iter_has_next(&iter)) - { - auto key = yyjson_mut_obj_iter_next(&iter); - auto value = yyjson_mut_obj_iter_get_val(key); - // Copy ownership to our doc - key = yyjson_mut_val_mut_copy(dst_doc, key); - value = yyjson_mut_val_mut_copy(dst_doc, value); - yyjson_mut_obj_add(dst, key, value); - } - - return; - } - - throw JSONException("Unsupported JSON type?"); -} - -json_reference_t& json_reference_t::operator =(const json_reference_t& other) -{ - copy_yyjson(doc, v, other.v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const json_reference_t&& other) -{ - // FIXME: maybe we can check whether the docs are the same or something to make this faster? - copy_yyjson(doc, v, other.v); - return *this; -} - -// --------------------------------------- Basic data types support ------------------------------------------ -json_reference_t& json_reference_t::operator =(const int& v) -{ - yyjson_mut_set_sint(this->v, v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const uint& v) -{ - yyjson_mut_set_uint(this->v, v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const int64_t& v) -{ - yyjson_mut_set_sint(this->v, v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const uint64_t& v) -{ - yyjson_mut_set_uint(this->v, v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const bool& v) -{ - yyjson_mut_set_bool(this->v, v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const double& v) -{ - yyjson_mut_set_real(this->v, v); - return *this; -} - -json_reference_t& json_reference_t::operator =(const std::string_view& v) -{ - // copy ownership of string to doc - auto our_v = yyjson_mut_strncpy(doc, v.data(), v.size()); - yyjson_mut_set_str(this->v, yyjson_mut_get_str(our_v)); - return *this; -} - -json_reference_t& json_reference_t::operator =(const char *v) -{ - // copy ownership of string to doc - auto our_v = yyjson_mut_strcpy(doc, v); - yyjson_mut_set_str(this->v, yyjson_mut_get_str(our_v)); - return *this; -} - -bool json_reference_t::is_int() const -{ - if (yyjson_mut_is_sint(v)) - { - return (std::numeric_limits::min() <= yyjson_mut_get_sint(v)) && - (yyjson_mut_get_sint(v) <= std::numeric_limits::max()); - } - - if (yyjson_mut_is_uint(v)) - { - return (yyjson_mut_get_uint(v) <= std::numeric_limits::max()); - } - - return false; -} - -json_reference_t::operator int() const -{ - if (!is_int()) - { - throw JSONException("Not an int"); - } - - return yyjson_mut_get_int(v); -} - -int json_reference_t::as_int() const -{ - if (!is_int()) - { - throw JSONException("Not an int"); - } - - return (int)(*this); -} - -bool json_reference_t::is_int64() const -{ - if (yyjson_mut_is_uint(v)) - { - return yyjson_mut_get_uint(v) <= std::numeric_limits::max(); - } - - return yyjson_mut_is_sint(v); -} - -json_reference_t::operator int64_t() const -{ - if (!is_int64()) - { - throw JSONException("Not an int64"); - } - - if (yyjson_mut_is_uint(v)) - { - return yyjson_mut_get_uint(v); - } else - { - return yyjson_mut_get_sint(v); - } -} - -int64_t json_reference_t::as_int64() const -{ - if (!is_int64()) - { - throw JSONException("Not an int64"); - } - - return (int64_t)(*this); -} - -bool json_reference_t::is_uint() const -{ - return yyjson_mut_is_uint(v) && - (yyjson_mut_get_uint(v) <= std::numeric_limits::max()); -} - -json_reference_t::operator uint() const -{ - if (!is_uint()) - { - throw JSONException("Not an uint"); - } - - return yyjson_mut_get_uint(v); -} - -unsigned int json_reference_t::as_uint() const -{ - if (!is_uint()) - { - throw JSONException("Not an uint"); - } - - return (unsigned int)(*this); -} - -bool json_reference_t::is_uint64() const -{ - return yyjson_mut_is_uint(v); -} - -json_reference_t::operator uint64_t() const -{ - if (!is_uint64()) - { - throw JSONException("Not an uint64"); - } - - return yyjson_mut_get_uint(v); -} - -uint64_t json_reference_t::as_uint64() const -{ - if (!is_uint64()) - { - throw JSONException("Not an uint64"); - } - - return (uint64_t)(*this); -} - -bool json_reference_t::is_bool() const -{ - return yyjson_mut_is_bool(v); -} - -json_reference_t::operator bool() const -{ - if (!is_bool()) - { - throw JSONException("Not a bool"); - } - - return yyjson_mut_get_bool(v); -} - -bool json_reference_t::as_bool() const -{ - if (!is_bool()) - { - throw JSONException("Not a bool"); - } - - return (bool)(*this); -} - -bool json_reference_t::is_double() const -{ - return yyjson_mut_is_num(v); -} - -json_reference_t::operator double() const -{ - if (!is_double()) - { - throw JSONException("Not a double"); - } - - return yyjson_mut_get_num(v); -} - -double json_reference_t::as_double() const -{ - if (!is_double()) - { - throw JSONException("Not a double"); - } - - return (double)(*this); -} - -bool json_reference_t::is_string() const -{ - return yyjson_mut_is_str(v); -} - -json_reference_t::operator std::string() const -{ - if (!is_string()) - { - throw JSONException("Not a string"); - } - - return std::string(yyjson_mut_get_str(v)); -} - -std::string json_reference_t::as_string() const -{ - if (!is_string()) - { - throw JSONException("Not a string"); - } - - return (std::string)*this; -} - -void json_t::init() -{ - this->doc = yyjson_mut_doc_new(NULL); - this->v = yyjson_mut_null(this->doc); - yyjson_mut_doc_set_root(doc, v); -} - -json_t::json_t() -{ - init(); -} - -json_t::~json_t() -{ - yyjson_mut_doc_free(doc); -} - -json_t::json_t(const json_reference_t& ref) : json_t() -{ - copy_yyjson(doc, this->v, ref.get_raw_value()); -} - -json_t::json_t(yyjson_mut_doc *doc) -{ - this->doc = doc; - this->v = yyjson_mut_doc_get_root(this->doc); -} - -json_t::json_t(const json_t& other) : json_reference_t() -{ - *this = other; -} - -json_t& json_t::operator =(const json_t& other) -{ - if (this != &other) - { - yyjson_mut_doc_free(doc); - init(); - copy_yyjson(doc, this->v, other.v); - } - - return *this; -} - -json_t::json_t(json_t&& other) -{ - *this = std::move(other); -} - -json_t& json_t::operator =(json_t&& other) -{ - if (this != &other) - { - yyjson_mut_doc_free(doc); - this->doc = other.doc; - this->v = other.v; - - other.doc = NULL; - other.v = NULL; - } - - return *this; -} - -json_t::json_t(int v) : json_t() -{ - *this = v; -} - -json_t::json_t(unsigned v) : json_t() -{ - *this = v; -} - -json_t::json_t(int64_t v) : json_t() -{ - *this = v; -} - -json_t::json_t(uint64_t v) : json_t() -{ - *this = v; -} - -json_t::json_t(double v) : json_t() -{ - *this = v; -} - -json_t::json_t(const std::string_view& v) : json_t() -{ - *this = v; -} - -json_t::json_t(const char *v) : json_t() -{ - *this = v; -} - -json_t::json_t(bool v) : json_t() -{ - *this = v; -} - -json_t json_t::array() -{ - json_t r; - yyjson_mut_set_arr(r.v); - return r; -} - -json_t json_t::null() -{ - json_t r; - yyjson_mut_set_null(r.v); - return r; -} - -std::optional json_t::parse_string(const std::string_view& source, - json_t& result) -{ - yyjson_read_err error; - auto doc = yyjson_read_opts((char*)source.data(), source.length(), 0, NULL, &error); - - if (!doc) - { - return std::string("Failed to parse JSON, error ") + - std::to_string(error.code) + ": " + error.msg + std::string("(at offset ") + - std::to_string(error.pos) + ")"; - } - - result = json_t{yyjson_doc_mut_copy(doc, NULL)}; - yyjson_doc_free(doc); - return std::nullopt; -} - -void json_t::map_serialized(std::function callback) const -{ - size_t len; - char *result = yyjson_mut_write(this->doc, 0, &len); - callback(result, len); - free(result); -} - -std::string json_t::serialize() const -{ - std::string result; - map_serialized([&] (const char *source, size_t length) - { - result.append(source, length); - }); - - return result; -} diff --git a/src/util/json.hpp b/src/util/json.hpp deleted file mode 100644 index 4e83cb8d..00000000 --- a/src/util/json.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -extern "C" { - struct yyjson_mut_val; - struct yyjson_mut_doc; -}; - -class JSONException : public std::exception -{ - public: - std::string msg; - - JSONException(std::string msg) : msg(msg) - {} - - const char * what() const noexcept override - { - return msg.c_str(); - } -}; - -/** - * A temporary non-owning reference to a JSON value. - */ -class json_t; -class json_reference_t -{ - public: - // ------------------------------------------- Array support --------------------------------------------- - bool is_array() const; - json_reference_t operator [](const size_t& idx) const; - void append(const json_reference_t& elem); - void append(int value); - void append(unsigned int value); - void append(int64_t value); - void append(uint64_t value); - void append(double value); - void append(bool value); - void append(const std::string_view& value); - void append(const char *value); - size_t size() const; - - // ------------------------------------------- Object support -------------------------------------------- - bool has_member(const std::string_view& key) const; - bool is_object() const; - bool is_null() const; - json_reference_t operator [](const char *key) const; - json_reference_t operator [](const std::string_view& key) const; - std::vector get_member_names() const; - json_reference_t& operator =(const json_reference_t& v); - json_reference_t& operator =(const json_reference_t&& other); - - // ------------------------------------- Basic data types support ---------------------------------------- - json_reference_t& operator =(const int& v); - json_reference_t& operator =(const unsigned int& v); - json_reference_t& operator =(const int64_t& v); - json_reference_t& operator =(const uint64_t& v); - json_reference_t& operator =(const bool& v); - json_reference_t& operator =(const double& v); - json_reference_t& operator =(const std::string_view& v); - json_reference_t& operator =(const char *v); - - bool is_int() const; - operator int() const; - int as_int() const; - bool is_int64() const; - operator int64_t() const; - int64_t as_int64() const; - bool is_uint() const; - operator unsigned int() const; - unsigned int as_uint() const; - bool is_uint64() const; - operator uint64_t() const; - uint64_t as_uint64() const; - bool is_bool() const; - operator bool() const; - bool as_bool() const; - bool is_double() const; - operator double() const; - double as_double() const; - bool is_string() const; - operator std::string() const; - std::string as_string() const; - - yyjson_mut_val *get_raw_value() const - { - return v; - } - - yyjson_mut_doc *get_raw_doc() const - { - return doc; - } - - private: - friend class json_t; - json_reference_t() - {} - json_reference_t(yyjson_mut_doc *doc, yyjson_mut_val *val) : doc(doc), v(val) - {} - - yyjson_mut_doc *doc = NULL; - yyjson_mut_val *v = NULL; - - // Non-copyable, non-moveable. - json_reference_t(const json_reference_t& other) = delete; - json_reference_t(const json_reference_t&& other) = delete; -}; - -class json_t final : public json_reference_t -{ - public: - json_t(); - json_t(const json_reference_t& ref); - json_t(const json_t& other); - json_t(yyjson_mut_doc *doc); - ~json_t(); - - json_t& operator =(const json_t& other); - json_t(json_t&& other); - json_t& operator =(json_t&& other); - - json_t(int v); - json_t(unsigned int v); - json_t(int64_t v); - json_t(uint64_t v); - json_t(double v); - json_t(const std::string_view& v); - json_t(const char *v); - json_t(bool v); - - static json_t array(); - static json_t null(); - - /** - * Parse the given source as a JSON document. - * - * @result Where to store the parsed document on success. - * @return On failure, an error message describing the problem with the JSON source will be returned. - * Otherwise, the function will return std::nullopt. - */ - static std::optional parse_string(const std::string_view& source, - json_t& result); - - /** - * Serialize the JSON document and handle it using the provided callback. - * - * Note that the source string will be freed afterwards, so if the caller needs the data for longer, they - * need to make a copy of it. - */ - void map_serialized(std::function callback) const; - - /** - * Get a JSON string representation of the document. - */ - std::string serialize() const; - - private: - void init(); -}; diff --git a/src/util/meson.build b/src/util/meson.build index 3db9d928..6f2b8701 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -6,7 +6,6 @@ util = static_library( 'wf-autohide-window.cpp', 'wf-popover.cpp', 'css-config.cpp', - 'json.cpp', 'wf-ipc.cpp', ], dependencies: [wf_protos, wayland_client, gtkmm, wfconfig, libinotify, gtklayershell, json], diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index a3a25edc..4f71afff 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -24,7 +24,6 @@ #include "glibmm/error.h" #include "glibmm/iochannel.h" #include "glibmm/main.h" -#include "json.hpp" #include "sigc++/functors/mem_fun.h" WayfireIPC::WayfireIPC() @@ -185,8 +184,8 @@ bool WayfireIPC::receive(Glib::IOCondition cond) return false; } - json_t message; - auto err = json_t::parse_string(buf, message); + wf::json_t message; + auto err = wf::json_t::parse_string(buf, message); if (err.has_value()) { LOGE("Parse error: ", err.value(), " message: ", buf, " length: ", buf.length()); @@ -221,9 +220,6 @@ bool WayfireIPC::receive(Glib::IOCondition cond) { LOGE("GIO Error: ", e.what()); return false; - } catch (const JSONException& e) - { - LOGE("JSON error: ", e.what()); } return true; @@ -233,16 +229,16 @@ void WayfireIPC::subscribe_all(IIPCSubscriber *subscriber) { subscribers.insert(subscriber); - json_t new_subs; + wf::json_t new_subs; new_subs["method"] = "window-rules/events/watch"; send(new_subs.serialize()); } void WayfireIPC::subscribe(IIPCSubscriber *subscriber, const std::vector& events) { - json_t new_subs; + wf::json_t new_subs; new_subs["method"] = "window-rules/events/watch"; - new_subs["events"] = json_t::array(); + new_subs["events"] = wf::json_t::array(); for (auto event : events) { diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index 1903916e..5498d471 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -6,7 +6,7 @@ #include "giomm/socketconnection.h" #include "glibmm/iochannel.h" #include "glibmm/refptr.h" -#include "json.hpp" +#include #include "sigc++/connection.h" #include #include @@ -20,10 +20,10 @@ class IIPCSubscriber { public: - virtual void on_event(json_t) = 0; + virtual void on_event(wf::json_t) = 0; }; -using response_handler = std::function; +using response_handler = std::function; class WayfireIPC { diff --git a/subprojects/wf-json b/subprojects/wf-json new file mode 160000 index 00000000..830739b5 --- /dev/null +++ b/subprojects/wf-json @@ -0,0 +1 @@ +Subproject commit 830739b5d978019f8d421662fb7b280ba21b5362 diff --git a/subprojects/yyjson.wrap b/subprojects/yyjson.wrap deleted file mode 100644 index 3bf85901..00000000 --- a/subprojects/yyjson.wrap +++ /dev/null @@ -1,5 +0,0 @@ -[wrap-git] -url = https://github.com/ibireme/yyjson.git -revision = HEAD -depth = 1 -method = cmake From 0f63bef05c7a274cc622ec0476cb34395ade9aa2 Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 23 Nov 2025 18:05:58 +0300 Subject: [PATCH 14/21] IPC rework --- src/panel/panel.cpp | 9 ++-- src/panel/panel.hpp | 3 +- src/panel/widgets/language.cpp | 15 +++--- src/panel/widgets/language.hpp | 4 +- src/util/wf-ipc.cpp | 91 +++++++++++++++++++++++++++------- src/util/wf-ipc.hpp | 42 ++++++++++------ src/util/wf-shell-app.cpp | 3 -- src/util/wf-shell-app.hpp | 1 - 8 files changed, 116 insertions(+), 52 deletions(-) diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 93e5ae12..34bdc513 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -36,7 +36,6 @@ class WayfirePanel::impl { std::unique_ptr window; - std::shared_ptr ipc_manager; Gtk::CenterBox content_box; Gtk::Box left_box, center_box, right_box; @@ -190,7 +189,7 @@ class WayfirePanel::impl if (name == "language") { - return Widget(new WayfireLanguage(ipc_manager->get_IPC())); + return Widget(new WayfireLanguage()); } if (auto pixel = widget_with_value(name, "spacing")) @@ -291,7 +290,7 @@ class WayfirePanel::impl } public: - impl(WayfireOutput *output, std::shared_ptr ipc) : ipc_manager(ipc), output(output) + impl(WayfireOutput *output) : output(output) { create_window(); } @@ -325,7 +324,7 @@ class WayfirePanel::impl } }; -WayfirePanel::WayfirePanel(WayfireOutput *output, std::shared_ptr ipc_manager) : pimpl(new impl(output, ipc_manager)) +WayfirePanel::WayfirePanel(WayfireOutput *output) : pimpl(new impl(output)) {} wl_surface*WayfirePanel::get_wl_surface() @@ -378,7 +377,7 @@ void WayfirePanelApp::on_activate() void WayfirePanelApp::handle_new_output(WayfireOutput *output) { priv->panels[output] = std::unique_ptr( - new WayfirePanel(output, ipc_manager)); + new WayfirePanel(output)); } WayfirePanel*WayfirePanelApp::panel_for_wl_output(wl_output *output) diff --git a/src/panel/panel.hpp b/src/panel/panel.hpp index 9e84f724..cae9903e 100644 --- a/src/panel/panel.hpp +++ b/src/panel/panel.hpp @@ -6,13 +6,12 @@ #include #include -#include "wf-ipc.hpp" #include "wf-shell-app.hpp" class WayfirePanel { public: - WayfirePanel(WayfireOutput *output, std::shared_ptr ipc); + WayfirePanel(WayfireOutput *output); wl_surface *get_wl_surface(); Gtk::Window& get_window(); diff --git a/src/panel/widgets/language.cpp b/src/panel/widgets/language.cpp index 35dc094e..c0d925fa 100644 --- a/src/panel/widgets/language.cpp +++ b/src/panel/widgets/language.cpp @@ -11,6 +11,7 @@ #include "language.hpp" #include "gtkmm/button.h" #include "sigc++/functors/mem_fun.h" +#include "wf-ipc.hpp" void WayfireLanguage::init(Gtk::Box *container) { @@ -20,8 +21,8 @@ void WayfireLanguage::init(Gtk::Box *container) button.signal_clicked().connect(sigc::mem_fun(*this, &WayfireLanguage::next_layout)); button.show(); - ipc->subscribe(this, {"keyboard-modifier-state-changed"}); - ipc->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (wf::json_t data) + ipc_client->subscribe(this, {"keyboard-modifier-state-changed"}); + ipc_client->send("{\"method\":\"wayfire/get-keyboard-state\"}", [=] (wf::json_t data) { set_available(data["possible-layouts"]); set_current(data["layout-index"]); @@ -109,13 +110,15 @@ void WayfireLanguage::next_layout() message["method"] = "wayfire/set-keyboard-state"; message["data"] = wf::json_t(); message["data"]["layout-index"] = next; - ipc->send(message.serialize()); + ipc_client->send(message.serialize()); } -WayfireLanguage::WayfireLanguage(std::shared_ptr ipc) : ipc(ipc) -{} +WayfireLanguage::WayfireLanguage() +{ + ipc_client = WayfireIPC::get_instance()->create_client(); +} WayfireLanguage::~WayfireLanguage() { - ipc->unsubscribe(this); + ipc_client->unsubscribe(this); } diff --git a/src/panel/widgets/language.hpp b/src/panel/widgets/language.hpp index bdbe5b8f..a1819724 100644 --- a/src/panel/widgets/language.hpp +++ b/src/panel/widgets/language.hpp @@ -22,7 +22,7 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber // Gtk::Label label; Gtk::Button button; - std::shared_ptr ipc; + std::shared_ptr ipc_client; uint32_t current_layout; std::vector available_layouts; @@ -33,7 +33,7 @@ class WayfireLanguage : public WayfireWidget, public IIPCSubscriber void set_current(uint32_t index); void set_available(wf::json_t layouts); void next_layout(); - WayfireLanguage(std::shared_ptr ipc); + WayfireLanguage(); ~WayfireLanguage(); }; diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index 4f71afff..e0e255f2 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "wf-ipc.hpp" @@ -39,6 +40,7 @@ WayfireIPC::WayfireIPC() WayfireIPC::~WayfireIPC() { disconnect(); + LOGI("IPC destroyed"); } void WayfireIPC::connect() @@ -68,13 +70,13 @@ void WayfireIPC::disconnect() void WayfireIPC::send(const std::string& message) { send_message(message); - response_handlers.push(std::nullopt); + response_handlers.push(0); } -void WayfireIPC::send(const std::string& message, response_handler cb) +void WayfireIPC::send(const std::string& message, int response_handler) { send_message(message); - response_handlers.push(cb); + response_handlers.push(response_handler); } void WayfireIPC::send_message(const std::string& message) @@ -109,6 +111,9 @@ void WayfireIPC::write_stream(const std::string& message) try { writing = true; uint32_t length = message.size(); + // Pointer to data must be valid until completely wrote and + // slot is called, as documented for write_all_async. + // So we pin it with a shared pointer, destroyed *after* slot is called. auto all_data = std::make_shared((char*)&length, 4); *all_data += message; output->write_all_async(all_data->data(), all_data->size(), @@ -210,9 +215,10 @@ bool WayfireIPC::receive(Glib::IOCondition cond) { auto handler = response_handlers.front(); response_handlers.pop(); - if (handler.has_value()) + auto client = clients.find(handler); + if (client != clients.end()) { - handler.value()(message); + client->second->handle_response(message); } } } @@ -267,27 +273,74 @@ void WayfireIPC::unsubscribe(IIPCSubscriber *subscriber) } } -// WayfireIPCManager -std::shared_ptr WayfireIPCManager::get_IPC() +std::shared_ptr WayfireIPC::create_client() { - if (ipc == nullptr) + auto client = new IPCClient(next_client_id, shared_from_this()); + clients[next_client_id++] = client; + + // Zero is reserved for NO CLIENT id, so just in case :) + if (next_client_id == 0) { - ipc = new WayfireIPC(); + next_client_id++; } - counter++; - return std::shared_ptr(ipc, [this] (WayfireIPC*) - { - release(); - }); + return std::shared_ptr(client); } -void WayfireIPCManager::release() +void WayfireIPC::client_destroyed(int id) { - counter--; - if (counter == 0) + clients.erase(id); +} + +std::shared_ptr WayfireIPC::get_instance() +{ + static std::weak_ptr ipc; + + auto instance = ipc.lock(); + if (!instance) { - delete ipc; - ipc = nullptr; + instance = std::shared_ptr(new WayfireIPC()); + ipc = instance; } + + return instance; +} + +// IPCClient +IPCClient::~IPCClient() +{ + ipc->client_destroyed(id); } + +void IPCClient::send(const std::string& message) +{ + ipc->send(message); +} + +void IPCClient::send(const std::string& message, response_handler cb) +{ + response_handlers.push(cb); + ipc->send(message, id); +} + +void IPCClient::handle_response(wf::json_t response) +{ + auto handler = response_handlers.front(); + response_handlers.pop(); + handler(response); +} + +void IPCClient::subscribe(IIPCSubscriber *subscriber, const std::vector& events) +{ + ipc->subscribe(subscriber, events); +} + +void IPCClient::subscribe_all(IIPCSubscriber *subscriber) +{ + ipc->subscribe_all(subscriber); +} + +void IPCClient::unsubscribe(IIPCSubscriber *subscriber) +{ + ipc->unsubscribe(subscriber); +} \ No newline at end of file diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index 5498d471..9f825274 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -2,10 +2,12 @@ #define WF_IPC_HPP #include "gio/gio.h" +#include "giomm/cancellable.h" #include "giomm/outputstream.h" #include "giomm/socketconnection.h" #include "glibmm/iochannel.h" #include "glibmm/refptr.h" +#include #include #include "sigc++/connection.h" #include @@ -25,11 +27,29 @@ class IIPCSubscriber using response_handler = std::function; -class WayfireIPC -{ - std::queue> response_handlers; +class WayfireIPC; +class IPCClient { + int id; + std::shared_ptr ipc; + std::queue response_handlers; + public: + IPCClient(int id, std::shared_ptr ipc) : id(id), ipc(ipc) {} + ~IPCClient(); + int get_id(); + void handle_response(wf::json_t response); + void send(const std::string& message); + void send(const std::string& message, response_handler cb); + void subscribe(IIPCSubscriber *subscriber, const std::vector& events); + void subscribe_all(IIPCSubscriber *subscriber); + void unsubscribe(IIPCSubscriber *subscriber); +}; + +class WayfireIPC : public std::enable_shared_from_this { + std::queue response_handlers; std::set subscribers; std::unordered_map> subscriptions; + int next_client_id{1}; + std::unordered_map clients; uint32_t length; sigc::connection sig_connection; Glib::RefPtr connection; @@ -48,22 +68,16 @@ class WayfireIPC public: void send(const std::string& message); - void send(const std::string& message, response_handler); + void send(const std::string& message, int response_handler); void subscribe(IIPCSubscriber *subscriber, const std::vector& events); void subscribe_all(IIPCSubscriber *subscriber); void unsubscribe(IIPCSubscriber *subscriber); + std::shared_ptr create_client(); + void client_destroyed(int id); + + static std::shared_ptr get_instance(); WayfireIPC(); ~WayfireIPC(); }; -class WayfireIPCManager -{ - uint counter = 0; - WayfireIPC *ipc = nullptr; - void release(); - - public: - std::shared_ptr get_IPC(); -}; - #endif // WF_IPC_HPP diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index ead81c2a..969c0c95 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -1,5 +1,4 @@ #include "wf-shell-app.hpp" -#include "wf-ipc.hpp" #include #include #include @@ -200,8 +199,6 @@ void WayfireShellApp::on_activate() std::exit(-1); } - ipc_manager = std::make_shared(); - wl_registry *registry = wl_display_get_registry(wl_display); wl_registry_add_listener(registry, ®istry_listener, this); wl_display_roundtrip(wl_display); diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index fe9310bf..20207cf2 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -71,7 +71,6 @@ class WayfireShellApp int inotify_css_fd; wf::config::config_manager_t config; zwf_shell_manager_v2 *wf_shell_manager = nullptr; - std::shared_ptr ipc_manager; WayfireShellApp(); virtual ~WayfireShellApp(); From adeac00322d9223a7480863511ad720b82b1d131 Mon Sep 17 00:00:00 2001 From: WShad Date: Fri, 28 Nov 2025 21:49:00 +0300 Subject: [PATCH 15/21] fix: graceful IPC shutdown, logs --- src/util/meson.build | 2 +- src/util/wf-ipc.cpp | 63 +++++++++++++++++++++++++++++++++----------- src/util/wf-ipc.hpp | 2 +- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/util/meson.build b/src/util/meson.build index 6f2b8701..cdffc3de 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -8,7 +8,7 @@ util = static_library( 'css-config.cpp', 'wf-ipc.cpp', ], - dependencies: [wf_protos, wayland_client, gtkmm, wfconfig, libinotify, gtklayershell, json], + dependencies: [wf_protos, gtklayershell, wayland_client, gtkmm, wfconfig, libinotify, json], ) util_includes = include_directories('.') diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index e0e255f2..135df857 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #include "wf-ipc.hpp" +#include "giomm/cancellable.h" #include "giomm/error.h" #include "giomm/socketclient.h" #include "giomm/unixsocketaddress.h" @@ -40,7 +42,6 @@ WayfireIPC::WayfireIPC() WayfireIPC::~WayfireIPC() { disconnect(); - LOGI("IPC destroyed"); } void WayfireIPC::connect() @@ -57,13 +58,13 @@ void WayfireIPC::connect() connection->get_socket()->set_blocking(false); output = connection->get_output_stream(); input = connection->get_input_stream(); + cancel = Gio::Cancellable::create(); } void WayfireIPC::disconnect() { + cancel->cancel(); sig_connection.disconnect(); - input->close(); - output->close(); connection->close(); } @@ -94,7 +95,7 @@ void WayfireIPC::send_message(const std::string& message) void WayfireIPC::write_next() { - if (writing) + if (writing || cancel->is_cancelled()) { return; } @@ -124,19 +125,29 @@ void WayfireIPC::write_stream(const std::string& message) auto success = output->write_all_finish(result, written); if (!success) { - LOGE("Write failed. Bytes written: ", written); + LOGE("IPC error: write failed. Bytes written: ", written); } this->writing = false; - write_next(); + if (!cancel->is_cancelled()) + { + write_next(); + } } catch (const Glib::Error& e) { - LOGE("Write failed: ", e.what()); + if (e.code() == Gio::IO_ERROR_CANCELLED) + { + // Intended behavior + return; + } else + { + LOGE("IPC error: write failed: ", e.what()); + } } - }); + }, cancel); } catch (const Gio::Error& e) { - LOGE("GIO Error: ", e.what()); + LOGE("IPC error: ", e.what()); } } @@ -159,19 +170,30 @@ bool WayfireIPC::receive(Glib::IOCondition cond) { try { ssize_t received = 0; + uint32_t length; + // TODO: Input buffer can(?) contain incomplete message while (connection->get_socket()->get_available_bytes() > 0) { - received = input->read(&length, 4); + received = input->read(&length, sizeof(length)); if (received == -1) { - LOGE("Receive message length failed"); + LOGE("IPC error: Receive message length failed"); return false; } if (received == 0) { - LOGE("Disconnected"); + LOGE("IPC error: Disconnected"); + return false; + } + + if (received != sizeof(length)) + { + LOGE("IPC error: failed to read message. Expected (bytes): ", + sizeof(length), + ", was read (bytes)", + received); return false; } @@ -179,13 +201,22 @@ bool WayfireIPC::receive(Glib::IOCondition cond) received = input->read(&buf[0], length); if (received == -1) { - LOGE("Receive message body failed"); + LOGE("IPC error: receive message body failed"); return false; } if (received == 0) { - LOGE("Disconnected"); + LOGE("IPC error: Disconnected"); + return false; + } + + if (received != length) + { + LOGE("IPC error: failed to read message. Expected (bytes): ", + length, + ", was read (bytes)", + received); return false; } @@ -193,7 +224,7 @@ bool WayfireIPC::receive(Glib::IOCondition cond) auto err = wf::json_t::parse_string(buf, message); if (err.has_value()) { - LOGE("Parse error: ", err.value(), " message: ", buf, " length: ", buf.length()); + LOGE("IPC error: JSON parse: ", err.value(), " message: ", buf, " length: ", buf.length()); return false; } @@ -224,7 +255,7 @@ bool WayfireIPC::receive(Glib::IOCondition cond) } } catch (const Gio::Error& e) { - LOGE("GIO Error: ", e.what()); + LOGE("IPC error: ", e.what()); return false; } diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index 9f825274..f02b22b1 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -50,11 +50,11 @@ class WayfireIPC : public std::enable_shared_from_this { std::unordered_map> subscriptions; int next_client_id{1}; std::unordered_map clients; - uint32_t length; sigc::connection sig_connection; Glib::RefPtr connection; Glib::RefPtr input; Glib::RefPtr output; + Glib::RefPtr cancel; std::queue write_queue; bool writing = false; From 3857365d7c2f5a5865a085933c839742f9941f7a Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 7 Dec 2025 21:53:18 +0300 Subject: [PATCH 16/21] chore: code-style --- src/util/wf-ipc.cpp | 22 +++++++++++----------- src/util/wf-ipc.hpp | 16 ++++++++++------ 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index 135df857..53383478 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -115,7 +115,7 @@ void WayfireIPC::write_stream(const std::string& message) // Pointer to data must be valid until completely wrote and // slot is called, as documented for write_all_async. // So we pin it with a shared pointer, destroyed *after* slot is called. - auto all_data = std::make_shared((char*)&length, 4); + auto all_data = std::make_shared((char*)&length, 4); *all_data += message; output->write_all_async(all_data->data(), all_data->size(), [this, all_data] (Glib::RefPtr& result) @@ -191,9 +191,9 @@ bool WayfireIPC::receive(Glib::IOCondition cond) if (received != sizeof(length)) { LOGE("IPC error: failed to read message. Expected (bytes): ", - sizeof(length), - ", was read (bytes)", - received); + sizeof(length), + ", was read (bytes)", + received); return false; } @@ -214,9 +214,9 @@ bool WayfireIPC::receive(Glib::IOCondition cond) if (received != length) { LOGE("IPC error: failed to read message. Expected (bytes): ", - length, - ", was read (bytes)", - received); + length, + ", was read (bytes)", + received); return false; } @@ -308,7 +308,7 @@ std::shared_ptr WayfireIPC::create_client() { auto client = new IPCClient(next_client_id, shared_from_this()); clients[next_client_id++] = client; - + // Zero is reserved for NO CLIENT id, so just in case :) if (next_client_id == 0) { @@ -320,7 +320,7 @@ std::shared_ptr WayfireIPC::create_client() void WayfireIPC::client_destroyed(int id) { - clients.erase(id); + clients.erase(id); } std::shared_ptr WayfireIPC::get_instance() @@ -333,7 +333,7 @@ std::shared_ptr WayfireIPC::get_instance() instance = std::shared_ptr(new WayfireIPC()); ipc = instance; } - + return instance; } @@ -374,4 +374,4 @@ void IPCClient::subscribe_all(IIPCSubscriber *subscriber) void IPCClient::unsubscribe(IIPCSubscriber *subscriber) { ipc->unsubscribe(subscriber); -} \ No newline at end of file +} diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index f02b22b1..a4dcb1b2 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -28,12 +28,15 @@ class IIPCSubscriber using response_handler = std::function; class WayfireIPC; -class IPCClient { - int id; - std::shared_ptr ipc; - std::queue response_handlers; +class IPCClient +{ + int id; + std::shared_ptr ipc; + std::queue response_handlers; + public: - IPCClient(int id, std::shared_ptr ipc) : id(id), ipc(ipc) {} + IPCClient(int id, std::shared_ptr ipc) : id(id), ipc(ipc) + {} ~IPCClient(); int get_id(); void handle_response(wf::json_t response); @@ -44,7 +47,8 @@ class IPCClient { void unsubscribe(IIPCSubscriber *subscriber); }; -class WayfireIPC : public std::enable_shared_from_this { +class WayfireIPC : public std::enable_shared_from_this +{ std::queue response_handlers; std::set subscribers; std::unordered_map> subscriptions; From 3574e126b19fb19c88b4997b6ea94988b5cc36dd Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 7 Dec 2025 23:41:22 +0300 Subject: [PATCH 17/21] CI: yyjson --- .github/workflows/ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e8b9f3a8..a1b316df 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,7 +9,7 @@ jobs: steps: - run: echo 'http://dl-cdn.alpinelinux.org/alpine/v3.22/community' > /etc/apk/repositories - run: echo 'http://dl-cdn.alpinelinux.org/alpine/v3.22/main' >> /etc/apk/repositories - - run: apk --no-cache add git g++ binutils pkgconf meson ninja musl-dev gtkmm4-dev vala gobject-introspection gobject-introspection-dev pulseaudio-dev libdbusmenu-glib-dev alsa-lib-dev + - run: apk --no-cache add git g++ binutils pkgconf meson ninja musl-dev gtkmm4-dev vala gobject-introspection gobject-introspection-dev pulseaudio-dev libdbusmenu-glib-dev alsa-lib-dev yyjson-dev - run: echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories - run: echo 'http://dl-cdn.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories - run: apk --no-cache add wayland-protocols wayfire-dev gtk4-layer-shell-dev gtk4-layer-shell From 6fea5d2ef0725a2ed531c85cec134d87dd04d5e9 Mon Sep 17 00:00:00 2001 From: WShad Date: Sun, 7 Dec 2025 23:54:38 +0300 Subject: [PATCH 18/21] chore: more code-style --- src/util/wf-shell-app.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index 969c0c95..b5cd142c 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -177,7 +177,8 @@ static void registry_add_object(void *data, struct wl_registry *registry, static void registry_remove_object(void *data, struct wl_registry *registry, uint32_t name) -{} +{ +} static struct wl_registry_listener registry_listener = { @@ -343,4 +344,4 @@ WayfireOutput::~WayfireOutput() sigc::signal WayfireOutput::toggle_menu_signal() { return m_toggle_menu_signal; -} \ No newline at end of file +} From 43ec9d2ad1d5f2a3b0e62fb642f67e8ef68f9ad8 Mon Sep 17 00:00:00 2001 From: WShad Date: Mon, 8 Dec 2025 00:02:07 +0300 Subject: [PATCH 19/21] chore: clean-up --- src/util/wf-ipc.hpp | 3 --- src/util/wf-shell-app.hpp | 1 - 2 files changed, 4 deletions(-) diff --git a/src/util/wf-ipc.hpp b/src/util/wf-ipc.hpp index a4dcb1b2..968190f4 100644 --- a/src/util/wf-ipc.hpp +++ b/src/util/wf-ipc.hpp @@ -1,18 +1,15 @@ #ifndef WF_IPC_HPP #define WF_IPC_HPP -#include "gio/gio.h" #include "giomm/cancellable.h" #include "giomm/outputstream.h" #include "giomm/socketconnection.h" #include "glibmm/iochannel.h" #include "glibmm/refptr.h" -#include #include #include "sigc++/connection.h" #include #include -#include #include #include #include diff --git a/src/util/wf-shell-app.hpp b/src/util/wf-shell-app.hpp index 20207cf2..c7036ba8 100644 --- a/src/util/wf-shell-app.hpp +++ b/src/util/wf-shell-app.hpp @@ -10,7 +10,6 @@ #include #include "wayfire-shell-unstable-v2-client-protocol.h" -#include "wf-ipc.hpp" using GMonitor = Glib::RefPtr; From b2c8eaf81d50cdf48d80cf6865946cb325050469 Mon Sep 17 00:00:00 2001 From: WShad Date: Mon, 8 Dec 2025 00:18:11 +0300 Subject: [PATCH 20/21] chore: different uncrustify?? --- dependencies/wayfire-upstream | 1 + src/util/wf-shell-app.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 160000 dependencies/wayfire-upstream diff --git a/dependencies/wayfire-upstream b/dependencies/wayfire-upstream new file mode 160000 index 00000000..60231d5d --- /dev/null +++ b/dependencies/wayfire-upstream @@ -0,0 +1 @@ +Subproject commit 60231d5d8e7e4e5261894cea098b2c688726544f diff --git a/src/util/wf-shell-app.cpp b/src/util/wf-shell-app.cpp index b5cd142c..b740d864 100644 --- a/src/util/wf-shell-app.cpp +++ b/src/util/wf-shell-app.cpp @@ -177,8 +177,7 @@ static void registry_add_object(void *data, struct wl_registry *registry, static void registry_remove_object(void *data, struct wl_registry *registry, uint32_t name) -{ -} +{} static struct wl_registry_listener registry_listener = { From 6dbfa791a4087a355c8eeac610b8d3d87cc5cd26 Mon Sep 17 00:00:00 2001 From: WShad Date: Mon, 8 Dec 2025 13:03:04 +0300 Subject: [PATCH 21/21] fix: deps, paths, enums --- src/panel/meson.build | 1 + src/util/wf-ipc.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/panel/meson.build b/src/panel/meson.build index a3ef0788..d2c4b058 100644 --- a/src/panel/meson.build +++ b/src/panel/meson.build @@ -31,6 +31,7 @@ deps = [ wfconfig, dbusmenu_gtk, xkbregistry, + json, ] if libpulse.found() diff --git a/src/util/wf-ipc.cpp b/src/util/wf-ipc.cpp index 53383478..f5ee8735 100644 --- a/src/util/wf-ipc.cpp +++ b/src/util/wf-ipc.cpp @@ -3,8 +3,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -36,7 +36,7 @@ WayfireIPC::WayfireIPC() sig_connection = Glib::signal_io().connect( sigc::mem_fun(*this, &WayfireIPC::receive), connection->get_socket()->get_fd(), - Glib::IO_IN); + Glib::IOCondition::IO_IN); } WayfireIPC::~WayfireIPC() @@ -104,7 +104,7 @@ void WayfireIPC::write_next() sig_connection = Glib::signal_io().connect( sigc::mem_fun(*this, &WayfireIPC::send_queue), connection->get_socket()->get_fd(), - Glib::IO_OUT); + Glib::IOCondition::IO_OUT); } void WayfireIPC::write_stream(const std::string& message) @@ -135,7 +135,7 @@ void WayfireIPC::write_stream(const std::string& message) } } catch (const Glib::Error& e) { - if (e.code() == Gio::IO_ERROR_CANCELLED) + if (e.code() == G_IO_ERROR_CANCELLED) { // Intended behavior return;