fix: Make the application work properly using i3wm
This commit is contained in:
parent
0bf26642d2
commit
eb38fb85ac
@ -423,6 +423,7 @@ The configuration syntax is based on the `ini` file format.
|
|||||||
;
|
;
|
||||||
; Currently supported WM's:
|
; Currently supported WM's:
|
||||||
; bspwm
|
; bspwm
|
||||||
|
; i3
|
||||||
; Default: none
|
; Default: none
|
||||||
wm-restack = bspwm
|
wm-restack = bspwm
|
||||||
~~~
|
~~~
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "components/x11/xlib.hpp"
|
#include "components/x11/xlib.hpp"
|
||||||
#include "components/x11/xutils.hpp"
|
#include "components/x11/xutils.hpp"
|
||||||
#include "utils/bspwm.hpp"
|
#include "utils/bspwm.hpp"
|
||||||
|
#include "utils/i3.hpp"
|
||||||
#include "utils/math.hpp"
|
#include "utils/math.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
#include "utils/threading.hpp"
|
#include "utils/threading.hpp"
|
||||||
@ -28,7 +29,7 @@ namespace bar_signals {
|
|||||||
delegate::Signal1<string> action_click;
|
delegate::Signal1<string> action_click;
|
||||||
};
|
};
|
||||||
|
|
||||||
class bar : public xpp::event::sink<evt::button_press> {
|
class bar : public xpp::event::sink<evt::button_press, evt::expose> {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Construct bar
|
* Construct bar
|
||||||
@ -244,23 +245,76 @@ class bar : public xpp::event::sink<evt::button_press> {
|
|||||||
|
|
||||||
m_log.trace("bar: Set _NET_WM_WINDOW_TYPE");
|
m_log.trace("bar: Set _NET_WM_WINDOW_TYPE");
|
||||||
{
|
{
|
||||||
xcb_atom_t win_types[2] = {_NET_WM_WINDOW_TYPE_DOCK, _NET_WM_WINDOW_TYPE_NORMAL};
|
// const uint32_t win_types[2] = {_NET_WM_WINDOW_TYPE_DOCK, _NET_WM_WINDOW_TYPE_NORMAL};
|
||||||
|
const uint32_t win_types[1] = {_NET_WM_WINDOW_TYPE_DOCK};
|
||||||
m_connection.change_property_checked(
|
m_connection.change_property_checked(
|
||||||
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, 2, &win_types);
|
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, 1, win_types);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("bar: Set _NET_WM_STATE");
|
m_log.trace("bar: Set _NET_WM_STATE");
|
||||||
{
|
{
|
||||||
xcb_atom_t win_states[2] = {_NET_WM_STATE_STICKY, _NET_WM_STATE_SKIP_TASKBAR};
|
if (m_bar.width == m_bar.monitor->w) {
|
||||||
|
const uint32_t win_states[3] = {
|
||||||
|
_NET_WM_STATE_STICKY, _NET_WM_STATE_SKIP_TASKBAR, _NET_WM_STATE_MAXIMIZED_VERT};
|
||||||
m_connection.change_property_checked(
|
m_connection.change_property_checked(
|
||||||
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STATE, XCB_ATOM_ATOM, 32, 2, &win_states);
|
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STATE, XCB_ATOM_ATOM, 32, 3, win_states);
|
||||||
|
} else {
|
||||||
|
const uint32_t win_states[2] = {_NET_WM_STATE_STICKY, _NET_WM_STATE_SKIP_TASKBAR};
|
||||||
|
m_connection.change_property_checked(
|
||||||
|
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STATE, XCB_ATOM_ATOM, 32, 2, win_states);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.trace("bar: Set _NET_WM_STRUT");
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
uint32_t none{0};
|
||||||
|
uint32_t value_list[4]{
|
||||||
|
static_cast<uint32_t>(m_bar.x), // left
|
||||||
|
none, // right
|
||||||
|
m_bar.bottom ? none : m_bar.height + m_bar.offset_y, // top
|
||||||
|
m_bar.bottom ? m_bar.height + m_bar.offset_y : none, // bottom
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
m_connection.change_property_checked(
|
||||||
|
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4, value_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.trace("bar: Set _NET_WM_STRUT_PARTIAL");
|
||||||
|
{
|
||||||
|
// clang-format off
|
||||||
|
uint32_t none{0};
|
||||||
|
const uint32_t value_list[12]{
|
||||||
|
static_cast<uint32_t>(m_bar.x), // left
|
||||||
|
none, // right
|
||||||
|
m_bar.bottom ? none : m_bar.height + m_bar.offset_y, // top
|
||||||
|
m_bar.bottom ? m_bar.height + m_bar.offset_y : none, // bottom
|
||||||
|
none, // left_start_y
|
||||||
|
none, // left_end_y
|
||||||
|
none, // right_start_y
|
||||||
|
none, // right_end_y
|
||||||
|
m_bar.bottom ? none : m_bar.x, // top_start_x
|
||||||
|
m_bar.bottom ? none : static_cast<uint32_t>(m_bar.x + m_bar.width), // top_end_x
|
||||||
|
m_bar.bottom ? m_bar.x : none, // bottom_start_x
|
||||||
|
m_bar.bottom ? static_cast<uint32_t>(m_bar.x + m_bar.width) : none, // bottom_end_x
|
||||||
|
};
|
||||||
|
// clang-format on
|
||||||
|
m_connection.change_property_checked(XCB_PROP_MODE_REPLACE, m_window, _NET_WM_STRUT_PARTIAL,
|
||||||
|
XCB_ATOM_CARDINAL, 32, 12, value_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.trace("bar: Set _NET_WM_DESKTOP");
|
||||||
|
{
|
||||||
|
const uint32_t value_list[1]{-1u};
|
||||||
|
m_connection.change_property_checked(
|
||||||
|
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, value_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("bar: Set _NET_WM_PID");
|
m_log.trace("bar: Set _NET_WM_PID");
|
||||||
{
|
{
|
||||||
int pid = getpid();
|
const uint32_t value_list[1]{uint32_t(getpid())};
|
||||||
m_connection.change_property_checked(
|
m_connection.change_property_checked(
|
||||||
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &pid);
|
XCB_PROP_MODE_REPLACE, m_window, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, value_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("bar: Create pixmap");
|
m_log.trace("bar: Create pixmap");
|
||||||
@ -281,14 +335,27 @@ class bar : public xpp::event::sink<evt::button_press> {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
auto wm_restack = m_conf.get<string>(bs, "wm-restack");
|
auto wm_restack = m_conf.get<string>(bs, "wm-restack");
|
||||||
|
auto restacked = false;
|
||||||
|
|
||||||
if (wm_restack == "bspwm") {
|
if (wm_restack == "bspwm") {
|
||||||
if (bspwm_util::restack_above_root(m_connection, m_bar.monitor, m_window))
|
restacked = bspwm_util::restack_above_root(m_connection, m_bar.monitor, m_window);
|
||||||
m_log.info("Successfully restacked window above Bspwm root");
|
|
||||||
else
|
} else if (wm_restack == "i3" && m_bar.dock) {
|
||||||
m_log.err("Failed to restack bar window above Bspwm root");
|
restacked = i3_util::restack_above_root(m_connection, m_bar.monitor, m_window);
|
||||||
|
|
||||||
|
} else if (wm_restack == "i3" && !m_bar.dock) {
|
||||||
|
m_log.warn("Ignoring restack of i3 window (not needed when dock = false)");
|
||||||
|
wm_restack.clear();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
m_log.warn("Unsupported wm-restack option '%s'", wm_restack);
|
m_log.warn("Ignoring unsupported wm-restack option '%s'", wm_restack);
|
||||||
|
wm_restack.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (restacked) {
|
||||||
|
m_log.info("Successfully restacked bar window");
|
||||||
|
} else if (!wm_restack.empty()) {
|
||||||
|
m_log.err("Failed to restack bar window");
|
||||||
}
|
}
|
||||||
} catch (const key_error& err) {
|
} catch (const key_error& err) {
|
||||||
}
|
}
|
||||||
@ -296,13 +363,6 @@ class bar : public xpp::event::sink<evt::button_press> {
|
|||||||
// }}}
|
// }}}
|
||||||
// Create graphic contexts {{{
|
// Create graphic contexts {{{
|
||||||
|
|
||||||
// XCB_GC_LINE_WIDTH
|
|
||||||
// XCB_GC_LINE_STYLE
|
|
||||||
// -- XCB_LINE_STYLE_SOLID
|
|
||||||
// xcb_poly_line (connection, XCB_COORD_MODE_PREVIOUS, window, foreground, 4, polyline);
|
|
||||||
// xcb_poly_line(conn, XCB_COORD_MODE_ORIGIN, drawable, gc, 2, (xcb_point_t[]) { {10, 10}, {100,
|
|
||||||
// 10} });
|
|
||||||
|
|
||||||
m_log.trace("bar: Create graphic contexts");
|
m_log.trace("bar: Create graphic contexts");
|
||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@ -598,6 +658,16 @@ class bar : public xpp::event::sink<evt::button_press> {
|
|||||||
}
|
}
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for XCB_EXPOSE events
|
||||||
|
*/
|
||||||
|
void handle(const evt::expose& evt) { // {{{
|
||||||
|
if (evt->window != m_window)
|
||||||
|
return;
|
||||||
|
m_log.trace("bar: Received expose event");
|
||||||
|
flush();
|
||||||
|
} // }}}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Handle alignment update
|
* Handle alignment update
|
||||||
|
@ -10,6 +10,7 @@ struct cached_atom {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static xcb_atom_t _NET_WM_NAME;
|
static xcb_atom_t _NET_WM_NAME;
|
||||||
|
static xcb_atom_t _NET_WM_DESKTOP;
|
||||||
static xcb_atom_t _NET_WM_WINDOW_TYPE;
|
static xcb_atom_t _NET_WM_WINDOW_TYPE;
|
||||||
static xcb_atom_t _NET_WM_WINDOW_TYPE_DOCK;
|
static xcb_atom_t _NET_WM_WINDOW_TYPE_DOCK;
|
||||||
static xcb_atom_t _NET_WM_WINDOW_TYPE_NORMAL;
|
static xcb_atom_t _NET_WM_WINDOW_TYPE_NORMAL;
|
||||||
@ -18,6 +19,9 @@ static xcb_atom_t _NET_WM_STATE;
|
|||||||
static xcb_atom_t _NET_WM_STATE_STICKY;
|
static xcb_atom_t _NET_WM_STATE_STICKY;
|
||||||
static xcb_atom_t _NET_WM_STATE_SKIP_TASKBAR;
|
static xcb_atom_t _NET_WM_STATE_SKIP_TASKBAR;
|
||||||
static xcb_atom_t _NET_WM_STATE_ABOVE;
|
static xcb_atom_t _NET_WM_STATE_ABOVE;
|
||||||
|
static xcb_atom_t _NET_WM_STATE_MAXIMIZED_VERT;
|
||||||
|
static xcb_atom_t _NET_WM_STRUT;
|
||||||
|
static xcb_atom_t _NET_WM_STRUT_PARTIAL;
|
||||||
static xcb_atom_t WM_PROTOCOLS;
|
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;
|
||||||
@ -29,8 +33,9 @@ static xcb_atom_t _NET_SYSTEM_TRAY_ORIENTATION;
|
|||||||
static xcb_atom_t WM_TAKE_FOCUS;
|
static xcb_atom_t WM_TAKE_FOCUS;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static cached_atom ATOMS[18] = {
|
static cached_atom ATOMS[22] = {
|
||||||
{"_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_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},
|
||||||
{"_NET_WM_WINDOW_TYPE_DOCK", sizeof("_NET_WM_WINDOW_TYPE_DOCK") - 1, &_NET_WM_WINDOW_TYPE_DOCK},
|
{"_NET_WM_WINDOW_TYPE_DOCK", sizeof("_NET_WM_WINDOW_TYPE_DOCK") - 1, &_NET_WM_WINDOW_TYPE_DOCK},
|
||||||
{"_NET_WM_WINDOW_TYPE_NORMAL", sizeof("_NET_WM_WINDOW_TYPE_NORMAL") - 1, &_NET_WM_WINDOW_TYPE_NORMAL},
|
{"_NET_WM_WINDOW_TYPE_NORMAL", sizeof("_NET_WM_WINDOW_TYPE_NORMAL") - 1, &_NET_WM_WINDOW_TYPE_NORMAL},
|
||||||
@ -39,6 +44,9 @@ static cached_atom ATOMS[18] = {
|
|||||||
{"_NET_WM_STATE_STICKY", sizeof("_NET_WM_STATE_STICKY") - 1, &_NET_WM_STATE_STICKY},
|
{"_NET_WM_STATE_STICKY", sizeof("_NET_WM_STATE_STICKY") - 1, &_NET_WM_STATE_STICKY},
|
||||||
{"_NET_WM_STATE_SKIP_TASKBAR", sizeof("_NET_WM_STATE_SKIP_TASKBAR") - 1, &_NET_WM_STATE_SKIP_TASKBAR},
|
{"_NET_WM_STATE_SKIP_TASKBAR", sizeof("_NET_WM_STATE_SKIP_TASKBAR") - 1, &_NET_WM_STATE_SKIP_TASKBAR},
|
||||||
{"_NET_WM_STATE_ABOVE", sizeof("_NET_WM_STATE_ABOVE") - 1, &_NET_WM_STATE_ABOVE},
|
{"_NET_WM_STATE_ABOVE", sizeof("_NET_WM_STATE_ABOVE") - 1, &_NET_WM_STATE_ABOVE},
|
||||||
|
{"_NET_WM_STATE_MAXIMIZED_VERT", sizeof("_NET_WM_STATE_MAXIMIZED_VERT") - 1, &_NET_WM_STATE_MAXIMIZED_VERT},
|
||||||
|
{"_NET_WM_STRUT", sizeof("_NET_WM_STRUT") - 1, &_NET_WM_STRUT},
|
||||||
|
{"_NET_WM_STRUT_PARTIAL", sizeof("_NET_WM_STRUT_PARTIAL") - 1, &_NET_WM_STRUT_PARTIAL},
|
||||||
{"WM_PROTOCOLS", sizeof("WM_PROTOCOLS") - 1, &WM_PROTOCOLS},
|
{"WM_PROTOCOLS", sizeof("WM_PROTOCOLS") - 1, &WM_PROTOCOLS},
|
||||||
{"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},
|
||||||
|
@ -275,8 +275,8 @@ class traymanager
|
|||||||
m_logger.trace("tray: Create tray window %s, (%ix%i+%i+%i)", m_connection.id(m_tray),
|
m_logger.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, x, y);
|
||||||
auto scr = m_connection.screen();
|
auto scr = m_connection.screen();
|
||||||
const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
|
||||||
const uint32_t values[2]{m_settings.background,
|
const uint32_t values[3]{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 + m_settings.spacing * 2, 0,
|
||||||
|
@ -137,10 +137,12 @@ class window : public xpp::window<connection_t&> {
|
|||||||
//
|
//
|
||||||
// window operator<<(cw_flush f) {
|
// window operator<<(cw_flush f) {
|
||||||
// if (f.checked)
|
// if (f.checked)
|
||||||
// m_connection.create_window_checked(m_depth, m_window, m_parent, m_x, m_y, m_width, m_height,
|
// m_connection.create_window_checked(m_depth, m_window, m_parent, m_x, m_y, m_width,
|
||||||
|
// m_height,
|
||||||
// m_border, m_class, m_visual, m_mask, m_params);
|
// m_border, m_class, m_visual, m_mask, m_params);
|
||||||
// else
|
// else
|
||||||
// m_connection.create_window(m_depth, m_window, m_parent, m_x, m_y, m_width, m_height, m_border,
|
// m_connection.create_window(m_depth, m_window, m_parent, m_x, m_y, m_width, m_height,
|
||||||
|
// m_border,
|
||||||
// m_class, m_visual, m_mask, m_params);
|
// m_class, m_visual, m_mask, m_params);
|
||||||
// return m_window;
|
// return m_window;
|
||||||
// }
|
// }
|
||||||
|
60
include/utils/i3.hpp
Normal file
60
include/utils/i3.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "components/x11/connection.hpp"
|
||||||
|
#include "components/x11/randr.hpp"
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "utils/socket.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
LEMONBUDDY_NS
|
||||||
|
|
||||||
|
namespace i3_util {
|
||||||
|
/**
|
||||||
|
* Get all i3 root windows
|
||||||
|
*/
|
||||||
|
auto root_windows(connection& conn, string output_name = "") {
|
||||||
|
vector<xcb_window_t> roots;
|
||||||
|
auto children = conn.query_tree(conn.screen()->root).children();
|
||||||
|
|
||||||
|
for (auto it = children.begin(); it != children.end(); it++) {
|
||||||
|
auto cookie = xcb_icccm_get_wm_name(conn, *it);
|
||||||
|
xcb_icccm_get_text_property_reply_t reply;
|
||||||
|
|
||||||
|
if (xcb_icccm_get_wm_name_reply(conn, cookie, &reply, nullptr) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (("[i3 con] output " + output_name).compare(0, 16 + output_name.length(), reply.name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
roots.emplace_back(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restack given window above the i3 root window
|
||||||
|
* defined for the given monitor
|
||||||
|
*
|
||||||
|
* Fixes the issue with always-on-top window's
|
||||||
|
*/
|
||||||
|
bool restack_above_root(connection& conn, const monitor_t& mon, const xcb_window_t win) {
|
||||||
|
for (auto&& root : root_windows(conn, mon->name)) {
|
||||||
|
const uint32_t value_mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
|
||||||
|
const uint32_t value_list[2]{root, XCB_STACK_MODE_ABOVE};
|
||||||
|
|
||||||
|
conn.configure_window_checked(win, value_mask, value_list);
|
||||||
|
conn.flush();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LEMONBUDDY_NS_END
|
@ -8,8 +8,6 @@
|
|||||||
#include "components/logger.hpp"
|
#include "components/logger.hpp"
|
||||||
#include "components/x11/xutils.hpp"
|
#include "components/x11/xutils.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "utils/bspwm.hpp"
|
|
||||||
#include "utils/file.hpp"
|
|
||||||
#include "utils/inotify.hpp"
|
#include "utils/inotify.hpp"
|
||||||
|
|
||||||
using namespace lemonbuddy;
|
using namespace lemonbuddy;
|
||||||
|
Loading…
Reference in New Issue
Block a user