/*
 * GTK UI -- clipboard support
 *
 * Copyright (C) 2021 Gerd Hoffmann <kraxel@redhat.com>
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/main-loop.h"

#include "ui/gtk.h"

static QemuClipboardSelection gd_find_selection(GtkDisplayState *gd,
                                                GtkClipboard *clipboard)
{
    QemuClipboardSelection s;

    for (s = 0; s < QEMU_CLIPBOARD_SELECTION__COUNT; s++) {
        if (gd->gtkcb[s] == clipboard) {
            return s;
        }
    }
    return QEMU_CLIPBOARD_SELECTION_CLIPBOARD;
}

static void gd_clipboard_get_data(GtkClipboard     *clipboard,
                                  GtkSelectionData *selection_data,
                                  guint             selection_info,
                                  gpointer          data)
{
    GtkDisplayState *gd = data;
    QemuClipboardSelection s = gd_find_selection(gd, clipboard);
    QemuClipboardType type = QEMU_CLIPBOARD_TYPE_TEXT;
    QemuClipboardInfo *info = qemu_clipboard_info_ref(gd->cbinfo[s]);

    qemu_clipboard_request(info, type);
    while (info == gd->cbinfo[s] &&
           info->types[type].available &&
           info->types[type].data == NULL) {
        main_loop_wait(false);
    }

    if (info == gd->cbinfo[s] && gd->cbowner[s]) {
        gtk_selection_data_set_text(selection_data,
                                    info->types[type].data,
                                    info->types[type].size);
    } else {
        /* clipboard owner changed while waiting for the data */
    }

    qemu_clipboard_info_unref(info);
}

static void gd_clipboard_clear(GtkClipboard *clipboard,
                               gpointer data)
{
    GtkDisplayState *gd = data;
    QemuClipboardSelection s = gd_find_selection(gd, clipboard);

    gd->cbowner[s] = false;
}

static void gd_clipboard_notify(Notifier *notifier, void *data)
{
    GtkDisplayState *gd = container_of(notifier, GtkDisplayState, cbpeer.update);
    QemuClipboardInfo *info = data;
    QemuClipboardSelection s = info->selection;
    bool self_update = info->owner == &gd->cbpeer;

    if (info != gd->cbinfo[s]) {
        qemu_clipboard_info_unref(gd->cbinfo[s]);
        gd->cbinfo[s] = qemu_clipboard_info_ref(info);
        gd->cbpending[s] = 0;
        if (!self_update) {
            GtkTargetList *list;
            GtkTargetEntry *targets;
            gint n_targets;

            list = gtk_target_list_new(NULL, 0);
            if (info->types[QEMU_CLIPBOARD_TYPE_TEXT].available) {
                gtk_target_list_add_text_targets(list, 0);
            }
            targets = gtk_target_table_new_from_list(list, &n_targets);

            gtk_clipboard_clear(gd->gtkcb[s]);
            gd->cbowner[s] = true;
            gtk_clipboard_set_with_data(gd->gtkcb[s],
                                        targets, n_targets,
                                        gd_clipboard_get_data,
                                        gd_clipboard_clear,
                                        gd);

            gtk_target_table_free(targets, n_targets);
            gtk_target_list_unref(list);
        }
        return;
    }

    if (self_update) {
        return;
    }

    /*
     * Clipboard got updated, with data probably.  No action here, we
     * are waiting for updates in gd_clipboard_get_data().
     */
}

static void gd_clipboard_request(QemuClipboardInfo *info,
                                 QemuClipboardType type)
{
    GtkDisplayState *gd = container_of(info->owner, GtkDisplayState, cbpeer);
    char *text;

    switch (type) {
    case QEMU_CLIPBOARD_TYPE_TEXT:
        text = gtk_clipboard_wait_for_text(gd->gtkcb[info->selection]);
        if (text) {
            qemu_clipboard_set_data(&gd->cbpeer, info, type,
                                    strlen(text), text, true);
            g_free(text);
        }
        break;
    default:
        break;
    }
}

static void gd_owner_change(GtkClipboard *clipboard,
                            GdkEvent *event,
                            gpointer data)
{
    GtkDisplayState *gd = data;
    QemuClipboardSelection s = gd_find_selection(gd, clipboard);
    QemuClipboardInfo *info;

    if (gd->cbowner[s]) {
        /* ignore notifications about our own grabs */
        return;
    }


    switch (event->owner_change.reason) {
    case GDK_SETTING_ACTION_NEW:
        info = qemu_clipboard_info_new(&gd->cbpeer, s);
        if (gtk_clipboard_wait_is_text_available(clipboard)) {
            info->types[QEMU_CLIPBOARD_TYPE_TEXT].available = true;
        }

        qemu_clipboard_update(info);
        qemu_clipboard_info_unref(info);
        break;
    default:
        break;
    }
}

void gd_clipboard_init(GtkDisplayState *gd)
{
    gd->cbpeer.name = "gtk";
    gd->cbpeer.update.notify = gd_clipboard_notify;
    gd->cbpeer.request = gd_clipboard_request;
    qemu_clipboard_peer_register(&gd->cbpeer);

    gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD] =
        gtk_clipboard_get(gdk_atom_intern("CLIPBOARD", FALSE));
    gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY] =
        gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE));
    gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY] =
        gtk_clipboard_get(gdk_atom_intern("SECONDARY", FALSE));

    g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_CLIPBOARD],
                     "owner-change", G_CALLBACK(gd_owner_change), gd);
    g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_PRIMARY],
                     "owner-change", G_CALLBACK(gd_owner_change), gd);
    g_signal_connect(gd->gtkcb[QEMU_CLIPBOARD_SELECTION_SECONDARY],
                     "owner-change", G_CALLBACK(gd_owner_change), gd);
}
