1
0
Fork 0
mirror of https://github.com/polybar/polybar.git synced 2024-11-25 13:55:47 -05:00

refactor(x11): Cleanup

This commit is contained in:
Michael Carlberg 2017-01-24 08:49:27 +01:00
parent a5d6670121
commit 6692b4a8da
40 changed files with 344 additions and 638 deletions

View file

@ -13,15 +13,14 @@ addons:
- llvm-toolchain-precise-3.8
- sourceline: "ppa:george-edison55/george-edison"
packages:
- gcc-5
- g++-5
- clang-3.8
- cmake
- cmake-data
- g++-5
- gcc-5
- i3-wm
- libasound2-dev
- libboost-dev
- libfreetype6-dev
- libcairo2-dev
- libiw-dev
- libmpdclient-dev
- libxcb-ewmh-dev

View file

@ -68,8 +68,8 @@ A [pull-request has been submitted](https://github.com/voidlinux/void-packages/p
### Dependencies
A compiler with C++14 support ([clang-3.4+](http://llvm.org/releases/download.html), [gcc-5.1+](https://gcc.gnu.org/releases.html)).
- cmake
- libXft
- cairo
- libxcb
- python2
- xcb-proto
- xcb-util-image
@ -77,11 +77,11 @@ A compiler with C++14 support ([clang-3.4+](http://llvm.org/releases/download.ht
- xcb-util-xrm
Optional dependencies for extended module support:
- alsa-lib (required by `internal/volume`)
- jsoncpp (required by `internal/i3`)
- libmpdclient (required by `internal/mpd`)
- libcurl (required by `internal/github`)
- wireless_tools (required by `internal/network`)
- alsa-lib *required by `internal/volume`*
- jsoncpp *required by `internal/i3`*
- libmpdclient *required by `internal/mpd`*
- libcurl *required by `internal/github`*
- wireless_tools *required by `internal/network`*
Find a more complete list on the [dedicated wiki page](https://github.com/jaagr/polybar/wiki/Compiling).
@ -119,10 +119,6 @@ Details on how to setup and configure the bar and each module have been moved to
$ polybar example
~~~
**NOTE:** If the bar output looks odd, it's probably because you're
missing the fonts defined in the config. Update the config or install the
missing fonts.
### Running

View file

@ -66,12 +66,12 @@ option(ENABLE_I3 "Enable i3 support" ON)
option(ENABLE_MPD "Enable mpd support" ON)
option(ENABLE_NETWORK "Enable network support" ON)
option(WITH_XRANDR "XRANDR support" ON)
option(WITH_XRENDER "XRENDER support" OFF)
option(WITH_XDAMAGE "XDAMAGE support" OFF)
option(WITH_XSYNC "XSYNC support" OFF)
option(WITH_XCOMPOSITE "XCOMPOSITE support" OFF)
option(WITH_XKB "XKB support" ON)
option(WITH_XRANDR "xcb-randr support" ON)
option(WITH_XRENDER "xcb-render support" OFF)
option(WITH_XDAMAGE "xcb-damage support" OFF)
option(WITH_XSYNC "xcb-sync support" OFF)
option(WITH_XCOMPOSITE "xcb-composite support" OFF)
option(WITH_XKB "xcb-xkb support" ON)
option(WITH_XRM "xcb-xrm support" ON)
if(NOT DEFINED WITH_XRM)

View file

@ -62,14 +62,14 @@ colored_option(STATUS " i3" ENABLE_I3 "32;1" "37;2")
colored_option(STATUS " mpd" ENABLE_MPD "32;1" "37;2")
colored_option(STATUS " network" ENABLE_NETWORK "32;1" "37;2")
message(STATUS " X extensions:")
colored_option(STATUS " XRandR" WITH_XRANDR "32;1" "37;2")
colored_option(STATUS " XRandR (enable monitors)" ENABLE_XRANDR_MONITORS "32;1" "37;2")
colored_option(STATUS " XRender" WITH_XRENDER "32;1" "37;2")
colored_option(STATUS " XDamage" WITH_XDAMAGE "32;1" "37;2")
colored_option(STATUS " XSync" WITH_XSYNC "32;1" "37;2")
colored_option(STATUS " XComposite" WITH_XCOMPOSITE "32;1" "37;2")
colored_option(STATUS " Xkb" WITH_XKB "32;1" "37;2")
colored_option(STATUS " Xrm" WITH_XRM "32;1" "37;2")
colored_option(STATUS " xcb-randr" WITH_XRANDR "32;1" "37;2")
colored_option(STATUS " xcb-randr (monitor support)" ENABLE_XRANDR_MONITORS "32;1" "37;2")
colored_option(STATUS " xcb-render" WITH_XRENDER "32;1" "37;2")
colored_option(STATUS " xcb-damage" WITH_XDAMAGE "32;1" "37;2")
colored_option(STATUS " xcb-sync" WITH_XSYNC "32;1" "37;2")
colored_option(STATUS " xcb-composite" WITH_XCOMPOSITE "32;1" "37;2")
colored_option(STATUS " xcb-xkb" WITH_XKB "32;1" "37;2")
colored_option(STATUS " xcb-xrm" WITH_XRM "32;1" "37;2")
if(CMAKE_BUILD_TYPE_LOWER STREQUAL "debug")
message(STATUS " Debug options:")

View file

@ -9,7 +9,6 @@
#include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp"
#include "settings.hpp"
#include "x11/events.hpp"
#include "x11/types.hpp"
#include "x11/window.hpp"

View file

@ -9,7 +9,6 @@
#include "events/signal_receiver.hpp"
#include "events/types.hpp"
#include "utils/file.hpp"
#include "x11/events.hpp"
#include "x11/types.hpp"
POLYBAR_NS

View file

@ -4,7 +4,6 @@
#include "components/types.hpp"
#include "events/signal_emitter.hpp"
#include "events/signal_fwd.hpp"
#include "x11/events.hpp"
#include "x11/extensions/randr.hpp"
#include "x11/types.hpp"
#include "x11/window.hpp"

View file

@ -6,7 +6,6 @@
#include "modules/meta/event_handler.hpp"
#include "modules/meta/input_handler.hpp"
#include "modules/meta/static_module.hpp"
#include "x11/events.hpp"
#include "x11/extensions/xkb.hpp"
#include "x11/window.hpp"

View file

@ -2,7 +2,6 @@
#include "modules/meta/event_handler.hpp"
#include "modules/meta/static_module.hpp"
#include "x11/events.hpp"
#include "x11/ewmh.hpp"
#include "x11/icccm.hpp"
#include "x11/window.hpp"
@ -18,7 +17,7 @@ namespace modules {
~active_window();
bool match(const xcb_window_t win) const;
string title(xcb_ewmh_connection_t* ewmh) const;
string title() const;
private:
xcb_connection_t* m_connection{nullptr};
@ -43,7 +42,6 @@ namespace modules {
static constexpr const char* TAG_LABEL{"<label>"};
connection& m_connection;
ewmh_connection_t m_ewmh;
unique_ptr<active_window> m_active;
label_t m_label;
};

View file

@ -7,7 +7,6 @@
#include "modules/meta/event_handler.hpp"
#include "modules/meta/input_handler.hpp"
#include "modules/meta/static_module.hpp"
#include "x11/events.hpp"
#include "x11/ewmh.hpp"
#include "x11/icccm.hpp"
#include "x11/window.hpp"

View file

@ -102,7 +102,7 @@ const auto print_build_info = [](bool extended = false) {
(ENABLE_NETWORK ? '+' : '-'));
if (extended) {
printf("\n");
printf("X extensions: %cxrandr (%cmonitors) %cxrender %cxdamage %cxsync %cxcomposite %cxkb %cxcb-util-xrm\n",
printf("X extensions: %crandr (%cmonitors) %crender %cdamage %csync %ccomposite %cxkb %cxrm\n",
(WITH_XRANDR ? '+' : '-'),
(ENABLE_XRANDR_MONITORS ? '+' : '-'),
(WITH_XRENDER ? '+' : '-'),

View file

@ -1,16 +1,12 @@
#pragma once
#include <X11/X.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xutil.h>
#include <cstdlib>
#include <xcb/xcb.h>
#include <xpp/core.hpp>
#include <xpp/generic/factory.hpp>
#include <xpp/proto/x.hpp>
#include "common.hpp"
#include "components/screen.hpp"
#include "x11/events.hpp"
#include "x11/extensions/all.hpp"
#include "x11/registry.hpp"
#include "x11/types.hpp"
@ -18,19 +14,6 @@
POLYBAR_NS
namespace detail {
class displaylock {
public:
explicit displaylock(Display* display) : m_display(forward<decltype(display)>(display)) {
XLockDisplay(m_display);
}
~displaylock() {
XUnlockDisplay(m_display);
}
protected:
Display* m_display;
};
template <typename Connection, typename... Extensions>
class interfaces : public xpp::x::extension::interface<interfaces<Connection, Extensions...>, Connection>,
public Extensions::template interface<interfaces<Connection, Extensions...>, Connection>... {
@ -49,12 +32,12 @@ namespace detail {
private Extensions...,
private Extensions::error_dispatcher... {
public:
template <typename... Args>
explicit connection_base(Args&&... args)
: xpp::core(forward<Args>(args)...)
explicit connection_base(xcb_connection_t* c, int s)
: xpp::core(c)
, interfaces<connection_base<Derived, Extensions...>, Extensions...>(*this)
, Extensions(m_c.get())...
, Extensions::error_dispatcher(static_cast<Extensions&>(*this).get())... {
core::m_screen = s;
m_root_window = screen_of_display(default_screen())->root;
}
@ -116,9 +99,9 @@ class connection : public detail::connection_base<connection&, XPP_EXTENSION_LIS
using base_type = detail::connection_base<connection&, XPP_EXTENSION_LIST>;
using make_type = connection&;
static make_type make(Display* display = nullptr);
static make_type make(xcb_connection_t* conn = nullptr, int default_screen = 0);
explicit connection(Display* dsp);
explicit connection(xcb_connection_t* c, int default_screen);
~connection();
const connection& operator=(const connection& o) {
@ -130,8 +113,6 @@ class connection : public detail::connection_base<connection&, XPP_EXTENSION_LIS
static void pack_values(unsigned int mask, const xcb_params_gc_t* src, unsigned int* dest);
static void pack_values(unsigned int mask, const xcb_params_configure_window_t* src, unsigned int* dest);
operator Display*() const;
Visual* visual(unsigned char depth = 32U);
xcb_screen_t* screen(bool realloc = false);
string id(xcb_window_t w) const;
@ -145,6 +126,8 @@ class connection : public detail::connection_base<connection&, XPP_EXTENSION_LIS
xcb_visualtype_t* visual_type(xcb_screen_t* screen, int match_depth = 32);
bool root_pixmap(xcb_pixmap_t* pixmap, int* depth, xcb_rectangle_t* rect);
static string error_str(int error_code);
void dispatch_event(const shared_ptr<xcb_generic_event_t>& evt) const;
@ -181,8 +164,6 @@ class connection : public detail::connection_base<connection&, XPP_EXTENSION_LIS
}
protected:
Display* m_display{nullptr};
map<unsigned char, Visual*> m_visual;
registry m_registry{*this};
xcb_screen_t* m_screen{nullptr};
};

View file

@ -1,59 +0,0 @@
#pragma once
#include <xpp/event.hpp>
#include "common.hpp"
POLYBAR_NS
class connection;
namespace evt {
// window focus events
using focus_in = xpp::x::event::focus_in<connection&>;
using focus_out = xpp::x::event::focus_out<connection&>;
// cursor events
using enter_notify = xpp::x::event::enter_notify<connection&>;
using leave_notify = xpp::x::event::leave_notify<connection&>;
using motion_notify = xpp::x::event::motion_notify<connection&>;
// keyboard events
using button_press = xpp::x::event::button_press<connection&>;
using button_release = xpp::x::event::button_release<connection&>;
using key_press = xpp::x::event::key_press<connection&>;
using key_release = xpp::x::event::key_release<connection&>;
using keymap_notify = xpp::x::event::keymap_notify<connection&>;
// render events
using circulate_notify = xpp::x::event::circulate_notify<connection&>;
using circulate_request = xpp::x::event::circulate_request<connection&>;
using colormap_notify = xpp::x::event::colormap_notify<connection&>;
using configure_notify = xpp::x::event::configure_notify<connection&>;
using configure_request = xpp::x::event::configure_request<connection&>;
using create_notify = xpp::x::event::create_notify<connection&>;
using destroy_notify = xpp::x::event::destroy_notify<connection&>;
using expose = xpp::x::event::expose<connection&>;
using graphics_exposure = xpp::x::event::graphics_exposure<connection&>;
using gravity_notify = xpp::x::event::gravity_notify<connection&>;
using map_notify = xpp::x::event::map_notify<connection&>;
using map_request = xpp::x::event::map_request<connection&>;
using mapping_notify = xpp::x::event::mapping_notify<connection&>;
using no_exposure = xpp::x::event::no_exposure<connection&>;
using reparent_notify = xpp::x::event::reparent_notify<connection&>;
using resize_request = xpp::x::event::resize_request<connection&>;
using unmap_notify = xpp::x::event::unmap_notify<connection&>;
using visibility_notify = xpp::x::event::visibility_notify<connection&>;
// data events
using client_message = xpp::x::event::client_message<connection&>;
using ge_generic = xpp::x::event::ge_generic<connection&>;
using property_notify = xpp::x::event::property_notify<connection&>;
// selection events
using selection_clear = xpp::x::event::selection_clear<connection&>;
using selection_notify = xpp::x::event::selection_notify<connection&>;
using selection_request = xpp::x::event::selection_request<connection&>;
}
POLYBAR_NS_END

View file

@ -14,19 +14,26 @@ using ewmh_connection_t = malloc_ptr_t<xcb_ewmh_connection_t>;
namespace ewmh_util {
ewmh_connection_t initialize();
bool supports(xcb_ewmh_connection_t* ewmh, xcb_atom_t atom, int screen = 0);
bool supports(xcb_atom_t atom, int screen = 0);
string get_wm_name(xcb_ewmh_connection_t* conn, xcb_window_t win);
string get_visible_name(xcb_ewmh_connection_t* conn, xcb_window_t win);
string get_icon_name(xcb_ewmh_connection_t* conn, xcb_window_t win);
string get_wm_name(xcb_window_t win);
string get_visible_name(xcb_window_t win);
string get_icon_name(xcb_window_t win);
string get_reply_string(xcb_ewmh_get_utf8_strings_reply_t* reply);
vector<position> get_desktop_viewports(xcb_ewmh_connection_t* conn, int screen = 0);
vector<string> get_desktop_names(xcb_ewmh_connection_t* conn, int screen = 0);
unsigned int get_current_desktop(xcb_ewmh_connection_t* conn, int screen = 0);
xcb_window_t get_active_window(xcb_ewmh_connection_t* conn, int screen = 0);
vector<position> get_desktop_viewports(int screen = 0);
vector<string> get_desktop_names(int screen = 0);
unsigned int get_current_desktop(int screen = 0);
xcb_window_t get_active_window(int screen = 0);
void change_current_desktop(xcb_ewmh_connection_t* conn, unsigned int desktop);
void change_current_desktop(unsigned int desktop);
void set_wm_window_type(xcb_window_t win, vector<xcb_atom_t> types);
void set_wm_state(xcb_window_t win, vector<xcb_atom_t> states);
void set_wm_pid(xcb_window_t win);
void set_wm_pid(xcb_window_t win, unsigned int pid);
void set_wm_desktop(xcb_window_t win, unsigned int desktop = -1u);
void set_wm_window_opacity(xcb_window_t win, unsigned long int values);
}
POLYBAR_NS_END

View file

@ -1,24 +0,0 @@
#pragma once
#include <xcb/xcb.h>
#include "common.hpp"
POLYBAR_NS
namespace {
inline bool operator==(const xcb_rectangle_t& a, const xcb_rectangle_t& b) {
return a.width == b.width && a.height == b.height && a.x == b.x && a.y == b.y;
}
inline bool operator!=(const xcb_rectangle_t& a, const xcb_rectangle_t& b) {
return !(a == b);
}
inline bool operator==(const xcb_rectangle_t& a, int b) {
return a.width == b && a.height == b && a.x == b && a.y == b;
}
inline bool operator!=(const xcb_rectangle_t& a, int b) {
return !(a == b);
}
}
POLYBAR_NS_END

View file

@ -1,29 +0,0 @@
#pragma once
#include <xcb/xcb.h>
#include "common.hpp"
#include "x11/connection.hpp"
POLYBAR_NS
namespace graphics_util {
struct root_pixmap {
unsigned char depth{0};
unsigned short int width{0};
unsigned short int height{0};
short int x{0};
short int y{0};
xcb_pixmap_t pixmap{0};
};
bool create_window(connection& conn, xcb_window_t* win, short int x = 0, short int y = 0, unsigned short int w = 1, unsigned short int h = 1,
xcb_window_t root = 0);
bool create_pixmap(connection& conn, xcb_drawable_t dst, unsigned short int w, unsigned short int h, xcb_pixmap_t* pixmap);
bool create_pixmap(connection& conn, xcb_drawable_t dst, unsigned short int w, unsigned short int h, unsigned char d, xcb_pixmap_t* pixmap);
bool create_gc(connection& conn, xcb_drawable_t drawable, xcb_gcontext_t* gc);
bool get_root_pixmap(connection& conn, root_pixmap* rpix);
}
POLYBAR_NS_END

View file

@ -7,8 +7,11 @@
POLYBAR_NS
namespace icccm_util {
string get_wm_name(xcb_connection_t* conn, xcb_window_t win);
string get_wm_name(xcb_connection_t* c, xcb_window_t w);
string get_reply_string(xcb_icccm_get_text_property_reply_t* reply);
void set_wm_name(xcb_connection_t* c, xcb_window_t w, const char* wmname, size_t l, const char* wmclass, size_t l2);
void set_wm_protocols(xcb_connection_t* c, xcb_window_t w, vector<xcb_atom_t> flags);
}
POLYBAR_NS_END

View file

@ -1,18 +1,15 @@
#pragma once
#include <xcb/xcb.h>
#include <chrono>
#include "common.hpp"
#include "components/logger.hpp"
#include "components/types.hpp"
#include "events/signal_emitter.hpp"
#include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp"
#include "utils/concurrency.hpp"
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/events.hpp"
#include "x11/graphics.hpp"
#include "x11/tray_client.hpp"
#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
@ -142,7 +139,11 @@ class tray_manager : public xpp::event::sink<evt::expose, evt::visibility_notify
xcb_gcontext_t m_gc{0};
xcb_pixmap_t m_pixmap{0};
graphics_util::root_pixmap m_rootpixmap{};
xcb_pixmap_t m_rootpixmap{0};
int m_rootpixmap_depth{0};
xcb_rectangle_t m_rootpixmap_geom{0, 0, 0U, 0U};
unsigned int m_prevwidth{0};
unsigned int m_prevheight{0};

View file

@ -1,5 +1,7 @@
#pragma once
#include <xpp/event.hpp>
#include "common.hpp"
namespace xpp {
@ -36,4 +38,47 @@ using atom = xpp::atom<connection&>;
using font = xpp::font<connection&>;
using cursor = xpp::cursor<connection&>;
namespace evt {
// window focus events
using focus_in = xpp::x::event::focus_in<connection&>;
using focus_out = xpp::x::event::focus_out<connection&>;
// cursor events
using enter_notify = xpp::x::event::enter_notify<connection&>;
using leave_notify = xpp::x::event::leave_notify<connection&>;
using motion_notify = xpp::x::event::motion_notify<connection&>;
// keyboard events
using button_press = xpp::x::event::button_press<connection&>;
using button_release = xpp::x::event::button_release<connection&>;
using key_press = xpp::x::event::key_press<connection&>;
using key_release = xpp::x::event::key_release<connection&>;
using keymap_notify = xpp::x::event::keymap_notify<connection&>;
// render events
using circulate_notify = xpp::x::event::circulate_notify<connection&>;
using circulate_request = xpp::x::event::circulate_request<connection&>;
using colormap_notify = xpp::x::event::colormap_notify<connection&>;
using configure_notify = xpp::x::event::configure_notify<connection&>;
using configure_request = xpp::x::event::configure_request<connection&>;
using create_notify = xpp::x::event::create_notify<connection&>;
using destroy_notify = xpp::x::event::destroy_notify<connection&>;
using expose = xpp::x::event::expose<connection&>;
using graphics_exposure = xpp::x::event::graphics_exposure<connection&>;
using gravity_notify = xpp::x::event::gravity_notify<connection&>;
using map_notify = xpp::x::event::map_notify<connection&>;
using map_request = xpp::x::event::map_request<connection&>;
using mapping_notify = xpp::x::event::mapping_notify<connection&>;
using no_exposure = xpp::x::event::no_exposure<connection&>;
using reparent_notify = xpp::x::event::reparent_notify<connection&>;
using resize_request = xpp::x::event::resize_request<connection&>;
using unmap_notify = xpp::x::event::unmap_notify<connection&>;
using visibility_notify = xpp::x::event::visibility_notify<connection&>;
// data events
using client_message = xpp::x::event::client_message<connection&>;
using ge_generic = xpp::x::event::ge_generic<connection&>;
using property_notify = xpp::x::event::property_notify<connection&>;
// selection events
using selection_clear = xpp::x::event::selection_clear<connection&>;
using selection_notify = xpp::x::event::selection_notify<connection&>;
using selection_request = xpp::x::event::selection_request<connection&>;
}
POLYBAR_NS_END

View file

@ -16,19 +16,9 @@ class window : public xpp::window<connection&> {
window& operator=(const xcb_window_t win);
window create_checked(
short int x, short int y, unsigned short int w, unsigned short int h, unsigned int mask = 0, const xcb_params_cw_t* p = nullptr);
window change_event_mask(unsigned int mask);
window ensure_event_mask(unsigned int event);
window reconfigure_geom(unsigned short int w, unsigned short int h, short int x = 0, short int y = 0);
window reconfigure_pos(short int x, short int y);
window reconfigure_struts(unsigned short int w, unsigned short int h, short int x, bool bottom = false);
void redraw();
void visibility_notify(xcb_visibility_t state);
};
POLYBAR_NS_END

View file

@ -1,19 +0,0 @@
#pragma once
#include <xcb/xcb.h>
#include "common.hpp"
POLYBAR_NS
namespace wm_util {
void set_wm_name(xcb_connection_t* conn, xcb_window_t win, const string& wm_name, const string& wm_class);
void set_wm_protocols(xcb_connection_t* conn, xcb_window_t win, vector<xcb_atom_t> flags);
void set_wm_window_type(xcb_connection_t* conn, xcb_window_t win, vector<xcb_atom_t> types);
void set_wm_state(xcb_connection_t* conn, xcb_window_t win, vector<xcb_atom_t> states);
void set_wm_pid(xcb_connection_t* conn, xcb_window_t win, pid_t pid);
void set_wm_desktop(xcb_connection_t* conn, xcb_window_t win, unsigned int desktop = -1u);
void set_wm_window_opacity(xcb_connection_t* conn, xcb_window_t win, unsigned long int values);
}
POLYBAR_NS_END

View file

@ -1,7 +1,5 @@
#pragma once
#include <xcb/xcb.h>
#include "common.hpp"
#include "x11/connection.hpp"

View file

@ -10,18 +10,14 @@ list(REMOVE_ITEM SOURCES ipc.cpp)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(PkgConfig)
find_package(Threads REQUIRED)
find_package(X11_XCB REQUIRED)
pkg_check_modules(CAIRO REQUIRED cairo-fc)
# pkg_check_modules(PANGOCAIRO REQUIRED pangocairo)
set(APP_LIBRARIES ${APP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
# set(APP_LIBRARIES ${APP_LIBRARIES} ${PANGOCAIRO_LIBRARIES})
set(APP_LIBRARIES ${APP_LIBRARIES} ${CAIRO_LIBRARIES})
set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/include)
set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/lib/concurrentqueue/include)
set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR})
# set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${PANGOCAIRO_INCLUDE_DIRS})
set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${CAIRO_INCLUDE_DIRS})
# xpp library
@ -147,9 +143,7 @@ make_executable(${PROJECT_NAME} SOURCES
target_link_libraries(${PROJECT_NAME} Threads::Threads)
target_compile_options(${PROJECT_NAME} PUBLIC
$<$<CXX_COMPILER_ID:GNU>:$<$<CONFIG:MinSizeRel>:-flto>>
${X11_XCB_DEFINITIONS}
${XCB_DEFINITIONS})
$<$<CXX_COMPILER_ID:GNU>:$<$<CONFIG:MinSizeRel>:-flto>>)
# }}}
# Create executable target: ipc messager {{{

View file

@ -1,4 +1,3 @@
#include <xcb/xcb_icccm.h>
#include <algorithm>
#include "components/bar.hpp"
@ -17,9 +16,10 @@
#include "utils/string.hpp"
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/ewmh.hpp"
#include "x11/extensions/all.hpp"
#include "x11/icccm.hpp"
#include "x11/tray_manager.hpp"
#include "x11/wm.hpp"
#if ENABLE_I3
#include "utils/i3.hpp"
@ -28,7 +28,6 @@
POLYBAR_NS
using namespace signals::ui;
using namespace wm_util;
/**
* Create instance
@ -436,21 +435,22 @@ void bar::reconfigure_struts() {
* Reconfigure window wm hint values
*/
void bar::reconfigure_wm_hints() {
const auto& win = m_opts.window;
m_log.trace("bar: Set window WM_NAME");
xcb_icccm_set_wm_name(m_connection, m_opts.window, XCB_ATOM_STRING, 8, m_opts.wmname.size(), m_opts.wmname.c_str());
xcb_icccm_set_wm_class(m_connection, m_opts.window, 15, "polybar\0Polybar");
icccm_util::set_wm_name(m_connection, win, m_opts.wmname.c_str(), m_opts.wmname.size(), "polybar\0Polybar", 15_z);
m_log.trace("bar: Set window _NET_WM_WINDOW_TYPE");
set_wm_window_type(m_connection, m_opts.window, {_NET_WM_WINDOW_TYPE_DOCK});
ewmh_util::set_wm_window_type(win, {_NET_WM_WINDOW_TYPE_DOCK});
m_log.trace("bar: Set window _NET_WM_STATE");
set_wm_state(m_connection, m_opts.window, {_NET_WM_STATE_STICKY, _NET_WM_STATE_ABOVE});
ewmh_util::set_wm_state(win, {_NET_WM_STATE_STICKY, _NET_WM_STATE_ABOVE});
m_log.trace("bar: Set window _NET_WM_DESKTOP");
set_wm_desktop(m_connection, m_opts.window, 0xFFFFFFFF);
ewmh_util::set_wm_desktop(win, 0xFFFFFFFF);
m_log.trace("bar: Set window _NET_WM_PID");
set_wm_pid(m_connection, m_opts.window, getpid());
ewmh_util::set_wm_pid(win);
}
/**
@ -785,8 +785,7 @@ bool bar::on(const signals::ui::tick&) {
bool bar::on(const signals::ui::dim_window& sig) {
m_opts.dimmed = sig.cast() != 1.0;
set_wm_window_opacity(m_connection, m_opts.window, sig.cast() * 0xFFFFFFFF);
m_connection.flush();
ewmh_util::set_wm_window_opacity(m_opts.window, sig.cast() * 0xFFFFFFFF);
return false;
}

View file

@ -9,7 +9,6 @@
#include "components/types.hpp"
#include "events/signal.hpp"
#include "events/signal_emitter.hpp"
#include "events/signal_receiver.hpp"
#include "modules/meta/event_handler.hpp"
#include "modules/meta/factory.hpp"
#include "utils/command.hpp"
@ -18,13 +17,10 @@
#include "utils/string.hpp"
#include "utils/time.hpp"
#include "x11/connection.hpp"
#include "x11/events.hpp"
#include "x11/extensions/all.hpp"
#include "x11/tray_manager.hpp"
#include "x11/types.hpp"
#include <csignal>
POLYBAR_NS
array<int, 2> g_eventpipe{{-1, -1}};

View file

@ -9,7 +9,6 @@
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/extensions/all.hpp"
#include "x11/generic.hpp"
#include "x11/winspec.hpp"
POLYBAR_NS

View file

@ -8,7 +8,6 @@
#include "events/signal.hpp"
#include "events/signal_emitter.hpp"
#include "x11/connection.hpp"
#include "x11/events.hpp"
#include "x11/extensions/all.hpp"
#include "x11/registry.hpp"
#include "x11/types.hpp"

View file

@ -67,15 +67,17 @@ int main(int argc, char** argv) {
//==================================================
// Connect to X server
//==================================================
XInitThreads();
Display* xdisplay{XOpenDisplay(nullptr)};
auto xcb_error = 0;
auto xcb_screen = 0;
auto xcb_connection = xcb_connect(nullptr, &xcb_screen);
if (xdisplay == nullptr) {
logger.err("A connection to X could not be established... ");
return EXIT_FAILURE;
if (xcb_connection == nullptr) {
throw application_error("A connection to X could not be established...");
} else if ((xcb_error = xcb_connection_has_error(xcb_connection))) {
throw application_error("X connection error... (what: " + connection::error_str(xcb_error) + ")");
}
connection& conn{connection::make(xdisplay)};
connection& conn{connection::make(xcb_connection, xcb_screen)};
conn.ensure_event_mask(conn.root(), XCB_EVENT_MASK_PROPERTY_CHANGE);
//==================================================

View file

@ -4,7 +4,7 @@
#include "drawtypes/ramp.hpp"
#include "utils/math.hpp"
#include "x11/connection.hpp"
#include "x11/graphics.hpp"
#include "x11/winspec.hpp"
#include "modules/meta/base.inl"
@ -48,9 +48,12 @@ namespace modules {
}
// Create window that will proxy all RandR notify events
if (!graphics_util::create_window(m_connection, &m_proxy, -1, -1, 1, 1)) {
throw module_error("Failed to create event proxy");
}
// clang-format off
m_proxy = winspec(m_connection)
<< cw_size(1, 1)
<< cw_pos(-1, -1)
<< cw_flush(true);
// clang-format on
// Connect with the event registry and make sure we get
// notified when a RandR output property gets modified

View file

@ -3,7 +3,6 @@
#include "utils/factory.hpp"
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/graphics.hpp"
#include "modules/meta/base.inl"
@ -45,12 +44,12 @@ namespace modules {
* _NET_WM_NAME
* _NET_WM_VISIBLE_NAME
*/
string active_window::title(xcb_ewmh_connection_t* ewmh) const {
string active_window::title() const {
string title;
if (!(title = ewmh_util::get_wm_name(ewmh, m_window)).empty()) {
if (!(title = ewmh_util::get_wm_name(m_window)).empty()) {
return title;
} else if (!(title = ewmh_util::get_visible_name(ewmh, m_window)).empty()) {
} else if (!(title = ewmh_util::get_visible_name(m_window)).empty()) {
return title;
} else if (!(title = icccm_util::get_wm_name(m_connection, m_window)).empty()) {
return title;
@ -65,12 +64,12 @@ namespace modules {
xwindow_module::xwindow_module(const bar_settings& bar, string name_)
: static_module<xwindow_module>(bar, move(name_)), m_connection(connection::make()) {
// Initialize ewmh atoms
if ((m_ewmh = ewmh_util::initialize()) == nullptr) {
if ((ewmh_util::initialize()) == nullptr) {
throw module_error("Failed to initialize ewmh atoms");
}
// Check if the WM supports _NET_ACTIVE_WINDOW
if (!ewmh_util::supports(m_ewmh.get(), _NET_ACTIVE_WINDOW)) {
if (!ewmh_util::supports(_NET_ACTIVE_WINDOW)) {
throw module_error("The WM does not list _NET_ACTIVE_WINDOW as a supported hint");
}
@ -109,13 +108,13 @@ namespace modules {
m_active.reset();
}
if (!m_active && (win = ewmh_util::get_active_window(&*m_ewmh)) != XCB_NONE) {
if (!m_active && (win = ewmh_util::get_active_window()) != XCB_NONE) {
m_active = make_unique<active_window>(m_connection, win);
}
if (m_label) {
m_label->reset_tokens();
m_label->replace_token("%title%", m_active ? m_active->title(&*m_ewmh) : "");
m_label->replace_token("%title%", m_active ? m_active->title() : "");
}
broadcast();

View file

@ -31,12 +31,12 @@ namespace modules {
}
// Check if the WM supports _NET_CURRENT_DESKTOP
if (!ewmh_util::supports(m_ewmh.get(), m_ewmh->_NET_CURRENT_DESKTOP)) {
if (!ewmh_util::supports(m_ewmh->_NET_CURRENT_DESKTOP)) {
throw module_error("The WM does not support _NET_CURRENT_DESKTOP, aborting...");
}
// Check if the WM supports _NET_DESKTOP_VIEWPORT
if (!ewmh_util::supports(m_ewmh.get(), m_ewmh->_NET_DESKTOP_VIEWPORT) && m_pinworkspaces) {
if (!ewmh_util::supports(m_ewmh->_NET_DESKTOP_VIEWPORT) && m_pinworkspaces) {
throw module_error("The WM does not support _NET_DESKTOP_VIEWPORT (required when `pin-workspaces = true`)");
} else if (!m_pinworkspaces) {
m_monitorsupport = false;
@ -96,14 +96,14 @@ namespace modules {
* Fetch and parse data
*/
void xworkspaces_module::update() {
auto current = ewmh_util::get_current_desktop(m_ewmh.get());
auto names = ewmh_util::get_desktop_names(m_ewmh.get());
auto current = ewmh_util::get_current_desktop();
auto names = ewmh_util::get_desktop_names();
vector<position> viewports;
size_t num{0};
position pos{};
if (m_monitorsupport) {
viewports = ewmh_util::get_desktop_viewports(m_ewmh.get());
viewports = ewmh_util::get_desktop_viewports();
num = math_util::min(names.size(), viewports.size());
} else {
num = names.size();
@ -215,7 +215,7 @@ namespace modules {
unsigned int new_desktop{0};
unsigned int min_desktop{0};
unsigned int max_desktop{0};
unsigned int current_desktop{ewmh_util::get_current_desktop(m_ewmh.get())};
unsigned int current_desktop{ewmh_util::get_current_desktop()};
for (auto&& viewport : m_viewports) {
for (auto&& desktop : viewport->desktops) {
@ -245,7 +245,7 @@ namespace modules {
if (new_desktop != current_desktop) {
m_log.info("%s: Requesting change to desktop #%u", name(), new_desktop);
ewmh_util::change_current_desktop(m_ewmh.get(), new_desktop);
ewmh_util::change_current_desktop(new_desktop);
m_connection.flush();
} else {
m_log.info("%s: Ignoring change to current desktop", name());

View file

@ -42,14 +42,12 @@ namespace i3_util {
* Get main root window
*/
xcb_window_t root_window(connection& conn) {
auto ewmh = ewmh_util::initialize();
auto children = conn.query_tree(conn.screen()->root).children();
const auto wm_name = [&](xcb_ewmh_connection_t* ewmh, xcb_window_t win) -> string {
const auto wm_name = [&](xcb_connection_t* conn, xcb_window_t win) -> string {
string title;
if (!(title = ewmh_util::get_wm_name(ewmh, win)).empty()) {
if (!(title = ewmh_util::get_wm_name(win)).empty()) {
return title;
} else if (!(title = icccm_util::get_wm_name(ewmh->connection, win)).empty()) {
} else if (!(title = icccm_util::get_wm_name(conn, win)).empty()) {
return title;
} else {
return "";
@ -57,7 +55,7 @@ namespace i3_util {
};
for (auto it = children.begin(); it != children.end(); it++) {
if (wm_name(&*ewmh, *it) == "i3") {
if (wm_name(conn, *it) == "i3") {
return *it;
}
}

View file

@ -13,14 +13,12 @@ POLYBAR_NS
/**
* Create instance
*/
connection::make_type connection::make(Display* display) {
connection::make_type connection::make(xcb_connection_t* conn, int default_screen) {
return static_cast<connection::make_type>(
*factory_util::singleton<std::remove_reference_t<connection::make_type>>(display));
*factory_util::singleton<std::remove_reference_t<connection::make_type>>(conn, default_screen));
}
connection::connection(Display* dsp) : base_type(XGetXCBConnection(dsp)), m_display(dsp) {
XSetEventQueueOwner(m_display, XCBOwnsEventQueue);
connection::connection(xcb_connection_t* c, int default_screen) : base_type(c, default_screen) {
// Preload required xcb atoms {{{
vector<xcb_intern_atom_cookie_t> cookies(memory_util::countof(ATOMS));
@ -62,13 +60,7 @@ connection::connection(Display* dsp) : base_type(XGetXCBConnection(dsp)), m_disp
}
connection::~connection() {
if (m_display != nullptr) {
XCloseDisplay(m_display);
} else {
disconnect();
std::for_each(m_visual.begin(), m_visual.end(), [=](pair<unsigned char, Visual*> p) { XFree(p.second); });
m_visual.clear();
}
disconnect();
}
void connection::pack_values(unsigned int mask, const unsigned int* src, unsigned int* dest) {
@ -88,21 +80,6 @@ void connection::pack_values(unsigned int mask, const xcb_params_configure_windo
pack_values(mask, reinterpret_cast<const unsigned int*>(src), dest);
}
connection::operator Display*() const {
return m_display;
}
Visual* connection::visual(unsigned char depth) {
auto visual_it = m_visual.find(depth);
if (visual_it == m_visual.end()) {
XVisualInfo info{};
if (XMatchVisualInfo(*this, default_screen(), depth, TrueColor, &info)) {
visual_it = m_visual.emplace_hint(visual_it, depth, info.visual);
}
}
return visual_it->second;
}
/**
* Create X window id string
*/
@ -188,6 +165,38 @@ xcb_visualtype_t* connection::visual_type(xcb_screen_t* screen, int match_depth)
return nullptr;
}
/**
* Query root window pixmap
*/
bool connection::root_pixmap(xcb_pixmap_t* pixmap, int* depth, xcb_rectangle_t* rect) {
const xcb_atom_t pixmap_properties[3]{ESETROOT_PMAP_ID, _XROOTMAP_ID, _XSETROOT_ID};
for (auto&& property : pixmap_properties) {
try {
auto prop = get_property(false, screen()->root, property, XCB_ATOM_PIXMAP, 0L, 1L);
if (prop->format == 32 && prop->value_len == 1) {
*pixmap = *prop.value<xcb_pixmap_t>().begin();
}
} catch (const exception& err) {
continue;
}
}
if (*pixmap) {
try {
auto geom = get_geometry(*pixmap);
*depth = geom->depth;
rect->width = geom->width;
rect->height = geom->height;
rect->x = geom->x;
rect->y = geom->y;
return true;
} catch (const exception& err) {
*pixmap = XCB_NONE;
*rect = xcb_rectangle_t{0, 0, 0U, 0U};
}
}
return false;
}
/**
* Parse connection error
*/

View file

@ -1,6 +1,9 @@
#include "x11/ewmh.hpp"
#include <unistd.h>
#include "components/types.hpp"
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/ewmh.hpp"
POLYBAR_NS
@ -15,31 +18,28 @@ namespace ewmh_util {
return g_connection;
}
bool supports(xcb_ewmh_connection_t* ewmh, xcb_atom_t atom, int screen) {
bool supports(xcb_atom_t atom, int screen) {
auto conn = initialize().get();
bool supports{false};
xcb_ewmh_get_atoms_reply_t reply{};
reply.atoms = nullptr;
if (!xcb_ewmh_get_supported_reply(ewmh, xcb_ewmh_get_supported(ewmh, screen), &reply, nullptr)) {
return false;
}
for (size_t n = 0; n < reply.atoms_len; ++n) {
if (reply.atoms[n] == atom) {
supports = true;
break;
if (xcb_ewmh_get_supported_reply(conn, xcb_ewmh_get_supported(conn, screen), &reply, nullptr)) {
for (size_t n = 0; n < reply.atoms_len; ++n) {
if (reply.atoms[n] == atom) {
supports = true;
break;
}
}
if (reply.atoms != nullptr) {
xcb_ewmh_get_atoms_reply_wipe(&reply);
}
}
if (reply.atoms != nullptr) {
xcb_ewmh_get_atoms_reply_wipe(&reply);
}
return supports;
}
string get_wm_name(xcb_ewmh_connection_t* conn, xcb_window_t win) {
string get_wm_name(xcb_window_t win) {
auto conn = initialize().get();
xcb_ewmh_get_utf8_strings_reply_t utf8_reply{};
if (xcb_ewmh_get_wm_name_reply(conn, xcb_ewmh_get_wm_name(conn, win), &utf8_reply, nullptr)) {
return get_reply_string(&utf8_reply);
@ -47,7 +47,8 @@ namespace ewmh_util {
return "";
}
string get_visible_name(xcb_ewmh_connection_t* conn, xcb_window_t win) {
string get_visible_name(xcb_window_t win) {
auto conn = initialize().get();
xcb_ewmh_get_utf8_strings_reply_t utf8_reply{};
if (xcb_ewmh_get_wm_visible_name_reply(conn, xcb_ewmh_get_wm_visible_name(conn, win), &utf8_reply, nullptr)) {
return get_reply_string(&utf8_reply);
@ -55,7 +56,8 @@ namespace ewmh_util {
return "";
}
string get_icon_name(xcb_ewmh_connection_t* conn, xcb_window_t win) {
string get_icon_name(xcb_window_t win) {
auto conn = initialize().get();
xcb_ewmh_get_utf8_strings_reply_t utf8_reply{};
if (xcb_ewmh_get_wm_icon_name_reply(conn, xcb_ewmh_get_wm_icon_name(conn, win), &utf8_reply, nullptr)) {
return get_reply_string(&utf8_reply);
@ -64,75 +66,103 @@ namespace ewmh_util {
}
string get_reply_string(xcb_ewmh_get_utf8_strings_reply_t* reply) {
if (reply == nullptr) {
return "";
string str;
if (reply) {
str = string(reply->strings, reply->strings_len);
xcb_ewmh_get_utf8_strings_reply_wipe(reply);
}
string str(reply->strings, reply->strings_len);
xcb_ewmh_get_utf8_strings_reply_wipe(reply);
return str;
}
unsigned int get_current_desktop(xcb_ewmh_connection_t* conn, int screen) {
unsigned int desktop{0};
if (xcb_ewmh_get_current_desktop_reply(conn, xcb_ewmh_get_current_desktop(conn, screen), &desktop, nullptr)) {
return desktop;
}
return XCB_NONE;
unsigned int get_current_desktop(int screen) {
auto conn = initialize().get();
unsigned int desktop = XCB_NONE;
xcb_ewmh_get_current_desktop_reply(conn, xcb_ewmh_get_current_desktop(conn, screen), &desktop, nullptr);
return desktop;
}
vector<position> get_desktop_viewports(xcb_ewmh_connection_t* conn, int screen) {
vector<position> get_desktop_viewports(int screen) {
auto conn = initialize().get();
vector<position> viewports;
xcb_ewmh_get_desktop_viewport_reply_t reply{};
if (!xcb_ewmh_get_desktop_viewport_reply(conn, xcb_ewmh_get_desktop_viewport(conn, screen), &reply, nullptr)) {
return viewports;
if (xcb_ewmh_get_desktop_viewport_reply(conn, xcb_ewmh_get_desktop_viewport(conn, screen), &reply, nullptr)) {
for (size_t n = 0; n < reply.desktop_viewport_len; n++) {
viewports.emplace_back(position{
static_cast<short int>(reply.desktop_viewport[n].x), static_cast<short int>(reply.desktop_viewport[n].y)});
}
}
for (size_t n = 0; n < reply.desktop_viewport_len; n++) {
viewports.emplace_back(position{
static_cast<short int>(reply.desktop_viewport[n].x), static_cast<short int>(reply.desktop_viewport[n].y)});
}
return viewports;
}
vector<string> get_desktop_names(xcb_ewmh_connection_t* conn, int screen) {
vector<string> get_desktop_names(int screen) {
auto conn = initialize().get();
vector<string> names;
xcb_ewmh_get_utf8_strings_reply_t reply{};
if (!xcb_ewmh_get_desktop_names_reply(conn, xcb_ewmh_get_desktop_names(conn, screen), &reply, nullptr)) {
return names;
}
char buffer[BUFSIZ];
size_t len{0};
for (size_t n = 0; n < reply.strings_len; n++) {
if (reply.strings[n] == '\0') {
if (xcb_ewmh_get_desktop_names_reply(conn, xcb_ewmh_get_desktop_names(conn, screen), &reply, nullptr)) {
char buffer[BUFSIZ];
size_t len{0};
for (size_t n = 0; n < reply.strings_len; n++) {
if (reply.strings[n] == '\0') {
names.emplace_back(buffer, len);
len = 0;
} else {
buffer[len++] = reply.strings[n];
}
}
if (len) {
names.emplace_back(buffer, len);
len = 0;
} else {
buffer[len++] = reply.strings[n];
}
}
if (len) {
names.emplace_back(buffer, len);
}
return names;
}
xcb_window_t get_active_window(xcb_ewmh_connection_t* conn, int screen) {
xcb_window_t win{0};
if (!xcb_ewmh_get_active_window_reply(conn, xcb_ewmh_get_active_window(conn, screen), &win, nullptr)) {
return XCB_NONE;
}
xcb_window_t get_active_window(int screen) {
auto conn = initialize().get();
unsigned int win = XCB_NONE;
xcb_ewmh_get_active_window_reply(conn, xcb_ewmh_get_active_window(conn, screen), &win, nullptr);
return win;
}
void change_current_desktop(xcb_ewmh_connection_t* conn, unsigned int desktop) {
void change_current_desktop(unsigned int desktop) {
auto conn = initialize().get();
xcb_ewmh_request_change_current_desktop(conn, 0, desktop, XCB_CURRENT_TIME);
xcb_flush(conn->connection);
}
void set_wm_window_type(xcb_window_t win, vector<xcb_atom_t> types) {
auto conn = initialize().get();
xcb_ewmh_set_wm_window_type(conn, win, types.size(), types.data());
xcb_flush(conn->connection);
}
void set_wm_state(xcb_window_t win, vector<xcb_atom_t> states) {
auto conn = initialize().get();
xcb_ewmh_set_wm_state(conn, win, states.size(), states.data());
xcb_flush(conn->connection);
}
void set_wm_pid(xcb_window_t win) {
auto conn = initialize().get();
xcb_ewmh_set_wm_pid(conn, win, getpid());
xcb_flush(conn->connection);
}
void set_wm_pid(xcb_window_t win, unsigned int pid) {
auto conn = initialize().get();
xcb_ewmh_set_wm_pid(conn, win, pid);
xcb_flush(conn->connection);
}
void set_wm_desktop(xcb_window_t win, unsigned int desktop) {
auto conn = initialize().get();
xcb_ewmh_set_wm_desktop(conn, win, desktop);
xcb_flush(conn->connection);
}
void set_wm_window_opacity(xcb_window_t win, unsigned long int values) {
auto conn = initialize().get();
xcb_change_property(conn->connection, XCB_PROP_MODE_REPLACE, win, _NET_WM_WINDOW_OPACITY, XCB_ATOM_CARDINAL, 32, 1, &values);
xcb_flush(conn->connection);
}
}

View file

@ -1,119 +0,0 @@
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_util.h>
#include "errors.hpp"
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/graphics.hpp"
POLYBAR_NS
namespace graphics_util {
/**
* Create a basic window
*/
bool create_window(connection& conn, xcb_window_t* win, short int x, short int y, unsigned short int w,
unsigned short int h, xcb_window_t root) {
if (!root) {
root = conn.screen()->root;
}
try {
auto copy = XCB_COPY_FROM_PARENT;
*win = conn.generate_id();
conn.create_window_checked(copy, *win, root, x, y, w, h, 0, copy, copy, 0, nullptr);
return true;
} catch (const exception& err) {
*win = XCB_NONE;
}
return false;
}
/**
* Create a basic pixmap with the same depth as the
* root depth of the default screen
*/
bool create_pixmap(
connection& conn, xcb_drawable_t dst, unsigned short int w, unsigned short int h, xcb_pixmap_t* pixmap) {
return graphics_util::create_pixmap(conn, dst, w, h, conn.screen()->root_depth, pixmap);
}
/**
* Create a basic pixmap with specific depth
*/
bool create_pixmap(connection& conn, xcb_drawable_t dst, unsigned short int w, unsigned short int h, unsigned char d,
xcb_pixmap_t* pixmap) {
try {
*pixmap = conn.generate_id();
conn.create_pixmap_checked(d, *pixmap, dst, w, h);
return true;
} catch (const exception& err) {
*pixmap = XCB_NONE;
}
return false;
}
/**
* Create a basic gc
*/
bool create_gc(connection& conn, xcb_drawable_t drawable, xcb_gcontext_t* gc) {
try {
xcb_params_gc_t params{};
unsigned int mask = 0;
unsigned int values[32];
XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 1);
connection::pack_values(mask, &params, values);
*gc = conn.generate_id();
conn.create_gc_checked(*gc, drawable, mask, values);
return true;
} catch (const exception& err) {
*gc = XCB_NONE;
}
return false;
}
/**
* Query for the root window pixmap
*/
bool get_root_pixmap(connection& conn, root_pixmap* rpix) {
auto screen = conn.screen();
const xcb_atom_t pixmap_properties[3]{ESETROOT_PMAP_ID, _XROOTMAP_ID, _XSETROOT_ID};
for (auto&& property : pixmap_properties) {
auto cookie = xcb_get_property(conn, false, screen->root, property, XCB_ATOM_PIXMAP, 0L, 1L);
auto reply = xcb_get_property_reply(conn, cookie, nullptr);
if (reply && reply->format == 32 && reply->value_len == 1) {
rpix->pixmap = *static_cast<xcb_pixmap_t*>(xcb_get_property_value(reply));
}
}
if (!rpix->pixmap) {
return false;
}
auto cookie = xcb_get_geometry(conn, rpix->pixmap);
auto reply = xcb_get_geometry_reply(conn, cookie, nullptr);
if (!reply) {
rpix->pixmap = XCB_NONE;
return false;
}
rpix->depth = reply->depth;
rpix->width = reply->width;
rpix->height = reply->height;
rpix->x = reply->x;
rpix->y = reply->y;
return true;
}
}
POLYBAR_NS_END

View file

@ -1,24 +1,34 @@
#include "x11/icccm.hpp"
#include "x11/atoms.hpp"
POLYBAR_NS
namespace icccm_util {
string get_wm_name(xcb_connection_t* conn, xcb_window_t win) {
string get_wm_name(xcb_connection_t* c, xcb_window_t w) {
xcb_icccm_get_text_property_reply_t reply{};
if (xcb_icccm_get_wm_name_reply(conn, xcb_icccm_get_wm_name(conn, win), &reply, nullptr)) {
if (xcb_icccm_get_wm_name_reply(c, xcb_icccm_get_wm_name(c, w), &reply, nullptr)) {
return get_reply_string(&reply);
}
return "";
}
string get_reply_string(xcb_icccm_get_text_property_reply_t* reply) {
if (reply->name == nullptr) {
return "";
string str;
if (reply) {
str = string(reply->name, reply->name_len);
xcb_icccm_get_text_property_reply_wipe(reply);
}
string str(reply->name, reply->name_len);
xcb_icccm_get_text_property_reply_wipe(reply);
return str;
}
void set_wm_name(xcb_connection_t* c, xcb_window_t w, const char* wmname, size_t l, const char* wmclass, size_t l2) {
xcb_icccm_set_wm_name(c, w, XCB_ATOM_STRING, 8, l, wmname);
xcb_icccm_set_wm_class(c, w, l2, wmclass);
}
void set_wm_protocols(xcb_connection_t* c, xcb_window_t w, vector<xcb_atom_t> flags) {
xcb_icccm_set_wm_protocols(c, w, WM_PROTOCOLS, flags.size(), flags.data());
}
}
POLYBAR_NS_END

View file

@ -1,9 +1,7 @@
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_image.h>
#include <thread>
#include "components/config.hpp"
#include "components/types.hpp"
#include "errors.hpp"
#include "events/signal.hpp"
#include "utils/color.hpp"
@ -13,11 +11,11 @@
#include "utils/process.hpp"
#include "x11/atoms.hpp"
#include "x11/connection.hpp"
#include "x11/graphics.hpp"
#include "x11/ewmh.hpp"
#include "x11/icccm.hpp"
#include "x11/tray_manager.hpp"
#include "x11/window.hpp"
#include "x11/winspec.hpp"
#include "x11/wm.hpp"
#include "x11/xembed.hpp"
#include "x11/xresources.hpp"
@ -38,8 +36,6 @@
POLYBAR_NS
using namespace wm_util;
/**
* Create instance
*/
@ -272,7 +268,7 @@ void tray_manager::deactivate(bool clear_selection) {
m_tray = 0;
m_pixmap = 0;
m_gc = 0;
m_rootpixmap.pixmap = 0;
m_rootpixmap = 0;
m_prevwidth = 0;
m_prevheight = 0;
m_opts.configured_x = 0;
@ -400,7 +396,7 @@ void tray_manager::reconfigure_clients() {
void tray_manager::reconfigure_bg(bool realloc) {
if (!m_opts.transparent || m_clients.empty() || !m_mapped) {
return;
} else if (!m_rootpixmap.pixmap) {
} else if (!m_rootpixmap) {
realloc = true;
}
@ -413,16 +409,16 @@ void tray_manager::reconfigure_bg(bool realloc) {
m_log.trace("tray: Reconfigure bg (realloc=%i)", realloc);
if (realloc && !get_root_pixmap(m_connection, &m_rootpixmap)) {
if (realloc && !m_connection.root_pixmap(&m_rootpixmap, &m_rootpixmap_depth, &m_rootpixmap_geom)) {
return m_log.err("Failed to get root pixmap for tray background (realloc=%i)", realloc);
} else if (realloc) {
// clang-format off
m_log.info("Tray root pixmap (rootpmap=%s, geom=%dx%d+%d+%d, tray=%s, pmap=%s, gc=%s)",
m_connection.id(m_rootpixmap.pixmap),
m_rootpixmap.width,
m_rootpixmap.height,
m_rootpixmap.x,
m_rootpixmap.y,
m_connection.id(m_rootpixmap),
m_rootpixmap_geom.width,
m_rootpixmap_geom.height,
m_rootpixmap_geom.x,
m_rootpixmap_geom.y,
m_connection.id(m_tray),
m_connection.id(m_pixmap),
m_connection.id(m_gc));
@ -434,15 +430,15 @@ void tray_manager::reconfigure_bg(bool realloc) {
auto x = calculate_x(w);
auto y = calculate_y();
auto px = math_util::max(0, m_rootpixmap.x + x);
auto py = math_util::max(0, m_rootpixmap.y + y);
auto px = math_util::max(0, m_rootpixmap_geom.x + x);
auto py = math_util::max(0, m_rootpixmap_geom.y + y);
// Make sure we don't try to copy void content
if (px + w > m_rootpixmap.width) {
w -= px + w - m_rootpixmap.width;
if (px + w > m_rootpixmap_geom.width) {
w -= px + w - m_rootpixmap_geom.width;
}
if (py + h > m_rootpixmap.height) {
h -= py + h - m_rootpixmap.height;
if (py + h > m_rootpixmap_geom.height) {
h -= py + h - m_rootpixmap_geom.height;
}
if (realloc) {
@ -450,8 +446,7 @@ void tray_manager::reconfigure_bg(bool realloc) {
unsigned char image_depth;
try {
auto image_reply =
m_connection.get_image(XCB_IMAGE_FORMAT_Z_PIXMAP, m_rootpixmap.pixmap, px, py, w, h, XCB_COPY_PLANE);
auto image_reply = m_connection.get_image(XCB_IMAGE_FORMAT_Z_PIXMAP, m_rootpixmap, px, py, w, h, XCB_COPY_PLANE);
image_depth = image_reply->depth;
std::back_insert_iterator<decltype(image_data)> back_it(image_data);
std::copy(image_reply.data().begin(), image_reply.data().end(), back_it);
@ -469,7 +464,7 @@ void tray_manager::reconfigure_bg(bool realloc) {
}
}
m_connection.copy_area_checked(m_rootpixmap.pixmap, m_pixmap, m_gc, px, py, 0, 0, w, h);
m_connection.copy_area_checked(m_rootpixmap, m_pixmap, m_gc, px, py, 0, 0, w, h);
}
/**
@ -487,7 +482,7 @@ void tray_manager::refresh_window() {
auto width = calculate_w();
auto height = calculate_h();
if (m_opts.transparent && !m_rootpixmap.pixmap) {
if (m_opts.transparent && !m_rootpixmap) {
xcb_rectangle_t rect{0, 0, static_cast<uint16_t>(width), static_cast<uint16_t>(height)};
m_connection.poly_fill_rectangle(m_pixmap, m_gc, 1, &rect);
}
@ -571,7 +566,7 @@ void tray_manager::create_bg(bool realloc) {
if (!m_opts.transparent) {
return;
}
if (!realloc && m_pixmap && m_gc && m_rootpixmap.pixmap) {
if (!realloc && m_pixmap && m_gc && m_rootpixmap) {
return;
}
if (realloc && m_pixmap) {
@ -586,10 +581,27 @@ void tray_manager::create_bg(bool realloc) {
auto w = m_opts.width_max;
auto h = calculate_h();
if (!m_pixmap && !graphics_util::create_pixmap(m_connection, m_tray, w, h, &m_pixmap)) {
return m_log.err("Failed to create pixmap for tray background");
} else if (!m_gc && !graphics_util::create_gc(m_connection, m_pixmap, &m_gc)) {
return m_log.err("Failed to create gcontext for tray background");
if (!m_pixmap) {
try {
m_pixmap = m_connection.generate_id();
m_connection.create_pixmap_checked(m_connection.screen()->root_depth, m_pixmap, m_tray, w, h);
} catch (const exception& err) {
return m_log.err("Failed to create pixmap for tray background (err: %s)", err.what());
}
}
if (!m_gc) {
try {
xcb_params_gc_t params{};
unsigned int mask = 0;
unsigned int values[32];
XCB_AUX_ADD_PARAM(&mask, &params, graphics_exposures, 1);
connection::pack_values(mask, &params, values);
m_gc = m_connection.generate_id();
m_connection.create_gc_checked(m_gc, m_pixmap, mask, values);
} catch (const exception& err) {
return m_log.err("Failed to create gcontext for tray background (err: %s)", err.what());
}
}
try {
@ -632,21 +644,20 @@ void tray_manager::set_wm_hints() {
const unsigned int visual{m_connection.screen()->root_visual};
const unsigned int orientation{_NET_SYSTEM_TRAY_ORIENTATION_HORZ};
m_log.trace("tray: Set window WM_NAME / WM_CLASS", m_connection.id(m_tray));
xcb_icccm_set_wm_name(m_connection, m_tray, XCB_ATOM_STRING, 8, 19, TRAY_WM_NAME);
xcb_icccm_set_wm_class(m_connection, m_tray, 12, TRAY_WM_CLASS);
m_log.trace("bar: Set window WM_NAME / WM_CLASS");
icccm_util::set_wm_name(m_connection, m_tray, TRAY_WM_NAME, 19_z, TRAY_WM_CLASS, 12_z);
m_log.trace("tray: Set window WM_PROTOCOLS");
set_wm_protocols(m_connection, m_tray, {WM_DELETE_WINDOW, WM_TAKE_FOCUS});
icccm_util::set_wm_protocols(m_connection, m_tray, {WM_DELETE_WINDOW, WM_TAKE_FOCUS});
m_log.trace("tray: Set window _NET_WM_WINDOW_TYPE");
set_wm_window_type(m_connection, m_tray, {_NET_WM_WINDOW_TYPE_DOCK, _NET_WM_WINDOW_TYPE_NORMAL});
ewmh_util::set_wm_window_type(m_tray, {_NET_WM_WINDOW_TYPE_DOCK, _NET_WM_WINDOW_TYPE_NORMAL});
m_log.trace("tray: Set window _NET_WM_STATE");
set_wm_state(m_connection, m_tray, {_NET_WM_STATE_SKIP_TASKBAR});
ewmh_util::set_wm_state(m_tray, {_NET_WM_STATE_SKIP_TASKBAR});
m_log.trace("tray: Set window _NET_WM_PID");
set_wm_pid(m_connection, m_tray, getpid());
ewmh_util::set_wm_pid(m_tray);
m_log.trace("tray: Set window _NET_SYSTEM_TRAY_VISUAL");
xcb_change_property(
@ -1148,8 +1159,7 @@ bool tray_manager::on(const visibility_change& evt) {
bool tray_manager::on(const dim_window& evt) {
if (m_activated) {
wm_util::set_wm_window_opacity(m_connection, m_tray, evt.cast() * 0xFFFFFFFF);
m_connection.flush();
ewmh_util::set_wm_window_opacity(m_tray, evt.cast() * 0xFFFFFFFF);
}
// let the event bubble
return false;

View file

@ -1,5 +1,3 @@
#include <xcb/xcb_icccm.h>
#include "components/types.hpp"
#include "utils/memory.hpp"
#include "x11/atoms.hpp"
@ -10,41 +8,7 @@
POLYBAR_NS
window& window::operator=(const xcb_window_t win) {
*this = window{connection(), win};
return *this;
}
/**
* Create window and check for errors
*/
window window::create_checked(
short int x, short int y, unsigned short int w, unsigned short int h, unsigned int mask, const xcb_params_cw_t* p) {
if (*this == XCB_NONE) {
*this = connection().generate_id();
}
auto root = connection().screen()->root;
auto copy = XCB_COPY_FROM_PARENT;
unsigned int values[16]{0};
connection::pack_values(mask, p, values);
connection().create_window_checked(copy, *this, root, x, y, w, h, 0, copy, copy, mask, values);
return *this;
}
/**
* Change the window event mask
*/
window window::change_event_mask(unsigned int mask) {
change_attributes_checked(XCB_CW_EVENT_MASK, &mask);
return *this;
}
/**
* Add given event to the event mask unless already added
*/
window window::ensure_event_mask(unsigned int event) {
connection().ensure_event_mask(*this, event);
resource(connection(), win);
return *this;
}
@ -108,26 +72,4 @@ window window::reconfigure_struts(unsigned short int w, unsigned short int h, sh
return *this;
}
/**
* Trigger redraw by toggling visibility state
*/
void window::redraw() {
visibility_notify(XCB_VISIBILITY_FULLY_OBSCURED);
visibility_notify(XCB_VISIBILITY_UNOBSCURED);
connection().flush();
}
/**
* Send visibility notify event
*/
void window::visibility_notify(xcb_visibility_t state) {
auto notify = memory_util::make_malloc_ptr<xcb_visibility_notify_event_t, 32_z>();
notify->response_type = XCB_VISIBILITY_NOTIFY;
notify->window = *this;
notify->state = state;
unsigned int mask{XCB_EVENT_MASK_NO_EVENT};
connection().send_event(false, *this, mask, reinterpret_cast<const char*>(notify.get()));
}
POLYBAR_NS_END

View file

@ -1,5 +1,3 @@
#include <xcb/xcb.h>
#include "x11/connection.hpp"
#include "x11/winspec.hpp"

View file

@ -1,45 +0,0 @@
#include <unistd.h>
#include <xcb/xcb_icccm.h>
#include "utils/math.hpp"
#include "x11/atoms.hpp"
#include "x11/wm.hpp"
POLYBAR_NS
namespace wm_util {
void set_wm_name(xcb_connection_t* conn, xcb_window_t win, const string& wm_name, const string& wm_class) {
xcb_icccm_set_wm_name(conn, win, XCB_ATOM_STRING, 8, wm_name.length(), wm_name.c_str());
xcb_icccm_set_wm_class(conn, win, wm_class.length(), wm_class.c_str());
}
void set_wm_protocols(xcb_connection_t* conn, xcb_window_t win, vector<xcb_atom_t> flags) {
xcb_icccm_set_wm_protocols(conn, win, WM_PROTOCOLS, flags.size(), flags.data());
}
void set_wm_window_type(xcb_connection_t* conn, xcb_window_t win, vector<xcb_atom_t> types) {
xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, win, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, types.size(), types.data());
}
void set_wm_state(xcb_connection_t* conn, xcb_window_t win, vector<xcb_atom_t> states) {
xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, win, _NET_WM_STATE, XCB_ATOM_ATOM, 32, states.size(), states.data());
}
void set_wm_pid(xcb_connection_t* conn, xcb_window_t win, pid_t pid) {
pid = getpid();
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &pid);
}
void set_wm_desktop(xcb_connection_t* conn, xcb_window_t win, unsigned int desktop) {
const unsigned int value_list[1]{desktop};
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, value_list);
}
void set_wm_window_opacity(xcb_connection_t* conn, xcb_window_t win, unsigned long int values) {
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win, _NET_WM_WINDOW_OPACITY, XCB_ATOM_CARDINAL, 32, 1, &values);
}
}
POLYBAR_NS_END