Merge remote-tracking branch 'origin/hotfix/3.5.7'

This commit is contained in:
patrick96 2021-09-21 18:22:57 +02:00
commit 2512123a6c
No known key found for this signature in database
GPG Key ID: 521E5E03AEBCA1A7
9 changed files with 129 additions and 64 deletions

View File

@ -135,6 +135,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `internal/xworkspaces`: Broken scroll-wrapping and order of workspaces when scrolling - `internal/xworkspaces`: Broken scroll-wrapping and order of workspaces when scrolling
([`#2491`](https://github.com/polybar/polybar/issues/2491)) ([`#2491`](https://github.com/polybar/polybar/issues/2491))
## [3.5.7] - 2021-09-21
### Fixed
- The tray mistakenly removed tray icons that did not support XEMBED
([`#2479`](https://github.com/polybar/polybar/issues/2479),
[`#2442`](https://github.com/polybar/polybar/issues/2442))
- `custom/ipc`: Only the first appearance of the `%pid%` token was replaced
([`#2500`](https://github.com/polybar/polybar/issues/2500))
## [3.5.6] - 2021-05-24 ## [3.5.6] - 2021-05-24
### Build ### Build
@ -157,7 +164,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- Empty color values are no longer treated as invalid and no longer produce an error. - Empty color values are no longer treated as invalid and no longer produce an error.
[Unreleased]: https://github.com/polybar/polybar/compare/3.5.6...HEAD [Unreleased]: https://github.com/polybar/polybar/compare/3.5.7...HEAD
[3.5.7]: https://github.com/polybar/polybar/releases/tag/3.5.7
[3.5.6]: https://github.com/polybar/polybar/releases/tag/3.5.6 [3.5.6]: https://github.com/polybar/polybar/releases/tag/3.5.6
[3.5.5]: https://github.com/polybar/polybar/releases/tag/3.5.5 [3.5.5]: https://github.com/polybar/polybar/releases/tag/3.5.5
[3.5.4]: https://github.com/polybar/polybar/releases/tag/3.5.4 [3.5.4]: https://github.com/polybar/polybar/releases/tag/3.5.4

View File

@ -4,12 +4,12 @@
#include "common.hpp" #include "common.hpp"
#include "utils/concurrency.hpp" #include "utils/concurrency.hpp"
#include "x11/xembed.hpp"
POLYBAR_NS POLYBAR_NS
// fwd declarations // fwd declarations
class connection; class connection;
struct xembed_data;
class tray_client { class tray_client {
public: public:
@ -28,7 +28,10 @@ class tray_client {
void mapped(bool state); void mapped(bool state);
xcb_window_t window() const; xcb_window_t window() const;
xembed_data* xembed() const;
void query_xembed();
bool is_xembed_supported() const;
const xembed::info& get_xembed() const;
void ensure_state() const; void ensure_state() const;
void reconfigure(int x, int y) const; void reconfigure(int x, int y) const;
@ -38,7 +41,18 @@ class tray_client {
connection& m_connection; connection& m_connection;
xcb_window_t m_window{0}; xcb_window_t m_window{0};
shared_ptr<xembed_data> m_xembed; /**
* Whether the client window supports XEMBED.
*
* A tray client can still work when it doesn't support XEMBED.
*/
bool m_xembed_supported{false};
/**
* _XEMBED_INFO of the client window
*/
xembed::info m_xembed;
bool m_mapped{false}; bool m_mapped{false};
unsigned int m_width; unsigned int m_width;

View File

@ -34,7 +34,6 @@ using namespace std::chrono_literals;
// fwd declarations // fwd declarations
class connection; class connection;
struct xembed_data;
class background_manager; class background_manager;
class bg_slice; class bg_slice;

View File

@ -21,24 +21,41 @@ POLYBAR_NS
#define XEMBED_FOCUS_FIRST 1 #define XEMBED_FOCUS_FIRST 1
#define XEMBED_FOCUS_LAST 1 #define XEMBED_FOCUS_LAST 1
struct xembed_data { /**
unsigned long version; * Max XEMBED version supported.
unsigned long flags; */
xcb_timestamp_t time; #define XEMBED_MAX_VERSION UINT32_C(0)
xcb_atom_t xembed;
xcb_atom_t xembed_info;
};
/**
* Implementation of parts of the XEMBED spec (as much as needed to get the tray working).
*
* Ref: https://specifications.freedesktop.org/xembed-spec/xembed-spec-latest.html
*/
namespace xembed { namespace xembed {
xembed_data* query(connection& conn, xcb_window_t win, xembed_data* data);
class info {
public:
void set(uint32_t* data);
uint32_t get_version() const;
uint32_t get_flags() const;
bool is_mapped() const;
protected:
uint32_t version;
uint32_t flags;
};
bool query(connection& conn, xcb_window_t win, info& data);
void send_message(connection& conn, xcb_window_t target, long message, long d1, long d2, long d3); void send_message(connection& conn, xcb_window_t target, long message, long d1, long d2, long d3);
void send_focus_event(connection& conn, xcb_window_t target); void send_focus_event(connection& conn, xcb_window_t target);
void notify_embedded(connection& conn, xcb_window_t win, xcb_window_t embedder, long version); void notify_embedded(connection& conn, xcb_window_t win, xcb_window_t embedder, uint32_t version);
void notify_activated(connection& conn, xcb_window_t win); void notify_activated(connection& conn, xcb_window_t win);
void notify_deactivated(connection& conn, xcb_window_t win); void notify_deactivated(connection& conn, xcb_window_t win);
void notify_focused(connection& conn, xcb_window_t win, long focus_type); void notify_focused(connection& conn, xcb_window_t win, long focus_type);
void notify_unfocused(connection& conn, xcb_window_t win); void notify_unfocused(connection& conn, xcb_window_t win);
void unembed(connection& conn, xcb_window_t win, xcb_window_t root); void unembed(connection& conn, xcb_window_t win, xcb_window_t root);
} } // namespace xembed
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -38,18 +38,15 @@ namespace modules {
m_actions.emplace(make_pair<mousebtn, string>(mousebtn::DOUBLE_RIGHT, m_conf.get(name(), "double-click-right", ""s))); m_actions.emplace(make_pair<mousebtn, string>(mousebtn::DOUBLE_RIGHT, m_conf.get(name(), "double-click-right", ""s)));
// clang-format on // clang-format on
const auto pid_token = [](string& s) { const auto pid_token = [](const string& s) {
string::size_type p = s.find("%pid%"); return string_util::replace_all(s, "%pid%", to_string(getpid()));
if (p != string::npos) {
s.replace(p, 5, to_string(getpid()));
}
}; };
for (auto& action : m_actions) { for (auto& action : m_actions) {
pid_token(action.second); action.second = pid_token(action.second);
} }
for (auto& hook : m_hooks) { for (auto& hook : m_hooks) {
pid_token(hook->command); hook->command = pid_token(hook->command);
} }
m_formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, {TAG_OUTPUT}); m_formatter->add(DEFAULT_FORMAT, TAG_OUTPUT, {TAG_OUTPUT});

View File

@ -5,16 +5,11 @@
#include "utils/memory.hpp" #include "utils/memory.hpp"
#include "x11/connection.hpp" #include "x11/connection.hpp"
#include "x11/xembed.hpp"
POLYBAR_NS POLYBAR_NS
tray_client::tray_client(connection& conn, xcb_window_t win, unsigned int w, unsigned int h) tray_client::tray_client(connection& conn, xcb_window_t win, unsigned int w, unsigned int h)
: m_connection(conn), m_window(win), m_width(w), m_height(h) { : m_connection(conn), m_window(win), m_width(w), m_height(h) {}
m_xembed = memory_util::make_malloc_ptr<xembed_data>();
m_xembed->version = XEMBED_VERSION;
m_xembed->flags = XEMBED_MAPPED;
}
tray_client::~tray_client() { tray_client::~tray_client() {
xembed::unembed(m_connection, window(), m_connection.root()); xembed::unembed(m_connection, window(), m_connection.root());
@ -60,20 +55,31 @@ xcb_window_t tray_client::window() const {
return m_window; return m_window;
} }
/** void tray_client::query_xembed() {
* Get xembed data pointer m_xembed_supported = xembed::query(m_connection, m_window, m_xembed);
*/ }
xembed_data* tray_client::xembed() const {
return m_xembed.get(); bool tray_client::is_xembed_supported() const {
return m_xembed_supported;
}
const xembed::info& tray_client::get_xembed() const {
return m_xembed;
} }
/** /**
* Make sure that the window mapping state is correct * Make sure that the window mapping state is correct
*/ */
void tray_client::ensure_state() const { void tray_client::ensure_state() const {
if (!mapped() && ((xembed()->flags & XEMBED_MAPPED) == XEMBED_MAPPED)) { bool should_be_mapped = true;
if (is_xembed_supported()) {
should_be_mapped = m_xembed.is_mapped();
}
if (!mapped() && should_be_mapped) {
m_connection.map_window_checked(window()); m_connection.map_window_checked(window());
} else if (mapped() && ((xembed()->flags & XEMBED_MAPPED) != XEMBED_MAPPED)) { } else if (mapped() && !should_be_mapped) {
m_connection.unmap_window_checked(window()); m_connection.unmap_window_checked(window());
} }
} }

View File

@ -21,6 +21,12 @@
#include "x11/winspec.hpp" #include "x11/winspec.hpp"
#include "x11/xembed.hpp" #include "x11/xembed.hpp"
/*
* Tray implementation according to the System Tray Protocol.
*
* Ref: https://specifications.freedesktop.org/systemtray-spec/systemtray-spec-latest.html
*/
// ==================================================================================================== // ====================================================================================================
// //
// TODO: 32-bit visual // TODO: 32-bit visual
@ -740,14 +746,20 @@ void tray_manager::process_docking_request(xcb_window_t win) {
auto& client = m_clients.back(); auto& client = m_clients.back();
try { try {
m_log.trace("tray: Get client _XEMBED_INFO"); client->query_xembed();
xembed::query(m_connection, win, client->xembed()); } catch (const xpp::x::error::window& err) {
} catch (const std::exception& err) {
m_log.err("Failed to query _XEMBED_INFO, removing client... (%s)", err.what()); m_log.err("Failed to query _XEMBED_INFO, removing client... (%s)", err.what());
remove_client(win, true); remove_client(win, true);
return; return;
} }
m_log.trace("tray: xembed = %s", client->is_xembed_supported() ? "true" : "false");
if (client->is_xembed_supported()) {
m_log.trace("tray: version = 0x%x, flags = 0x%x, XEMBED_MAPPED = %s", client->get_xembed().get_version(),
client->get_xembed().get_flags(), client->get_xembed().is_mapped() ? "true" : "false");
}
try { try {
const unsigned int mask = XCB_CW_EVENT_MASK; const unsigned int mask = XCB_CW_EVENT_MASK;
const unsigned int values[]{XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY}; const unsigned int values[]{XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
@ -765,10 +777,12 @@ void tray_manager::process_docking_request(xcb_window_t win) {
m_connection.reparent_window_checked( m_connection.reparent_window_checked(
client->window(), m_tray, calculate_client_x(client->window()), calculate_client_y()); client->window(), m_tray, calculate_client_x(client->window()), calculate_client_y());
m_log.trace("tray: Send embbeded notification to client"); if (client->is_xembed_supported()) {
xembed::notify_embedded(m_connection, client->window(), m_tray, client->xembed()->version); m_log.trace("tray: Send embbeded notification to client");
xembed::notify_embedded(m_connection, client->window(), m_tray, client->get_xembed().get_version());
}
if (client->xembed()->flags & XEMBED_MAPPED) { if (!client->is_xembed_supported() || client->get_xembed().is_mapped()) {
m_log.trace("tray: Map client"); m_log.trace("tray: Map client");
m_connection.map_window_checked(client->window()); m_connection.map_window_checked(client->window());
} }
@ -1019,7 +1033,6 @@ void tray_manager::handle(const evt::property_notify& evt) {
m_log.trace("tray: _XEMBED_INFO: %s", m_connection.id(evt->window)); m_log.trace("tray: _XEMBED_INFO: %s", m_connection.id(evt->window));
auto xd = client->xembed();
auto win = client->window(); auto win = client->window();
if (evt->state == XCB_PROPERTY_NEW_VALUE) { if (evt->state == XCB_PROPERTY_NEW_VALUE) {
@ -1027,20 +1040,17 @@ void tray_manager::handle(const evt::property_notify& evt) {
} }
try { try {
m_log.trace("tray: Get client _XEMBED_INFO"); client->query_xembed();
xembed::query(m_connection, win, xd);
} catch (const application_error& err) {
m_log.err(err.what());
return;
} catch (const xpp::x::error::window& err) { } catch (const xpp::x::error::window& err) {
m_log.err("Failed to query _XEMBED_INFO, removing client... (%s)", err.what()); m_log.err("Failed to query _XEMBED_INFO, removing client... (%s)", err.what());
remove_client(win, true); remove_client(win, true);
return; return;
} }
m_log.trace("tray: _XEMBED_INFO[0]=%u _XEMBED_INFO[1]=%u", xd->version, xd->flags); m_log.trace("tray: version = 0x%x, flags = 0x%x, XEMBED_MAPPED = %s", client->get_xembed().get_version(),
client->get_xembed().get_flags(), client->get_xembed().is_mapped() ? "true" : "false");
if ((client->xembed()->flags & XEMBED_MAPPED) & XEMBED_MAPPED) { if (client->get_xembed().is_mapped()) {
reconfigure(); reconfigure();
} }
} }

View File

@ -5,26 +5,40 @@
POLYBAR_NS POLYBAR_NS
namespace xembed { namespace xembed {
void info::set(uint32_t* data) {
version = data[0];
flags = data[1];
}
uint32_t info::get_version() const {
return version;
}
uint32_t info::get_flags() const {
return flags;
}
bool info::is_mapped() const {
return (flags & XEMBED_MAPPED) == XEMBED_MAPPED;
}
/** /**
* Query _XEMBED_INFO for the given window * Query _XEMBED_INFO for the given window
*
* \return Whether valid XEMBED info was found
*/ */
xembed_data* query(connection& conn, xcb_window_t win, xembed_data* data) { bool query(connection& conn, xcb_window_t win, info& data) {
auto info = conn.get_property(false, win, _XEMBED_INFO, XCB_GET_PROPERTY_TYPE_ANY, 0L, 2); auto info = conn.get_property(false, win, _XEMBED_INFO, _XEMBED_INFO, 0L, 2);
if (info->value_len == 0) { if (info->value_len == 0) {
throw application_error("Invalid _XEMBED_INFO for window " + conn.id(win)); return false;
} }
std::vector<unsigned int> xembed_data{info.value<unsigned int>().begin(), info.value<unsigned int>().end()}; std::vector<uint32_t> xembed_data{info.value<uint32_t>().begin(), info.value<uint32_t>().end()};
data.set(xembed_data.data());
data->xembed = _XEMBED; return true;
data->xembed_info = _XEMBED_INFO;
data->time = XCB_CURRENT_TIME;
data->flags = xembed_data[1];
data->version = xembed_data[0];
return data;
} }
/** /**
@ -53,8 +67,8 @@ namespace xembed {
/** /**
* Acknowledge window embedding * Acknowledge window embedding
*/ */
void notify_embedded(connection& conn, xcb_window_t win, xcb_window_t embedder, long version) { void notify_embedded(connection& conn, xcb_window_t win, xcb_window_t embedder, uint32_t version) {
send_message(conn, win, XEMBED_EMBEDDED_NOTIFY, 0, embedder, version); send_message(conn, win, XEMBED_EMBEDDED_NOTIFY, 0, embedder, std::min(version, XEMBED_MAX_VERSION));
} }
/** /**

View File

@ -1,4 +1,4 @@
# Polybar version information # Polybar version information
# Update this on every release # Update this on every release
# This is used to create the version string if a git repo is not available # This is used to create the version string if a git repo is not available
3.5.6 3.5.7