fractional scaling impl

This commit is contained in:
vaxerski 2023-01-29 14:00:08 +00:00
parent 1a147160cf
commit b8d2b97e13
10 changed files with 100 additions and 18 deletions

View File

@ -67,6 +67,8 @@ target_link_libraries(hyprpaper
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_SOURCE_DIR}/wlr-layer-shell-unstable-v1-protocol.o
${CMAKE_SOURCE_DIR}/xdg-shell-protocol.o
${CMAKE_SOURCE_DIR}/fractional-scale-v1-protocol.o
${CMAKE_SOURCE_DIR}/viewporter-protocol.o
wayland-cursor
)

View File

@ -30,7 +30,27 @@ xdg-shell-protocol.c:
xdg-shell-protocol.o: xdg-shell-protocol.h
protocols: wlr-layer-shell-unstable-v1-protocol.o xdg-shell-protocol.o
fractional-scale-v1-protocol.h:
$(WAYLAND_SCANNER) client-header \
$(WAYLAND_PROTOCOLS)/staging/fractional-scale/fractional-scale-v1.xml $@
fractional-scale-v1-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/staging/fractional-scale/fractional-scale-v1.xml $@
fractional-scale-v1-protocol.o: fractional-scale-v1-protocol.h
viewporter-protocol.h:
$(WAYLAND_SCANNER) client-header \
$(WAYLAND_PROTOCOLS)/stable/viewporter/viewporter.xml $@
viewporter-protocol.c:
$(WAYLAND_SCANNER) private-code \
$(WAYLAND_PROTOCOLS)/stable/viewporter/viewporter.xml $@
viewporter-protocol.o: viewporter-protocol.h
protocols: wlr-layer-shell-unstable-v1-protocol.o xdg-shell-protocol.o fractional-scale-v1-protocol.o viewporter-protocol.o
clear:
rm -rf build

View File

@ -2,6 +2,13 @@
Hyprpaper is a blazing fast wallpaper utility for Hyprland with the ability to dynamically change wallpapers through sockets. It will work on all wlroots-based compositors, though.
# Features
- Per-output wallpapers
- fill or contain modes
- fractional scaling support
- IPC for blazing fast wallpaper switches
- preloading targets into memory
# Installation
[AUR](https://aur.archlinux.org/packages/hyprpaper-git): `yay -S hyprpaper-git`

View File

@ -419,6 +419,9 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
}
}
const Vector2D DIMENSIONS = pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? Vector2D{pMonitor->size.x * pMonitor->pCurrentLayerSurface->fScale, pMonitor->size.y * pMonitor->pCurrentLayerSurface->fScale} : Vector2D{pMonitor->size.x * pMonitor->scale, pMonitor->size.y * pMonitor->scale};
const double SURFACESCALE = pMonitor->pCurrentLayerSurface->pFractionalScaleInfo ? pMonitor->pCurrentLayerSurface->fScale : pMonitor->scale;
const auto PCAIRO = PBUFFER->cairo;
cairo_save(PCAIRO);
cairo_set_operator(PCAIRO, CAIRO_OPERATOR_CLEAR);
@ -427,7 +430,7 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
if (CONTAIN) {
cairo_set_source_rgb(PCAIRO, 0, 0, 0);
cairo_rectangle(PCAIRO, 0, 0, pMonitor->size.x * pMonitor->scale, pMonitor->size.y * pMonitor->scale);
cairo_rectangle(PCAIRO, 0, 0, DIMENSIONS.x, DIMENSIONS.y);
cairo_fill(PCAIRO);
@ -441,38 +444,45 @@ void CHyprpaper::renderWallpaperForMonitor(SMonitor* pMonitor) {
if (!CONTAIN) {
if (pMonitor->size.x / pMonitor->size.y > PWALLPAPERTARGET->m_vSize.x / PWALLPAPERTARGET->m_vSize.y) {
scale = pMonitor->size.x * pMonitor->scale / PWALLPAPERTARGET->m_vSize.x;
scale = DIMENSIONS.x / PWALLPAPERTARGET->m_vSize.x;
origin.y = -(PWALLPAPERTARGET->m_vSize.y * scale - pMonitor->size.y * pMonitor->scale) / 2.f / scale;
origin.y = -(PWALLPAPERTARGET->m_vSize.y * scale - DIMENSIONS.y) / 2.f / scale;
} else {
scale = pMonitor->size.y * pMonitor->scale / PWALLPAPERTARGET->m_vSize.y;
scale = DIMENSIONS.y / PWALLPAPERTARGET->m_vSize.y;
origin.x = -(PWALLPAPERTARGET->m_vSize.x * scale - pMonitor->size.x * pMonitor->scale) / 2.f / scale;
origin.x = -(PWALLPAPERTARGET->m_vSize.x * scale - DIMENSIONS.x) / 2.f / scale;
}
} else {
if (pMonitor->size.x / pMonitor->size.y > PWALLPAPERTARGET->m_vSize.x / PWALLPAPERTARGET->m_vSize.y) {
scale = (pMonitor->size.y * pMonitor->scale) / PWALLPAPERTARGET->m_vSize.y;
scale = (DIMENSIONS.y) / PWALLPAPERTARGET->m_vSize.y;
origin.x = (pMonitor->size.x * pMonitor->scale - PWALLPAPERTARGET->m_vSize.x * scale);
origin.x = (DIMENSIONS.x - PWALLPAPERTARGET->m_vSize.x * scale);
} else {
scale = (pMonitor->size.x * pMonitor->scale) / PWALLPAPERTARGET->m_vSize.x;
scale = (DIMENSIONS.x) / PWALLPAPERTARGET->m_vSize.x;
origin.y = (pMonitor->size.y * pMonitor->scale - PWALLPAPERTARGET->m_vSize.y * scale);
origin.y = (DIMENSIONS.y - PWALLPAPERTARGET->m_vSize.y * scale);
}
}
Debug::log(LOG, "Image data for %s: %s at [%.2f, %.2f], scale: %.2f (original image size: [%i, %i])", pMonitor->name.c_str(), PWALLPAPERTARGET->m_szPath.c_str(), origin.x, origin.y, scale, (int)PWALLPAPERTARGET->m_vSize.x, (int)PWALLPAPERTARGET->m_vSize.y);
cairo_scale(PCAIRO, scale, scale);
cairo_scale(PCAIRO, scale * (DIMENSIONS.x / (pMonitor->size.x * pMonitor->scale)), scale * (DIMENSIONS.x / (pMonitor->size.x * pMonitor->scale)));
cairo_set_source_surface(PCAIRO, PWALLPAPERTARGET->m_pCairoSurface, origin.x, origin.y);
cairo_paint(PCAIRO);
cairo_restore(PCAIRO);
wl_surface_attach(pMonitor->pCurrentLayerSurface->pSurface, PBUFFER->buffer, 0, 0);
wl_surface_set_buffer_scale(pMonitor->pCurrentLayerSurface->pSurface, pMonitor->scale);
wl_surface_damage_buffer(pMonitor->pCurrentLayerSurface->pSurface, 0, 0, pMonitor->size.x, pMonitor->size.y);
wl_surface_set_buffer_scale(pMonitor->pCurrentLayerSurface->pSurface, SURFACESCALE);
wl_surface_damage_buffer(pMonitor->pCurrentLayerSurface->pSurface, 0, 0, 0xFFFF, 0xFFFF);
if (pMonitor->pCurrentLayerSurface->pFractionalScaleInfo) {
wl_fixed_t w, h;
w = wl_fixed_from_int((int)DIMENSIONS.x);
h = wl_fixed_from_int((int)DIMENSIONS.y);
wp_viewport_set_source(pMonitor->pCurrentLayerSurface->pViewport, wl_fixed_from_int(0), wl_fixed_from_int(0), w, h);
}
wl_surface_commit(pMonitor->pCurrentLayerSurface->pSurface);
// check if we dont need to remove a wallpaper

View File

@ -16,10 +16,12 @@ struct SWallpaperRenderData {
class CHyprpaper {
public:
// important
wl_display* m_sDisplay;
wl_compositor* m_sCompositor;
wl_shm* m_sSHM;
zwlr_layer_shell_v1* m_sLayerShell;
wl_display* m_sDisplay; // assured
wl_compositor* m_sCompositor; // assured
wl_shm* m_sSHM; // assured
zwlr_layer_shell_v1* m_sLayerShell = nullptr; // expected
wp_fractional_scale_manager_v1* m_sFractionalScale = nullptr; // will remain null if not bound
wp_viewporter* m_sViewporter = nullptr; // expected
// init the utility
CHyprpaper();

View File

@ -120,7 +120,11 @@ void Events::handleGlobal(void *data, struct wl_registry *registry, uint32_t nam
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
g_pHyprpaper->createSeat((wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, 1));
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
g_pHyprpaper->m_sLayerShell = (zwlr_layer_shell_v1 *)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
g_pHyprpaper->m_sLayerShell = (zwlr_layer_shell_v1*)wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
} else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) {
g_pHyprpaper->m_sFractionalScale = (wp_fractional_scale_manager_v1*)wl_registry_bind(registry, name, &wp_fractional_scale_manager_v1_interface, 1);
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
g_pHyprpaper->m_sViewporter = (wp_viewporter*)wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
}
}
@ -134,3 +138,16 @@ void Events::handleGlobalRemove(void *data, struct wl_registry *registry, uint32
}
}
void Events::handlePreferredScale(void *data, wp_fractional_scale_v1* fractionalScaleInfo, uint32_t scale) {
const double SCALE = scale / 120.0;
CLayerSurface *const pLS = (CLayerSurface*)data;
Debug::log(LOG, "handlePreferredScale: %.2lf for %lx", SCALE, pLS);
if (pLS->fScale != SCALE) {
pLS->fScale = SCALE;
g_pHyprpaper->tick(true);
}
}

View File

@ -35,6 +35,8 @@ namespace Events {
void handlePointerLeave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface);
void handlePreferredScale(void *data, wp_fractional_scale_v1 *wp_fractional_scale_v1, uint32_t scale);
inline const wl_output_listener outputListener = {.geometry = geometry, .mode = mode, .done = done, .scale = scale, .name = name, .description = description};
inline const zwlr_layer_surface_v1_listener layersurfaceListener = { .configure = ls_configure, .closed = handleLSClosed };
@ -44,4 +46,6 @@ namespace Events {
inline const wl_pointer_listener pointerListener = { .enter = handlePointerEnter, .leave = handlePointerLeave, .motion = handlePointerMotion, .button = handlePointerButton, .axis = handlePointerAxis };
inline const wl_seat_listener seatListener = { .capabilities = handleCapabilities };
inline const wp_fractional_scale_v1_listener scaleListener = { .preferred_scale = handlePreferredScale };
}

View File

@ -18,6 +18,8 @@
extern "C" {
#include "wlr-layer-shell-unstable-v1-protocol.h"
#include "xdg-shell-protocol.h"
#include "fractional-scale-v1-protocol.h"
#include "viewporter-protocol.h"
#include <wayland-client.h>
#include <wayland-cursor.h>
}

View File

@ -37,10 +37,24 @@ CLayerSurface::CLayerSurface(SMonitor* pMonitor) {
wl_region_destroy(PINPUTREGION);
// fractional scale, if supported by the compositor
if (g_pHyprpaper->m_sFractionalScale) {
pFractionalScaleInfo = wp_fractional_scale_manager_v1_get_fractional_scale(g_pHyprpaper->m_sFractionalScale, pSurface);
wp_fractional_scale_v1_add_listener(pFractionalScaleInfo, &Events::scaleListener, this);
pViewport = wp_viewporter_get_viewport(g_pHyprpaper->m_sViewporter, pSurface);
wl_surface_commit(pSurface);
}
wl_display_flush(g_pHyprpaper->m_sDisplay);
}
CLayerSurface::~CLayerSurface() {
if (g_pHyprpaper->m_sFractionalScale && pFractionalScaleInfo) {
wp_fractional_scale_v1_destroy(pFractionalScaleInfo);
wp_viewport_destroy(pViewport);
}
zwlr_layer_surface_v1_destroy(pLayerSurface);
wl_surface_destroy(pSurface);

View File

@ -16,4 +16,8 @@ public:
wl_cursor_image* pCursorImg = nullptr;
wl_surface* pCursorSurface = nullptr;
wp_fractional_scale_v1* pFractionalScaleInfo = nullptr;
wp_viewport* pViewport = nullptr;
double fScale = 1.0;
};