Compare commits

...

10 commits

Author SHA1 Message Date
1793111112
Custom changes + IPC Patch 2024-01-28 00:04:26 +01:00
Raphael Robatsch
7433a1ff99 Loosen required zwlr_layer_shell_v1 version
Version 1 is enough for somebar. dwl exports version 3 but we don't even
need to go that high.
2023-11-30 17:11:26 +01:00
Ben Collerson
8c52d4704c clickable tags patch improvement 2023-08-02 20:18:08 +02:00
mortezadadgar
e1f8c63064 Fix possible OOB access for clicking tags
specify the signed type for indexing tags as intended
for `tag >= 0` check.

Signed-off-by: mortezadadgar <mortezadadgar97@gmail.com>
2023-08-01 21:24:08 +02:00
Ben Collerson
b069830640 patch: clickable tags using wtype 2023-04-08 19:30:30 +02:00
Sam Nystrom
af73bc3996 add patch to disable window title 2023-03-05 14:05:57 +01:00
Raphael Robatsch
9cdbf5f56f rebase ipc.patch 2023-02-25 09:06:44 +01:00
medanisjbara
624e92927b hide-vacant-tags: fix tag 0 is hiding all 2022-12-30 14:14:03 +01:00
Henrique Possatto
ea9dbfe022 patch to show square tag indicator like dwm 2022-12-30 14:11:14 +01:00
Raphael Robatsch
7d8c2f8b8c release v1.0.3 2022-12-11 19:30:30 +01:00
15 changed files with 456 additions and 109 deletions

2
.gitignore vendored
View file

@ -2,3 +2,5 @@ compile_commands.json
build build
.cache .cache
src/config.hpp src/config.hpp
custom_somebar.patch
somebar_config.hpp

View file

@ -1,4 +1,4 @@
## [Unreleased] ## [1.0.3] - 2022-12-11
### Added ### Added
- New patches: markup-in-status-messages, show-status-on-selected-monitor (benc) - New patches: markup-in-status-messages, show-status-on-selected-monitor (benc)
### Fixed ### Fixed

View file

@ -0,0 +1,91 @@
From: Ben Collerson <benc@benc.cc>
Date: Sat, 1 Apr 2023 09:16:19 +1000
Subject: [PATCH somebar] clickable tags using wtype
---
src/bar.cpp | 3 ++-
src/common.hpp | 2 ++
src/config.def.hpp | 5 +++++
src/main.cpp | 15 +++++++++++++++
4 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/bar.cpp b/src/bar.cpp
index af92f49..8b68759 100644
--- a/src/bar.cpp
+++ b/src/bar.cpp
@@ -182,9 +182,10 @@ void Bar::click(Monitor* mon, int x, int, int btn)
} else if (x > _layoutCmp.x) {
control = ClkLayoutSymbol;
} else for (int tag = _tags.size()-1; tag >= 0; tag--) {
+ // you may need logic to skip tags if they are hidden elsewhere.
if (x > _tags[tag].component.x) {
control = ClkTagBar;
- arg.ui = 1<<tag;
+ arg.ui = tag;
argp = &arg;
break;
}
diff --git a/src/common.hpp b/src/common.hpp
index c905358..a386029 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -39,6 +39,8 @@ extern wl_compositor* compositor;
extern wl_shm* shm;
extern zwlr_layer_shell_v1* wlrLayerShell;
+void view(Monitor& m, const Arg& arg);
+void tag(Monitor& m, const Arg& arg);
void spawn(Monitor&, const Arg& arg);
void setCloexec(int fd);
[[noreturn]] void die(const char* why);
diff --git a/src/config.def.hpp b/src/config.def.hpp
index 40a8c95..de193ea 100644
--- a/src/config.def.hpp
+++ b/src/config.def.hpp
@@ -4,6 +4,9 @@
#pragma once
#include "common.hpp"
+#define WTYPE "/usr/bin/wtype"
+#define MODKEY "alt"
+
constexpr bool topbar = true;
constexpr int paddingX = 10;
@@ -23,5 +26,7 @@ static std::vector<std::string> tagNames = {
};
constexpr Button buttons[] = {
+ { ClkTagBar, BTN_LEFT, view, {0} },
+ { ClkTagBar, BTN_RIGHT, tag, {0} },
{ ClkStatusText, BTN_RIGHT, spawn, {.v = termcmd} },
};
diff --git a/src/main.cpp b/src/main.cpp
index 6274959..3c35b20 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -85,6 +85,21 @@ static int statusFifoFd {-1};
static int statusFifoWriter {-1};
static bool quitting {false};
+// update keybindings to match your dwl
+void view(Monitor& m, const Arg& arg)
+{
+ char tag[2];
+ snprintf(tag, 2, "%i", arg.ui + 1);
+ if(fork() == 0)
+ execl(WTYPE, "wtype", "-M", MODKEY, tag, (char*)NULL);
+}
+void tag(Monitor& m, const Arg& arg)
+{
+ char tag[2];
+ snprintf(tag, 2, "%i", arg.ui + 1);
+ if(fork() == 0)
+ execl(WTYPE, "wtype", "-M", MODKEY, "-M", "shift", tag, (char*)NULL);
+}
void spawn(Monitor&, const Arg& arg)
{
if (fork() == 0) {
--
2.40.1

View file

@ -0,0 +1,15 @@
From: Sam Nystrom <samuel.l.nystrom@gmail.com>
Date: Sat, 4 Mar 2023 17:38:12 -0500
Description: disable window title
diff --git a/src/bar.cpp b/src/bar.cpp
index 507ce62..1b6f771 100644
--- a/src/bar.cpp
+++ b/src/bar.cpp
@@ -227,7 +227,6 @@ void Bar::render()
renderTags();
setColorScheme(_selected ? colorActive : colorInactive);
renderComponent(_layoutCmp);
- renderComponent(_titleCmp);
renderStatus();
_painter = nullptr;

View file

@ -0,0 +1,34 @@
From: Henrique Possatto <henriquempossatto@gmail.com>
Date: Mon, 26 Dec 2022 18:01:35 -0300
Subject: [PATCH somebar] patch to show square tag indicator like dwm
diff --git a/src/bar.cpp b/src/bar.cpp
index 507ce62..4fda8b0 100644
--- a/src/bar.cpp
+++ b/src/bar.cpp
@@ -245,12 +245,17 @@ void Bar::renderTags()
tag.state & TagState::Active ? colorActive : colorInactive,
tag.state & TagState::Urgent);
renderComponent(tag.component);
- auto indicators = std::min(tag.numClients, static_cast<int>(_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);
+
+ if(!tag.numClients)
+ continue;
+
+ int s = barfont.height / 9;
+ int w = barfont.height / 6 + 2;
+ if (tag.focusedClient != -1) {
+ cairo_rectangle(_painter, tag.component.x + s, s, w, w);
+ cairo_fill(_painter);
+ } else {
+ cairo_rectangle(_painter, (double)(tag.component.x + s) + 0.5, (double)(s) + 0.5, w, w);
cairo_set_line_width(_painter, 1);
cairo_stroke(_painter);
}
--
2.39.0

View file

@ -5,30 +5,50 @@ diff --git a/src/bar.cpp b/src/bar.cpp
index fab5a8f..38e7b5f 100644 index fab5a8f..38e7b5f 100644
--- a/src/bar.cpp --- a/src/bar.cpp
+++ b/src/bar.cpp +++ b/src/bar.cpp
@@ -240,12 +240,22 @@ void Bar::render() @@ -240,13 +240,36 @@ void Bar::render()
void Bar::renderTags() void Bar::renderTags()
{ {
+ bool focused; + // Check if all tags are active (Mod+0)
+ bool allActive = true;
for (auto &tag : _tags) { for (auto &tag : _tags) {
- setColorScheme( + if (tag.state & TagState::Active){
- tag.state & TagState::Active ? colorActive : colorInactive, + if (!allActive){
- tag.state & TagState::Urgent); + allActive = true;
- renderComponent(tag.component); + break;
+ focused = false; + }
auto indicators = std::min(tag.numClients, static_cast<int>(_bufs->height/2)); + allActive = false;
+ for (auto ind = 0; ind < indicators; ind++) {
+ if (tag.focusedClient){
+ focused = true;
+ } + }
+ } + }
+ +
+ if (tag.state & TagState::Active || focused){ + bool renderThis;
+ setColorScheme( + for (auto &tag : _tags) {
+ tag.state & TagState::Active ? colorActive : colorInactive, + renderThis = false;
+ tag.state & TagState::Urgent); setColorScheme(
+ renderComponent(tag.component); tag.state & TagState::Active ? colorActive : colorInactive,
+ } tag.state & TagState::Urgent);
- renderComponent(tag.component);
+ // Reder active tag if it's the only one active
+ if (!allActive && tag.state & TagState::Active)
+ renderThis = true;
auto indicators = std::min(tag.numClients, static_cast<int>(_bufs->height/2));
for (auto ind = 0; ind < indicators; ind++) { for (auto ind = 0; ind < indicators; ind++) {
+ // render tags having indicators
+ if (tag.focusedClient == -1)
+ renderThis = true;
+ // render tags having the focused client
+ if (tag.focusedClient == 0){
+ renderThis = true;
+ }
auto w = ind == tag.focusedClient ? 7 : 1; auto w = ind == tag.focusedClient ? 7 : 1;
cairo_move_to(_painter, tag.component.x, ind*2+0.5); cairo_move_to(_painter, tag.component.x, ind*2+0.5);
cairo_rel_line_to(_painter, w, 0);
@@ -254,6 +277,8 @@ void Bar::renderTags()
cairo_set_line_width(_painter, 1);
cairo_stroke(_painter);
}
+ if (renderThis)
+ renderComponent(tag.component);
}
}

View file

@ -193,7 +193,7 @@ index 0000000..390f5a1
+ </interface> + </interface>
+</protocol> +</protocol>
diff --git a/src/common.hpp b/src/common.hpp diff --git a/src/common.hpp b/src/common.hpp
index aed4480..12a3e2e 100644 index c905358..9b62a94 100644
--- a/src/common.hpp --- a/src/common.hpp
+++ b/src/common.hpp +++ b/src/common.hpp
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
@ -219,7 +219,7 @@ index aed4480..12a3e2e 100644
void spawn(Monitor&, const Arg& arg); void spawn(Monitor&, const Arg& arg);
void setCloexec(int fd); void setCloexec(int fd);
[[noreturn]] void die(const char* why); [[noreturn]] void die(const char* why);
@@ -59,6 +67,7 @@ WL_DELETER(wl_output, wl_output_release); @@ -65,6 +73,7 @@ WL_DELETER(wl_output, wl_output_release_checked);
WL_DELETER(wl_pointer, wl_pointer_release); WL_DELETER(wl_pointer, wl_pointer_release);
WL_DELETER(wl_seat, wl_seat_release); WL_DELETER(wl_seat, wl_seat_release);
WL_DELETER(wl_surface, wl_surface_destroy); WL_DELETER(wl_surface, wl_surface_destroy);
@ -250,7 +250,7 @@ index 40a8c95..a9560cb 100644
{ ClkStatusText, BTN_RIGHT, spawn, {.v = termcmd} }, { ClkStatusText, BTN_RIGHT, spawn, {.v = termcmd} },
}; };
diff --git a/src/main.cpp b/src/main.cpp diff --git a/src/main.cpp b/src/main.cpp
index 6198d8b..9e7549a 100644 index 6274959..01be870 100644
--- a/src/main.cpp --- a/src/main.cpp
+++ b/src/main.cpp +++ b/src/main.cpp
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
@ -403,8 +403,8 @@ index 6198d8b..9e7549a 100644
- wl_display_roundtrip(display); // wait for xdg_output names before we read stdin - wl_display_roundtrip(display); // wait for xdg_output names before we read stdin
} }
void setupStatusFifo() bool createFifo(std::string path)
@@ -259,66 +331,6 @@ void setupStatusFifo() @@ -273,68 +345,6 @@ void setupStatusFifo()
} }
} }
@ -435,6 +435,7 @@ index 6198d8b..9e7549a 100644
- return; - return;
- if (command == "title") { - if (command == "title") {
- auto title = std::string {}; - auto title = std::string {};
- stream >> std::ws;
- std::getline(stream, title); - std::getline(stream, title);
- mon->bar.setTitle(title); - mon->bar.setTitle(title);
- } else if (command == "selmon") { - } else if (command == "selmon") {
@ -461,6 +462,7 @@ index 6198d8b..9e7549a 100644
- mon->tags = tags; - mon->tags = tags;
- } else if (command == "layout") { - } else if (command == "layout") {
- auto layout = std::string {}; - auto layout = std::string {};
- stream >> std::ws;
- std::getline(stream, layout); - std::getline(stream, layout);
- mon->bar.setLayout(layout); - mon->bar.setLayout(layout);
- } - }
@ -471,7 +473,7 @@ index 6198d8b..9e7549a 100644
const std::string prefixStatus = "status "; const std::string prefixStatus = "status ";
const std::string prefixShow = "show "; const std::string prefixShow = "show ";
const std::string prefixHide = "hide "; const std::string prefixHide = "hide ";
@@ -393,6 +405,10 @@ void onGlobalAdd(void*, wl_registry* registry, uint32_t name, const char* interf @@ -409,6 +419,10 @@ void onGlobalAdd(void*, wl_registry* registry, uint32_t name, const char* interf
xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr); xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr);
return; return;
} }
@ -482,7 +484,7 @@ index 6198d8b..9e7549a 100644
if (wl_seat* wlSeat; reg.handle(wlSeat, wl_seat_interface, 7)) { if (wl_seat* wlSeat; reg.handle(wlSeat, wl_seat_interface, 7)) {
auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr<wl_seat> {wlSeat}}); auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr<wl_seat> {wlSeat}});
wl_seat_add_listener(wlSeat, &seatListener, &seat); wl_seat_add_listener(wlSeat, &seatListener, &seat);
@@ -494,10 +510,6 @@ int main(int argc, char* argv[]) @@ -522,10 +536,6 @@ int main(int argc, char* argv[])
.fd = displayFd, .fd = displayFd,
.events = POLLIN, .events = POLLIN,
}); });
@ -493,7 +495,7 @@ index 6198d8b..9e7549a 100644
if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0) { if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0) {
diesys("fcntl F_SETFL"); diesys("fcntl F_SETFL");
} }
@@ -522,8 +534,6 @@ int main(int argc, char* argv[]) @@ -550,8 +560,6 @@ int main(int argc, char* argv[])
ev.events = POLLIN; ev.events = POLLIN;
waylandFlush(); waylandFlush();
} }

2
generate_patch.sh Executable file
View file

@ -0,0 +1,2 @@
git diff 1.0.3 > custom_somebar.patch
cp ./src/config.def.hpp somebar_config.hpp

View file

@ -15,6 +15,7 @@ wayland_xmls = [
wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml', wl_protocol_dir + '/stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir + '/unstable/xdg-output/xdg-output-unstable-v1.xml', wl_protocol_dir + '/unstable/xdg-output/xdg-output-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml', 'wlr-layer-shell-unstable-v1.xml',
'net-tapesoftware-dwl-wm-unstable-v1.xml',
] ]
wayland_sources = [ wayland_sources = [
wayland_scanner_code.process(wayland_xmls), wayland_scanner_code.process(wayland_xmls),

View file

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="net_tapesoftware_dwl_wm_unstable_v1">
<copyright>
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:
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.
</copyright>
<interface name="znet_tapesoftware_dwl_wm_v1" version="1">
<description summary="control the dwl state">
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.
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.
</description>
<request name="release" type="destructor">
<description summary="release dwl_wm">
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.
</description>
</request>
<request name="get_monitor">
<description summary="gets a dwl monitor from an output">
Gets a dwl monitor for the specified output. The window manager
state on the output can be controlled using the monitor.
</description>
<arg name="id" type="new_id" interface="znet_tapesoftware_dwl_wm_monitor_v1" />
<arg name="output" type="object" interface="wl_output" />
</request>
<event name="tag">
<description summary="announces the presence of a tag">
This event is sent immediately after binding.
A roundtrip after binding guarantees that the client has received all tags.
</description>
<arg name="name" type="string"/>
</event>
<event name="layout">
<description summary="announces the presence of a layout">
This event is sent immediately after binding.
A roundtrip after binding guarantees that the client has received all layouts.
</description>
<arg name="name" type="string"/>
</event>
</interface>
<interface name="znet_tapesoftware_dwl_wm_monitor_v1" version="1">
<description summary="control 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.
Requests are not double-buffered: The compositor will update itself
immediately.
</description>
<enum name="tag_state">
<entry name="none" value="0" summary="no state"/>
<entry name="active" value="1" summary="tag is active"/>
<entry name="urgent" value="2" summary="tag has at least one urgent client"/>
</enum>
<request name="release" type="destructor">
<description summary="release dwl_monitor">
This request indicates that the client is done with this dwl_monitor.
All further requests are ignored.
</description>
</request>
<event name="selected">
<description summary="updates the selected state of the monitor">
If 'selected' is nonzero, this monitor is the currently selected one.
</description>
<arg name="selected" type="uint"/>
</event>
<event name="tag">
<description summary="updates the state of one tag">
Announces the update of a tag. num_clients and focused_client can be
used to draw client indicators.
</description>
<arg name="tag" type="uint" summary="index of a tag received by the dwl_wm_v1.tag event." />
<arg name="state" type="uint" enum="tag_state"/>
<arg name="num_clients" type="uint" summary="number of clients on this tag"/>
<arg name="focused_client" type="int" summary="out of num_clients. -1 if there is no focused client"/>
</event>
<event name="layout">
<description summary="updates the selected layout">
Announces the update of the selected layout.
</description>
<arg name="layout" type="uint" summary="index of a layout received by the dwl_wm_v1.layout event."/>
</event>
<event name="title">
<description summary="updates the focused client">
Announces the update of the selected client.
</description>
<arg name="title" type="string"/>
</event>
<event name="frame">
<description summary="end of status update sequence">
Sent after all other events belonging to the status update has been sent.
Clients should redraw themselves now.
</description>
</event>
<request name="set_tags">
<description summary="sets the active tags on this monitor.">
Changes are applied immediately.
</description>
<arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/>
<arg name="toggle_tagset" type="uint"/>
</request>
<request name="set_client_tags">
<description summary="updates the tags of the focused client.">
tags are updated as follows:
new_tags = (current_tags AND and_tags) XOR xor_tags
Changes are applied immediately.
</description>
<arg name="and_tags" type="uint"/>
<arg name="xor_tags" type="uint"/>
</request>
<request name="set_layout">
<description summary="sets the active layout on this monitor.">
Changes are applied immediately.
</description>
<arg name="layout" type="uint" summary="index of a layout received by the dwl_wm_v1.layout event."/>
</request>
</interface>
</protocol>

View file

@ -181,7 +181,7 @@ void Bar::click(Monitor* mon, int x, int, int btn)
control = ClkWinTitle; control = ClkWinTitle;
} else if (x > _layoutCmp.x) { } else if (x > _layoutCmp.x) {
control = ClkLayoutSymbol; control = ClkLayoutSymbol;
} else for (auto tag = _tags.size()-1; tag >= 0; tag--) { } else for (int tag = _tags.size()-1; tag >= 0; tag--) {
if (x > _tags[tag].component.x) { if (x > _tags[tag].component.x) {
control = ClkTagBar; control = ClkTagBar;
arg.ui = 1<<tag; arg.ui = 1<<tag;

View file

@ -10,6 +10,7 @@
#include <cairo/cairo.h> #include <cairo/cairo.h>
#include <pango/pango.h> #include <pango/pango.h>
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h"
struct Color { struct Color {
Color() {} Color() {}
@ -38,7 +39,14 @@ extern wl_display* display;
extern wl_compositor* compositor; extern wl_compositor* compositor;
extern wl_shm* shm; extern wl_shm* shm;
extern zwlr_layer_shell_v1* wlrLayerShell; extern zwlr_layer_shell_v1* wlrLayerShell;
extern std::vector<std::string> tagNames;
extern std::vector<std::string> layoutNames;
void view(Monitor& m, const Arg& arg);
void toggleview(Monitor& m, const Arg& arg);
void setlayout(Monitor& m, const Arg& arg);
void tag(Monitor& m, const Arg& arg);
void toggletag(Monitor& m, const Arg& arg);
void spawn(Monitor&, const Arg& arg); void spawn(Monitor&, const Arg& arg);
void setCloexec(int fd); void setCloexec(int fd);
[[noreturn]] void die(const char* why); [[noreturn]] void die(const char* why);
@ -65,6 +73,7 @@ WL_DELETER(wl_output, wl_output_release_checked);
WL_DELETER(wl_pointer, wl_pointer_release); WL_DELETER(wl_pointer, wl_pointer_release);
WL_DELETER(wl_seat, wl_seat_release); WL_DELETER(wl_seat, wl_seat_release);
WL_DELETER(wl_surface, wl_surface_destroy); WL_DELETER(wl_surface, wl_surface_destroy);
WL_DELETER(znet_tapesoftware_dwl_wm_monitor_v1, znet_tapesoftware_dwl_wm_monitor_v1_release);
WL_DELETER(zwlr_layer_surface_v1, zwlr_layer_surface_v1_destroy); WL_DELETER(zwlr_layer_surface_v1, zwlr_layer_surface_v1_destroy);
WL_DELETER(cairo_t, cairo_destroy); WL_DELETER(cairo_t, cairo_destroy);

View file

@ -16,12 +16,11 @@ constexpr ColorScheme colorInactive = {Color(0xbb, 0xbb, 0xbb), Color(0x22, 0x22
constexpr ColorScheme colorActive = {Color(0xee, 0xee, 0xee), Color(0x00, 0x55, 0x77)}; constexpr ColorScheme colorActive = {Color(0xee, 0xee, 0xee), Color(0x00, 0x55, 0x77)};
constexpr const char* termcmd[] = {"foot", nullptr}; constexpr const char* termcmd[] = {"foot", nullptr};
static std::vector<std::string> tagNames = {
"1", "2", "3",
"4", "5", "6",
"7", "8", "9",
};
constexpr Button buttons[] = { 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} }, { ClkStatusText, BTN_RIGHT, spawn, {.v = termcmd} },
}; };

View file

@ -10,7 +10,7 @@
template<size_t BufSize> template<size_t BufSize>
class LineBuffer { class LineBuffer {
using Iterator = typename std::array<char, BufSize>::iterator; using Iterator = typename std::array<char, BufSize>::iterator;
std::array<char, BufSize> _buffer; std::array<char, BufSize> _buffer = {};
Iterator _bufferedTo; Iterator _bufferedTo;
Iterator _consumedTo; Iterator _consumedTo;
bool _discardLine {false}; bool _discardLine {false};

View file

@ -3,7 +3,6 @@
#include <algorithm> #include <algorithm>
#include <cstdio> #include <cstdio>
#include <sstream>
#include <list> #include <list>
#include <optional> #include <optional>
#include <utility> #include <utility>
@ -21,8 +20,8 @@
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h" #include "xdg-shell-client-protocol.h"
#include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h"
#include "common.hpp" #include "common.hpp"
#include "config.hpp"
#include "bar.hpp" #include "bar.hpp"
#include "line_buffer.hpp" #include "line_buffer.hpp"
@ -34,6 +33,7 @@ struct Monitor {
bool desiredVisibility {true}; bool desiredVisibility {true};
bool hasData; bool hasData;
uint32_t tags; uint32_t tags;
wl_unique_ptr<znet_tapesoftware_dwl_wm_monitor_v1> dwlMonitor;
}; };
struct SeatPointer { struct SeatPointer {
@ -54,8 +54,6 @@ static void updatemon(Monitor &mon);
static void onReady(); static void onReady();
static void setupStatusFifo(); static void setupStatusFifo();
static void onStatus(); static void onStatus();
static void onStdin();
static void handleStdin(const std::string& line);
static void updateVisibility(const std::string& name, bool(*updater)(bool)); static void updateVisibility(const std::string& name, bool(*updater)(bool));
static void onGlobalAdd(void*, wl_registry* registry, uint32_t name, const char* interface, uint32_t version); static void onGlobalAdd(void*, wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
static void onGlobalRemove(void*, wl_registry* registry, uint32_t name); static void onGlobalRemove(void*, wl_registry* registry, uint32_t name);
@ -67,6 +65,9 @@ wl_display* display;
wl_compositor* compositor; wl_compositor* compositor;
wl_shm* shm; wl_shm* shm;
zwlr_layer_shell_v1* wlrLayerShell; zwlr_layer_shell_v1* wlrLayerShell;
znet_tapesoftware_dwl_wm_v1* dwlWm;
std::vector<std::string> tagNames;
std::vector<std::string> layoutNames;
static xdg_wm_base* xdgWmBase; static xdg_wm_base* xdgWmBase;
static zxdg_output_manager_v1* xdgOutputManager; static zxdg_output_manager_v1* xdgOutputManager;
static wl_surface* cursorSurface; static wl_surface* cursorSurface;
@ -85,6 +86,26 @@ static int statusFifoFd {-1};
static int statusFifoWriter {-1}; static int statusFifoWriter {-1};
static bool quitting {false}; 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);
}
void toggleview(Monitor& m, const Arg& arg)
{
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);
}
void tag(Monitor& m, const Arg& arg)
{
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(), ~0, arg.ui);
}
void spawn(Monitor&, const Arg& arg) void spawn(Monitor&, const Arg& arg)
{ {
if (fork() == 0) { if (fork() == 0) {
@ -189,11 +210,62 @@ static const struct wl_seat_listener seatListener = {
.name = [](void*, wl_seat*, const char* name) { } .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);
},
};
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<Monitor*>(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<Monitor*>(mv);
int tagState = TagState::None;
if (state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE)
tagState |= TagState::Active;
if (state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT)
tagState |= TagState::Urgent;
mon->bar.setTag(tag, tagState, numClients, focusedClient);
uint32_t mask = 1 << tag;
if (tagState & TagState::Active) {
mon->tags |= mask;
} else {
mon->tags &= ~mask;
}
},
.layout = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t layout) {
auto mon = static_cast<Monitor*>(mv);
mon->bar.setLayout(layoutNames[layout]);
},
.title = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*, const char* title) {
auto mon = static_cast<Monitor*>(mv);
mon->bar.setTitle(title);
},
.frame = [](void* mv, znet_tapesoftware_dwl_wm_monitor_v1*) {
auto mon = static_cast<Monitor*>(mv);
mon->hasData = true;
updatemon(*mon);
}
};
void setupMonitor(uint32_t name, wl_output* output) { void setupMonitor(uint32_t name, wl_output* output) {
auto& monitor = monitors.emplace_back(Monitor {name, {}, wl_unique_ptr<wl_output> {output}}); auto& monitor = monitors.emplace_back(Monitor {name, {}, wl_unique_ptr<wl_output> {output}});
monitor.bar.setStatus(lastStatus); monitor.bar.setStatus(lastStatus);
auto xdgOutput = zxdg_output_manager_v1_get_xdg_output(xdgOutputManager, monitor.wlOutput.get()); auto xdgOutput = zxdg_output_manager_v1_get_xdg_output(xdgOutputManager, monitor.wlOutput.get());
zxdg_output_v1_add_listener(xdgOutput, &xdgOutputListener, &monitor); zxdg_output_v1_add_listener(xdgOutput, &xdgOutputListener, &monitor);
monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get()));
znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor);
} }
void updatemon(Monitor& mon) void updatemon(Monitor& mon)
@ -219,6 +291,7 @@ void onReady()
requireGlobal(shm, "wl_shm"); requireGlobal(shm, "wl_shm");
requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1"); requireGlobal(wlrLayerShell, "zwlr_layer_shell_v1");
requireGlobal(xdgOutputManager, "zxdg_output_manager_v1"); requireGlobal(xdgOutputManager, "zxdg_output_manager_v1");
requireGlobal(dwlWm, "znet_tapesoftware_dwl_wm_v1");
setupStatusFifo(); setupStatusFifo();
wl_display_roundtrip(display); // roundtrip so we receive all dwl tags etc. wl_display_roundtrip(display); // roundtrip so we receive all dwl tags etc.
@ -226,7 +299,6 @@ void onReady()
for (auto output : uninitializedOutputs) { for (auto output : uninitializedOutputs) {
setupMonitor(output.first, output.second); setupMonitor(output.first, output.second);
} }
wl_display_roundtrip(display); // wait for xdg_output names before we read stdin
} }
bool createFifo(std::string path) bool createFifo(std::string path)
@ -273,68 +345,6 @@ void setupStatusFifo()
} }
} }
static LineBuffer<512> stdinBuffer;
static void onStdin()
{
auto res = stdinBuffer.readLines(
[](void* p, size_t size) { return read(0, p, size); },
[](char* p, size_t size) { handleStdin({p, size}); });
if (res == 0) {
quitting = true;
}
}
static void handleStdin(const std::string& line)
{
// this parses the lines that dwl sends in printstatus()
std::string monName, command;
auto stream = std::istringstream {line};
stream >> monName >> command;
if (!stream.good()) {
return;
}
auto mon = std::find_if(begin(monitors), end(monitors), [&](const Monitor& mon) {
return mon.xdgName == monName;
});
if (mon == end(monitors))
return;
if (command == "title") {
auto title = std::string {};
stream >> std::ws;
std::getline(stream, title);
mon->bar.setTitle(title);
} else if (command == "selmon") {
uint32_t selected;
stream >> selected;
mon->bar.setSelected(selected);
if (selected) {
selmon = &*mon;
} else if (selmon == &*mon) {
selmon = nullptr;
}
} else if (command == "tags") {
uint32_t occupied, tags, clientTags, urgent;
stream >> occupied >> tags >> clientTags >> urgent;
for (auto i=0u; i<tagNames.size(); i++) {
auto tagMask = 1 << i;
int state = TagState::None;
if (tags & tagMask)
state |= TagState::Active;
if (urgent & tagMask)
state |= TagState::Urgent;
mon->bar.setTag(i, state, occupied & tagMask ? 1 : 0, clientTags & tagMask ? 0 : -1);
}
mon->tags = tags;
} else if (command == "layout") {
auto layout = std::string {};
stream >> std::ws;
std::getline(stream, layout);
mon->bar.setLayout(layout);
}
mon->hasData = true;
updatemon(*mon);
}
const std::string prefixStatus = "status "; const std::string prefixStatus = "status ";
const std::string prefixShow = "show "; const std::string prefixShow = "show ";
const std::string prefixHide = "hide "; const std::string prefixHide = "hide ";
@ -403,12 +413,16 @@ void onGlobalAdd(void*, wl_registry* registry, uint32_t name, const char* interf
auto reg = HandleGlobalHelper { registry, name, interface }; auto reg = HandleGlobalHelper { registry, name, interface };
if (reg.handle(compositor, wl_compositor_interface, 4)) return; if (reg.handle(compositor, wl_compositor_interface, 4)) return;
if (reg.handle(shm, wl_shm_interface, 1)) return; if (reg.handle(shm, wl_shm_interface, 1)) return;
if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 4)) return; if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 1)) return;
if (reg.handle(xdgOutputManager, zxdg_output_manager_v1_interface, 3)) return; if (reg.handle(xdgOutputManager, zxdg_output_manager_v1_interface, 3)) return;
if (reg.handle(xdgWmBase, xdg_wm_base_interface, 2)) { if (reg.handle(xdgWmBase, xdg_wm_base_interface, 2)) {
xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr); xdg_wm_base_add_listener(xdgWmBase, &xdgWmBaseListener, nullptr);
return; 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)) { if (wl_seat* wlSeat; reg.handle(wlSeat, wl_seat_interface, 7)) {
auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr<wl_seat> {wlSeat}}); auto& seat = seats.emplace_back(Seat {name, wl_unique_ptr<wl_seat> {wlSeat}});
wl_seat_add_listener(wlSeat, &seatListener, &seat); wl_seat_add_listener(wlSeat, &seatListener, &seat);
@ -522,10 +536,6 @@ int main(int argc, char* argv[])
.fd = displayFd, .fd = displayFd,
.events = POLLIN, .events = POLLIN,
}); });
pollfds.push_back({
.fd = STDIN_FILENO,
.events = POLLIN,
});
if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0) { if (fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK) < 0) {
diesys("fcntl F_SETFL"); diesys("fcntl F_SETFL");
} }
@ -550,8 +560,6 @@ int main(int argc, char* argv[])
ev.events = POLLIN; ev.events = POLLIN;
waylandFlush(); waylandFlush();
} }
} else if (ev.fd == STDIN_FILENO && (ev.revents & POLLIN)) {
onStdin();
} else if (ev.fd == statusFifoFd && (ev.revents & POLLIN)) { } else if (ev.fd == statusFifoFd && (ev.revents & POLLIN)) {
onStatus(); onStatus();
} else if (ev.fd == signalSelfPipe[0] && (ev.revents & POLLIN)) { } else if (ev.fd == signalSelfPipe[0] && (ev.revents & POLLIN)) {