input: add keyboard movement (#143)

This commit is contained in:
Sepandar 2025-11-06 00:25:41 +00:00 committed by GitHub
parent b645b892b1
commit 5ab0e1aaa4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 133 additions and 115 deletions

View file

@ -118,4 +118,4 @@ void SMonitor::initSCFrame() {
Debug::log(CRIT, "Failed to get a Screencopy!");
g_pHyprpicker->finish(1);
});
}
}

View file

@ -14,11 +14,11 @@ struct SMonitor {
SP<CCWlOutput> output = nullptr;
uint32_t wayland_name = 0;
Vector2D size;
int scale;
int32_t scale;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
bool ready = false;
CLayerSurface* pLS = nullptr;
SP<CCZwlrScreencopyFrameV1> pSCFrame = nullptr;
};
};

View file

@ -1,9 +1,14 @@
#include "hyprpicker.hpp"
#include "src/debug/Log.hpp"
#include "src/notify/Notify.hpp"
#include <csignal>
#include <cstddef>
#include <cstdio>
#include <format>
#include <hyprutils/math/Vector2D.hpp>
#include <wayland-client-protocol.h>
#include <xkbcommon/xkbcommon-keysyms.h>
#include <xkbcommon/xkbcommon.h>
static void sigHandler(int sig) {
g_pHyprpicker->m_vLayerSurfaces.clear();
@ -13,7 +18,7 @@ static void sigHandler(int sig) {
void CHyprpicker::init() {
m_pXKBContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!m_pXKBContext)
Debug::log(ERR, "Failed to create xkb context");
Debug::log(ERR, "Failed to create xkb context, keyboard movement not supported");
m_pWLDisplay = wl_display_connect(nullptr);
@ -149,6 +154,116 @@ void CHyprpicker::finish(int code) {
exit(code);
}
void CHyprpicker::outputColor() {
// relative brightness of a color
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
const auto FLUMI = [](const float& c) -> float { return c <= 0.03928 ? c / 12.92 : powf((c + 0.055) / 1.055, 2.4); };
// get the px and print it
const auto MOUSECOORDSABS = m_vLastCoords.floor() / m_pLastSurface->m_pMonitor->size;
const auto CLICKPOS = MOUSECOORDSABS * m_pLastSurface->screenBuffer->pixelSize;
const auto COL = getColorFromPixel(m_pLastSurface, CLICKPOS);
// threshold: (lumi_white + 0.05) / (x + 0.05) == (x + 0.05) / (lumi_black + 0.05)
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
const uint8_t FG = 0.2126 * FLUMI(COL.r / 255.0f) + 0.7152 * FLUMI(COL.g / 255.0f) + 0.0722 * FLUMI(COL.b / 255.0f) > 0.17913 ? 0 : 255;
std::string hexColor = std::format("#{0:02x}{1:02x}{2:02x}", COL.r, COL.g, COL.b);
switch (m_bSelectedOutputMode) {
case OUTPUT_CMYK: {
float c, m, y, k;
COL.getCMYK(c, m, y, k);
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(c, m, y, k));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(formattedColor);
if (m_bNotify)
NNotify::send(hexColor, formattedColor);
finish();
break;
}
case OUTPUT_HEX: {
std::string rHex, gHex, bHex;
if (m_bUseLowerCase) {
rHex = std::format("{:02x}", COL.r);
gHex = std::format("{:02x}", COL.g);
bHex = std::format("{:02x}", COL.b);
} else {
rHex = std::format("{:02X}", COL.r);
gHex = std::format("{:02X}", COL.g);
bHex = std::format("{:02X}", COL.b);
}
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(rHex, gHex, bHex));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(hexColor);
if (m_bNotify)
NNotify::send(hexColor, hexColor);
finish();
break;
}
case OUTPUT_RGB: {
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(COL.r, COL.g, COL.b));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(formattedColor);
if (m_bNotify)
NNotify::send(hexColor, formattedColor);
finish();
break;
}
case OUTPUT_HSL:
case OUTPUT_HSV: {
float h, s, l_or_v;
if (m_bSelectedOutputMode == OUTPUT_HSV)
COL.getHSV(h, s, l_or_v);
else
COL.getHSL(h, s, l_or_v);
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(h, s, l_or_v));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(formattedColor);
if (m_bNotify)
NNotify::send(hexColor, formattedColor);
finish();
break;
}
}
finish();
}
void CHyprpicker::recheckACK() {
for (auto& ls : m_vLayerSurfaces) {
if ((ls->wantsACK || ls->wantsReload) && ls->screenBuffer) {
@ -606,9 +721,19 @@ void CHyprpicker::initKeyboard() {
m_pKeyboard->setKey([this](CCWlKeyboard* r, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
return;
if (m_pXKBState) {
if (xkb_state_key_get_one_sym(m_pXKBState, key + 8) == XKB_KEY_Escape)
int32_t XKBKey = xkb_state_key_get_one_sym(m_pXKBState, key + 8);
if (XKBKey == XKB_KEY_Right)
m_vLastCoords.x += m_vLastCoords.x < m_pLastSurface->m_pMonitor->size.x;
else if (XKBKey == XKB_KEY_Left)
m_vLastCoords.x -= m_vLastCoords.x > 0;
else if (XKBKey == XKB_KEY_Up)
m_vLastCoords.y -= m_vLastCoords.y > 0;
else if (XKBKey == XKB_KEY_Down)
m_vLastCoords.y += m_vLastCoords.y < m_pLastSurface->m_pMonitor->size.y;
else if (XKBKey == XKB_KEY_Return)
outputColor();
else if (XKBKey == XKB_KEY_Escape)
finish(2);
} else if (key == 1) // Assume keycode 1 is escape
finish(2);
@ -654,115 +779,7 @@ void CHyprpicker::initMouse() {
markDirty();
});
m_pPointer->setButton([this](CCWlPointer* r, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state) {
// relative brightness of a color
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
const auto FLUMI = [](const float& c) -> float { return c <= 0.03928 ? c / 12.92 : powf((c + 0.055) / 1.055, 2.4); };
// get the px and print it
const auto MOUSECOORDSABS = m_vLastCoords.floor() / m_pLastSurface->m_pMonitor->size;
const auto CLICKPOS = MOUSECOORDSABS * m_pLastSurface->screenBuffer->pixelSize;
const auto COL = getColorFromPixel(m_pLastSurface, CLICKPOS);
// threshold: (lumi_white + 0.05) / (x + 0.05) == (x + 0.05) / (lumi_black + 0.05)
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
const uint8_t FG = 0.2126 * FLUMI(COL.r / 255.0f) + 0.7152 * FLUMI(COL.g / 255.0f) + 0.0722 * FLUMI(COL.b / 255.0f) > 0.17913 ? 0 : 255;
std::string hexColor = std::format("#{0:02x}{1:02x}{2:02x}", COL.r, COL.g, COL.b);
switch (m_bSelectedOutputMode) {
case OUTPUT_CMYK: {
float c, m, y, k;
COL.getCMYK(c, m, y, k);
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(c, m, y, k));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(formattedColor);
if (m_bNotify)
NNotify::send(hexColor, formattedColor);
finish();
break;
}
case OUTPUT_HEX: {
std::string rHex, gHex, bHex;
if (m_bUseLowerCase) {
rHex = std::format("{:02x}", COL.r);
gHex = std::format("{:02x}", COL.g);
bHex = std::format("{:02x}", COL.b);
} else {
rHex = std::format("{:02X}", COL.r);
gHex = std::format("{:02X}", COL.g);
bHex = std::format("{:02X}", COL.b);
}
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(rHex, gHex, bHex));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(hexColor);
if (m_bNotify)
NNotify::send(hexColor, hexColor);
finish();
break;
}
case OUTPUT_RGB: {
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(COL.r, COL.g, COL.b));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(formattedColor);
if (m_bNotify)
NNotify::send(hexColor, formattedColor);
finish();
break;
}
case OUTPUT_HSL:
case OUTPUT_HSV: {
float h, s, l_or_v;
if (m_bSelectedOutputMode == OUTPUT_HSV)
COL.getHSV(h, s, l_or_v);
else
COL.getHSL(h, s, l_or_v);
std::string formattedColor = std::vformat(m_sOutputFormat, std::make_format_args(h, s, l_or_v));
if (m_bFancyOutput)
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, formattedColor.c_str());
else
Debug::log(NONE, formattedColor.c_str());
if (m_bAutoCopy)
NClipboard::copy(formattedColor);
if (m_bNotify)
NNotify::send(hexColor, formattedColor);
finish();
break;
}
}
finish();
});
m_pPointer->setButton([this](CCWlPointer* r, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state) { outputColor(); });
m_pPointer->setAxis([this](CCWlPointer* r, uint32_t time, uint32_t axis, wl_fixed_t value) {
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
return;

View file

@ -80,6 +80,7 @@ class CHyprpicker {
void markDirty();
void finish(int code = 0);
void outputColor();
CColor getColorFromPixel(CLayerSurface*, Vector2D);