diff --git a/meson.build b/meson.build index 3c53b50..98516e9 100644 --- a/meson.build +++ b/meson.build @@ -1,9 +1,9 @@ project('somebar', ['c', 'cpp'], - version: '0.1.0', - default_options: [ - 'cpp_std=c++17', - 'cpp_args=-Wno-parentheses', - ]) + version: '0.1.0', + default_options: [ + 'cpp_std=c++17', + 'cpp_args=-Wno-parentheses', + ]) wayland_dep = dependency('wayland-client') wayland_cursor_dep = dependency('wayland-cursor') @@ -14,16 +14,16 @@ pangocairo_dep = dependency('pangocairo') subdir('protocols') executable('somebar', - 'src/main.cpp', - 'src/shm_buffer.cpp', - 'src/bar.cpp', - wayland_sources, - dependencies: [ - wayland_dep, - wayland_cursor_dep, - cairo_dep, - pango_dep, - pangocairo_dep, - ], - install: true, - cpp_args: '-DSOMEBAR_VERSION="@0@"'.format(meson.project_version())) + 'src/main.cpp', + 'src/shm_buffer.cpp', + 'src/bar.cpp', + wayland_sources, + dependencies: [ + wayland_dep, + wayland_cursor_dep, + cairo_dep, + pango_dep, + pangocairo_dep, + ], + install: true, + cpp_args: '-DSOMEBAR_VERSION="@0@"'.format(meson.project_version())) diff --git a/protocols/meson.build b/protocols/meson.build index 023c918..5752608 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -3,21 +3,21 @@ wayland_scanner = find_program('wayland-scanner') wayland_protos_dep = dependency('wayland-protocols') wl_protocol_dir = wayland_protos_dep.get_pkgconfig_variable('pkgdatadir') wayland_scanner_code = generator( - wayland_scanner, - output: '@BASENAME@-protocol.c', - arguments: ['private-code', '@INPUT@', '@OUTPUT@']) + wayland_scanner, + output: '@BASENAME@-protocol.c', + arguments: ['private-code', '@INPUT@', '@OUTPUT@']) wayland_scanner_client = generator( - wayland_scanner, - output: '@BASENAME@-client-protocol.h', - arguments: ['client-header', '@INPUT@', '@OUTPUT@']) + wayland_scanner, + output: '@BASENAME@-client-protocol.h', + arguments: ['client-header', '@INPUT@', '@OUTPUT@']) wayland_xmls = [ - wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml', - wl_protocol_dir + '/unstable/xdg-output/xdg-output-unstable-v1.xml', - 'wlr-layer-shell-unstable-v1.xml', - 'net-tapesoftware-dwl-wm-unstable-v1.xml', + wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml', + wl_protocol_dir + '/unstable/xdg-output/xdg-output-unstable-v1.xml', + 'wlr-layer-shell-unstable-v1.xml', + 'net-tapesoftware-dwl-wm-unstable-v1.xml', ] wayland_sources = [ - wayland_scanner_code.process(wayland_xmls), - wayland_scanner_client.process(wayland_xmls), + wayland_scanner_code.process(wayland_xmls), + wayland_scanner_client.process(wayland_xmls), ] diff --git a/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml b/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml index 4fe5b73..390f5a1 100644 --- a/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml +++ b/protocols/net-tapesoftware-dwl-wm-unstable-v1.xml @@ -1,164 +1,164 @@ - - Copyright (c) 2021 Raphael Robatsch + + Copyright (c) 2021 Raphael Robatsch - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: - The above copyright notice and this permission notice (including the - next paragraph) shall be included in all copies or substantial portions - of the Software. + The above copyright notice and this permission notice (including the + next paragraph) shall be included in all copies or substantial portions + of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + - - - This interface is exposed as a global in the wl_registry. + + + This interface is exposed as a global in the wl_registry. - Clients can use this protocol to receive updates of the window manager - state (active tags, active layout, and focused window). - Clients can also control this state. + Clients can use this protocol to receive updates of the window manager + state (active tags, active layout, and focused window). + Clients can also control this state. - After binding, the client will receive the available tags and layouts - with the 'tag' and 'layout' events. These can be used in subsequent - dwl_wm_monitor_v1.set_tags/set_layout requests, and to interpret the - dwl_wm_monitor_v1.layout/tag events. - + After binding, the client will receive the available tags and layouts + with the 'tag' and 'layout' events. These can be used in subsequent + dwl_wm_monitor_v1.set_tags/set_layout requests, and to interpret the + dwl_wm_monitor_v1.layout/tag events. + - - - This request indicates that the client will not use the dwl_wm - object any more. Objects that have been created through this instance - are not affected. - - + + + This request indicates that the client will not use the dwl_wm + object any more. Objects that have been created through this instance + are not affected. + + - - - Gets a dwl monitor for the specified output. The window manager - state on the output can be controlled using the monitor. - - - - + + + Gets a dwl monitor for the specified output. The window manager + state on the output can be controlled using the monitor. + + + + - - - This event is sent immediately after binding. - A roundtrip after binding guarantees that the client has received all tags. - - - + + + This event is sent immediately after binding. + A roundtrip after binding guarantees that the client has received all tags. + + + - - - This event is sent immediately after binding. - A roundtrip after binding guarantees that the client has received all layouts. - - - - + + + This event is sent immediately after binding. + A roundtrip after binding guarantees that the client has received all layouts. + + + + - - - Observes and controls one monitor. + + + Observes and controls one monitor. - Events are double-buffered: Clients should cache all events and only - redraw themselves once the 'frame' event is sent. + Events are double-buffered: Clients should cache all events and only + redraw themselves once the 'frame' event is sent. - Requests are not double-buffered: The compositor will update itself - immediately. - + Requests are not double-buffered: The compositor will update itself + immediately. + - - - - - + + + + + - - - This request indicates that the client is done with this dwl_monitor. - All further requests are ignored. - - + + + This request indicates that the client is done with this dwl_monitor. + All further requests are ignored. + + - - - If 'selected' is nonzero, this monitor is the currently selected one. - - - + + + If 'selected' is nonzero, this monitor is the currently selected one. + + + - - - Announces the update of a tag. num_clients and focused_client can be - used to draw client indicators. - - - - - - + + + Announces the update of a tag. num_clients and focused_client can be + used to draw client indicators. + + + + + + - - - Announces the update of the selected layout. - - - + + + Announces the update of the selected layout. + + + - - - Announces the update of the selected client. - - - + + + Announces the update of the selected client. + + + - - - Sent after all other events belonging to the status update has been sent. - Clients should redraw themselves now. - - + + + Sent after all other events belonging to the status update has been sent. + Clients should redraw themselves now. + + - - - Changes are applied immediately. - - - - + + + Changes are applied immediately. + + + + - - - tags are updated as follows: - new_tags = (current_tags AND and_tags) XOR xor_tags + + + tags are updated as follows: + new_tags = (current_tags AND and_tags) XOR xor_tags - Changes are applied immediately. - - - - + Changes are applied immediately. + + + + - - - Changes are applied immediately. - - - - + + + Changes are applied immediately. + + + + diff --git a/src/bar.cpp b/src/bar.cpp index 959e822..bcc4c05 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -11,44 +11,44 @@ #include "pango/pango-layout.h" const zwlr_layer_surface_v1_listener Bar::_layerSurfaceListener = { - [](void* owner, zwlr_layer_surface_v1*, uint32_t serial, uint32_t width, uint32_t height) - { - static_cast(owner)->layerSurfaceConfigure(serial, width, height); - } + [](void* owner, zwlr_layer_surface_v1*, uint32_t serial, uint32_t width, uint32_t height) + { + static_cast(owner)->layerSurfaceConfigure(serial, width, height); + } }; const wl_callback_listener Bar::_frameListener = { - [](void* owner, wl_callback* cb, uint32_t) - { - static_cast(owner)->render(); - wl_callback_destroy(cb); - } + [](void* owner, wl_callback* cb, uint32_t) + { + static_cast(owner)->render(); + wl_callback_destroy(cb); + } }; struct Font { - PangoFontDescription* description; - int height {0}; + PangoFontDescription* description; + int height {0}; }; static Font getFont() { - auto fontMap = pango_cairo_font_map_get_default(); - if (!fontMap) die("pango_cairo_font_map_get_default"); - auto fontDesc = pango_font_description_from_string(font); - if (!fontDesc) die("pango_font_description_from_string"); - auto tempContext = pango_font_map_create_context(fontMap); - if (!tempContext) die("pango_font_map_create_context"); - auto font = pango_font_map_load_font(fontMap, tempContext, fontDesc); - if (!font) die("pango_font_map_load_font"); - auto metrics = pango_font_get_metrics(font, pango_language_get_default()); - if (!metrics) die("pango_font_get_metrics"); + auto fontMap = pango_cairo_font_map_get_default(); + if (!fontMap) die("pango_cairo_font_map_get_default"); + auto fontDesc = pango_font_description_from_string(font); + if (!fontDesc) die("pango_font_description_from_string"); + auto tempContext = pango_font_map_create_context(fontMap); + if (!tempContext) die("pango_font_map_create_context"); + auto font = pango_font_map_load_font(fontMap, tempContext, fontDesc); + if (!font) die("pango_font_map_load_font"); + auto metrics = pango_font_get_metrics(font, pango_language_get_default()); + if (!metrics) die("pango_font_get_metrics"); - auto res = Font {}; - res.description = fontDesc; - res.height = PANGO_PIXELS(pango_font_metrics_get_height(metrics)); + auto res = Font {}; + res.description = fontDesc; + res.height = PANGO_PIXELS(pango_font_metrics_get_height(metrics)); - pango_font_metrics_unref(metrics); - g_object_unref(font); - g_object_unref(tempContext); - return res; + pango_font_metrics_unref(metrics); + g_object_unref(font); + g_object_unref(tempContext); + return res; } static Font barfont = getFont(); @@ -56,27 +56,27 @@ BarComponent::BarComponent() { } BarComponent::BarComponent(wl_unique_ptr layout) : pangoLayout {std::move(layout)} {} int BarComponent::width() const { - int w, h; - pango_layout_get_size(pangoLayout.get(), &w, &h); - return PANGO_PIXELS(w); + int w, h; + pango_layout_get_size(pangoLayout.get(), &w, &h); + return PANGO_PIXELS(w); } void BarComponent::setText(const std::string& text) { - _text = std::make_unique(text); - pango_layout_set_text(pangoLayout.get(), _text->c_str(), _text->size()); + _text = std::make_unique(text); + pango_layout_set_text(pangoLayout.get(), _text->c_str(), _text->size()); } Bar::Bar(Monitor* mon) { - _mon = mon; - _pangoContext.reset(pango_font_map_create_context(pango_cairo_font_map_get_default())); - if (!_pangoContext) die("pango_font_map_create_context"); - for (auto i=0u; i _statusCmp.x) { - control = ClkStatusText; - } else if (x > _titleCmp.x) { - control = ClkWinTitle; - } else if (x > _layoutCmp.x) { - control = ClkLayoutSymbol; - } else for (auto tag = _tags.size()-1; tag >= 0; tag--) { - if (x > _tags[tag].component.x) { - control = ClkTagBar; - arg.ui = 1< _statusCmp.x) { + control = ClkStatusText; + } else if (x > _titleCmp.x) { + control = ClkWinTitle; + } else if (x > _layoutCmp.x) { + control = ClkLayoutSymbol; + } else for (auto tag = _tags.size()-1; tag >= 0; tag--) { + if (x > _tags[tag].component.x) { + control = ClkTagBar; + arg.ui = 1< {cairo_image_surface_create_for_data( - _bufs->data(), - CAIRO_FORMAT_ARGB32, - _bufs->width, - _bufs->height, - _bufs->stride - )}; - auto painter = wl_unique_ptr {cairo_create(img.get())}; - _painter = painter.get(); - pango_cairo_update_context(_painter, _pangoContext.get()); - _x = 0; + if (!visible()) return; + auto img = wl_unique_ptr {cairo_image_surface_create_for_data( + _bufs->data(), + CAIRO_FORMAT_ARGB32, + _bufs->width, + _bufs->height, + _bufs->stride + )}; + auto painter = wl_unique_ptr {cairo_create(img.get())}; + _painter = painter.get(); + pango_cairo_update_context(_painter, _pangoContext.get()); + _x = 0; - renderTags(); - setColorScheme(_selected ? colorActive : colorInactive); - renderComponent(_layoutCmp); - renderComponent(_titleCmp); - renderStatus(); - - _painter = nullptr; - wl_surface_attach(_surface.get(), _bufs->buffer(), 0, 0); - wl_surface_damage(_surface.get(), 0, 0, INT_MAX, INT_MAX); - wl_surface_commit(_surface.get()); - _bufs->flip(); - _invalid = false; + renderTags(); + setColorScheme(_selected ? colorActive : colorInactive); + renderComponent(_layoutCmp); + renderComponent(_titleCmp); + renderStatus(); + + _painter = nullptr; + wl_surface_attach(_surface.get(), _bufs->buffer(), 0, 0); + wl_surface_damage(_surface.get(), 0, 0, INT_MAX, INT_MAX); + wl_surface_commit(_surface.get()); + _bufs->flip(); + _invalid = false; } void Bar::renderTags() { - for (auto &tag : _tags) { - setColorScheme( - tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE ? colorActive : colorInactive, - tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT); - renderComponent(tag.component); - auto indicators = std::min(tag.numClients, _bufs->height/2); - for (auto ind = 0; ind < indicators; ind++) { - auto w = ind == tag.focusedClient ? 7 : 1; - cairo_move_to(_painter, tag.component.x, ind*2+0.5); - cairo_rel_line_to(_painter, w, 0); - cairo_close_path(_painter); - cairo_set_line_width(_painter, 1); - cairo_stroke(_painter); - } - } + for (auto &tag : _tags) { + setColorScheme( + tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE ? colorActive : colorInactive, + tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT); + renderComponent(tag.component); + auto indicators = std::min(tag.numClients, _bufs->height/2); + for (auto ind = 0; ind < indicators; ind++) { + auto w = ind == tag.focusedClient ? 7 : 1; + cairo_move_to(_painter, tag.component.x, ind*2+0.5); + cairo_rel_line_to(_painter, w, 0); + cairo_close_path(_painter); + cairo_set_line_width(_painter, 1); + cairo_stroke(_painter); + } + } } void Bar::renderStatus() { - pango_cairo_update_layout(_painter, _statusCmp.pangoLayout.get()); - beginBg(); - auto start = _bufs->width - _statusCmp.width() - paddingX*2; - cairo_rectangle(_painter, _x, 0, _bufs->width-_x+start, _bufs->height); - cairo_fill(_painter); + pango_cairo_update_layout(_painter, _statusCmp.pangoLayout.get()); + beginBg(); + auto start = _bufs->width - _statusCmp.width() - paddingX*2; + cairo_rectangle(_painter, _x, 0, _bufs->width-_x+start, _bufs->height); + cairo_fill(_painter); - _x = start; - renderComponent(_statusCmp); + _x = start; + renderComponent(_statusCmp); } void Bar::setColorScheme(const ColorScheme& scheme, bool invert) { - _colorScheme = invert - ? ColorScheme {scheme.bg, scheme.fg} - : ColorScheme {scheme.fg, scheme.bg}; + _colorScheme = invert + ? ColorScheme {scheme.bg, scheme.fg} + : ColorScheme {scheme.fg, scheme.bg}; } static void setColor(cairo_t* painter, const Color& color) { - cairo_set_source_rgba(painter, color.r/255.0, color.g/255.0, color.b/255.0, color.a/255.0); + cairo_set_source_rgba(painter, color.r/255.0, color.g/255.0, color.b/255.0, color.a/255.0); } void Bar::beginFg() { setColor(_painter, _colorScheme.fg); } void Bar::beginBg() { setColor(_painter, _colorScheme.bg); } void Bar::renderComponent(BarComponent& component) { - pango_cairo_update_layout(_painter, component.pangoLayout.get()); - auto size = component.width() + paddingX*2; - component.x = _x; + pango_cairo_update_layout(_painter, component.pangoLayout.get()); + auto size = component.width() + paddingX*2; + component.x = _x; - beginBg(); - cairo_rectangle(_painter, _x, 0, size, _bufs->height); - cairo_fill(_painter); - cairo_move_to(_painter, _x+paddingX, paddingY); + beginBg(); + cairo_rectangle(_painter, _x, 0, size, _bufs->height); + cairo_fill(_painter); + cairo_move_to(_painter, _x+paddingX, paddingY); - beginFg(); - pango_cairo_show_layout(_painter, component.pangoLayout.get()); - _x += size; + beginFg(); + pango_cairo_show_layout(_painter, component.pangoLayout.get()); + _x += size; } BarComponent Bar::createComponent(const std::string &initial) { - auto layout = pango_layout_new(_pangoContext.get()); - pango_layout_set_font_description(layout, barfont.description); - auto res = BarComponent {wl_unique_ptr {layout}}; - res.setText(initial); - return res; + auto layout = pango_layout_new(_pangoContext.get()); + pango_layout_set_font_description(layout, barfont.description); + auto res = BarComponent {wl_unique_ptr {layout}}; + res.setText(initial); + return res; } diff --git a/src/bar.hpp b/src/bar.hpp index 7c7bf32..4fc72e9 100644 --- a/src/bar.hpp +++ b/src/bar.hpp @@ -11,65 +11,65 @@ #include "shm_buffer.hpp" class BarComponent { - std::unique_ptr _text; + std::unique_ptr _text; public: - BarComponent(); - explicit BarComponent(wl_unique_ptr layout); - int width() const; - void setText(const std::string& text); - wl_unique_ptr pangoLayout; - int x {0}; + BarComponent(); + explicit BarComponent(wl_unique_ptr layout); + int width() const; + void setText(const std::string& text); + wl_unique_ptr pangoLayout; + int x {0}; }; struct Tag { - znet_tapesoftware_dwl_wm_monitor_v1_tag_state state; - int numClients; - int focusedClient; - BarComponent component; + znet_tapesoftware_dwl_wm_monitor_v1_tag_state state; + int numClients; + int focusedClient; + BarComponent component; }; struct Monitor; class Bar { - static const zwlr_layer_surface_v1_listener _layerSurfaceListener; - static const wl_callback_listener _frameListener; + static const zwlr_layer_surface_v1_listener _layerSurfaceListener; + static const wl_callback_listener _frameListener; - wl_unique_ptr _surface; - wl_unique_ptr _layerSurface; - wl_unique_ptr _pangoContext; - Monitor* _mon; - std::optional _bufs; - std::vector _tags; - BarComponent _layoutCmp, _titleCmp, _statusCmp; - bool _selected; - bool _invalid {false}; + wl_unique_ptr _surface; + wl_unique_ptr _layerSurface; + wl_unique_ptr _pangoContext; + Monitor* _mon; + std::optional _bufs; + std::vector _tags; + BarComponent _layoutCmp, _titleCmp, _statusCmp; + bool _selected; + bool _invalid {false}; - // only vaild during render() - cairo_t* _painter {nullptr}; - int _x; - ColorScheme _colorScheme; + // only vaild during render() + cairo_t* _painter {nullptr}; + int _x; + ColorScheme _colorScheme; - void layerSurfaceConfigure(uint32_t serial, uint32_t width, uint32_t height); - void render(); - void renderTags(); - void renderStatus(); + void layerSurfaceConfigure(uint32_t serial, uint32_t width, uint32_t height); + void render(); + void renderTags(); + void renderStatus(); - // low-level rendering - void setColorScheme(const ColorScheme& scheme, bool invert = false); - void beginFg(); - void beginBg(); - void renderComponent(BarComponent& component); - BarComponent createComponent(const std::string& initial = {}); + // low-level rendering + void setColorScheme(const ColorScheme& scheme, bool invert = false); + void beginFg(); + void beginBg(); + void renderComponent(BarComponent& component); + BarComponent createComponent(const std::string& initial = {}); public: - Bar(Monitor *mon); - const wl_surface* surface() const; - bool visible() const; - void show(wl_output* output); - void hide(); - void setTag(int tag, znet_tapesoftware_dwl_wm_monitor_v1_tag_state state, int numClients, int focusedClient); - void setSelected(bool selected); - void setLayout(int layout); - void setTitle(const std::string& title); - void setStatus(const std::string& status); - void invalidate(); - void click(int x, int y, int btn); + Bar(Monitor *mon); + const wl_surface* surface() const; + bool visible() const; + void show(wl_output* output); + void hide(); + void setTag(int tag, znet_tapesoftware_dwl_wm_monitor_v1_tag_state state, int numClients, int focusedClient); + void setSelected(bool selected); + void setLayout(int layout); + void setTitle(const std::string& title); + void setStatus(const std::string& status); + void invalidate(); + void click(int x, int y, int btn); }; diff --git a/src/common.hpp b/src/common.hpp index 3b2f491..548f67e 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -13,12 +13,12 @@ #include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h" struct Color { - Color() {} - constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a=255) : r(r), g(g), b(b), a(a) { } - uint8_t r, g, b, a {255}; + Color() {} + constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a=255) : r(r), g(g), b(b), a(a) { } + uint8_t r, g, b, a {255}; }; struct ColorScheme { - Color fg, bg; + Color fg, bg; }; union Arg { unsigned int ui; @@ -53,8 +53,8 @@ void spawn(Monitor&, const Arg& arg); template struct wl_deleter; #define WL_DELETER(type, fn) template<> struct wl_deleter { \ - void operator()(type* v) { if(v) fn(v); } \ - } + void operator()(type* v) { if(v) fn(v); } \ + } template using wl_unique_ptr = std::unique_ptr>; diff --git a/src/config.def.hpp b/src/config.def.hpp index 6197917..a9560cb 100644 --- a/src/config.def.hpp +++ b/src/config.def.hpp @@ -17,10 +17,10 @@ constexpr ColorScheme colorActive = {Color(0xee, 0xee, 0xee), Color(0x00, 0x55, constexpr const char* termcmd[] = {"foot", nullptr}; constexpr Button buttons[] = { - { ClkTagBar, BTN_LEFT, view, {0} }, - { ClkTagBar, BTN_RIGHT, tag, {0} }, - { ClkTagBar, BTN_MIDDLE, toggletag, {0} }, - { ClkLayoutSymbol, BTN_LEFT, setlayout, {.ui = 0} }, - { ClkLayoutSymbol, BTN_RIGHT, setlayout, {.ui = 2} }, - { ClkStatusText, BTN_RIGHT, spawn, {.v = termcmd} }, + { ClkTagBar, BTN_LEFT, view, {0} }, + { ClkTagBar, BTN_RIGHT, tag, {0} }, + { ClkTagBar, BTN_MIDDLE, toggletag, {0} }, + { ClkLayoutSymbol, BTN_LEFT, setlayout, {.ui = 0} }, + { ClkLayoutSymbol, BTN_RIGHT, setlayout, {.ui = 2} }, + { ClkStatusText, BTN_RIGHT, spawn, {.v = termcmd} }, }; diff --git a/src/line_buffer.hpp b/src/line_buffer.hpp index 64c6053..5331bf2 100644 --- a/src/line_buffer.hpp +++ b/src/line_buffer.hpp @@ -9,63 +9,63 @@ // reads data from Reader, and passes complete lines to Consumer. template class LineBuffer { - using Iterator = typename std::array::iterator; - std::array _buffer; - Iterator _bufferedTo; - Iterator _consumedTo; - bool _discardLine {false}; + using Iterator = typename std::array::iterator; + std::array _buffer; + Iterator _bufferedTo; + Iterator _consumedTo; + bool _discardLine {false}; public: - LineBuffer() - : _bufferedTo {_buffer.begin()} - , _consumedTo {_buffer.begin()} - { - } + LineBuffer() + : _bufferedTo {_buffer.begin()} + , _consumedTo {_buffer.begin()} + { + } - template - ssize_t readLines(const Reader& reader, const Consumer& consumer) - { - while (true) { - auto bytesRead = reader(_bufferedTo, _buffer.end() - _bufferedTo); - if (bytesRead <= 0) { - return bytesRead; - } - _bufferedTo += bytesRead; - dispatchLines(consumer); - resetBuffer(); - } - } -private: - template - void dispatchLines(const Consumer& consumer) - { - while (true) { - auto separator = std::find(_consumedTo, _bufferedTo, '\n'); - if (separator == _bufferedTo) { - break; - } - size_t lineLength = separator - _consumedTo; - if (!_discardLine) { - consumer(_consumedTo, lineLength); - } - _consumedTo = separator + 1; - _discardLine = false; - } - } + template + ssize_t readLines(const Reader& reader, const Consumer& consumer) + { + while (true) { + auto bytesRead = reader(_bufferedTo, _buffer.end() - _bufferedTo); + if (bytesRead <= 0) { + return bytesRead; + } + _bufferedTo += bytesRead; + dispatchLines(consumer); + resetBuffer(); + } + } + private: + template + void dispatchLines(const Consumer& consumer) + { + while (true) { + auto separator = std::find(_consumedTo, _bufferedTo, '\n'); + if (separator == _bufferedTo) { + break; + } + size_t lineLength = separator - _consumedTo; + if (!_discardLine) { + consumer(_consumedTo, lineLength); + } + _consumedTo = separator + 1; + _discardLine = false; + } + } - void resetBuffer() - { - size_t bytesRemaining = _bufferedTo - _consumedTo; - if (bytesRemaining == _buffer.size()) { - // line too long - _discardLine = true; - _consumedTo = _buffer.begin(); - _bufferedTo = _buffer.begin(); - } else if (bytesRemaining > 0 && _consumedTo > _buffer.begin()) { - // move the last partial message to the front of the buffer, so a full-sized - // message will fit - std::copy(_consumedTo, _bufferedTo, _buffer.begin()); - _consumedTo = _buffer.begin(); - _bufferedTo = _consumedTo + bytesRemaining; - } - } + void resetBuffer() + { + size_t bytesRemaining = _bufferedTo - _consumedTo; + if (bytesRemaining == _buffer.size()) { + // line too long + _discardLine = true; + _consumedTo = _buffer.begin(); + _bufferedTo = _buffer.begin(); + } else if (bytesRemaining > 0 && _consumedTo > _buffer.begin()) { + // move the last partial message to the front of the buffer, so a full-sized + // message will fit + std::copy(_consumedTo, _bufferedTo, _buffer.begin()); + _consumedTo = _buffer.begin(); + _bufferedTo = _consumedTo + bytesRemaining; + } + } }; diff --git a/src/main.cpp b/src/main.cpp index cfb5986..68be4b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -26,26 +26,26 @@ #include "line_buffer.hpp" struct Monitor { - uint32_t registryName; - std::string xdgName; - wl_unique_ptr wlOutput; - wl_unique_ptr dwlMonitor; - std::optional bar; - bool desiredVisibility {true}; - bool hasData; - uint32_t tags; + uint32_t registryName; + std::string xdgName; + wl_unique_ptr wlOutput; + wl_unique_ptr dwlMonitor; + std::optional bar; + bool desiredVisibility {true}; + bool hasData; + uint32_t tags; }; struct SeatPointer { - wl_unique_ptr wlPointer; - Bar* focusedBar; - int x, y; - std::vector btns; + wl_unique_ptr wlPointer; + Bar* focusedBar; + int x, y; + std::vector btns; }; struct Seat { - uint32_t name; - wl_unique_ptr wlSeat; - std::optional pointer; + uint32_t name; + wl_unique_ptr wlSeat; + std::optional pointer; }; static void updatemon(Monitor &mon); @@ -81,238 +81,238 @@ static bool quitting {false}; void view(Monitor& m, const Arg& arg) { - znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), arg.ui, 1); + znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), arg.ui, 1); } void toggleview(Monitor& m, const Arg& arg) { - znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), m.tags ^ arg.ui, 0); + znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), m.tags ^ arg.ui, 0); } void setlayout(Monitor& m, const Arg& arg) { - znet_tapesoftware_dwl_wm_monitor_v1_set_layout(m.dwlMonitor.get(), arg.ui); + znet_tapesoftware_dwl_wm_monitor_v1_set_layout(m.dwlMonitor.get(), arg.ui); } void tag(Monitor& m, const Arg& arg) { - znet_tapesoftware_dwl_wm_monitor_v1_set_client_tags(m.dwlMonitor.get(), 0, arg.ui); + znet_tapesoftware_dwl_wm_monitor_v1_set_client_tags(m.dwlMonitor.get(), 0, arg.ui); } void toggletag(Monitor& m, const Arg& arg) { - znet_tapesoftware_dwl_wm_monitor_v1_set_client_tags(m.dwlMonitor.get(), 0xffffff, arg.ui); + znet_tapesoftware_dwl_wm_monitor_v1_set_client_tags(m.dwlMonitor.get(), 0xffffff, arg.ui); } void spawn(Monitor&, const Arg& arg) { - if (fork() == 0) { - auto argv = static_cast(arg.v); - setsid(); - execvp(argv[0], argv); - fprintf(stderr, "somebar: execvp %s ", argv[0]); - perror(" failed"); - exit(1); - } + if (fork() == 0) { + auto argv = static_cast(arg.v); + setsid(); + execvp(argv[0], argv); + fprintf(stderr, "somebar: execvp %s ", argv[0]); + perror(" failed"); + exit(1); + } } static const struct xdg_wm_base_listener xdgWmBaseListener = { - [](void*, xdg_wm_base* sender, uint32_t serial) { - xdg_wm_base_pong(sender, serial); - } + [](void*, xdg_wm_base* sender, uint32_t serial) { + xdg_wm_base_pong(sender, serial); + } }; static const struct zxdg_output_v1_listener xdgOutputListener = { - .logical_position = [](void*, zxdg_output_v1*, int, int) { }, - .logical_size = [](void*, zxdg_output_v1*, int, int) { }, - .done = [](void*, zxdg_output_v1*) { }, - .name = [](void* mp, zxdg_output_v1* xdgOutput, const char* name) { - auto& monitor = *static_cast(mp); - monitor.xdgName = name; - zxdg_output_v1_destroy(xdgOutput); - }, - .description = [](void*, zxdg_output_v1*, const char*) { }, + .logical_position = [](void*, zxdg_output_v1*, int, int) { }, + .logical_size = [](void*, zxdg_output_v1*, int, int) { }, + .done = [](void*, zxdg_output_v1*) { }, + .name = [](void* mp, zxdg_output_v1* xdgOutput, const char* name) { + auto& monitor = *static_cast(mp); + monitor.xdgName = name; + zxdg_output_v1_destroy(xdgOutput); + }, + .description = [](void*, zxdg_output_v1*, const char*) { }, }; static Bar* barFromSurface(const wl_surface *surface) { - auto mon = std::find_if(begin(monitors), end(monitors), [surface](const Monitor& mon) { - return mon.bar && mon.bar->surface() == surface; - }); - return mon != end(monitors) && mon->bar ? &*mon->bar : nullptr; + auto mon = std::find_if(begin(monitors), end(monitors), [surface](const Monitor& mon) { + return mon.bar && mon.bar->surface() == surface; + }); + return mon != end(monitors) && mon->bar ? &*mon->bar : nullptr; } static const struct wl_pointer_listener pointerListener = { - .enter = [](void* sp, wl_pointer* pointer, uint32_t serial, - wl_surface* surface, wl_fixed_t x, wl_fixed_t y) - { - auto& seat = *static_cast(sp); - seat.pointer->focusedBar = barFromSurface(surface); - if (!cursorImage) { - auto cursorTheme = wl_cursor_theme_load(nullptr, 24, shm); - cursorImage = wl_cursor_theme_get_cursor(cursorTheme, "left_ptr")->images[0]; - cursorSurface = wl_compositor_create_surface(compositor); - wl_surface_attach(cursorSurface, wl_cursor_image_get_buffer(cursorImage), 0, 0); - wl_surface_commit(cursorSurface); - } - wl_pointer_set_cursor(pointer, serial, cursorSurface, - cursorImage->hotspot_x, cursorImage->hotspot_y); - }, - .leave = [](void* sp, wl_pointer*, uint32_t serial, wl_surface*) { - auto& seat = *static_cast(sp); - seat.pointer->focusedBar = nullptr; - }, - .motion = [](void* sp, wl_pointer*, uint32_t, wl_fixed_t x, wl_fixed_t y) { - auto& seat = *static_cast(sp); - seat.pointer->x = wl_fixed_to_int(x); - seat.pointer->y = wl_fixed_to_int(y); - }, - .button = [](void* sp, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) { - auto& seat = *static_cast(sp); - auto it = std::find(begin(seat.pointer->btns), end(seat.pointer->btns), button); - if (pressed == WL_POINTER_BUTTON_STATE_PRESSED && it == end(seat.pointer->btns)) { - seat.pointer->btns.push_back(button); - } else if (pressed == WL_POINTER_BUTTON_STATE_RELEASED && it != end(seat.pointer->btns)) { - seat.pointer->btns.erase(it); - } - }, - .axis = [](void* sp, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { }, - .frame = [](void* sp, wl_pointer*) { - auto& seat = *static_cast(sp); - if (!seat.pointer->focusedBar) return; - for (auto btn : seat.pointer->btns) { - seat.pointer->focusedBar->click(seat.pointer->x, seat.pointer->y, btn); - } - seat.pointer->btns.clear(); - }, - .axis_source = [](void*, wl_pointer*, uint32_t) { }, - .axis_stop = [](void*, wl_pointer*, uint32_t, uint32_t) { }, - .axis_discrete = [](void*, wl_pointer*, uint32_t, int32_t) { }, + .enter = [](void* sp, wl_pointer* pointer, uint32_t serial, + wl_surface* surface, wl_fixed_t x, wl_fixed_t y) + { + auto& seat = *static_cast(sp); + seat.pointer->focusedBar = barFromSurface(surface); + if (!cursorImage) { + auto cursorTheme = wl_cursor_theme_load(nullptr, 24, shm); + cursorImage = wl_cursor_theme_get_cursor(cursorTheme, "left_ptr")->images[0]; + cursorSurface = wl_compositor_create_surface(compositor); + wl_surface_attach(cursorSurface, wl_cursor_image_get_buffer(cursorImage), 0, 0); + wl_surface_commit(cursorSurface); + } + wl_pointer_set_cursor(pointer, serial, cursorSurface, + cursorImage->hotspot_x, cursorImage->hotspot_y); + }, + .leave = [](void* sp, wl_pointer*, uint32_t serial, wl_surface*) { + auto& seat = *static_cast(sp); + seat.pointer->focusedBar = nullptr; + }, + .motion = [](void* sp, wl_pointer*, uint32_t, wl_fixed_t x, wl_fixed_t y) { + auto& seat = *static_cast(sp); + seat.pointer->x = wl_fixed_to_int(x); + seat.pointer->y = wl_fixed_to_int(y); + }, + .button = [](void* sp, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) { + auto& seat = *static_cast(sp); + auto it = std::find(begin(seat.pointer->btns), end(seat.pointer->btns), button); + if (pressed == WL_POINTER_BUTTON_STATE_PRESSED && it == end(seat.pointer->btns)) { + seat.pointer->btns.push_back(button); + } else if (pressed == WL_POINTER_BUTTON_STATE_RELEASED && it != end(seat.pointer->btns)) { + seat.pointer->btns.erase(it); + } + }, + .axis = [](void* sp, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { }, + .frame = [](void* sp, wl_pointer*) { + auto& seat = *static_cast(sp); + if (!seat.pointer->focusedBar) return; + for (auto btn : seat.pointer->btns) { + seat.pointer->focusedBar->click(seat.pointer->x, seat.pointer->y, btn); + } + seat.pointer->btns.clear(); + }, + .axis_source = [](void*, wl_pointer*, uint32_t) { }, + .axis_stop = [](void*, wl_pointer*, uint32_t, uint32_t) { }, + .axis_discrete = [](void*, wl_pointer*, uint32_t, int32_t) { }, }; static const struct wl_seat_listener seatListener = { - .capabilities = [](void* sp, wl_seat*, uint32_t cap) - { - auto& seat = *static_cast(sp); - auto hasPointer = cap & WL_SEAT_CAPABILITY_POINTER; - if (!seat.pointer && hasPointer) { - auto &pointer = seat.pointer.emplace(); - pointer.wlPointer = wl_unique_ptr {wl_seat_get_pointer(seat.wlSeat.get())}; - wl_pointer_add_listener(seat.pointer->wlPointer.get(), &pointerListener, &seat); - } else if (seat.pointer && !hasPointer) { - seat.pointer.reset(); - } - }, - .name = [](void*, wl_seat*, const char *name) { } + .capabilities = [](void* sp, wl_seat*, uint32_t cap) + { + auto& seat = *static_cast(sp); + auto hasPointer = cap & WL_SEAT_CAPABILITY_POINTER; + if (!seat.pointer && hasPointer) { + auto &pointer = seat.pointer.emplace(); + pointer.wlPointer = wl_unique_ptr {wl_seat_get_pointer(seat.wlSeat.get())}; + wl_pointer_add_listener(seat.pointer->wlPointer.get(), &pointerListener, &seat); + } else if (seat.pointer && !hasPointer) { + seat.pointer.reset(); + } + }, + .name = [](void*, wl_seat*, const char *name) { } }; static const struct znet_tapesoftware_dwl_wm_v1_listener dwlWmListener = { - .tag = [](void*, znet_tapesoftware_dwl_wm_v1*, const char* name) { - tagNames.push_back(name); - }, - .layout = [](void*, znet_tapesoftware_dwl_wm_v1*, const char* name) { - layoutNames.push_back(name); - }, + .tag = [](void*, znet_tapesoftware_dwl_wm_v1*, const char* name) { + tagNames.push_back(name); + }, + .layout = [](void*, znet_tapesoftware_dwl_wm_v1*, const char* name) { + layoutNames.push_back(name); + }, }; static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorListener { - .selected = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t selected) { - auto mon = static_cast(mv); - if (selected) { - selmon = mon; - } else if (selmon == mon) { - selmon = nullptr; - } - mon->bar->setSelected(selected); - }, - .tag = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t tag, uint32_t state, uint32_t numClients, int32_t focusedClient) { - auto mon = static_cast(mv); - mon->bar->setTag(tag, static_cast(state), numClients, focusedClient); - uint32_t mask = 1 << tag; - if (state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE) { - mon->tags |= mask; - } else { - mon->tags &= ~mask; - } - }, - .layout = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t layout) { - auto mon = static_cast(mv); - mon->bar->setLayout(layout); - }, - .title = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, const char* title) { - auto mon = static_cast(mv); - mon->bar->setTitle(title); - }, - .frame = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*) { - auto mon = static_cast(mv); - mon->hasData = true; - updatemon(*mon); - } + .selected = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t selected) { + auto mon = static_cast(mv); + if (selected) { + selmon = mon; + } else if (selmon == mon) { + selmon = nullptr; + } + mon->bar->setSelected(selected); + }, + .tag = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t tag, uint32_t state, uint32_t numClients, int32_t focusedClient) { + auto mon = static_cast(mv); + mon->bar->setTag(tag, static_cast(state), numClients, focusedClient); + uint32_t mask = 1 << tag; + if (state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE) { + mon->tags |= mask; + } else { + mon->tags &= ~mask; + } + }, + .layout = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t layout) { + auto mon = static_cast(mv); + mon->bar->setLayout(layout); + }, + .title = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, const char* title) { + auto mon = static_cast(mv); + mon->bar->setTitle(title); + }, + .frame = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*) { + auto mon = static_cast(mv); + mon->hasData = true; + updatemon(*mon); + } }; static void setupMonitor(Monitor& monitor) { - monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get())); - monitor.bar.emplace(&monitor); - monitor.bar->setStatus(lastStatus); - auto xdgOutput = zxdg_output_manager_v1_get_xdg_output(xdgOutputManager, monitor.wlOutput.get()); - zxdg_output_v1_add_listener(xdgOutput, &xdgOutputListener, &monitor); - znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor); + monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get())); + monitor.bar.emplace(&monitor); + monitor.bar->setStatus(lastStatus); + auto xdgOutput = zxdg_output_manager_v1_get_xdg_output(xdgOutputManager, monitor.wlOutput.get()); + zxdg_output_v1_add_listener(xdgOutput, &xdgOutputListener, &monitor); + znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor); } static void updatemon(Monitor& mon) { - if (!mon.hasData) return; - if (mon.desiredVisibility) { - if (mon.bar->visible()) { - mon.bar->invalidate(); - } else { - mon.bar->show(mon.wlOutput.get()); - } - } else if (mon.bar->visible()) { - mon.bar->hide(); - } + if (!mon.hasData) return; + if (mon.desiredVisibility) { + if (mon.bar->visible()) { + mon.bar->invalidate(); + } else { + mon.bar->show(mon.wlOutput.get()); + } + } else if (mon.bar->visible()) { + mon.bar->hide(); + } } // called after we have received the initial batch of globals static void onReady() { - requireGlobal(compositor, "wl_compositor"); - requireGlobal(shm, "wl_shm"); - requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1"); - requireGlobal(xdgOutputManager, "zxdg_output_manager_v1"); - requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1"); - setupStatusFifo(); - wl_display_roundtrip(display); // roundtrip so we receive all dwl tags etc. - ready = true; - for (auto& monitor : monitors) { - setupMonitor(monitor); - } + requireGlobal(compositor, "wl_compositor"); + requireGlobal(shm, "wl_shm"); + requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1"); + requireGlobal(xdgOutputManager, "zxdg_output_manager_v1"); + requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1"); + setupStatusFifo(); + wl_display_roundtrip(display); // roundtrip so we receive all dwl tags etc. + ready = true; + for (auto& monitor : monitors) { + setupMonitor(monitor); + } } static void setupStatusFifo() { - for (auto i=0; i<100; i++) { - auto path = std::string{getenv("XDG_RUNTIME_DIR")} + "/somebar-" + std::to_string(i); - auto result = mkfifo(path.c_str(), 0666); - if (result == 0) { - auto fd = open(path.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY); - if (fd < 0) { - diesys("open status fifo reader"); - } - statusFifoName = path; - statusFifoFd = fd; + for (auto i=0; i<100; i++) { + auto path = std::string{getenv("XDG_RUNTIME_DIR")} + "/somebar-" + std::to_string(i); + auto result = mkfifo(path.c_str(), 0666); + if (result == 0) { + auto fd = open(path.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY); + if (fd < 0) { + diesys("open status fifo reader"); + } + statusFifoName = path; + statusFifoFd = fd; - fd = open(path.c_str(), O_CLOEXEC | O_WRONLY); - if (fd < 0) { - diesys("open status fifo writer"); - } - statusFifoWriter = fd; + fd = open(path.c_str(), O_CLOEXEC | O_WRONLY); + if (fd < 0) { + diesys("open status fifo writer"); + } + statusFifoWriter = fd; - epoll_event ev = {0}; - ev.events = EPOLLIN; - ev.data.fd = statusFifoFd; - if (epoll_ctl(epoll, EPOLL_CTL_ADD, statusFifoFd, &ev) < 0) { - diesys("epoll_ctl add status fifo"); - } - return; - } else if (errno != EEXIST) { - diesys("mkfifo"); - } - } + epoll_event ev = {0}; + ev.events = EPOLLIN; + ev.data.fd = statusFifoFd; + if (epoll_ctl(epoll, EPOLL_CTL_ADD, statusFifoFd, &ev) < 0) { + diesys("epoll_ctl add status fifo"); + } + return; + } else if (errno != EEXIST) { + diesys("mkfifo"); + } + } } const std::string prefixStatus = "status "; @@ -325,243 +325,243 @@ const std::string argSelected = "selected"; template static void updateVisibility(const std::string& name, T updater) { - auto isCurrent = name == argSelected; - auto isAll = name == argAll; - for (auto& mon : monitors) { - if (isAll || - isCurrent && &mon == selmon || - mon.xdgName == name) { - auto newVisibility = updater(mon.desiredVisibility); - if (newVisibility != mon.desiredVisibility) { - mon.desiredVisibility = newVisibility; - updatemon(mon); - } - } - } + auto isCurrent = name == argSelected; + auto isAll = name == argAll; + for (auto& mon : monitors) { + if (isAll || + isCurrent && &mon == selmon || + mon.xdgName == name) { + auto newVisibility = updater(mon.desiredVisibility); + if (newVisibility != mon.desiredVisibility) { + mon.desiredVisibility = newVisibility; + updatemon(mon); + } + } + } } static LineBuffer<512> _statusBuffer; static void onStatus() { - _statusBuffer.readLines( - [](void* p, size_t size) { - return read(statusFifoFd, p, size); - }, - [](const char* buffer, size_t n) { - auto str = std::string {buffer, n}; - if (str.rfind(prefixStatus, 0) == 0) { - lastStatus = str.substr(prefixStatus.size()); - for (auto &monitor : monitors) { - if (monitor.bar) { - monitor.bar->setStatus(lastStatus); - monitor.bar->invalidate(); - } - } - } else if (str.rfind(prefixShow, 0) == 0) { - updateVisibility(str.substr(prefixShow.size()), [](bool) { return true; }); - } else if (str.rfind(prefixHide, 0) == 0) { - updateVisibility(str.substr(prefixHide.size()), [](bool) { return false; }); - } else if (str.rfind(prefixToggle, 0) == 0) { - updateVisibility(str.substr(prefixToggle.size()), [](bool vis) { return !vis; }); - } - }); + _statusBuffer.readLines( + [](void* p, size_t size) { + return read(statusFifoFd, p, size); + }, + [](const char* buffer, size_t n) { + auto str = std::string {buffer, n}; + if (str.rfind(prefixStatus, 0) == 0) { + lastStatus = str.substr(prefixStatus.size()); + for (auto &monitor : monitors) { + if (monitor.bar) { + monitor.bar->setStatus(lastStatus); + monitor.bar->invalidate(); + } + } + } else if (str.rfind(prefixShow, 0) == 0) { + updateVisibility(str.substr(prefixShow.size()), [](bool) { return true; }); + } else if (str.rfind(prefixHide, 0) == 0) { + updateVisibility(str.substr(prefixHide.size()), [](bool) { return false; }); + } else if (str.rfind(prefixToggle, 0) == 0) { + updateVisibility(str.substr(prefixToggle.size()), [](bool vis) { return !vis; }); + } + }); } struct HandleGlobalHelper { - wl_registry* registry; - uint32_t name; - const char* interface; + wl_registry* registry; + uint32_t name; + const char* interface; - template - bool handle(T& store, const wl_interface& iface, int version) { - if (strcmp(interface, iface.name)) return false; - store = static_cast(wl_registry_bind(registry, name, &iface, version)); - return true; - } + template + bool handle(T& store, const wl_interface& iface, int version) { + if (strcmp(interface, iface.name)) return false; + store = static_cast(wl_registry_bind(registry, name, &iface, version)); + return true; + } }; static void registryHandleGlobal(void*, wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { - auto reg = HandleGlobalHelper { registry, name, interface }; - if (reg.handle(compositor, wl_compositor_interface, 4)) return; - if (reg.handle(shm, wl_shm_interface, 1)) return; - if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 4)) return; - if (reg.handle(xdgOutputManager, zxdg_output_manager_v1_interface, 3)) return; - if (reg.handle(xdgWmBase, xdg_wm_base_interface, 2)) { - xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr); - return; - } - if (reg.handle(dwlWm, znet_tapesoftware_dwl_wm_v1_interface, 1)) { - znet_tapesoftware_dwl_wm_v1_add_listener(dwlWm, &dwlWmListener, nullptr); - return; - } - if (wl_seat *wlSeat; reg.handle(wlSeat, wl_seat_interface, 7)) { - auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr {wlSeat}}); - wl_seat_add_listener(wlSeat, &seatListener, &seat); - return; - } - if (wl_output *output; reg.handle(output, wl_output_interface, 1)) { - auto& m = monitors.emplace_back(Monitor {name, {}, wl_unique_ptr {output}}); - if (ready) { - setupMonitor(m); - } - return; - } + auto reg = HandleGlobalHelper { registry, name, interface }; + if (reg.handle(compositor, wl_compositor_interface, 4)) return; + if (reg.handle(shm, wl_shm_interface, 1)) return; + if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 4)) return; + if (reg.handle(xdgOutputManager, zxdg_output_manager_v1_interface, 3)) return; + if (reg.handle(xdgWmBase, xdg_wm_base_interface, 2)) { + xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr); + return; + } + if (reg.handle(dwlWm, znet_tapesoftware_dwl_wm_v1_interface, 1)) { + znet_tapesoftware_dwl_wm_v1_add_listener(dwlWm, &dwlWmListener, nullptr); + return; + } + if (wl_seat *wlSeat; reg.handle(wlSeat, wl_seat_interface, 7)) { + auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr {wlSeat}}); + wl_seat_add_listener(wlSeat, &seatListener, &seat); + return; + } + if (wl_output *output; reg.handle(output, wl_output_interface, 1)) { + auto& m = monitors.emplace_back(Monitor {name, {}, wl_unique_ptr {output}}); + if (ready) { + setupMonitor(m); + } + return; + } } static void registryHandleRemove(void*, wl_registry* registry, uint32_t name) { - monitors.remove_if([name](const Monitor &mon) { return mon.registryName == name; }); - seats.remove_if([name](const Seat &seat) { return seat.name == name; }); + monitors.remove_if([name](const Monitor &mon) { return mon.registryName == name; }); + seats.remove_if([name](const Seat &seat) { return seat.name == name; }); } static const struct wl_registry_listener registry_listener = { - .global = registryHandleGlobal, - .global_remove = registryHandleRemove, + .global = registryHandleGlobal, + .global_remove = registryHandleRemove, }; int main(int argc, char* argv[]) { - int opt; - while ((opt = getopt(argc, argv, "chv")) != -1) { - switch (opt) { - case 'h': - printf("Usage: %s [-h] [-v] [-c command]\n", argv[0]); - printf(" -h: Show this help\n"); - printf(" -v: Show somebar version\n"); - printf(" -c: Sends a command to sombar. See README for details.\n"); - printf("If any of these are specified, somebar exits after the action.\n"); - printf("Otherwise, somebar will display itself.\n"); - exit(0); - case 'v': - printf("somebar " SOMEBAR_VERSION "\n"); - exit(0); - case 'c': - if (optind >= argc) { - die("Expected command"); - } - auto path = std::string {getenv("XDG_RUNTIME_DIR")} + "/somebar-0"; - int fd = open(path.c_str(), O_WRONLY | O_CLOEXEC); - if (fd < 0) { - fprintf(stderr, "could not open %s: ", path.c_str()); - perror(""); - exit(1); - } - auto str = std::string {}; - for (auto i = optind; i optind) str += " "; - str += argv[i]; - } - str += "\n"; - write(fd, str.c_str(), str.size()); - exit(0); - } - } - static sigset_t blockedsigs; - sigemptyset(&blockedsigs); - sigaddset(&blockedsigs, SIGINT); - sigaddset(&blockedsigs, SIGTERM); - sigprocmask(SIG_BLOCK, &blockedsigs, nullptr); + int opt; + while ((opt = getopt(argc, argv, "chv")) != -1) { + switch (opt) { + case 'h': + printf("Usage: %s [-h] [-v] [-c command]\n", argv[0]); + printf(" -h: Show this help\n"); + printf(" -v: Show somebar version\n"); + printf(" -c: Sends a command to sombar. See README for details.\n"); + printf("If any of these are specified, somebar exits after the action.\n"); + printf("Otherwise, somebar will display itself.\n"); + exit(0); + case 'v': + printf("somebar " SOMEBAR_VERSION "\n"); + exit(0); + case 'c': + if (optind >= argc) { + die("Expected command"); + } + auto path = std::string {getenv("XDG_RUNTIME_DIR")} + "/somebar-0"; + int fd = open(path.c_str(), O_WRONLY | O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "could not open %s: ", path.c_str()); + perror(""); + exit(1); + } + auto str = std::string {}; + for (auto i = optind; i optind) str += " "; + str += argv[i]; + } + str += "\n"; + write(fd, str.c_str(), str.size()); + exit(0); + } + } + static sigset_t blockedsigs; + sigemptyset(&blockedsigs); + sigaddset(&blockedsigs, SIGINT); + sigaddset(&blockedsigs, SIGTERM); + sigprocmask(SIG_BLOCK, &blockedsigs, nullptr); - epoll_event epollEv = {0}; - std::array epollEvents; - epoll = epoll_create1(EPOLL_CLOEXEC); - if (epoll < 0) { - diesys("epoll_create1"); - } - int sfd = signalfd(-1, &blockedsigs, SFD_CLOEXEC | SFD_NONBLOCK); - if (sfd < 0) { - diesys("signalfd"); - } - epollEv.events = EPOLLIN; - epollEv.data.fd = sfd; - if (epoll_ctl(epoll, EPOLL_CTL_ADD, sfd, &epollEv) < 0) { - diesys("epoll_ctl add signalfd"); - } + epoll_event epollEv = {0}; + std::array epollEvents; + epoll = epoll_create1(EPOLL_CLOEXEC); + if (epoll < 0) { + diesys("epoll_create1"); + } + int sfd = signalfd(-1, &blockedsigs, SFD_CLOEXEC | SFD_NONBLOCK); + if (sfd < 0) { + diesys("signalfd"); + } + epollEv.events = EPOLLIN; + epollEv.data.fd = sfd; + if (epoll_ctl(epoll, EPOLL_CTL_ADD, sfd, &epollEv) < 0) { + diesys("epoll_ctl add signalfd"); + } - display = wl_display_connect(nullptr); - if (!display) { - die("Failed to connect to Wayland display"); - } - displayFd = wl_display_get_fd(display); + display = wl_display_connect(nullptr); + if (!display) { + die("Failed to connect to Wayland display"); + } + displayFd = wl_display_get_fd(display); - auto registry = wl_display_get_registry(display); - wl_registry_add_listener(registry, ®istry_listener, nullptr); - wl_display_roundtrip(display); - onReady(); + auto registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istry_listener, nullptr); + wl_display_roundtrip(display); + onReady(); - epollEv.events = EPOLLIN; - epollEv.data.fd = displayFd; - if (epoll_ctl(epoll, EPOLL_CTL_ADD, displayFd, &epollEv) < 0) { - diesys("epoll_ctl add wayland_display"); - } + epollEv.events = EPOLLIN; + epollEv.data.fd = displayFd; + if (epoll_ctl(epoll, EPOLL_CTL_ADD, displayFd, &epollEv) < 0) { + diesys("epoll_ctl add wayland_display"); + } - while (!quitting) { - waylandFlush(); - auto res = epoll_wait(epoll, epollEvents.data(), epollEvents.size(), -1); - if (res < 0) { - if (errno != EINTR) { - diesys("epoll_wait"); - } - } else { - for (auto i=0; i(mmap(nullptr, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); - _mapping = MemoryMapping {ptr, totalSize}; - close(fd); - for (auto i=0; i { wl_shm_pool_create_buffer(pool, offset, width, height, stride, format) }, - }; - } - wl_shm_pool_destroy(pool); + auto oneSize = stride*size_t(h); + auto totalSize = oneSize * n; + auto fd = memfd_create("wl_shm", MFD_CLOEXEC); + ftruncate(fd, totalSize); + auto pool = wl_shm_create_pool(shm, fd, totalSize); + auto ptr = reinterpret_cast(mmap(nullptr, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + _mapping = MemoryMapping {ptr, totalSize}; + close(fd); + for (auto i=0; i { wl_shm_pool_create_buffer(pool, offset, width, height, stride, format) }, + }; + } + wl_shm_pool_destroy(pool); } uint8_t* ShmBuffer::data() { return _buffers[_current].data; } diff --git a/src/shm_buffer.hpp b/src/shm_buffer.hpp index 283cebb..217d2b6 100644 --- a/src/shm_buffer.hpp +++ b/src/shm_buffer.hpp @@ -8,38 +8,38 @@ #include "common.hpp" class MemoryMapping { - void* _ptr {nullptr}; - size_t _size {0}; + void* _ptr {nullptr}; + size_t _size {0}; public: - MemoryMapping() { } - explicit MemoryMapping(void* ptr, size_t size) : _ptr(ptr), _size(size) { } - MemoryMapping(const MemoryMapping&) = delete; - MemoryMapping(MemoryMapping&& other) { swap(other); } - MemoryMapping& operator=(const MemoryMapping& other) = delete; - MemoryMapping& operator=(MemoryMapping&& other) { swap(other); return *this; } - ~MemoryMapping() { if (_ptr) munmap(_ptr, _size); } - void swap(MemoryMapping &other) { - using std::swap; - swap(_ptr, other._ptr); - swap(_size, other._size); - } + MemoryMapping() { } + explicit MemoryMapping(void* ptr, size_t size) : _ptr(ptr), _size(size) { } + MemoryMapping(const MemoryMapping&) = delete; + MemoryMapping(MemoryMapping&& other) { swap(other); } + MemoryMapping& operator=(const MemoryMapping& other) = delete; + MemoryMapping& operator=(MemoryMapping&& other) { swap(other); return *this; } + ~MemoryMapping() { if (_ptr) munmap(_ptr, _size); } + void swap(MemoryMapping &other) { + using std::swap; + swap(_ptr, other._ptr); + swap(_size, other._size); + } }; // double buffered shm // format is must be 32-bit class ShmBuffer { - struct Buf { - uint8_t* data {nullptr}; - wl_unique_ptr buffer; - }; - std::array _buffers; - int _current {0}; - MemoryMapping _mapping; + struct Buf { + uint8_t* data {nullptr}; + wl_unique_ptr buffer; + }; + std::array _buffers; + int _current {0}; + MemoryMapping _mapping; public: - int width, height, stride; + int width, height, stride; - explicit ShmBuffer(int width, int height, wl_shm_format format); - uint8_t* data(); - wl_buffer* buffer(); - void flip(); + explicit ShmBuffer(int width, int height, wl_shm_format format); + uint8_t* data(); + wl_buffer* buffer(); + void flip(); };