Improve Clipboard support, add Clipboard.onUpdate (resolve #925)

This commit is contained in:
Joshua Granick
2017-06-06 19:32:33 -07:00
parent e17e4f45f8
commit f4e003d799
10 changed files with 241 additions and 57 deletions

View File

@@ -276,6 +276,14 @@ class HTML5Window {
}
private function handleCutOrCopyEvent (event:ClipboardEvent):Void {
event.clipboardData.setData ("text/plain", Clipboard.text);
event.preventDefault ();
}
private function handleFocusEvent (event:FocusEvent):Void {
if (enableTextEvents) {
@@ -313,27 +321,6 @@ class HTML5Window {
}
private function handleCutOrCopyEvent (event:ClipboardEvent):Void {
event.clipboardData.setData('text/plain', Clipboard.text);
event.preventDefault(); // We want our data, not data from any selection, to be written to the clipboard
}
private function handlePasteEvent (event:ClipboardEvent):Void {
if(untyped event.clipboardData.types.indexOf('text/plain') > -1){
var text = Clipboard.text = event.clipboardData.getData('text/plain');
parent.onTextInput.dispatch (text);
// We are already handling the data from the clipboard, we do not want it inserted into the hidden input
event.preventDefault();
}
}
private function handleInputEvent (event:InputEvent):Void {
// In order to ensure that the browser will fire clipboard events, we always need to have something selected.
@@ -470,7 +457,7 @@ class HTML5Window {
} else {
parent.onMouseWheel.dispatch (untyped event.deltaX, - untyped event.deltaY);
parent.onMouseWheel.dispatch (untyped event.deltaX, -untyped event.deltaY);
if (parent.onMouseWheel.canceled) {
@@ -483,6 +470,26 @@ class HTML5Window {
}
private function handlePasteEvent (event:ClipboardEvent):Void {
if (untyped event.clipboardData.types.indexOf ("text/plain") > -1) {
var text = event.clipboardData.getData ("text/plain");
Clipboard.text = text;
if (enableTextEvents) {
parent.onTextInput.dispatch (text);
}
event.preventDefault ();
}
}
private function handleResizeEvent (event:js.html.Event):Void {
primaryTouch = null;
@@ -675,26 +682,26 @@ class HTML5Window {
public function setClipboard (value:String):Void {
if (Browser.document.queryCommandEnabled ("copy")) {
var inputEnabled = enableTextEvents;
setEnableTextEvents (true); // create textInput if necessary
setEnableTextEvents (false);
var cacheText = textInput.value;
textInput.value = value;
textInput.select ();
if (Browser.document.queryCommandEnabled ("copy")) {
Browser.document.execCommand ("copy");
}
textInput.value = cacheText;
setEnableTextEvents (inputEnabled);
}
}
public function setEnableTextEvents (value:Bool):Bool {

View File

@@ -12,6 +12,7 @@ import lime.graphics.GLRenderContext;
import lime.graphics.RenderContext;
import lime.graphics.Renderer;
import lime.math.Rectangle;
import lime.system.Clipboard;
import lime.system.Display;
import lime.system.DisplayMode;
import lime.system.Sensor;
@@ -38,6 +39,7 @@ import lime.ui.Window;
@:access(lime.graphics.opengl.GL)
@:access(lime.graphics.GLRenderContext)
@:access(lime.graphics.Renderer)
@:access(lime.system.Clipboard)
@:access(lime.system.Sensor)
@:access(lime.ui.Gamepad)
@:access(lime.ui.Joystick)
@@ -48,6 +50,7 @@ class NativeApplication {
private var applicationEventInfo = new ApplicationEventInfo (UPDATE);
private var clipboardEventInfo = new ClipboardEventInfo ();
private var currentTouches = new Map<Int, Touch> ();
private var dropEventInfo = new DropEventInfo ();
private var gamepadEventInfo = new GamepadEventInfo ();
@@ -111,6 +114,7 @@ class NativeApplication {
#if !macro
NativeCFFI.lime_application_event_manager_register (handleApplicationEvent, applicationEventInfo);
NativeCFFI.lime_clipboard_event_manager_register (handleClipboardEvent, clipboardEventInfo);
NativeCFFI.lime_drop_event_manager_register (handleDropEvent, dropEventInfo);
NativeCFFI.lime_gamepad_event_manager_register (handleGamepadEvent, gamepadEventInfo);
NativeCFFI.lime_joystick_event_manager_register (handleJoystickEvent, joystickEventInfo);
@@ -203,6 +207,13 @@ class NativeApplication {
}
private function handleClipboardEvent ():Void {
Clipboard.__update ();
}
private function handleDropEvent ():Void {
for (window in parent.windows) {
@@ -746,6 +757,36 @@ private class ApplicationEventInfo {
}
private class ClipboardEventInfo {
public var type:ClipboardEventType;
public function new (type:ClipboardEventType = null) {
this.type = type;
}
public function clone ():ClipboardEventInfo {
return new ClipboardEventInfo (type);
}
}
@:enum private abstract ClipboardEventType(Int) {
var UPDATE = 0;
}
private class DropEventInfo {

View File

@@ -43,6 +43,7 @@ class NativeCFFI {
@:cffi private static function lime_bytes_get_data_pointer_offset (data:Dynamic, offset:Int):Float;
@:cffi private static function lime_bytes_read_file (path:String, bytes:Dynamic):Dynamic;
@:cffi private static function lime_cffi_get_native_pointer (ptr:Dynamic):Float;
@:cffi private static function lime_clipboard_event_manager_register (callback:Dynamic, eventObject:Dynamic):Void;
@:cffi private static function lime_clipboard_get_text ():Dynamic;
@:cffi private static function lime_clipboard_set_text (text:String):Void;
@:cffi private static function lime_data_pointer_offset (dataPointer:DataPointer, offset:Int):Float;

View File

@@ -3,6 +3,7 @@ package lime.system;
import lime._backend.native.NativeCFFI;
import lime.app.Application;
import lime.app.Event;
#if flash
import flash.desktop.Clipboard in FlashClipboard;
@@ -22,12 +23,36 @@ import lime._backend.html5.HTML5Window;
class Clipboard {
public static var onUpdate = new Event<Void->Void> ();
public static var text (get, set):String;
#if js
private static var _text : String;
private static var _text:String;
private static function __update ():Void {
var cacheText = _text;
#if (lime_cffi && !macro)
_text = NativeCFFI.lime_clipboard_get_text ();
#elseif flash
if (FlashClipboard.generalClipboard.hasFormat (TEXT_FORMAT)) {
_text = FlashClipboard.generalClipboard.getData (TEXT_FORMAT);
}
_text = null;
#end
if (_text != cacheText) {
onUpdate.dispatch ();
}
}
@@ -38,45 +63,41 @@ class Clipboard {
private static function get_text ():String {
#if (lime_cffi && !macro)
return NativeCFFI.lime_clipboard_get_text ();
#elseif flash
if (FlashClipboard.generalClipboard.hasFormat (TEXT_FORMAT)) {
return FlashClipboard.generalClipboard.getData (TEXT_FORMAT);
}
return null;
#elseif js
return _text;
#else
return null;
#if flash
__update ();
#end
return _text;
}
private static function set_text (value:String):String {
var cacheText = _text;
_text = value;
#if (lime_cffi && !macro)
NativeCFFI.lime_clipboard_set_text (value);
return value;
#elseif flash
FlashClipboard.generalClipboard.setData (TEXT_FORMAT, value);
return value;
#elseif (js && html5)
_text = value;
var window = Application.current.window;
if (window != null) {
window.backend.setClipboard (value);
}
return value;
#else
return null;
#end
if (_text != cacheText) {
onUpdate.dispatch ();
}
return value;
}

View File

@@ -255,6 +255,7 @@
<file name="src/media/containers/WAV.cpp" />
<file name="src/media/AudioBuffer.cpp" />
<file name="src/system/CFFIPointer.cpp" />
<file name="src/system/ClipboardEvent.cpp" />
<file name="src/system/DisplayMode.cpp" />
<file name="src/system/JNI.cpp" if="android" />
<file name="src/system/Locale.cpp" unless="mac || ios" />

View File

@@ -0,0 +1,37 @@
#ifndef LIME_SYSTEM_CLIPBOARD_EVENT_H
#define LIME_SYSTEM_CLIPBOARD_EVENT_H
#include <hx/CFFI.h>
namespace lime {
enum ClipboardEventType {
CLIPBOARD_UPDATE
};
class ClipboardEvent {
public:
static AutoGCRoot* callback;
static AutoGCRoot* eventObject;
ClipboardEvent ();
static void Dispatch (ClipboardEvent* event);
ClipboardEventType type;
};
}
#endif

View File

@@ -22,6 +22,7 @@
#include <media/AudioBuffer.h>
#include <system/CFFIPointer.h>
#include <system/Clipboard.h>
#include <system/ClipboardEvent.h>
#include <system/JNI.h>
#include <system/Locale.h>
#include <system/SensorEvent.h>
@@ -272,6 +273,14 @@ namespace lime {
}
void lime_clipboard_event_manager_register (value callback, value eventObject) {
ClipboardEvent::callback = new AutoGCRoot (callback);
ClipboardEvent::eventObject = new AutoGCRoot (eventObject);
}
value lime_clipboard_get_text () {
if (Clipboard::HasText ()) {
@@ -1794,6 +1803,7 @@ namespace lime {
DEFINE_PRIME2 (lime_bytes_read_file);
DEFINE_PRIME1 (lime_cffi_get_native_pointer);
DEFINE_PRIME1 (lime_cffi_set_finalizer);
DEFINE_PRIME2v (lime_clipboard_event_manager_register);
DEFINE_PRIME0 (lime_clipboard_get_text);
DEFINE_PRIME1v (lime_clipboard_set_text);
DEFINE_PRIME2 (lime_data_pointer_offset);

View File

@@ -48,6 +48,7 @@ namespace lime {
nextUpdate = 0;
ApplicationEvent applicationEvent;
ClipboardEvent clipboardEvent;
DropEvent dropEvent;
GamepadEvent gamepadEvent;
JoystickEvent joystickEvent;
@@ -156,6 +157,11 @@ namespace lime {
inBackground = false;
break;
case SDL_CLIPBOARDUPDATE:
ProcessClipboardEvent (event);
break;
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
@@ -316,6 +322,19 @@ namespace lime {
}
void SDLApplication::ProcessClipboardEvent (SDL_Event* event) {
if (ClipboardEvent::callback) {
clipboardEvent.type = CLIPBOARD_UPDATE;
ClipboardEvent::Dispatch (&clipboardEvent);
}
}
void SDLApplication::ProcessDropEvent (SDL_Event* event) {
if (DropEvent::callback) {

View File

@@ -6,6 +6,7 @@
#include <app/Application.h>
#include <app/ApplicationEvent.h>
#include <graphics/RenderEvent.h>
#include <system/ClipboardEvent.h>
#include <system/SensorEvent.h>
#include <ui/DropEvent.h>
#include <ui/GamepadEvent.h>
@@ -39,6 +40,7 @@ namespace lime {
private:
void HandleEvent (SDL_Event* event);
void ProcessClipboardEvent (SDL_Event* event);
void ProcessDropEvent (SDL_Event* event);
void ProcessGamepadEvent (SDL_Event* event);
void ProcessJoystickEvent (SDL_Event* event);
@@ -57,6 +59,7 @@ namespace lime {
bool active;
ApplicationEvent applicationEvent;
ClipboardEvent clipboardEvent;
Uint32 currentUpdate;
double framePeriod;
DropEvent dropEvent;

View File

@@ -0,0 +1,44 @@
#include <hx/CFFI.h>
#include <system/ClipboardEvent.h>
namespace lime {
AutoGCRoot* ClipboardEvent::callback = 0;
AutoGCRoot* ClipboardEvent::eventObject = 0;
static int id_type;
static bool init = false;
ClipboardEvent::ClipboardEvent () {
type = CLIPBOARD_UPDATE;
}
void ClipboardEvent::Dispatch (ClipboardEvent* event) {
if (ClipboardEvent::callback) {
if (!init) {
id_type = val_id ("type");
init = true;
}
value object = (ClipboardEvent::eventObject ? ClipboardEvent::eventObject->get () : alloc_empty_object ());
alloc_field (object, id_type, alloc_int (event->type));
val_call0 (ClipboardEvent::callback->get ());
}
}
}