mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-31 07:52:42 +01:00 
			
		
		
		
	Merge pull request #441 from alebastr/gtk-layer-shell
Use gtk-layer-shell library for correct positioning of popups
This commit is contained in:
		| @@ -1,5 +1,6 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <gdkmm/monitor.h> | ||||
| #include <glibmm/refptr.h> | ||||
| #include <gtkmm/box.h> | ||||
| #include <gtkmm/cssprovider.h> | ||||
| @@ -15,10 +16,11 @@ namespace waybar { | ||||
|  | ||||
| class Factory; | ||||
| struct waybar_output { | ||||
|   struct wl_output *     output = nullptr; | ||||
|   std::string            name; | ||||
|   uint32_t               wl_name; | ||||
|   struct zxdg_output_v1 *xdg_output = nullptr; | ||||
|   Glib::RefPtr<Gdk::Monitor> monitor; | ||||
|   std::string                name; | ||||
|  | ||||
|   std::unique_ptr<struct zxdg_output_v1, decltype(&zxdg_output_v1_destroy)> xdg_output = { | ||||
|       nullptr, &zxdg_output_v1_destroy}; | ||||
| }; | ||||
|  | ||||
| class Bar { | ||||
| @@ -30,13 +32,12 @@ class Bar { | ||||
|   auto toggle() -> void; | ||||
|   void handleSignal(int); | ||||
|  | ||||
|   struct waybar_output *        output; | ||||
|   Json::Value                   config; | ||||
|   Gtk::Window                   window; | ||||
|   struct wl_surface *           surface; | ||||
|   struct zwlr_layer_surface_v1 *layer_surface; | ||||
|   bool                          visible = true; | ||||
|   bool                          vertical = false; | ||||
|   struct waybar_output *output; | ||||
|   Json::Value           config; | ||||
|   Gtk::Window           window; | ||||
|   struct wl_surface *   surface; | ||||
|   bool                  visible = true; | ||||
|   bool                  vertical = false; | ||||
|  | ||||
|  private: | ||||
|   static constexpr const char *MIN_HEIGHT_MSG = | ||||
| @@ -51,7 +52,9 @@ class Bar { | ||||
|                                           uint32_t, uint32_t); | ||||
|   static void layerSurfaceHandleClosed(void *, struct zwlr_layer_surface_v1 *); | ||||
|  | ||||
|   void destroyOutput(); | ||||
| #ifdef HAVE_GTK_LAYER_SHELL | ||||
|   void initGtkLayerShell(); | ||||
| #endif | ||||
|   void onConfigure(GdkEventConfigure *ev); | ||||
|   void onRealize(); | ||||
|   void onMap(GdkEventAny *ev); | ||||
| @@ -68,6 +71,9 @@ class Bar { | ||||
|     int bottom = 0; | ||||
|     int left = 0; | ||||
|   } margins_; | ||||
|   struct zwlr_layer_surface_v1 *layer_surface_; | ||||
|   // use gtk-layer-shell instead of handling layer surfaces directly | ||||
|   bool                                          use_gls_ = false; | ||||
|   uint32_t                                      width_ = 0; | ||||
|   uint32_t                                      height_ = 1; | ||||
|   uint8_t                                       anchor_; | ||||
|   | ||||
| @@ -34,17 +34,15 @@ class Client { | ||||
|   bool isValidOutput(const Json::Value &config, std::unique_ptr<struct waybar_output> &output); | ||||
|   auto setupConfig(const std::string &config_file) -> void; | ||||
|   auto setupCss(const std::string &css_file) -> void; | ||||
|   std::unique_ptr<struct waybar_output> &getOutput(uint32_t wl_name); | ||||
|   std::unique_ptr<struct waybar_output> &getOutput(void *); | ||||
|   std::vector<Json::Value> getOutputConfigs(std::unique_ptr<struct waybar_output> &output); | ||||
|  | ||||
|   static void handleGlobal(void *data, struct wl_registry *registry, uint32_t name, | ||||
|                            const char *interface, uint32_t version); | ||||
|   static void handleGlobalRemove(void *data, struct wl_registry *registry, uint32_t name); | ||||
|   static void handleLogicalPosition(void *, struct zxdg_output_v1 *, int32_t, int32_t); | ||||
|   static void handleLogicalSize(void *, struct zxdg_output_v1 *, int32_t, int32_t); | ||||
|   static void handleDone(void *, struct zxdg_output_v1 *); | ||||
|   static void handleName(void *, struct zxdg_output_v1 *, const char *); | ||||
|   static void handleDescription(void *, struct zxdg_output_v1 *, const char *); | ||||
|   static void handleOutputName(void *, struct zxdg_output_v1 *, const char *); | ||||
|   void        handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor); | ||||
|   void        handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor); | ||||
|  | ||||
|   Json::Value                                        config_; | ||||
|   Glib::RefPtr<Gtk::StyleContext>                    style_context_; | ||||
|   | ||||
							
								
								
									
										12
									
								
								meson.build
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								meson.build
									
									
									
									
									
								
							| @@ -52,7 +52,7 @@ spdlog = dependency('spdlog', version : ['>=1.3.1'], fallback : ['spdlog', 'spdl | ||||
| wayland_client = dependency('wayland-client') | ||||
| wayland_cursor = dependency('wayland-cursor') | ||||
| wayland_protos = dependency('wayland-protocols') | ||||
| gtkmm = dependency('gtkmm-3.0') | ||||
| gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0']) | ||||
| dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk')) | ||||
| giounix = dependency('gio-unix-2.0', required: get_option('dbusmenu-gtk')) | ||||
| jsoncpp = dependency('jsoncpp') | ||||
| @@ -62,6 +62,9 @@ libnlgen = dependency('libnl-genl-3.0', required: get_option('libnl')) | ||||
| libpulse = dependency('libpulse', required: get_option('pulseaudio')) | ||||
| libudev = dependency('libudev', required: get_option('libudev')) | ||||
| libmpdclient = dependency('libmpdclient', required: get_option('mpd')) | ||||
| gtk_layer_shell = dependency('gtk-layer-shell-0', | ||||
|         required: get_option('gtk-layer-shell'), | ||||
|         fallback : ['gtk-layer-shell', 'gtk_layer_shell_dep']) | ||||
| systemd = dependency('systemd', required: get_option('systemd')) | ||||
|  | ||||
| prefix = get_option('prefix') | ||||
| @@ -136,6 +139,10 @@ if libmpdclient.found() | ||||
|     src_files += 'src/modules/mpd.cpp' | ||||
| endif | ||||
|  | ||||
| if gtk_layer_shell.found() | ||||
|     add_project_arguments('-DHAVE_GTK_LAYER_SHELL', language: 'cpp') | ||||
| endif | ||||
|  | ||||
| subdir('protocol') | ||||
|  | ||||
| executable( | ||||
| @@ -158,7 +165,8 @@ executable( | ||||
|         libnlgen, | ||||
|         libpulse, | ||||
|         libudev, | ||||
|         libmpdclient | ||||
|         libmpdclient, | ||||
|         gtk_layer_shell | ||||
|     ], | ||||
|     include_directories: [include_directories('include')], | ||||
|     install: true, | ||||
|   | ||||
| @@ -7,3 +7,4 @@ option('dbusmenu-gtk', type: 'feature', value: 'auto', description: 'Enable supp | ||||
| option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages') | ||||
| option('mpd', type: 'feature', value: 'auto', description: 'Enable support for the Music Player Daemon') | ||||
| option('out', type: 'string', value : '/', description: 'output prefix directory') | ||||
| option('gtk-layer-shell', type: 'feature', value: 'disabled', description: 'Use gtk-layer-shell library for popups support') | ||||
|   | ||||
							
								
								
									
										92
									
								
								src/bar.cpp
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								src/bar.cpp
									
									
									
									
									
								
							| @@ -1,3 +1,7 @@ | ||||
| #ifdef HAVE_GTK_LAYER_SHELL | ||||
| #include <gtk-layer-shell.h> | ||||
| #endif | ||||
|  | ||||
| #include "bar.hpp" | ||||
| #include "client.hpp" | ||||
| #include "factory.hpp" | ||||
| @@ -8,7 +12,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) | ||||
|       config(w_config), | ||||
|       window{Gtk::WindowType::WINDOW_TOPLEVEL}, | ||||
|       surface(nullptr), | ||||
|       layer_surface(nullptr), | ||||
|       layer_surface_(nullptr), | ||||
|       anchor_(ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP), | ||||
|       left_(Gtk::ORIENTATION_HORIZONTAL, 0), | ||||
|       center_(Gtk::ORIENTATION_HORIZONTAL, 0), | ||||
| @@ -28,11 +32,6 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) | ||||
|   height_ = config["height"].isUInt() ? config["height"].asUInt() : height_; | ||||
|   width_ = config["width"].isUInt() ? config["width"].asUInt() : width_; | ||||
|  | ||||
|   window.signal_realize().connect_notify(sigc::mem_fun(*this, &Bar::onRealize)); | ||||
|   window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap)); | ||||
|   window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure)); | ||||
|   window.set_size_request(width_, height_); | ||||
|  | ||||
|   if (config["position"] == "bottom") { | ||||
|     anchor_ = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; | ||||
|   } else if (config["position"] == "left") { | ||||
| @@ -98,6 +97,17 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) | ||||
|     margins_ = {.top = gaps, .right = gaps, .bottom = gaps, .left = gaps}; | ||||
|   } | ||||
|  | ||||
| #ifdef HAVE_GTK_LAYER_SHELL | ||||
|   use_gls_ = config["gtk-layer-shell"].isBool() ? config["gtk-layer-shell"].asBool() : true; | ||||
|   if (use_gls_) { | ||||
|     initGtkLayerShell(); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|   window.signal_realize().connect_notify(sigc::mem_fun(*this, &Bar::onRealize)); | ||||
|   window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap)); | ||||
|   window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure)); | ||||
|   window.set_size_request(width_, height_); | ||||
|   setupWidgets(); | ||||
|  | ||||
|   if (window.get_realized()) { | ||||
| @@ -131,11 +141,43 @@ void waybar::Bar::onConfigure(GdkEventConfigure* ev) { | ||||
|       tmp_width = ev->width; | ||||
|     } | ||||
|   } | ||||
|   if (tmp_width != width_ || tmp_height != height_) { | ||||
|   if (use_gls_) { | ||||
|     width_ = tmp_width; | ||||
|     height_ = tmp_height; | ||||
|     spdlog::debug("Set surface size {}x{} for output {}", width_, height_, output->name); | ||||
|     setExclusiveZone(tmp_width, tmp_height); | ||||
|   } else if (tmp_width != width_ || tmp_height != height_) { | ||||
|     setSurfaceSize(tmp_width, tmp_height); | ||||
|   } | ||||
| } | ||||
|  | ||||
| #ifdef HAVE_GTK_LAYER_SHELL | ||||
| void waybar::Bar::initGtkLayerShell() { | ||||
|   auto gtk_window = window.gobj(); | ||||
|   // this has to be executed before GtkWindow.realize | ||||
|   gtk_layer_init_for_window(gtk_window); | ||||
|   gtk_layer_set_keyboard_interactivity(gtk_window, FALSE); | ||||
|   auto layer = config["layer"] == "top" ? GTK_LAYER_SHELL_LAYER_TOP : GTK_LAYER_SHELL_LAYER_BOTTOM; | ||||
|   gtk_layer_set_layer(gtk_window, layer); | ||||
|   gtk_layer_set_monitor(gtk_window, output->monitor->gobj()); | ||||
|   gtk_layer_set_namespace(gtk_window, "waybar"); | ||||
|  | ||||
|   gtk_layer_set_anchor( | ||||
|       gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, anchor_ & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT); | ||||
|   gtk_layer_set_anchor( | ||||
|       gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, anchor_ & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); | ||||
|   gtk_layer_set_anchor( | ||||
|       gtk_window, GTK_LAYER_SHELL_EDGE_TOP, anchor_ & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP); | ||||
|   gtk_layer_set_anchor( | ||||
|       gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, anchor_ & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM); | ||||
|  | ||||
|   gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_LEFT, margins_.left); | ||||
|   gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_RIGHT, margins_.right); | ||||
|   gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_TOP, margins_.top); | ||||
|   gtk_layer_set_margin(gtk_window, GTK_LAYER_SHELL_EDGE_BOTTOM, margins_.bottom); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void waybar::Bar::onRealize() { | ||||
|   auto gdk_window = window.get_window()->gobj(); | ||||
|   gdk_wayland_window_set_use_custom_surface(gdk_window); | ||||
| @@ -145,16 +187,22 @@ void waybar::Bar::onMap(GdkEventAny* ev) { | ||||
|   auto gdk_window = window.get_window()->gobj(); | ||||
|   surface = gdk_wayland_window_get_wl_surface(gdk_window); | ||||
|  | ||||
|   if (use_gls_) { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   auto client = waybar::Client::inst(); | ||||
|   // owned by output->monitor; no need to destroy | ||||
|   auto wl_output = gdk_wayland_monitor_get_wl_output(output->monitor->gobj()); | ||||
|   auto layer = | ||||
|       config["layer"] == "top" ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; | ||||
|   layer_surface = zwlr_layer_shell_v1_get_layer_surface( | ||||
|       client->layer_shell, surface, output->output, layer, "waybar"); | ||||
|   layer_surface_ = zwlr_layer_shell_v1_get_layer_surface( | ||||
|       client->layer_shell, surface, wl_output, layer, "waybar"); | ||||
|  | ||||
|   zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, false); | ||||
|   zwlr_layer_surface_v1_set_anchor(layer_surface, anchor_); | ||||
|   zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface_, false); | ||||
|   zwlr_layer_surface_v1_set_anchor(layer_surface_, anchor_); | ||||
|   zwlr_layer_surface_v1_set_margin( | ||||
|       layer_surface, margins_.top, margins_.right, margins_.bottom, margins_.left); | ||||
|       layer_surface_, margins_.top, margins_.right, margins_.bottom, margins_.left); | ||||
|   setSurfaceSize(width_, height_); | ||||
|   setExclusiveZone(width_, height_); | ||||
|  | ||||
| @@ -162,7 +210,7 @@ void waybar::Bar::onMap(GdkEventAny* ev) { | ||||
|       .configure = layerSurfaceHandleConfigure, | ||||
|       .closed = layerSurfaceHandleClosed, | ||||
|   }; | ||||
|   zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, this); | ||||
|   zwlr_layer_surface_v1_add_listener(layer_surface_, &layer_surface_listener, this); | ||||
|  | ||||
|   wl_surface_commit(surface); | ||||
|   wl_display_roundtrip(client->wl_display); | ||||
| @@ -182,7 +230,15 @@ void waybar::Bar::setExclusiveZone(uint32_t width, uint32_t height) { | ||||
|     } | ||||
|   } | ||||
|   spdlog::debug("Set exclusive zone {} for output {}", zone, output->name); | ||||
|   zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, zone); | ||||
|  | ||||
| #ifdef HAVE_GTK_LAYER_SHELL | ||||
|   if (use_gls_) { | ||||
|     gtk_layer_set_exclusive_zone(window.gobj(), zone); | ||||
|   } else | ||||
| #endif | ||||
|   { | ||||
|     zwlr_layer_surface_v1_set_exclusive_zone(layer_surface_, zone); | ||||
|   } | ||||
| } | ||||
|  | ||||
| void waybar::Bar::setSurfaceSize(uint32_t width, uint32_t height) { | ||||
| @@ -198,7 +254,7 @@ void waybar::Bar::setSurfaceSize(uint32_t width, uint32_t height) { | ||||
|     width += margins_.right + margins_.left; | ||||
|   } | ||||
|   spdlog::debug("Set surface size {}x{} for output {}", width, height, output->name); | ||||
|   zwlr_layer_surface_v1_set_size(layer_surface, width, height); | ||||
|   zwlr_layer_surface_v1_set_size(layer_surface_, width, height); | ||||
| } | ||||
|  | ||||
| // Converting string to button code rn as to avoid doing it later | ||||
| @@ -282,9 +338,9 @@ void waybar::Bar::layerSurfaceHandleConfigure(void* data, struct zwlr_layer_surf | ||||
|  | ||||
| void waybar::Bar::layerSurfaceHandleClosed(void* data, struct zwlr_layer_surface_v1* /*surface*/) { | ||||
|   auto o = static_cast<waybar::Bar*>(data); | ||||
|   if (o->layer_surface) { | ||||
|     zwlr_layer_surface_v1_destroy(o->layer_surface); | ||||
|     o->layer_surface = nullptr; | ||||
|   if (o->layer_surface_) { | ||||
|     zwlr_layer_surface_v1_destroy(o->layer_surface_); | ||||
|     o->layer_surface_ = nullptr; | ||||
|   } | ||||
|   o->modules_left_.clear(); | ||||
|   o->modules_center_.clear(); | ||||
|   | ||||
							
								
								
									
										120
									
								
								src/client.cpp
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								src/client.cpp
									
									
									
									
									
								
							| @@ -1,4 +1,5 @@ | ||||
| #include "client.hpp" | ||||
| #include <fmt/ostream.h> | ||||
| #include <spdlog/spdlog.h> | ||||
| #include <fstream> | ||||
| #include <iostream> | ||||
| @@ -33,11 +34,6 @@ void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint | ||||
|   if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { | ||||
|     client->layer_shell = static_cast<struct zwlr_layer_shell_v1 *>( | ||||
|         wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, version)); | ||||
|   } else if (strcmp(interface, wl_output_interface.name) == 0) { | ||||
|     auto wl_output = static_cast<struct wl_output *>( | ||||
|         wl_registry_bind(registry, name, &wl_output_interface, version)); | ||||
|     client->outputs_.emplace_back(new struct waybar_output({wl_output, "", name, nullptr})); | ||||
|     client->handleOutput(client->outputs_.back()); | ||||
|   } else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 && | ||||
|              version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { | ||||
|     client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1 *>(wl_registry_bind( | ||||
| @@ -50,58 +46,21 @@ void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint | ||||
|  | ||||
| void waybar::Client::handleGlobalRemove(void *   data, struct wl_registry * /*registry*/, | ||||
|                                         uint32_t name) { | ||||
|   auto client = static_cast<Client *>(data); | ||||
|   for (auto it = client->bars.begin(); it != client->bars.end();) { | ||||
|     if ((*it)->output->wl_name == name) { | ||||
|       auto output_name = (*it)->output->name; | ||||
|       (*it)->window.close(); | ||||
|       it = client->bars.erase(it); | ||||
|       spdlog::info("Bar removed from output: {}", output_name); | ||||
|     } else { | ||||
|       ++it; | ||||
|     } | ||||
|   } | ||||
|   auto it = std::find_if(client->outputs_.begin(), | ||||
|                          client->outputs_.end(), | ||||
|                          [&name](const auto &output) { return output->wl_name == name; }); | ||||
|   if (it != client->outputs_.end()) { | ||||
|     if ((*it)->xdg_output != nullptr) { | ||||
|       zxdg_output_v1_destroy((*it)->xdg_output); | ||||
|       (*it)->xdg_output = nullptr; | ||||
|     } | ||||
|     if ((*it)->output != nullptr) { | ||||
|       wl_output_destroy((*it)->output); | ||||
|       (*it)->output = nullptr; | ||||
|     } | ||||
|     client->outputs_.erase(it); | ||||
|   } | ||||
|   // Nothing here | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleOutput(std::unique_ptr<struct waybar_output> &output) { | ||||
|   static const struct zxdg_output_v1_listener xdgOutputListener = { | ||||
|       .logical_position = handleLogicalPosition, | ||||
|       .logical_size = handleLogicalSize, | ||||
|       .done = handleDone, | ||||
|       .name = handleName, | ||||
|       .description = handleDescription, | ||||
|       .logical_position = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {}, | ||||
|       .logical_size = [](void *, struct zxdg_output_v1 *, int32_t, int32_t) {}, | ||||
|       .done = [](void *, struct zxdg_output_v1 *) {}, | ||||
|       .name = &handleOutputName, | ||||
|       .description = [](void *, struct zxdg_output_v1 *, const char *) {}, | ||||
|   }; | ||||
|   output->xdg_output = zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, output->output); | ||||
|   zxdg_output_v1_add_listener(output->xdg_output, &xdgOutputListener, &output->wl_name); | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleLogicalPosition(void * /*data*/, | ||||
|                                            struct zxdg_output_v1 * /*zxdg_output_v1*/, | ||||
|                                            int32_t /*x*/, int32_t /*y*/) { | ||||
|   // Nothing here | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleLogicalSize(void * /*data*/, struct zxdg_output_v1 * /*zxdg_output_v1*/, | ||||
|                                        int32_t /*width*/, int32_t /*height*/) { | ||||
|   // Nothing here | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleDone(void * /*data*/, struct zxdg_output_v1 * /*zxdg_output_v1*/) { | ||||
|   // Nothing here | ||||
|   // owned by output->monitor; no need to destroy | ||||
|   auto wl_output = gdk_wayland_monitor_get_wl_output(output->monitor->gobj()); | ||||
|   output->xdg_output.reset(zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, wl_output)); | ||||
|   zxdg_output_v1_add_listener(output->xdg_output.get(), &xdgOutputListener, output.get()); | ||||
| } | ||||
|  | ||||
| bool waybar::Client::isValidOutput(const Json::Value &                    config, | ||||
| @@ -123,9 +82,9 @@ bool waybar::Client::isValidOutput(const Json::Value &                    config | ||||
|   return found; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<struct waybar::waybar_output> &waybar::Client::getOutput(uint32_t wl_name) { | ||||
|   auto it = std::find_if(outputs_.begin(), outputs_.end(), [&wl_name](const auto &output) { | ||||
|     return output->wl_name == wl_name; | ||||
| std::unique_ptr<struct waybar::waybar_output> &waybar::Client::getOutput(void *addr) { | ||||
|   auto it = std::find_if(outputs_.begin(), outputs_.end(), [&addr](const auto &output) { | ||||
|     return output.get() == addr; | ||||
|   }); | ||||
|   if (it == outputs_.end()) { | ||||
|     throw std::runtime_error("Unable to find valid output"); | ||||
| @@ -148,23 +107,19 @@ std::vector<Json::Value> waybar::Client::getOutputConfigs( | ||||
|   return configs; | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleName(void *      data, struct zxdg_output_v1 * /*xdg_output*/, | ||||
|                                 const char *name) { | ||||
|   auto wl_name = *static_cast<uint32_t *>(data); | ||||
| void waybar::Client::handleOutputName(void *      data, struct zxdg_output_v1 * /*xdg_output*/, | ||||
|                                       const char *name) { | ||||
|   auto client = waybar::Client::inst(); | ||||
|   try { | ||||
|     auto &output = client->getOutput(wl_name); | ||||
|     auto &output = client->getOutput(data); | ||||
|     output->name = name; | ||||
|     spdlog::debug("Output detected: {} ({} {})", | ||||
|                   name, | ||||
|                   output->monitor->get_manufacturer(), | ||||
|                   output->monitor->get_model()); | ||||
|     auto configs = client->getOutputConfigs(output); | ||||
|     if (configs.empty()) { | ||||
|       if (output->output != nullptr) { | ||||
|         wl_output_destroy(output->output); | ||||
|         output->output = nullptr; | ||||
|       } | ||||
|       if (output->xdg_output != nullptr) { | ||||
|         zxdg_output_v1_destroy(output->xdg_output); | ||||
|         output->xdg_output = nullptr; | ||||
|       } | ||||
|       output->xdg_output.reset(); | ||||
|     } else { | ||||
|       wl_display_roundtrip(client->wl_display); | ||||
|       for (const auto &config : configs) { | ||||
| @@ -179,9 +134,26 @@ void waybar::Client::handleName(void *      data, struct zxdg_output_v1 * /*xdg_ | ||||
|   } | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleDescription(void * /*data*/, struct zxdg_output_v1 * /*zxdg_output_v1*/, | ||||
|                                        const char * /*description*/) { | ||||
|   // Nothing here | ||||
| void waybar::Client::handleMonitorAdded(Glib::RefPtr<Gdk::Monitor> monitor) { | ||||
|   auto &output = outputs_.emplace_back(new struct waybar_output({monitor})); | ||||
|   handleOutput(output); | ||||
| } | ||||
|  | ||||
| void waybar::Client::handleMonitorRemoved(Glib::RefPtr<Gdk::Monitor> monitor) { | ||||
|   spdlog::debug("Output removed: {} {}", monitor->get_manufacturer(), monitor->get_model()); | ||||
|   for (auto it = bars.begin(); it != bars.end();) { | ||||
|     if ((*it)->output->monitor == monitor) { | ||||
|       auto output_name = (*it)->output->name; | ||||
|       (*it)->window.close(); | ||||
|       it = bars.erase(it); | ||||
|       spdlog::info("Bar removed from output: {}", output_name); | ||||
|     } else { | ||||
|       ++it; | ||||
|     } | ||||
|   } | ||||
|   std::remove_if(outputs_.begin(), outputs_.end(), [&monitor](const auto &output) { | ||||
|     return output->monitor == monitor; | ||||
|   }); | ||||
| } | ||||
|  | ||||
| std::tuple<const std::string, const std::string> waybar::Client::getConfigs( | ||||
| @@ -240,6 +212,14 @@ void waybar::Client::bindInterfaces() { | ||||
|   if (layer_shell == nullptr || xdg_output_manager == nullptr) { | ||||
|     throw std::runtime_error("Failed to acquire required resources."); | ||||
|   } | ||||
|   // add existing outputs and subscribe to updates | ||||
|   for (auto i = 0; i < gdk_display->get_n_monitors(); ++i) { | ||||
|     auto monitor = gdk_display->get_monitor(i); | ||||
|     handleMonitorAdded(monitor); | ||||
|   } | ||||
|   gdk_display->signal_monitor_added().connect(sigc::mem_fun(*this, &Client::handleMonitorAdded)); | ||||
|   gdk_display->signal_monitor_removed().connect( | ||||
|       sigc::mem_fun(*this, &Client::handleMonitorRemoved)); | ||||
| } | ||||
|  | ||||
| int waybar::Client::main(int argc, char *argv[]) { | ||||
|   | ||||
							
								
								
									
										5
									
								
								subprojects/gtk-layer-shell.wrap
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								subprojects/gtk-layer-shell.wrap
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| [wrap-file] | ||||
| directory = gtk-layer-shell-0.1.0 | ||||
| source_filename = gtk-layer-shell-0.1.0.tar.gz | ||||
| source_hash = f7569e27ae30b1a94c3ad6c955cf56240d6bc272b760d9d266ce2ccdb94a5cf0 | ||||
| source_url = https://github.com/wmww/gtk-layer-shell/archive/v0.1.0/gtk-layer-shell-0.1.0.tar.gz | ||||
		Reference in New Issue
	
	Block a user
	 Alex
					Alex