summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorSunderland93 <[email protected]>2026-08-09 12:52:33 +0400
committerLuke from DC <[email protected]>2026-08-19 19:15:44 +0000
commit82c1a8a60564890ccb812274d8da70e00a3cf83b (patch)
treeffbf803a0c667de5c3975f53d58749a768f905d7 /plugins
parent78d84fce70f7d6a24a37eb1dfdaa2575d2c9643b (diff)
downloadmate-settings-daemon-82c1a8a60564890ccb812274d8da70e00a3cf83b.tar.bz2
mate-settings-daemon-82c1a8a60564890ccb812274d8da70e00a3cf83b.tar.xz
clipboard: adjust offer timeout
Diffstat (limited to 'plugins')
-rw-r--r--plugins/clipboard/msd-clipboard-manager-wayland.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/plugins/clipboard/msd-clipboard-manager-wayland.c b/plugins/clipboard/msd-clipboard-manager-wayland.c
index 59babe8..a8701c8 100644
--- a/plugins/clipboard/msd-clipboard-manager-wayland.c
+++ b/plugins/clipboard/msd-clipboard-manager-wayland.c
@@ -67,6 +67,8 @@ typedef struct
GPtrArray *receives;
struct ext_data_control_source_v1 *source;
gboolean reoffer_pending;
+ guint reoffer_timeout;
+ gint64 last_activity_ms;
} SelectionState;
struct _MsdClipboardManagerWayland
@@ -114,6 +116,62 @@ state_from_kind (MsdClipboardManagerWayland *wl,
static void
start_reoffer (SelectionState *state);
+#define REOFFER_WINDOW_MS 2000
+#define REOFFER_QUIET_MS 1000
+
+static void
+cancel_reoffer (SelectionState *state)
+{
+ if (state->reoffer_timeout != 0) {
+ g_source_remove (state->reoffer_timeout);
+ state->reoffer_timeout = 0;
+ }
+}
+
+static gboolean
+reoffer_timeout_cb (gpointer data)
+{
+ SelectionState *state = data;
+
+ state->reoffer_timeout = 0;
+ start_reoffer (state);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+schedule_reoffer (SelectionState *state)
+{
+ if (state->cache == NULL || state->cache->len == 0)
+ return;
+ if (state->wl->dc_manager == NULL || state->wl->device == NULL)
+ return;
+ if (state->source != NULL)
+ return;
+
+ if (state->reoffer_timeout == 0) {
+ gint64 now;
+ guint delay;
+
+ now = g_get_monotonic_time () / 1000;
+
+ /* Keep a longer delay right after clipboard activity: an app
+ * may be about to re-assert its selection (e.g. GTK re-serving
+ * a torn copy if we steal ownership mid-store). Once the
+ * selection has been quiet, fall back to a shorter delay so
+ * pasting works soon after the source app is closed. */
+ delay = REOFFER_WINDOW_MS - (now - state->last_activity_ms);
+ if (delay > REOFFER_WINDOW_MS)
+ delay = REOFFER_WINDOW_MS;
+ if (delay < REOFFER_QUIET_MS)
+ delay = REOFFER_QUIET_MS;
+
+ state->reoffer_timeout = g_timeout_add (delay,
+ reoffer_timeout_cb,
+ state);
+ }
+}
+
static void
finalize_cache (SelectionState *state)
{
@@ -188,7 +246,7 @@ receive_finish (ClipReceive *recv)
if (state->reoffer_pending) {
state->reoffer_pending = FALSE;
- start_reoffer (state);
+ schedule_reoffer (state);
}
}
@@ -256,6 +314,8 @@ start_receives (SelectionState *state,
if (mimes == NULL)
return;
+ state->last_activity_ms = g_get_monotonic_time () / 1000;
+
for (i = 0; i < mimes->len; i++) {
ClipReceive *recv;
int fds[2];
@@ -355,6 +415,8 @@ handle_source_cancelled (void *data,
ext_data_control_source_v1_destroy (source);
state->source = NULL;
}
+
+ state->last_activity_ms = g_get_monotonic_time () / 1000;
}
static const struct ext_data_control_source_v1_listener source_listener = {
@@ -447,16 +509,18 @@ handle_selection_for (MsdClipboardManagerWayland *wl,
if (offer == NULL) {
state->offer = NULL;
- if (state->receives != NULL && state->receives->len > 0)
+ if (state->receives != NULL && state->receives->len > 0) {
state->reoffer_pending = TRUE;
- else
- start_reoffer (state);
+ } else {
+ schedule_reoffer (state);
+ }
return;
}
state->offer = offer;
state->reoffer_pending = FALSE;
+ cancel_reoffer (state);
if (wl->pending_offer == offer && wl->pending_mimes != NULL) {
GPtrArray *mimes;
@@ -587,6 +651,8 @@ selection_state_clear (SelectionState *state)
{
guint i;
+ cancel_reoffer (state);
+
if (state->source != NULL) {
ext_data_control_source_v1_destroy (state->source);
state->source = NULL;