mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-25 12:45:58 +01:00
internal: Support libhyprcursor (#5009)
woo --------- Co-authored-by: Mihai Fufezan <fufexan@protonmail.com>
This commit is contained in:
parent
e7a5db4852
commit
c3882bb832
18 changed files with 379 additions and 43 deletions
14
.github/actions/setup_base/action.yml
vendored
14
.github/actions/setup_base/action.yml
vendored
|
@ -12,6 +12,7 @@ runs:
|
||||||
- name: Get required pacman pkgs
|
- name: Get required pacman pkgs
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
sed -i -e "1i [extra-testing]\nInclude = /etc/pacman.d/mirrorlist" "/etc/pacman.conf"
|
||||||
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf
|
||||||
pacman --noconfirm --noprogressbar -Syyu
|
pacman --noconfirm --noprogressbar -Syyu
|
||||||
pacman --noconfirm --noprogressbar -Sy \
|
pacman --noconfirm --noprogressbar -Sy \
|
||||||
|
@ -51,7 +52,18 @@ runs:
|
||||||
wayland-protocols \
|
wayland-protocols \
|
||||||
xcb-util-errors \
|
xcb-util-errors \
|
||||||
xcb-util-renderutil \
|
xcb-util-renderutil \
|
||||||
xcb-util-wm
|
xcb-util-wm \
|
||||||
|
libzip \
|
||||||
|
librsvg
|
||||||
|
|
||||||
|
- name: Get hyprcursor-git
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/hyprwm/hyprcursor --recursive
|
||||||
|
cd hyprcursor
|
||||||
|
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
|
||||||
|
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||||
|
cmake --install build
|
||||||
|
|
||||||
- name: Get Xorg pacman pkgs
|
- name: Get Xorg pacman pkgs
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
|
@ -101,7 +101,7 @@ message(STATUS "Checking deps...")
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2) # we do not check for wlroots, as we provide it ourselves
|
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1 hyprlang>=0.3.2 hyprcursor) # we do not check for wlroots, as we provide it ourselves
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||||
|
|
||||||
|
|
72
flake.lock
72
flake.lock
|
@ -1,5 +1,29 @@
|
||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"hyprcursor": {
|
||||||
|
"inputs": {
|
||||||
|
"hyprlang": "hyprlang",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709942067,
|
||||||
|
"narHash": "sha256-DGU4zQDwIx6pXM6oHdA+89UU/QjqE05HiXOvigECJjI=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprcursor",
|
||||||
|
"rev": "a2233d4a2a58233457712acfd88d10a2a8a85711",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprcursor",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"hyprland-protocols": {
|
"hyprland-protocols": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
|
@ -24,6 +48,28 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hyprlang": {
|
"hyprlang": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"hyprcursor",
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709914708,
|
||||||
|
"narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=",
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprlang",
|
||||||
|
"rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hyprwm",
|
||||||
|
"repo": "hyprlang",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hyprlang_2": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
"nixpkgs"
|
"nixpkgs"
|
||||||
|
@ -33,11 +79,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1709775675,
|
"lastModified": 1709914708,
|
||||||
"narHash": "sha256-G+gIMUQBtfbbrnsM/OPJzebdqKFP6typplNCE7X8Szw=",
|
"narHash": "sha256-bR4o3mynoTa1Wi4ZTjbnsZ6iqVcPGriXp56bZh5UFTk=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprlang",
|
||||||
"rev": "f1db1a7e1faee2a5c67d03b6bd283da82eed3730",
|
"rev": "a685493fdbeec01ca8ccdf1f3655c044a8ce2fe2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -64,10 +110,11 @@
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
|
"hyprcursor": "hyprcursor",
|
||||||
"hyprland-protocols": "hyprland-protocols",
|
"hyprland-protocols": "hyprland-protocols",
|
||||||
"hyprlang": "hyprlang",
|
"hyprlang": "hyprlang_2",
|
||||||
"nixpkgs": "nixpkgs",
|
"nixpkgs": "nixpkgs",
|
||||||
"systems": "systems",
|
"systems": "systems_2",
|
||||||
"wlroots": "wlroots",
|
"wlroots": "wlroots",
|
||||||
"xdph": "xdph"
|
"xdph": "xdph"
|
||||||
}
|
}
|
||||||
|
@ -87,6 +134,21 @@
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"systems_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1689347949,
|
||||||
|
"narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default-linux",
|
||||||
|
"rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default-linux",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
"wlroots": {
|
"wlroots": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
|
|
|
@ -16,6 +16,12 @@
|
||||||
flake = false;
|
flake = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hyprcursor = {
|
||||||
|
url = "github:hyprwm/hyprcursor";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.systems.follows = "systems";
|
||||||
|
};
|
||||||
|
|
||||||
hyprland-protocols = {
|
hyprland-protocols = {
|
||||||
url = "github:hyprwm/hyprland-protocols";
|
url = "github:hyprwm/hyprland-protocols";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
binutils,
|
binutils,
|
||||||
cairo,
|
cairo,
|
||||||
git,
|
git,
|
||||||
|
hyprcursor,
|
||||||
hyprland-protocols,
|
hyprland-protocols,
|
||||||
hyprlang,
|
hyprlang,
|
||||||
jq,
|
jq,
|
||||||
|
@ -32,7 +33,6 @@
|
||||||
enableXWayland ? true,
|
enableXWayland ? true,
|
||||||
legacyRenderer ? false,
|
legacyRenderer ? false,
|
||||||
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
|
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
|
||||||
wrapRuntimeDeps ? true,
|
|
||||||
version ? "git",
|
version ? "git",
|
||||||
commit,
|
commit,
|
||||||
date,
|
date,
|
||||||
|
@ -75,6 +75,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||||
[
|
[
|
||||||
cairo
|
cairo
|
||||||
git
|
git
|
||||||
|
hyprcursor.dev
|
||||||
hyprland-protocols
|
hyprland-protocols
|
||||||
hyprlang
|
hyprlang
|
||||||
libdrm
|
libdrm
|
||||||
|
|
|
@ -21,6 +21,7 @@ in {
|
||||||
# Packages for variations of Hyprland, dependencies included.
|
# Packages for variations of Hyprland, dependencies included.
|
||||||
hyprland-packages = lib.composeManyExtensions [
|
hyprland-packages = lib.composeManyExtensions [
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
inputs.hyprcursor.overlays.default
|
||||||
inputs.hyprland-protocols.overlays.default
|
inputs.hyprland-protocols.overlays.default
|
||||||
inputs.hyprlang.overlays.default
|
inputs.hyprlang.overlays.default
|
||||||
self.overlays.wlroots-hyprland
|
self.overlays.wlroots-hyprland
|
||||||
|
|
|
@ -37,15 +37,16 @@ diff --git a/src/meson.build b/src/meson.build
|
||||||
index 45701f5f..3505cefe 100644
|
index 45701f5f..3505cefe 100644
|
||||||
--- a/src/meson.build
|
--- a/src/meson.build
|
||||||
+++ b/src/meson.build
|
+++ b/src/meson.build
|
||||||
@@ -9,17 +9,17 @@ executable('Hyprland', src,
|
@@ -9,7 +9,7 @@ executable('Hyprland', src,
|
||||||
server_protos,
|
server_protos,
|
||||||
dependency('wayland-server'),
|
dependency('wayland-server'),
|
||||||
dependency('wayland-client'),
|
dependency('wayland-client'),
|
||||||
- wlroots.get_variable('wlroots'),
|
- wlroots.get_variable('wlroots'),
|
||||||
+ dependency('wlroots'),
|
+ dependency('wlroots'),
|
||||||
dependency('cairo'),
|
dependency('cairo'),
|
||||||
|
dependency('hyprcursor'),
|
||||||
dependency('hyprlang', version: '>= 0.3.2'),
|
dependency('hyprlang', version: '>= 0.3.2'),
|
||||||
dependency('libdrm'),
|
@@ -16,12 +16,12 @@ executable('Hyprland', src,
|
||||||
dependency('egl'),
|
dependency('egl'),
|
||||||
dependency('xkbcommon'),
|
dependency('xkbcommon'),
|
||||||
dependency('libinput'),
|
dependency('libinput'),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Compositor.hpp"
|
#include "Compositor.hpp"
|
||||||
#include "helpers/Splashes.hpp"
|
#include "helpers/Splashes.hpp"
|
||||||
#include "config/ConfigValue.hpp"
|
#include "config/ConfigValue.hpp"
|
||||||
|
#include "managers/CursorManager.hpp"
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "debug/HyprCtl.hpp"
|
#include "debug/HyprCtl.hpp"
|
||||||
|
@ -182,18 +183,6 @@ void CCompositor::initServer() {
|
||||||
m_sWLRCursor = wlr_cursor_create();
|
m_sWLRCursor = wlr_cursor_create();
|
||||||
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout);
|
||||||
|
|
||||||
if (const auto XCURSORENV = getenv("XCURSOR_SIZE"); !XCURSORENV || std::string(XCURSORENV).empty())
|
|
||||||
setenv("XCURSOR_SIZE", "24", true);
|
|
||||||
|
|
||||||
const auto XCURSORENV = getenv("XCURSOR_SIZE");
|
|
||||||
int cursorSize = 24;
|
|
||||||
try {
|
|
||||||
cursorSize = std::stoi(XCURSORENV);
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "XCURSOR_SIZE invalid in check #2? ({})", XCURSORENV); }
|
|
||||||
|
|
||||||
m_sWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, cursorSize);
|
|
||||||
wlr_xcursor_manager_load(m_sWLRXCursorMgr, 1);
|
|
||||||
|
|
||||||
m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0");
|
m_sSeat.seat = wlr_seat_create(m_sWLDisplay, "seat0");
|
||||||
|
|
||||||
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
||||||
|
@ -422,6 +411,7 @@ void CCompositor::cleanup() {
|
||||||
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
wl_display_destroy_clients(g_pCompositor->m_sWLDisplay);
|
||||||
|
|
||||||
g_pDecorationPositioner.reset();
|
g_pDecorationPositioner.reset();
|
||||||
|
g_pCursorManager.reset();
|
||||||
g_pPluginSystem.reset();
|
g_pPluginSystem.reset();
|
||||||
g_pHyprNotificationOverlay.reset();
|
g_pHyprNotificationOverlay.reset();
|
||||||
g_pDebugOverlay.reset();
|
g_pDebugOverlay.reset();
|
||||||
|
@ -511,6 +501,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||||
|
|
||||||
Debug::log(LOG, "Creating the DecorationPositioner!");
|
Debug::log(LOG, "Creating the DecorationPositioner!");
|
||||||
g_pDecorationPositioner = std::make_unique<CDecorationPositioner>();
|
g_pDecorationPositioner = std::make_unique<CDecorationPositioner>();
|
||||||
|
|
||||||
|
Debug::log(LOG, "Creating the CursorManager!");
|
||||||
|
g_pCursorManager = std::make_unique<CCursorManager>();
|
||||||
} break;
|
} break;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,6 @@ class CCompositor {
|
||||||
wlr_layer_shell_v1* m_sWLRLayerShell;
|
wlr_layer_shell_v1* m_sWLRLayerShell;
|
||||||
wlr_xdg_shell* m_sWLRXDGShell;
|
wlr_xdg_shell* m_sWLRXDGShell;
|
||||||
wlr_cursor* m_sWLRCursor;
|
wlr_cursor* m_sWLRCursor;
|
||||||
wlr_xcursor_manager* m_sWLRXCursorMgr;
|
|
||||||
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
|
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
|
||||||
wlr_output_manager_v1* m_sWLROutputMgr;
|
wlr_output_manager_v1* m_sWLROutputMgr;
|
||||||
wlr_presentation* m_sWLRPresentation;
|
wlr_presentation* m_sWLRPresentation;
|
||||||
|
|
|
@ -347,6 +347,7 @@ CConfigManager::CConfigManager() {
|
||||||
m_pConfig->addConfigValue("misc:close_special_on_empty", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("misc:close_special_on_empty", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("misc:background_color", Hyprlang::INT{0xff111111});
|
m_pConfig->addConfigValue("misc:background_color", Hyprlang::INT{0xff111111});
|
||||||
m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0});
|
m_pConfig->addConfigValue("misc:new_window_takes_over_fullscreen", Hyprlang::INT{0});
|
||||||
|
m_pConfig->addConfigValue("misc:enable_hyprcursor", Hyprlang::INT{1});
|
||||||
|
|
||||||
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1});
|
||||||
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
|
m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1});
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
|
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "../managers/CursorManager.hpp"
|
||||||
|
|
||||||
static void trimTrailingComma(std::string& str) {
|
static void trimTrailingComma(std::string& str) {
|
||||||
if (!str.empty() && str.back() == ',')
|
if (!str.empty() && str.back() == ',')
|
||||||
|
@ -1045,16 +1046,7 @@ std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request)
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return "size not positive";
|
return "size not positive";
|
||||||
|
|
||||||
wlr_xcursor_manager_destroy(g_pCompositor->m_sWLRXCursorMgr);
|
g_pCursorManager->changeTheme(theme, size);
|
||||||
|
|
||||||
g_pCompositor->m_sWLRXCursorMgr = wlr_xcursor_manager_create(theme.c_str(), size);
|
|
||||||
|
|
||||||
setenv("XCURSOR_SIZE", SIZESTR.c_str(), true);
|
|
||||||
setenv("XCURSOR_THEME", theme.c_str(), true);
|
|
||||||
|
|
||||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
|
||||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, m->scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../helpers/WLClasses.hpp"
|
#include "../helpers/WLClasses.hpp"
|
||||||
#include "../managers/input/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
#include "../managers/CursorManager.hpp"
|
||||||
|
|
||||||
// ------------------------------ //
|
// ------------------------------ //
|
||||||
// __ __ _____ _____ _____ //
|
// __ __ _____ _____ _____ //
|
||||||
|
@ -69,10 +70,10 @@ void Events::listener_readyXWayland(wl_listener* listener, void* data) {
|
||||||
|
|
||||||
wlr_xwayland_set_seat(g_pXWaylandManager->m_sWLRXWayland, g_pCompositor->m_sSeat.seat);
|
wlr_xwayland_set_seat(g_pXWaylandManager->m_sWLRXWayland, g_pCompositor->m_sSeat.seat);
|
||||||
|
|
||||||
const auto XCURSOR = wlr_xcursor_manager_get_xcursor(g_pCompositor->m_sWLRXCursorMgr, "left_ptr", 1);
|
const auto CURSOR = g_pCursorManager->dataFor("left_ptr");
|
||||||
if (XCURSOR) {
|
if (CURSOR.surface) {
|
||||||
wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, XCURSOR->images[0]->buffer, XCURSOR->images[0]->width * 4, XCURSOR->images[0]->width,
|
wlr_xwayland_set_cursor(g_pXWaylandManager->m_sWLRXWayland, cairo_image_surface_get_data(CURSOR.surface), cairo_image_surface_get_stride(CURSOR.surface), CURSOR.size,
|
||||||
XCURSOR->images[0]->height, XCURSOR->images[0]->hotspot_x, XCURSOR->images[0]->hotspot_y);
|
CURSOR.size, CURSOR.hotspotX, CURSOR.hotspotY);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ROOT = xcb_setup_roots_iterator(xcb_get_setup(XCBCONNECTION)).data->root;
|
const auto ROOT = xcb_setup_roots_iterator(xcb_get_setup(XCBCONNECTION)).data->root;
|
||||||
|
|
|
@ -164,8 +164,6 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
|
|
||||||
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||||
|
|
||||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
|
||||||
|
|
||||||
Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output);
|
Debug::log(LOG, "Added new monitor with name {} at {:j0} with size {:j0}, pointer {:x}", output->name, vecPosition, vecPixelSize, (uintptr_t)output);
|
||||||
|
|
||||||
setupDefaultWS(monitorRule);
|
setupDefaultWS(monitorRule);
|
||||||
|
@ -192,8 +190,6 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||||
g_pCompositor->setActiveMonitor(this);
|
g_pCompositor->setActiveMonitor(this);
|
||||||
|
|
||||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
|
||||||
|
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(ID);
|
g_pHyprRenderer->arrangeLayersForMonitor(ID);
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(ID);
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,6 @@ extern "C" {
|
||||||
#include <wlr/types/wlr_server_decoration.h>
|
#include <wlr/types/wlr_server_decoration.h>
|
||||||
#include <wlr/types/wlr_viewporter.h>
|
#include <wlr/types/wlr_viewporter.h>
|
||||||
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
#include <wlr/types/wlr_virtual_keyboard_v1.h>
|
||||||
#include <wlr/types/wlr_xcursor_manager.h>
|
|
||||||
#include <wlr/types/wlr_xdg_activation_v1.h>
|
#include <wlr/types/wlr_xdg_activation_v1.h>
|
||||||
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
#include <wlr/types/wlr_xdg_decoration_v1.h>
|
||||||
#include <wlr/types/wlr_xdg_output_v1.h>
|
#include <wlr/types/wlr_xdg_output_v1.h>
|
||||||
|
@ -76,6 +75,7 @@ extern "C" {
|
||||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
#include <wlr/util/region.h>
|
#include <wlr/util/region.h>
|
||||||
|
#include <wlr/util/edges.h>
|
||||||
#include <wlr/types/wlr_tablet_pad.h>
|
#include <wlr/types/wlr_tablet_pad.h>
|
||||||
#include <wlr/types/wlr_tablet_tool.h>
|
#include <wlr/types/wlr_tablet_tool.h>
|
||||||
#include <wlr/types/wlr_tablet_v2.h>
|
#include <wlr/types/wlr_tablet_v2.h>
|
||||||
|
|
200
src/managers/CursorManager.cpp
Normal file
200
src/managers/CursorManager.cpp
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
#include "CursorManager.hpp"
|
||||||
|
#include "Compositor.hpp"
|
||||||
|
#include "../config/ConfigValue.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <wlr/interfaces/wlr_buffer.h>
|
||||||
|
#include <wlr/types/wlr_xcursor_manager.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cursorAnimTimer(void* data) {
|
||||||
|
g_pCursorManager->tickAnimatedCursor();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCursorManager::CCursorManager() {
|
||||||
|
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str());
|
||||||
|
|
||||||
|
// find default size. First, HYPRCURSOR_SIZE, then XCURSOR_SIZE, then 24
|
||||||
|
auto SIZE = getenv("HYPRCURSOR_SIZE");
|
||||||
|
if (SIZE) {
|
||||||
|
try {
|
||||||
|
m_iSize = std::stoi(SIZE);
|
||||||
|
} catch (...) { ; }
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE = getenv("XCURSOR_SIZE");
|
||||||
|
if (SIZE && m_iSize == 0) {
|
||||||
|
try {
|
||||||
|
m_iSize = std::stoi(SIZE);
|
||||||
|
} catch (...) { ; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iSize == 0)
|
||||||
|
m_iSize = 24;
|
||||||
|
|
||||||
|
m_pWLRXCursorMgr = wlr_xcursor_manager_create(nullptr, m_iSize);
|
||||||
|
wlr_xcursor_manager_load(m_pWLRXCursorMgr, 1.0);
|
||||||
|
|
||||||
|
m_pAnimationTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ::cursorAnimTimer, nullptr);
|
||||||
|
|
||||||
|
updateTheme();
|
||||||
|
|
||||||
|
g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateTheme(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::dropBufferRef(CCursorManager::CCursorBuffer* ref) {
|
||||||
|
std::erase_if(m_vCursorBuffers, [ref](const auto& buf) { return buf.get() == ref; });
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cursorBufferDestroy(struct wlr_buffer* wlr_buffer) {
|
||||||
|
CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base);
|
||||||
|
g_pCursorManager->dropBufferRef(buffer->parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cursorBufferBeginDataPtr(struct wlr_buffer* wlr_buffer, uint32_t flags, void** data, uint32_t* format, size_t* stride) {
|
||||||
|
CCursorManager::CCursorBuffer::SCursorWlrBuffer* buffer = wl_container_of(wlr_buffer, buffer, base);
|
||||||
|
|
||||||
|
if (flags & WLR_BUFFER_DATA_PTR_ACCESS_WRITE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*data = cairo_image_surface_get_data(buffer->surface);
|
||||||
|
*stride = cairo_image_surface_get_stride(buffer->surface);
|
||||||
|
*format = DRM_FORMAT_ARGB8888;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cursorBufferEndDataPtr(struct wlr_buffer* wlr_buffer) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
static const wlr_buffer_impl bufferImpl = {
|
||||||
|
.destroy = cursorBufferDestroy,
|
||||||
|
.begin_data_ptr_access = cursorBufferBeginDataPtr,
|
||||||
|
.end_data_ptr_access = cursorBufferEndDataPtr,
|
||||||
|
};
|
||||||
|
|
||||||
|
CCursorManager::CCursorBuffer::CCursorBuffer(cairo_surface_t* surf, const Vector2D& size_, const Vector2D& hot_) : size(size_), hotspot(hot_) {
|
||||||
|
wlrBuffer.surface = surf;
|
||||||
|
wlr_buffer_init(&wlrBuffer.base, &bufferImpl, size.x, size.y);
|
||||||
|
wlrBuffer.parent = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CCursorManager::CCursorBuffer::~CCursorBuffer() {
|
||||||
|
; // will be freed in .destroy
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_buffer* CCursorManager::getCursorBuffer() {
|
||||||
|
return !m_vCursorBuffers.empty() ? &m_vCursorBuffers.back()->wlrBuffer.base : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::setCursorSurface(wlr_surface* surf, const Vector2D& hotspot) {
|
||||||
|
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspot.x, hotspot.y);
|
||||||
|
|
||||||
|
m_bOurBufferConnected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::setCursorFromName(const std::string& name) {
|
||||||
|
|
||||||
|
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("misc:enable_hyprcursor");
|
||||||
|
|
||||||
|
if (!m_pHyprcursor->valid() || !*PUSEHYPRCURSOR) {
|
||||||
|
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, m_pWLRXCursorMgr, name.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sCurrentCursorShapeData = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo);
|
||||||
|
|
||||||
|
if (m_sCurrentCursorShapeData.images.size() < 1) {
|
||||||
|
Debug::log(ERR, "BUG THIS: No cursor returned by getShape()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>(m_sCurrentCursorShapeData.images[0].surface,
|
||||||
|
Vector2D{m_sCurrentCursorShapeData.images[0].size, m_sCurrentCursorShapeData.images[0].size},
|
||||||
|
Vector2D{m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY}));
|
||||||
|
|
||||||
|
if (g_pCompositor->m_sWLRCursor)
|
||||||
|
wlr_cursor_set_buffer(g_pCompositor->m_sWLRCursor, getCursorBuffer(), m_sCurrentCursorShapeData.images[0].hotspotX, m_sCurrentCursorShapeData.images[0].hotspotY,
|
||||||
|
m_fCursorScale);
|
||||||
|
|
||||||
|
m_bOurBufferConnected = true;
|
||||||
|
|
||||||
|
if (m_sCurrentCursorShapeData.images.size() > 1) {
|
||||||
|
// animated
|
||||||
|
wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[0].delay);
|
||||||
|
m_iCurrentAnimationFrame = 0;
|
||||||
|
} else {
|
||||||
|
// disarm
|
||||||
|
wl_event_source_timer_update(m_pAnimationTimer, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::tickAnimatedCursor() {
|
||||||
|
if (m_sCurrentCursorShapeData.images.size() < 2 || !m_bOurBufferConnected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_iCurrentAnimationFrame++;
|
||||||
|
if ((size_t)m_iCurrentAnimationFrame >= m_sCurrentCursorShapeData.images.size())
|
||||||
|
m_iCurrentAnimationFrame = 0;
|
||||||
|
|
||||||
|
m_vCursorBuffers.emplace_back(std::make_unique<CCursorBuffer>(
|
||||||
|
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].surface,
|
||||||
|
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].size},
|
||||||
|
Vector2D{m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY}));
|
||||||
|
|
||||||
|
if (g_pCompositor->m_sWLRCursor)
|
||||||
|
wlr_cursor_set_buffer(g_pCompositor->m_sWLRCursor, getCursorBuffer(), m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotX,
|
||||||
|
m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].hotspotY, m_fCursorScale);
|
||||||
|
|
||||||
|
wl_event_source_timer_update(m_pAnimationTimer, m_sCurrentCursorShapeData.images[m_iCurrentAnimationFrame].delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
SCursorImageData CCursorManager::dataFor(const std::string& name) {
|
||||||
|
const auto IMAGES = m_pHyprcursor->getShape(name.c_str(), m_sCurrentStyleInfo);
|
||||||
|
|
||||||
|
if (IMAGES.images.empty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return IMAGES.images[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::updateTheme() {
|
||||||
|
float highestScale = 1.0;
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
if (m->scale > highestScale)
|
||||||
|
highestScale = m->scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highestScale * m_iSize == m_sCurrentStyleInfo.size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_sCurrentStyleInfo.size && m_pHyprcursor->valid())
|
||||||
|
m_pHyprcursor->cursorSurfaceStyleDone(m_sCurrentStyleInfo);
|
||||||
|
|
||||||
|
m_sCurrentStyleInfo.size = m_iSize * highestScale;
|
||||||
|
m_fCursorScale = highestScale;
|
||||||
|
|
||||||
|
if (m_pHyprcursor->valid())
|
||||||
|
m_pHyprcursor->loadThemeStyle(m_sCurrentStyleInfo);
|
||||||
|
|
||||||
|
setCursorFromName("left_ptr");
|
||||||
|
|
||||||
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||||
|
m->forceFullFrames = 5;
|
||||||
|
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCursorManager::changeTheme(const std::string& name, const int size) {
|
||||||
|
m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(name.empty() ? "" : name.c_str());
|
||||||
|
m_szTheme = name;
|
||||||
|
m_iSize = size;
|
||||||
|
|
||||||
|
setenv("XCURSOR_SIZE", std::to_string(m_iSize).c_str(), true);
|
||||||
|
setenv("XCURSOR_THEME", name.c_str(), true);
|
||||||
|
|
||||||
|
updateTheme();
|
||||||
|
}
|
69
src/managers/CursorManager.hpp
Normal file
69
src/managers/CursorManager.hpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <hyprcursor/hyprcursor.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include "../includes.hpp"
|
||||||
|
#include "../helpers/Vector2D.hpp"
|
||||||
|
|
||||||
|
struct wlr_buffer;
|
||||||
|
struct wlr_xcursor_manager;
|
||||||
|
|
||||||
|
class CCursorManager {
|
||||||
|
public:
|
||||||
|
CCursorManager();
|
||||||
|
|
||||||
|
wlr_buffer* getCursorBuffer();
|
||||||
|
|
||||||
|
void setCursorFromName(const std::string& name);
|
||||||
|
void setCursorSurface(wlr_surface* surf, const Vector2D& hotspot);
|
||||||
|
|
||||||
|
void changeTheme(const std::string& name, const int size);
|
||||||
|
void updateTheme();
|
||||||
|
SCursorImageData dataFor(const std::string& name); // for xwayland
|
||||||
|
|
||||||
|
void tickAnimatedCursor();
|
||||||
|
|
||||||
|
class CCursorBuffer {
|
||||||
|
public:
|
||||||
|
CCursorBuffer(cairo_surface_t* surf, const Vector2D& size, const Vector2D& hotspot);
|
||||||
|
~CCursorBuffer();
|
||||||
|
|
||||||
|
struct SCursorWlrBuffer {
|
||||||
|
wlr_buffer base;
|
||||||
|
cairo_surface_t* surface = nullptr;
|
||||||
|
bool dropped = false;
|
||||||
|
CCursorBuffer* parent = nullptr;
|
||||||
|
} wlrBuffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector2D size;
|
||||||
|
Vector2D hotspot;
|
||||||
|
|
||||||
|
friend class CCursorManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
void dropBufferRef(CCursorBuffer* ref);
|
||||||
|
|
||||||
|
bool m_bOurBufferConnected = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<CCursorBuffer>> m_vCursorBuffers;
|
||||||
|
|
||||||
|
std::unique_ptr<Hyprcursor::CHyprcursorManager> m_pHyprcursor;
|
||||||
|
|
||||||
|
std::string m_szTheme = "";
|
||||||
|
int m_iSize = 24;
|
||||||
|
float m_fCursorScale = 1.0;
|
||||||
|
|
||||||
|
Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo;
|
||||||
|
|
||||||
|
wl_event_source* m_pAnimationTimer = nullptr;
|
||||||
|
int m_iCurrentAnimationFrame = 0;
|
||||||
|
Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData;
|
||||||
|
|
||||||
|
// xcursor fallback
|
||||||
|
wlr_xcursor_manager* m_pWLRXCursorMgr = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<CCursorManager> g_pCursorManager;
|
|
@ -11,6 +11,7 @@ executable('Hyprland', src,
|
||||||
dependency('wayland-client'),
|
dependency('wayland-client'),
|
||||||
wlroots.get_variable('wlroots'),
|
wlroots.get_variable('wlroots'),
|
||||||
dependency('cairo'),
|
dependency('cairo'),
|
||||||
|
dependency('hyprcursor'),
|
||||||
dependency('hyprlang', version: '>= 0.3.2'),
|
dependency('hyprlang', version: '>= 0.3.2'),
|
||||||
dependency('libdrm'),
|
dependency('libdrm'),
|
||||||
dependency('egl'),
|
dependency('egl'),
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../helpers/Region.hpp"
|
#include "../helpers/Region.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "../config/ConfigValue.hpp"
|
#include "../config/ConfigValue.hpp"
|
||||||
|
#include "../managers/CursorManager.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
|
@ -2193,7 +2194,7 @@ void CHyprRenderer::setCursorFromName(const std::string& name, bool force) {
|
||||||
if (m_bCursorHidden && !force)
|
if (m_bCursorHidden && !force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str());
|
g_pCursorManager->setCursorFromName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprRenderer::ensureCursorRenderingMode() {
|
void CHyprRenderer::ensureCursorRenderingMode() {
|
||||||
|
|
Loading…
Reference in a new issue