mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-31 07:52:42 +01:00 
			
		
		
		
	Add DWL tags module
This commit is contained in:
		| @@ -9,6 +9,7 @@ | ||||
| - Sway (Workspaces, Binding mode, Focused window name) | ||||
| - River (Mapping mode, Tags, Focused window name) | ||||
| - Hyprland (Focused window name) | ||||
| - DWL (Tags) [requires dwl ipc patch](https://github.com/djpohly/dwl/wiki/ipc) | ||||
| - Tray [#21](https://github.com/Alexays/Waybar/issues/21) | ||||
| - Local time | ||||
| - Battery | ||||
|   | ||||
| @@ -23,6 +23,9 @@ | ||||
| #include "modules/river/tags.hpp" | ||||
| #include "modules/river/window.hpp" | ||||
| #endif | ||||
| #ifdef HAVE_DWL | ||||
| #include "modules/dwl/tags.hpp" | ||||
| #endif | ||||
| #ifdef HAVE_HYPRLAND | ||||
| #include "modules/hyprland/backend.hpp" | ||||
| #include "modules/hyprland/language.hpp" | ||||
|   | ||||
							
								
								
									
										34
									
								
								include/modules/dwl/tags.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								include/modules/dwl/tags.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <gtkmm/button.h> | ||||
| #include <wayland-client.h> | ||||
|  | ||||
| #include "AModule.hpp" | ||||
| #include "bar.hpp" | ||||
| #include "dwl-bar-ipc-unstable-v1-client-protocol.h" | ||||
| #include "xdg-output-unstable-v1-client-protocol.h" | ||||
|  | ||||
| namespace waybar::modules::dwl { | ||||
|  | ||||
| class Tags : public waybar::AModule { | ||||
|  public: | ||||
|   Tags(const std::string &, const waybar::Bar &, const Json::Value &); | ||||
|   virtual ~Tags(); | ||||
|  | ||||
|   // Handlers for wayland events | ||||
|   void handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused); | ||||
|  | ||||
|   void handle_primary_clicked(uint32_t tag); | ||||
|   bool handle_button_press(GdkEventButton *event_button, uint32_t tag); | ||||
|  | ||||
|   struct zdwl_manager_v1 *status_manager_; | ||||
|   struct wl_seat *seat_; | ||||
|  | ||||
|  private: | ||||
|   const waybar::Bar &bar_; | ||||
|   Gtk::Box box_; | ||||
|   std::vector<Gtk::Button> buttons_; | ||||
|   struct zdwl_output_v1 *output_status_; | ||||
| }; | ||||
|  | ||||
| } /* namespace waybar::modules::dwl */ | ||||
							
								
								
									
										49
									
								
								man/waybar-dwl-tags.5.scd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								man/waybar-dwl-tags.5.scd
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| waybar-dwl-tags(5) | ||||
|  | ||||
| # NAME | ||||
|  | ||||
| waybar - dwl tags module | ||||
|  | ||||
| # DESCRIPTION | ||||
|  | ||||
| The *tags* module displays the current state of tags in dwl. | ||||
|  | ||||
| # CONFIGURATION | ||||
|  | ||||
| Addressed by *dwl/tags* | ||||
|  | ||||
| *num-tags*: ++ | ||||
|     typeof: uint ++ | ||||
|     default: 9 ++ | ||||
|     The number of tags that should be displayed. Max 32. | ||||
|  | ||||
| *tag-labels*: ++ | ||||
|     typeof: array ++ | ||||
|     The label to display for each tag. | ||||
|  | ||||
| *disable-click*: ++ | ||||
|    typeof: bool ++ | ||||
|    default: false ++ | ||||
|    If set to false, you can left click to set focused tag. Right click to toggle tag focus. If set to true this behaviour is disabled. | ||||
|  | ||||
| # EXAMPLE | ||||
|  | ||||
| ``` | ||||
| "dwl/tags": { | ||||
|     "num-tags": 5 | ||||
| } | ||||
| ``` | ||||
|  | ||||
| # STYLE | ||||
|  | ||||
| - *#tags button* | ||||
| - *#tags button.occupied* | ||||
| - *#tags button.focused* | ||||
| - *#tags button.urgent* | ||||
|  | ||||
| Note that occupied/focused/urgent status may overlap. That is, a tag may be | ||||
| both occupied and focused at the same time. | ||||
|  | ||||
| # SEE ALSO | ||||
|  | ||||
| waybar(5), dwl(1) | ||||
| @@ -227,6 +227,11 @@ if true | ||||
|     src_files += 'src/modules/river/layout.cpp' | ||||
| endif | ||||
|  | ||||
| if true | ||||
|     add_project_arguments('-DHAVE_DWL', language: 'cpp') | ||||
|     src_files += 'src/modules/dwl/tags.cpp' | ||||
| endif | ||||
|  | ||||
| if true | ||||
|     add_project_arguments('-DHAVE_HYPRLAND', language: 'cpp') | ||||
|     src_files += 'src/modules/hyprland/backend.cpp' | ||||
|   | ||||
							
								
								
									
										167
									
								
								protocol/dwl-bar-ipc-unstable-v1.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								protocol/dwl-bar-ipc-unstable-v1.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- | ||||
| This is largely ripped from somebar's ipc patchset; just with some personal modifications. | ||||
| I would probably just submit raphi's patchset but I don't think that would be polite. | ||||
| --> | ||||
| <protocol name="dwl_bar_ipc_unstable_v1"> | ||||
|   <description summary="inter-proccess-communication about dwl's state"> | ||||
|       This protocol allows clients to get updates from dwl and vice versa. | ||||
|  | ||||
|       Warning! The protocol described in this file is experimental and | ||||
|       backward incompatible changes may be made. Backward compatible | ||||
|       changes may be added together with the corresponding interface | ||||
|       version bump. | ||||
|       Backward incompatible changes are done by bumping the version | ||||
|       number in the protocol and interface names and resetting the | ||||
|       interface version. Once the protocol is to be declared stable, | ||||
|       the 'z' prefix and the version number in the protocol and | ||||
|       interface names are removed and the interface version number is | ||||
|       reset. | ||||
|   </description> | ||||
|  | ||||
|   <interface name="zdwl_manager_v1" version="3"> | ||||
|     <description summary="manage dwl state"> | ||||
|       This interface is exposed as a global in wl_registry. | ||||
|  | ||||
|       Clients can use this interface to get a dwl_output. | ||||
|       After binding the client will revieve dwl_manager.tag and dwl_manager.layout events. | ||||
|       The dwl_manager.tag and dwl_manager.layout events expose tags and layouts to the client. | ||||
|     </description> | ||||
|  | ||||
|     <request name="release" type="destructor"> | ||||
|       <description summary="release dwl_manager"> | ||||
|         Indicates that the client will not the dwl_manager object anymore. | ||||
|         Objects created through this instance are not affected. | ||||
|       </description> | ||||
|     </request> | ||||
|  | ||||
|     <request name="get_output"> | ||||
|       <description summary="get a dwl_output for a wl_output"> | ||||
|         Get a dwl_output for the specified wl_output. | ||||
|       </description> | ||||
|       <arg name="id" type="new_id" interface="zdwl_output_v1"/> | ||||
|       <arg name="output" type="object" interface="wl_output"/> | ||||
|     </request> | ||||
|  | ||||
|     <event name="tag"> | ||||
|       <description summary="Announces a tag"> | ||||
|         This event is sent after binding. | ||||
|         A roundtrip after binding guarantees the client recieved all tags. | ||||
|       </description> | ||||
|       <arg name="name" type="string"/> | ||||
|     </event> | ||||
|  | ||||
|     <event name="layout"> | ||||
|       <description summary="Announces a layout"> | ||||
|         This event is sent after binding. | ||||
|         A roundtrip after binding guarantees the client recieved all layouts. | ||||
|       </description> | ||||
|       <arg name="name" type="string"/> | ||||
|     </event> | ||||
|   </interface> | ||||
|  | ||||
|   <interface name="zdwl_output_v1" version="3"> | ||||
|     <description summary="control dwl output"> | ||||
|       Observe and control a dwl output. | ||||
|  | ||||
|       Events are double-buffered: | ||||
|       Clients should cache events and redraw when a dwl_output.done event is sent. | ||||
|  | ||||
|       Request are not double-buffered: | ||||
|       The compositor will update immediately upon request. | ||||
|     </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_output"> | ||||
|         Indicates to that the client no longer needs this dwl_output. | ||||
|       </description> | ||||
|     </request> | ||||
|  | ||||
|     <event name="toggle_visibility"> | ||||
|       <description summary="Toggle client visibilty"> | ||||
|         Indicates the client should hide or show themselves. | ||||
|         If the client is visible then hide, if hidden then show. | ||||
|       </description> | ||||
|     </event> | ||||
|  | ||||
|     <event name="active"> | ||||
|       <description summary="Update the selected output."> | ||||
|         Indicates if the output is active. Zero is invalid, nonzero is valid. | ||||
|       </description> | ||||
|       <arg name="active" type="uint"/> | ||||
|     </event> | ||||
|  | ||||
|     <event name="tag"> | ||||
|       <description summary="Update the state of a tag."> | ||||
|         Indicates that a tag has been updated. | ||||
|       </description> | ||||
|       <arg name="tag" type="uint" summary="Index of the tag"/> | ||||
|       <arg name="state" type="uint" enum="tag_state" summary="The state of the tag."/> | ||||
|       <arg name="clients" type="uint" summary="The number of clients in the tag."/> | ||||
|       <arg name="focused" type="uint" summary="If there is a focused client. Nonzero being valid, zero being invalid."/> | ||||
|     </event> | ||||
|  | ||||
|     <event name="layout"> | ||||
|       <description summary="Update the layout."> | ||||
|         Indicates a new layout is selected. | ||||
|       </description> | ||||
|       <arg name="layout" type="uint" summary="Index of the layout."/> | ||||
|     </event> | ||||
|  | ||||
|     <event name="title"> | ||||
|       <description summary="Update the title."> | ||||
|         Indicates the title has changed. | ||||
|       </description> | ||||
|       <arg name="title" type="string" summary="The new title name."/> | ||||
|     </event> | ||||
|  | ||||
|     <event name="appid" since="2"> | ||||
|       <description summary="Update the appid."> | ||||
|         Indicates the appid has changed. | ||||
|       </description> | ||||
|       <arg name="appid" type="string" summary="The new appid."/> | ||||
|     </event> | ||||
|  | ||||
|     <event name="layout_symbol" since="3"> | ||||
|       <description summary="Update the current layout symbol"> | ||||
|           Indicates the layout has changed. Since layout symbols are now dynamic. | ||||
|           As opposed to the zdwl_manager_v1.layout event, this should take precendence when displaying. | ||||
|           This also means ignoring the zdwl_output_v1.layout event. | ||||
|       </description> | ||||
|       <arg name="layout" type="string" summary="The new layout"/> | ||||
|     </event> | ||||
|  | ||||
|  | ||||
|     <event name="frame"> | ||||
|       <description summary="The update sequence is done."> | ||||
|         Indicates that a sequence of status updates have finished and the client should redraw. | ||||
|       </description> | ||||
|     </event> | ||||
|  | ||||
|     <request name="set_layout"> | ||||
|       <description summary="Set the layout of this output"/> | ||||
|       <arg name="index" type="uint" summary="index of a layout recieved by dwl_manager.layout"/> | ||||
|     </request> | ||||
|  | ||||
|     <request name="set_tags"> | ||||
|       <description summary="Set the active tags of this output"/> | ||||
|       <arg name="tagmask" type="uint" summary="bitmask of the tags that should be set."/> | ||||
|       <arg name="toggle_tagset" type="uint" summary="toggle the selected tagset, zero for invalid, nonzero for valid."/> | ||||
|     </request> | ||||
|  | ||||
|     <request name="set_client_tags"> | ||||
|       <description summary="Set the tags of the focused client."> | ||||
|         The tags are updated as follows: | ||||
|         new_tags = (current_tags AND and_tags) XOR xor_tags | ||||
|       </description> | ||||
|       <arg name="and_tags" type="uint"/> | ||||
|       <arg name="xor_tags" type="uint"/> | ||||
|     </request> | ||||
|   </interface> | ||||
| </protocol> | ||||
| @@ -30,6 +30,7 @@ client_protocols = [ | ||||
| 	['ext-workspace-unstable-v1.xml'], | ||||
| 	['river-status-unstable-v1.xml'], | ||||
| 	['river-control-unstable-v1.xml'], | ||||
| 	['dwl-bar-ipc-unstable-v1.xml'], | ||||
| ] | ||||
|  | ||||
| client_protos_src = [] | ||||
|   | ||||
| @@ -68,6 +68,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { | ||||
|       return new waybar::modules::river::Layout(id, bar_, config_[name]); | ||||
|     } | ||||
| #endif | ||||
| #ifdef HAVE_DWL | ||||
|     if (ref == "dwl/tags") { | ||||
|       return new waybar::modules::dwl::Tags(id, bar_, config_[name]); | ||||
|     } | ||||
| #endif | ||||
| #ifdef HAVE_HYPRLAND | ||||
|     if (ref == "hyprland/window") { | ||||
|       return new waybar::modules::hyprland::Window(id, bar_, config_[name]); | ||||
|   | ||||
							
								
								
									
										224
									
								
								src/modules/dwl/tags.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								src/modules/dwl/tags.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| #include "modules/dwl/tags.hpp" | ||||
|  | ||||
| #include <gtkmm/button.h> | ||||
| #include <gtkmm/label.h> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <wayland-client.h> | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #include "client.hpp" | ||||
| #include "dwl-bar-ipc-unstable-v1-client-protocol.h" | ||||
|  | ||||
| #define TAG_INACTIVE 0 | ||||
| #define TAG_ACTIVE 1 | ||||
| #define TAG_URGENT 2 | ||||
|  | ||||
| namespace waybar::modules::dwl { | ||||
|  | ||||
| /* dwl stuff */ | ||||
| wl_array tags, layouts; | ||||
|  | ||||
| static uint num_tags = 0; | ||||
|  | ||||
| void toggle_visibility(void* data, zdwl_output_v1* zdwl_output_v1) { | ||||
|   // Intentionally empty | ||||
| } | ||||
|  | ||||
| void active(void* data, zdwl_output_v1* zdwl_output_v1, uint32_t active) { | ||||
|   // Intentionally empty | ||||
| } | ||||
|  | ||||
| static void set_tag(void* data, zdwl_output_v1* zdwl_output_v1, uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) { | ||||
|   static_cast<Tags *>(data)->handle_view_tags(tag, state, clients, focused); | ||||
|  | ||||
|   num_tags = (state & ZDWL_OUTPUT_V1_TAG_STATE_ACTIVE) ? num_tags | (1 << tag) : num_tags & ~(1 << tag); | ||||
| } | ||||
|  | ||||
| void set_layout_symbol(void* data, zdwl_output_v1* zdwl_output_v1, const char *layout) { | ||||
|   // Intentionally empty | ||||
| } | ||||
|  | ||||
| void title(void* data, zdwl_output_v1* zdwl_output_v1, const char* title) { | ||||
|   // Intentionally empty | ||||
| } | ||||
|  | ||||
| void dwl_frame(void* data, zdwl_output_v1* zdwl_output_v1) { | ||||
|   // Intentionally empty | ||||
| } | ||||
|  | ||||
| static void set_layout(void* data, zdwl_output_v1* zdwl_output_v1, uint32_t layout) { | ||||
|   // Intentionally empty | ||||
| } | ||||
|  | ||||
| static void appid(void *data, zdwl_output_v1 *zdwl_output_v1, const char *appid) { | ||||
|   // Intentionally empty | ||||
| }; | ||||
|  | ||||
| static const zdwl_output_v1_listener output_status_listener_impl { | ||||
|     .toggle_visibility = toggle_visibility, | ||||
|     .active = active, | ||||
|     .tag = set_tag, | ||||
|     .layout = set_layout, | ||||
|     .title = title, | ||||
|     .appid = appid, | ||||
|     .layout_symbol = set_layout_symbol, | ||||
|     .frame = dwl_frame, | ||||
| }; | ||||
|  | ||||
| void add_layout(void* data, zdwl_manager_v1* zdwl_manager_v1, const char* name) { | ||||
|   void* temp = wl_array_add(&layouts, sizeof(char**)); | ||||
|   if (!temp) | ||||
|     return; | ||||
|  | ||||
|   char* dup = strdup(name); | ||||
|  | ||||
|   memcpy(temp, &dup, sizeof(char**)); | ||||
| } | ||||
|  | ||||
| void add_tag(void* data, zdwl_manager_v1* zdwl_manager_v1, const char* name) { | ||||
|   void* temp = wl_array_add(&tags, sizeof(char**)); | ||||
|   if (!temp) | ||||
|     return; | ||||
|  | ||||
|   char* dup = strdup(name); /* Gain ownership of name */ | ||||
|  | ||||
|   memcpy(temp, &dup, sizeof(char**)); /* Copy a pointer of it into the array */; | ||||
| } | ||||
|  | ||||
| static const struct zdwl_manager_v1_listener dwl_listener = { | ||||
|   .tag = add_tag, | ||||
|   .layout = add_layout, | ||||
| }; | ||||
|  | ||||
| static void handle_global(void *data, struct wl_registry *registry, uint32_t name, | ||||
|                           const char *interface, uint32_t version) { | ||||
|   if (std::strcmp(interface, zdwl_manager_v1_interface.name) == 0) { | ||||
|     static_cast<Tags *>(data)->status_manager_ = static_cast<struct zdwl_manager_v1 *>( | ||||
|         (zdwl_manager_v1*)wl_registry_bind(registry, name, &zdwl_manager_v1_interface, 3)); | ||||
|         zdwl_manager_v1_add_listener(static_cast<Tags *>(data)->status_manager_, &dwl_listener, NULL); | ||||
|   } | ||||
|   if (std::strcmp(interface, wl_seat_interface.name) == 0) { | ||||
|     version = std::min<uint32_t>(version, 1); | ||||
|     static_cast<Tags *>(data)->seat_ = static_cast<struct wl_seat *>( | ||||
|         wl_registry_bind(registry, name, &wl_seat_interface, version)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { | ||||
|   /* Ignore event */ | ||||
| } | ||||
|  | ||||
| static const wl_registry_listener registry_listener_impl = {.global = handle_global, | ||||
|                                                             .global_remove = handle_global_remove}; | ||||
|  | ||||
| Tags::Tags(const std::string &id, const waybar::Bar &bar, const Json::Value &config) | ||||
|     : waybar::AModule(config, "tags", id, false, false), | ||||
|       status_manager_{nullptr}, | ||||
|       seat_{nullptr}, | ||||
|       bar_(bar), | ||||
|       box_{bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0}, | ||||
|       output_status_{nullptr} { | ||||
|   struct wl_display *display = Client::inst()->wl_display; | ||||
|   struct wl_registry *registry = wl_display_get_registry(display); | ||||
|   wl_registry_add_listener(registry, ®istry_listener_impl, this); | ||||
|   wl_display_roundtrip(display); | ||||
|  | ||||
|   if (!status_manager_) { | ||||
|     spdlog::error("dwl_status_manager_v1 not advertised"); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   if (!seat_) { | ||||
|     spdlog::error("wl_seat not advertised"); | ||||
|   } | ||||
|  | ||||
|   box_.set_name("tags"); | ||||
|   if (!id.empty()) { | ||||
|     box_.get_style_context()->add_class(id); | ||||
|   } | ||||
|   event_box_.add(box_); | ||||
|  | ||||
|   // Default to 9 tags, cap at 32 | ||||
|   const uint32_t num_tags = | ||||
|       config["num-tags"].isUInt() ? std::min<uint32_t>(32, config_["num-tags"].asUInt()) : 9; | ||||
|  | ||||
|   std::vector<std::string> tag_labels(num_tags); | ||||
|   for (uint32_t tag = 0; tag < num_tags; ++tag) { | ||||
|     tag_labels[tag] = std::to_string(tag + 1); | ||||
|   } | ||||
|   const Json::Value custom_labels = config["tag-labels"]; | ||||
|   if (custom_labels.isArray() && !custom_labels.empty()) { | ||||
|     for (uint32_t tag = 0; tag < std::min(num_tags, custom_labels.size()); ++tag) { | ||||
|       tag_labels[tag] = custom_labels[tag].asString(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   uint32_t i = 1; | ||||
|   for (const auto &tag_label : tag_labels) { | ||||
|     Gtk::Button &button = buttons_.emplace_back(tag_label); | ||||
|     button.set_relief(Gtk::RELIEF_NONE); | ||||
|     box_.pack_start(button, false, false, 0); | ||||
|     if (!config_["disable-click"].asBool()) { | ||||
|       button.signal_clicked().connect( | ||||
|           sigc::bind(sigc::mem_fun(*this, &Tags::handle_primary_clicked), i)); | ||||
|       button.signal_button_press_event().connect( | ||||
|           sigc::bind(sigc::mem_fun(*this, &Tags::handle_button_press), i)); | ||||
|     } | ||||
|     button.show(); | ||||
|     i <<= 1; | ||||
|   } | ||||
|  | ||||
|   struct wl_output *output = gdk_wayland_monitor_get_wl_output(bar_.output->monitor->gobj()); | ||||
|   output_status_ = zdwl_manager_v1_get_output(status_manager_, output); | ||||
|   zdwl_output_v1_add_listener(output_status_, &output_status_listener_impl, this); | ||||
|  | ||||
|   zdwl_manager_v1_destroy(status_manager_); | ||||
| } | ||||
|  | ||||
| Tags::~Tags() { | ||||
|   if (output_status_) { | ||||
|     zdwl_manager_v1_destroy(status_manager_); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void Tags::handle_primary_clicked(uint32_t tag) { | ||||
|   if (!output_status_) return; | ||||
|  | ||||
|   zdwl_output_v1_set_tags(output_status_, tag, 1); | ||||
| } | ||||
|  | ||||
| bool Tags::handle_button_press(GdkEventButton *event_button, uint32_t tag) { | ||||
|   if (event_button->type == GDK_BUTTON_PRESS && event_button->button == 3) { | ||||
|  | ||||
|     if (!output_status_) return true; | ||||
|     zdwl_output_v1_set_tags(output_status_, num_tags ^ tag, 0); | ||||
|   } | ||||
|   return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| void Tags::handle_view_tags(uint32_t tag, uint32_t state, uint32_t clients, uint32_t focused) { | ||||
|   // First clear all occupied state | ||||
|   auto &button = buttons_[tag]; | ||||
|   if (clients) { | ||||
|     button.get_style_context()->add_class("occupied"); | ||||
|   } else { | ||||
|     button.get_style_context()->remove_class("occupied"); | ||||
|   } | ||||
|  | ||||
|   if (state & TAG_ACTIVE) { | ||||
|       button.get_style_context()->add_class("focused"); | ||||
|   } else { | ||||
|       button.get_style_context()->remove_class("focused"); | ||||
|   } | ||||
|  | ||||
|   if (state & TAG_URGENT) { | ||||
|       button.get_style_context()->add_class("urgent"); | ||||
|   } else { | ||||
|       button.get_style_context()->remove_class("urgent"); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| } /* namespace waybar::modules::dwl */ | ||||
		Reference in New Issue
	
	Block a user
	 David Delarosa
					David Delarosa