mirror of
https://github.com/hyprwm/hyprpicker.git
synced 2025-12-20 00:10:02 +01:00
core: add Notifications Support (#130)
new feature, a flag for notifications -n / --notify. It's using the notify-send command line utility to send desktop notifications. By default I made it compatible with dunst (you will need to enable full markup in the dunst config) but it should work with other notification daemons too.
This commit is contained in:
parent
b01491ac4e
commit
68bc7875fd
10 changed files with 110 additions and 56 deletions
|
|
@ -46,3 +46,4 @@ cmake --install ./build
|
|||
# Caveats
|
||||
|
||||
"Freezes" your displays when picking the color.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,12 @@
|
|||
#include "Clipboard.hpp"
|
||||
|
||||
#include "../includes.hpp"
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
void Clipboard::copy(const char* fmt, ...) {
|
||||
char buf[CLIPBOARDMESSAGESIZE] = "";
|
||||
char* outputStr;
|
||||
void NClipboard::copy(std::string data) {
|
||||
Hyprutils::OS::CProcess copy("wl-copy", {data});
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buf, sizeof buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
outputStr = strdup(buf);
|
||||
|
||||
if (fork() == 0)
|
||||
execlp("wl-copy", "wl-copy", outputStr, NULL);
|
||||
|
||||
free(outputStr);
|
||||
copy.runAsync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#define CLIPBOARDMESSAGESIZE 24
|
||||
#include <string>
|
||||
|
||||
namespace Clipboard {
|
||||
void copy(const char* fmt, ...);
|
||||
namespace NClipboard {
|
||||
void copy(std::string data);
|
||||
};
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include "helpers/Monitor.hpp"
|
||||
#include "helpers/Color.hpp"
|
||||
#include "clipboard/Clipboard.hpp"
|
||||
#include "notify/Notify.hpp"
|
||||
|
||||
// git stuff
|
||||
#ifndef GIT_COMMIT_HASH
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
#include "hyprpicker.hpp"
|
||||
#include "src/notify/Notify.hpp"
|
||||
#include <csignal>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <format>
|
||||
|
||||
void sigHandler(int sig) {
|
||||
static void sigHandler(int sig) {
|
||||
g_pHyprpicker->m_vLayerSurfaces.clear();
|
||||
exit(0);
|
||||
}
|
||||
|
|
@ -242,13 +246,13 @@ void CHyprpicker::convertBuffer(SP<SPoolBuffer> pBuffer) {
|
|||
|
||||
for (int y = 0; y < pBuffer->pixelSize.y; ++y) {
|
||||
for (int x = 0; x < pBuffer->pixelSize.x; ++x) {
|
||||
struct pixel {
|
||||
struct SPixel {
|
||||
// little-endian ARGB
|
||||
unsigned char blue;
|
||||
unsigned char green;
|
||||
unsigned char red;
|
||||
unsigned char alpha;
|
||||
}* px = (struct pixel*)(data + (y * (int)pBuffer->pixelSize.x * 4) + (x * 4));
|
||||
}* px = (struct SPixel*)(data + (static_cast<ptrdiff_t>(y * (int)pBuffer->pixelSize.x * 4)) + (static_cast<ptrdiff_t>(x * 4)));
|
||||
|
||||
std::swap(px->red, px->blue);
|
||||
}
|
||||
|
|
@ -262,7 +266,7 @@ void CHyprpicker::convertBuffer(SP<SPoolBuffer> pBuffer) {
|
|||
|
||||
for (int y = 0; y < pBuffer->pixelSize.y; ++y) {
|
||||
for (int x = 0; x < pBuffer->pixelSize.x; ++x) {
|
||||
uint32_t* px = (uint32_t*)(data + (y * (int)pBuffer->pixelSize.x * 4) + (x * 4));
|
||||
uint32_t* px = (uint32_t*)(data + (static_cast<ptrdiff_t>(y * (int)pBuffer->pixelSize.x * 4)) + (static_cast<ptrdiff_t>(x * 4)));
|
||||
|
||||
// conv to 8 bit
|
||||
uint8_t R = (uint8_t)std::round((255.0 * (((*px) & 0b00000000000000000000001111111111) >> 0) / 1023.0));
|
||||
|
|
@ -292,19 +296,19 @@ void* CHyprpicker::convert24To32Buffer(SP<SPoolBuffer> pBuffer) {
|
|||
case WL_SHM_FORMAT_BGR888: {
|
||||
for (int y = 0; y < pBuffer->pixelSize.y; ++y) {
|
||||
for (int x = 0; x < pBuffer->pixelSize.x; ++x) {
|
||||
struct pixel3 {
|
||||
struct SPixel3 {
|
||||
// little-endian RGB
|
||||
unsigned char blue;
|
||||
unsigned char green;
|
||||
unsigned char red;
|
||||
}* srcPx = (struct pixel3*)(oldBuffer + (y * pBuffer->stride) + (x * 3));
|
||||
struct pixel4 {
|
||||
}* srcPx = (struct SPixel3*)(oldBuffer + (static_cast<size_t>(y * pBuffer->stride)) + (static_cast<ptrdiff_t>(x * 3)));
|
||||
struct SPixel4 {
|
||||
// little-endian ARGB
|
||||
unsigned char blue;
|
||||
unsigned char green;
|
||||
unsigned char red;
|
||||
unsigned char alpha;
|
||||
}* dstPx = (struct pixel4*)(newBuffer + (y * newBufferStride) + (x * 4));
|
||||
}* dstPx = (struct SPixel4*)(newBuffer + (static_cast<ptrdiff_t>(y * newBufferStride)) + (static_cast<ptrdiff_t>(x * 4)));
|
||||
*dstPx = {.blue = srcPx->red, .green = srcPx->green, .red = srcPx->blue, .alpha = 0xFF};
|
||||
}
|
||||
}
|
||||
|
|
@ -312,19 +316,19 @@ void* CHyprpicker::convert24To32Buffer(SP<SPoolBuffer> pBuffer) {
|
|||
case WL_SHM_FORMAT_RGB888: {
|
||||
for (int y = 0; y < pBuffer->pixelSize.y; ++y) {
|
||||
for (int x = 0; x < pBuffer->pixelSize.x; ++x) {
|
||||
struct pixel3 {
|
||||
struct SPixel3 {
|
||||
// big-endian RGB
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
}* srcPx = (struct pixel3*)(oldBuffer + (y * pBuffer->stride) + (x * 3));
|
||||
struct pixel4 {
|
||||
}* srcPx = (struct SPixel3*)(oldBuffer + (y * pBuffer->stride) + (x * 3));
|
||||
struct SPixel4 {
|
||||
// big-endian ARGB
|
||||
unsigned char alpha;
|
||||
unsigned char red;
|
||||
unsigned char green;
|
||||
unsigned char blue;
|
||||
}* dstPx = (struct pixel4*)(newBuffer + (y * newBufferStride) + (x * 4));
|
||||
}* dstPx = (struct SPixel4*)(newBuffer + (y * newBufferStride) + (x * 4));
|
||||
*dstPx = {.alpha = 0xFF, .red = srcPx->red, .green = srcPx->green, .blue = srcPx->blue};
|
||||
}
|
||||
}
|
||||
|
|
@ -460,7 +464,7 @@ void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) {
|
|||
break;
|
||||
};
|
||||
};
|
||||
cairo_set_source_rgba(PCAIRO, 0.0, 0.0, 0.0, 0.5);
|
||||
cairo_set_source_rgba(PCAIRO, 0.0, 0.0, 0.0, 0.75);
|
||||
|
||||
double x, y, width = 8 + (11 * previewBuffer.length()), height = 28, radius = 6;
|
||||
|
||||
|
|
@ -548,12 +552,13 @@ CColor CHyprpicker::getColorFromPixel(CLayerSurface* pLS, Vector2D pix) {
|
|||
return CColor{.r = 0, .g = 0, .b = 0, .a = 0};
|
||||
|
||||
void* dataSrc = pLS->screenBuffer->paddedData ? pLS->screenBuffer->paddedData : pLS->screenBuffer->data;
|
||||
struct pixel {
|
||||
|
||||
struct SPixel {
|
||||
unsigned char blue;
|
||||
unsigned char green;
|
||||
unsigned char red;
|
||||
unsigned char alpha;
|
||||
}* px = (struct pixel*)((char*)dataSrc + ((ptrdiff_t)pix.y * (int)pLS->screenBuffer->pixelSize.x * 4) + ((ptrdiff_t)pix.x * 4));
|
||||
}* px = (struct SPixel*)((char*)dataSrc + ((ptrdiff_t)pix.y * (int)pLS->screenBuffer->pixelSize.x * 4) + ((ptrdiff_t)pix.x * 4));
|
||||
|
||||
return CColor{.r = px->red, .g = px->green, .b = px->blue, .a = px->alpha};
|
||||
}
|
||||
|
|
@ -655,21 +660,6 @@ void CHyprpicker::initMouse() {
|
|||
// 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;
|
||||
|
||||
switch (m_bSelectedOutputMode) {
|
||||
case OUTPUT_CMYK: {
|
||||
float c, m, y, k;
|
||||
COL.getCMYK(c, m, y, k);
|
||||
if (m_bFancyOutput)
|
||||
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%g%% %g%% %g%% %g%%\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, c, m, y, k);
|
||||
else
|
||||
Debug::log(NONE, "%g%% %g%% %g%% %g%%", c, m, y, k);
|
||||
|
||||
if (m_bAutoCopy)
|
||||
Clipboard::copy("%g%% %g%% %g%% %g%%", c, m, y, k);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
case OUTPUT_HEX: {
|
||||
auto toHex = [this](int i) -> std::string {
|
||||
const char* DS = m_bUseLowerCase ? "0123456789abcdef" : "0123456789ABCDEF";
|
||||
|
||||
|
|
@ -681,10 +671,30 @@ void CHyprpicker::initMouse() {
|
|||
return result;
|
||||
};
|
||||
|
||||
auto hexR = toHex(COL.r);
|
||||
auto hexG = toHex(COL.g);
|
||||
auto hexB = toHex(COL.b);
|
||||
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::format("{}% {}% {}% {}%", c, m, y, k);
|
||||
|
||||
if (m_bFancyOutput)
|
||||
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%g%% %g%% %g%% %g%%\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, c, m, y, k);
|
||||
else
|
||||
Debug::log(NONE, "%g%% %g%% %g%% %g%%", c, m, y, k);
|
||||
|
||||
if (m_bAutoCopy)
|
||||
NClipboard::copy(formattedColor);
|
||||
|
||||
if (m_bNotify)
|
||||
NNotify::send(hexColor, formattedColor);
|
||||
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
case OUTPUT_HEX: {
|
||||
if (m_bFancyOutput)
|
||||
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im#%s%s%s\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, toHex(COL.r).c_str(), toHex(COL.g).c_str(),
|
||||
toHex(COL.b).c_str());
|
||||
|
|
@ -692,18 +702,28 @@ void CHyprpicker::initMouse() {
|
|||
Debug::log(NONE, "#%s%s%s", toHex(COL.r).c_str(), toHex(COL.g).c_str(), toHex(COL.b).c_str());
|
||||
|
||||
if (m_bAutoCopy)
|
||||
Clipboard::copy("#%s%s%s", toHex(COL.r).c_str(), toHex(COL.g).c_str(), toHex(COL.b).c_str());
|
||||
NClipboard::copy(hexColor);
|
||||
|
||||
if (m_bNotify)
|
||||
NNotify::send(hexColor, hexColor);
|
||||
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
case OUTPUT_RGB: {
|
||||
std::string formattedColor = std::format("{} {} {}", COL.r, COL.g, COL.b);
|
||||
|
||||
if (m_bFancyOutput)
|
||||
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%i %i %i\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, COL.r, COL.g, COL.b);
|
||||
else
|
||||
Debug::log(NONE, "%i %i %i", COL.r, COL.g, COL.b);
|
||||
|
||||
if (m_bAutoCopy)
|
||||
Clipboard::copy("%i %i %i", COL.r, COL.g, COL.b);
|
||||
NClipboard::copy(formattedColor);
|
||||
|
||||
if (m_bNotify)
|
||||
NNotify::send(hexColor, formattedColor);
|
||||
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
|
|
@ -714,13 +734,20 @@ void CHyprpicker::initMouse() {
|
|||
COL.getHSV(h, s, l_or_v);
|
||||
else
|
||||
COL.getHSL(h, s, l_or_v);
|
||||
|
||||
std::string formattedColor = std::format("{} {}% {}%", h, s, l_or_v);
|
||||
|
||||
if (m_bFancyOutput)
|
||||
Debug::log(NONE, "\033[38;2;%i;%i;%i;48;2;%i;%i;%im%g %g%% %g%%\033[0m", FG, FG, FG, COL.r, COL.g, COL.b, h, s, l_or_v);
|
||||
else
|
||||
Debug::log(NONE, "%g %g%% %g%%", h, s, l_or_v);
|
||||
|
||||
if (m_bAutoCopy)
|
||||
Clipboard::copy("%g %g%% %g%%", h, s, l_or_v);
|
||||
NClipboard::copy(formattedColor);
|
||||
|
||||
if (m_bNotify)
|
||||
NNotify::send(hexColor, formattedColor);
|
||||
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class CHyprpicker {
|
|||
bool m_bFancyOutput = true;
|
||||
|
||||
bool m_bAutoCopy = false;
|
||||
bool m_bNotify = false;
|
||||
bool m_bRenderInactive = false;
|
||||
bool m_bNoZoom = false;
|
||||
bool m_bNoFractional = false;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,9 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include <hyprutils/memory/WeakPtr.hpp>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
using namespace Hyprutils::Memory;
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
#define SP CSharedPointer
|
||||
#define WP CWeakPointer
|
||||
|
|
|
|||
11
src/main.cpp
11
src/main.cpp
|
|
@ -8,7 +8,8 @@ static void help() {
|
|||
std::cout << "Hyprpicker usage: hyprpicker [arg [...]].\n\nArguments:\n"
|
||||
<< " -a | --autocopy | Automatically copies the output to the clipboard (requires wl-clipboard)\n"
|
||||
<< " -f | --format=fmt | Specifies the output format (cmyk, hex, rgb, hsl, hsv)\n"
|
||||
<< " -n | --no-fancy | Disables the \"fancy\" (aka. colored) outputting\n"
|
||||
<< " -n | --notify | Sends a desktop notification when a color is picked (requires notify-send and a notification daemon like dunst)\n"
|
||||
<< " -b | --no-fancy | Disables the \"fancy\" (aka. colored) outputting\n"
|
||||
<< " -h | --help | Show this help message\n"
|
||||
<< " -r | --render-inactive | Render (freeze) inactive displays\n"
|
||||
<< " -z | --no-zoom | Disable the zoom lens\n"
|
||||
|
|
@ -28,7 +29,8 @@ int main(int argc, char** argv, char** envp) {
|
|||
static struct option long_options[] = {{"autocopy", no_argument, nullptr, 'a'},
|
||||
{"format", required_argument, nullptr, 'f'},
|
||||
{"help", no_argument, nullptr, 'h'},
|
||||
{"no-fancy", no_argument, nullptr, 'n'},
|
||||
{"no-fancy", no_argument, nullptr, 'b'},
|
||||
{"notify", no_argument, nullptr, 'n'},
|
||||
{"render-inactive", no_argument, nullptr, 'r'},
|
||||
{"no-zoom", no_argument, nullptr, 'z'},
|
||||
{"no-fractional", no_argument, nullptr, 't'},
|
||||
|
|
@ -39,7 +41,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
{"version", no_argument, nullptr, 'V'},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
|
||||
int c = getopt_long(argc, argv, ":f:hnarzqvtdlV", long_options, &option_index);
|
||||
int c = getopt_long(argc, argv, ":f:hnbarzqvtdlV", long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
|
@ -61,7 +63,8 @@ int main(int argc, char** argv, char** envp) {
|
|||
}
|
||||
break;
|
||||
case 'h': help(); exit(0);
|
||||
case 'n': g_pHyprpicker->m_bFancyOutput = false; break;
|
||||
case 'b': g_pHyprpicker->m_bFancyOutput = false; break;
|
||||
case 'n': g_pHyprpicker->m_bNotify = true; break;
|
||||
case 'a': g_pHyprpicker->m_bAutoCopy = true; break;
|
||||
case 'r': g_pHyprpicker->m_bRenderInactive = true; break;
|
||||
case 'z': g_pHyprpicker->m_bNoZoom = true; break;
|
||||
|
|
|
|||
19
src/notify/Notify.cpp
Normal file
19
src/notify/Notify.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include "Notify.hpp"
|
||||
|
||||
#include "../includes.hpp"
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <format>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
|
||||
void NNotify::send(std::string hexColor, std::string formattedColor) {
|
||||
std::string notifyBody = std::format("<span>Selected color: <span color='{}'><b>{}</b></span></span>", hexColor, formattedColor);
|
||||
|
||||
Hyprutils::OS::CProcess notify("notify-send", {"-t", "5000", "-i", "color-select-symbolic", "Color Picker", notifyBody});
|
||||
|
||||
notify.runAsync();
|
||||
}
|
||||
8
src/notify/Notify.hpp
Normal file
8
src/notify/Notify.hpp
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace NNotify {
|
||||
void send(std::string hexColor, std::string formattedColor);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue