alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (XClipboard.java)

This example Java source code file (XClipboard.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awt, checkchangetimertask, clipboard, datatransfer, drag, drop, getintegeraction, object, runnable, selectionnotifyhandler, sortedmap, string, sunclipboard, transferable, util, xatom, xclipboard, xeventdispatcher, xselection, xselectionevent

The XClipboard.java Java example source code

/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt.X11;

import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.DataFlavor;
import java.util.SortedMap;
import java.io.IOException;
import java.security.AccessController;
import java.util.HashMap;
import java.util.Map;
import sun.awt.UNIXToolkit;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.SunClipboard;
import sun.awt.datatransfer.ClipboardTransferable;
import sun.security.action.GetIntegerAction;

/**
 * A class which interfaces with the X11 selection service in order to support
 * data transfer via Clipboard operations.
 */
public final class XClipboard extends SunClipboard implements OwnershipListener
{
    private final XSelection selection;
    // Time of calling XConvertSelection().
    private long convertSelectionTime;
    // The flag used not to call XConvertSelection() if the previous SelectionNotify
    // has not been processed by checkChange().
    private volatile boolean isSelectionNotifyProcessed;
    // The property in which the owner should place requested targets
    // when tracking changes of available data flavors (practically targets).
    private volatile XAtom targetsPropertyAtom;

    private static final Object classLock = new Object();

    private static final int defaultPollInterval = 200;

    private static int pollInterval;

    private static Map<Long, XClipboard> targetsAtom2Clipboard;

    /**
     * Creates a system clipboard object.
     */
    public XClipboard(String name, String selectionName) {
        super(name);
        selection = new XSelection(XAtom.get(selectionName));
        selection.registerOwershipListener(this);
    }

    /*
     * NOTE: This method may be called by privileged threads.
     *       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
     */
    public void ownershipChanged(final boolean isOwner) {
        if (isOwner) {
            checkChangeHere(contents);
        } else {
            lostOwnershipImpl();
        }
    }

    protected synchronized void setContentsNative(Transferable contents) {
        SortedMap<Long,DataFlavor> formatMap =
            DataTransferer.getInstance().getFormatsForTransferable
                (contents, DataTransferer.adaptFlavorMap(flavorMap));
        long[] formats = DataTransferer.keysToLongArray(formatMap);

        if (!selection.setOwner(contents, formatMap, formats,
                                XToolkit.getCurrentServerTime())) {
            this.owner = null;
            this.contents = null;
        }
    }

    public long getID() {
        return selection.getSelectionAtom().getAtom();
    }

    @Override
    public synchronized Transferable getContents(Object requestor) {
        if (contents != null) {
            return contents;
        }
        return new ClipboardTransferable(this);
    }

    /* Caller is synchronized on this. */
    protected void clearNativeContext() {
        selection.reset();
    }


    protected long[] getClipboardFormats() {
        return selection.getTargets(XToolkit.getCurrentServerTime());
    }

    protected byte[] getClipboardData(long format) throws IOException {
        return selection.getData(format, XToolkit.getCurrentServerTime());
    }

    private void checkChangeHere(Transferable contents) {
        if (areFlavorListenersRegistered()) {
            checkChange(DataTransferer.getInstance().
                        getFormatsForTransferableAsArray(contents, flavorMap));
        }
    }

    private static int getPollInterval() {
        synchronized (XClipboard.classLock) {
            if (pollInterval <= 0) {
                pollInterval = AccessController.doPrivileged(
                        new GetIntegerAction("awt.datatransfer.clipboard.poll.interval",
                                             defaultPollInterval));
                if (pollInterval <= 0) {
                    pollInterval = defaultPollInterval;
                }
            }
            return pollInterval;
        }
    }

    private XAtom getTargetsPropertyAtom() {
        if (null == targetsPropertyAtom) {
            targetsPropertyAtom =
                    XAtom.get("XAWT_TARGETS_OF_SELECTION:" + selection.getSelectionAtom().getName());
        }
        return targetsPropertyAtom;
    }

    protected void registerClipboardViewerChecked() {
        // for XConvertSelection() to be called for the first time in getTargetsDelayed()
        isSelectionNotifyProcessed = true;

        boolean mustSchedule = false;
        synchronized (XClipboard.classLock) {
            if (targetsAtom2Clipboard == null) {
                targetsAtom2Clipboard = new HashMap<Long, XClipboard>(2);
            }
            mustSchedule = targetsAtom2Clipboard.isEmpty();
            targetsAtom2Clipboard.put(getTargetsPropertyAtom().getAtom(), this);
            if (mustSchedule) {
                XToolkit.addEventDispatcher(XWindow.getXAWTRootWindow().getWindow(),
                                            new SelectionNotifyHandler());
            }
        }
        if (mustSchedule) {
            XToolkit.schedule(new CheckChangeTimerTask(), XClipboard.getPollInterval());
        }
    }

    private static class CheckChangeTimerTask implements Runnable {
        public void run() {
            for (XClipboard clpbrd : targetsAtom2Clipboard.values()) {
                clpbrd.getTargetsDelayed();
            }
            synchronized (XClipboard.classLock) {
                if (targetsAtom2Clipboard != null && !targetsAtom2Clipboard.isEmpty()) {
                    // The viewer is still registered, schedule next poll.
                    XToolkit.schedule(this, XClipboard.getPollInterval());
                }
            }
        }
    }

    private static class SelectionNotifyHandler implements XEventDispatcher {
        public void dispatchEvent(XEvent ev) {
            if (ev.get_type() == XConstants.SelectionNotify) {
                final XSelectionEvent xse = ev.get_xselection();
                XClipboard clipboard = null;
                synchronized (XClipboard.classLock) {
                    if (targetsAtom2Clipboard != null && targetsAtom2Clipboard.isEmpty()) {
                        // The viewer was unregistered, remove the dispatcher.
                        XToolkit.removeEventDispatcher(XWindow.getXAWTRootWindow().getWindow(), this);
                        return;
                    }
                    final long propertyAtom = xse.get_property();
                    clipboard = targetsAtom2Clipboard.get(propertyAtom);
                }
                if (null != clipboard) {
                    clipboard.checkChange(xse);
                }
            }
        }
    }

    protected void unregisterClipboardViewerChecked() {
        isSelectionNotifyProcessed = false;
        synchronized (XClipboard.classLock) {
            targetsAtom2Clipboard.remove(getTargetsPropertyAtom().getAtom());
        }
    }

    // checkChange() will be called on SelectionNotify
    private void getTargetsDelayed() {
        XToolkit.awtLock();
        try {
            long curTime = System.currentTimeMillis();
            if (isSelectionNotifyProcessed || curTime >= (convertSelectionTime + UNIXToolkit.getDatatransferTimeout()))
            {
                convertSelectionTime = curTime;
                XlibWrapper.XConvertSelection(XToolkit.getDisplay(),
                                              selection.getSelectionAtom().getAtom(),
                                              XDataTransferer.TARGETS_ATOM.getAtom(),
                                              getTargetsPropertyAtom().getAtom(),
                                              XWindow.getXAWTRootWindow().getWindow(),
                                              XConstants.CurrentTime);
                isSelectionNotifyProcessed = false;
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    /*
     * Tracks changes of available formats.
     * NOTE: This method may be called by privileged threads.
     *       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
     */
    private void checkChange(XSelectionEvent xse) {
        final long propertyAtom = xse.get_property();
        if (propertyAtom != getTargetsPropertyAtom().getAtom()) {
            // wrong atom
            return;
        }

        final XAtom selectionAtom = XAtom.get(xse.get_selection());
        final XSelection changedSelection = XSelection.getSelection(selectionAtom);

        if (null == changedSelection || changedSelection != selection) {
            // unknown selection - do nothing
            return;
        }

        isSelectionNotifyProcessed = true;

        if (selection.isOwner()) {
            // selection is owner - do not need formats
            return;
        }

        long[] formats = null;

        if (propertyAtom == XConstants.None) {
            // We treat None property atom as "empty selection".
            formats = new long[0];
        } else {
            WindowPropertyGetter targetsGetter =
                new WindowPropertyGetter(XWindow.getXAWTRootWindow().getWindow(),
                                         XAtom.get(propertyAtom), 0,
                                         XSelection.MAX_LENGTH, true,
                                         XConstants.AnyPropertyType);
            try {
                targetsGetter.execute();
                formats = XSelection.getFormats(targetsGetter);
            } finally {
                targetsGetter.dispose();
            }
        }

        checkChange(formats);
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java XClipboard.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.