mirror of
https://github.com/hyprwm/hyprpaper.git
synced 2024-11-16 22:25:59 +01:00
fractional scaling impl
This commit is contained in:
parent
1a147160cf
commit
b8d2b97e13
10 changed files with 100 additions and 18 deletions
|
@ -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
|
||||
)
|
||||
|
||||
|
|
22
Makefile
22
Makefile
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue