MacGapProject / MacGap1

Desktop WebKit wrapper for HTML/CSS/JS applications.
Other
3.55k stars 209 forks source link

Clipboard access #31

Open MaKleSoft opened 12 years ago

MaKleSoft commented 12 years ago

Support for reading from and writing to the clipboard would be awesome.

liamks commented 12 years ago

Once my file api pull-request is accepted I'll tackle this (it should be easy). I was thinking of the following api:

macgap.clipboard.read()
macgap.clipboard.write('asdf')

//OR

macgap.app.readClipboard()
macgap.app.writeToClipboard('asdf')
MaKleSoft commented 12 years ago

That would be great. Thanks!

MaKleSoft commented 12 years ago

Any news on this? If not, can maybe anyone maybe give me some quick instructions on how to implement something like this myself?

liamks commented 12 years ago

I'm working on this right now, I'll provide an update when I'm done.

maccman commented 12 years ago

liamks are you sure there isn't already a 'paste' event?

liamks commented 12 years ago

It looks like there might be: http://www.quirksmode.org/dom/events/cutcopypaste.html

It looks like it would only access the clipboard within a single window - would that be sufficient to avoid having to add this feature?

MaKleSoft commented 12 years ago

Actually what I am looking for is not a way to capture when a user copies or pastes data (e.g. via cmd + v) but to programmatically write or read data from/to the clipboard. Not sure if that is clear here. @liamks If you do implement it, could you please also update the macgap generator project? I'm having trouble with compiling xcode projects right now. (Which is part of the reason why I havent tackled this myself yet) Thanks!

maccman commented 12 years ago

I'm not sure it's a good idea to separate clipboard access from ctrl c - what's the use case?

MaKleSoft commented 12 years ago

There's a lot of use cases, actually. The most straightforward would be a clipboard manager. In my case I'm trying to give the user a convenient way of copying data from a password manager to the clipboard. Simply tap on a field to copy it to the clipboard. There is an API for that in Chrome and Titanium Desktop and I'm sure in most other web app packagers, too, so I don't see why there shouldn't be one in MacGap.

maccman commented 12 years ago

Ok, interesting. Perhaps we should copy Titanium's API for writing.

liamks commented 12 years ago

@maccman what portion of Titanium's API should I set out for?

http://developer.appcelerator.com/apidoc/mobile/1.7.1/Titanium.UI.Clipboard-module

I can most likely give it a shot this Wednesday. Next week I'm away, but I'd like to get this resolved soon.

MaKleSoft commented 12 years ago

getText and setText would be sufficient for me. Though I dont understand why you need to look at the Titanium API at all. Can't you find everything that you need here? https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/PasteboardGuide106/Introduction/Introduction.html

maccman commented 12 years ago

Yes, @MaKleSoft's right - we should follow the webview API.

MaKleSoft commented 12 years ago

I havent noticed this before but normal copy and paste from inputs doesnt work either.

liamks commented 12 years ago

It appears that the WebKit API already works within MacGap.

document.body.oncopy = function(e){
  e.preventDefault();
  console.log(e.clipboardData.setData("text/plain","asdf"))
}

The above will intercept a copy event and write "asdf" to the clipboard (and print true to the console).

More info: http://www.javascriptbank.com/javascript/article/how-to/accessing-the-system-clipboard-content-with-javascript/preview/en/ https://developer.apple.com/library/safari/#documentation/appleapplications/Conceptual/SafariJSProgTopics/Tasks/CopyAndPaste.html http://almaer.com/blog/supporting-the-system-clipboard-in-your-web-applications-what-a-pain

MaKleSoft commented 12 years ago

@liamks I don't think we understand each other. I dont want to intercept the copy or paste event. That would require the user to do a cmd + c or cmd + v.What I want to do is to manipulate the clipboard contents at ANY time, e. g. when the user presses a button. Now I've allready figured out the copying and pasting portion of the code. For example the obj-c function for writing a text to the clipboard would be

- (void) setClipboard:(NSString*)text {
    NSPasteboard *pasteboard;
    pasteboard = [NSPasteboard generalPasteboard];

    NSInteger changeCount = [pasteboard clearContents];

    NSArray *objectsToCopy = [NSArray arrayWithObjects:text,nil];;
    [pasteboard writeObjects:objectsToCopy];
}

The only thing I can't figure out is how to create a bridge between the javascript call (e.g. macgap.app.setClipboard()) and the obj-c function. If anybody can explain to me how that works then I'll be happy to implement it myself.

MaKleSoft commented 12 years ago

Also, as I mentioned before, copying and pasting via cmd + c and cmd + v doesn't work for me at all (the oncopy event doesn't get fired, either). Can you confirm this?

liamks commented 12 years ago

cmd + c and cmd + v work fine for me, that's how I was able to test the above code. The reason I posted the above code was not because I misunderstood you but because Webkit's API is entirely event based for copy and paste (as far as I can tell). In Internet Explorer one can modify the clipboard without events, but it appears that the only way to access the clipboard is through events in Webkit. What your asking for is a deviation from Webkit, which may be fine, but I wanted to explore native solutions first. For instance can you trigger the 'oncopy' event within your button/link click handler? If so then you don't need the objective-c code.

On a side node to bridge the gap between obj-c and javascript look at the classes within Classes/Commands, Then to bridge one of those classes look at 'WebViewDelegate.m' and add line like:

    if (self.clipboard == nil) {
        self.clipboard = [Clipboard new];
    }

Make sure you have @synthesize clipboard; at the top of the .m file and @property (nonatomic, retain) Clipboard *clipboard; in the .h file.

MaKleSoft commented 12 years ago

There actually is a way of doing it in webkit itself, albeit a rather hacky one. To write something to the clipboard you can use a hidden input element, fill it with the desired text, put focus on it and then call

document.execCommand("copy");

The same thing works with

document.execCommand("paste");

Unfortunately this does not seem to work in Macgap. Maybe you just have to change some parameter in the webview object to make this work, but I just don't know enough objective c to investigate this.

Its weird that normal copying and pasting works for you but not for me. Maybe it has something to do with the fact that I'm compiling the project on Lion using XCode 4.3? Or could there be any other reason?

Thanks for the directions! Say I simply want to add the functions to the macgap.app namespace, would I just need to add the corresponding methods to the App class then? Because that hasn't worked for me last time I tried.

liamks commented 12 years ago

If you plan on adding it to macgap.app then you'll also need to make modifications to the + (NSString*) webScriptNameForSelector:(SEL)selector method in App.m. Also make sure that you include the signatures of the methods that you are adding to the header file (App.h) to make them public.

Macmee commented 12 years ago

Has there been any progress with this? Is there a way to copy something to the user's clipboard using a function call within javascript?