mirror of
https://github.com/brl/mutter.git
synced 2025-01-01 07:22:15 +00:00
dd2beae6a8
As with other parts, make objects have the ability to walk up the ownership chain to the context, to get things like the Wayland compositor or backend instances. Contains these squashed commits: display: Don't get backend from singleton window: Don't get backend from singleton keybindings: Don't get backend from singleton workspace: Don't get backend from singleton display: Don't get Wayland compositor from singleton selection: Add display getter context/main: Get backend directly from the context clipboard-manager: Don't get display from singleton stack-tracker: Don't use singleton MetaLater API startup-notification: Hook up sequences and activations to display This allows using context aware API directly. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2718>
181 lines
5.7 KiB
C
181 lines
5.7 KiB
C
/*
|
|
* Copyright (C) 2018 Red Hat
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
* 02111-1307, USA.
|
|
*
|
|
* Author: Carlos Garnacho <carlosg@gnome.org>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "core/meta-clipboard-manager.h"
|
|
#include "core/meta-selection-private.h"
|
|
#include "meta/meta-selection-source-memory.h"
|
|
|
|
#define MAX_TEXT_SIZE (4 * 1024 * 1024) /* 4MB */
|
|
#define MAX_IMAGE_SIZE (200 * 1024 * 1024) /* 200MB */
|
|
|
|
/* Supported mimetype globs, from least to most preferred */
|
|
static struct {
|
|
const char *mimetype_glob;
|
|
ssize_t max_transfer_size;
|
|
} supported_mimetypes[] = {
|
|
{ "image/tiff", MAX_IMAGE_SIZE },
|
|
{ "image/bmp", MAX_IMAGE_SIZE },
|
|
{ "image/gif", MAX_IMAGE_SIZE },
|
|
{ "image/jpeg", MAX_IMAGE_SIZE },
|
|
{ "image/webp", MAX_IMAGE_SIZE },
|
|
{ "image/png", MAX_IMAGE_SIZE },
|
|
{ "image/svg+xml", MAX_IMAGE_SIZE },
|
|
{ "text/plain", MAX_TEXT_SIZE },
|
|
{ "text/plain;charset=utf-8", MAX_TEXT_SIZE },
|
|
};
|
|
|
|
static gboolean
|
|
mimetype_match (const char *mimetype,
|
|
int *idx,
|
|
gssize *max_transfer_size)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (supported_mimetypes); i++)
|
|
{
|
|
if (g_pattern_match_simple (supported_mimetypes[i].mimetype_glob, mimetype))
|
|
{
|
|
*max_transfer_size = supported_mimetypes[i].max_transfer_size;
|
|
*idx = i;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
transfer_cb (MetaSelection *selection,
|
|
GAsyncResult *result,
|
|
GOutputStream *output)
|
|
{
|
|
MetaDisplay *display = meta_selection_get_display (selection);
|
|
GError *error = NULL;
|
|
|
|
if (!meta_selection_transfer_finish (selection, result, &error))
|
|
{
|
|
g_warning ("Failed to store clipboard: %s", error->message);
|
|
g_error_free (error);
|
|
g_object_unref (output);
|
|
return;
|
|
}
|
|
|
|
g_output_stream_close (output, NULL, NULL);
|
|
display->saved_clipboard =
|
|
g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output));
|
|
g_object_unref (output);
|
|
}
|
|
|
|
static void
|
|
owner_changed_cb (MetaSelection *selection,
|
|
MetaSelectionType selection_type,
|
|
MetaSelectionSource *new_owner,
|
|
MetaDisplay *display)
|
|
{
|
|
if (selection_type != META_SELECTION_CLIPBOARD)
|
|
return;
|
|
|
|
if (new_owner && new_owner != display->selection_source)
|
|
{
|
|
GOutputStream *output;
|
|
GList *mimetypes, *l;
|
|
int best_idx = -1;
|
|
const char *best = NULL;
|
|
ssize_t transfer_size = -1;
|
|
|
|
/* New selection source, find the best mimetype in order to
|
|
* keep a copy of it.
|
|
*/
|
|
g_clear_object (&display->selection_source);
|
|
g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
|
|
g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
|
|
|
|
mimetypes = meta_selection_get_mimetypes (selection, selection_type);
|
|
|
|
for (l = mimetypes; l; l = l->next)
|
|
{
|
|
gssize max_transfer_size;
|
|
int idx;
|
|
|
|
if (!mimetype_match (l->data, &idx, &max_transfer_size))
|
|
continue;
|
|
|
|
if (best_idx < idx)
|
|
{
|
|
best_idx = idx;
|
|
best = l->data;
|
|
transfer_size = max_transfer_size;
|
|
}
|
|
}
|
|
|
|
if (best_idx < 0)
|
|
{
|
|
g_list_free_full (mimetypes, g_free);
|
|
return;
|
|
}
|
|
|
|
display->saved_clipboard_mimetype = g_strdup (best);
|
|
g_list_free_full (mimetypes, g_free);
|
|
output = g_memory_output_stream_new_resizable ();
|
|
meta_selection_transfer_async (selection,
|
|
META_SELECTION_CLIPBOARD,
|
|
display->saved_clipboard_mimetype,
|
|
transfer_size,
|
|
output,
|
|
NULL,
|
|
(GAsyncReadyCallback) transfer_cb,
|
|
output);
|
|
}
|
|
else if (!new_owner && display->saved_clipboard)
|
|
{
|
|
/* Old owner is gone, time to take over */
|
|
new_owner = meta_selection_source_memory_new (display->saved_clipboard_mimetype,
|
|
display->saved_clipboard);
|
|
g_set_object (&display->selection_source, new_owner);
|
|
meta_selection_set_owner (selection, selection_type, new_owner);
|
|
g_object_unref (new_owner);
|
|
}
|
|
}
|
|
|
|
void
|
|
meta_clipboard_manager_init (MetaDisplay *display)
|
|
{
|
|
MetaSelection *selection;
|
|
|
|
selection = meta_display_get_selection (display);
|
|
g_signal_connect_after (selection, "owner-changed",
|
|
G_CALLBACK (owner_changed_cb), display);
|
|
}
|
|
|
|
void
|
|
meta_clipboard_manager_shutdown (MetaDisplay *display)
|
|
{
|
|
MetaSelection *selection;
|
|
|
|
g_clear_object (&display->selection_source);
|
|
g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
|
|
g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
|
|
selection = meta_display_get_selection (display);
|
|
g_signal_handlers_disconnect_by_func (selection, owner_changed_cb, display);
|
|
}
|