From 6f32582d2282fd97f18e54db0f45f53f18edde4f Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Sep 2025 05:45:32 +0800 Subject: [PATCH] core: add more flexible positioning and scaling (#138) * feat: use axis scroller to change scale * feat: add option -s to set scale and -u to set radius * Optimize optarg conversion --- src/hyprpicker.cpp | 20 +++++++++++++++++--- src/hyprpicker.hpp | 4 +++- src/main.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/hyprpicker.cpp b/src/hyprpicker.cpp index 15b3b84..9669003 100644 --- a/src/hyprpicker.cpp +++ b/src/hyprpicker.cpp @@ -406,7 +406,7 @@ void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) { cairo_scale(PCAIRO, 1, 1); - cairo_arc(PCAIRO, CLICKPOS.x, CLICKPOS.y, 105 / SCALEBUFS.x, 0, 2 * M_PI); + cairo_arc(PCAIRO, CLICKPOS.x, CLICKPOS.y, m_iCircleRadius + 5 / SCALEBUFS.x, 0, 2 * M_PI); cairo_clip(PCAIRO); cairo_fill(PCAIRO); @@ -422,11 +422,11 @@ void CHyprpicker::renderSurface(CLayerSurface* pSurface, bool forceInactive) { cairo_matrix_t matrix; cairo_matrix_init_identity(&matrix); cairo_matrix_translate(&matrix, CLICKPOSBUF.x + 0.5f, CLICKPOSBUF.y + 0.5f); - cairo_matrix_scale(&matrix, 0.1f, 0.1f); + cairo_matrix_scale(&matrix, 1.0 / m_fZoomScale, 1.0 / m_fZoomScale); cairo_matrix_translate(&matrix, (-CLICKPOSBUF.x / SCALEBUFS.x) - 0.5f, (-CLICKPOSBUF.y / SCALEBUFS.y) - 0.5f); cairo_pattern_set_matrix(PATTERN, &matrix); cairo_set_source(PCAIRO, PATTERN); - cairo_arc(PCAIRO, CLICKPOS.x, CLICKPOS.y, 100 / SCALEBUFS.x, 0, 2 * M_PI); + cairo_arc(PCAIRO, CLICKPOS.x, CLICKPOS.y, m_iCircleRadius / SCALEBUFS.x, 0, 2 * M_PI); cairo_clip(PCAIRO); cairo_paint(PCAIRO); @@ -756,4 +756,18 @@ void CHyprpicker::initMouse() { finish(); }); + + m_pPointer->setAxis([this](CCWlPointer* r, uint32_t time, uint32_t axis, wl_fixed_t value) { + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) + return; + + double delta = wl_fixed_to_double(value); + + if (delta < 0) + m_fZoomScale = std::min(m_fZoomScale + 1.0, 100.0); + else + m_fZoomScale = std::max(m_fZoomScale - 1.0, 1.0); + + markDirty(); + }); } diff --git a/src/hyprpicker.hpp b/src/hyprpicker.hpp index f577dfe..3353871 100644 --- a/src/hyprpicker.hpp +++ b/src/hyprpicker.hpp @@ -48,7 +48,9 @@ class CHyprpicker { bool m_bDisablePreview = false; bool m_bUseLowerCase = false; - bool m_bRunning = true; + bool m_bRunning = true; + float m_fZoomScale = 10.0; + int m_iCircleRadius = 100; std::vector> m_vMonitors; std::vector> m_vLayerSurfaces; diff --git a/src/main.cpp b/src/main.cpp index 0f43b18..3d7f92f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,8 @@ static void help() { << " -t | --no-fractional | Disable fractional scaling support\n" << " -d | --disable-preview | Disable live preview of color\n" << " -l | --lowercase-hex | Outputs the hexcode in lowercase\n" + << " -s | --scale=scale | Set the zoom scale (between 1 and 10)\n" + << " -u | --radius=radius | Set the circle radius (between 1 and 1000)\n" << " -V | --version | Print version info\n"; } @@ -39,9 +41,11 @@ int main(int argc, char** argv, char** envp) { {"disable-preview", no_argument, nullptr, 'd'}, {"lowercase-hex", no_argument, nullptr, 'l'}, {"version", no_argument, nullptr, 'V'}, + {"scale", required_argument, nullptr, 's'}, + {"radius", required_argument, nullptr, 'u'}, {nullptr, 0, nullptr, 0}}; - int c = getopt_long(argc, argv, ":f:hnbarzqvtdlV", long_options, &option_index); + int c = getopt_long(argc, argv, ":f:hnbarzqvtdlVs:u:", long_options, &option_index); if (c == -1) break; @@ -77,7 +81,41 @@ int main(int argc, char** argv, char** envp) { std::cout << "hyprpicker v" << HYPRPICKER_VERSION << "\n"; exit(0); } + case 's': { + float value; + auto result = std::from_chars(optarg, optarg + strlen(optarg), value); + if (result.ec != std::errc() || result.ptr != optarg + strlen(optarg)) { + std::cerr << "Invalid scale value: " << optarg << "\n"; + exit(1); + } + + if (value < 1.0f || value > 10.0f) { + std::cerr << "Scale must be between 1 and 10!\n"; + exit(1); + } + + g_pHyprpicker->m_fZoomScale = value; + break; + } + + case 'u': { + int value; + auto result = std::from_chars(optarg, optarg + strlen(optarg), value); + + if (result.ec != std::errc() || result.ptr != optarg + strlen(optarg)) { + std::cerr << "Invalid radius value: " << optarg << "\n"; + exit(1); + } + + if (value < 1 || value > 1000) { + std::cerr << "Radius must be between 1 and 1000!\n"; + exit(1); + } + + g_pHyprpicker->m_iCircleRadius = value; + break; + } default: help(); exit(1); } }