Merge pull request #6333 from electron/drag-item
Add `webContents.startDrag(item)` API
This commit is contained in:
commit
83ae14f2ed
8 changed files with 206 additions and 0 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include "atom/browser/lib/bluetooth_chooser.h"
|
#include "atom/browser/lib/bluetooth_chooser.h"
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "atom/browser/net/atom_network_delegate.h"
|
#include "atom/browser/net/atom_network_delegate.h"
|
||||||
|
#include "atom/browser/ui/drag_util.h"
|
||||||
#include "atom/browser/web_contents_permission_helper.h"
|
#include "atom/browser/web_contents_permission_helper.h"
|
||||||
#include "atom/browser/web_contents_preferences.h"
|
#include "atom/browser/web_contents_preferences.h"
|
||||||
#include "atom/browser/web_view_guest_delegate.h"
|
#include "atom/browser/web_view_guest_delegate.h"
|
||||||
|
@ -1205,6 +1206,35 @@ void WebContents::EndFrameSubscription() {
|
||||||
view->EndFrameSubscription();
|
view->EndFrameSubscription();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContents::StartDrag(const mate::Dictionary& item,
|
||||||
|
mate::Arguments* args) {
|
||||||
|
base::FilePath file;
|
||||||
|
std::vector<base::FilePath> files;
|
||||||
|
if (!item.Get("files", &files) && item.Get("file", &file)) {
|
||||||
|
files.push_back(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
mate::Handle<NativeImage> icon;
|
||||||
|
if (!item.Get("icon", &icon) && !file.empty()) {
|
||||||
|
// TODO(zcbenz): Set default icon from file.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error checking.
|
||||||
|
if (icon.IsEmpty()) {
|
||||||
|
args->ThrowError("icon must be set");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start dragging.
|
||||||
|
if (!files.empty()) {
|
||||||
|
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||||
|
base::MessageLoop::current());
|
||||||
|
DragFileItems(files, icon->image(), web_contents()->GetNativeView());
|
||||||
|
} else {
|
||||||
|
args->ThrowError("There is nothing to drag");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WebContents::OnCursorChange(const content::WebCursor& cursor) {
|
void WebContents::OnCursorChange(const content::WebCursor& cursor) {
|
||||||
content::WebCursor::CursorInfo info;
|
content::WebCursor::CursorInfo info;
|
||||||
cursor.GetCursorInfo(&info);
|
cursor.GetCursorInfo(&info);
|
||||||
|
@ -1324,6 +1354,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
||||||
.SetMethod("beginFrameSubscription",
|
.SetMethod("beginFrameSubscription",
|
||||||
&WebContents::BeginFrameSubscription)
|
&WebContents::BeginFrameSubscription)
|
||||||
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
||||||
|
.SetMethod("startDrag", &WebContents::StartDrag)
|
||||||
.SetMethod("setSize", &WebContents::SetSize)
|
.SetMethod("setSize", &WebContents::SetSize)
|
||||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||||
.SetMethod("getType", &WebContents::GetType)
|
.SetMethod("getType", &WebContents::GetType)
|
||||||
|
|
|
@ -142,6 +142,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
||||||
void BeginFrameSubscription(mate::Arguments* args);
|
void BeginFrameSubscription(mate::Arguments* args);
|
||||||
void EndFrameSubscription();
|
void EndFrameSubscription();
|
||||||
|
|
||||||
|
// Dragging native items.
|
||||||
|
void StartDrag(const mate::Dictionary& item, mate::Arguments* args);
|
||||||
|
|
||||||
// Methods for creating <webview>.
|
// Methods for creating <webview>.
|
||||||
void SetSize(const SetSizeParams& params);
|
void SetSize(const SetSizeParams& params);
|
||||||
bool IsGuest() const;
|
bool IsGuest() const;
|
||||||
|
|
24
atom/browser/ui/drag_util.h
Normal file
24
atom/browser/ui/drag_util.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright (c) 2016 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_BROWSER_UI_DRAG_UTIL_H_
|
||||||
|
#define ATOM_BROWSER_UI_DRAG_UTIL_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ui/gfx/image/image.h"
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
class FilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
void DragFileItems(const std::vector<base::FilePath>& files,
|
||||||
|
const gfx::Image& icon,
|
||||||
|
gfx::NativeView view);
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_UI_DRAG_UTIL_H_
|
58
atom/browser/ui/drag_util_mac.mm
Normal file
58
atom/browser/ui/drag_util_mac.mm
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (c) 2016 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "atom/browser/ui/drag_util.h"
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/strings/sys_string_conversions.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Write information about the file being dragged to the pasteboard.
|
||||||
|
void AddFilesToPasteboard(NSPasteboard* pasteboard,
|
||||||
|
const std::vector<base::FilePath>& files) {
|
||||||
|
NSMutableArray* fileList = [NSMutableArray array];
|
||||||
|
for (const base::FilePath& file : files)
|
||||||
|
[fileList addObject:base::SysUTF8ToNSString(file.value())];
|
||||||
|
[pasteboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
|
||||||
|
owner:nil];
|
||||||
|
[pasteboard setPropertyList:fileList forType:NSFilenamesPboardType];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void DragFileItems(const std::vector<base::FilePath>& files,
|
||||||
|
const gfx::Image& icon,
|
||||||
|
gfx::NativeView view) {
|
||||||
|
NSPasteboard* pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
|
||||||
|
AddFilesToPasteboard(pasteboard, files);
|
||||||
|
|
||||||
|
// Synthesize a drag event, since we don't have access to the actual event
|
||||||
|
// that initiated a drag (possibly consumed by the Web UI, for example).
|
||||||
|
NSPoint position = [[view window] mouseLocationOutsideOfEventStream];
|
||||||
|
NSTimeInterval eventTime = [[NSApp currentEvent] timestamp];
|
||||||
|
NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
|
||||||
|
location:position
|
||||||
|
modifierFlags:NSLeftMouseDraggedMask
|
||||||
|
timestamp:eventTime
|
||||||
|
windowNumber:[[view window] windowNumber]
|
||||||
|
context:nil
|
||||||
|
eventNumber:0
|
||||||
|
clickCount:1
|
||||||
|
pressure:1.0];
|
||||||
|
|
||||||
|
// Run the drag operation.
|
||||||
|
[[view window] dragImage:icon.ToNSImage()
|
||||||
|
at:position
|
||||||
|
offset:NSZeroSize
|
||||||
|
event:dragEvent
|
||||||
|
pasteboard:pasteboard
|
||||||
|
source:view
|
||||||
|
slideBack:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
48
atom/browser/ui/drag_util_views.cc
Normal file
48
atom/browser/ui/drag_util_views.cc
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright (c) 2016 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/browser/ui/drag_util.h"
|
||||||
|
|
||||||
|
#include "ui/aura/window.h"
|
||||||
|
#include "ui/base/dragdrop/drag_drop_types.h"
|
||||||
|
#include "ui/base/dragdrop/drag_utils.h"
|
||||||
|
#include "ui/base/dragdrop/file_info.h"
|
||||||
|
#include "ui/base/dragdrop/os_exchange_data.h"
|
||||||
|
#include "ui/gfx/geometry/point.h"
|
||||||
|
#include "ui/gfx/screen.h"
|
||||||
|
#include "ui/views/widget/widget.h"
|
||||||
|
#include "ui/wm/public/drag_drop_client.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
void DragFileItems(const std::vector<base::FilePath>& files,
|
||||||
|
const gfx::Image& icon,
|
||||||
|
gfx::NativeView view) {
|
||||||
|
// Set up our OLE machinery
|
||||||
|
ui::OSExchangeData data;
|
||||||
|
|
||||||
|
drag_utils::CreateDragImageForFile(files[0], icon.AsImageSkia(), &data);
|
||||||
|
|
||||||
|
std::vector<ui::FileInfo> file_infos;
|
||||||
|
for (const base::FilePath& file : files) {
|
||||||
|
file_infos.push_back(ui::FileInfo(file, base::FilePath()));
|
||||||
|
}
|
||||||
|
data.SetFilenames(file_infos);
|
||||||
|
|
||||||
|
aura::Window* root_window = view->GetRootWindow();
|
||||||
|
if (!root_window || !aura::client::GetDragDropClient(root_window))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gfx::Point location = gfx::Screen::GetScreen()->GetCursorScreenPoint();
|
||||||
|
// TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
|
||||||
|
aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
|
||||||
|
data,
|
||||||
|
root_window,
|
||||||
|
view,
|
||||||
|
location,
|
||||||
|
ui::DragDropTypes::DRAG_COPY | ui::DragDropTypes::DRAG_LINK,
|
||||||
|
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
|
@ -943,6 +943,16 @@ defaults to `false`.
|
||||||
|
|
||||||
End subscribing for frame presentation events.
|
End subscribing for frame presentation events.
|
||||||
|
|
||||||
|
### `webContents.startDrag(item)`
|
||||||
|
|
||||||
|
* `item` object
|
||||||
|
* `file` String
|
||||||
|
* `icon` [NativeImage](native-image.md)
|
||||||
|
|
||||||
|
Sets the `item` as dragging item for current drag-drop operation, `file` is the
|
||||||
|
absolute path of the file to be dragged, and `icon` is the image showing under
|
||||||
|
the cursor when dragging.
|
||||||
|
|
||||||
### `webContents.savePage(fullPath, saveType, callback)`
|
### `webContents.savePage(fullPath, saveType, callback)`
|
||||||
|
|
||||||
* `fullPath` String - The full file path.
|
* `fullPath` String - The full file path.
|
||||||
|
|
|
@ -321,6 +321,35 @@ win.setRepresentedFilename('/etc/passwd');
|
||||||
win.setDocumentEdited(true);
|
win.setDocumentEdited(true);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Dragging files out of the window
|
||||||
|
|
||||||
|
For certain kinds of apps that manipulate on files, it is important to be able
|
||||||
|
to drag files from Electron to other apps. To implement this feature in your
|
||||||
|
app, you need to call `webContents.startDrag(item)` API on `ondragstart` event.
|
||||||
|
|
||||||
|
In web page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a href="#" id="drag">item</a>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
document.getElementById('drag').ondragstart = (event) => {
|
||||||
|
event.preventDefault()
|
||||||
|
ipcRenderer.send('ondragstart', '/path/to/item')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
In the main process:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ipcMain.on('ondragstart', (event, filePath) => {
|
||||||
|
event.sender.startDrag({
|
||||||
|
file: filePath,
|
||||||
|
icon: '/path/to/icon.png'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows
|
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows
|
||||||
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows
|
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows
|
||||||
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows
|
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows
|
||||||
|
|
|
@ -245,6 +245,9 @@
|
||||||
'atom/browser/ui/atom_menu_model.h',
|
'atom/browser/ui/atom_menu_model.h',
|
||||||
'atom/browser/ui/cocoa/atom_menu_controller.h',
|
'atom/browser/ui/cocoa/atom_menu_controller.h',
|
||||||
'atom/browser/ui/cocoa/atom_menu_controller.mm',
|
'atom/browser/ui/cocoa/atom_menu_controller.mm',
|
||||||
|
'atom/browser/ui/drag_util_mac.mm',
|
||||||
|
'atom/browser/ui/drag_util_views.cc',
|
||||||
|
'atom/browser/ui/drag_util.h',
|
||||||
'atom/browser/ui/file_dialog.h',
|
'atom/browser/ui/file_dialog.h',
|
||||||
'atom/browser/ui/file_dialog_gtk.cc',
|
'atom/browser/ui/file_dialog_gtk.cc',
|
||||||
'atom/browser/ui/file_dialog_mac.mm',
|
'atom/browser/ui/file_dialog_mac.mm',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue