17c804472Sopenharmony_ci/*
27c804472Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
37c804472Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
47c804472Sopenharmony_ci * you may not use this file except in compliance with the License.
57c804472Sopenharmony_ci * You may obtain a copy of the License at
67c804472Sopenharmony_ci *
77c804472Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
87c804472Sopenharmony_ci *
97c804472Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
107c804472Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
117c804472Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c804472Sopenharmony_ci * See the License for the specific language governing permissions and
137c804472Sopenharmony_ci * limitations under the License.
147c804472Sopenharmony_ci */
157c804472Sopenharmony_ci
167c804472Sopenharmony_ci#include "ClipboardX11.h"
177c804472Sopenharmony_ci#include <iostream>
187c804472Sopenharmony_ci#include <cstring>
197c804472Sopenharmony_ci#include <X11/Xlib.h>
207c804472Sopenharmony_ci
217c804472Sopenharmony_civoid ClipboardX11::SetClipboardData(const std::string& str)
227c804472Sopenharmony_ci{
237c804472Sopenharmony_ci    display = XOpenDisplay(0);
247c804472Sopenharmony_ci    int ret = DefaultScreen(display);
257c804472Sopenharmony_ci    window = XCreateSimpleWindow(display, RootWindow(display, ret), 0, 0, 1, 1, 0,
267c804472Sopenharmony_ci        BlackPixel(display, ret), WhitePixel(display, ret));
277c804472Sopenharmony_ci    targets_atom = XInternAtom(display, "TARGETS", 0);
287c804472Sopenharmony_ci    text_atom = XInternAtom(display, "TEXT", 0);
297c804472Sopenharmony_ci    UTF8 = XInternAtom(display, "UTF8_STRING", 1);
307c804472Sopenharmony_ci    if (UTF8 == None) UTF8 = XA_STRING;
317c804472Sopenharmony_ci    Atom selection = XInternAtom(display, "CLIPBOARD", 0);
327c804472Sopenharmony_ci    SetCopyData(selection, str, strlen(str.c_str()));
337c804472Sopenharmony_ci}
347c804472Sopenharmony_ci
357c804472Sopenharmony_ciconst std::string ClipboardX11::GetClipboardData()
367c804472Sopenharmony_ci{
377c804472Sopenharmony_ci    display = XOpenDisplay(0);
387c804472Sopenharmony_ci    int ret = DefaultScreen(display);
397c804472Sopenharmony_ci    window = XCreateSimpleWindow(display, RootWindow(display, ret), 0, 0, 1, 1, 0,
407c804472Sopenharmony_ci                                 BlackPixel(display, ret), WhitePixel(display, ret));
417c804472Sopenharmony_ci    std::string retStr; // NOLINT
427c804472Sopenharmony_ci    UTF8 = XInternAtom(display, "UTF8_STRING", True);
437c804472Sopenharmony_ci    if (UTF8 != None) retStr = GetPasteType(UTF8);
447c804472Sopenharmony_ci    if (retStr.empty()) retStr = GetPasteType(XA_STRING);
457c804472Sopenharmony_ci    return retStr;
467c804472Sopenharmony_ci}
477c804472Sopenharmony_ci
487c804472Sopenharmony_civoid ClipboardX11::SetCopyData(const Atom& selection, const std::string& text, const int size)
497c804472Sopenharmony_ci{
507c804472Sopenharmony_ci    XEvent event;
517c804472Sopenharmony_ci    XSetSelectionOwner (display, selection, window, 0);
527c804472Sopenharmony_ci    if (XGetSelectionOwner (display, selection) != window) {
537c804472Sopenharmony_ci        return;
547c804472Sopenharmony_ci    }
557c804472Sopenharmony_ci    while (1) {
567c804472Sopenharmony_ci        XNextEvent (display, &event);
577c804472Sopenharmony_ci        if (event.type == SelectionRequest) {
587c804472Sopenharmony_ci            if (event.xselectionrequest.selection != selection) {
597c804472Sopenharmony_ci                break;
607c804472Sopenharmony_ci            }
617c804472Sopenharmony_ci            XSelectionRequestEvent* xsr = &event.xselectionrequest;
627c804472Sopenharmony_ci            XSelectionEvent ev = {0};
637c804472Sopenharmony_ci            int ret = 0;
647c804472Sopenharmony_ci            ev.type = SelectionNotify, ev.display = xsr->display, ev.requestor = xsr->requestor,
657c804472Sopenharmony_ci            ev.selection = xsr->selection, ev.time = xsr->time, ev.target = xsr->target,
667c804472Sopenharmony_ci            ev.property = xsr->property;
677c804472Sopenharmony_ci            if (ev.target == targets_atom) {
687c804472Sopenharmony_ci                ret = XChangeProperty(ev.display, ev.requestor, ev.property,
697c804472Sopenharmony_ci                                      XA_ATOM, nFormateProp32, PropModeReplace,
707c804472Sopenharmony_ci                                      (unsigned char*)&UTF8, 1);
717c804472Sopenharmony_ci            } else if (ev.target == XA_STRING || ev.target == text_atom) {
727c804472Sopenharmony_ci                ret = XChangeProperty(ev.display, ev.requestor, ev.property, XA_STRING,
737c804472Sopenharmony_ci                                      nFormateProp8, PropModeReplace, (unsigned char*)text.c_str(), size);
747c804472Sopenharmony_ci            } else if (ev.target == UTF8) {
757c804472Sopenharmony_ci                ret = XChangeProperty(ev.display, ev.requestor, ev.property, UTF8,
767c804472Sopenharmony_ci                                      nFormateProp8, PropModeReplace, (unsigned char*)text.c_str(), size);
777c804472Sopenharmony_ci            } else {
787c804472Sopenharmony_ci                ev.property = None;
797c804472Sopenharmony_ci            }
807c804472Sopenharmony_ci            if ((ret & nEvenNumber) == 0) {
817c804472Sopenharmony_ci                XSendEvent (display, ev.requestor, 0, 0, (XEvent *)&ev);
827c804472Sopenharmony_ci            }
837c804472Sopenharmony_ci        }
847c804472Sopenharmony_ci    }
857c804472Sopenharmony_ci}
867c804472Sopenharmony_ci
877c804472Sopenharmony_cistd::string ClipboardX11::GetPasteType(const Atom& atom)
887c804472Sopenharmony_ci{
897c804472Sopenharmony_ci    XEvent event;
907c804472Sopenharmony_ci    int format;
917c804472Sopenharmony_ci    unsigned long num, size;
927c804472Sopenharmony_ci    char* data = nullptr;
937c804472Sopenharmony_ci    std::string retStr;
947c804472Sopenharmony_ci    Atom target, CLIPBOARD = XInternAtom(display, "CLIPBOARD", 0), XSEL_DATA = XInternAtom(display, "XSEL_DATA", 0);
957c804472Sopenharmony_ci    XConvertSelection(display, CLIPBOARD, atom, XSEL_DATA, window, CurrentTime);
967c804472Sopenharmony_ci    XSync(display, 0);
977c804472Sopenharmony_ci    XNextEvent(display, &event);
987c804472Sopenharmony_ci    if (event.type == SelectionNotify) {
997c804472Sopenharmony_ci        if (event.xselection.selection != CLIPBOARD) {
1007c804472Sopenharmony_ci            return retStr;
1017c804472Sopenharmony_ci        }
1027c804472Sopenharmony_ci        if (event.xselection.property) {
1037c804472Sopenharmony_ci            XGetWindowProperty(event.xselection.display, event.xselection.requestor, event.xselection.property, 0L,
1047c804472Sopenharmony_ci                               (~0L), 0, AnyPropertyType, &target, &format, &size, &num, (unsigned char**)&data);
1057c804472Sopenharmony_ci            if (target == UTF8 || target == XA_STRING) {
1067c804472Sopenharmony_ci                std::string str(data);
1077c804472Sopenharmony_ci                retStr = str;
1087c804472Sopenharmony_ci            }
1097c804472Sopenharmony_ci            XFree(data);
1107c804472Sopenharmony_ci            XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
1117c804472Sopenharmony_ci        }
1127c804472Sopenharmony_ci    }
1137c804472Sopenharmony_ci    return retStr;
1147c804472Sopenharmony_ci}