mirror of
https://github.com/polybar/polybar.git
synced 2024-11-25 13:55:47 -05:00
tray: Align center and extend configuration
- The tray can now be centered in the bar - Set window atoms: * _NET_SYSTEM_TRAY_COLORS * _NET_SYSTEM_TRAY_VISUAL - New parameters added: * tray-background: Define background color * tray-offset-x: X position offset * tray-offset-y: Y position offset * tray-padding: Add spacing on the side of each icon * tray-maxsize: Size limit for tray icons, default: 16 * tray-scale: Icon zoom, default: 1.0 * tray-detached: The bar will ignore tray updates
This commit is contained in:
parent
dd7967dede
commit
94298741b6
7 changed files with 205 additions and 71 deletions
|
@ -38,6 +38,8 @@ modules-center = date
|
||||||
modules-right = volume memory cpu
|
modules-right = volume memory cpu
|
||||||
|
|
||||||
tray-position = right
|
tray-position = right
|
||||||
|
tray-background = #33ffffff
|
||||||
|
tray-padding = 4
|
||||||
|
|
||||||
|
|
||||||
[module/memory]
|
[module/memory]
|
||||||
|
|
|
@ -33,11 +33,13 @@ font-0 = tamzen:size=9;1
|
||||||
font-1 = siji:pixelsize=10;0
|
font-1 = siji:pixelsize=10;0
|
||||||
font-2 = unifont:size=6;-1
|
font-2 = unifont:size=6;-1
|
||||||
|
|
||||||
modules-left = mpd
|
modules-left = bspwm
|
||||||
modules-center = bspwm
|
modules-center = mpd
|
||||||
modules-right = volume memory cpu date
|
modules-right = volume memory cpu date
|
||||||
|
|
||||||
tray-position = right
|
tray-position = right
|
||||||
|
tray-background = #33ffffff
|
||||||
|
tray-padding = 4
|
||||||
|
|
||||||
wm-restack = bspwm
|
wm-restack = bspwm
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ modules-left = i3
|
||||||
modules-right = xbacklight date
|
modules-right = xbacklight date
|
||||||
|
|
||||||
tray-position = right
|
tray-position = right
|
||||||
|
tray-background = #33ffffff
|
||||||
|
tray-padding = 4
|
||||||
|
|
||||||
|
|
||||||
[module/i3]
|
[module/i3]
|
||||||
|
|
|
@ -106,9 +106,12 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
// }}}
|
// }}}
|
||||||
// Set bar colors {{{
|
// Set bar colors {{{
|
||||||
|
|
||||||
m_bar.background = color::parse(m_conf.get<string>(bs, "background", m_bar.background.hex_to_rgba()));
|
m_bar.background =
|
||||||
m_bar.foreground = color::parse(m_conf.get<string>(bs, "foreground", m_bar.foreground.hex_to_rgba()));
|
color::parse(m_conf.get<string>(bs, "background", m_bar.background.hex_to_rgba()));
|
||||||
m_bar.linecolor = color::parse(m_conf.get<string>(bs, "linecolor", m_bar.linecolor.hex_to_rgba()));
|
m_bar.foreground =
|
||||||
|
color::parse(m_conf.get<string>(bs, "foreground", m_bar.foreground.hex_to_rgba()));
|
||||||
|
m_bar.linecolor =
|
||||||
|
color::parse(m_conf.get<string>(bs, "linecolor", m_bar.linecolor.hex_to_rgba()));
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
// Set border values {{{
|
// Set border values {{{
|
||||||
|
@ -398,6 +401,8 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
m_tray.align = alignment::LEFT;
|
m_tray.align = alignment::LEFT;
|
||||||
else if (tray_position == "right")
|
else if (tray_position == "right")
|
||||||
m_tray.align = alignment::RIGHT;
|
m_tray.align = alignment::RIGHT;
|
||||||
|
else if (tray_position == "center")
|
||||||
|
m_tray.align = alignment::CENTER;
|
||||||
else
|
else
|
||||||
m_tray.align = alignment::NONE;
|
m_tray.align = alignment::NONE;
|
||||||
} catch (const key_error& err) {
|
} catch (const key_error& err) {
|
||||||
|
@ -405,30 +410,76 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_tray.align != alignment::NONE) {
|
if (m_tray.align != alignment::NONE) {
|
||||||
m_tray.background = m_bar.background.value();
|
|
||||||
m_tray.height = m_bar.height;
|
m_tray.height = m_bar.height;
|
||||||
m_tray.height -= m_borders.at(border::BOTTOM).size;
|
m_tray.height -= m_borders.at(border::BOTTOM).size;
|
||||||
m_tray.height -= m_borders.at(border::TOP).size;
|
m_tray.height -= m_borders.at(border::TOP).size;
|
||||||
|
m_tray.height_fill = m_tray.height;
|
||||||
|
|
||||||
if (m_tray.height % 2 != 0) {
|
if (m_tray.height % 2 != 0) {
|
||||||
m_tray.height--;
|
m_tray.height--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_tray.height > 24) {
|
auto maxsize = m_conf.get<int>(bs, "tray-maxsize", 16);
|
||||||
m_tray.spacing = (m_tray.height - 24) / 2;
|
if (m_tray.height > maxsize) {
|
||||||
m_tray.height = 24;
|
m_tray.spacing += (m_tray.height - maxsize) / 2;
|
||||||
|
m_tray.height = maxsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_tray.width = m_tray.height;
|
m_tray.width = m_tray.height;
|
||||||
m_tray.orig_y = m_bar.y + m_borders.at(border::TOP).size;
|
m_tray.orig_y = m_bar.y + m_borders.at(border::TOP).size;
|
||||||
|
|
||||||
if (m_tray.align == alignment::RIGHT)
|
// Apply user-defined scaling
|
||||||
m_tray.orig_x = m_bar.x + m_bar.width - m_borders.at(border::RIGHT).size;
|
auto scale = m_conf.get<float>(bs, "tray-scale", 1.0);
|
||||||
else
|
m_tray.width *= scale;
|
||||||
m_tray.orig_x = m_bar.x + m_borders.at(border::LEFT).size;
|
m_tray.height_fill *= scale;
|
||||||
}
|
|
||||||
|
|
||||||
m_tray.sibling = m_window;
|
if (m_tray.align == alignment::RIGHT) {
|
||||||
|
m_tray.orig_x = m_bar.x + m_bar.width - m_borders.at(border::RIGHT).size;
|
||||||
|
} else if (m_tray.align == alignment::LEFT) {
|
||||||
|
m_tray.orig_x = m_bar.x + m_borders.at(border::LEFT).size;
|
||||||
|
} else if (m_tray.align == alignment::CENTER) {
|
||||||
|
m_tray.orig_x = center_x() - (m_tray.width / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set user-defined background color
|
||||||
|
try {
|
||||||
|
auto tray_background = m_conf.get<string>(bs, "tray-background");
|
||||||
|
m_tray.background = color::parse(tray_background).value();
|
||||||
|
} catch (const key_error&) {
|
||||||
|
m_tray.background = m_bar.background.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add user-defined padding
|
||||||
|
m_tray.spacing += m_conf.get<int>(bs, "tray-padding", 0);
|
||||||
|
|
||||||
|
// Add user-defiend offset
|
||||||
|
auto offset_x_def = m_conf.get<string>(bs, "tray-offset-x", "");
|
||||||
|
auto offset_y_def = m_conf.get<string>(bs, "tray-offset-y", "");
|
||||||
|
|
||||||
|
auto offset_x = std::atoi(offset_x_def.c_str());
|
||||||
|
auto offset_y = std::atoi(offset_y_def.c_str());
|
||||||
|
|
||||||
|
if (offset_x != 0 && offset_x_def.find("%") != string::npos) {
|
||||||
|
offset_x = math_util::percentage_to_value(offset_x, m_bar.monitor->w);
|
||||||
|
offset_x -= m_tray.width / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset_y != 0 && offset_y_def.find("%") != string::npos) {
|
||||||
|
offset_y = math_util::percentage_to_value(offset_y, m_bar.monitor->h);
|
||||||
|
offset_y -= m_tray.width / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_tray.orig_x += offset_x;
|
||||||
|
m_tray.orig_y += offset_y;
|
||||||
|
|
||||||
|
// Add tray update callback unless explicitly disabled
|
||||||
|
if (!m_conf.get<bool>(bs, "tray-detached", false)) {
|
||||||
|
g_signals::tray::report_slotcount = bind(&bar::on_tray_report, this, placeholders::_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put the tray next to the bar in the window stack
|
||||||
|
m_tray.sibling = m_window;
|
||||||
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
// Connect signal handlers {{{
|
// Connect signal handlers {{{
|
||||||
|
@ -447,9 +498,6 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
g_signals::parser::unicode_text_write = bind(&bar::draw_character, this, placeholders::_1);
|
g_signals::parser::unicode_text_write = bind(&bar::draw_character, this, placeholders::_1);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
if (m_tray.align != alignment::NONE)
|
|
||||||
g_signals::tray::report_slotcount = bind(&bar::on_tray_report, this, placeholders::_1);
|
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
m_connection.attach_sink(this, 1);
|
m_connection.attach_sink(this, 1);
|
||||||
|
@ -674,6 +722,28 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* Get the horizontal center pos
|
||||||
|
*/
|
||||||
|
int center_x() {
|
||||||
|
int x = m_bar.x;
|
||||||
|
x += m_bar.width;
|
||||||
|
x -= m_borders[border::RIGHT].size;
|
||||||
|
x += m_borders[border::LEFT].size;
|
||||||
|
x /= 2;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the inner width of the bar
|
||||||
|
*/
|
||||||
|
int width_inner() {
|
||||||
|
auto w = m_bar.width;
|
||||||
|
w -= m_borders[border::RIGHT].size;
|
||||||
|
w -= m_borders[border::LEFT].size;
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle alignment update
|
* Handle alignment update
|
||||||
*/
|
*/
|
||||||
|
@ -778,8 +848,8 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
||||||
* Handle color change
|
* Handle color change
|
||||||
*/
|
*/
|
||||||
void on_color_change(gc gc_, color color_) { //{{{
|
void on_color_change(gc gc_, color color_) { //{{{
|
||||||
m_log.trace_x(
|
m_log.trace_x("bar: color_change(%i, %s -> %s)", static_cast<int>(gc_), color_.hex_to_rgba(),
|
||||||
"bar: color_change(%i, %s -> %s)", static_cast<int>(gc_), color_.hex_to_rgba(), color_.hex_to_rgb());
|
color_.hex_to_rgb());
|
||||||
|
|
||||||
if (gc_ == gc::FG) {
|
if (gc_ == gc::FG) {
|
||||||
m_fontmanager->allocate_color(color_);
|
m_fontmanager->allocate_color(color_);
|
||||||
|
|
|
@ -69,9 +69,11 @@ struct tray_settings {
|
||||||
orig_y = o.orig_y;
|
orig_y = o.orig_y;
|
||||||
width = o.width;
|
width = o.width;
|
||||||
height = o.height;
|
height = o.height;
|
||||||
|
height_fill = o.height_fill;
|
||||||
spacing = o.spacing;
|
spacing = o.spacing;
|
||||||
slots = o.slots;
|
slots = o.slots;
|
||||||
sibling = o.sibling;
|
sibling = o.sibling;
|
||||||
|
bg_pixmap = o.bg_pixmap;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,9 +83,11 @@ struct tray_settings {
|
||||||
int16_t orig_y{0};
|
int16_t orig_y{0};
|
||||||
uint16_t width{0};
|
uint16_t width{0};
|
||||||
uint16_t height{0};
|
uint16_t height{0};
|
||||||
|
uint16_t height_fill{0};
|
||||||
uint16_t spacing{0};
|
uint16_t spacing{0};
|
||||||
uint16_t slots{0};
|
uint16_t slots{0};
|
||||||
uint32_t sibling;
|
uint32_t sibling{0};
|
||||||
|
uint32_t bg_pixmap{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct border_settings {
|
struct border_settings {
|
||||||
|
|
|
@ -26,16 +26,18 @@ static xcb_atom_t WM_PROTOCOLS;
|
||||||
static xcb_atom_t WM_DELETE_WINDOW;
|
static xcb_atom_t WM_DELETE_WINDOW;
|
||||||
static xcb_atom_t _XEMBED;
|
static xcb_atom_t _XEMBED;
|
||||||
static xcb_atom_t _XEMBED_INFO;
|
static xcb_atom_t _XEMBED_INFO;
|
||||||
static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE;
|
|
||||||
static xcb_atom_t MANAGER;
|
static xcb_atom_t MANAGER;
|
||||||
static xcb_atom_t WM_STATE;
|
static xcb_atom_t WM_STATE;
|
||||||
|
static xcb_atom_t _NET_SYSTEM_TRAY_OPCODE;
|
||||||
static xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION;
|
static xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION;
|
||||||
|
static xcb_atom_t _NET_SYSTEM_TRAY_VISUAL;
|
||||||
|
static xcb_atom_t _NET_SYSTEM_TRAY_COLORS;
|
||||||
static xcb_atom_t WM_TAKE_FOCUS;
|
static xcb_atom_t WM_TAKE_FOCUS;
|
||||||
static xcb_atom_t Backlight;
|
static xcb_atom_t Backlight;
|
||||||
static xcb_atom_t BACKLIGHT;
|
static xcb_atom_t BACKLIGHT;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static cached_atom ATOMS[24] = {
|
static cached_atom ATOMS[26] = {
|
||||||
{"_NET_WM_NAME", sizeof("_NET_WM_NAME") - 1, &_NET_WM_NAME},
|
{"_NET_WM_NAME", sizeof("_NET_WM_NAME") - 1, &_NET_WM_NAME},
|
||||||
{"_NET_WM_DESKTOP", sizeof("_NET_WM_DESKTOP") - 1, &_NET_WM_DESKTOP},
|
{"_NET_WM_DESKTOP", sizeof("_NET_WM_DESKTOP") - 1, &_NET_WM_DESKTOP},
|
||||||
{"_NET_WM_WINDOW_TYPE", sizeof("_NET_WM_WINDOW_TYPE") - 1, &_NET_WM_WINDOW_TYPE},
|
{"_NET_WM_WINDOW_TYPE", sizeof("_NET_WM_WINDOW_TYPE") - 1, &_NET_WM_WINDOW_TYPE},
|
||||||
|
@ -53,10 +55,12 @@ static cached_atom ATOMS[24] = {
|
||||||
{"WM_DELETE_WINDOW", sizeof("WM_DELETE_WINDOW") - 1, &WM_DELETE_WINDOW},
|
{"WM_DELETE_WINDOW", sizeof("WM_DELETE_WINDOW") - 1, &WM_DELETE_WINDOW},
|
||||||
{"_XEMBED", sizeof("_XEMBED") - 1, &_XEMBED},
|
{"_XEMBED", sizeof("_XEMBED") - 1, &_XEMBED},
|
||||||
{"_XEMBED_INFO", sizeof("_XEMBED_INFO") - 1, &_XEMBED_INFO},
|
{"_XEMBED_INFO", sizeof("_XEMBED_INFO") - 1, &_XEMBED_INFO},
|
||||||
{"_NET_SYSTEM_TRAY_OPCODE", sizeof("_NET_SYSTEM_TRAY_OPCODE") - 1, &_NET_SYSTEM_TRAY_OPCODE},
|
|
||||||
{"MANAGER", sizeof("MANAGER") - 1, &MANAGER},
|
{"MANAGER", sizeof("MANAGER") - 1, &MANAGER},
|
||||||
{"WM_STATE", sizeof("WM_STATE") - 1, &WM_STATE},
|
{"WM_STATE", sizeof("WM_STATE") - 1, &WM_STATE},
|
||||||
|
{"_NET_SYSTEM_TRAY_OPCODE", sizeof("_NET_SYSTEM_TRAY_OPCODE") - 1, &_NET_SYSTEM_TRAY_OPCODE},
|
||||||
{"_NET_SYSTEM_TRAY_ORIENTATION", sizeof("_NET_SYSTEM_TRAY_ORIENTATION") - 1, &_NET_SYSTEM_TRAY_ORIENTATION},
|
{"_NET_SYSTEM_TRAY_ORIENTATION", sizeof("_NET_SYSTEM_TRAY_ORIENTATION") - 1, &_NET_SYSTEM_TRAY_ORIENTATION},
|
||||||
|
{"_NET_SYSTEM_TRAY_VISUAL", sizeof("_NET_SYSTEM_TRAY_VISUAL") - 1, &_NET_SYSTEM_TRAY_VISUAL},
|
||||||
|
{"_NET_SYSTEM_TRAY_COLORS", sizeof("_NET_SYSTEM_TRAY_COLORS") - 1, &_NET_SYSTEM_TRAY_COLORS},
|
||||||
{"WM_TAKE_FOCUS", sizeof("WM_TAKE_FOCUS") - 1, &WM_TAKE_FOCUS},
|
{"WM_TAKE_FOCUS", sizeof("WM_TAKE_FOCUS") - 1, &WM_TAKE_FOCUS},
|
||||||
{"Backlight", sizeof("Backlight") - 1, &Backlight},
|
{"Backlight", sizeof("Backlight") - 1, &Backlight},
|
||||||
{"BACKLIGHT", sizeof("BACKLIGHT") - 1, &BACKLIGHT},
|
{"BACKLIGHT", sizeof("BACKLIGHT") - 1, &BACKLIGHT},
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "components/types.hpp"
|
#include "components/types.hpp"
|
||||||
#include "components/x11/connection.hpp"
|
#include "components/x11/connection.hpp"
|
||||||
#include "components/x11/xembed.hpp"
|
#include "components/x11/xembed.hpp"
|
||||||
|
#include "utils/color.hpp"
|
||||||
#include "utils/memory.hpp"
|
#include "utils/memory.hpp"
|
||||||
#include "utils/process.hpp"
|
#include "utils/process.hpp"
|
||||||
|
|
||||||
|
@ -141,6 +142,7 @@ class traymanager
|
||||||
try {
|
try {
|
||||||
create_window();
|
create_window();
|
||||||
set_wmhints();
|
set_wmhints();
|
||||||
|
set_traycolors();
|
||||||
} catch (const std::exception& err) {
|
} catch (const std::exception& err) {
|
||||||
m_log.err(err.what());
|
m_log.err(err.what());
|
||||||
m_log.err("Cannot activate traymanager... failed to setup window");
|
m_log.err("Cannot activate traymanager... failed to setup window");
|
||||||
|
@ -200,14 +202,14 @@ class traymanager
|
||||||
g_signals::bar::visibility_change = nullptr;
|
g_signals::bar::visibility_change = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("tray: Unembed all clients");
|
|
||||||
m_clients.clear();
|
|
||||||
|
|
||||||
if (m_connection.get_selection_owner_unchecked(m_atom).owner<xcb_window_t>() == m_tray) {
|
if (m_connection.get_selection_owner_unchecked(m_atom).owner<xcb_window_t>() == m_tray) {
|
||||||
m_log.trace("tray: Unset selection owner");
|
m_log.trace("tray: Unset selection owner");
|
||||||
m_connection.set_selection_owner(XCB_NONE, m_atom, XCB_CURRENT_TIME);
|
m_connection.set_selection_owner(XCB_NONE, m_atom, XCB_CURRENT_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_log.trace("tray: Unembed clients");
|
||||||
|
m_clients.clear();
|
||||||
|
|
||||||
if (m_tray != XCB_NONE) {
|
if (m_tray != XCB_NONE) {
|
||||||
if (m_mapped) {
|
if (m_mapped) {
|
||||||
m_log.trace("tray: Unmap window");
|
m_log.trace("tray: Unmap window");
|
||||||
|
@ -246,30 +248,37 @@ class traymanager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_signals::tray::report_slotcount)
|
m_settings.slots = mapped_clients;
|
||||||
g_signals::tray::report_slotcount(mapped_clients);
|
|
||||||
|
|
||||||
if (!width && m_mapped) {
|
try {
|
||||||
m_connection.unmap_window_checked(m_tray);
|
if (g_signals::tray::report_slotcount)
|
||||||
return;
|
g_signals::tray::report_slotcount(mapped_clients);
|
||||||
} else if (width && !m_mapped) {
|
|
||||||
m_connection.map_window_checked(m_tray);
|
if (!width && m_mapped) {
|
||||||
m_lastwidth = 0;
|
m_connection.unmap_window_checked(m_tray);
|
||||||
return;
|
return;
|
||||||
} else if (!width) {
|
} else if (width && !m_mapped) {
|
||||||
return;
|
m_connection.map_window_checked(m_tray);
|
||||||
|
m_lastwidth = 0;
|
||||||
|
return;
|
||||||
|
} else if (!width) {
|
||||||
|
return;
|
||||||
|
} else if ((width += m_settings.spacing) == m_lastwidth) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lastwidth = width;
|
||||||
|
|
||||||
|
// clear window to get rid of frozen artifacts
|
||||||
|
m_connection.clear_area(1, m_tray, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
// update window
|
||||||
|
const uint32_t val[2]{static_cast<uint32_t>(calculate_x(width)), width};
|
||||||
|
m_connection.configure_window(m_tray, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_WIDTH, val);
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Failed to configure tray window (%s)", err.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((width += m_settings.spacing) == m_lastwidth) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lastwidth = width;
|
|
||||||
|
|
||||||
// update window
|
|
||||||
const uint32_t val[2]{static_cast<uint32_t>(calculate_x()), width};
|
|
||||||
m_connection.configure_window(m_tray, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_WIDTH, val);
|
|
||||||
|
|
||||||
// reposition clients
|
// reposition clients
|
||||||
uint32_t pos_x = m_settings.spacing;
|
uint32_t pos_x = m_settings.spacing;
|
||||||
for (auto&& client : m_clients) {
|
for (auto&& client : m_clients) {
|
||||||
|
@ -315,10 +324,12 @@ class traymanager
|
||||||
/**
|
/**
|
||||||
* Calculate the tray window's horizontal position
|
* Calculate the tray window's horizontal position
|
||||||
*/
|
*/
|
||||||
int16_t calculate_x() const {
|
int16_t calculate_x(uint32_t width) const {
|
||||||
auto x = m_settings.orig_x;
|
auto x = m_settings.orig_x;
|
||||||
if (m_settings.align == alignment::RIGHT)
|
if (m_settings.align == alignment::RIGHT)
|
||||||
x -= ((m_settings.width + m_settings.spacing) * m_clients.size() + m_settings.spacing);
|
x -= ((m_settings.width + m_settings.spacing) * m_clients.size() + m_settings.spacing);
|
||||||
|
else if (m_settings.align == alignment::CENTER)
|
||||||
|
x -= (width / 2) - (m_settings.width / 2);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,31 +365,29 @@ class traymanager
|
||||||
* Create tray window
|
* Create tray window
|
||||||
*/
|
*/
|
||||||
void create_window() {
|
void create_window() {
|
||||||
auto x = calculate_x();
|
auto x = calculate_x(0);
|
||||||
auto y = calculate_y();
|
auto y = calculate_y();
|
||||||
|
auto scr = m_connection.screen();
|
||||||
|
|
||||||
m_tray = m_connection.generate_id();
|
m_tray = m_connection.generate_id();
|
||||||
m_log.trace("tray: Create tray window %s, (%ix%i+%i+%i)", m_connection.id(m_tray),
|
m_log.trace("tray: Create tray window %s, (%ix%i+%i+%i)", m_connection.id(m_tray),
|
||||||
m_settings.width, m_settings.height, x, y);
|
m_settings.width, m_settings.height_fill, x, y);
|
||||||
auto scr = m_connection.screen();
|
|
||||||
const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
|
const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
|
||||||
const uint32_t values[3]{m_settings.background, true,
|
const uint32_t values[4]{m_settings.background, true,
|
||||||
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
||||||
|
|
||||||
m_connection.create_window_checked(scr->root_depth, m_tray, scr->root, x, y,
|
m_connection.create_window_checked(scr->root_depth, m_tray, scr->root, x, y,
|
||||||
m_settings.width + m_settings.spacing * 2, m_settings.height + m_settings.spacing * 2, 0,
|
m_settings.width + m_settings.spacing * 2, m_settings.height_fill, 0,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, mask, values);
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, mask, values);
|
||||||
|
|
||||||
try {
|
// Put the tray window above the defined sibling in the window stack
|
||||||
// Put the tray window above the defined sibling in the window stack
|
if (m_settings.sibling != XCB_NONE) {
|
||||||
if (m_settings.sibling != XCB_NONE) {
|
const uint32_t value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
|
||||||
const uint32_t value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
|
const uint32_t value_list[2]{m_settings.sibling, XCB_STACK_MODE_ABOVE};
|
||||||
const uint32_t value_list[2]{m_settings.sibling, XCB_STACK_MODE_ABOVE};
|
m_connection.configure_window_checked(m_tray, value_mask, value_list);
|
||||||
m_connection.configure_window_checked(m_tray, value_mask, value_list);
|
m_connection.flush();
|
||||||
m_connection.flush();
|
m_restacked = true;
|
||||||
m_restacked = true;
|
|
||||||
}
|
|
||||||
} catch (const std::exception& err) {
|
|
||||||
auto id = m_connection.id(m_settings.sibling);
|
|
||||||
m_log.trace("tray: Failed to put tray above %s in the stack (%s)", id, err.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,12 +424,43 @@ class traymanager
|
||||||
m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_tray,
|
m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_tray,
|
||||||
_NET_SYSTEM_TRAY_ORIENTATION, _NET_SYSTEM_TRAY_ORIENTATION, 32, 1, values);
|
_NET_SYSTEM_TRAY_ORIENTATION, _NET_SYSTEM_TRAY_ORIENTATION, 32, 1, values);
|
||||||
|
|
||||||
|
m_log.trace("tray: Set window _NET_SYSTEM_TRAY_VISUAL");
|
||||||
|
const uint32_t values2[1]{m_connection.screen()->root_visual};
|
||||||
|
m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_tray,
|
||||||
|
_NET_SYSTEM_TRAY_ORIENTATION, XCB_ATOM_VISUALID, 32, 1, values2);
|
||||||
|
|
||||||
m_log.trace("tray: Set window _NET_WM_PID");
|
m_log.trace("tray: Set window _NET_WM_PID");
|
||||||
int pid = getpid();
|
int pid = getpid();
|
||||||
m_connection.change_property(
|
m_connection.change_property(
|
||||||
XCB_PROP_MODE_REPLACE, m_tray, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &pid);
|
XCB_PROP_MODE_REPLACE, m_tray, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set color atom used by clients when determing icon theme
|
||||||
|
*/
|
||||||
|
void set_traycolors() {
|
||||||
|
m_log.trace("tray: Set _NET_SYSTEM_TRAY_COLORS to %x", m_settings.background);
|
||||||
|
|
||||||
|
auto c = color_util::make_32bit(m_settings.background);
|
||||||
|
auto r = color_util::red(c);
|
||||||
|
auto g = color_util::green(c);
|
||||||
|
auto b = color_util::blue(c);
|
||||||
|
|
||||||
|
const uint32_t colors[12] = {
|
||||||
|
r, g, b, // normal
|
||||||
|
r, g, b, // error
|
||||||
|
r, g, b, // warning
|
||||||
|
r, g, b, // success
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_tray, _NET_SYSTEM_TRAY_COLORS,
|
||||||
|
XCB_ATOM_CARDINAL, 32, 12, colors);
|
||||||
|
} catch (const std::exception& err) {
|
||||||
|
m_log.err("Failed to set tray colors");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Acquire the systray selection
|
* Acquire the systray selection
|
||||||
*/
|
*/
|
||||||
|
@ -479,6 +519,13 @@ class traymanager
|
||||||
return m_settings.spacing;
|
return m_settings.spacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates a client's y position
|
||||||
|
*/
|
||||||
|
int calculate_client_ypos() {
|
||||||
|
return (m_settings.height_fill - m_settings.height) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process client docking request
|
* Process client docking request
|
||||||
*/
|
*/
|
||||||
|
@ -526,11 +573,14 @@ class traymanager
|
||||||
m_connection.change_save_set_checked(XCB_SET_MODE_INSERT, client->window());
|
m_connection.change_save_set_checked(XCB_SET_MODE_INSERT, client->window());
|
||||||
|
|
||||||
m_log.trace("tray: Update tray client event mask");
|
m_log.trace("tray: Update tray client event mask");
|
||||||
const uint32_t event_mask[]{XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
const uint32_t event_mask[]{XCB_BACK_PIXMAP_PARENT_RELATIVE,
|
||||||
m_connection.change_window_attributes_checked(client->window(), XCB_CW_EVENT_MASK, event_mask);
|
XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_STRUCTURE_NOTIFY};
|
||||||
|
m_connection.change_window_attributes_checked(
|
||||||
|
client->window(), XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK, event_mask);
|
||||||
|
|
||||||
m_log.trace("tray: Reparent tray client");
|
m_log.trace("tray: Reparent tray client");
|
||||||
m_connection.reparent_window_checked(client->window(), m_tray, m_settings.spacing, m_settings.spacing);
|
m_connection.reparent_window_checked(
|
||||||
|
client->window(), m_tray, m_settings.spacing, calculate_client_ypos());
|
||||||
|
|
||||||
m_log.trace("tray: Configure tray client size");
|
m_log.trace("tray: Configure tray client size");
|
||||||
const uint32_t values[]{m_settings.width, m_settings.height};
|
const uint32_t values[]{m_settings.width, m_settings.height};
|
||||||
|
@ -623,7 +673,7 @@ class traymanager
|
||||||
auto client = find_client(evt->window);
|
auto client = find_client(evt->window);
|
||||||
if (client) {
|
if (client) {
|
||||||
m_log.trace("tray: Received configure_request for client %s", m_connection.id(evt->window));
|
m_log.trace("tray: Received configure_request for client %s", m_connection.id(evt->window));
|
||||||
client->configure_notify(calculate_client_xpos(evt->window), m_settings.spacing,
|
client->configure_notify(calculate_client_xpos(evt->window), calculate_client_ypos(),
|
||||||
m_settings.width, m_settings.height);
|
m_settings.width, m_settings.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,7 +688,7 @@ class traymanager
|
||||||
auto client = find_client(evt->window);
|
auto client = find_client(evt->window);
|
||||||
if (client) {
|
if (client) {
|
||||||
m_log.trace("tray: Received resize_request for client %s", m_connection.id(evt->window));
|
m_log.trace("tray: Received resize_request for client %s", m_connection.id(evt->window));
|
||||||
client->configure_notify(calculate_client_xpos(evt->window), m_settings.spacing,
|
client->configure_notify(calculate_client_xpos(evt->window), calculate_client_ypos(),
|
||||||
m_settings.width, m_settings.height);
|
m_settings.width, m_settings.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue