mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-31 06:05:44 +00:00
138 lines
5.2 KiB
Java
138 lines
5.2 KiB
Java
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.gecko.util;
|
|
|
|
import java.util.concurrent.SynchronousQueue;
|
|
|
|
import org.mozilla.gecko.AppConstants.Versions;
|
|
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
|
|
|
|
import android.content.ClipData;
|
|
import android.content.Context;
|
|
import android.util.Log;
|
|
|
|
public final class Clipboard {
|
|
// Volatile but not synchronized: we don't care about the race condition in
|
|
// init, because both app contexts will be the same, but we do care about a
|
|
// thread having a stale null value of mContext.
|
|
volatile static Context mContext;
|
|
private final static String LOGTAG = "GeckoClipboard";
|
|
private final static SynchronousQueue<String> sClipboardQueue = new SynchronousQueue<String>();
|
|
|
|
private Clipboard() {
|
|
}
|
|
|
|
public static void init(final Context c) {
|
|
if (mContext != null) {
|
|
Log.w(LOGTAG, "Clipboard.init() called twice!");
|
|
return;
|
|
}
|
|
mContext = c.getApplicationContext();
|
|
}
|
|
|
|
@WrapElementForJNI(stubName = "GetClipboardTextWrapper")
|
|
public static String getText() {
|
|
// If we're on the UI thread or the background thread, we have a looper on the thread
|
|
// and can just call this directly. For any other threads, post the call to the
|
|
// background thread.
|
|
|
|
if (ThreadUtils.isOnUiThread() || ThreadUtils.isOnBackgroundThread()) {
|
|
return getClipboardTextImpl();
|
|
}
|
|
|
|
ThreadUtils.postToBackgroundThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
String text = getClipboardTextImpl();
|
|
try {
|
|
sClipboardQueue.put(text != null ? text : "");
|
|
} catch (InterruptedException ie) {}
|
|
}
|
|
});
|
|
|
|
try {
|
|
return sClipboardQueue.take();
|
|
} catch (InterruptedException ie) {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
@WrapElementForJNI(stubName = "SetClipboardText")
|
|
public static void setText(final CharSequence text) {
|
|
ThreadUtils.postToBackgroundThread(new Runnable() {
|
|
@Override
|
|
@SuppressWarnings("deprecation")
|
|
public void run() {
|
|
// In API Level 11 and above, CLIPBOARD_SERVICE returns android.content.ClipboardManager,
|
|
// which is a subclass of android.text.ClipboardManager.
|
|
if (Versions.feature11Plus) {
|
|
final android.content.ClipboardManager cm = (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
final ClipData clip = ClipData.newPlainText("Text", text);
|
|
try {
|
|
cm.setPrimaryClip(clip);
|
|
} catch (NullPointerException e) {
|
|
// Bug 776223: This is a Samsung clipboard bug. setPrimaryClip() can throw
|
|
// a NullPointerException if Samsung's /data/clipboard directory is full.
|
|
// Fortunately, the text is still successfully copied to the clipboard.
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Deprecated.
|
|
android.text.ClipboardManager cm = (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
cm.setText(text);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @return true if the clipboard is nonempty, false otherwise.
|
|
*/
|
|
@WrapElementForJNI
|
|
public static boolean hasText() {
|
|
if (Versions.feature11Plus) {
|
|
android.content.ClipboardManager cm = (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
return cm.hasPrimaryClip();
|
|
}
|
|
|
|
// Deprecated.
|
|
android.text.ClipboardManager cm = (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
return cm.hasText();
|
|
}
|
|
|
|
/**
|
|
* Deletes all text from the clipboard.
|
|
*/
|
|
@WrapElementForJNI
|
|
public static void clearText() {
|
|
setText(null);
|
|
}
|
|
|
|
/**
|
|
* On some devices, access to the clipboard service needs to happen
|
|
* on a thread with a looper, so this function requires a looper is
|
|
* present on the thread.
|
|
*/
|
|
@SuppressWarnings("deprecation")
|
|
static String getClipboardTextImpl() {
|
|
if (Versions.feature11Plus) {
|
|
android.content.ClipboardManager cm = (android.content.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
if (cm.hasPrimaryClip()) {
|
|
ClipData clip = cm.getPrimaryClip();
|
|
if (clip != null) {
|
|
ClipData.Item item = clip.getItemAt(0);
|
|
return item.coerceToText(mContext).toString();
|
|
}
|
|
}
|
|
} else {
|
|
android.text.ClipboardManager cm = (android.text.ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
|
|
if (cm.hasText()) {
|
|
return cm.getText().toString();
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|