2024-08-30 14:53:25 +00:00
|
|
|
/*
|
2024-09-17 19:00:25 +00:00
|
|
|
* Deskflow -- mouse and keyboard sharing utility
|
2026-05-13 00:18:18 +00:00
|
|
|
* SPDX-FileCopyrightText: (C) 2025 - 2026 Deskflow Developers
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
* SPDX-FileCopyrightText: (C) 2024, 2026 Synergy App Ltd
|
|
|
|
|
* SPDX-FileCopyrightText: (C) 2022, 2026 Red Hat, Inc.
|
2025-01-24 00:11:17 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
2024-08-30 14:53:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
#include "deskflow/IClipboard.h"
|
2024-08-30 14:53:25 +00:00
|
|
|
#include "mt/Thread.h"
|
|
|
|
|
#include "platform/EiScreen.h"
|
|
|
|
|
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
#include <QByteArray>
|
|
|
|
|
|
2024-08-30 14:53:25 +00:00
|
|
|
#include <glib.h>
|
|
|
|
|
#include <libportal/inputcapture.h>
|
|
|
|
|
#include <libportal/portal.h>
|
|
|
|
|
|
2026-05-13 00:18:18 +00:00
|
|
|
#include <cstdint>
|
|
|
|
|
#include <map>
|
2026-05-13 00:19:18 +00:00
|
|
|
#include <utility>
|
2026-05-13 00:18:18 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
2024-09-17 19:00:25 +00:00
|
|
|
namespace deskflow {
|
2024-08-30 14:53:25 +00:00
|
|
|
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
class EiClipboard;
|
|
|
|
|
|
2024-10-17 18:04:35 +00:00
|
|
|
class PortalInputCapture
|
|
|
|
|
{
|
2024-08-30 14:53:25 +00:00
|
|
|
public:
|
|
|
|
|
PortalInputCapture(EiScreen *screen, IEventQueue *events);
|
|
|
|
|
~PortalInputCapture();
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
|
|
|
|
|
// Get the clipboard for the specified ID
|
|
|
|
|
EiClipboard *getClipboard(ClipboardID id) const;
|
2024-08-30 14:53:25 +00:00
|
|
|
void enable();
|
|
|
|
|
void disable();
|
|
|
|
|
void release();
|
|
|
|
|
void release(double x, double y);
|
2025-08-06 23:41:44 +00:00
|
|
|
bool isActive() const
|
2024-10-17 18:04:35 +00:00
|
|
|
{
|
2025-06-20 00:49:53 +00:00
|
|
|
return m_isActive;
|
2024-10-17 18:04:35 +00:00
|
|
|
}
|
2024-08-30 14:53:25 +00:00
|
|
|
|
|
|
|
|
private:
|
2025-05-23 20:52:46 +00:00
|
|
|
void glibThread(const void *);
|
2025-06-20 00:49:53 +00:00
|
|
|
gboolean timeoutHandler() const;
|
|
|
|
|
gboolean initSession();
|
2026-02-02 01:10:24 +00:00
|
|
|
void setupSession(XdpInputCaptureSession *session);
|
|
|
|
|
void handleStart(GObject *object, GAsyncResult *res);
|
2025-06-20 00:49:53 +00:00
|
|
|
void handleInitSession(GObject *object, GAsyncResult *res);
|
|
|
|
|
void handleSetPointerBarriers(const GObject *object, GAsyncResult *res);
|
|
|
|
|
void handleSessionClosed(XdpSession *session);
|
|
|
|
|
void handleDisabled(const XdpInputCaptureSession *session, const GVariant *option);
|
2025-06-20 15:20:37 +00:00
|
|
|
void handleActivated(const XdpInputCaptureSession *session, const std::uint32_t activationId, GVariant *options);
|
|
|
|
|
void
|
|
|
|
|
handleDeactivated(const XdpInputCaptureSession *session, const std::uint32_t activationId, const GVariant *options);
|
2025-06-20 02:29:34 +00:00
|
|
|
void handleZonesChanged(XdpInputCaptureSession *session, const GVariant *options);
|
2024-08-30 14:53:25 +00:00
|
|
|
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
void handleSelectionOwnerChanged(XdpSession *session, GStrv mimeTypes, gboolean isOwner);
|
|
|
|
|
void handleSelectionTransfer(XdpSession *session, const char *mimeType, uint32_t serial);
|
|
|
|
|
void readClipboardSelection(XdpSession *session);
|
|
|
|
|
void claimClipboardOwnership(XdpSession *session);
|
|
|
|
|
|
|
|
|
|
struct SupportedMime
|
|
|
|
|
{
|
|
|
|
|
const char *mime;
|
|
|
|
|
IClipboard::Format format;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Listed in preference order: richer formats first.
|
|
|
|
|
static constexpr SupportedMime kSupportedMimes[] = {
|
|
|
|
|
{"image/png", IClipboard::Format::Bitmap},
|
|
|
|
|
{"text/plain;charset=utf-8", IClipboard::Format::Text},
|
|
|
|
|
{"text/plain", IClipboard::Format::Text},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static QByteArray formatMimeTypes(const char *const *mimeTypes);
|
|
|
|
|
static const SupportedMime *findSupportedMime(const char *mime);
|
|
|
|
|
static const SupportedMime *pickSupportedMime(const char *const *available);
|
|
|
|
|
static QByteArray dibToBmp(const std::string &dib);
|
|
|
|
|
static std::string bmpToDib(const QByteArray &bmp);
|
|
|
|
|
static QByteArray encodeFormat(IClipboard::Format format, const std::string &data);
|
|
|
|
|
static std::string decodeFormat(IClipboard::Format format, const QByteArray &bytes);
|
|
|
|
|
static QByteArray readSelectionBytes(XdpSession *session, const char *mime, qint64 maxBytes);
|
|
|
|
|
|
2024-08-30 14:53:25 +00:00
|
|
|
/// g_signal_connect callback wrapper
|
2025-06-20 15:20:37 +00:00
|
|
|
static void sessionClosed(XdpSession *session, const gpointer data)
|
2024-10-17 18:04:35 +00:00
|
|
|
{
|
2025-06-20 00:49:53 +00:00
|
|
|
static_cast<PortalInputCapture *>(data)->handleSessionClosed(session);
|
2024-08-30 14:53:25 +00:00
|
|
|
}
|
2025-06-20 15:20:37 +00:00
|
|
|
static void disabled(const XdpInputCaptureSession *session, const GVariant *options, const gpointer data)
|
2024-10-17 18:04:35 +00:00
|
|
|
{
|
2025-06-20 00:49:53 +00:00
|
|
|
static_cast<PortalInputCapture *>(data)->handleDisabled(session, options);
|
2024-08-30 14:53:25 +00:00
|
|
|
}
|
2025-06-20 15:20:37 +00:00
|
|
|
static void activated(
|
|
|
|
|
const XdpInputCaptureSession *session, const std::uint32_t activationId, GVariant *options, const gpointer data
|
|
|
|
|
)
|
2024-10-17 18:04:35 +00:00
|
|
|
{
|
2025-06-20 00:49:53 +00:00
|
|
|
static_cast<PortalInputCapture *>(data)->handleActivated(session, activationId, options);
|
2024-08-30 14:53:25 +00:00
|
|
|
}
|
2025-06-20 15:20:37 +00:00
|
|
|
static void deactivated(
|
|
|
|
|
const XdpInputCaptureSession *session, const std::uint32_t activationId, const GVariant *options,
|
|
|
|
|
const gpointer data
|
|
|
|
|
)
|
2024-10-17 18:04:35 +00:00
|
|
|
{
|
2025-06-20 00:49:53 +00:00
|
|
|
static_cast<PortalInputCapture *>(data)->handleDeactivated(session, activationId, options);
|
2024-08-30 14:53:25 +00:00
|
|
|
}
|
2025-06-20 15:20:37 +00:00
|
|
|
static void zonesChanged(XdpInputCaptureSession *session, const GVariant *options, const gpointer data)
|
2024-10-17 18:04:35 +00:00
|
|
|
{
|
2025-06-20 00:49:53 +00:00
|
|
|
static_cast<PortalInputCapture *>(data)->handleZonesChanged(session, options);
|
2024-08-30 14:53:25 +00:00
|
|
|
}
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
static void selectionOwnerChanged(XdpSession *session, GStrv mimeTypes, gboolean isOwner, const gpointer data)
|
|
|
|
|
{
|
|
|
|
|
static_cast<PortalInputCapture *>(data)->handleSelectionOwnerChanged(session, mimeTypes, isOwner);
|
|
|
|
|
}
|
|
|
|
|
static void selectionTransfer(XdpSession *session, const char *mimeType, uint32_t serial, const gpointer data)
|
|
|
|
|
{
|
|
|
|
|
static_cast<PortalInputCapture *>(data)->handleSelectionTransfer(session, mimeType, serial);
|
|
|
|
|
}
|
2024-08-30 14:53:25 +00:00
|
|
|
|
|
|
|
|
private:
|
2025-06-20 15:16:55 +00:00
|
|
|
enum class Signal : uint8_t
|
|
|
|
|
{
|
|
|
|
|
SessionClosed,
|
|
|
|
|
Disabled,
|
|
|
|
|
Activated,
|
|
|
|
|
Deactivated,
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
ZonesChanged,
|
|
|
|
|
|
|
|
|
|
// Clipboard signals
|
|
|
|
|
SelectionOwnerChanged,
|
|
|
|
|
SelectionTransfer,
|
2025-06-20 15:16:55 +00:00
|
|
|
};
|
|
|
|
|
|
2026-05-13 00:18:18 +00:00
|
|
|
enum class BarrierSide : uint8_t
|
|
|
|
|
{
|
|
|
|
|
Left,
|
|
|
|
|
Right,
|
|
|
|
|
Top,
|
|
|
|
|
Bottom
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-13 00:19:18 +00:00
|
|
|
struct BarrierInfo
|
|
|
|
|
{
|
|
|
|
|
guint id = 0;
|
|
|
|
|
BarrierSide side = BarrierSide::Left;
|
|
|
|
|
gint x = 0;
|
|
|
|
|
gint y = 0;
|
|
|
|
|
guint width = 0;
|
|
|
|
|
guint height = 0;
|
|
|
|
|
gint x1 = 0;
|
|
|
|
|
gint y1 = 0;
|
|
|
|
|
gint x2 = 0;
|
|
|
|
|
gint y2 = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct Bounds
|
|
|
|
|
{
|
|
|
|
|
gint left = 0;
|
|
|
|
|
gint top = 0;
|
|
|
|
|
gint right = 0;
|
|
|
|
|
gint bottom = 0;
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-13 00:18:18 +00:00
|
|
|
static const char *barrierSideName(BarrierSide side);
|
2026-05-13 00:19:18 +00:00
|
|
|
static int
|
|
|
|
|
scaleCoordinateBetweenRanges(double value, int sourceMin, int sourceMax, int destinationMin, int destinationMax);
|
|
|
|
|
bool getPortalBounds(Bounds &bounds) const;
|
|
|
|
|
bool getClosestReleaseBarrier(
|
|
|
|
|
double x, double y, int screenLeft, int screenTop, int screenRight, int screenBottom, const Bounds &portalBounds,
|
|
|
|
|
BarrierInfo &barrier
|
|
|
|
|
) const;
|
|
|
|
|
std::pair<int, int> mapPortalActivationToScreenPosition(guint barrierId, double rawX, double rawY) const;
|
|
|
|
|
std::pair<double, double> mapPortalReleasePosition(double x, double y) const;
|
2026-05-13 00:18:18 +00:00
|
|
|
void addBarrier(guint id, BarrierSide side, gint zoneX, gint zoneY, guint zoneWidth, guint zoneHeight);
|
|
|
|
|
|
2025-06-20 00:49:53 +00:00
|
|
|
EiScreen *m_screen = nullptr;
|
|
|
|
|
IEventQueue *m_events = nullptr;
|
2026-02-02 01:10:24 +00:00
|
|
|
int m_portalVersion = 0;
|
2024-08-30 14:53:25 +00:00
|
|
|
|
2025-06-20 00:49:53 +00:00
|
|
|
Thread *m_glibThread;
|
|
|
|
|
GMainLoop *m_glibMainLoop = nullptr;
|
2024-08-30 14:53:25 +00:00
|
|
|
|
2025-06-20 00:49:53 +00:00
|
|
|
XdpPortal *m_portal = nullptr;
|
|
|
|
|
XdpInputCaptureSession *m_session = nullptr;
|
2024-08-30 14:53:25 +00:00
|
|
|
|
2025-06-20 15:20:37 +00:00
|
|
|
std::map<Signal, gulong> m_signals = {
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
{Signal::SessionClosed, 0}, {Signal::Disabled, 0}, {Signal::Activated, 0},
|
|
|
|
|
{Signal::Deactivated, 0}, {Signal::ZonesChanged, 0},
|
|
|
|
|
|
|
|
|
|
{Signal::SelectionOwnerChanged, 0}, {Signal::SelectionTransfer, 0},
|
2025-06-20 15:16:55 +00:00
|
|
|
};
|
2024-08-30 14:53:25 +00:00
|
|
|
|
2025-06-20 00:49:53 +00:00
|
|
|
bool m_enabled = false;
|
|
|
|
|
bool m_isActive = false;
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
bool m_pendingClipboardRead = false;
|
2025-06-20 00:49:53 +00:00
|
|
|
std::uint32_t m_activationId = 0;
|
2024-08-30 14:53:25 +00:00
|
|
|
|
2025-06-20 00:49:53 +00:00
|
|
|
std::vector<XdpInputCapturePointerBarrier *> m_barriers;
|
2026-05-13 00:19:18 +00:00
|
|
|
std::vector<BarrierInfo> m_barrierInfo;
|
feat: inputcapture clipboard support
Send the clipboard over the libportal InputCapture portal. Only built
if the installed libportal has clipboard support.
AI disclosure: Claude was used on both sides of this work.
- Peter Hutterer: "The second commit was purely written by Claude
after I stared at this for too long without seeing any hope of
getting started. Turns out Claude wrote something that at least
looks correct and it does work. It needs review but also needs
knowledge of deskflow's internals that I don't have..."
- Nick Bolton: Claude also assisted with the follow-up work listed
below (image copy/paste, session re-request, race fixes, size/mime
validation, and CMake detection).
Server side (Wayland host, Peter Hutterer):
- Initial scaffolding for inputcapture clipboard support, guarded so it
only builds when the portal exposes the clipboard API.
- Integrate clipboard data into the inputcapture session so the host
clipboard can be offered to the remote (the Claude-written commit
referenced above).
Client side (Wayland receiver, KoljaFrahm):
- Receive clipboard data from the server and feed it into the local
clipboard through libportal. Built on the reference code by Peter:
https://github.com/whot/libportal-clipboard-test/tree/main
Build integration and rebase (Chris Rizzitello, sithlord48):
- Add the original CMake check for libportal/clipboard.h to define
HAVE_LIBPORTAL_CLIPBOARD, and guard the libportal clipboard use on
it.
- Update the code style and rebase onto the updated input capture
session persistence: https://github.com/deskflow/deskflow/pull/9415
Image support and reliability fixes (Nick Bolton):
- Support image copy/paste in addition to text, so screenshots and
other image clipboard contents work both ways through inputcapture.
- Re-request the input capture session when it comes up without a
clipboard, so new testers with existing sessions can get clipboard
functionality without needing to clear the session.
- Defer clipboard reads until the input capture session is active,
avoiding races where reads happen before the portal is ready.
- Fix assorted style issues in original commit to match conventions.
- Check the configured clipboard size limit and validate incoming
mime types before forwarding inputcapture clipboard data.
- Switch the CMake clipboard probe to check_symbol_exists so detection
matches what the compiler actually sees in the headers.
Co-authored-by: Nick Bolton <nick@symless.com>
Co-authored-by: KoljaFrahm <GitHub.Kolja@dfgh.net>
Co-authored-by: Chris Rizzitello <sithlord48@gmail.com>
2026-02-05 04:01:33 +00:00
|
|
|
|
|
|
|
|
EiClipboard *m_clipboard = nullptr;
|
2024-08-30 14:53:25 +00:00
|
|
|
};
|
|
|
|
|
|
2024-09-17 19:00:25 +00:00
|
|
|
} // namespace deskflow
|