mirror of
https://github.com/hyprwm/hyprlock.git
synced 2025-02-03 16:29:48 +01:00
Core: move to hyprwayland-scanner (#624)
nix: add hyprwayland-scanner dep flake.lock: update --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
This commit is contained in:
parent
77d194c1e9
commit
753c538dea
21 changed files with 724 additions and 882 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -8,6 +8,6 @@ Makefile
|
|||
cmake_install.cmake
|
||||
build/
|
||||
compile_commands.json
|
||||
protocols/*.c
|
||||
protocols/*.h
|
||||
protocols/*.cpp
|
||||
protocols/*.hpp
|
||||
*.kdev4
|
||||
|
|
|
@ -57,6 +57,7 @@ message(STATUS "Checking deps...")
|
|||
find_package(Threads REQUIRED)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(hyprwayland-scanner 0.4.4 REQUIRED)
|
||||
pkg_check_modules(
|
||||
deps
|
||||
REQUIRED
|
||||
|
@ -85,54 +86,49 @@ target_link_libraries(hyprlock PRIVATE pam rt Threads::Threads PkgConfig::deps
|
|||
OpenGL::EGL OpenGL::GL)
|
||||
|
||||
# protocols
|
||||
find_program(WaylandScanner NAMES wayland-scanner)
|
||||
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||
execute_process(
|
||||
COMMAND pkg-config --variable=pkgdatadir wayland-protocols
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
|
||||
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
|
||||
message(
|
||||
STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}")
|
||||
|
||||
function(protocol protoPath protoName external)
|
||||
function(protocolnew protoPath protoName external)
|
||||
if(external)
|
||||
execute_process(
|
||||
COMMAND ${WaylandScanner} client-header ${protoPath}
|
||||
protocols/${protoName}-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
execute_process(
|
||||
COMMAND ${WaylandScanner} private-code ${protoPath}
|
||||
protocols/${protoName}-protocol.c
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(hyprlock PRIVATE protocols/${protoName}-protocol.c)
|
||||
set(path ${CMAKE_SOURCE_DIR}/${protoPath})
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND
|
||||
${WaylandScanner} client-header ${WAYLAND_PROTOCOLS_DIR}/${protoPath}
|
||||
protocols/${protoName}-protocol.h
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
execute_process(
|
||||
COMMAND
|
||||
${WaylandScanner} private-code ${WAYLAND_PROTOCOLS_DIR}/${protoPath}
|
||||
protocols/${protoName}-protocol.c
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(hyprlock PRIVATE protocols/${protoName}-protocol.c)
|
||||
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp
|
||||
COMMAND hyprwayland-scanner --client ${path}/${protoName}.xml
|
||||
${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(hyprlock PRIVATE protocols/${protoName}.cpp
|
||||
protocols/${protoName}.hpp)
|
||||
endfunction()
|
||||
function(protocolWayland)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp
|
||||
${CMAKE_SOURCE_DIR}/protocols/wayland.hpp
|
||||
COMMAND hyprwayland-scanner --wayland-enums --client
|
||||
${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
target_sources(hyprlock PRIVATE protocols/wayland.cpp protocols/wayland.hpp)
|
||||
endfunction()
|
||||
|
||||
make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so
|
||||
# the dir won't be there
|
||||
protocol("staging/ext-session-lock/ext-session-lock-v1.xml"
|
||||
"ext-session-lock-v1" false)
|
||||
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
|
||||
protocol("unstable/tablet/tablet-unstable-v2.xml" "tablet-unstable-v2" false)
|
||||
protocol("staging/fractional-scale/fractional-scale-v1.xml"
|
||||
"fractional-scale-v1" false)
|
||||
protocol("stable/viewporter/viewporter.xml" "viewporter" false)
|
||||
protocol("protocols/wlr-screencopy-unstable-v1.xml"
|
||||
"wlr-screencopy-unstable-v1" true)
|
||||
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml"
|
||||
"linux-dmabuf-unstable-v1" false)
|
||||
|
||||
protocolwayland()
|
||||
|
||||
protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
|
||||
protocolnew("staging/ext-session-lock" "ext-session-lock-v1" false)
|
||||
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
|
||||
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
|
||||
protocolnew("stable/viewporter" "viewporter" false)
|
||||
protocolnew("staging/cursor-shape" "cursor-shape-v1" false)
|
||||
protocolnew("stable/tablet" "tablet-v2" false)
|
||||
|
||||
# Installation
|
||||
install(TARGETS hyprlock)
|
||||
|
|
|
@ -28,6 +28,7 @@ You need the following dependencies
|
|||
- wayland-client
|
||||
- wayland-protocols
|
||||
- mesa
|
||||
- hyprwayland-scanner
|
||||
|
||||
And the development libraries for the following
|
||||
- cairo
|
||||
|
|
48
flake.lock
48
flake.lock
|
@ -13,11 +13,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733684019,
|
||||
"narHash": "sha256-2kYREgmSmbLsmDpLEq96hxVAU3qz8aCvVhF65yCFZHY=",
|
||||
"lastModified": 1734906236,
|
||||
"narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprgraphics",
|
||||
"rev": "fb2c0268645a77403af3b8a4ce8fa7ba5917f15d",
|
||||
"rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -39,11 +39,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1734364628,
|
||||
"narHash": "sha256-ii8fzJfI953n/EmIxVvq64ZAwhvwuuPHWfGd61/mJG8=",
|
||||
"lastModified": 1735393019,
|
||||
"narHash": "sha256-NPpqA8rtmDLsEmZOmz+qR67zsB6Y503Jnv+nSFLKJZ8=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprlang",
|
||||
"rev": "16e59c1eb13d9fb6de066f54e7555eb5e8a4aba5",
|
||||
"rev": "55608efdaa387af7bfdc0eddb404c409958efa43",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -62,11 +62,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1733502241,
|
||||
"narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=",
|
||||
"lastModified": 1735316583,
|
||||
"narHash": "sha256-AiiUwHWHfEdpFzXy7l1x3zInCUa1xcRMrbZ1XRSkzwU=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprutils",
|
||||
"rev": "104117aed6dd68561be38b50f218190aa47f2cd8",
|
||||
"rev": "8f15d45b120b33712f6db477fe5ffb18034d0ea8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -75,13 +75,36 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"hyprwayland-scanner": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": [
|
||||
"systems"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1735493474,
|
||||
"narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hyprwm",
|
||||
"repo": "hyprwayland-scanner",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1734119587,
|
||||
"narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=",
|
||||
"lastModified": 1735291276,
|
||||
"narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5",
|
||||
"rev": "634fd46801442d760e09493a794c4f15db2d0cbb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -96,6 +119,7 @@
|
|||
"hyprgraphics": "hyprgraphics",
|
||||
"hyprlang": "hyprlang",
|
||||
"hyprutils": "hyprutils",
|
||||
"hyprwayland-scanner": "hyprwayland-scanner",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"systems": "systems"
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
inputs.systems.follows = "systems";
|
||||
inputs.hyprutils.follows = "hyprutils";
|
||||
};
|
||||
|
||||
hyprwayland-scanner = {
|
||||
url = "github:hyprwm/hyprwayland-scanner";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs.systems.follows = "systems";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
hyprgraphics,
|
||||
hyprlang,
|
||||
hyprutils,
|
||||
hyprwayland-scanner,
|
||||
pam,
|
||||
pango,
|
||||
sdbus-cpp,
|
||||
|
@ -33,6 +34,7 @@ stdenv.mkDerivation {
|
|||
nativeBuildInputs = [
|
||||
cmake
|
||||
pkg-config
|
||||
hyprwayland-scanner
|
||||
wayland-scanner
|
||||
];
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ in {
|
|||
inputs.hyprgraphics.overlays.default
|
||||
inputs.hyprlang.overlays.default
|
||||
inputs.hyprutils.overlays.default
|
||||
inputs.hyprwayland-scanner.overlays.default
|
||||
inputs.self.overlays.sdbuscpp
|
||||
(final: prev: {
|
||||
hyprlock = prev.callPackage ./default.nix {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
#include "CursorShape.hpp"
|
||||
#include "hyprlock.hpp"
|
||||
#include "Seat.hpp"
|
||||
|
||||
CCursorShape::CCursorShape(wp_cursor_shape_manager_v1* mgr) : mgr(mgr) {
|
||||
if (!g_pHyprlock->m_pPointer)
|
||||
CCursorShape::CCursorShape(SP<CCWpCursorShapeManagerV1> mgr) : mgr(mgr) {
|
||||
if (!g_pSeatManager->m_pPointer)
|
||||
return;
|
||||
|
||||
dev = wp_cursor_shape_manager_v1_get_pointer(mgr, g_pHyprlock->m_pPointer);
|
||||
dev = makeShared<CCWpCursorShapeDeviceV1>(mgr->sendGetPointer(g_pSeatManager->m_pPointer->resource()));
|
||||
}
|
||||
|
||||
void CCursorShape::setShape(const wp_cursor_shape_device_v1_shape shape) {
|
||||
void CCursorShape::setShape(const wpCursorShapeDeviceV1Shape shape) {
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
wp_cursor_shape_device_v1_set_shape(dev, lastCursorSerial, shape);
|
||||
dev->sendSetShape(lastCursorSerial, shape);
|
||||
}
|
||||
|
||||
void CCursorShape::hideCursor() {
|
||||
wl_pointer_set_cursor(g_pHyprlock->m_pPointer, lastCursorSerial, nullptr, 0, 0);
|
||||
g_pSeatManager->m_pPointer->sendSetCursor(lastCursorSerial, nullptr, 0, 0);
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "cursor-shape-v1-protocol.h"
|
||||
#include "../defines.hpp"
|
||||
#include "cursor-shape-v1.hpp"
|
||||
|
||||
class CCursorShape {
|
||||
public:
|
||||
CCursorShape(wp_cursor_shape_manager_v1* mgr);
|
||||
CCursorShape(SP<CCWpCursorShapeManagerV1> mgr);
|
||||
|
||||
void setShape(const wp_cursor_shape_device_v1_shape shape);
|
||||
void setShape(const wpCursorShapeDeviceV1Shape shape);
|
||||
void hideCursor();
|
||||
|
||||
uint32_t lastCursorSerial = 0;
|
||||
|
||||
private:
|
||||
wp_cursor_shape_manager_v1* mgr = nullptr;
|
||||
wp_cursor_shape_device_v1* dev = nullptr;
|
||||
SP<CCWpCursorShapeManagerV1> mgr = nullptr;
|
||||
SP<CCWpCursorShapeDeviceV1> dev = nullptr;
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <memory>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
|
|
|
@ -5,51 +5,13 @@
|
|||
#include "../renderer/Renderer.hpp"
|
||||
#include "src/config/ConfigManager.hpp"
|
||||
|
||||
static void handleConfigure(void* data, ext_session_lock_surface_v1* surf, uint32_t serial, uint32_t width, uint32_t height) {
|
||||
const auto PSURF = (CSessionLockSurface*)data;
|
||||
PSURF->configure({(double)width, (double)height}, serial);
|
||||
}
|
||||
|
||||
static const ext_session_lock_surface_v1_listener lockListener = {
|
||||
.configure = handleConfigure,
|
||||
};
|
||||
|
||||
static void handlePreferredScale(void* data, wp_fractional_scale_v1* wp_fractional_scale_v1, uint32_t scale) {
|
||||
const auto PSURF = (CSessionLockSurface*)data;
|
||||
const bool SAMESCALE = PSURF->fractionalScale == scale / 120.0;
|
||||
PSURF->fractionalScale = scale / 120.0;
|
||||
|
||||
Debug::log(LOG, "Got fractional scale: {}", PSURF->fractionalScale);
|
||||
|
||||
if (!SAMESCALE && PSURF->readyForFrame)
|
||||
PSURF->onScaleUpdate();
|
||||
}
|
||||
|
||||
static const wp_fractional_scale_v1_listener fsListener = {
|
||||
.preferred_scale = handlePreferredScale,
|
||||
};
|
||||
|
||||
CSessionLockSurface::~CSessionLockSurface() {
|
||||
if (fractional) {
|
||||
wp_viewport_destroy(viewport);
|
||||
wp_fractional_scale_v1_destroy(fractional);
|
||||
}
|
||||
|
||||
if (eglWindow)
|
||||
wl_egl_window_destroy(eglWindow);
|
||||
|
||||
if (lockSurface)
|
||||
ext_session_lock_surface_v1_destroy(lockSurface);
|
||||
|
||||
if (surface)
|
||||
wl_surface_destroy(surface);
|
||||
|
||||
if (frameCallback)
|
||||
wl_callback_destroy(frameCallback);
|
||||
}
|
||||
|
||||
CSessionLockSurface::CSessionLockSurface(COutput* output) : output(output) {
|
||||
surface = wl_compositor_create_surface(g_pHyprlock->getCompositor());
|
||||
surface = makeShared<CCWlSurface>(g_pHyprlock->getCompositor()->sendCreateSurface());
|
||||
|
||||
if (!surface) {
|
||||
Debug::log(CRIT, "Couldn't create wl_surface");
|
||||
|
@ -62,11 +24,19 @@ CSessionLockSurface::CSessionLockSurface(COutput* output) : output(output) {
|
|||
const auto PVIEWPORTER = g_pHyprlock->getViewporter();
|
||||
|
||||
if (ENABLE_FSV1 && PFRACTIONALMGR && PVIEWPORTER) {
|
||||
fractional = wp_fractional_scale_manager_v1_get_fractional_scale(PFRACTIONALMGR, surface);
|
||||
if (fractional) {
|
||||
wp_fractional_scale_v1_add_listener(fractional, &fsListener, this);
|
||||
viewport = wp_viewporter_get_viewport(PVIEWPORTER, surface);
|
||||
}
|
||||
fractional = makeShared<CCWpFractionalScaleV1>(PFRACTIONALMGR->sendGetFractionalScale(surface->resource()));
|
||||
|
||||
fractional->setPreferredScale([this](CCWpFractionalScaleV1*, uint32_t scale) {
|
||||
const bool SAMESCALE = fractionalScale == scale / 120.0;
|
||||
fractionalScale = scale / 120.0;
|
||||
|
||||
Debug::log(LOG, "Got fractional scale: {:.1f}%", fractionalScale * 100.F);
|
||||
|
||||
if (!SAMESCALE && readyForFrame)
|
||||
onScaleUpdate();
|
||||
});
|
||||
|
||||
viewport = makeShared<CCWpViewport>(PVIEWPORTER->sendGetViewport(surface->resource()));
|
||||
}
|
||||
|
||||
if (!PFRACTIONALMGR)
|
||||
|
@ -74,14 +44,14 @@ CSessionLockSurface::CSessionLockSurface(COutput* output) : output(output) {
|
|||
if (!PVIEWPORTER)
|
||||
Debug::log(LOG, "No viewporter support! Oops, won't be able to scale!");
|
||||
|
||||
lockSurface = ext_session_lock_v1_get_lock_surface(g_pHyprlock->getSessionLock(), surface, output->output);
|
||||
lockSurface = makeShared<CCExtSessionLockSurfaceV1>(g_pHyprlock->getSessionLock()->sendGetLockSurface(surface->resource(), output->output->resource()));
|
||||
|
||||
if (!lockSurface) {
|
||||
Debug::log(CRIT, "Couldn't create ext_session_lock_surface_v1");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ext_session_lock_surface_v1_add_listener(lockSurface, &lockListener, this);
|
||||
lockSurface->setConfigure([this](CCExtSessionLockSurfaceV1* r, uint32_t serial, uint32_t width, uint32_t height) { configure({(double)width, (double)height}, serial); });
|
||||
}
|
||||
|
||||
void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) {
|
||||
|
@ -97,22 +67,22 @@ void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) {
|
|||
|
||||
if (fractional) {
|
||||
size = (size_ * fractionalScale).floor();
|
||||
wp_viewport_set_destination(viewport, logicalSize.x, logicalSize.y);
|
||||
wl_surface_set_buffer_scale(surface, 1);
|
||||
viewport->sendSetDestination(logicalSize.x, logicalSize.y);
|
||||
surface->sendSetBufferScale(1);
|
||||
} else {
|
||||
size = size_ * output->scale;
|
||||
wl_surface_set_buffer_scale(surface, output->scale);
|
||||
surface->sendSetBufferScale(output->scale);
|
||||
}
|
||||
|
||||
if (!SAMESERIAL)
|
||||
ext_session_lock_surface_v1_ack_configure(lockSurface, serial);
|
||||
lockSurface->sendAckConfigure(serial);
|
||||
|
||||
Debug::log(LOG, "Configuring surface for logical {} and pixel {}", logicalSize, size);
|
||||
|
||||
wl_surface_damage_buffer(surface, 0, 0, 0xFFFF, 0xFFFF);
|
||||
surface->sendDamageBuffer(0, 0, 0xFFFF, 0xFFFF);
|
||||
|
||||
if (!eglWindow) {
|
||||
eglWindow = wl_egl_window_create(surface, size.x, size.y);
|
||||
eglWindow = wl_egl_window_create((wl_surface*)surface->resource(), size.x, size.y);
|
||||
if (!eglWindow) {
|
||||
Debug::log(CRIT, "Couldn't create eglWindow");
|
||||
exit(1);
|
||||
|
@ -145,19 +115,6 @@ void CSessionLockSurface::onScaleUpdate() {
|
|||
configure(logicalSize, serial);
|
||||
}
|
||||
|
||||
static void handleDone(void* data, wl_callback* wl_callback, uint32_t callback_data) {
|
||||
const auto PSURF = (CSessionLockSurface*)data;
|
||||
|
||||
if (g_pHyprlock->m_bTerminate)
|
||||
return;
|
||||
|
||||
PSURF->onCallback();
|
||||
}
|
||||
|
||||
static const wl_callback_listener callbackListener = {
|
||||
.done = handleDone,
|
||||
};
|
||||
|
||||
void CSessionLockSurface::render() {
|
||||
Debug::log(TRACE, "render lock");
|
||||
|
||||
|
@ -167,8 +124,13 @@ void CSessionLockSurface::render() {
|
|||
}
|
||||
|
||||
const auto FEEDBACK = g_pRenderer->renderLock(*this);
|
||||
frameCallback = wl_surface_frame(surface);
|
||||
wl_callback_add_listener(frameCallback, &callbackListener, this);
|
||||
frameCallback = makeShared<CCWlCallback>(surface->sendFrame());
|
||||
frameCallback->setDone([this](CCWlCallback* r, uint32_t data) {
|
||||
if (g_pHyprlock->m_bTerminate)
|
||||
return;
|
||||
|
||||
onCallback();
|
||||
});
|
||||
|
||||
eglSwapBuffers(g_pEGL->eglDisplay, eglSurface);
|
||||
|
||||
|
@ -176,8 +138,7 @@ void CSessionLockSurface::render() {
|
|||
}
|
||||
|
||||
void CSessionLockSurface::onCallback() {
|
||||
wl_callback_destroy(frameCallback);
|
||||
frameCallback = nullptr;
|
||||
frameCallback.reset();
|
||||
|
||||
if (needsFrame && !g_pHyprlock->m_bTerminate && g_pEGL) {
|
||||
needsFrame = false;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "ext-session-lock-v1-protocol.h"
|
||||
#include "viewporter-protocol.h"
|
||||
#include "fractional-scale-v1-protocol.h"
|
||||
#include "../defines.hpp"
|
||||
#include "wayland.hpp"
|
||||
#include "ext-session-lock-v1.hpp"
|
||||
#include "viewporter.hpp"
|
||||
#include "fractional-scale-v1.hpp"
|
||||
#include "../helpers/Math.hpp"
|
||||
#include <wayland-egl.h>
|
||||
#include <EGL/egl.h>
|
||||
|
@ -27,22 +28,22 @@ class CSessionLockSurface {
|
|||
void onScaleUpdate();
|
||||
|
||||
private:
|
||||
COutput* output = nullptr;
|
||||
wl_surface* surface = nullptr;
|
||||
ext_session_lock_surface_v1* lockSurface = nullptr;
|
||||
uint32_t serial = 0;
|
||||
wl_egl_window* eglWindow = nullptr;
|
||||
Vector2D size;
|
||||
Vector2D logicalSize;
|
||||
float appliedScale;
|
||||
EGLSurface eglSurface = nullptr;
|
||||
wp_fractional_scale_v1* fractional = nullptr;
|
||||
wp_viewport* viewport = nullptr;
|
||||
COutput* output = nullptr;
|
||||
SP<CCWlSurface> surface = nullptr;
|
||||
SP<CCExtSessionLockSurfaceV1> lockSurface = nullptr;
|
||||
uint32_t serial = 0;
|
||||
wl_egl_window* eglWindow = nullptr;
|
||||
Vector2D size;
|
||||
Vector2D logicalSize;
|
||||
float appliedScale;
|
||||
EGLSurface eglSurface = nullptr;
|
||||
SP<CCWpFractionalScaleV1> fractional = nullptr;
|
||||
SP<CCWpViewport> viewport = nullptr;
|
||||
|
||||
bool needsFrame = false;
|
||||
bool needsFrame = false;
|
||||
|
||||
// wayland callbacks
|
||||
wl_callback* frameCallback = nullptr;
|
||||
SP<CCWlCallback> frameCallback = nullptr;
|
||||
|
||||
friend class CRenderer;
|
||||
};
|
|
@ -3,61 +3,41 @@
|
|||
#include "hyprlock.hpp"
|
||||
#include "../renderer/Renderer.hpp"
|
||||
|
||||
static void handleGeometry(void* data, wl_output* output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make,
|
||||
const char* model, int32_t transform) {
|
||||
const auto POUTPUT = (COutput*)data;
|
||||
POUTPUT->transform = (wl_output_transform)transform;
|
||||
COutput::COutput(SP<CCWlOutput> output_, uint32_t name_) : name(name_), output(output_) {
|
||||
output->setDescription([this](CCWlOutput* r, const char* description) {
|
||||
stringDesc = description ? std::string{description} : "";
|
||||
Debug::log(LOG, "output {} description {}", name, stringDesc);
|
||||
});
|
||||
|
||||
Debug::log(LOG, "output {} make {} model {}", POUTPUT->name, make ? make : "", model ? model : "");
|
||||
}
|
||||
|
||||
static void handleMode(void* data, wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
||||
const auto POUTPUT = (COutput*)data;
|
||||
|
||||
// handle portrait mode and flipped cases
|
||||
if (POUTPUT->transform % 2 == 1)
|
||||
POUTPUT->size = {height, width};
|
||||
else
|
||||
POUTPUT->size = {width, height};
|
||||
}
|
||||
|
||||
static void handleDone(void* data, wl_output* output) {
|
||||
const auto POUTPUT = (COutput*)data;
|
||||
Debug::log(LOG, "output {} done", POUTPUT->name);
|
||||
if (g_pHyprlock->m_bLocked && !POUTPUT->sessionLockSurface) {
|
||||
// if we are already locked, create a surface dynamically
|
||||
Debug::log(LOG, "Creating a surface dynamically for output as we are already locked");
|
||||
POUTPUT->sessionLockSurface = std::make_unique<CSessionLockSurface>(POUTPUT);
|
||||
}
|
||||
}
|
||||
|
||||
static void handleScale(void* data, wl_output* output, int32_t factor) {
|
||||
const auto POUTPUT = (COutput*)data;
|
||||
POUTPUT->scale = factor;
|
||||
}
|
||||
|
||||
static void handleName(void* data, wl_output* output, const char* name) {
|
||||
const auto POUTPUT = (COutput*)data;
|
||||
POUTPUT->stringName = std::string{name} + POUTPUT->stringName;
|
||||
POUTPUT->stringPort = std::string{name};
|
||||
Debug::log(LOG, "output {} name {}", POUTPUT->name, name);
|
||||
}
|
||||
|
||||
static void handleDescription(void* data, wl_output* output, const char* description) {
|
||||
const auto POUTPUT = (COutput*)data;
|
||||
POUTPUT->stringDesc = description ? std::string{description} : "";
|
||||
Debug::log(LOG, "output {} description {}", POUTPUT->name, POUTPUT->stringDesc);
|
||||
}
|
||||
|
||||
static const wl_output_listener outputListener = {
|
||||
.geometry = handleGeometry,
|
||||
.mode = handleMode,
|
||||
.done = handleDone,
|
||||
.scale = handleScale,
|
||||
.name = handleName,
|
||||
.description = handleDescription,
|
||||
};
|
||||
|
||||
COutput::COutput(wl_output* output, uint32_t name) : name(name), output(output) {
|
||||
wl_output_add_listener(output, &outputListener, this);
|
||||
output->setName([this](CCWlOutput* r, const char* name) {
|
||||
stringName = std::string{name} + stringName;
|
||||
stringPort = std::string{name};
|
||||
Debug::log(LOG, "output {} name {}", name, name);
|
||||
});
|
||||
|
||||
output->setScale([this](CCWlOutput* r, int32_t sc) { scale = sc; });
|
||||
|
||||
output->setDone([this](CCWlOutput* r) {
|
||||
Debug::log(LOG, "output {} done", name);
|
||||
if (g_pHyprlock->m_bLocked && !sessionLockSurface) {
|
||||
// if we are already locked, create a surface dynamically
|
||||
Debug::log(LOG, "Creating a surface dynamically for output as we are already locked");
|
||||
sessionLockSurface = std::make_unique<CSessionLockSurface>(this);
|
||||
}
|
||||
});
|
||||
|
||||
output->setMode([this](CCWlOutput* r, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
||||
// handle portrait mode and flipped cases
|
||||
if (transform % 2 == 1)
|
||||
size = {height, width};
|
||||
else
|
||||
size = {width, height};
|
||||
});
|
||||
|
||||
output->setGeometry(
|
||||
[this](CCWlOutput* r, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform) {
|
||||
transform = (wl_output_transform)transform;
|
||||
|
||||
Debug::log(LOG, "output {} make {} model {}", name, make ? make : "", model ? model : "");
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "../defines.hpp"
|
||||
#include "wayland.hpp"
|
||||
#include "../helpers/Math.hpp"
|
||||
#include "LockSurface.hpp"
|
||||
#include <memory>
|
||||
|
||||
class COutput {
|
||||
public:
|
||||
COutput(wl_output* output, uint32_t name);
|
||||
COutput(SP<CCWlOutput> output, uint32_t name);
|
||||
|
||||
uint32_t name = 0;
|
||||
bool focused = false;
|
||||
|
@ -20,7 +21,7 @@ class COutput {
|
|||
|
||||
std::unique_ptr<CSessionLockSurface> sessionLockSurface;
|
||||
|
||||
wl_output* output = nullptr;
|
||||
SP<CCWlOutput> output = nullptr;
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
138
src/core/Seat.cpp
Normal file
138
src/core/Seat.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
#include "Seat.hpp"
|
||||
#include "hyprlock.hpp"
|
||||
#include "../helpers/Log.hpp"
|
||||
#include "../config/ConfigManager.hpp"
|
||||
#include <chrono>
|
||||
#include <sys/mman.h>
|
||||
|
||||
CSeatManager::~CSeatManager() {
|
||||
if (m_pXKBState)
|
||||
xkb_state_unref(m_pXKBState);
|
||||
if (m_pXKBKeymap)
|
||||
xkb_keymap_unref(m_pXKBKeymap);
|
||||
if (m_pXKBContext)
|
||||
xkb_context_unref(m_pXKBContext);
|
||||
}
|
||||
|
||||
void CSeatManager::registerSeat(SP<CCWlSeat> seat) {
|
||||
m_pSeat = seat;
|
||||
|
||||
m_pXKBContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!m_pXKBContext)
|
||||
Debug::log(ERR, "Failed to create xkb context");
|
||||
|
||||
m_pSeat->setCapabilities([this](CCWlSeat* r, wl_seat_capability caps) {
|
||||
if (caps & WL_SEAT_CAPABILITY_POINTER) {
|
||||
m_pPointer = makeShared<CCWlPointer>(r->sendGetPointer());
|
||||
|
||||
m_pPointer->setMotion([](CCWlPointer* r, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||
if (std::chrono::system_clock::now() > g_pHyprlock->m_tGraceEnds)
|
||||
return;
|
||||
|
||||
if (!g_pHyprlock->isUnlocked() && g_pHyprlock->m_vLastEnterCoords.distance({wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)}) > 5) {
|
||||
Debug::log(LOG, "In grace and cursor moved more than 5px, unlocking!");
|
||||
g_pHyprlock->unlock();
|
||||
}
|
||||
});
|
||||
|
||||
m_pPointer->setEnter([this](CCWlPointer* r, uint32_t serial, wl_proxy* surf, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||
if (!m_pCursorShape)
|
||||
return;
|
||||
|
||||
static auto* const PHIDE = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:hide_cursor");
|
||||
|
||||
m_pCursorShape->lastCursorSerial = serial;
|
||||
|
||||
if (**PHIDE)
|
||||
m_pCursorShape->hideCursor();
|
||||
else
|
||||
m_pCursorShape->setShape(wpCursorShapeDeviceV1Shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
|
||||
|
||||
g_pHyprlock->m_vLastEnterCoords = {wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)};
|
||||
});
|
||||
}
|
||||
|
||||
if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||
m_pKeeb = makeShared<CCWlKeyboard>(r->sendGetKeyboard());
|
||||
|
||||
m_pKeeb->setKeymap([this](CCWlKeyboard*, wl_keyboard_keymap_format format, int32_t fd, uint32_t size) {
|
||||
if (!m_pXKBContext)
|
||||
return;
|
||||
|
||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||
Debug::log(ERR, "Could not recognise keymap format");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* buf = (const char*)mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
Debug::log(ERR, "Failed to mmap xkb keymap: {}", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pXKBKeymap = xkb_keymap_new_from_buffer(m_pXKBContext, buf, size - 1, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
munmap((void*)buf, size);
|
||||
close(fd);
|
||||
|
||||
if (!m_pXKBKeymap) {
|
||||
Debug::log(ERR, "Failed to compile xkb keymap");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pXKBState = xkb_state_new(m_pXKBKeymap);
|
||||
if (!m_pXKBState) {
|
||||
Debug::log(ERR, "Failed to create xkb state");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PCOMOPOSETABLE = xkb_compose_table_new_from_locale(m_pXKBContext, setlocale(LC_CTYPE, nullptr), XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!PCOMOPOSETABLE) {
|
||||
Debug::log(ERR, "Failed to create xkb compose table");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pXKBComposeState = xkb_compose_state_new(PCOMOPOSETABLE, XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
});
|
||||
|
||||
m_pKeeb->setKey([](CCWlKeyboard* r, uint32_t serial, uint32_t time, uint32_t key, wl_keyboard_key_state state) {
|
||||
g_pHyprlock->onKey(key, state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
});
|
||||
|
||||
m_pKeeb->setModifiers([this](CCWlKeyboard* r, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
|
||||
if (!m_pXKBState)
|
||||
return;
|
||||
|
||||
if (group != g_pHyprlock->m_uiActiveLayout) {
|
||||
g_pHyprlock->m_uiActiveLayout = group;
|
||||
for (auto& t : g_pHyprlock->getTimers()) {
|
||||
if (t->canForceUpdate()) {
|
||||
t->call(t);
|
||||
t->cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xkb_state_update_mask(m_pXKBState, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
g_pHyprlock->m_bCapsLock = xkb_state_mod_name_is_active(m_pXKBState, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED);
|
||||
g_pHyprlock->m_bNumLock = xkb_state_mod_name_is_active(m_pXKBState, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED);
|
||||
});
|
||||
|
||||
m_pKeeb->setRepeatInfo([](CCWlKeyboard* r, int32_t rate, int32_t delay) {
|
||||
g_pHyprlock->m_iKeebRepeatRate = rate;
|
||||
g_pHyprlock->m_iKeebRepeatDelay = delay;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
m_pSeat->setName([](CCWlSeat* r, const char* name) { Debug::log(LOG, "Exposed seat name: {}", name ? name : "nullptr"); });
|
||||
}
|
||||
|
||||
void CSeatManager::registerCursorShape(SP<CCWpCursorShapeManagerV1> shape) {
|
||||
m_pCursorShape = std::make_unique<CCursorShape>(shape);
|
||||
}
|
||||
|
||||
bool CSeatManager::registered() {
|
||||
return m_pSeat;
|
||||
}
|
33
src/core/Seat.hpp
Normal file
33
src/core/Seat.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "CursorShape.hpp"
|
||||
#include "wayland.hpp"
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbcommon-compose.h>
|
||||
#include <memory>
|
||||
|
||||
class CSeatManager {
|
||||
public:
|
||||
CSeatManager() = default;
|
||||
~CSeatManager();
|
||||
|
||||
void registerSeat(SP<CCWlSeat> seat);
|
||||
void registerCursorShape(SP<CCWpCursorShapeManagerV1> shape);
|
||||
bool registered();
|
||||
|
||||
SP<CCWlKeyboard> m_pKeeb;
|
||||
SP<CCWlPointer> m_pPointer;
|
||||
|
||||
std::unique_ptr<CCursorShape> m_pCursorShape;
|
||||
|
||||
xkb_context* m_pXKBContext = nullptr;
|
||||
xkb_keymap* m_pXKBKeymap = nullptr;
|
||||
xkb_state* m_pXKBState = nullptr;
|
||||
xkb_compose_state* m_pXKBComposeState = nullptr;
|
||||
|
||||
private:
|
||||
SP<CCWlSeat> m_pSeat;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CSeatManager> g_pSeatManager = std::make_unique<CSeatManager>();
|
|
@ -5,7 +5,6 @@
|
|||
#include "../auth/Auth.hpp"
|
||||
#include "../auth/Fingerprint.hpp"
|
||||
#include "Egl.hpp"
|
||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||
#include <sys/wait.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/mman.h>
|
||||
|
@ -32,16 +31,11 @@ CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const b
|
|||
|
||||
g_pEGL = std::make_unique<CEGL>(m_sWaylandState.display);
|
||||
|
||||
m_pXKBContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
if (!m_pXKBContext)
|
||||
Debug::log(ERR, "Failed to create xkb context");
|
||||
|
||||
if (!immediate) {
|
||||
const auto PGRACE = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:grace");
|
||||
m_tGraceEnds = **PGRACE ? std::chrono::system_clock::now() + std::chrono::seconds(**PGRACE) : std::chrono::system_clock::from_time_t(0);
|
||||
} else {
|
||||
} else
|
||||
m_tGraceEnds = std::chrono::system_clock::from_time_t(0);
|
||||
}
|
||||
|
||||
const auto PIMMEDIATERENDER = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:immediate_render");
|
||||
m_bImmediateRender = immediateRender || **PIMMEDIATERENDER;
|
||||
|
@ -57,159 +51,55 @@ CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const b
|
|||
CHyprlock::~CHyprlock() {
|
||||
if (dma.gbmDevice)
|
||||
gbm_device_destroy(dma.gbmDevice);
|
||||
|
||||
if (m_pXKBState)
|
||||
xkb_state_unref(m_pXKBState);
|
||||
|
||||
if (m_pXKBKeymap)
|
||||
xkb_keymap_unref(m_pXKBKeymap);
|
||||
}
|
||||
|
||||
// wl_seat
|
||||
static void registerSignalAction(int sig, void (*handler)(int), int sa_flags = 0) {
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = sa_flags;
|
||||
sigaction(sig, &sa, nullptr);
|
||||
}
|
||||
|
||||
static void handleCapabilities(void* data, wl_seat* wl_seat, uint32_t capabilities);
|
||||
static void handleName(void* data, struct wl_seat* wl_seat, const char* name);
|
||||
static void handleUnlockSignal(int sig) {
|
||||
if (sig == SIGUSR1) {
|
||||
Debug::log(LOG, "Unlocking with a SIGUSR1");
|
||||
g_pHyprlock->releaseSessionLock();
|
||||
}
|
||||
}
|
||||
|
||||
inline const wl_seat_listener seatListener = {
|
||||
.capabilities = handleCapabilities,
|
||||
.name = handleName,
|
||||
};
|
||||
static void handleForceUpdateSignal(int sig) {
|
||||
if (sig == SIGUSR2) {
|
||||
for (auto& t : g_pHyprlock->getTimers()) {
|
||||
if (t->canForceUpdate()) {
|
||||
t->call(t);
|
||||
t->cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end wl_seat
|
||||
|
||||
// dmabuf
|
||||
|
||||
static void handleDMABUFFormat(void* data, struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, uint32_t format) {
|
||||
static void handlePollTerminate(int sig) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleDMABUFModifier(void* data, struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf_v1, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo) {
|
||||
g_pHyprlock->dma.dmabufMods.push_back({format, (((uint64_t)modifier_hi) << 32) | modifier_lo});
|
||||
static void handleCriticalSignal(int sig) {
|
||||
g_pHyprlock->attemptRestoreOnDeath();
|
||||
|
||||
// remove our handlers
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGABRT, &sa, nullptr);
|
||||
sigaction(SIGSEGV, &sa, nullptr);
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
inline const zwp_linux_dmabuf_v1_listener dmabufListener = {
|
||||
.format = handleDMABUFFormat,
|
||||
.modifier = handleDMABUFModifier,
|
||||
};
|
||||
|
||||
static void dmabufFeedbackMainDevice(void* data, zwp_linux_dmabuf_feedback_v1* feedback, wl_array* device_arr) {
|
||||
Debug::log(LOG, "[core] dmabufFeedbackMainDevice");
|
||||
|
||||
RASSERT(!g_pHyprlock->dma.gbm, "double dmabuf feedback");
|
||||
|
||||
dev_t device;
|
||||
assert(device_arr->size == sizeof(device));
|
||||
memcpy(&device, device_arr->data, sizeof(device));
|
||||
|
||||
drmDevice* drmDev;
|
||||
if (drmGetDeviceFromDevId(device, /* flags */ 0, &drmDev) != 0) {
|
||||
Debug::log(WARN, "[dmabuf] unable to open main device?");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g_pHyprlock->dma.gbmDevice = g_pHyprlock->createGBMDevice(drmDev);
|
||||
drmFreeDevice(&drmDev);
|
||||
}
|
||||
|
||||
static void dmabufFeedbackFormatTable(void* data, zwp_linux_dmabuf_feedback_v1* feedback, int fd, uint32_t size) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackFormatTable");
|
||||
|
||||
g_pHyprlock->dma.dmabufMods.clear();
|
||||
|
||||
g_pHyprlock->dma.formatTable = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (g_pHyprlock->dma.formatTable == MAP_FAILED) {
|
||||
Debug::log(ERR, "[core] format table failed to mmap");
|
||||
g_pHyprlock->dma.formatTable = nullptr;
|
||||
g_pHyprlock->dma.formatTableSize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
g_pHyprlock->dma.formatTableSize = size;
|
||||
}
|
||||
|
||||
static void dmabufFeedbackDone(void* data, zwp_linux_dmabuf_feedback_v1* feedback) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackDone");
|
||||
|
||||
if (g_pHyprlock->dma.formatTable)
|
||||
munmap(g_pHyprlock->dma.formatTable, g_pHyprlock->dma.formatTableSize);
|
||||
|
||||
g_pHyprlock->dma.formatTable = nullptr;
|
||||
g_pHyprlock->dma.formatTableSize = 0;
|
||||
}
|
||||
|
||||
static void dmabufFeedbackTrancheTargetDevice(void* data, zwp_linux_dmabuf_feedback_v1* feedback, wl_array* device_arr) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackTrancheTargetDevice");
|
||||
|
||||
dev_t device;
|
||||
assert(device_arr->size == sizeof(device));
|
||||
memcpy(&device, device_arr->data, sizeof(device));
|
||||
|
||||
drmDevice* drmDev;
|
||||
if (drmGetDeviceFromDevId(device, /* flags */ 0, &drmDev) != 0)
|
||||
return;
|
||||
|
||||
if (g_pHyprlock->dma.gbmDevice) {
|
||||
drmDevice* drmDevRenderer = NULL;
|
||||
drmGetDevice2(gbm_device_get_fd(g_pHyprlock->dma.gbmDevice), /* flags */ 0, &drmDevRenderer);
|
||||
g_pHyprlock->dma.deviceUsed = drmDevicesEqual(drmDevRenderer, drmDev);
|
||||
} else {
|
||||
g_pHyprlock->dma.gbmDevice = g_pHyprlock->createGBMDevice(drmDev);
|
||||
g_pHyprlock->dma.deviceUsed = g_pHyprlock->dma.gbm;
|
||||
}
|
||||
}
|
||||
|
||||
static void dmabufFeedbackTrancheFlags(void* data, zwp_linux_dmabuf_feedback_v1* feedback, uint32_t flags) {
|
||||
;
|
||||
}
|
||||
|
||||
static void dmabufFeedbackTrancheFormats(void* data, zwp_linux_dmabuf_feedback_v1* feedback, wl_array* indices) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackTrancheFormats");
|
||||
|
||||
if (!g_pHyprlock->dma.deviceUsed || !g_pHyprlock->dma.formatTable)
|
||||
return;
|
||||
|
||||
struct fm_entry {
|
||||
uint32_t format;
|
||||
uint32_t padding;
|
||||
uint64_t modifier;
|
||||
};
|
||||
// An entry in the table has to be 16 bytes long
|
||||
assert(sizeof(fm_entry) == 16);
|
||||
|
||||
uint32_t n_modifiers = g_pHyprlock->dma.formatTableSize / sizeof(fm_entry);
|
||||
fm_entry* fm_entry = (struct fm_entry*)g_pHyprlock->dma.formatTable;
|
||||
uint16_t* idx;
|
||||
|
||||
for (idx = (uint16_t*)indices->data; (const char*)idx < (const char*)indices->data + indices->size; idx++) {
|
||||
if (*idx >= n_modifiers)
|
||||
continue;
|
||||
|
||||
Debug::log(TRACE, "GPU Reports supported format {:x} with modifier {:x}", (fm_entry + *idx)->format, (fm_entry + *idx)->modifier);
|
||||
|
||||
g_pHyprlock->dma.dmabufMods.push_back({(fm_entry + *idx)->format, (fm_entry + *idx)->modifier});
|
||||
}
|
||||
}
|
||||
|
||||
static void dmabufFeedbackTrancheDone(void* data, struct zwp_linux_dmabuf_feedback_v1* zwp_linux_dmabuf_feedback_v1) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackTrancheDone");
|
||||
|
||||
g_pHyprlock->dma.deviceUsed = false;
|
||||
}
|
||||
|
||||
inline const zwp_linux_dmabuf_feedback_v1_listener dmabufFeedbackListener = {
|
||||
.done = dmabufFeedbackDone,
|
||||
.format_table = dmabufFeedbackFormatTable,
|
||||
.main_device = dmabufFeedbackMainDevice,
|
||||
.tranche_done = dmabufFeedbackTrancheDone,
|
||||
.tranche_target_device = dmabufFeedbackTrancheTargetDevice,
|
||||
.tranche_formats = dmabufFeedbackTrancheFormats,
|
||||
.tranche_flags = dmabufFeedbackTrancheFlags,
|
||||
};
|
||||
|
||||
static char* gbm_find_render_node(drmDevice* device) {
|
||||
drmDevice* devices[64];
|
||||
char* render_node = NULL;
|
||||
char* render_node = nullptr;
|
||||
|
||||
int n = drmGetDevices2(0, devices, sizeof(devices) / sizeof(devices[0]));
|
||||
for (int i = 0; i < n; ++i) {
|
||||
|
@ -242,140 +132,175 @@ gbm_device* CHyprlock::createGBMDevice(drmDevice* dev) {
|
|||
if (fd < 0) {
|
||||
Debug::log(ERR, "[core] couldn't open render node");
|
||||
free(renderNode);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
free(renderNode);
|
||||
return gbm_create_device(fd);
|
||||
}
|
||||
|
||||
// end dmabuf
|
||||
void CHyprlock::addDmabufListener() {
|
||||
dma.linuxDmabufFeedback->setTrancheDone([this](CCZwpLinuxDmabufFeedbackV1* r) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackTrancheDone");
|
||||
|
||||
// wl_registry
|
||||
dma.deviceUsed = false;
|
||||
});
|
||||
|
||||
static void handleGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) {
|
||||
g_pHyprlock->onGlobal(data, registry, name, interface, version);
|
||||
}
|
||||
dma.linuxDmabufFeedback->setTrancheFormats([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* indices) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackTrancheFormats");
|
||||
|
||||
static void handleGlobalRemove(void* data, struct wl_registry* registry, uint32_t name) {
|
||||
g_pHyprlock->onGlobalRemoved(data, registry, name);
|
||||
}
|
||||
if (!dma.deviceUsed || !dma.formatTable)
|
||||
return;
|
||||
|
||||
inline const wl_registry_listener registryListener = {
|
||||
.global = handleGlobal,
|
||||
.global_remove = handleGlobalRemove,
|
||||
};
|
||||
struct fm_entry {
|
||||
uint32_t format;
|
||||
uint32_t padding;
|
||||
uint64_t modifier;
|
||||
};
|
||||
// An entry in the table has to be 16 bytes long
|
||||
assert(sizeof(fm_entry) == 16);
|
||||
|
||||
void CHyprlock::onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) {
|
||||
const std::string IFACE = interface;
|
||||
Debug::log(LOG, " | got iface: {} v{}", IFACE, version);
|
||||
uint32_t n_modifiers = dma.formatTableSize / sizeof(fm_entry);
|
||||
fm_entry* fm_entry = (struct fm_entry*)dma.formatTable;
|
||||
uint16_t* idx;
|
||||
|
||||
if (IFACE == ext_session_lock_manager_v1_interface.name) {
|
||||
m_sWaylandState.sessionLock = (ext_session_lock_manager_v1*)wl_registry_bind(registry, name, &ext_session_lock_manager_v1_interface, version);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == wl_seat_interface.name) {
|
||||
if (m_sWaylandState.seat) {
|
||||
Debug::log(WARN, "Hyprlock does not support multi-seat configurations. Only binding to the first seat.");
|
||||
for (idx = (uint16_t*)indices->data; (const char*)idx < (const char*)indices->data + indices->size; idx++) {
|
||||
if (*idx >= n_modifiers)
|
||||
continue;
|
||||
|
||||
Debug::log(TRACE, "GPU Reports supported format {:x} with modifier {:x}", (fm_entry + *idx)->format, (fm_entry + *idx)->modifier);
|
||||
|
||||
dma.dmabufMods.push_back({(fm_entry + *idx)->format, (fm_entry + *idx)->modifier});
|
||||
}
|
||||
});
|
||||
|
||||
dma.linuxDmabufFeedback->setTrancheTargetDevice([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* device_arr) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackTrancheTargetDevice");
|
||||
|
||||
dev_t device;
|
||||
assert(device_arr->size == sizeof(device));
|
||||
memcpy(&device, device_arr->data, sizeof(device));
|
||||
|
||||
drmDevice* drmDev;
|
||||
if (drmGetDeviceFromDevId(device, /* flags */ 0, &drmDev) != 0)
|
||||
return;
|
||||
|
||||
if (dma.gbmDevice) {
|
||||
drmDevice* drmDevRenderer = nullptr;
|
||||
drmGetDevice2(gbm_device_get_fd(dma.gbmDevice), /* flags */ 0, &drmDevRenderer);
|
||||
dma.deviceUsed = drmDevicesEqual(drmDevRenderer, drmDev);
|
||||
} else {
|
||||
dma.gbmDevice = createGBMDevice(drmDev);
|
||||
dma.deviceUsed = dma.gbm;
|
||||
}
|
||||
});
|
||||
|
||||
dma.linuxDmabufFeedback->setDone([this](CCZwpLinuxDmabufFeedbackV1* r) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackDone");
|
||||
|
||||
if (dma.formatTable)
|
||||
munmap(dma.formatTable, dma.formatTableSize);
|
||||
|
||||
dma.formatTable = nullptr;
|
||||
dma.formatTableSize = 0;
|
||||
});
|
||||
|
||||
dma.linuxDmabufFeedback->setFormatTable([this](CCZwpLinuxDmabufFeedbackV1* r, int fd, uint32_t size) {
|
||||
Debug::log(TRACE, "[core] dmabufFeedbackFormatTable");
|
||||
|
||||
dma.dmabufMods.clear();
|
||||
|
||||
dma.formatTable = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (dma.formatTable == MAP_FAILED) {
|
||||
Debug::log(ERR, "[core] format table failed to mmap");
|
||||
dma.formatTable = nullptr;
|
||||
dma.formatTableSize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
m_sWaylandState.seat = (wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, version);
|
||||
wl_seat_add_listener(m_sWaylandState.seat, &seatListener, nullptr);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == wl_output_interface.name) {
|
||||
m_vOutputs.emplace_back(std::make_unique<COutput>((wl_output*)wl_registry_bind(registry, name, &wl_output_interface, version), name));
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == wp_cursor_shape_manager_v1_interface.name) {
|
||||
m_pCursorShape = std::make_unique<CCursorShape>((wp_cursor_shape_manager_v1*)wl_registry_bind(registry, name, &wp_cursor_shape_manager_v1_interface, version));
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == wl_compositor_interface.name) {
|
||||
m_sWaylandState.compositor = (wl_compositor*)wl_registry_bind(registry, name, &wl_compositor_interface, version);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == wp_fractional_scale_manager_v1_interface.name) {
|
||||
m_sWaylandState.fractional = (wp_fractional_scale_manager_v1*)wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, version);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == wp_viewporter_interface.name) {
|
||||
m_sWaylandState.viewporter = (wp_viewporter*)wl_registry_bind(registry, name, &wp_viewporter_interface, version);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == zwp_linux_dmabuf_v1_interface.name) {
|
||||
if (version < 4) {
|
||||
Debug::log(ERR, "cannot use linux_dmabuf with ver < 4");
|
||||
return;
|
||||
dma.formatTableSize = size;
|
||||
});
|
||||
|
||||
dma.linuxDmabufFeedback->setMainDevice([this](CCZwpLinuxDmabufFeedbackV1* r, wl_array* device_arr) {
|
||||
Debug::log(LOG, "[core] dmabufFeedbackMainDevice");
|
||||
|
||||
RASSERT(!dma.gbm, "double dmabuf feedback");
|
||||
|
||||
dev_t device;
|
||||
assert(device_arr->size == sizeof(device));
|
||||
memcpy(&device, device_arr->data, sizeof(device));
|
||||
|
||||
drmDevice* drmDev;
|
||||
if (drmGetDeviceFromDevId(device, /* flags */ 0, &drmDev) != 0) {
|
||||
Debug::log(WARN, "[dmabuf] unable to open main device?");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dma.linuxDmabuf = wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, version);
|
||||
dma.linuxDmabufFeedback = zwp_linux_dmabuf_v1_get_default_feedback((zwp_linux_dmabuf_v1*)dma.linuxDmabuf);
|
||||
zwp_linux_dmabuf_feedback_v1_add_listener((zwp_linux_dmabuf_feedback_v1*)dma.linuxDmabufFeedback, &dmabufFeedbackListener, nullptr);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
} else if (IFACE == zwlr_screencopy_manager_v1_interface.name) {
|
||||
m_sWaylandState.screencopy = (zwlr_screencopy_manager_v1*)wl_registry_bind(registry, name, &zwlr_screencopy_manager_v1_interface, version);
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
}
|
||||
}
|
||||
dma.gbmDevice = createGBMDevice(drmDev);
|
||||
drmFreeDevice(&drmDev);
|
||||
});
|
||||
|
||||
void CHyprlock::onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name) {
|
||||
Debug::log(LOG, " | removed iface {}", name);
|
||||
auto outputIt = std::find_if(m_vOutputs.begin(), m_vOutputs.end(), [name](const auto& other) { return other->name == name; });
|
||||
if (outputIt != m_vOutputs.end()) {
|
||||
g_pRenderer->removeWidgetsFor(outputIt->get()->sessionLockSurface.get());
|
||||
m_vOutputs.erase(outputIt);
|
||||
}
|
||||
}
|
||||
|
||||
// end wl_registry
|
||||
|
||||
static void registerSignalAction(int sig, void (*handler)(int), int sa_flags = 0) {
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = sa_flags;
|
||||
sigaction(sig, &sa, NULL);
|
||||
}
|
||||
|
||||
static void handleUnlockSignal(int sig) {
|
||||
if (sig == SIGUSR1) {
|
||||
Debug::log(LOG, "Unlocking with a SIGUSR1");
|
||||
g_pHyprlock->releaseSessionLock();
|
||||
}
|
||||
}
|
||||
|
||||
static void forceUpdateTimers() {
|
||||
for (auto& t : g_pHyprlock->getTimers()) {
|
||||
if (t->canForceUpdate()) {
|
||||
t->call(t);
|
||||
t->cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void handleForceUpdateSignal(int sig) {
|
||||
if (sig == SIGUSR2) {
|
||||
forceUpdateTimers();
|
||||
}
|
||||
}
|
||||
|
||||
static void handlePollTerminate(int sig) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleCriticalSignal(int sig) {
|
||||
g_pHyprlock->attemptRestoreOnDeath();
|
||||
|
||||
// remove our handlers
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGABRT, &sa, NULL);
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
|
||||
abort();
|
||||
dma.linuxDmabuf->setModifier([this](CCZwpLinuxDmabufV1* r, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo) {
|
||||
dma.dmabufMods.push_back({format, (((uint64_t)modifier_hi) << 32) | modifier_lo});
|
||||
});
|
||||
}
|
||||
|
||||
void CHyprlock::run() {
|
||||
m_sWaylandState.registry = wl_display_get_registry(m_sWaylandState.display);
|
||||
m_sWaylandState.registry = makeShared<CCWlRegistry>((wl_proxy*)wl_display_get_registry(m_sWaylandState.display));
|
||||
m_sWaylandState.registry->setGlobal([this](CCWlRegistry* r, uint32_t name, const char* interface, uint32_t version) {
|
||||
const std::string IFACE = interface;
|
||||
Debug::log(LOG, " | got iface: {} v{}", IFACE, version);
|
||||
|
||||
wl_registry_add_listener(m_sWaylandState.registry, ®istryListener, nullptr);
|
||||
if (IFACE == zwp_linux_dmabuf_v1_interface.name) {
|
||||
if (version < 4) {
|
||||
Debug::log(ERR, "cannot use linux_dmabuf with ver < 4");
|
||||
return;
|
||||
}
|
||||
|
||||
dma.linuxDmabuf = makeShared<CCZwpLinuxDmabufV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &zwp_linux_dmabuf_v1_interface, 4));
|
||||
dma.linuxDmabufFeedback = makeShared<CCZwpLinuxDmabufFeedbackV1>(dma.linuxDmabuf->sendGetDefaultFeedback());
|
||||
|
||||
addDmabufListener();
|
||||
} else if (IFACE == wl_seat_interface.name) {
|
||||
if (g_pSeatManager->registered()) {
|
||||
Debug::log(WARN, "Hyprlock does not support multi-seat configurations. Only binding to the first seat.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pSeatManager->registerSeat(makeShared<CCWlSeat>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_seat_interface, 9)));
|
||||
} else if (IFACE == ext_session_lock_manager_v1_interface.name)
|
||||
m_sWaylandState.sessionLock =
|
||||
makeShared<CCExtSessionLockManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &ext_session_lock_manager_v1_interface, 1));
|
||||
else if (IFACE == wl_output_interface.name)
|
||||
m_vOutputs.emplace_back(
|
||||
std::make_unique<COutput>(makeShared<CCWlOutput>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_output_interface, 4)), name));
|
||||
else if (IFACE == wp_cursor_shape_manager_v1_interface.name)
|
||||
g_pSeatManager->registerCursorShape(
|
||||
makeShared<CCWpCursorShapeManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wp_cursor_shape_manager_v1_interface, 1)));
|
||||
else if (IFACE == wl_compositor_interface.name)
|
||||
m_sWaylandState.compositor = makeShared<CCWlCompositor>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_compositor_interface, 4));
|
||||
else if (IFACE == wp_fractional_scale_manager_v1_interface.name)
|
||||
m_sWaylandState.fractional =
|
||||
makeShared<CCWpFractionalScaleManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wp_fractional_scale_manager_v1_interface, 1));
|
||||
else if (IFACE == wp_viewporter_interface.name)
|
||||
m_sWaylandState.viewporter = makeShared<CCWpViewporter>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wp_viewporter_interface, 1));
|
||||
else if (IFACE == zwlr_screencopy_manager_v1_interface.name)
|
||||
m_sWaylandState.screencopy =
|
||||
makeShared<CCZwlrScreencopyManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &zwlr_screencopy_manager_v1_interface, 3));
|
||||
else
|
||||
return;
|
||||
|
||||
Debug::log(LOG, " > Bound to {} v{}", IFACE, version);
|
||||
});
|
||||
m_sWaylandState.registry->setGlobalRemove([this](CCWlRegistry* r, uint32_t name) {
|
||||
Debug::log(LOG, " | removed iface {}", name);
|
||||
auto outputIt = std::find_if(m_vOutputs.begin(), m_vOutputs.end(), [name](const auto& other) { return other->name == name; });
|
||||
if (outputIt != m_vOutputs.end()) {
|
||||
g_pRenderer->removeWidgetsFor(outputIt->get()->sessionLockSurface.get());
|
||||
m_vOutputs.erase(outputIt);
|
||||
}
|
||||
});
|
||||
|
||||
wl_display_roundtrip(m_sWaylandState.display);
|
||||
|
||||
|
@ -576,18 +501,21 @@ void CHyprlock::run() {
|
|||
}
|
||||
}
|
||||
|
||||
const auto DPY = m_sWaylandState.display;
|
||||
|
||||
m_sLoopState.timerEvent = true;
|
||||
m_sLoopState.timerCV.notify_all();
|
||||
g_pRenderer->asyncResourceGatherer->notify();
|
||||
g_pRenderer->asyncResourceGatherer->await();
|
||||
m_sWaylandState = {};
|
||||
dma = {};
|
||||
|
||||
m_vOutputs.clear();
|
||||
g_pEGL.reset();
|
||||
g_pRenderer = nullptr;
|
||||
g_pRenderer.reset();
|
||||
g_pSeatManager.reset();
|
||||
|
||||
xkb_context_unref(m_pXKBContext);
|
||||
|
||||
wl_display_disconnect(m_sWaylandState.display);
|
||||
wl_display_disconnect(DPY);
|
||||
|
||||
pthread_kill(pollThr.native_handle(), SIGRTMIN);
|
||||
|
||||
|
@ -618,202 +546,6 @@ bool CHyprlock::isUnlocked() {
|
|||
return m_bFadeStarted || m_bTerminate;
|
||||
}
|
||||
|
||||
// wl_seat
|
||||
|
||||
static void handlePointerEnter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||
if (!g_pHyprlock->m_pCursorShape)
|
||||
return;
|
||||
|
||||
static auto* const PHIDE = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:hide_cursor");
|
||||
|
||||
g_pHyprlock->m_pCursorShape->lastCursorSerial = serial;
|
||||
|
||||
if (**PHIDE)
|
||||
g_pHyprlock->m_pCursorShape->hideCursor();
|
||||
else
|
||||
g_pHyprlock->m_pCursorShape->setShape(wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
|
||||
|
||||
g_pHyprlock->m_vLastEnterCoords = {wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)};
|
||||
}
|
||||
|
||||
static void handlePointerLeave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handlePointerAxis(void* data, wl_pointer* wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
static void handlePointerMotion(void* data, struct wl_pointer* wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||
static auto* const PHIDE = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:hide_cursor");
|
||||
|
||||
if (std::chrono::system_clock::now() > g_pHyprlock->m_tGraceEnds)
|
||||
return;
|
||||
|
||||
if (!g_pHyprlock->isUnlocked() && g_pHyprlock->m_vLastEnterCoords.distance({wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)}) > 5) {
|
||||
Debug::log(LOG, "In grace and cursor moved more than 5px, unlocking!");
|
||||
g_pHyprlock->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
static void handlePointerButton(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t button_state) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleFrame(void* data, struct wl_pointer* wl_pointer) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleAxisSource(void* data, struct wl_pointer* wl_pointer, uint32_t axis_source) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleAxisStop(void* data, struct wl_pointer* wl_pointer, uint32_t time, uint32_t axis) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleAxisDiscrete(void* data, struct wl_pointer* wl_pointer, uint32_t axis, int32_t discrete) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleAxisValue120(void* data, struct wl_pointer* wl_pointer, uint32_t axis, int32_t value120) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleAxisRelativeDirection(void* data, struct wl_pointer* wl_pointer, uint32_t axis, uint32_t direction) {
|
||||
;
|
||||
}
|
||||
|
||||
inline const wl_pointer_listener pointerListener = {
|
||||
.enter = handlePointerEnter,
|
||||
.leave = handlePointerLeave,
|
||||
.motion = handlePointerMotion,
|
||||
.button = handlePointerButton,
|
||||
.axis = handlePointerAxis,
|
||||
.frame = handleFrame,
|
||||
.axis_source = handleAxisSource,
|
||||
.axis_stop = handleAxisStop,
|
||||
.axis_discrete = handleAxisDiscrete,
|
||||
.axis_value120 = handleAxisValue120,
|
||||
.axis_relative_direction = handleAxisRelativeDirection,
|
||||
};
|
||||
|
||||
static void handleKeyboardKeymap(void* data, wl_keyboard* wl_keyboard, uint format, int fd, uint size) {
|
||||
if (!g_pHyprlock->m_pXKBContext)
|
||||
return;
|
||||
|
||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||
Debug::log(ERR, "Could not recognise keymap format");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* buf = (const char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (buf == MAP_FAILED) {
|
||||
Debug::log(ERR, "Failed to mmap xkb keymap: {}", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
g_pHyprlock->m_pXKBKeymap = xkb_keymap_new_from_buffer(g_pHyprlock->m_pXKBContext, buf, size - 1, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
munmap((void*)buf, size);
|
||||
close(fd);
|
||||
|
||||
if (!g_pHyprlock->m_pXKBKeymap) {
|
||||
Debug::log(ERR, "Failed to compile xkb keymap");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pHyprlock->m_pXKBState = xkb_state_new(g_pHyprlock->m_pXKBKeymap);
|
||||
if (!g_pHyprlock->m_pXKBState) {
|
||||
Debug::log(ERR, "Failed to create xkb state");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PCOMOPOSETABLE = xkb_compose_table_new_from_locale(g_pHyprlock->m_pXKBContext, setlocale(LC_CTYPE, nullptr), XKB_COMPOSE_COMPILE_NO_FLAGS);
|
||||
|
||||
if (!PCOMOPOSETABLE) {
|
||||
Debug::log(ERR, "Failed to create xkb compose table");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pHyprlock->m_pXKBComposeState = xkb_compose_state_new(PCOMOPOSETABLE, XKB_COMPOSE_STATE_NO_FLAGS);
|
||||
}
|
||||
|
||||
static void handleKeyboardKey(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
|
||||
g_pHyprlock->onKey(key, state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
}
|
||||
|
||||
static void handleKeyboardEnter(void* data, wl_keyboard* wl_keyboard, uint serial, wl_surface* surface, wl_array* keys) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleKeyboardLeave(void* data, wl_keyboard* wl_keyboard, uint serial, wl_surface* surface) {
|
||||
;
|
||||
}
|
||||
|
||||
static void handleKeyboardModifiers(void* data, wl_keyboard* wl_keyboard, uint serial, uint mods_depressed, uint mods_latched, uint mods_locked, uint group) {
|
||||
if (!g_pHyprlock->m_pXKBState)
|
||||
return;
|
||||
|
||||
if (group != g_pHyprlock->m_uiActiveLayout) {
|
||||
g_pHyprlock->m_uiActiveLayout = group;
|
||||
forceUpdateTimers();
|
||||
}
|
||||
|
||||
xkb_state_update_mask(g_pHyprlock->m_pXKBState, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
g_pHyprlock->m_bCapsLock = xkb_state_mod_name_is_active(g_pHyprlock->m_pXKBState, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED);
|
||||
g_pHyprlock->m_bNumLock = xkb_state_mod_name_is_active(g_pHyprlock->m_pXKBState, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED);
|
||||
}
|
||||
|
||||
static void handleRepeatInfo(void* data, struct wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) {
|
||||
g_pHyprlock->m_iKeebRepeatRate = rate;
|
||||
g_pHyprlock->m_iKeebRepeatDelay = delay;
|
||||
}
|
||||
|
||||
inline const wl_keyboard_listener keyboardListener = {
|
||||
.keymap = handleKeyboardKeymap,
|
||||
.enter = handleKeyboardEnter,
|
||||
.leave = handleKeyboardLeave,
|
||||
.key = handleKeyboardKey,
|
||||
.modifiers = handleKeyboardModifiers,
|
||||
.repeat_info = handleRepeatInfo,
|
||||
};
|
||||
|
||||
static void handleCapabilities(void* data, wl_seat* wl_seat, uint32_t capabilities) {
|
||||
if (capabilities & WL_SEAT_CAPABILITY_POINTER) {
|
||||
g_pHyprlock->m_pPointer = wl_seat_get_pointer(wl_seat);
|
||||
wl_pointer_add_listener(g_pHyprlock->m_pPointer, &pointerListener, wl_seat);
|
||||
}
|
||||
|
||||
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
|
||||
g_pHyprlock->m_pKeeb = wl_seat_get_keyboard(wl_seat);
|
||||
wl_keyboard_add_listener(g_pHyprlock->m_pKeeb, &keyboardListener, wl_seat);
|
||||
}
|
||||
}
|
||||
|
||||
static void handleName(void* data, struct wl_seat* wl_seat, const char* name) {
|
||||
;
|
||||
}
|
||||
|
||||
// end wl_seat
|
||||
|
||||
// session_lock
|
||||
|
||||
static void handleLocked(void* data, ext_session_lock_v1* ext_session_lock_v1) {
|
||||
g_pHyprlock->onLockLocked();
|
||||
}
|
||||
|
||||
static void handleFinished(void* data, ext_session_lock_v1* ext_session_lock_v1) {
|
||||
g_pHyprlock->onLockFinished();
|
||||
}
|
||||
|
||||
static const ext_session_lock_v1_listener sessionLockListener = {
|
||||
.locked = handleLocked,
|
||||
.finished = handleFinished,
|
||||
};
|
||||
|
||||
// end session_lock
|
||||
|
||||
void CHyprlock::clearPasswordBuffer() {
|
||||
if (m_sPasswordState.passBuffer.empty())
|
||||
return;
|
||||
|
@ -852,8 +584,8 @@ void CHyprlock::startKeyRepeat(xkb_keysym_t sym) {
|
|||
m_pKeyRepeatTimer.reset();
|
||||
}
|
||||
|
||||
if (m_pXKBComposeState)
|
||||
xkb_compose_state_reset(m_pXKBComposeState);
|
||||
if (g_pSeatManager->m_pXKBComposeState)
|
||||
xkb_compose_state_reset(g_pSeatManager->m_pXKBComposeState);
|
||||
|
||||
if (m_iKeebRepeatDelay <= 0)
|
||||
return;
|
||||
|
@ -907,16 +639,16 @@ void CHyprlock::onKey(uint32_t key, bool down) {
|
|||
}
|
||||
|
||||
if (down) {
|
||||
m_bCapsLock = xkb_state_mod_name_is_active(g_pHyprlock->m_pXKBState, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED);
|
||||
m_bNumLock = xkb_state_mod_name_is_active(g_pHyprlock->m_pXKBState, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED);
|
||||
m_bCtrl = xkb_state_mod_name_is_active(m_pXKBState, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE);
|
||||
m_bCapsLock = xkb_state_mod_name_is_active(g_pSeatManager->m_pXKBState, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED);
|
||||
m_bNumLock = xkb_state_mod_name_is_active(g_pSeatManager->m_pXKBState, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED);
|
||||
m_bCtrl = xkb_state_mod_name_is_active(g_pSeatManager->m_pXKBState, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE);
|
||||
|
||||
const auto SYM = xkb_state_key_get_one_sym(m_pXKBState, key + 8);
|
||||
const auto SYM = xkb_state_key_get_one_sym(g_pSeatManager->m_pXKBState, key + 8);
|
||||
|
||||
enum xkb_compose_status composeStatus = XKB_COMPOSE_NOTHING;
|
||||
if (m_pXKBComposeState) {
|
||||
xkb_compose_state_feed(m_pXKBComposeState, SYM);
|
||||
composeStatus = xkb_compose_state_get_status(m_pXKBComposeState);
|
||||
if (g_pSeatManager->m_pXKBComposeState) {
|
||||
xkb_compose_state_feed(g_pSeatManager->m_pXKBComposeState, SYM);
|
||||
composeStatus = xkb_compose_state_get_status(g_pSeatManager->m_pXKBComposeState);
|
||||
}
|
||||
|
||||
handleKeySym(SYM, composeStatus == XKB_COMPOSE_COMPOSED);
|
||||
|
@ -924,8 +656,8 @@ void CHyprlock::onKey(uint32_t key, bool down) {
|
|||
if (SYM == XKB_KEY_BackSpace || SYM == XKB_KEY_Delete) // keys allowed to repeat
|
||||
startKeyRepeat(SYM);
|
||||
|
||||
} else if (m_pXKBComposeState && xkb_compose_state_get_status(m_pXKBComposeState) == XKB_COMPOSE_COMPOSED)
|
||||
xkb_compose_state_reset(m_pXKBComposeState);
|
||||
} else if (g_pSeatManager->m_pXKBComposeState && xkb_compose_state_get_status(g_pSeatManager->m_pXKBComposeState) == XKB_COMPOSE_COMPOSED)
|
||||
xkb_compose_state_reset(g_pSeatManager->m_pXKBComposeState);
|
||||
|
||||
renderAllOutputs();
|
||||
}
|
||||
|
@ -961,7 +693,7 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
|
|||
m_bNumLock = !m_bNumLock;
|
||||
} else {
|
||||
char buf[16] = {0};
|
||||
int len = (composed) ? xkb_compose_state_get_utf8(m_pXKBComposeState, buf, sizeof(buf)) /* nullbyte */ + 1 :
|
||||
int len = (composed) ? xkb_compose_state_get_utf8(g_pSeatManager->m_pXKBComposeState, buf, sizeof(buf)) /* nullbyte */ + 1 :
|
||||
xkb_keysym_to_utf8(SYM, buf, sizeof(buf)) /* already includes a nullbyte */;
|
||||
|
||||
if (len > 1)
|
||||
|
@ -971,8 +703,11 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
|
|||
|
||||
void CHyprlock::acquireSessionLock() {
|
||||
Debug::log(LOG, "Locking session");
|
||||
m_sLockState.lock = ext_session_lock_manager_v1_lock(m_sWaylandState.sessionLock);
|
||||
ext_session_lock_v1_add_listener(m_sLockState.lock, &sessionLockListener, nullptr);
|
||||
m_sLockState.lock = makeShared<CCExtSessionLockV1>(m_sWaylandState.sessionLock->sendLock());
|
||||
|
||||
m_sLockState.lock->setLocked([this](CCExtSessionLockV1* r) { onLockLocked(); });
|
||||
|
||||
m_sLockState.lock->setFinished([this](CCExtSessionLockV1* r) { onLockFinished(); });
|
||||
|
||||
// roundtrip in case the compositor sends `finished` right away
|
||||
wl_display_roundtrip(m_sWaylandState.display);
|
||||
|
@ -996,7 +731,7 @@ void CHyprlock::releaseSessionLock() {
|
|||
return;
|
||||
}
|
||||
|
||||
ext_session_lock_v1_unlock_and_destroy(m_sLockState.lock);
|
||||
m_sLockState.lock->sendUnlockAndDestroy();
|
||||
m_sLockState.lock = nullptr;
|
||||
|
||||
Debug::log(LOG, "Unlocked, exiting!");
|
||||
|
@ -1030,24 +765,24 @@ void CHyprlock::onLockFinished() {
|
|||
if (m_bLocked)
|
||||
// The `finished` event specifies that whenever the `locked` event has been recieved and the compositor sends `finished`,
|
||||
// `unlock_and_destroy` should be called by the client.
|
||||
// This does not mean the session gets unlocked! That is ultimatly the responsiblity of the compositor.
|
||||
ext_session_lock_v1_unlock_and_destroy(m_sLockState.lock);
|
||||
// This does not mean the session gets unlocked! That is ultimately the responsiblity of the compositor.
|
||||
m_sLockState.lock->sendUnlockAndDestroy();
|
||||
else
|
||||
ext_session_lock_v1_destroy(m_sLockState.lock);
|
||||
m_sLockState.lock.reset();
|
||||
|
||||
m_sLockState.lock = nullptr;
|
||||
m_bTerminate = true;
|
||||
}
|
||||
|
||||
ext_session_lock_manager_v1* CHyprlock::getSessionLockMgr() {
|
||||
SP<CCExtSessionLockManagerV1> CHyprlock::getSessionLockMgr() {
|
||||
return m_sWaylandState.sessionLock;
|
||||
}
|
||||
|
||||
ext_session_lock_v1* CHyprlock::getSessionLock() {
|
||||
SP<CCExtSessionLockV1> CHyprlock::getSessionLock() {
|
||||
return m_sLockState.lock;
|
||||
}
|
||||
|
||||
wl_compositor* CHyprlock::getCompositor() {
|
||||
SP<CCWlCompositor> CHyprlock::getCompositor() {
|
||||
return m_sWaylandState.compositor;
|
||||
}
|
||||
|
||||
|
@ -1055,11 +790,11 @@ wl_display* CHyprlock::getDisplay() {
|
|||
return m_sWaylandState.display;
|
||||
}
|
||||
|
||||
wp_fractional_scale_manager_v1* CHyprlock::getFractionalMgr() {
|
||||
SP<CCWpFractionalScaleManagerV1> CHyprlock::getFractionalMgr() {
|
||||
return m_sWaylandState.fractional;
|
||||
}
|
||||
|
||||
wp_viewporter* CHyprlock::getViewporter() {
|
||||
SP<CCWpViewporter> CHyprlock::getViewporter() {
|
||||
return m_sWaylandState.viewporter;
|
||||
}
|
||||
|
||||
|
@ -1086,7 +821,17 @@ std::vector<std::shared_ptr<CTimer>> CHyprlock::getTimers() {
|
|||
}
|
||||
|
||||
void CHyprlock::enqueueForceUpdateTimers() {
|
||||
addTimer(std::chrono::milliseconds(1), [](std::shared_ptr<CTimer> self, void* data) { forceUpdateTimers(); }, nullptr, false);
|
||||
addTimer(
|
||||
std::chrono::milliseconds(1),
|
||||
[](std::shared_ptr<CTimer> self, void* data) {
|
||||
for (auto& t : g_pHyprlock->getTimers()) {
|
||||
if (t->canForceUpdate()) {
|
||||
t->call(t);
|
||||
t->cancel();
|
||||
}
|
||||
}
|
||||
},
|
||||
nullptr, false);
|
||||
}
|
||||
|
||||
std::string CHyprlock::spawnSync(const std::string& cmd) {
|
||||
|
@ -1102,7 +847,7 @@ std::string CHyprlock::spawnSync(const std::string& cmd) {
|
|||
return proc.stdOut();
|
||||
}
|
||||
|
||||
zwlr_screencopy_manager_v1* CHyprlock::getScreencopy() {
|
||||
SP<CCZwlrScreencopyManagerV1> CHyprlock::getScreencopy() {
|
||||
return m_sWaylandState.screencopy;
|
||||
}
|
||||
|
||||
|
@ -1146,7 +891,7 @@ void CHyprlock::attemptRestoreOnDeath() {
|
|||
ofs.close();
|
||||
|
||||
if (m_bLocked && m_sLockState.lock) {
|
||||
ext_session_lock_v1_destroy(m_sLockState.lock);
|
||||
m_sLockState.lock.reset();
|
||||
|
||||
// Destroy sessionLockSurfaces
|
||||
m_vOutputs.clear();
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "ext-session-lock-v1-protocol.h"
|
||||
#include "fractional-scale-v1-protocol.h"
|
||||
#include "wlr-screencopy-unstable-v1-protocol.h"
|
||||
#include "viewporter-protocol.h"
|
||||
#include "../defines.hpp"
|
||||
#include "wayland.hpp"
|
||||
#include "ext-session-lock-v1.hpp"
|
||||
#include "fractional-scale-v1.hpp"
|
||||
#include "wlr-screencopy-unstable-v1.hpp"
|
||||
#include "linux-dmabuf-v1.hpp"
|
||||
#include "viewporter.hpp"
|
||||
#include "Output.hpp"
|
||||
#include "Seat.hpp"
|
||||
#include "CursorShape.hpp"
|
||||
#include "Timer.hpp"
|
||||
#include <memory>
|
||||
|
@ -29,82 +32,73 @@ class CHyprlock {
|
|||
CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender, const bool noFadeIn);
|
||||
~CHyprlock();
|
||||
|
||||
void run();
|
||||
void run();
|
||||
|
||||
void unlock();
|
||||
bool isUnlocked();
|
||||
void unlock();
|
||||
bool isUnlocked();
|
||||
|
||||
void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
|
||||
void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);
|
||||
void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
|
||||
void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);
|
||||
|
||||
std::shared_ptr<CTimer> addTimer(const std::chrono::system_clock::duration& timeout, std::function<void(std::shared_ptr<CTimer> self, void* data)> cb_, void* data,
|
||||
bool force = false);
|
||||
std::shared_ptr<CTimer> addTimer(const std::chrono::system_clock::duration& timeout, std::function<void(std::shared_ptr<CTimer> self, void* data)> cb_, void* data,
|
||||
bool force = false);
|
||||
|
||||
void enqueueForceUpdateTimers();
|
||||
void enqueueForceUpdateTimers();
|
||||
|
||||
void onLockLocked();
|
||||
void onLockFinished();
|
||||
void onLockLocked();
|
||||
void onLockFinished();
|
||||
|
||||
void acquireSessionLock();
|
||||
void releaseSessionLock();
|
||||
void acquireSessionLock();
|
||||
void releaseSessionLock();
|
||||
|
||||
void createSessionLockSurfaces();
|
||||
void createSessionLockSurfaces();
|
||||
|
||||
void attemptRestoreOnDeath();
|
||||
void attemptRestoreOnDeath();
|
||||
|
||||
std::string spawnSync(const std::string& cmd);
|
||||
std::string spawnSync(const std::string& cmd);
|
||||
|
||||
void onKey(uint32_t key, bool down);
|
||||
void startKeyRepeat(xkb_keysym_t sym);
|
||||
void repeatKey(xkb_keysym_t sym);
|
||||
void handleKeySym(xkb_keysym_t sym, bool compose);
|
||||
void onPasswordCheckTimer();
|
||||
void clearPasswordBuffer();
|
||||
bool passwordCheckWaiting();
|
||||
std::optional<std::string> passwordLastFailReason();
|
||||
void onKey(uint32_t key, bool down);
|
||||
void startKeyRepeat(xkb_keysym_t sym);
|
||||
void repeatKey(xkb_keysym_t sym);
|
||||
void handleKeySym(xkb_keysym_t sym, bool compose);
|
||||
void onPasswordCheckTimer();
|
||||
void clearPasswordBuffer();
|
||||
bool passwordCheckWaiting();
|
||||
std::optional<std::string> passwordLastFailReason();
|
||||
|
||||
void renderOutput(const std::string& stringPort);
|
||||
void renderAllOutputs();
|
||||
void renderOutput(const std::string& stringPort);
|
||||
void renderAllOutputs();
|
||||
|
||||
size_t getPasswordBufferLen();
|
||||
size_t getPasswordBufferDisplayLen();
|
||||
size_t getPasswordBufferLen();
|
||||
size_t getPasswordBufferDisplayLen();
|
||||
|
||||
ext_session_lock_manager_v1* getSessionLockMgr();
|
||||
ext_session_lock_v1* getSessionLock();
|
||||
wl_compositor* getCompositor();
|
||||
wl_display* getDisplay();
|
||||
wp_fractional_scale_manager_v1* getFractionalMgr();
|
||||
wp_viewporter* getViewporter();
|
||||
zwlr_screencopy_manager_v1* getScreencopy();
|
||||
SP<CCExtSessionLockManagerV1> getSessionLockMgr();
|
||||
SP<CCExtSessionLockV1> getSessionLock();
|
||||
SP<CCWlCompositor> getCompositor();
|
||||
wl_display* getDisplay();
|
||||
SP<CCWpFractionalScaleManagerV1> getFractionalMgr();
|
||||
SP<CCWpViewporter> getViewporter();
|
||||
SP<CCZwlrScreencopyManagerV1> getScreencopy();
|
||||
|
||||
wl_pointer* m_pPointer = nullptr;
|
||||
std::unique_ptr<CCursorShape> m_pCursorShape;
|
||||
int32_t m_iKeebRepeatRate = 25;
|
||||
int32_t m_iKeebRepeatDelay = 600;
|
||||
|
||||
wl_keyboard* m_pKeeb = nullptr;
|
||||
xkb_context* m_pXKBContext = nullptr;
|
||||
xkb_keymap* m_pXKBKeymap = nullptr;
|
||||
xkb_state* m_pXKBState = nullptr;
|
||||
xkb_compose_state* m_pXKBComposeState = nullptr;
|
||||
xkb_layout_index_t m_uiActiveLayout = 0;
|
||||
|
||||
int32_t m_iKeebRepeatRate = 25;
|
||||
int32_t m_iKeebRepeatDelay = 600;
|
||||
bool m_bTerminate = false;
|
||||
|
||||
xkb_layout_index_t m_uiActiveLayout = 0;
|
||||
bool m_bLocked = false;
|
||||
|
||||
bool m_bTerminate = false;
|
||||
bool m_bCapsLock = false;
|
||||
bool m_bNumLock = false;
|
||||
bool m_bCtrl = false;
|
||||
bool m_bFadeStarted = false;
|
||||
|
||||
bool m_bLocked = false;
|
||||
bool m_bImmediateRender = false;
|
||||
|
||||
bool m_bCapsLock = false;
|
||||
bool m_bNumLock = false;
|
||||
bool m_bCtrl = false;
|
||||
bool m_bFadeStarted = false;
|
||||
bool m_bNoFadeIn = false;
|
||||
|
||||
bool m_bImmediateRender = false;
|
||||
|
||||
bool m_bNoFadeIn = false;
|
||||
|
||||
std::string m_sCurrentDesktop = "";
|
||||
std::string m_sCurrentDesktop = "";
|
||||
|
||||
//
|
||||
std::chrono::system_clock::time_point m_tGraceEnds;
|
||||
|
@ -117,34 +111,35 @@ class CHyprlock {
|
|||
std::vector<std::shared_ptr<CTimer>> getTimers();
|
||||
|
||||
struct {
|
||||
void* linuxDmabuf = nullptr;
|
||||
void* linuxDmabufFeedback = nullptr;
|
||||
SP<CCZwpLinuxDmabufV1> linuxDmabuf = nullptr;
|
||||
SP<CCZwpLinuxDmabufFeedbackV1> linuxDmabufFeedback = nullptr;
|
||||
|
||||
gbm_bo* gbm = nullptr;
|
||||
gbm_device* gbmDevice = nullptr;
|
||||
gbm_bo* gbm = nullptr;
|
||||
gbm_device* gbmDevice = nullptr;
|
||||
|
||||
void* formatTable = nullptr;
|
||||
size_t formatTableSize = 0;
|
||||
bool deviceUsed = false;
|
||||
void* formatTable = nullptr;
|
||||
size_t formatTableSize = 0;
|
||||
bool deviceUsed = false;
|
||||
|
||||
std::vector<SDMABUFModifier> dmabufMods;
|
||||
std::vector<SDMABUFModifier> dmabufMods;
|
||||
} dma;
|
||||
gbm_device* createGBMDevice(drmDevice* dev);
|
||||
|
||||
private:
|
||||
struct {
|
||||
wl_display* display = nullptr;
|
||||
wl_registry* registry = nullptr;
|
||||
wl_seat* seat = nullptr;
|
||||
ext_session_lock_manager_v1* sessionLock = nullptr;
|
||||
wl_compositor* compositor = nullptr;
|
||||
wp_fractional_scale_manager_v1* fractional = nullptr;
|
||||
wp_viewporter* viewporter = nullptr;
|
||||
zwlr_screencopy_manager_v1* screencopy = nullptr;
|
||||
wl_display* display = nullptr;
|
||||
SP<CCWlRegistry> registry = nullptr;
|
||||
SP<CCExtSessionLockManagerV1> sessionLock = nullptr;
|
||||
SP<CCWlCompositor> compositor = nullptr;
|
||||
SP<CCWpFractionalScaleManagerV1> fractional = nullptr;
|
||||
SP<CCWpViewporter> viewporter = nullptr;
|
||||
SP<CCZwlrScreencopyManagerV1> screencopy = nullptr;
|
||||
} m_sWaylandState;
|
||||
|
||||
void addDmabufListener();
|
||||
|
||||
struct {
|
||||
ext_session_lock_v1* lock = nullptr;
|
||||
SP<CCExtSessionLockV1> lock = nullptr;
|
||||
} m_sLockState;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
#include "DMAFrame.hpp"
|
||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||
#include "wlr-screencopy-unstable-v1-protocol.h"
|
||||
#include "../helpers/Log.hpp"
|
||||
#include "../core/hyprlock.hpp"
|
||||
#include "../core/Egl.hpp"
|
||||
|
@ -15,77 +13,6 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullpt
|
|||
static PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
||||
|
||||
//
|
||||
static void wlrOnBuffer(void* data, zwlr_screencopy_frame_v1* frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) {
|
||||
const auto PDATA = (SScreencopyData*)data;
|
||||
|
||||
Debug::log(TRACE, "[sc] wlrOnBuffer for {}", (void*)PDATA);
|
||||
|
||||
PDATA->size = stride * height;
|
||||
PDATA->stride = stride;
|
||||
}
|
||||
|
||||
static void wlrOnFlags(void* data, zwlr_screencopy_frame_v1* frame, uint32_t flags) {
|
||||
;
|
||||
}
|
||||
|
||||
static void wlrOnReady(void* data, zwlr_screencopy_frame_v1* frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
|
||||
const auto PDATA = (SScreencopyData*)data;
|
||||
|
||||
Debug::log(TRACE, "[sc] wlrOnReady for {}", (void*)PDATA);
|
||||
|
||||
if (!PDATA->frame->onBufferReady()) {
|
||||
Debug::log(ERR, "onBufferReady failed");
|
||||
return;
|
||||
}
|
||||
|
||||
zwlr_screencopy_frame_v1_destroy(frame);
|
||||
}
|
||||
|
||||
static void wlrOnFailed(void* data, zwlr_screencopy_frame_v1* frame) {
|
||||
;
|
||||
}
|
||||
|
||||
static void wlrOnDamage(void* data, zwlr_screencopy_frame_v1* frame, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
||||
;
|
||||
}
|
||||
|
||||
static void wlrOnDmabuf(void* data, zwlr_screencopy_frame_v1* frame, uint32_t format, uint32_t width, uint32_t height) {
|
||||
const auto PDATA = (SScreencopyData*)data;
|
||||
|
||||
Debug::log(TRACE, "[sc] wlrOnDmabuf for {}", (void*)PDATA);
|
||||
|
||||
PDATA->w = width;
|
||||
PDATA->h = height;
|
||||
PDATA->fmt = format;
|
||||
|
||||
Debug::log(TRACE, "[sc] DMABUF format reported: {:x}", format);
|
||||
}
|
||||
|
||||
static void wlrOnBufferDone(void* data, zwlr_screencopy_frame_v1* frame) {
|
||||
const auto PDATA = (SScreencopyData*)data;
|
||||
|
||||
Debug::log(TRACE, "[sc] wlrOnBufferDone for {}", (void*)PDATA);
|
||||
|
||||
if (!PDATA->frame->onBufferDone()) {
|
||||
Debug::log(ERR, "onBufferDone failed");
|
||||
return;
|
||||
}
|
||||
|
||||
zwlr_screencopy_frame_v1_copy(frame, PDATA->frame->wlBuffer);
|
||||
|
||||
Debug::log(TRACE, "[sc] wlr frame copied");
|
||||
}
|
||||
|
||||
static const zwlr_screencopy_frame_v1_listener wlrFrameListener = {
|
||||
.buffer = wlrOnBuffer,
|
||||
.flags = wlrOnFlags,
|
||||
.ready = wlrOnReady,
|
||||
.failed = wlrOnFailed,
|
||||
.damage = wlrOnDamage,
|
||||
.linux_dmabuf = wlrOnDmabuf,
|
||||
.buffer_done = wlrOnBufferDone,
|
||||
};
|
||||
|
||||
std::string CDMAFrame::getResourceId(COutput* output) {
|
||||
return std::format("dma:{}-{}x{}", output->stringPort, output->size.x, output->size.y);
|
||||
}
|
||||
|
@ -105,11 +32,48 @@ CDMAFrame::CDMAFrame(COutput* output_) {
|
|||
eglQueryDmaBufModifiersEXT = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC)eglGetProcAddress("eglQueryDmaBufModifiersEXT");
|
||||
|
||||
// firstly, plant a listener for the frame
|
||||
frameCb = zwlr_screencopy_manager_v1_capture_output(g_pHyprlock->getScreencopy(), false, output_->output);
|
||||
frameCb = makeShared<CCZwlrScreencopyFrameV1>(g_pHyprlock->getScreencopy()->sendCaptureOutput(false, output_->output->resource()));
|
||||
|
||||
scdata.frame = this;
|
||||
frameCb->setBufferDone([this](CCZwlrScreencopyFrameV1* r) {
|
||||
Debug::log(TRACE, "[sc] wlrOnBufferDone for {}", (void*)this);
|
||||
|
||||
zwlr_screencopy_frame_v1_add_listener(frameCb, &wlrFrameListener, &scdata);
|
||||
if (!onBufferDone()) {
|
||||
Debug::log(ERR, "onBufferDone failed");
|
||||
return;
|
||||
}
|
||||
|
||||
frameCb->sendCopy(wlBuffer->resource());
|
||||
|
||||
Debug::log(TRACE, "[sc] wlr frame copied");
|
||||
});
|
||||
|
||||
frameCb->setLinuxDmabuf([this](CCZwlrScreencopyFrameV1* r, uint32_t format, uint32_t width, uint32_t height) {
|
||||
Debug::log(TRACE, "[sc] wlrOnDmabuf for {}", (void*)this);
|
||||
|
||||
w = width;
|
||||
h = height;
|
||||
fmt = format;
|
||||
|
||||
Debug::log(TRACE, "[sc] DMABUF format reported: {:x}", format);
|
||||
});
|
||||
|
||||
frameCb->setReady([this](CCZwlrScreencopyFrameV1* r, uint32_t, uint32_t, uint32_t) {
|
||||
Debug::log(TRACE, "[sc] wlrOnReady for {}", (void*)this);
|
||||
|
||||
if (!onBufferReady()) {
|
||||
Debug::log(ERR, "onBufferReady failed");
|
||||
return;
|
||||
}
|
||||
|
||||
frameCb.reset();
|
||||
});
|
||||
|
||||
frameCb->setBuffer([this](CCZwlrScreencopyFrameV1* r, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) {
|
||||
Debug::log(TRACE, "[sc] wlrOnBuffer for {}", (void*)this);
|
||||
|
||||
frameSize = stride * height;
|
||||
frameStride = stride;
|
||||
});
|
||||
}
|
||||
|
||||
CDMAFrame::~CDMAFrame() {
|
||||
|
@ -124,16 +88,16 @@ bool CDMAFrame::onBufferDone() {
|
|||
|
||||
if (!eglQueryDmaBufModifiersEXT) {
|
||||
Debug::log(WARN, "Querying modifiers without eglQueryDmaBufModifiersEXT support");
|
||||
bo = gbm_bo_create(g_pHyprlock->dma.gbmDevice, scdata.w, scdata.h, scdata.fmt, flags);
|
||||
bo = gbm_bo_create(g_pHyprlock->dma.gbmDevice, w, h, fmt, flags);
|
||||
} else {
|
||||
std::vector<uint64_t> mods;
|
||||
mods.resize(64);
|
||||
std::vector<EGLBoolean> externalOnly;
|
||||
externalOnly.resize(64);
|
||||
int num = 0;
|
||||
if (!eglQueryDmaBufModifiersEXT(g_pEGL->eglDisplay, scdata.fmt, 64, mods.data(), externalOnly.data(), &num) || num == 0) {
|
||||
if (!eglQueryDmaBufModifiersEXT(g_pEGL->eglDisplay, fmt, 64, mods.data(), externalOnly.data(), &num) || num == 0) {
|
||||
Debug::log(WARN, "eglQueryDmaBufModifiersEXT failed, falling back to regular bo");
|
||||
bo = gbm_bo_create(g_pHyprlock->dma.gbmDevice, scdata.w, scdata.h, scdata.fmt, flags);
|
||||
bo = gbm_bo_create(g_pHyprlock->dma.gbmDevice, w, h, fmt, flags);
|
||||
} else {
|
||||
Debug::log(LOG, "eglQueryDmaBufModifiersEXT found {} mods", num);
|
||||
std::vector<uint64_t> goodMods;
|
||||
|
@ -150,8 +114,7 @@ bool CDMAFrame::onBufferDone() {
|
|||
uint64_t zero = 0;
|
||||
bool hasLinear = std::find(goodMods.begin(), goodMods.end(), 0) != goodMods.end();
|
||||
|
||||
bo = gbm_bo_create_with_modifiers2(g_pHyprlock->dma.gbmDevice, scdata.w, scdata.h, scdata.fmt, hasLinear ? &zero : goodMods.data(), hasLinear ? 1 : goodMods.size(),
|
||||
flags);
|
||||
bo = gbm_bo_create_with_modifiers2(g_pHyprlock->dma.gbmDevice, w, h, fmt, hasLinear ? &zero : goodMods.data(), hasLinear ? 1 : goodMods.size(), flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +128,7 @@ bool CDMAFrame::onBufferDone() {
|
|||
uint64_t mod = gbm_bo_get_modifier(bo);
|
||||
Debug::log(LOG, "bo chose modifier {:x}", mod);
|
||||
|
||||
zwp_linux_buffer_params_v1* params = zwp_linux_dmabuf_v1_create_params((zwp_linux_dmabuf_v1*)g_pHyprlock->dma.linuxDmabuf);
|
||||
auto params = makeShared<CCZwpLinuxBufferParamsV1>(g_pHyprlock->dma.linuxDmabuf->sendCreateParams());
|
||||
if (!params) {
|
||||
Debug::log(ERR, "zwp_linux_dmabuf_v1_create_params failed");
|
||||
gbm_bo_destroy(bo);
|
||||
|
@ -180,7 +143,7 @@ bool CDMAFrame::onBufferDone() {
|
|||
|
||||
if (fd[plane] < 0) {
|
||||
Debug::log(ERR, "gbm_bo_get_fd_for_plane failed");
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
params.reset();
|
||||
gbm_bo_destroy(bo);
|
||||
for (size_t plane_tmp = 0; plane_tmp < plane; plane_tmp++) {
|
||||
close(fd[plane_tmp]);
|
||||
|
@ -188,11 +151,11 @@ bool CDMAFrame::onBufferDone() {
|
|||
return false;
|
||||
}
|
||||
|
||||
zwp_linux_buffer_params_v1_add(params, fd[plane], plane, offset[plane], stride[plane], mod >> 32, mod & 0xffffffff);
|
||||
params->sendAdd(fd[plane], plane, offset[plane], stride[plane], mod >> 32, mod & 0xffffffff);
|
||||
}
|
||||
|
||||
wlBuffer = zwp_linux_buffer_params_v1_create_immed(params, scdata.w, scdata.h, scdata.fmt, 0);
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
wlBuffer = makeShared<CCWlBuffer>(params->sendCreateImmed(w, h, fmt, (zwpLinuxBufferParamsV1Flags)0));
|
||||
params.reset();
|
||||
|
||||
if (!wlBuffer) {
|
||||
Debug::log(ERR, "[pw] zwp_linux_buffer_params_v1_create_immed failed");
|
||||
|
@ -212,14 +175,14 @@ bool CDMAFrame::onBufferReady() {
|
|||
static const int entries_per_attrib = 2;
|
||||
EGLAttrib attribs[(general_attribs + plane_attribs * 4) * entries_per_attrib + 1];
|
||||
int attr = 0;
|
||||
Vector2D size{scdata.w, scdata.h};
|
||||
Vector2D size{w, h};
|
||||
|
||||
attribs[attr++] = EGL_WIDTH;
|
||||
attribs[attr++] = size.x;
|
||||
attribs[attr++] = EGL_HEIGHT;
|
||||
attribs[attr++] = size.y;
|
||||
attribs[attr++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[attr++] = scdata.fmt;
|
||||
attribs[attr++] = fmt;
|
||||
attribs[attr++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
attribs[attr++] = fd[0];
|
||||
attribs[attr++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
#include "../core/Output.hpp"
|
||||
#include <gbm.h>
|
||||
#include "Shared.hpp"
|
||||
|
||||
struct zwlr_screencopy_frame_v1;
|
||||
#include "linux-dmabuf-v1.hpp"
|
||||
#include "wlr-screencopy-unstable-v1.hpp"
|
||||
|
||||
class CDMAFrame;
|
||||
|
||||
struct SScreencopyData {
|
||||
int w = 0, h = 0;
|
||||
uint32_t fmt;
|
||||
size_t size;
|
||||
size_t stride;
|
||||
CDMAFrame* frame = nullptr;
|
||||
};
|
||||
|
||||
class CDMAFrame {
|
||||
public:
|
||||
static std::string getResourceId(COutput* output);
|
||||
|
@ -26,22 +19,25 @@ class CDMAFrame {
|
|||
bool onBufferDone();
|
||||
bool onBufferReady();
|
||||
|
||||
wl_buffer* wlBuffer = nullptr;
|
||||
SP<CCWlBuffer> wlBuffer = nullptr;
|
||||
|
||||
std::string resourceID;
|
||||
|
||||
SPreloadedAsset asset;
|
||||
|
||||
private:
|
||||
gbm_bo* bo = nullptr;
|
||||
gbm_bo* bo = nullptr;
|
||||
|
||||
int planes = 0;
|
||||
int planes = 0;
|
||||
|
||||
int fd[4];
|
||||
uint32_t size[4], stride[4], offset[4];
|
||||
int fd[4];
|
||||
uint32_t size[4], stride[4], offset[4];
|
||||
|
||||
zwlr_screencopy_frame_v1* frameCb = nullptr;
|
||||
SScreencopyData scdata;
|
||||
SP<CCZwlrScreencopyFrameV1> frameCb = nullptr;
|
||||
int w = 0, h = 0;
|
||||
uint32_t fmt = 0;
|
||||
size_t frameSize = 0;
|
||||
size_t frameStride = 0;
|
||||
|
||||
EGLImage image = nullptr;
|
||||
EGLImage image = nullptr;
|
||||
};
|
|
@ -101,7 +101,7 @@ static void replaceAllAttempts(std::string& str) {
|
|||
static void replaceAllLayout(std::string& str) {
|
||||
|
||||
const auto LAYOUTIDX = g_pHyprlock->m_uiActiveLayout;
|
||||
const auto LAYOUTNAME = xkb_keymap_layout_get_name(g_pHyprlock->m_pXKBKeymap, LAYOUTIDX);
|
||||
const auto LAYOUTNAME = xkb_keymap_layout_get_name(g_pSeatManager->m_pXKBKeymap, LAYOUTIDX);
|
||||
const std::string STR = LAYOUTNAME ? LAYOUTNAME : "error";
|
||||
size_t pos = 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue