Merge pull request #727 from NBonaparte/change-cursor
feat: Change cursors over clickable/scrollable areas
This commit is contained in:
commit
4663d01a51
@ -29,6 +29,7 @@ addons:
|
|||||||
- libxcb-randr0-dev
|
- libxcb-randr0-dev
|
||||||
- libxcb-util0-dev
|
- libxcb-util0-dev
|
||||||
- libxcb-xkb-dev
|
- libxcb-xkb-dev
|
||||||
|
- libxcb-cursor-dev
|
||||||
- libxcb1-dev
|
- libxcb1-dev
|
||||||
- python-xcbgen
|
- python-xcbgen
|
||||||
- xcb-proto
|
- xcb-proto
|
||||||
|
@ -9,6 +9,7 @@ checklib(ENABLE_MPD "pkg-config" libmpdclient)
|
|||||||
checklib(ENABLE_NETWORK "cmake" Libiw)
|
checklib(ENABLE_NETWORK "cmake" Libiw)
|
||||||
checklib(WITH_XRM "pkg-config" xcb-xrm)
|
checklib(WITH_XRM "pkg-config" xcb-xrm)
|
||||||
checklib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12")
|
checklib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12")
|
||||||
|
checklib(WITH_XCURSOR "pkg-config" "xcb-cursor")
|
||||||
|
|
||||||
if(NOT DEFINED ENABLE_CCACHE AND CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
|
if(NOT DEFINED ENABLE_CCACHE AND CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
|
||||||
set(ENABLE_CCACHE ON)
|
set(ENABLE_CCACHE ON)
|
||||||
@ -36,6 +37,7 @@ option(WITH_XSYNC "xcb-sync support" OFF)
|
|||||||
option(WITH_XCOMPOSITE "xcb-composite support" OFF)
|
option(WITH_XCOMPOSITE "xcb-composite support" OFF)
|
||||||
option(WITH_XKB "xcb-xkb support" ON)
|
option(WITH_XKB "xcb-xkb support" ON)
|
||||||
option(WITH_XRM "xcb-xrm support" ON)
|
option(WITH_XRM "xcb-xrm support" ON)
|
||||||
|
option(WITH_XCURSOR "xcb-cursor support" ON)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
|
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
|
||||||
option(DEBUG_LOGGER "Debug logging" ON)
|
option(DEBUG_LOGGER "Debug logging" ON)
|
||||||
|
@ -20,3 +20,4 @@ querylib(WITH_XRANDR_MONITORS "pkg-config" "xcb-randr>=1.12" libs dirs)
|
|||||||
querylib(WITH_XRENDER "pkg-config" xcb-render libs dirs)
|
querylib(WITH_XRENDER "pkg-config" xcb-render libs dirs)
|
||||||
querylib(WITH_XRM "pkg-config" xcb-xrm libs dirs)
|
querylib(WITH_XRM "pkg-config" xcb-xrm libs dirs)
|
||||||
querylib(WITH_XSYNC "pkg-config" xcb-sync libs dirs)
|
querylib(WITH_XSYNC "pkg-config" xcb-sync libs dirs)
|
||||||
|
querylib(WITH_XCURSOR "pkg-config" xcb-cursor libs dirs)
|
||||||
|
@ -28,6 +28,7 @@ colored_option(" xcb-sync" WITH_XSYNC)
|
|||||||
colored_option(" xcb-composite" WITH_XCOMPOSITE)
|
colored_option(" xcb-composite" WITH_XCOMPOSITE)
|
||||||
colored_option(" xcb-xkb" WITH_XKB)
|
colored_option(" xcb-xkb" WITH_XKB)
|
||||||
colored_option(" xcb-xrm" WITH_XRM)
|
colored_option(" xcb-xrm" WITH_XRM)
|
||||||
|
colored_option(" xcb-cursor" WITH_XCURSOR)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
|
if(CMAKE_BUILD_TYPE_UPPER MATCHES DEBUG)
|
||||||
message(STATUS " Debug options:")
|
message(STATUS " Debug options:")
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
_pkgname=polybar
|
_pkgname=polybar
|
||||||
pkgname="${_pkgname}-git"
|
pkgname="${_pkgname}-git"
|
||||||
pkgver=3.0.5
|
pkgver=3.0.5
|
||||||
pkgrel=3
|
pkgrel=4
|
||||||
pkgdesc="A fast and easy-to-use status bar"
|
pkgdesc="A fast and easy-to-use status bar"
|
||||||
arch=("i686" "x86_64")
|
arch=("i686" "x86_64")
|
||||||
url="https://github.com/jaagr/polybar"
|
url="https://github.com/jaagr/polybar"
|
||||||
license=("MIT")
|
license=("MIT")
|
||||||
depends=("cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm")
|
depends=("cairo" "xcb-util-image" "xcb-util-wm" "xcb-util-xrm" "xcb-util-cursor")
|
||||||
optdepends=("alsa-lib: volume module support"
|
optdepends=("alsa-lib: volume module support"
|
||||||
"libmpdclient: mpd module support"
|
"libmpdclient: mpd module support"
|
||||||
"wireless_tools: network module support"
|
"wireless_tools: network module support"
|
||||||
|
@ -66,6 +66,9 @@ tray-padding = 2
|
|||||||
;scroll-up = i3wm-wsnext
|
;scroll-up = i3wm-wsnext
|
||||||
;scroll-down = i3wm-wsprev
|
;scroll-down = i3wm-wsprev
|
||||||
|
|
||||||
|
cursor-click = pointer
|
||||||
|
cursor-scroll = ns-resize
|
||||||
|
|
||||||
[module/xwindow]
|
[module/xwindow]
|
||||||
type = internal/xwindow
|
type = internal/xwindow
|
||||||
label = %title:0:30:...%
|
label = %title:0:30:...%
|
||||||
|
@ -26,9 +26,13 @@ class tray_manager;
|
|||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
|
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
|
||||||
evt::leave_notify, evt::destroy_notify, evt::client_message>,
|
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message>,
|
||||||
public signal_receiver<SIGN_PRIORITY_BAR, signals::eventqueue::start, signals::ui::tick,
|
public signal_receiver<SIGN_PRIORITY_BAR, signals::eventqueue::start, signals::ui::tick,
|
||||||
signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window> {
|
signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
, signals::ui::cursor_change
|
||||||
|
#endif
|
||||||
|
> {
|
||||||
public:
|
public:
|
||||||
using make_type = unique_ptr<bar>;
|
using make_type = unique_ptr<bar>;
|
||||||
static make_type make(bool only_initialize_values = false);
|
static make_type make(bool only_initialize_values = false);
|
||||||
@ -56,6 +60,7 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
void handle(const evt::destroy_notify& evt);
|
void handle(const evt::destroy_notify& evt);
|
||||||
void handle(const evt::enter_notify& evt);
|
void handle(const evt::enter_notify& evt);
|
||||||
void handle(const evt::leave_notify& evt);
|
void handle(const evt::leave_notify& evt);
|
||||||
|
void handle(const evt::motion_notify& evt);
|
||||||
void handle(const evt::button_press& evt);
|
void handle(const evt::button_press& evt);
|
||||||
void handle(const evt::expose& evt);
|
void handle(const evt::expose& evt);
|
||||||
void handle(const evt::property_notify& evt);
|
void handle(const evt::property_notify& evt);
|
||||||
@ -65,6 +70,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
bool on(const signals::ui::shade_window&);
|
bool on(const signals::ui::shade_window&);
|
||||||
bool on(const signals::ui::tick&);
|
bool on(const signals::ui::tick&);
|
||||||
bool on(const signals::ui::dim_window&);
|
bool on(const signals::ui::dim_window&);
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
bool on(const signals::ui::cursor_change&);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
connection& m_connection;
|
connection& m_connection;
|
||||||
@ -85,6 +93,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||||||
|
|
||||||
mousebtn m_buttonpress_btn{mousebtn::NONE};
|
mousebtn m_buttonpress_btn{mousebtn::NONE};
|
||||||
int m_buttonpress_pos{0};
|
int m_buttonpress_pos{0};
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
int m_motion_pos{0};
|
||||||
|
#endif
|
||||||
|
|
||||||
event_timer m_buttonpress{0L, 5L};
|
event_timer m_buttonpress{0L, 5L};
|
||||||
event_timer m_doubleclick{0L, 150L};
|
event_timer m_doubleclick{0L, 150L};
|
||||||
|
@ -153,6 +153,10 @@ struct bar_settings {
|
|||||||
|
|
||||||
bool override_redirect{false};
|
bool override_redirect{false};
|
||||||
|
|
||||||
|
string cursor{};
|
||||||
|
string cursor_click{};
|
||||||
|
string cursor_scroll{};
|
||||||
|
|
||||||
vector<action> actions{};
|
vector<action> actions{};
|
||||||
|
|
||||||
bool dimmed{false};
|
bool dimmed{false};
|
||||||
|
@ -102,6 +102,9 @@ namespace signals {
|
|||||||
struct button_press : public detail::value_signal<button_press, string> {
|
struct button_press : public detail::value_signal<button_press, string> {
|
||||||
using base_type::base_type;
|
using base_type::base_type;
|
||||||
};
|
};
|
||||||
|
struct cursor_change : public detail::value_signal<cursor_change, string> {
|
||||||
|
using base_type::base_type;
|
||||||
|
};
|
||||||
struct visibility_change : public detail::value_signal<visibility_change, bool> {
|
struct visibility_change : public detail::value_signal<visibility_change, bool> {
|
||||||
using base_type::base_type;
|
using base_type::base_type;
|
||||||
};
|
};
|
||||||
|
@ -32,6 +32,7 @@ namespace signals {
|
|||||||
struct changed;
|
struct changed;
|
||||||
struct tick;
|
struct tick;
|
||||||
struct button_press;
|
struct button_press;
|
||||||
|
struct cursor_change;
|
||||||
struct visibility_change;
|
struct visibility_change;
|
||||||
struct dim_window;
|
struct dim_window;
|
||||||
struct shade_window;
|
struct shade_window;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#cmakedefine01 WITH_XCOMPOSITE
|
#cmakedefine01 WITH_XCOMPOSITE
|
||||||
#cmakedefine01 WITH_XKB
|
#cmakedefine01 WITH_XKB
|
||||||
#cmakedefine01 WITH_XRM
|
#cmakedefine01 WITH_XRM
|
||||||
|
#cmakedefine01 WITH_XCURSOR
|
||||||
|
|
||||||
#if WITH_XRANDR
|
#if WITH_XRANDR
|
||||||
#cmakedefine01 WITH_XRANDR_MONITORS
|
#cmakedefine01 WITH_XRANDR_MONITORS
|
||||||
@ -106,7 +107,7 @@ const auto print_build_info = [](bool extended = false) {
|
|||||||
(ENABLE_NETWORK ? '+' : '-'));
|
(ENABLE_NETWORK ? '+' : '-'));
|
||||||
if (extended) {
|
if (extended) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("X extensions: %crandr (%cmonitors) %crender %cdamage %csync %ccomposite %cxkb %cxrm\n",
|
printf("X extensions: %crandr (%cmonitors) %crender %cdamage %csync %ccomposite %cxkb %cxrm %cxcursor\n",
|
||||||
(WITH_XRANDR ? '+' : '-'),
|
(WITH_XRANDR ? '+' : '-'),
|
||||||
(WITH_XRANDR_MONITORS ? '+' : '-'),
|
(WITH_XRANDR_MONITORS ? '+' : '-'),
|
||||||
(WITH_XRENDER ? '+' : '-'),
|
(WITH_XRENDER ? '+' : '-'),
|
||||||
@ -114,7 +115,8 @@ const auto print_build_info = [](bool extended = false) {
|
|||||||
(WITH_XSYNC ? '+' : '-'),
|
(WITH_XSYNC ? '+' : '-'),
|
||||||
(WITH_XCOMPOSITE ? '+' : '-'),
|
(WITH_XCOMPOSITE ? '+' : '-'),
|
||||||
(WITH_XKB ? '+' : '-'),
|
(WITH_XKB ? '+' : '-'),
|
||||||
(WITH_XRM ? '+' : '-'));
|
(WITH_XRM ? '+' : '-'),
|
||||||
|
(WITH_XCURSOR ? '+' : '-'));
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("Build type: @CMAKE_BUILD_TYPE@\n");
|
printf("Build type: @CMAKE_BUILD_TYPE@\n");
|
||||||
printf("Compiler: @CMAKE_CXX_COMPILER@\n");
|
printf("Compiler: @CMAKE_CXX_COMPILER@\n");
|
||||||
|
27
include/x11/cursor.hpp
Normal file
27
include/x11/cursor.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "settings.hpp"
|
||||||
|
|
||||||
|
#if not WITH_XCURSOR
|
||||||
|
#error "Not built with support for xcb-cursor..."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <xcb/xcb_cursor.h>
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
#include "x11/connection.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace cursor_util {
|
||||||
|
static const map<string, vector<string>> cursors = {
|
||||||
|
{"pointer", {"pointing_hand", "pointer", "hand", "hand1", "hand2", "e29285e634086352946a0e7090d73106", "9d800788f1b08800ae810202380a0822"}},
|
||||||
|
{"default", {"left_ptr", "arrow", "dnd-none", "op_left_arrow"}},
|
||||||
|
{"ns-resize", {"size_ver", "sb_v_double_arrow", "v_double_arrow", "n-resize", "s-resize", "col-resize", "top_side", "bottom_side", "base_arrow_up", "base_arrow_down", "based_arrow_down", "based_arrow_up", "00008160000006810000408080010102"}}
|
||||||
|
};
|
||||||
|
bool valid(string name);
|
||||||
|
bool set_cursor(xcb_connection_t *c, xcb_screen_t *screen, xcb_window_t w, string name);
|
||||||
|
}
|
||||||
|
|
||||||
|
POLYBAR_NS_END
|
@ -49,6 +49,9 @@ endif()
|
|||||||
if(NOT WITH_XRM)
|
if(NOT WITH_XRM)
|
||||||
list(REMOVE_ITEM files x11/xresources.cpp)
|
list(REMOVE_ITEM files x11/xresources.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT WITH_XCURSOR)
|
||||||
|
list(REMOVE_ITEM files x11/cursor.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
#include "x11/icccm.hpp"
|
#include "x11/icccm.hpp"
|
||||||
#include "x11/tray_manager.hpp"
|
#include "x11/tray_manager.hpp"
|
||||||
|
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
#include "x11/cursor.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_I3
|
#if ENABLE_I3
|
||||||
#include "utils/i3.hpp"
|
#include "utils/i3.hpp"
|
||||||
#endif
|
#endif
|
||||||
@ -126,6 +130,19 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
|
|||||||
m_opts.dimvalue = m_conf.get(bs, "dim-value", 1.0);
|
m_opts.dimvalue = m_conf.get(bs, "dim-value", 1.0);
|
||||||
m_opts.dimvalue = math_util::cap(m_opts.dimvalue, 0.0, 1.0);
|
m_opts.dimvalue = math_util::cap(m_opts.dimvalue, 0.0, 1.0);
|
||||||
|
|
||||||
|
m_opts.cursor_click = m_conf.get(bs, "cursor-click", ""s);
|
||||||
|
m_opts.cursor_scroll = m_conf.get(bs, "cursor-scroll", ""s);
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
if (!m_opts.cursor_click.empty() && !cursor_util::valid(m_opts.cursor_click)) {
|
||||||
|
m_log.warn("Ignoring unsupported cursor-click option '%s'", m_opts.cursor_click);
|
||||||
|
m_opts.cursor_click.clear();
|
||||||
|
}
|
||||||
|
if (!m_opts.cursor_scroll.empty() && !cursor_util::valid(m_opts.cursor_scroll)) {
|
||||||
|
m_log.warn("Ignoring unsupported cursor-scroll option '%s'", m_opts.cursor_scroll);
|
||||||
|
m_opts.cursor_scroll.clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Build WM_NAME
|
// Build WM_NAME
|
||||||
m_opts.wmname = m_conf.get(bs, "wm-name", "polybar-" + bs.substr(4) + "_" + m_opts.monitor->name);
|
m_opts.wmname = m_conf.get(bs, "wm-name", "polybar-" + bs.substr(4) + "_" + m_opts.monitor->name);
|
||||||
m_opts.wmname = string_util::replace(m_opts.wmname, " ", "-");
|
m_opts.wmname = string_util::replace(m_opts.wmname, " ", "-");
|
||||||
@ -554,7 +571,6 @@ void bar::handle(const evt::enter_notify&) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_opts.dimmed) {
|
if (m_opts.dimmed) {
|
||||||
m_taskqueue->defer_unique("window-dim", 25ms, [&](size_t) {
|
m_taskqueue->defer_unique("window-dim", 25ms, [&](size_t) {
|
||||||
m_opts.dimmed = false;
|
m_opts.dimmed = false;
|
||||||
@ -580,7 +596,6 @@ void bar::handle(const evt::leave_notify&) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!m_opts.dimmed) {
|
if (!m_opts.dimmed) {
|
||||||
m_taskqueue->defer_unique("window-dim", 3s, [&](size_t) {
|
m_taskqueue->defer_unique("window-dim", 3s, [&](size_t) {
|
||||||
m_opts.dimmed = true;
|
m_opts.dimmed = true;
|
||||||
@ -589,6 +604,69 @@ void bar::handle(const evt::leave_notify&) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler for XCB_MOTION_NOTIFY events
|
||||||
|
*
|
||||||
|
* Used to change the cursor depending on the module
|
||||||
|
*/
|
||||||
|
void bar::handle(const evt::motion_notify& evt) {
|
||||||
|
m_log.trace("bar: Detected motion: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y);
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
m_motion_pos = evt->event_x;
|
||||||
|
// scroll cursor is less important than click cursor, so we shouldn't return until we are sure there is no click action
|
||||||
|
bool found_scroll = false;
|
||||||
|
const auto find_click_area = [&](const action& action) {
|
||||||
|
if (!m_opts.cursor_click.empty() && !(action.button == mousebtn::SCROLL_UP || action.button == mousebtn::SCROLL_DOWN || action.button == mousebtn::NONE)) {
|
||||||
|
if (!string_util::compare(m_opts.cursor, m_opts.cursor_click)) {
|
||||||
|
m_opts.cursor = m_opts.cursor_click;
|
||||||
|
m_sig.emit(cursor_change{string{m_opts.cursor}});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (!m_opts.cursor_scroll.empty() && (action.button == mousebtn::SCROLL_UP || action.button == mousebtn::SCROLL_DOWN)) {
|
||||||
|
if (!found_scroll) {
|
||||||
|
found_scroll = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto&& action : m_renderer->actions()) {
|
||||||
|
if (action.test(m_motion_pos)) {
|
||||||
|
m_log.trace("Found matching input area");
|
||||||
|
if(find_click_area(action))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found_scroll) {
|
||||||
|
if (!string_util::compare(m_opts.cursor, m_opts.cursor_scroll)) {
|
||||||
|
m_opts.cursor = m_opts.cursor_scroll;
|
||||||
|
m_sig.emit(cursor_change{string{m_opts.cursor}});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (auto&& action : m_opts.actions) {
|
||||||
|
if (!action.command.empty()) {
|
||||||
|
m_log.trace("Found matching fallback handler");
|
||||||
|
if(find_click_area(action))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found_scroll) {
|
||||||
|
if (!string_util::compare(m_opts.cursor, m_opts.cursor_scroll)) {
|
||||||
|
m_opts.cursor = m_opts.cursor_scroll;
|
||||||
|
m_sig.emit(cursor_change{string{m_opts.cursor}});
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string_util::compare(m_opts.cursor, "default")) {
|
||||||
|
m_log.trace("No matching cursor area found");
|
||||||
|
m_opts.cursor = "default";
|
||||||
|
m_sig.emit(cursor_change{string{m_opts.cursor}});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler for XCB_BUTTON_PRESS events
|
* Event handler for XCB_BUTTON_PRESS events
|
||||||
*
|
*
|
||||||
@ -703,6 +781,9 @@ bool bar::on(const signals::eventqueue::start&) {
|
|||||||
if (m_opts.dimvalue != 1.0) {
|
if (m_opts.dimvalue != 1.0) {
|
||||||
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW);
|
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW);
|
||||||
}
|
}
|
||||||
|
if (!m_opts.cursor_click.empty() || !m_opts.cursor_scroll.empty() ) {
|
||||||
|
m_connection.ensure_event_mask(m_opts.window, XCB_EVENT_MASK_POINTER_MOTION);
|
||||||
|
}
|
||||||
|
|
||||||
m_log.info("Bar window: %s", m_connection.id(m_opts.window));
|
m_log.info("Bar window: %s", m_connection.id(m_opts.window));
|
||||||
restack_window();
|
restack_window();
|
||||||
@ -841,4 +922,14 @@ bool bar::on(const signals::ui::dim_window& sig) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if WITH_XCURSOR
|
||||||
|
bool bar::on(const signals::ui::cursor_change& sig) {
|
||||||
|
if(!cursor_util::set_cursor(m_connection, m_connection.screen(), m_opts.window, sig.cast())) {
|
||||||
|
m_log.warn("Failed to create cursor context");
|
||||||
|
}
|
||||||
|
m_connection.flush();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
29
src/x11/cursor.cpp
Normal file
29
src/x11/cursor.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "x11/cursor.hpp"
|
||||||
|
|
||||||
|
POLYBAR_NS
|
||||||
|
|
||||||
|
namespace cursor_util {
|
||||||
|
bool valid(string name) {
|
||||||
|
if (cursors.find(name) != cursors.end())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool set_cursor(xcb_connection_t *c, xcb_screen_t *screen, xcb_window_t w, string name) {
|
||||||
|
xcb_cursor_t cursor = XCB_CURSOR_NONE;
|
||||||
|
xcb_cursor_context_t *ctx;
|
||||||
|
|
||||||
|
if (xcb_cursor_context_new(c, screen, &ctx) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (auto&& cursor_name : cursors.at(name)) {
|
||||||
|
cursor = xcb_cursor_load_cursor(ctx, cursor_name.c_str());
|
||||||
|
if (cursor != XCB_CURSOR_NONE)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
xcb_change_window_attributes(c, w, XCB_CW_CURSOR, &cursor);
|
||||||
|
xcb_cursor_context_free(ctx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
POLYBAR_NS_END
|
Loading…
Reference in New Issue
Block a user