Уже давно весьма огорчаюсь тем, что в моём любимом Gpick отвалилась пипетка с тех пор, как KDE со своей Плазмой прочно переехали на Wayland. Если раньше я ещё мирился с GTK-шностью Gpick (про KDE, плазму и вяленого — поручик, молчать!), то теперь совсем взгрустнулось…
Началось всё с того, что я напрочь забыл, какие у меня в «Местах» цвета какие. Я же человек правильный, нормальные человеческие названия для переменных ведь не путь джедая, верно? Посмотрев на своё
@mixin theme { $color-01: rgba($col-36, $opacity-07); $color-02: rgba($col-36, $opacity-11); $color-03: rgba($col-36, $opacity-13); $color-04: rgba($col-36, $opacity-12);…
(и ещё такого на пару сотен строк только в одном файле), я прослезился, ударил стену головой и решил исправляться к лучшему. Заодно перейти на адекватные CSS-переменные, а не этот SCSS-хардкор. Но вот без пипетки это грустновато…
Итак, нужна, прости Господи, пипетка. Ставить и терпеть ещё и штатный kcolorpicker, а уж тем более, kcolorchooser (при живом-то, ну, почти, Gpick) в своём уютном Artix я не намерен. Ладно про настройки я молчу, в которых у KDE-шных поделий обычно по две штуки — «Показывать иконку справа вместо слева» и «Рассказывать анекдоты раз в час вместо раза в полчаса». Но функционал… Непосредственного нету, а посредственного на полгига.
hyprpicker, который, как написано в пояснялке, does not suck, не просто wlroots-compatible. Проблема в том, что это я сейчас «wlroots-incompatible». Что остаётся? Правильно. Велосипедить.
Стал пытаться думать мозгом. Ударился было в bash-скрипты, но довольно быстро работать там с DBus, асинхронностью порталов и прочими мониторами стало очень больно.
Сунулся было набросать простенькую утилитку на C++/Qt (последний оборот звучит, правда? 😁) — стало ещё больнее. Ну, вы знаете. Для того, чтобы в дверь врезать новый замок, нам жизненно необходимо вокруг неё построить десятимиллионный мегаполис с инфраструктурой, аэропортом, полицией и трамвайной сетью. Не говоря уже о заведениях с преферансом и барышнями…
Короче, плюнул и наваял скрипт на Питоне (хоть я его и терпеть не могу). Получилось, имхо, просто прекрасно. При запуске даёт тебе пипетку, ждёт, пока жмакнешь ей где-нибудь на экране, и выдаёт на выход сразу пачку CSS-значений на любой вкус в таком виде:
HEX: #7e80ea HSL: hsl(238 72% 70%) RGBb: rgb(126 128 234) RGBp: rgb(49.4% 50.2% 91.8%)
Тут тебе и RGB, хоть в HEX, хоть в числах байта, хоть в процентах, и HSL. А ежели запускать ещё и с ключиком -c или --copy, то заодно и копирует первое HEX-значение в буфер обмена. Можно повесить на хоткей хоть голым, хоть через какую-нибудь shell-трубу с опциональным парсером. Красота! 😁
В общем, делюсь с городом и миром. Может, кому-то пригодится и сэкономит нервы и время:
#!/usr/bin/env python3import sysimport colorsysimport subprocessimport argparsefrom gi.repository import GLib, Gioparser = argparse.ArgumentParser( description="Wayland XDG-Portal Color Picker")parser.add_argument( "-c", "--copy", action="store_true", help="Also, copy the HEX value to the clipboard")args = parser.parse_args()loop = GLib.MainLoop()channels = Nonebus = Gio.bus_get_sync(Gio.BusType.SESSION, None)def on_signal_received( connection, sender_name, object_path, interface_name, signal_name, parameters, user_data): global channels try: code, results = parameters.unpack() if code == 0 and 'color' in results: channels = results['color'] except Exception as e: sys.stderr.write(f"Signal error: {e}\n") finally: loop.quit()def on_method_reply(connection, res): try: reply = connection.call_finish(res) request_path = reply.unpack()[0] bus.signal_subscribe( "org.freedesktop.portal.Desktop", "org.freedesktop.portal.Request", "Response", request_path, None, Gio.DBusSignalFlags.NONE, on_signal_received, None ) except Exception as e: sys.stderr.write(f"Method error: {e}\n") loop.quit()bus.call( "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.Screenshot", "PickColor", GLib.Variant("(sa{sv})", ("", {})), None, Gio.DBusSignalFlags.NONE, -1, None, on_method_reply)loop.run()if channels and len(channels) >= 3: r_f, g_f, b_f = channels[0], channels[1], channels[2] r_b, g_b, b_b = int(r_f * 255), int(g_f * 255), int(b_f * 255) hex_color = f"#{r_b:02x}{g_b:02x}{b_b:02x}" r_p, g_p, b_p = r_f * 100, g_f * 100, b_f * 100 h_f, l_f, s_f = colorsys.rgb_to_hls(r_f, g_f, b_f) h, s, l = int(h_f * 360), int(s_f * 100), int(l_f * 100) print(f"HEX: {hex_color}") print(f"HSL: hsl({h} {s}% {l}%)") print(f"RGBb: rgb({r_b} {g_b} {b_b})") print(f"RGBp: rgb({r_p:.1f}% {g_p:.1f}% {b_p:.1f}%)") if args.copy: try: subprocess.run( ['wl-copy', hex_color], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) except Exception: try: p = subprocess.Popen( ['xclip', '-selection', 'clipboard'], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL ) p.communicate(input=hex_color.encode()) except Exception: pass sys.exit(0)else: sys.stderr.write("Cancelled by the user.\n") sys.exit(1)
А если лениво отсюда копировать, закоммитил в своём GitHub-овском репозитории других полезняшек: ds-colorpicker.
Вот. Пользуйтесь, и больше велосипедов богу СПО! 😁
ссылка на оригинал статьи https://habr.com/ru/articles/1060500/