From 376b3a496e07c055ffd4aa51e1639be63f99ec52 Mon Sep 17 00:00:00 2001 From: Alexander Ljungberg Date: Mon, 19 Aug 2013 20:44:38 +0100 Subject: [PATCH] Fixed: copy and paste by Cappuccino Edit menu not working. When the Edit menu is used to cut or to paste, Cappuccino needs to do all the work of making it happen. But the current code relied on the browser doing part of the work. This fix adds new state so CPTextField can know if it should expect the browser to do some of the work or not. Refs #1964. --- AppKit/CPEvent.j | 23 ++++++++++++++++++++++ AppKit/CPTextField.j | 4 ++-- AppKit/Platform/DOM/CPPlatformPasteboard.j | 12 +++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/AppKit/CPEvent.j b/AppKit/CPEvent.j index 478a08897..190065d4d 100644 --- a/AppKit/CPEvent.j +++ b/AppKit/CPEvent.j @@ -68,6 +68,11 @@ var _CPEventPeriodicEventPeriod = 0, float _deltaX; float _deltaY; float _deltaZ; + +#if PLATFORM(DOM) + BOOL _suppressCappuccinoCut; + BOOL _suppressCappuccinoPaste; +#endif } /*! @@ -473,6 +478,24 @@ var _CPEventPeriodicEventPeriod = 0, return !firstResponderIsText; } +/*! + Return YES if this event is a part of processing a browser controlled cut or paste event + where the browser will go ahead and do the work of cutting or pasting within the input + element after processing of this event. The implication is that it should not be done by + the CPTextField (or whatever else is controlling the input) since this would result in + nothing being cut (because the field already cut the text out), or a double paste + (because the field pasted as well as the browser). +*/ +- (BOOL)_platformIsEffectingCutOrPaste +{ +#if PLATFORM(DOM) + return _suppressCappuccinoCut || _suppressCappuccinoPaste; +#else + return NO; +#endif +} + + /*! Generates periodic events every \c aPeriod seconds. diff --git a/AppKit/CPTextField.j b/AppKit/CPTextField.j index 31b9af003..90638db9b 100644 --- a/AppKit/CPTextField.j +++ b/AppKit/CPTextField.j @@ -1356,7 +1356,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); if (![self isEditable]) return; - if (![CPPlatform isBrowser]) + if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste]) { [self deleteBackward:sender]; } @@ -1376,7 +1376,7 @@ CPTextFieldStatePlaceholder = CPThemeState("placeholder"); if (!([self isEnabled] && [self isEditable])) return; - if (![CPPlatform isBrowser]) + if (![[CPApp currentEvent] _platformIsEffectingCutOrPaste]) { var pasteboard = [CPPasteboard generalPasteboard]; diff --git a/AppKit/Platform/DOM/CPPlatformPasteboard.j b/AppKit/Platform/DOM/CPPlatformPasteboard.j index 69a1e667f..e6232d66f 100644 --- a/AppKit/Platform/DOM/CPPlatformPasteboard.j +++ b/AppKit/Platform/DOM/CPPlatformPasteboard.j @@ -37,6 +37,9 @@ #if PLATFORM(DOM) +#define SUPPRESS_CAPPUCCINO_CUT_FOR_EVENT(anEvent) anEvent._suppressCappuccinoCut = YES +#define SUPPRESS_CAPPUCCINO_PASTE_FOR_EVENT(anEvent) anEvent._suppressCappuccinoPaste = YES + var hasEditableTarget = function(aDOMEvent) { var target = aDOMEvent.target || aDOMEvent.srcElement; @@ -261,6 +264,11 @@ var hasEditableTarget = function(aDOMEvent) currentEventShouldDefinitelyBubble = YES; } + + if (!currentEventShouldBeSuppressed && characters === "v") + SUPPRESS_CAPPUCCINO_PASTE_FOR_EVENT(anEvent); + else if (!currentEventShouldBeSuppressed && characters == "x") + SUPPRESS_CAPPUCCINO_CUT_FOR_EVENT(anEvent); } - (BOOL)windowShouldSuppressKeyEvent @@ -456,6 +464,8 @@ Return true if the event may be a copy and paste event, but the target is not an var anEvent = [self _fakeClipboardEvent:aDOMEvent type:"v"], platformWindow = [[anEvent window] platformWindow]; + SUPPRESS_CAPPUCCINO_PASTE_FOR_EVENT(anEvent); + // By default we'll stop the native handling of the event since we're handling it ourselves. However, we need to // stop it before we send the event so that the event can overrule our choice. CPTextField for instance wants the // default handling when focused (which is to insert into the field). @@ -480,6 +490,8 @@ Return true if the event may be a copy and paste event, but the target is not an var anEvent = [self _fakeClipboardEvent:aDOMEvent type:(aDOMEvent.type.indexOf("cut") != CPNotFound ? "x" : "c")], platformWindow = [[anEvent window] platformWindow]; + SUPPRESS_CAPPUCCINO_CUT_FOR_EVENT(anEvent); + [platformWindow _propagateCurrentDOMEvent:NO] // Let the app react through copy: and cut: actions.