diff --git a/lime/_backend/html5/HTML5Window.hx b/lime/_backend/html5/HTML5Window.hx index 38c91d55f..ac16aea09 100644 --- a/lime/_backend/html5/HTML5Window.hx +++ b/lime/_backend/html5/HTML5Window.hx @@ -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,24 +682,24 @@ class HTML5Window { public function setClipboard (value:String):Void { + var inputEnabled = enableTextEvents; + + setEnableTextEvents (true); // create textInput if necessary + + var cacheText = textInput.value; + textInput.value = value; + textInput.select (); + if (Browser.document.queryCommandEnabled ("copy")) { - var inputEnabled = enableTextEvents; - - setEnableTextEvents (true); // create textInput if necessary - setEnableTextEvents (false); - - var cacheText = textInput.value; - textInput.value = value; - Browser.document.execCommand ("copy"); - textInput.value = cacheText; - - setEnableTextEvents (inputEnabled); - } + textInput.value = cacheText; + + setEnableTextEvents (inputEnabled); + } diff --git a/lime/_backend/native/NativeApplication.hx b/lime/_backend/native/NativeApplication.hx index 92a5040c0..0311eb05f 100644 --- a/lime/_backend/native/NativeApplication.hx +++ b/lime/_backend/native/NativeApplication.hx @@ -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 (); 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 { diff --git a/lime/_backend/native/NativeCFFI.hx b/lime/_backend/native/NativeCFFI.hx index b4bf6c58b..a5ac1c323 100644 --- a/lime/_backend/native/NativeCFFI.hx +++ b/lime/_backend/native/NativeCFFI.hx @@ -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; diff --git a/lime/system/Clipboard.hx b/lime/system/Clipboard.hx index be35a1668..1f2d869b6 100644 --- a/lime/system/Clipboard.hx +++ b/lime/system/Clipboard.hx @@ -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,11 +23,35 @@ import lime._backend.html5.HTML5Window; class Clipboard { + public static var onUpdate = new EventVoid> (); public static var text (get, set):String; - - #if js - private static var _text : String; - #end + + 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; + } diff --git a/project/Build.xml b/project/Build.xml index 35a8dc31a..d8f15b729 100644 --- a/project/Build.xml +++ b/project/Build.xml @@ -255,6 +255,7 @@ + diff --git a/project/include/system/ClipboardEvent.h b/project/include/system/ClipboardEvent.h new file mode 100644 index 000000000..3c4c4fb0d --- /dev/null +++ b/project/include/system/ClipboardEvent.h @@ -0,0 +1,37 @@ +#ifndef LIME_SYSTEM_CLIPBOARD_EVENT_H +#define LIME_SYSTEM_CLIPBOARD_EVENT_H + + +#include + + +namespace lime { + + + enum ClipboardEventType { + + CLIPBOARD_UPDATE + + }; + + + class ClipboardEvent { + + public: + + static AutoGCRoot* callback; + static AutoGCRoot* eventObject; + + ClipboardEvent (); + + static void Dispatch (ClipboardEvent* event); + + ClipboardEventType type; + + }; + + +} + + +#endif \ No newline at end of file diff --git a/project/src/ExternalInterface.cpp b/project/src/ExternalInterface.cpp index 6db4413b3..255a5c232 100644 --- a/project/src/ExternalInterface.cpp +++ b/project/src/ExternalInterface.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -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); diff --git a/project/src/backend/sdl/SDLApplication.cpp b/project/src/backend/sdl/SDLApplication.cpp index 6507ac792..6125bb525 100644 --- a/project/src/backend/sdl/SDLApplication.cpp +++ b/project/src/backend/sdl/SDLApplication.cpp @@ -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) { diff --git a/project/src/backend/sdl/SDLApplication.h b/project/src/backend/sdl/SDLApplication.h index a701bf20b..460d849cd 100644 --- a/project/src/backend/sdl/SDLApplication.h +++ b/project/src/backend/sdl/SDLApplication.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/project/src/system/ClipboardEvent.cpp b/project/src/system/ClipboardEvent.cpp new file mode 100644 index 000000000..5003ffd8d --- /dev/null +++ b/project/src/system/ClipboardEvent.cpp @@ -0,0 +1,44 @@ +#include +#include + + +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 ()); + + } + + } + + +} \ No newline at end of file