Commit f9479f53 authored by jonlee@apple.com's avatar jonlee@apple.com

Dragging a file onto <input type="file"> should give distinct visual feedback

https://bugs.webkit.org/show_bug.cgi?id=13897
<rdar://problem/5232483>

Reviewed by Dan Bernstein.

When hovering over a file input element, we set the button's state to active
to differentiate dragging one file over the input element (which populates that
element) versus over the document (which would load the file into the view).

* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::HTMLInputElement):
(WebCore::HTMLInputElement::canReceiveDroppedFiles):
(WebCore::HTMLInputElement::setCanReceiveDroppedFiles): If set, the element
is updated, which sets the active state on the button control.
* html/HTMLInputElement.h: Add a boolean member representing whether the file
input can receive dropped files.
* page/DragController.cpp:
(WebCore::DragController::DragController): Update/set the file input that
can receive dropped files.
(WebCore::DragController::dragExited):
(WebCore::DragController::tryDocumentDrag):
(WebCore::DragController::concludeEditDrag):
* page/DragController.h:
* rendering/RenderFileUploadControl.cpp:
(WebCore::RenderFileUploadControl::updateFromElement): Sets the button active
state if the input can receive dropped files.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@99369 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9bbb3d77
2011-11-04 Jon Lee <jonlee@apple.com>
Dragging a file onto <input type="file"> should give distinct visual feedback
https://bugs.webkit.org/show_bug.cgi?id=13897
<rdar://problem/5232483>
Reviewed by Dan Bernstein.
When hovering over a file input element, we set the button's state to active
to differentiate dragging one file over the input element (which populates that
element) versus over the document (which would load the file into the view).
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::HTMLInputElement):
(WebCore::HTMLInputElement::canReceiveDroppedFiles):
(WebCore::HTMLInputElement::setCanReceiveDroppedFiles): If set, the element
is updated, which sets the active state on the button control.
* html/HTMLInputElement.h: Add a boolean member representing whether the file
input can receive dropped files.
* page/DragController.cpp:
(WebCore::DragController::DragController): Update/set the file input that
can receive dropped files.
(WebCore::DragController::dragExited):
(WebCore::DragController::tryDocumentDrag):
(WebCore::DragController::concludeEditDrag):
* page/DragController.h:
* rendering/RenderFileUploadControl.cpp:
(WebCore::RenderFileUploadControl::updateFromElement): Sets the button active
state if the input can receive dropped files.
2011-11-05 Darin Adler <darin@apple.com>
Improve pending resource hash table code, including fixing a memory leak
......
......@@ -94,6 +94,7 @@ HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* docum
, m_stateRestored(false)
, m_parsingInProgress(createdByParser)
, m_wasModifiedByUser(false)
, m_canReceiveDroppedFiles(false)
, m_inputType(InputType::createText(this))
{
ASSERT(hasTagName(inputTag) || hasTagName(isindexTag));
......@@ -1410,6 +1411,19 @@ Icon* HTMLInputElement::icon() const
return m_inputType->icon();
}
bool HTMLInputElement::canReceiveDroppedFiles() const
{
return m_canReceiveDroppedFiles;
}
void HTMLInputElement::setCanReceiveDroppedFiles(bool canReceiveDroppedFiles)
{
if (m_canReceiveDroppedFiles == canReceiveDroppedFiles)
return;
m_canReceiveDroppedFiles = canReceiveDroppedFiles;
renderer()->updateFromElement();
}
String HTMLInputElement::visibleValue() const
{
return m_inputType->visibleValue();
......
......@@ -209,6 +209,10 @@ public:
FileList* files();
void receiveDroppedFiles(const Vector<String>&);
Icon* icon() const;
// These functions are used for rendering the input active during a
// drag-and-drop operation.
bool canReceiveDroppedFiles() const;
void setCanReceiveDroppedFiles(bool);
void addSearchResult();
void onSearch();
......@@ -351,6 +355,7 @@ private:
bool m_stateRestored : 1;
bool m_parsingInProgress : 1;
bool m_wasModifiedByUser : 1;
bool m_canReceiveDroppedFiles : 1;
OwnPtr<InputType> m_inputType;
};
......
......@@ -88,6 +88,7 @@ DragController::DragController(Page* page, DragClient* client)
, m_client(client)
, m_documentUnderMouse(0)
, m_dragInitiator(0)
, m_fileInputElementUnderMouse(0)
, m_dragDestinationAction(DragDestinationActionNone)
, m_dragSourceAction(DragSourceActionNone)
, m_didInitiateDrag(false)
......@@ -181,6 +182,9 @@ void DragController::dragExited(DragData* dragData)
clipboard->setAccessPolicy(ClipboardNumb); // invalidate clipboard here for security
}
mouseMovedIntoDocument(0);
if (m_fileInputElementUnderMouse)
m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false);
m_fileInputElementUnderMouse = 0;
}
DragSession DragController::dragUpdated(DragData* dragData)
......@@ -328,25 +332,32 @@ bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction a
return false;
HTMLInputElement* elementAsFileInput = asFileInput(element);
if (!elementAsFileInput)
if (m_fileInputElementUnderMouse != elementAsFileInput) {
if (m_fileInputElementUnderMouse)
m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false);
m_fileInputElementUnderMouse = elementAsFileInput;
}
if (!m_fileInputElementUnderMouse)
m_page->dragCaretController()->setCaretPosition(m_documentUnderMouse->frame()->visiblePositionForPoint(point));
Frame* innerFrame = element->document()->frame();
dragSession.operation = dragIsMove(innerFrame->selection(), dragData) ? DragOperationMove : DragOperationCopy;
dragSession.mouseIsOverFileInput = elementAsFileInput;
dragSession.mouseIsOverFileInput = m_fileInputElementUnderMouse;
dragSession.numberOfItemsToBeAccepted = 0;
unsigned numberOfFiles = dragData->numberOfFiles();
if (elementAsFileInput) {
if (elementAsFileInput->disabled())
if (m_fileInputElementUnderMouse) {
if (m_fileInputElementUnderMouse->disabled())
dragSession.numberOfItemsToBeAccepted = 0;
else if (elementAsFileInput->multiple())
else if (m_fileInputElementUnderMouse->multiple())
dragSession.numberOfItemsToBeAccepted = numberOfFiles;
else
dragSession.numberOfItemsToBeAccepted = 1;
if (!dragSession.numberOfItemsToBeAccepted)
dragSession.operation = DragOperationNone;
m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(dragSession.numberOfItemsToBeAccepted);
} else {
// We are not over a file input element. The dragged item(s) will only
// be loaded into the view the number of dragged items is 1.
......@@ -355,8 +366,12 @@ bool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction a
return true;
}
// If we're not over an editable region, make sure we're clearing any prior drag cursor.
// We are not over an editable region. Make sure we're clearing any prior drag cursor.
m_page->dragCaretController()->clear();
if (m_fileInputElementUnderMouse)
m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false);
m_fileInputElementUnderMouse = 0;
return false;
}
......@@ -400,6 +415,11 @@ bool DragController::concludeEditDrag(DragData* dragData)
ASSERT(dragData);
ASSERT(!m_isHandlingDrag);
if (m_fileInputElementUnderMouse) {
m_fileInputElementUnderMouse->setCanReceiveDroppedFiles(false);
m_fileInputElementUnderMouse = 0;
}
if (!m_documentUnderMouse)
return false;
......
......@@ -42,6 +42,7 @@ namespace WebCore {
class Element;
class Frame;
class FrameSelection;
class HTMLInputElement;
class Image;
class IntRect;
class Node;
......@@ -117,6 +118,7 @@ namespace WebCore {
RefPtr<Document> m_documentUnderMouse; // The document the mouse was last dragged over.
RefPtr<Document> m_dragInitiator; // The Document (if any) that initiated the drag.
RefPtr<HTMLInputElement> m_fileInputElementUnderMouse;
DragDestinationAction m_dragDestinationAction;
DragSourceAction m_dragSourceAction;
......
......@@ -71,6 +71,8 @@ void RenderFileUploadControl::updateFromElement()
// updateFromElement() eventually.
if (button->disabled() != newDisabled)
button->setDisabled(newDisabled);
button->setActive(input->canReceiveDroppedFiles());
}
// This only supports clearing out the files, but that's OK because for
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment