Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package xdg-desktop-portal-hyprland for openSUSE:Factory checked in at 2024-07-10 16:49:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/xdg-desktop-portal-hyprland (Old) and /work/SRC/openSUSE:Factory/.xdg-desktop-portal-hyprland.new.2080 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "xdg-desktop-portal-hyprland" Wed Jul 10 16:49:55 2024 rev:11 rq:1186488 version:1.3.2 Changes: -------- --- /work/SRC/openSUSE:Factory/xdg-desktop-portal-hyprland/xdg-desktop-portal-hyprland.changes 2024-02-26 19:45:30.662169426 +0100 +++ /work/SRC/openSUSE:Factory/.xdg-desktop-portal-hyprland.new.2080/xdg-desktop-portal-hyprland.changes 2024-07-10 16:50:01.368735675 +0200 @@ -1,0 +2,31 @@ +Wed Jul 10 00:53:52 UTC 2024 - Soc Virnyl Estela <obs@uncomfyhalomacro.pl> + +- Add ./fix-compilation-with-pw.patch + +------------------------------------------------------------------- +Wed Jul 10 00:26:41 UTC 2024 - Soc Virnyl Estela <obs@uncomfyhalomacro.pl> + +- Switch from gcc to clang + +------------------------------------------------------------------- +Tue Jul 9 23:42:41 UTC 2024 - Soc Virnyl Estela <obs@uncomfyhalomacro.pl> + +- Cleanup specfile. Remove subprojects + +------------------------------------------------------------------- +Tue Jul 9 23:39:45 UTC 2024 - Soc Virnyl Estela <obs@uncomfyhalomacro.pl> + +- Remove fix-systemd-service-file-install-path.patch +- Add hyprland-protocols as build dependency + +------------------------------------------------------------------- +Tue Jul 9 23:31:42 UTC 2024 - Soc Virnyl Estela <obs@uncomfyhalomacro.pl> + +- Update to version 1.3.2: + * added screencopy:max_fps config option + * core: don't critically exit when no HOME env is set + * core: avoid using uninitialized ptrs + * screencast: remove frame callbacks on stream state change + * screencast: fixup timing issues with frame re-scheduling + +------------------------------------------------------------------- Old: ---- fix-systemd-service-file-install-path.patch xdg-desktop-portal-hyprland-1.3.1.tar.gz New: ---- fix-compilation-with-pw.patch xdg-desktop-portal-hyprland-1.3.2.tar.gz BETA DEBUG BEGIN: Old: - Remove fix-systemd-service-file-install-path.patch - Add hyprland-protocols as build dependency BETA DEBUG END: BETA DEBUG BEGIN: New: - Add ./fix-compilation-with-pw.patch BETA DEBUG END: ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ xdg-desktop-portal-hyprland.spec ++++++ --- /var/tmp/diff_new_pack.JOlmmG/_old 2024-07-10 16:50:02.240767695 +0200 +++ /var/tmp/diff_new_pack.JOlmmG/_new 2024-07-10 16:50:02.244767842 +0200 @@ -16,18 +16,24 @@ # +%global __builder ninja + Name: xdg-desktop-portal-hyprland -Version: 1.3.1 +Version: 1.3.2 Release: 0 Summary: Extended xdg-desktop-portal backend for Hyprland License: MIT Group: System/Libraries URL: https://github.com/hyprwm/xdg-desktop-portal-hyprland Source0: https://github.com/hyprwm/xdg-desktop-portal-hyprland/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz -Patch1: fix-systemd-service-file-install-path.patch +Patch1: https://github.com/hyprwm/xdg-desktop-portal-hyprland/commit/c5b30938710d6c5... BuildRequires: cmake -BuildRequires: gcc-c++ +# Seems some of the C and CXX flags are CLANG specific +BuildRequires: clang +BuildRequires: clang-devel BuildRequires: hyprland-protocols-devel +BuildRequires: ninja +BuildRequires: pipewire-devel BuildRequires: pkgconfig BuildRequires: qt6-base-devel BuildRequires: qt6-wayland @@ -35,12 +41,13 @@ BuildRequires: qt6-waylandclient-devel BuildRequires: qt6-waylandclient-private-devel BuildRequires: scdoc >= 1.9.7 +BuildRequires: util-linux BuildRequires: pkgconfig(gbm) >= 21.3 +BuildRequires: pkgconfig(hyprland-protocols) BuildRequires: pkgconfig(hyprlang) BuildRequires: pkgconfig(inih) BuildRequires: pkgconfig(libdrm) >= 2.4.109 BuildRequires: pkgconfig(libjpeg) -BuildRequires: pkgconfig(libpipewire-0.3) >= 0.3.62 BuildRequires: pkgconfig(libsystemd) BuildRequires: pkgconfig(pango) BuildRequires: pkgconfig(pangocairo) @@ -49,6 +56,7 @@ BuildRequires: pkgconfig(uuid) BuildRequires: pkgconfig(wayland-client) BuildRequires: pkgconfig(wayland-protocols) >= 1.24 +BuildRequires: pkgconfig(wlroots) >= 0.17.0 # Screencasting won't work without pipewire, but it's not a hard dependency. Recommends: pipewire >= 0.3.41 @@ -64,9 +72,14 @@ %prep %autosetup -p1 +pushd subprojects +rm -rfv hyprland-protocols sdbus-cpp +popd %build -%cmake +%cmake \ + -DCMAKE_C_COMPILER="clang" \ + -DCMAKE_CXX_COMPILER="clang++" %cmake_build %install ++++++ fix-compilation-with-pw.patch ++++++ From c5b30938710d6c599f3f5cd99a3ffac35381fb0f Mon Sep 17 00:00:00 2001 From: Vaxry <vaxry@vaxry.net> Date: Tue, 2 Jul 2024 19:45:04 +0200 Subject: [PATCH] core: fix compilation with pw >= 1.1.82 fixes #227 --- src/shared/ScreencopyShared.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/shared/ScreencopyShared.hpp b/src/shared/ScreencopyShared.hpp index d626da6..cc077cf 100644 --- a/src/shared/ScreencopyShared.hpp +++ b/src/shared/ScreencopyShared.hpp @@ -5,16 +5,12 @@ extern "C" { #include <spa/pod/builder.h> -#undef SPA_VERSION_POD_BUILDER_CALLBACKS -#define SPA_VERSION_POD_BUILDER_CALLBACKS .version = 0 #include <spa/buffer/meta.h> #include <spa/utils/result.h> #include <spa/param/props.h> #include <spa/param/format-utils.h> #include <spa/param/video/format-utils.h> #include <spa/pod/dynamic.h> -#undef SPA_VERSION_POD_BUILDER_CALLBACKS -#define SPA_VERSION_POD_BUILDER_CALLBACKS 0 } #include <wayland-client.h> ++++++ xdg-desktop-portal-hyprland-1.3.1.tar.gz -> xdg-desktop-portal-hyprland-1.3.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/CMakeLists.txt new/xdg-desktop-portal-hyprland-1.3.2/CMakeLists.txt --- old/xdg-desktop-portal-hyprland-1.3.1/CMakeLists.txt 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/CMakeLists.txt 2024-06-13 11:48:34.000000000 +0200 @@ -9,6 +9,7 @@ ) set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") +set(SYSTEMD_SERVICES ON CACHE BOOL "Install systemd service file") if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Configuring XDPH in Debug with CMake") @@ -27,12 +28,14 @@ include(GNUInstallDirs) set(LIBEXECDIR ${CMAKE_INSTALL_FULL_LIBEXECDIR}) configure_file(org.freedesktop.impl.portal.desktop.hyprland.service.in org.freedesktop.impl.portal.desktop.hyprland.service @ONLY) -configure_file(contrib/systemd/xdg-desktop-portal-hyprland.service.in contrib/systemd/xdg-desktop-portal-hyprland.service @ONLY) +if(SYSTEMD_SERVICES) + configure_file(contrib/systemd/xdg-desktop-portal-hyprland.service.in contrib/systemd/xdg-desktop-portal-hyprland.service @ONLY) +endif() set(CMAKE_CXX_STANDARD 23) add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing -Wno-pointer-arith - -fpermissive -Wno-address-of-temporary) + $<$<COMPILE_LANG_AND_ID:CXX,GNU>:-fpermissive> -Wno-address-of-temporary) # dependencies message(STATUS "Checking deps...") @@ -40,13 +43,13 @@ find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols libpipewire-0.3 libspa-0.2 libdrm gbm hyprlang>=0.2.0) +pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-client wayland-protocols wayland-scanner libpipewire-0.3 libspa-0.2 libdrm gbm hyprlang>=0.2.0) # check whether we can find sdbus-c++ through pkg-config pkg_check_modules(SDBUS IMPORTED_TARGET sdbus-c++) if(NOT SDBUS_FOUND) include_directories("subprojects/sdbus-cpp/include/") - add_subdirectory(subprojects/sdbus-cpp) + add_subdirectory(subprojects/sdbus-cpp EXCLUDE_FROM_ALL) add_library(PkgConfig::SDBUS ALIAS sdbus-c++) endif() @@ -63,33 +66,27 @@ target_link_libraries(xdg-desktop-portal-hyprland PRIVATE rt PkgConfig::SDBUS Threads::Threads PkgConfig::deps) # protocols -find_program(WaylandScanner NAMES wayland-scanner) +pkg_get_variable(WaylandScanner wayland-scanner 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}") function(protocol 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(xdg-desktop-portal-hyprland PRIVATE protocols/${protoName}-protocol.c) + set(path ${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(xdg-desktop-portal-hyprland PRIVATE protocols/${protoName}-protocol.c) + set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) endif() + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h + COMMAND ${WaylandScanner} client-header ${path} ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.h + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c + COMMAND ${WaylandScanner} private-code ${path} ${CMAKE_SOURCE_DIR}/protocols/${protoName}-protocol.c + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + target_sources(xdg-desktop-portal-hyprland PRIVATE protocols/${protoName}-protocol.h) + target_sources(xdg-desktop-portal-hyprland PRIVATE protocols/${protoName}-protocol.c) endfunction() protocol("protocols/wlr-foreign-toplevel-management-unstable-v1.xml" "wlr-foreign-toplevel-management-unstable-v1" true) @@ -104,4 +101,6 @@ install(FILES hyprland.portal DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/xdg-desktop-portal/portals") install(FILES ${CMAKE_BINARY_DIR}/org.freedesktop.impl.portal.desktop.hyprland.service DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/dbus-1/services") -install(FILES ${CMAKE_BINARY_DIR}/contrib/systemd/xdg-desktop-portal-hyprland.service DESTINATION "${CMAKE_INSTALL_LIBDIR}/systemd/user") +if(SYSTEMD_SERVICES) + install(FILES ${CMAKE_BINARY_DIR}/contrib/systemd/xdg-desktop-portal-hyprland.service DESTINATION "lib/systemd/user") +endif() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/README.md new/xdg-desktop-portal-hyprland-1.3.2/README.md --- old/xdg-desktop-portal-hyprland-1.3.1/README.md 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/README.md 2024-06-13 11:48:34.000000000 +0200 @@ -24,11 +24,12 @@ ```sh git clone --recursive https://github.com/hyprwm/xdg-desktop-portal-hyprland cd xdg-desktop-portal-hyprland/ -cmake -DCMAKE_INSTALL_LIBEXECDIR=/usr/lib -B build -cmake --install /usr +cmake -DCMAKE_INSTALL_LIBEXECDIR=/usr/lib -DCMAKE_INSTALL_PREFIX=/usr -B build +cmake --build build +sudo cmake --install build ``` ## Running, FAQs, etc. See -[the Hyprland wiki](https://wiki.hyprland.org/Useful-Utilities/Hyprland-desktop-portal) +[the Hyprland wiki](https://wiki.hyprland.org/Useful-Utilities/xdg-desktop-portal-hyprland/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/VERSION new/xdg-desktop-portal-hyprland-1.3.2/VERSION --- old/xdg-desktop-portal-hyprland-1.3.1/VERSION 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/VERSION 2024-06-13 11:48:34.000000000 +0200 @@ -1 +1 @@ -1.3.1 +1.3.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/flake.lock new/xdg-desktop-portal-hyprland-1.3.2/flake.lock --- old/xdg-desktop-portal-hyprland-1.3.1/flake.lock 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/flake.lock 2024-06-13 11:48:34.000000000 +0200 @@ -25,14 +25,17 @@ }, "hyprlang": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" }, "locked": { - "lastModified": 1704287638, - "narHash": "sha256-TuRXJGwtK440AXQNl5eiqmQqY4LZ/9+z/R7xC0ie3iA=", + "lastModified": 1713121246, + "narHash": "sha256-502X0Q0fhN6tJK7iEUA8CghONKSatW/Mqj4Wappd++0=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "6624f2bb66d4d27975766e81f77174adbe58ec97", + "rev": "78fcaa27ae9e1d782faa3ff06c8ea55ddce63706", "type": "github" }, "original": { @@ -43,27 +46,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1702645756, - "narHash": "sha256-qKI6OR3TYJYQB3Q8mAZ+DG4o/BR9ptcv9UnRV2hzljc=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "40c3c94c241286dd2243ea34d3aef8a488f9e4d0", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1703961334, - "narHash": "sha256-M1mV/Cq+pgjk0rt6VxoyyD+O8cOUiai8t9Q6Yyq4noY=", + "lastModified": 1712963716, + "narHash": "sha256-WKm9CvgCldeIVvRz87iOMi8CFVB1apJlkUT4GGvA0iM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "b0d36bd0a420ecee3bc916c91886caca87c894e9", + "rev": "cfd6b5fc90b15709b780a5a1619695a88505a176", "type": "github" }, "original": { @@ -77,14 +64,29 @@ "inputs": { "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", - "nixpkgs": "nixpkgs_2", - "systems": "systems" + "nixpkgs": "nixpkgs", + "systems": "systems_2" } }, "systems": { "locked": { "lastModified": 1689347949, "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", "owner": "nix-systems", "repo": "default-linux", "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/flake.nix new/xdg-desktop-portal-hyprland-1.3.2/flake.nix --- old/xdg-desktop-portal-hyprland-1.3.1/flake.nix 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/flake.nix 2024-06-13 11:48:34.000000000 +0200 @@ -13,7 +13,10 @@ inputs.systems.follows = "systems"; }; - hyprlang.url = "github:hyprwm/hyprlang"; + hyprlang = { + url = "github:hyprwm/hyprlang"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/CMakeLists.txt new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/CMakeLists.txt --- old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/CMakeLists.txt 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/CMakeLists.txt 2024-06-13 11:48:34.000000000 +0200 @@ -2,6 +2,8 @@ project(hyprland-share-picker VERSION 0.1 LANGUAGES CXX) +set(QT_VERSION_MAJOR 6) + set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -9,14 +11,16 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) +find_package(QT NAMES Qt6 REQUIRED COMPONENTS Widgets) +find_package(Qt6 REQUIRED COMPONENTS Widgets) set(PROJECT_SOURCES main.cpp mainpicker.cpp mainpicker.h mainpicker.ui + elidedbutton.h + elidedbutton.cpp ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/elidedbutton.cpp new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/elidedbutton.cpp --- old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/elidedbutton.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/elidedbutton.cpp 2024-06-13 11:48:34.000000000 +0200 @@ -0,0 +1,31 @@ +#include "elidedbutton.h" + +ElidedButton::ElidedButton(QWidget *parent) + : QPushButton(parent) +{ +} + +ElidedButton::ElidedButton( const QString& text, QWidget* parent ) + : ElidedButton( parent ) +{ + setText(text); +} + +void ElidedButton::setText(QString text) +{ + og_text = text; + updateText(); +} + +void ElidedButton::resizeEvent(QResizeEvent *event) +{ + QPushButton::resizeEvent(event); + updateText(); +} + +void ElidedButton::updateText() +{ + QFontMetrics metrics(font()); + QString elided = metrics.elidedText(og_text, Qt::ElideRight, width() - 15); + QPushButton::setText(elided); +} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/elidedbutton.h new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/elidedbutton.h --- old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/elidedbutton.h 1970-01-01 01:00:00.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/elidedbutton.h 2024-06-13 11:48:34.000000000 +0200 @@ -0,0 +1,21 @@ +#ifndef ELIDEDBUTTON_H +#define ELIDEDBUTTON_H + +#include <QPushButton> + +class ElidedButton : public QPushButton +{ +public: + explicit ElidedButton(QWidget *parent = nullptr); + explicit ElidedButton(const QString &text, QWidget *parent = nullptr); + void setText(QString); + +protected: + void resizeEvent(QResizeEvent *); + +private: + void updateText(); + QString og_text; +}; + +#endif // ELIDEDBUTTON_H diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/main.cpp new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/main.cpp --- old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/main.cpp 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/main.cpp 2024-06-13 11:48:34.000000000 +0200 @@ -7,6 +7,7 @@ #include <QWidget> #include <QtDebug> #include <QtWidgets> +#include <QSettings> #include <array> #include <cstdio> #include <iostream> @@ -16,6 +17,7 @@ #include <vector> #include "mainpicker.h" +#include "elidedbutton.h" std::string execAndGet(const char* cmd) { std::array<char, 128> buffer; @@ -84,21 +86,24 @@ MainPicker w; mainPickerPtr = &w; + QSettings* settings = new QSettings("/tmp/hypr/hyprland-share-picker.conf", QSettings::IniFormat); + w.setGeometry(0, 0, settings->value("width").toInt(), settings->value("height").toInt()); + // get the tabwidget - const auto TABWIDGET = (QTabWidget*)w.children()[1]->children()[0]; - const auto ALLOWTOKENBUTTON = (QCheckBox*)w.children()[1]->children()[1]; + const auto TABWIDGET = w.findChild<QTabWidget *>("tabWidget"); + const auto ALLOWTOKENBUTTON = w.findChild<QCheckBox *>("checkBox"); const auto TAB1 = (QWidget*)TABWIDGET->children()[0]; const auto SCREENS_SCROLL_AREA_CONTENTS = (QWidget*)TAB1->findChild<QWidget*>("screens")->findChild<QScrollArea*>("scrollArea")->findChild<QWidget*>("scrollAreaWidgetContents"); + const auto SCREENS_SCROLL_AREA_CONTENTS_LAYOUT = SCREENS_SCROLL_AREA_CONTENTS->layout(); + // add all screens const auto SCREENS = picker.screens(); - constexpr int BUTTON_WIDTH = 441; constexpr int BUTTON_HEIGHT = 41; - constexpr int BUTTON_PAD = 4; for (int i = 0; i < SCREENS.size(); ++i) { const auto GEOMETRY = SCREENS[i]->geometry(); @@ -106,38 +111,44 @@ QString text = QString::fromStdString(std::string("Screen " + std::to_string(i) + " at " + std::to_string(GEOMETRY.x()) + ", " + std::to_string(GEOMETRY.y()) + " (" + std::to_string(GEOMETRY.width()) + "x" + std::to_string(GEOMETRY.height()) + ") (") + SCREENS[i]->name().toStdString() + ")"); - QPushButton* button = new QPushButton(text, (QWidget*)SCREENS_SCROLL_AREA_CONTENTS); - button->move(9, 5 + (BUTTON_HEIGHT + BUTTON_PAD) * i); - button->resize(BUTTON_WIDTH, BUTTON_HEIGHT); - QObject::connect(button, &QPushButton::clicked, [=]() { - std::string ID = button->text().toStdString(); - ID = ID.substr(ID.find_last_of('(') + 1); - ID = ID.substr(0, ID.find_last_of(')')); + QString outputName = SCREENS[i]->name(); + ElidedButton* button = new ElidedButton(text); + button->setMinimumSize(0, BUTTON_HEIGHT); + SCREENS_SCROLL_AREA_CONTENTS_LAYOUT->addWidget(button); + QObject::connect(button, &QPushButton::clicked, [=]() { std::cout << "[SELECTION]"; std::cout << (ALLOWTOKENBUTTON->isChecked() ? "r" : ""); std::cout << "/"; - std::cout << "screen:" << ID << "\n"; + std::cout << "screen:" << outputName.toStdString() << "\n"; + + settings->setValue("width", mainPickerPtr->width()); + settings->setValue("height", mainPickerPtr->height()); + settings->sync(); + pickerPtr->quit(); return 0; }); } - SCREENS_SCROLL_AREA_CONTENTS->resize(SCREENS_SCROLL_AREA_CONTENTS->size().width(), 5 + (BUTTON_HEIGHT + BUTTON_PAD) * SCREENS.size()); + QSpacerItem * SCREENS_SPACER = new QSpacerItem(0,10000, QSizePolicy::Expanding, QSizePolicy::Expanding); + SCREENS_SCROLL_AREA_CONTENTS_LAYOUT->addItem(SCREENS_SPACER); // windows const auto WINDOWS_SCROLL_AREA_CONTENTS = (QWidget*)TAB1->findChild<QWidget*>("windows")->findChild<QScrollArea*>("scrollArea_2")->findChild<QWidget*>("scrollAreaWidgetContents_2"); + const auto WINDOWS_SCROLL_AREA_CONTENTS_LAYOUT = WINDOWS_SCROLL_AREA_CONTENTS->layout(); + // loop over them int windowIterator = 0; for (auto& window : WINDOWLIST) { QString text = QString::fromStdString(window.clazz + ": " + window.name); - QPushButton* button = new QPushButton(text, (QWidget*)WINDOWS_SCROLL_AREA_CONTENTS); - button->move(9, 5 + (BUTTON_HEIGHT + BUTTON_PAD) * windowIterator); - button->resize(BUTTON_WIDTH, BUTTON_HEIGHT); + ElidedButton* button = new ElidedButton(text); + button->setMinimumSize(0, BUTTON_HEIGHT); + WINDOWS_SCROLL_AREA_CONTENTS_LAYOUT->addWidget(button); mainPickerPtr->windowIDs[button] = window.id; @@ -147,6 +158,11 @@ std::cout << "/"; std::cout << "window:" << mainPickerPtr->windowIDs[button] << "\n"; + + settings->setValue("width", mainPickerPtr->width()); + settings->setValue("height", mainPickerPtr->height()); + settings->sync(); + pickerPtr->quit(); return 0; }); @@ -154,16 +170,20 @@ windowIterator++; } - WINDOWS_SCROLL_AREA_CONTENTS->resize(WINDOWS_SCROLL_AREA_CONTENTS->size().width(), 5 + (BUTTON_HEIGHT + BUTTON_PAD) * windowIterator); + QSpacerItem * WINDOWS_SPACER = new QSpacerItem(0,10000, QSizePolicy::Expanding, QSizePolicy::Expanding); + WINDOWS_SCROLL_AREA_CONTENTS_LAYOUT->addItem(WINDOWS_SPACER); // lastly, region const auto REGION_OBJECT = (QWidget*)TAB1->findChild<QWidget*>("region"); + const auto REGION_LAYOUT = REGION_OBJECT->layout(); QString text = "Select region..."; + + ElidedButton* button = new ElidedButton(text); + button->setMaximumSize(400, BUTTON_HEIGHT); + REGION_LAYOUT->addWidget(button); + - QPushButton* button = new QPushButton(text, (QWidget*)REGION_OBJECT); - button->move(79, 80); - button->resize(321, 41); QObject::connect(button, &QPushButton::clicked, [=]() { auto REGION = execAndGet("slurp -f \"%o %x %y %w %h\""); REGION = REGION.substr(0, REGION.length()); @@ -206,6 +226,11 @@ std::cout << "/"; std::cout << "region:" << SCREEN_NAME << "@" << X - pScreen->geometry().x() << "," << Y - pScreen->geometry().y() << "," << W << "," << H << "\n"; + + settings->setValue("width", mainPickerPtr->width()); + settings->setValue("height", mainPickerPtr->height()); + settings->sync(); + pickerPtr->quit(); return 0; } catch (...) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/mainpicker.ui new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/mainpicker.ui --- old/xdg-desktop-portal-hyprland-1.3.1/hyprland-share-picker/mainpicker.ui 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/hyprland-share-picker/mainpicker.ui 2024-06-13 11:48:34.000000000 +0200 @@ -7,9 +7,15 @@ <x>0</x> <y>0</y> <width>500</width> - <height>290</height> + <height>300</height> </rect> </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> <width>500</width> @@ -18,163 +24,258 @@ </property> <property name="maximumSize"> <size> - <width>500</width> - <height>290</height> + <width>1280</width> + <height>800</height> </size> </property> <property name="windowTitle"> <string>MainPicker</string> </property> <widget class="QWidget" name="centralwidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="minimumSize"> <size> - <width>500</width> - <height>290</height> + <width>0</width> + <height>0</height> </size> </property> <property name="maximumSize"> <size> - <width>500</width> - <height>290</height> + <width>1280</width> + <height>800</height> </size> </property> - <widget class="QTabWidget" name="tabWidget"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>500</width> - <height>290</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>500</width> - <height>290</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>500</width> - <height>290</height> - </size> - </property> - <property name="toolTip"> - <string/> - </property> - <property name="tabPosition"> - <enum>QTabWidget::North</enum> - </property> - <property name="currentIndex"> - <number>0</number> - </property> - <widget class="QWidget" name="screens"> - <attribute name="title"> - <string>Screen</string> - </attribute> - <widget class="QScrollArea" name="scrollArea"> - <property name="geometry"> - <rect> - <x>9</x> - <y>9</y> - <width>461</width> - <height>201</height> - </rect> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - <property name="widgetResizable"> - <bool>false</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>459</width> - <height>239</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>459</width> - <height>239</height> - </size> - </property> - <property name="focusPolicy"> - <enum>Qt::WheelFocus</enum> - </property> - </widget> - </widget> - </widget> - <widget class="QWidget" name="windows"> - <attribute name="title"> - <string>Window</string> - </attribute> - <widget class="QScrollArea" name="scrollArea_2"> - <property name="geometry"> - <rect> - <x>9</x> - <y>9</y> - <width>461</width> - <height>201</height> - </rect> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - <property name="widgetResizable"> - <bool>false</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents_2"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>459</width> - <height>239</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>459</width> - <height>239</height> - </size> - </property> - <property name="focusPolicy"> - <enum>Qt::WheelFocus</enum> - </property> - </widget> - </widget> - </widget> - <widget class="QWidget" name="region"> - <attribute name="title"> - <string>Region</string> - </attribute> - </widget> - </widget> - <widget class="QCheckBox" name="checkBox"> - <property name="geometry"> - <rect> - <x>340</x> - <y>256</y> - <width>140</width> - <height>21</height> - </rect> - </property> - <property name="toolTip"> - <string>By selecting this, the application will be given a restore token that it can use to skip prompting you next time. Only select if you trust the application.</string> - </property> - <property name="text"> - <string>Allow a restore token</string> - </property> - </widget> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="tabWidget"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::StrongFocus</enum> + </property> + <property name="toolTip"> + <string/> + </property> + <property name="tabPosition"> + <enum>QTabWidget::North</enum> + </property> + <property name="currentIndex"> + <number>0</number> + </property> + <widget class="QWidget" name="screens"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <attribute name="title"> + <string>Screen</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QScrollArea" name="scrollArea"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustIgnored</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>410</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Ignored" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <layout class="QVBoxLayout" name="screensScrollAreaLayout"> + <property name="spacing"> + <number>6</number> + </property> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + </layout> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="windows"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <attribute name="title"> + <string>Window</string> + </attribute> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QScrollArea" name="scrollArea_2"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>410</width> + <height>18</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Ignored" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <layout class="QVBoxLayout" name="windowsScrollAreaLayout"/> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="region"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>16777215</height> + </size> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <attribute name="title"> + <string>Region</string> + </attribute> + <layout class="QGridLayout" name="gridLayout"> + <property name="sizeConstraint"> + <enum>QLayout::SetDefaultConstraint</enum> + </property> + </layout> + </widget> + </widget> + </item> + <item> + <widget class="QCheckBox" name="checkBox"> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> + </property> + <property name="toolTip"> + <string>By selecting this, the application will be given a restore token that it can use to skip prompting you next time. +Only select if you trust the application.</string> + </property> + <property name="layoutDirection"> + <enum>Qt::LeftToRight</enum> + </property> + <property name="text"> + <string>Allow a restore token</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> </widget> </widget> <tabstops> - <tabstop>scrollArea</tabstop> - <tabstop>scrollArea_2</tabstop> <tabstop>tabWidget</tabstop> </tabstops> <resources/> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/src/core/PortalManager.cpp new/xdg-desktop-portal-hyprland-1.3.2/src/core/PortalManager.cpp --- old/xdg-desktop-portal-hyprland-1.3.1/src/core/PortalManager.cpp 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/src/core/PortalManager.cpp 2024-06-13 11:48:34.000000000 +0200 @@ -9,7 +9,7 @@ #include <protocols/linux-dmabuf-unstable-v1-protocol.h> #include <pipewire/pipewire.h> -#include <sys/poll.h> +#include <poll.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> @@ -41,7 +41,8 @@ } static void handleOutputMode(void* data, struct wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { - ; + const auto POUTPUT = (SOutput*)data; + POUTPUT->refreshRate = std::round(refresh / 1000.0); } static void handleOutputScale(void* data, struct wl_output* wl_output, int32_t factor) { @@ -202,16 +203,16 @@ const auto XDG_CONFIG_HOME = getenv("XDG_CONFIG_HOME"); const auto HOME = getenv("HOME"); - if (!HOME && !XDG_CONFIG_HOME) { - Debug::log(CRIT, "Cannot proceed: neither $HOME nor $XDG_CONFIG_HOME is present in env"); - throw "$HOME and $XDG_CONFIG_HOME both missing from env"; - } + if (!HOME && !XDG_CONFIG_HOME) + Debug::log(WARN, "neither $HOME nor $XDG_CONFIG_HOME is present in env"); - std::string path = XDG_CONFIG_HOME ? std::string{XDG_CONFIG_HOME} + "/hypr/xdph.conf" : std::string{HOME} + "/.config/hypr/xdph.conf"; + std::string path = + (!XDG_CONFIG_HOME && !HOME) ? "/tmp/xdph.conf" : (XDG_CONFIG_HOME ? std::string{XDG_CONFIG_HOME} + "/hypr/xdph.conf" : std::string{HOME} + "/.config/hypr/xdph.conf"); m_sConfig.config = std::make_unique<Hyprlang::CConfig>(path.c_str(), Hyprlang::SConfigOptions{.allowMissingConfig = true}); - m_sConfig.config->addConfigValue("general:toplevel_dynamic_bind", {0L}); + m_sConfig.config->addConfigValue("general:toplevel_dynamic_bind", Hyprlang::INT{0L}); + m_sConfig.config->addConfigValue("screencopy:max_fps", Hyprlang::INT{120L}); m_sConfig.config->commence(); m_sConfig.config->parse(); @@ -421,13 +422,11 @@ while (1) { // dbus events // wait for being awakened - m_sEventLoopInternals.loopRequestMutex.unlock(); // unlock, we are ready to take events - std::unique_lock lk(m_sEventLoopInternals.loopMutex); if (m_sEventLoopInternals.shouldProcess == false) // avoid a lock if a thread managed to request something already since we .unlock()ed - m_sEventLoopInternals.loopSignal.wait(lk, [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events + m_sEventLoopInternals.loopSignal.wait_for(lk, std::chrono::seconds(5), [this] { return m_sEventLoopInternals.shouldProcess == true; }); // wait for events - m_sEventLoopInternals.loopRequestMutex.lock(); // lock incoming events + std::lock_guard<std::mutex> lg(m_sEventLoopInternals.loopRequestMutex); if (m_bTerminate) break; @@ -467,7 +466,6 @@ } } - // finalize wayland dispatching. Dispatch pending on the queue int ret = 0; do { ret = wl_display_dispatch_pending(m_sWaylandConnection.display); @@ -485,6 +483,7 @@ m_sPortals.globalShortcuts.reset(); m_sPortals.screencopy.reset(); + m_sPortals.screenshot.reset(); m_pConnection.reset(); pw_loop_destroy(m_sPipewire.loop); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/src/core/PortalManager.hpp new/xdg-desktop-portal-hyprland-1.3.2/src/core/PortalManager.hpp --- old/xdg-desktop-portal-hyprland-1.3.1/src/core/PortalManager.hpp 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/src/core/PortalManager.hpp 2024-06-13 11:48:34.000000000 +0200 @@ -19,9 +19,10 @@ struct SOutput { std::string name; - wl_output* output = nullptr; - uint32_t id = 0; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + wl_output* output = nullptr; + uint32_t id = 0; + float refreshRate = 60.0; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; }; struct SDMABUFModifier { @@ -61,8 +62,8 @@ void* linuxDmabuf = nullptr; void* linuxDmabufFeedback = nullptr; wl_shm* shm = nullptr; - gbm_bo* gbm; - gbm_device* gbmDevice; + gbm_bo* gbm = nullptr; + gbm_device* gbmDevice = nullptr; struct { void* formatTable = nullptr; size_t formatTableSize = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/src/helpers/MiscFunctions.cpp new/xdg-desktop-portal-hyprland-1.3.2/src/helpers/MiscFunctions.cpp --- old/xdg-desktop-portal-hyprland-1.3.1/src/helpers/MiscFunctions.cpp 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/src/helpers/MiscFunctions.cpp 2024-06-13 11:48:34.000000000 +0200 @@ -56,7 +56,7 @@ if (nextBegin < pathString.size()) paths.push_back(pathString.substr(nextBegin, pathString.size() - nextBegin)); - return std::ranges::any_of(paths, [&exec](std::string& path) { return std::filesystem::exists(path + "/" + exec); }); + return std::ranges::any_of(paths, [&exec](std::string& path) { return access((path + "/" + exec).c_str(), X_OK) == 0; }); } void sendEmptyDbusMethodReply(sdbus::MethodCall& call, u_int32_t responseCode) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/src/portals/Screencopy.cpp new/xdg-desktop-portal-hyprland-1.3.2/src/portals/Screencopy.cpp --- old/xdg-desktop-portal-hyprland-1.3.1/src/portals/Screencopy.cpp 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/src/portals/Screencopy.cpp 2024-06-13 11:48:34.000000000 +0200 @@ -6,6 +6,7 @@ #include <libdrm/drm_fourcc.h> #include <pipewire/pipewire.h> #include <protocols/linux-dmabuf-unstable-v1-protocol.h> +#include <unistd.h> // --------------- Wayland Protocol Handlers --------------- // @@ -487,6 +488,17 @@ if (SHAREDATA.type == TYPE_WINDOW && !m_sState.toplevel) { Debug::log(ERR, "[screencopy] Requested type window for no toplevel export protocol!"); SHAREDATA.type = TYPE_INVALID; + } else if (SHAREDATA.type == TYPE_OUTPUT || SHAREDATA.type == TYPE_GEOMETRY) { + const auto POUTPUT = g_pPortalManager->getOutputFromName(SHAREDATA.output); + + if (POUTPUT) { + static auto* const* PFPS = (Hyprlang::INT* const*)g_pPortalManager->m_sConfig.config->getConfigValuePtr("screencopy:max_fps")->getDataStaticPtr(); + + if (**PFPS <= 0) + PSESSION->sharingData.framerate = POUTPUT->refreshRate; + else + PSESSION->sharingData.framerate = std::clamp(POUTPUT->refreshRate, 1.F, (float)**PFPS); + } } PSESSION->selection = SHAREDATA; @@ -669,7 +681,15 @@ if (PSTREAM && !PSTREAM->streamState) return; - g_pPortalManager->addTimer({1000.0 / pSession->sharingData.framerate, [pSession]() { g_pPortalManager->m_sPortals.screencopy->startFrameCopy(pSession); }}); + // calculate frame delta and queue next frame + const auto FRAMETOOKMS = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - pSession->sharingData.begunFrame).count() / 1000.0; + const auto MSTILNEXTREFRESH = 1000.0 / (pSession->sharingData.framerate) - FRAMETOOKMS; + pSession->sharingData.begunFrame = std::chrono::system_clock::now(); + + Debug::log(TRACE, "[screencopy] set fps {}, frame took {:.2f}ms, ms till next refresh {:.2f}, estimated actual fps: {:.2f}", pSession->sharingData.framerate, FRAMETOOKMS, + MSTILNEXTREFRESH, std::clamp(1000.0 / FRAMETOOKMS, 1.0, (double)pSession->sharingData.framerate)); + + g_pPortalManager->addTimer({std::clamp(MSTILNEXTREFRESH - 1.0 /* safezone */, 6.0, 1000.0), [pSession]() { g_pPortalManager->m_sPortals.screencopy->startFrameCopy(pSession); }}); } bool CScreencopyPortal::hasToplevelCapabilities() { return m_sState.toplevel; @@ -730,6 +750,20 @@ Debug::log(LOG, "[pipewire] connected"); } +void CPipewireConnection::removeSessionFrameCallbacks(CScreencopyPortal::SSession* pSession) { + Debug::log(TRACE, "[pipewire] removeSessionFrameCallbacks called"); + + if (pSession->sharingData.frameCallback) + zwlr_screencopy_frame_v1_destroy(pSession->sharingData.frameCallback); + if (pSession->sharingData.windowFrameCallback) + hyprland_toplevel_export_frame_v1_destroy(pSession->sharingData.windowFrameCallback); + + pSession->sharingData.windowFrameCallback = nullptr; + pSession->sharingData.frameCallback = nullptr; + + pSession->sharingData.status = FRAME_NONE; +} + CPipewireConnection::~CPipewireConnection() { if (m_pCore) pw_core_disconnect(m_pCore); @@ -753,20 +787,21 @@ if (PSTREAM->pSession->sharingData.status == FRAME_NONE) g_pPortalManager->m_sPortals.screencopy->startFrameCopy(PSTREAM->pSession); else { - if (PSTREAM->pSession->sharingData.frameCallback) - zwlr_screencopy_frame_v1_destroy(PSTREAM->pSession->sharingData.frameCallback); - if (PSTREAM->pSession->sharingData.windowFrameCallback) - hyprland_toplevel_export_frame_v1_destroy(PSTREAM->pSession->sharingData.windowFrameCallback); - PSTREAM->pSession->sharingData.windowFrameCallback = nullptr; - PSTREAM->pSession->sharingData.frameCallback = nullptr; + g_pPortalManager->m_sPortals.screencopy->m_pPipewire->removeSessionFrameCallbacks(PSTREAM->pSession); g_pPortalManager->m_sPortals.screencopy->startFrameCopy(PSTREAM->pSession); } break; - default: PSTREAM->streamState = false; break; + default: { + PSTREAM->streamState = false; + g_pPortalManager->m_sPortals.screencopy->m_pPipewire->removeSessionFrameCallbacks(PSTREAM->pSession); + break; + } } - if (state == PW_STREAM_STATE_UNCONNECTED) + if (state == PW_STREAM_STATE_UNCONNECTED) { + g_pPortalManager->m_sPortals.screencopy->m_pPipewire->removeSessionFrameCallbacks(PSTREAM->pSession); g_pPortalManager->m_sPortals.screencopy->m_pPipewire->destroyStream(PSTREAM->pSession); + } } static void pwStreamParamChanged(void* data, uint32_t id, const spa_pod* param) { @@ -788,6 +823,7 @@ spa_pod_dynamic_builder_init(&dynBuilder[2], params_buffer[2], sizeof(params_buffer[2]), 2048); spa_format_video_raw_parse(param, &PSTREAM->pwVideoInfo); + Debug::log(TRACE, "[pw] Framerate: {}/{}", PSTREAM->pwVideoInfo.max_framerate.num, PSTREAM->pwVideoInfo.max_framerate.denom); PSTREAM->pSession->sharingData.framerate = PSTREAM->pwVideoInfo.max_framerate.num / PSTREAM->pwVideoInfo.max_framerate.denom; uint32_t data_type = 1 << SPA_DATA_MemFd; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/xdg-desktop-portal-hyprland-1.3.1/src/portals/Screencopy.hpp new/xdg-desktop-portal-hyprland-1.3.2/src/portals/Screencopy.hpp --- old/xdg-desktop-portal-hyprland-1.3.1/src/portals/Screencopy.hpp 2024-01-05 15:58:42.000000000 +0100 +++ new/xdg-desktop-portal-hyprland-1.3.2/src/portals/Screencopy.hpp 2024-06-13 11:48:34.000000000 +0200 @@ -6,23 +6,21 @@ #include "../shared/ScreencopyShared.hpp" #include <gbm.h> #include "../shared/Session.hpp" +#include <chrono> -enum cursorModes -{ +enum cursorModes { HIDDEN = 1, EMBEDDED = 2, METADATA = 4, }; -enum sourceTypes -{ +enum sourceTypes { MONITOR = 1, WINDOW = 2, VIRTUAL = 4, }; -enum frameStatus -{ +enum frameStatus { FRAME_NONE = 0, FRAME_QUEUED, FRAME_READY, @@ -72,16 +70,17 @@ SSelectionData selection; struct { - bool active = false; - zwlr_screencopy_frame_v1* frameCallback = nullptr; - hyprland_toplevel_export_frame_v1* windowFrameCallback = nullptr; - frameStatus status = FRAME_NONE; - uint64_t tvSec = 0; - uint32_t tvNsec = 0; - uint64_t tvTimestampNs = 0; - uint32_t nodeID = 0; - uint32_t framerate = 60; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + bool active = false; + zwlr_screencopy_frame_v1* frameCallback = nullptr; + hyprland_toplevel_export_frame_v1* windowFrameCallback = nullptr; + frameStatus status = FRAME_NONE; + uint64_t tvSec = 0; + uint32_t tvNsec = 0; + uint64_t tvTimestampNs = 0; + uint32_t nodeID = 0; + uint32_t framerate = 60; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + std::chrono::system_clock::time_point begunFrame = std::chrono::system_clock::now(); struct { uint32_t w = 0, h = 0, size = 0, stride = 0, fmt = 0; @@ -152,6 +151,7 @@ std::unique_ptr<SBuffer> createBuffer(SPWStream* pStream, bool dmabuf); SPWStream* streamFromSession(CScreencopyPortal::SSession* pSession); + void removeSessionFrameCallbacks(CScreencopyPortal::SSession* pSession); uint32_t buildFormatsFor(spa_pod_builder* b[2], const spa_pod* params[2], SPWStream* stream); void updateStreamParam(SPWStream* pStream);