click handling (without modifiers)

This commit is contained in:
Raphael Robatsch 2021-10-26 11:40:46 +02:00
parent dd9c7d72cc
commit 8c959d60a1
6 changed files with 115 additions and 31 deletions

View file

@ -75,22 +75,22 @@
<event name="selected"> <event name="selected">
<description summary="updates the selected state of the monitor"> <description summary="updates the selected state of the monitor">
</description> </description>
<arg name="selected" type="int"/> <arg name="selected" type="uint"/>
</event> </event>
<event name="tag"> <event name="tag">
<description summary="updates the state of one tag"> <description summary="updates the state of one tag">
</description> </description>
<arg name="tag" type="int"/> <arg name="tag" type="uint"/>
<arg name="state" type="uint" enum="tag_state"/> <arg name="state" type="uint" enum="tag_state"/>
<arg name="num_clients" type="int"/> <arg name="num_clients" type="uint"/>
<arg name="focused_client" type="int" summary="-1 if there is no focused client"/> <arg name="focused_client" type="int" summary="-1 if there is no focused client"/>
</event> </event>
<event name="layout"> <event name="layout">
<description summary="updates the selected layout"> <description summary="updates the selected layout">
</description> </description>
<arg name="layout" type="int"/> <arg name="layout" type="uint"/>
</event> </event>
<event name="title"> <event name="title">
@ -103,5 +103,18 @@
<description summary="sent after all other events have been sent. allows for atomic updates."> <description summary="sent after all other events have been sent. allows for atomic updates.">
</description> </description>
</event> </event>
<request name="set_tags">
<description summary="sets the active tags on this monitor. changes are applied immediately.">
</description>
<arg name="tagmask" type="uint"/>
<arg name="toggle_tagset" type="uint"/>
</request>
<request name="set_layout">
<description summary="sets the active layout on this monitor. changes are applied immediately.">
</description>
<arg name="layout" type="uint"/>
</request>
</interface> </interface>
</protocol> </protocol>

View file

@ -32,10 +32,11 @@ static QFontMetrics fontMetrics = QFontMetrics {font};
const wl_surface* Bar::surface() const { return _surface.get(); } const wl_surface* Bar::surface() const { return _surface.get(); }
Bar::Bar() Bar::Bar(Monitor *mon)
{ {
for (auto tag : tagNames) { _mon = mon;
_tags.push_back({ tag, ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_NONE, 0, 0, 0 }); for (auto i=0u; i<tagNames.size(); i++) {
_tags.push_back({ ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_NONE, 0, 0, 0 });
} }
} }
@ -57,11 +58,29 @@ void Bar::create(wl_output *output)
wl_surface_commit(_surface.get()); wl_surface_commit(_surface.get());
} }
void Bar::click(int x, int) void Bar::click(int x, int, int btn, unsigned int modifiers)
{ {
for (auto tag=_tags.rbegin(); tag != _tags.rend(); tag++) { Arg arg = {0};
if (x > tag->x) { Arg *argp = nullptr;
// todo toggle Control control = Control::None;
if (x > _statusX) {
control = Control::StatusText;
} else if (x > _titleX) {
control = Control::WinTitle;
} else if (x > _layoutX) {
control = Control::LayoutSymbol;
} else for (auto tag = _tags.size()-1; tag >= 0; tag--) {
if (x > _tags[tag].x) {
control = Control::TagBar;
arg.ui = 1<<tag;
argp = &arg;
break;
}
}
for (auto i = 0u; i < sizeof(buttons)/sizeof(buttons[0]); i++) {
const auto& button = buttons[i];
if (button.control == control && button.btn == btn && button.modifiers == modifiers) {
button.func(*_mon, *(argp ? argp : &button.arg));
return; return;
} }
} }
@ -112,8 +131,11 @@ void Bar::render()
renderTags(); renderTags();
setColorScheme(_selected ? colorActive : colorInactive); setColorScheme(_selected ? colorActive : colorInactive);
_layoutX = _x;
renderText(layoutNames[_layout]); renderText(layoutNames[_layout]);
_titleX = _x;
renderText(_title); renderText(_title);
_statusX = _x;
renderStatus(); renderStatus();
_painter = nullptr; _painter = nullptr;
@ -132,11 +154,12 @@ void Bar::setColorScheme(const ColorScheme &scheme)
void Bar::renderTags() void Bar::renderTags()
{ {
for (auto &tag : _tags) { for (auto i=0u; i<_tags.size(); i++) {
auto& tag = _tags[i];
tag.x = _x; tag.x = _x;
setColorScheme(tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT ? colorUrgent setColorScheme(tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_URGENT ? colorUrgent
: tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE ? colorActive : colorInactive); : tag.state & ZNET_TAPESOFTWARE_DWL_WM_MONITOR_V1_TAG_STATE_ACTIVE ? colorActive : colorInactive);
renderText(tag.name); renderText(tagNames[i]);
auto indicators = qMin(tag.numClients, _bufs->height/2); auto indicators = qMin(tag.numClients, _bufs->height/2);
for (auto ind = 0; ind < indicators; ind++) { for (auto ind = 0; ind < indicators; ind++) {
if (ind == tag.focusedClient) { if (ind == tag.focusedClient) {

View file

@ -13,22 +13,24 @@
#include "shm_buffer.hpp" #include "shm_buffer.hpp"
struct Tag { struct Tag {
QString name;
znet_tapesoftware_dwl_wm_monitor_v1_tag_state state; znet_tapesoftware_dwl_wm_monitor_v1_tag_state state;
int numClients; int numClients;
int focusedClient; int focusedClient;
int x; int x;
}; };
struct Monitor;
class Bar { class Bar {
static const zwlr_layer_surface_v1_listener _layerSurfaceListener; static const zwlr_layer_surface_v1_listener _layerSurfaceListener;
static const wl_callback_listener _frameListener; static const wl_callback_listener _frameListener;
wl_unique_ptr<wl_surface> _surface; wl_unique_ptr<wl_surface> _surface;
wl_unique_ptr<zwlr_layer_surface_v1> _layerSurface; wl_unique_ptr<zwlr_layer_surface_v1> _layerSurface;
Monitor *_mon;
QPainter *_painter {nullptr}; QPainter *_painter {nullptr};
std::optional<ShmBuffer> _bufs; std::optional<ShmBuffer> _bufs;
int _textY, _x; int _textY, _x;
int _statusX, _titleX, _layoutX;
bool _invalid {false}; bool _invalid {false};
std::vector<Tag> _tags; std::vector<Tag> _tags;
@ -45,7 +47,7 @@ class Bar {
int textWidth(const QString &text); int textWidth(const QString &text);
void setColorScheme(const ColorScheme &scheme); void setColorScheme(const ColorScheme &scheme);
public: public:
Bar(); Bar(Monitor *mon);
const wl_surface* surface() const; const wl_surface* surface() const;
void create(wl_output *output); void create(wl_output *output);
void setSelected(bool selected); void setSelected(bool selected);
@ -54,5 +56,5 @@ public:
void setTitle(const char *title); void setTitle(const char *title);
void setStatus(const QString &status); void setStatus(const QString &status);
void invalidate(); void invalidate();
void click(int x, int y); void click(int x, int y, int btn, unsigned int modifiers);
}; };

View file

@ -2,14 +2,26 @@
// See LICENSE file for copyright and license details. // See LICENSE file for copyright and license details.
#pragma once #pragma once
#include <wayland-client.h>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <wayland-client.h>
#include <linux/input-event-codes.h>
#include <QColor> #include <QColor>
#include <QString> #include <QString>
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h" #include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h"
struct ColorScheme {
QColor fg, bg;
};
union Arg {
int i;
unsigned int ui;
float f;
const void *v;
};
struct Monitor;
extern wl_display *display; extern wl_display *display;
extern wl_compositor *compositor; extern wl_compositor *compositor;
extern wl_shm *shm; extern wl_shm *shm;
@ -17,8 +29,17 @@ extern zwlr_layer_shell_v1 *wlrLayerShell;
extern std::vector<QString> tagNames; extern std::vector<QString> tagNames;
extern std::vector<QString> layoutNames; extern std::vector<QString> layoutNames;
struct ColorScheme { void toggleview(Monitor &m, const Arg &arg);
QColor fg, bg; void view(Monitor &m, const Arg &arg);
void setlayout(Monitor &m, const Arg &arg);
enum class Control { None, TagBar, LayoutSymbol, WinTitle, StatusText };
struct Button {
Control control;
unsigned int modifiers; // todo xkbcommon
int btn; // <linux/input-event-codes.h>
void (*func)(Monitor &mon, const Arg &arg);
const Arg arg;
}; };
// wayland smart pointers // wayland smart pointers

View file

@ -16,3 +16,11 @@ constexpr bool fontBold = false;
constexpr ColorScheme colorInactive = {QColor(0xbb, 0xbb, 0xbb), QColor(0x22, 0x22, 0x22)}; constexpr ColorScheme colorInactive = {QColor(0xbb, 0xbb, 0xbb), QColor(0x22, 0x22, 0x22)};
constexpr ColorScheme colorActive = {QColor(0xee, 0xee, 0xee), QColor(0x00, 0x55, 0x77)}; constexpr ColorScheme colorActive = {QColor(0xee, 0xee, 0xee), QColor(0x00, 0x55, 0x77)};
constexpr ColorScheme colorUrgent = {colorActive.bg, colorActive.fg}; constexpr ColorScheme colorUrgent = {colorActive.bg, colorActive.fg};
constexpr Button buttons[] = {
{ Control::TagBar, 0, BTN_LEFT, toggleview, {0} },
{ Control::TagBar, 0, BTN_MIDDLE, view, {0} },
//{ Control::TagBar, 0, BTN_RIGHT, tag, {0} },
{ Control::LayoutSymbol, 0, BTN_LEFT, setlayout, {.ui = 0} },
{ Control::LayoutSymbol, 0, BTN_RIGHT, setlayout, {.ui = 2} },
};

View file

@ -12,6 +12,7 @@
#include <unistd.h> #include <unistd.h>
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>
#include <optional> #include <optional>
#include <vector>
#include <QGuiApplication> #include <QGuiApplication>
#include <QSocketNotifier> #include <QSocketNotifier>
#include <wayland-client.h> #include <wayland-client.h>
@ -44,6 +45,7 @@ zwlr_layer_shell_v1 *wlrLayerShell;
znet_tapesoftware_dwl_wm_v1 *dwlWm; znet_tapesoftware_dwl_wm_v1 *dwlWm;
std::vector<QString> tagNames; std::vector<QString> tagNames;
std::vector<QString> layoutNames; std::vector<QString> layoutNames;
static xdg_wm_base *xdgWmBase;
static bool ready; static bool ready;
static std::vector<Monitor> monitors; static std::vector<Monitor> monitors;
static QString lastStatus; static QString lastStatus;
@ -53,7 +55,19 @@ static int statusFifoWriter {-1};
static QSocketNotifier *displayWriteNotifier; static QSocketNotifier *displayWriteNotifier;
static bool quitting {false}; static bool quitting {false};
static xdg_wm_base *xdgWmBase; void toggleview(Monitor &m, const Arg &arg)
{
znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), arg.ui, 0);
}
void view(Monitor &m, const Arg &arg)
{
znet_tapesoftware_dwl_wm_monitor_v1_set_tags(m.dwlMonitor.get(), arg.ui, 1);
}
void setlayout(Monitor &m, const Arg &arg)
{
znet_tapesoftware_dwl_wm_monitor_v1_set_layout(m.dwlMonitor.get(), arg.ui);
}
static const struct xdg_wm_base_listener xdgWmBaseListener = { static const struct xdg_wm_base_listener xdgWmBaseListener = {
[](void*, xdg_wm_base *sender, uint32_t serial) { [](void*, xdg_wm_base *sender, uint32_t serial) {
xdg_wm_base_pong(sender, serial); xdg_wm_base_pong(sender, serial);
@ -66,7 +80,7 @@ struct SeatState {
wl_cursor_image *cursorImage; wl_cursor_image *cursorImage;
Bar *focusedBar; Bar *focusedBar;
int x, y; int x, y;
bool leftButtonClick; std::vector<int> btns;
}; };
static SeatState seatState; static SeatState seatState;
static Bar* barFromSurface(const wl_surface *surface) static Bar* barFromSurface(const wl_surface *surface)
@ -92,17 +106,20 @@ static const struct wl_pointer_listener pointerListener = {
seatState.y = wl_fixed_to_int(y); seatState.y = wl_fixed_to_int(y);
}, },
.button = [](void*, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) { .button = [](void*, wl_pointer*, uint32_t, uint32_t, uint32_t button, uint32_t pressed) {
if (button == BTN_LEFT) { auto it = std::find(begin(seatState.btns), end(seatState.btns), button);
seatState.leftButtonClick = pressed == WL_POINTER_BUTTON_STATE_PRESSED; if (pressed == WL_POINTER_BUTTON_STATE_PRESSED && it == end(seatState.btns)) {
seatState.btns.push_back(button);
} else if (pressed == WL_POINTER_BUTTON_STATE_RELEASED && it != end(seatState.btns)) {
seatState.btns.erase(it);
} }
}, },
.axis = [](void*, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { }, .axis = [](void*, wl_pointer*, uint32_t, uint32_t, wl_fixed_t) { },
.frame = [](void*, wl_pointer*) { .frame = [](void*, wl_pointer*) {
if (!seatState.focusedBar) return; if (!seatState.focusedBar) return;
if (seatState.leftButtonClick) { for (auto btn : seatState.btns) {
seatState.leftButtonClick = false; seatState.focusedBar->click(seatState.x, seatState.y, btn, 0);
seatState.focusedBar->click(seatState.x, seatState.y);
} }
seatState.btns.clear();
}, },
.axis_source = [](void*, wl_pointer*, uint32_t) { }, .axis_source = [](void*, wl_pointer*, uint32_t) { },
.axis_stop = [](void*, wl_pointer*, uint32_t, uint32_t) { }, .axis_stop = [](void*, wl_pointer*, uint32_t, uint32_t) { },
@ -138,15 +155,15 @@ static const struct znet_tapesoftware_dwl_wm_v1_listener dwlWmListener = {
}; };
static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorListener { static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorListener {
.selected = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, int32_t selected) { .selected = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t selected) {
auto mon = static_cast<Monitor*>(mv); auto mon = static_cast<Monitor*>(mv);
mon->bar->setSelected(selected); mon->bar->setSelected(selected);
}, },
.tag = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, int32_t tag, uint32_t state, int32_t numClients, int32_t focusedClient) { .tag = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t tag, uint32_t state, uint32_t numClients, int32_t focusedClient) {
auto mon = static_cast<Monitor*>(mv); auto mon = static_cast<Monitor*>(mv);
mon->bar->setTag(tag, static_cast<znet_tapesoftware_dwl_wm_monitor_v1_tag_state>(state), numClients, focusedClient); mon->bar->setTag(tag, static_cast<znet_tapesoftware_dwl_wm_monitor_v1_tag_state>(state), numClients, focusedClient);
}, },
.layout = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, int32_t layout) { .layout = [](void *mv, znet_tapesoftware_dwl_wm_monitor_v1*, uint32_t layout) {
auto mon = static_cast<Monitor*>(mv); auto mon = static_cast<Monitor*>(mv);
mon->bar->setLayout(layout); mon->bar->setLayout(layout);
}, },
@ -160,13 +177,14 @@ static const struct znet_tapesoftware_dwl_wm_monitor_v1_listener dwlWmMonitorLis
mon->bar->invalidate(); mon->bar->invalidate();
} else { } else {
mon->bar->create(mon->wlOutput.get()); mon->bar->create(mon->wlOutput.get());
mon->created = true;
} }
} }
}; };
static void setupMonitor(Monitor &monitor) { static void setupMonitor(Monitor &monitor) {
monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get())); monitor.dwlMonitor.reset(znet_tapesoftware_dwl_wm_v1_get_monitor(dwlWm, monitor.wlOutput.get()));
monitor.bar.emplace(); monitor.bar.emplace(&monitor);
monitor.bar->setStatus(lastStatus); monitor.bar->setStatus(lastStatus);
znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor); znet_tapesoftware_dwl_wm_monitor_v1_add_listener(monitor.dwlMonitor.get(), &dwlWmMonitorListener, &monitor);
} }
@ -255,7 +273,6 @@ struct HandleGlobalHelper {
static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, const char *interface, uint32_t version) static void registryHandleGlobal(void*, wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
{ {
auto reg = HandleGlobalHelper { registry, name, interface }; auto reg = HandleGlobalHelper { registry, name, interface };
printf("got global: %s v%d\n", interface, version);
if (reg.handle(compositor, wl_compositor_interface, 4)) return; if (reg.handle(compositor, wl_compositor_interface, 4)) return;
if (reg.handle(shm, wl_shm_interface, 1)) return; if (reg.handle(shm, wl_shm_interface, 1)) return;
if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 4)) return; if (reg.handle(wlrLayerShell, zwlr_layer_shell_v1_interface, 4)) return;