polybar-dwm/include/modules/xworkspaces.hpp
Tim Schumacher 281fdf6382
The xworkspaces module should wait for EWMH to become available (#2429)
* The xworkspaces module should wait for EWMH to become available

Before this change if EWMH wasn't available the xworkspaces module was
permanently disabled. When polybar was started alongside the window
manager e.g. from .xinitrc this caused a race condition between polybar
and the window manager and the xworkspaces module may or may not be
displayed. After this change polybar will wait for EWMH to become
available. This change closes #1915, see that issue for more details.

Curiously this only required the removal of the error condition which
used the be raised when EWMH wasn't available. The xworkspaces module
will show up on the bar as soon as the first EWMH event is processed by
the existing event handling code. I can't argue much about the
correctness of this patch but it seems to work flawlessly in my testing
with xmonad. I didn't test any other window managers. Note that removing
the error condition below which checks that _NET_DESKTOP_VIEWPORT is
available might make this work with pin-workspaces=true. I couldn't test
the effects of that change because I only tested with xmonad and xmonad
doesn't support _NET_DESKTOP_VIEWPORT, so I didn't make that change.

* xworkspaces: Remove check fo _NET_DESKTOP_VIEWPORT

Implementations that don't support it will just return an empty list for
get_desktop_viewports and pin-workspaces won't do anything.

* Update changelog

Fixes #1915

Co-authored-by: Tim Schumacher <tim@timakro.de>
Co-authored-by: patrick96 <p.ziegler96@gmail.com>
2021-10-11 14:40:14 +02:00

112 lines
2.7 KiB
C++

#pragma once
#include "modules/meta/event_handler.hpp"
#include "modules/meta/static_module.hpp"
#include "x11/ewmh.hpp"
POLYBAR_NS
class connection;
namespace modules {
enum class desktop_state {
NONE,
ACTIVE,
URGENT,
EMPTY,
OCCUPIED,
};
enum class viewport_state {
NONE,
FOCUSED,
UNFOCUSED,
};
struct desktop {
explicit desktop(unsigned int index, desktop_state state, label_t&& label)
: index(index), state(state), label(label) {}
unsigned int index;
desktop_state state;
label_t label;
};
struct viewport {
position pos;
string name;
vector<unique_ptr<desktop>> desktops;
viewport_state state;
label_t label;
};
/**
* Module used to display EWMH desktops
*/
class xworkspaces_module : public static_module<xworkspaces_module>, public event_handler<evt::property_notify> {
public:
explicit xworkspaces_module(const bar_settings& bar, string name_);
void update();
string get_output();
bool build(builder* builder, const string& tag) const;
static constexpr auto TYPE = "internal/xworkspaces";
static constexpr auto EVENT_FOCUS = "focus";
static constexpr auto EVENT_NEXT = "next";
static constexpr auto EVENT_PREV = "prev";
protected:
void handle(const evt::property_notify& evt) override;
void rebuild_clientlist();
void rebuild_urgent_hints();
void rebuild_desktops();
void rebuild_desktop_states();
void update_current_desktop();
void action_focus(const string& data);
void action_next();
void action_prev();
void focus_direction(bool next);
void focus_desktop(unsigned new_desktop);
private:
static vector<string> get_desktop_names();
static constexpr const char* DEFAULT_ICON{"icon-default"};
static constexpr const char* DEFAULT_LABEL_STATE{"%icon% %name%"};
static constexpr const char* DEFAULT_LABEL_MONITOR{"%name%"};
static constexpr const char* TAG_LABEL_MONITOR{"<label-monitor>"};
static constexpr const char* TAG_LABEL_STATE{"<label-state>"};
connection& m_connection;
ewmh_connection_t m_ewmh;
vector<monitor_t> m_monitors;
vector<string> m_desktop_names;
vector<bool> m_urgent_desktops;
unsigned int m_current_desktop;
/**
* Maps an xcb window to its desktop number
*/
map<xcb_window_t, unsigned int> m_clients;
map<unsigned int, unsigned int> m_windows;
vector<unique_ptr<viewport>> m_viewports;
map<desktop_state, label_t> m_labels;
label_t m_monitorlabel;
iconset_t m_icons;
bool m_pinworkspaces{false};
bool m_click{true};
bool m_scroll{true};
bool m_revscroll{false};
size_t m_index{0};
};
} // namespace modules
POLYBAR_NS_END