Merge tag '3.5.7'
This commit is contained in:
commit
771cd1fd98
36
CHANGELOG.md
36
CHANGELOG.md
@ -1,4 +1,5 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
Each release should have the following subsections, if entries exist, in the
|
Each release should have the following subsections, if entries exist, in the
|
||||||
given order: `Breaking`, `Build`, `Deprecated`, `Removed`, `Added`, `Changed`,
|
given order: `Breaking`, `Build`, `Deprecated`, `Removed`, `Added`, `Changed`,
|
||||||
@ -56,3 +57,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
([`#2040`](https://github.com/polybar/polybar/issues/2040))
|
([`#2040`](https://github.com/polybar/polybar/issues/2040))
|
||||||
|
|
||||||
[Unreleased]: https://github.com/polybar/polybar/compare/3.5.2...HEAD
|
[Unreleased]: https://github.com/polybar/polybar/compare/3.5.2...HEAD
|
||||||
|
## [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
|
||||||
|
### Build
|
||||||
|
- Support building documentation on sphinx 4.0 ([`#2424`](https://github.com/polybar/polybar/issues/2424))
|
||||||
|
### Fixed
|
||||||
|
- Tray icons sometimes appears outside of bar ([`#2430`](https://github.com/polybar/polybar/issues/2430), [`#1679`](https://github.com/polybar/polybar/issues/1679))
|
||||||
|
- Crash in the i3 module ([`#2416`](https://github.com/polybar/polybar/issues/2416))
|
||||||
|
|
||||||
|
## [3.5.5] - 2021-03-01
|
||||||
|
### Build
|
||||||
|
- Support older python sphinx versions again ([`#2356`](https://github.com/polybar/polybar/issues/2356))
|
||||||
|
|
||||||
|
## [3.5.4] - 2021-01-07
|
||||||
|
### Fixed
|
||||||
|
- Wrong text displayed if module text ends with `}` ([`#2331`](https://github.com/polybar/polybar/issues/2331))
|
||||||
|
|
||||||
|
## [3.5.3] - 2020-12-23
|
||||||
|
### Build
|
||||||
|
- Don't use `git` when building documentation ([`#2309`](https://github.com/polybar/polybar/issues/2309))
|
||||||
|
### Fixed
|
||||||
|
- Empty color values are no longer treated as invalid and no longer produce an error.
|
||||||
|
|
||||||
|
[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.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.3]: https://github.com/polybar/polybar/releases/tag/3.5.3
|
||||||
|
49
doc/conf.py
49
doc/conf.py
@ -13,12 +13,22 @@
|
|||||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
#
|
#
|
||||||
import os
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import datetime
|
import datetime
|
||||||
import subprocess
|
import sphinx
|
||||||
from docutils.nodes import Node
|
import packaging.version
|
||||||
from typing import List
|
|
||||||
from sphinx.domains.changeset import VersionChange
|
|
||||||
|
|
||||||
|
def get_version(root_path):
|
||||||
|
"""
|
||||||
|
Reads the polybar version from the version.txt at the root of the repo.
|
||||||
|
"""
|
||||||
|
path = Path(root_path) / "version.txt"
|
||||||
|
with open(path, "r") as f:
|
||||||
|
for line in f.readlines():
|
||||||
|
if not line.startswith("#"):
|
||||||
|
return packaging.version.parse(line)
|
||||||
|
|
||||||
|
raise RuntimeError("No version found in {}".format(path))
|
||||||
|
|
||||||
# -- Project information -----------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
@ -50,6 +60,11 @@ else:
|
|||||||
# build folder.
|
# build folder.
|
||||||
doc_path = '@doc_path@'
|
doc_path = '@doc_path@'
|
||||||
|
|
||||||
|
# The version from the version.txt file. Since we are not always first
|
||||||
|
# configured by cmake, we don't necessarily have access to the current version
|
||||||
|
# number
|
||||||
|
version_txt = get_version(Path(doc_path).absolute().parent)
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
@ -170,6 +185,9 @@ man_pages = [
|
|||||||
('man/polybar.5', 'polybar', 'configuration file for polybar(1)', [], 5)
|
('man/polybar.5', 'polybar', 'configuration file for polybar(1)', [], 5)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
man_make_section_directory = False
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output ----------------------------------------------
|
# -- Options for Texinfo output ----------------------------------------------
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
@ -202,23 +220,32 @@ epub_exclude_files = ['search.html']
|
|||||||
# The 'versionadded' and 'versionchanged' directives are overridden.
|
# The 'versionadded' and 'versionchanged' directives are overridden.
|
||||||
suppress_warnings = ['app.add_directive']
|
suppress_warnings = ['app.add_directive']
|
||||||
|
|
||||||
def setup(app):
|
# It is not exactly clear in which version the VersionChange class was
|
||||||
|
# introduced, but we know it is available in at least 1.8.5.
|
||||||
|
# This feature is mainly needed for the online docs on readthedocs for the docs
|
||||||
|
# built from master, documentation built for proper releases should not even
|
||||||
|
# mention unreleased changes. Because of that it's not that important that this
|
||||||
|
# is added to local builds.
|
||||||
|
if packaging.version.parse(sphinx.__version__) >= packaging.version.parse("1.8.5"):
|
||||||
|
|
||||||
|
from typing import List
|
||||||
|
from docutils.nodes import Node
|
||||||
|
from sphinx.domains.changeset import VersionChange
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
app.add_directive('deprecated', VersionDirective)
|
app.add_directive('deprecated', VersionDirective)
|
||||||
app.add_directive('versionadded', VersionDirective)
|
app.add_directive('versionadded', VersionDirective)
|
||||||
app.add_directive('versionchanged', VersionDirective)
|
app.add_directive('versionchanged', VersionDirective)
|
||||||
|
|
||||||
class VersionDirective(VersionChange):
|
class VersionDirective(VersionChange):
|
||||||
"""
|
"""
|
||||||
Overwrites the Sphinx directive for versionchanged, versionadded, and
|
Overwrites the Sphinx directive for versionchanged, versionadded, and
|
||||||
deprecated and adds an unreleased tag to versions that are not yet released
|
deprecated and adds an unreleased tag to versions that are not yet released
|
||||||
"""
|
"""
|
||||||
def run(self) -> List[Node]:
|
def run(self) -> List[Node]:
|
||||||
# If the tag exists 'git rev-parse' will succeed and otherwise fail
|
directive_version = packaging.version.parse(self.arguments[0])
|
||||||
completed = subprocess.run(["git", "rev-parse", self.arguments[0]],
|
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, cwd=doc_path,
|
|
||||||
check=False)
|
|
||||||
|
|
||||||
if completed.returncode != 0:
|
if directive_version > version_txt:
|
||||||
self.arguments[0] += " (unreleased)"
|
self.arguments[0] += " (unreleased)"
|
||||||
|
|
||||||
return super().run()
|
return super().run()
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -225,6 +225,10 @@ chrono::duration<double> config::convert(string&& value) const {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
rgba config::convert(string&& value) const {
|
rgba config::convert(string&& value) const {
|
||||||
|
if (value.empty()) {
|
||||||
|
return rgba{};
|
||||||
|
}
|
||||||
|
|
||||||
rgba ret{value};
|
rgba ret{value};
|
||||||
|
|
||||||
if (!ret.has_color()) {
|
if (!ret.has_color()) {
|
||||||
|
@ -655,16 +655,7 @@ bool controller::process_update(bool force) {
|
|||||||
block_contents += padding_right;
|
block_contents += padding_right;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip unnecessary reset tags
|
contents += block_contents;
|
||||||
block_contents = string_util::replace_all(block_contents, "T-}%{T", "T");
|
|
||||||
block_contents = string_util::replace_all(block_contents, "B-}%{B#", "B#");
|
|
||||||
block_contents = string_util::replace_all(block_contents, "F-}%{F#", "F#");
|
|
||||||
block_contents = string_util::replace_all(block_contents, "U-}%{U#", "U#");
|
|
||||||
block_contents = string_util::replace_all(block_contents, "u-}%{u#", "u#");
|
|
||||||
block_contents = string_util::replace_all(block_contents, "o-}%{o#", "o#");
|
|
||||||
|
|
||||||
// Join consecutive tags
|
|
||||||
contents += string_util::replace_all(block_contents, "}%{", " ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -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});
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
|
#include "x11/tray_client.hpp"
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_aux.h>
|
#include <xcb/xcb_aux.h>
|
||||||
|
|
||||||
#include "utils/memory.hpp"
|
#include "utils/memory.hpp"
|
||||||
#include "x11/connection.hpp"
|
#include "x11/connection.hpp"
|
||||||
#include "x11/tray_client.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());
|
||||||
@ -28,11 +24,7 @@ unsigned int tray_client::height() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tray_client::clear_window() const {
|
void tray_client::clear_window() const {
|
||||||
try {
|
|
||||||
m_connection.clear_area_checked(1, window(), 0, 0, width(), height());
|
m_connection.clear_area_checked(1, window(), 0, 0, width(), height());
|
||||||
} catch (const xpp::x::error::window& err) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
@ -427,14 +433,22 @@ void tray_manager::refresh_window() {
|
|||||||
m_connection.poly_fill_rectangle(m_pixmap, m_gc, 1, &rect);
|
m_connection.poly_fill_rectangle(m_pixmap, m_gc, 1, &rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_surface)
|
if (m_surface) {
|
||||||
m_surface->flush();
|
m_surface->flush();
|
||||||
|
}
|
||||||
|
|
||||||
m_connection.clear_area(0, m_tray, 0, 0, width, height);
|
m_connection.clear_area(0, m_tray, 0, 0, width, height);
|
||||||
|
|
||||||
for (auto&& client : m_clients) {
|
for (auto&& client : m_clients) {
|
||||||
|
try {
|
||||||
|
if (client->mapped()) {
|
||||||
client->clear_window();
|
client->clear_window();
|
||||||
}
|
}
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
m_log.err("Failed to clear tray client %s '%s' (%s)", m_connection.id(client->window()),
|
||||||
|
ewmh_util::get_wm_name(client->window()), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_connection.flush();
|
m_connection.flush();
|
||||||
|
|
||||||
@ -726,26 +740,29 @@ void tray_manager::track_selection_owner(xcb_window_t owner) {
|
|||||||
* Process client docking request
|
* Process client docking request
|
||||||
*/
|
*/
|
||||||
void tray_manager::process_docking_request(xcb_window_t win) {
|
void tray_manager::process_docking_request(xcb_window_t win) {
|
||||||
m_log.info("Processing docking request from %s", m_connection.id(win));
|
m_log.info("Processing docking request from '%s' (%s)", ewmh_util::get_wm_name(win), m_connection.id(win));
|
||||||
|
|
||||||
m_clients.emplace_back(factory_util::shared<tray_client>(m_connection, win, m_opts.width, m_opts.height));
|
m_clients.emplace_back(factory_util::shared<tray_client>(m_connection, win, m_opts.width, m_opts.height));
|
||||||
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 application_error& err) {
|
|
||||||
m_log.err(err.what());
|
|
||||||
} 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 = %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_BACK_PIXMAP | XCB_CW_EVENT_MASK};
|
const unsigned int mask = XCB_CW_EVENT_MASK;
|
||||||
const unsigned int values[]{
|
const unsigned int values[]{XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
||||||
XCB_BACK_PIXMAP_PARENT_RELATIVE, XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
|
||||||
|
|
||||||
m_log.trace("tray: Update client window");
|
m_log.trace("tray: Update client window");
|
||||||
m_connection.change_window_attributes_checked(client->window(), mask, values);
|
m_connection.change_window_attributes_checked(client->window(), mask, values);
|
||||||
@ -760,15 +777,18 @@ 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());
|
||||||
|
|
||||||
|
if (client->is_xembed_supported()) {
|
||||||
m_log.trace("tray: Send embbeded notification to client");
|
m_log.trace("tray: Send embbeded notification to client");
|
||||||
xembed::notify_embedded(m_connection, client->window(), m_tray, client->xembed()->version);
|
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());
|
||||||
}
|
}
|
||||||
} catch (const xpp::x::error::window& err) {
|
|
||||||
m_log.err("Failed to setup tray client, removing... (%s)", err.what());
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Failed to setup tray client removing... (%s)", err.what());
|
||||||
remove_client(win, false);
|
remove_client(win, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1013,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) {
|
||||||
@ -1021,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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,26 +5,40 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace xembed {
|
namespace xembed {
|
||||||
/**
|
|
||||||
* Query _XEMBED_INFO for the given window
|
|
||||||
*/
|
|
||||||
xembed_data* query(connection& conn, xcb_window_t win, xembed_data* data) {
|
|
||||||
auto info = conn.get_property(false, win, _XEMBED_INFO, XCB_GET_PROPERTY_TYPE_ANY, 0L, 2);
|
|
||||||
|
|
||||||
if (info->value_len == 0) {
|
void info::set(uint32_t* data) {
|
||||||
throw application_error("Invalid _XEMBED_INFO for window " + conn.id(win));
|
version = data[0];
|
||||||
|
flags = data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<unsigned int> xembed_data{info.value<unsigned int>().begin(), info.value<unsigned int>().end()};
|
uint32_t info::get_version() const {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
data->xembed = _XEMBED;
|
uint32_t info::get_flags() const {
|
||||||
data->xembed_info = _XEMBED_INFO;
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
data->time = XCB_CURRENT_TIME;
|
bool info::is_mapped() const {
|
||||||
data->flags = xembed_data[1];
|
return (flags & XEMBED_MAPPED) == XEMBED_MAPPED;
|
||||||
data->version = xembed_data[0];
|
}
|
||||||
|
|
||||||
return data;
|
/**
|
||||||
|
* Query _XEMBED_INFO for the given window
|
||||||
|
*
|
||||||
|
* \return Whether valid XEMBED info was found
|
||||||
|
*/
|
||||||
|
bool query(connection& conn, xcb_window_t win, info& data) {
|
||||||
|
auto info = conn.get_property(false, win, _XEMBED_INFO, _XEMBED_INFO, 0L, 2);
|
||||||
|
|
||||||
|
if (info->value_len == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> xembed_data{info.value<uint32_t>().begin(), info.value<uint32_t>().end()};
|
||||||
|
data.set(xembed_data.data());
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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.2
|
3.5.7
|
||||||
|
Loading…
Reference in New Issue
Block a user