[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
trey
trey at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 08:45:18 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 22b5bf3b877c3ed6a9198e3350dc896c391e6a50
Author: trey <trey at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Mon Jun 14 17:00:05 2004 +0000
WebCore:
The drag image may be updated during a DHTML drag. This includes updating
from a Timer instead of a drag event handler. In addition, an arbitrary
element can be set as the one to snapshot for the drag image.
Reviewed by John
* khtml/ecma/kjs_events.cpp:
(ClipboardProtoFunc::tryCall): setDragImage accepts a node. Previously,
it had to be an Image object.
* khtml/rendering/render_object.cpp:
(RenderObject::paintingRootRect): Also returns top element's rect.
* khtml/rendering/render_object.h:
* khtml/xml/dom2_eventsimpl.h:
* kwq/KWQClipboard.h: New security mode where image is still writable, but
pasteboard is not.
(KWQClipboard::):
(KWQClipboard::setDragHasStarted):
* kwq/KWQClipboard.mm:
(KWQClipboard::KWQClipboard): Part may be passed. Needed in the source
case to generate an image from an element.
(KWQClipboard::setAccessPolicy): New, replaces former becomeNumb method
which wasn't flexible enough.
(KWQClipboard::accessPolicy): New getter.
(KWQClipboard::dragImage): No change, diff confusion.
(KWQClipboard::setDragImage): Call new helper, below.
(KWQClipboard::dragImageElement): New, return any element set.
(KWQClipboard::setDragImageElement): New, call new helper.
(KWQClipboard::setDragImage): New helper, set the image via either a
pixmap or an element to snapshot, pushes the result to WebKit if we've
already started the drag.
(KWQClipboard::dragNSImage): Generate an NSImage and mouse offset, no
matter how the drag image was set (Image or element).
* kwq/KWQKHTMLPart.h: A single clipboard is kept over the life of a
source drag instead of making one for each event.
* kwq/KWQKHTMLPart.mm:
(KWQKHTMLPart::KWQKHTMLPart): Init clipboard.
(KWQKHTMLPart::~KWQKHTMLPart): Free clipboard.
(KWQKHTMLPart::freeClipboard): New helper.
(KWQKHTMLPart::dispatchDragSrcEvent): Most code moved to caller.
(KWQKHTMLPart::khtmlMouseMoveEvent): Make clipboard for this drag session.
Init clipboard to make an image from the dragSource element. Mark the
drag as having started.
(KWQKHTMLPart::dragSourceMovedTo): Clipboard will update WK with any new
drag image, so we don't need to.
(KWQKHTMLPart::dragSourceEndedAt): Ditto.
(KWQKHTMLPart::elementImage): Also return element rect.
* kwq/WebCoreBridge.h: Glue moved to WebCoreGraphicsBridge.
* kwq/WebCoreBridge.mm:
(-[WebCoreBridge dragOperationForDraggingInfo:]): Use new method.
(-[WebCoreBridge dragExitedWithDraggingInfo:]): Ditto
(-[WebCoreBridge concludeDragForDraggingInfo:]): Ditto
* kwq/WebCoreGraphicsBridge.h:
* kwq/WebCoreGraphicsBridge.m:
(-[WebCoreGraphicsBridge setDraggingImage:at:]): Glue moved from WebBridge
WebKit:
Small rearrangement to support dynamic changing of the drag
image during DHTML dragging.
Reviewed by John
* WebCoreSupport.subproj/WebBridge.m: Bridge glue moved to WebGraphicsBridge.
* WebCoreSupport.subproj/WebGraphicsBridge.m:
(FlipImageSpec): Code moved from WebHTMLView.m.
(-[WebGraphicsBridge setDraggingImage:at:]): Ditto. Plus, we've added a gross
event posting hack to force CG drag manager to update the display when we set
the drag image.
* WebView.subproj/WebHTMLView.m: Code moved to WebGraphicsBridge.
* WebView.subproj/WebHTMLViewPrivate.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6822 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 0f86d6b..5ea8608 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,60 @@
+2004-06-12 Trey Matteson <trey at apple.com>
+
+ The drag image may be updated during a DHTML drag. This includes updating
+ from a Timer instead of a drag event handler. In addition, an arbitrary
+ element can be set as the one to snapshot for the drag image.
+
+ Reviewed by John
+
+ * khtml/ecma/kjs_events.cpp:
+ (ClipboardProtoFunc::tryCall): setDragImage accepts a node. Previously,
+ it had to be an Image object.
+ * khtml/rendering/render_object.cpp:
+ (RenderObject::paintingRootRect): Also returns top element's rect.
+ * khtml/rendering/render_object.h:
+ * khtml/xml/dom2_eventsimpl.h:
+ * kwq/KWQClipboard.h: New security mode where image is still writable, but
+ pasteboard is not.
+ (KWQClipboard::):
+ (KWQClipboard::setDragHasStarted):
+ * kwq/KWQClipboard.mm:
+ (KWQClipboard::KWQClipboard): Part may be passed. Needed in the source
+ case to generate an image from an element.
+ (KWQClipboard::setAccessPolicy): New, replaces former becomeNumb method
+ which wasn't flexible enough.
+ (KWQClipboard::accessPolicy): New getter.
+ (KWQClipboard::dragImage): No change, diff confusion.
+ (KWQClipboard::setDragImage): Call new helper, below.
+ (KWQClipboard::dragImageElement): New, return any element set.
+ (KWQClipboard::setDragImageElement): New, call new helper.
+ (KWQClipboard::setDragImage): New helper, set the image via either a
+ pixmap or an element to snapshot, pushes the result to WebKit if we've
+ already started the drag.
+ (KWQClipboard::dragNSImage): Generate an NSImage and mouse offset, no
+ matter how the drag image was set (Image or element).
+ * kwq/KWQKHTMLPart.h: A single clipboard is kept over the life of a
+ source drag instead of making one for each event.
+ * kwq/KWQKHTMLPart.mm:
+ (KWQKHTMLPart::KWQKHTMLPart): Init clipboard.
+ (KWQKHTMLPart::~KWQKHTMLPart): Free clipboard.
+ (KWQKHTMLPart::freeClipboard): New helper.
+ (KWQKHTMLPart::dispatchDragSrcEvent): Most code moved to caller.
+ (KWQKHTMLPart::khtmlMouseMoveEvent): Make clipboard for this drag session.
+ Init clipboard to make an image from the dragSource element. Mark the
+ drag as having started.
+ (KWQKHTMLPart::dragSourceMovedTo): Clipboard will update WK with any new
+ drag image, so we don't need to.
+ (KWQKHTMLPart::dragSourceEndedAt): Ditto.
+ (KWQKHTMLPart::elementImage): Also return element rect.
+ * kwq/WebCoreBridge.h: Glue moved to WebCoreGraphicsBridge.
+ * kwq/WebCoreBridge.mm:
+ (-[WebCoreBridge dragOperationForDraggingInfo:]): Use new method.
+ (-[WebCoreBridge dragExitedWithDraggingInfo:]): Ditto
+ (-[WebCoreBridge concludeDragForDraggingInfo:]): Ditto
+ * kwq/WebCoreGraphicsBridge.h:
+ * kwq/WebCoreGraphicsBridge.m:
+ (-[WebCoreGraphicsBridge setDraggingImage:at:]): Glue moved from WebBridge
+
2004-06-11 Chris Blumenberg <cblu at apple.com>
Support for WebKit drag & drop API.
diff --git a/WebCore/khtml/ecma/kjs_events.cpp b/WebCore/khtml/ecma/kjs_events.cpp
index 1964a0d..cce9171 100644
--- a/WebCore/khtml/ecma/kjs_events.cpp
+++ b/WebCore/khtml/ecma/kjs_events.cpp
@@ -1030,25 +1030,38 @@ Value ClipboardProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &
case Clipboard::SetDragImage:
{
if (args.size() != 3) {
- Object err = Error::create(exec,SyntaxError,"setData: Invalid number of arguments");
+ Object err = Error::create(exec, SyntaxError,"setDragImage: Invalid number of arguments");
exec->setException(err);
return err;
}
-
+
+ int x = (int)args[1].toNumber(exec);
+ int y = (int)args[2].toNumber(exec);
+
+ // See if they passed us a node
+ DOM::Node node = toNode(args[0]);
+ if (!node.isNull()) {
+ if (node.nodeType() == DOM::Node::ELEMENT_NODE) {
+ cb->clipboard->setDragImageElement(node, QPoint(x,y));
+ return Undefined();
+ } else {
+ Object err = Error::create(exec, SyntaxError,"setDragImageFromElement: Invalid first argument");
+ exec->setException(err);
+ return err;
+ }
+ }
+
+ // See if they passed us an Image object
ObjectImp *o = static_cast<ObjectImp*>(args[0].imp());
- if (!o->inherits(&Image::info)) {
+ if (o->inherits(&Image::info)) {
+ Image *JSImage = static_cast<Image*>(o);
+ cb->clipboard->setDragImage(JSImage->image()->pixmap(), QPoint(x,y));
+ return Undefined();
+ } else {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
-
- Image *JSImage = static_cast<Image*>(o);
- int x = (int)args[1].toNumber(exec);
- int y = (int)args[2].toNumber(exec);
- cb->clipboard->setDragImage(JSImage->image()->pixmap());
- cb->clipboard->setDragLocation(QPoint(x,y));
-
- return Undefined();
}
}
return Undefined();
diff --git a/WebCore/khtml/rendering/render_object.cpp b/WebCore/khtml/rendering/render_object.cpp
index 0669840..248f069 100644
--- a/WebCore/khtml/rendering/render_object.cpp
+++ b/WebCore/khtml/rendering/render_object.cpp
@@ -1094,9 +1094,10 @@ void RenderObject::addAbsoluteRectForLayer(QRect& result)
}
}
-QRect RenderObject::paintingRootRect()
+QRect RenderObject::paintingRootRect(QRect& topLevelRect)
{
QRect result = absoluteBoundingBoxRect();
+ topLevelRect = result;
for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
current->addAbsoluteRectForLayer(result);
}
diff --git a/WebCore/khtml/rendering/render_object.h b/WebCore/khtml/rendering/render_object.h
index 2c852f4..2a9bb24 100644
--- a/WebCore/khtml/rendering/render_object.h
+++ b/WebCore/khtml/rendering/render_object.h
@@ -613,7 +613,7 @@ public:
virtual void absoluteRects(QValueList<QRect>& rects, int _tx, int _ty);
// the rect that will be painted if this object is passed as the paintingRoot
- QRect paintingRootRect();
+ QRect paintingRootRect(QRect& topLevelRect);
#if APPLE_CHANGES
virtual void addFocusRingRects(QPainter *painter, int _tx, int _ty);
diff --git a/WebCore/khtml/xml/dom2_eventsimpl.h b/WebCore/khtml/xml/dom2_eventsimpl.h
index be4d543..be3fc4a 100644
--- a/WebCore/khtml/xml/dom2_eventsimpl.h
+++ b/WebCore/khtml/xml/dom2_eventsimpl.h
@@ -396,9 +396,10 @@ public:
virtual QStringList types() const = 0;
virtual QPoint dragLocation() const = 0;
- virtual void setDragLocation(const QPoint &) = 0;
virtual QPixmap dragImage() const = 0;
- virtual void setDragImage(const QPixmap &) = 0;
+ virtual void setDragImage(const QPixmap &, const QPoint &) = 0;
+ virtual const Node dragImageElement() = 0;
+ virtual void setDragImageElement(const Node &, const QPoint &) = 0;
};
}; //namespace
diff --git a/WebCore/kwq/KWQClipboard.h b/WebCore/kwq/KWQClipboard.h
index 0143f1a..6a84ca0 100644
--- a/WebCore/kwq/KWQClipboard.h
+++ b/WebCore/kwq/KWQClipboard.h
@@ -31,15 +31,17 @@
#import <AppKit/AppKit.h>
#include "xml/dom2_eventsimpl.h"
+class KWQKHTMLPart;
+
class KWQClipboard : public DOM::ClipboardImpl
{
public:
- // security mechanism
+ // security mechanisms
typedef enum {
- Numb, Writable, TypesReadable, Readable
+ Numb, ImageWritable, Writable, TypesReadable, Readable
} AccessPolicy;
- KWQClipboard(bool forDragging, NSPasteboard *pasteboard, AccessPolicy policy);
+ KWQClipboard(bool forDragging, NSPasteboard *pasteboard, AccessPolicy policy, KWQKHTMLPart *part = 0);
virtual ~KWQClipboard();
bool isForDragging() const;
@@ -57,30 +59,37 @@ public:
// extensions beyond IE's API
virtual QStringList types() const;
- QPoint dragLocation() const;
- void setDragLocation(const QPoint &);
+ QPoint dragLocation() const; // same point as client passed us
QPixmap dragImage() const;
- void setDragImage(const QPixmap &);
+ void setDragImage(const QPixmap &, const QPoint &);
+ const DOM::Node dragImageElement();
+ void setDragImageElement(const DOM::Node &, const QPoint &);
// Methods for getting info in Cocoa's type system
- NSImage *dragNSImage();
+ NSImage *dragNSImage(NSPoint *loc); // loc converted from dragLoc, based on whole image size
bool sourceOperation(NSDragOperation *op) const;
bool destinationOperation(NSDragOperation *op) const;
void setSourceOperation(NSDragOperation op);
void setDestinationOperation(NSDragOperation op);
- // sets AccessPolicy = Numb - trap door, once this is set, no going back
- void becomeNumb();
+ void setAccessPolicy(AccessPolicy policy);
+ AccessPolicy accessPolicy() const;
+ void setDragHasStarted() { m_dragStarted = true; }
private:
+ void setDragImage(const QPixmap &pm, const DOM::Node &, const QPoint &loc);
+
NSPasteboard *m_pasteboard;
bool m_forDragging;
DOM::DOMString m_dropEffect;
DOM::DOMString m_effectAllowed;
QPoint m_dragLoc;
QPixmap m_dragImage;
+ DOM::Node m_dragImageElement;
AccessPolicy m_policy;
int m_changeCount;
+ bool m_dragStarted;
+ KWQKHTMLPart *m_part; // used on the source side to generate dragging images
};
diff --git a/WebCore/kwq/KWQClipboard.mm b/WebCore/kwq/KWQClipboard.mm
index 4b643c9..22e1269 100644
--- a/WebCore/kwq/KWQClipboard.mm
+++ b/WebCore/kwq/KWQClipboard.mm
@@ -24,12 +24,16 @@
*/
#import "KWQClipboard.h"
+#import "KWQAssertions.h"
+#import "KWQKHTMLPart.h"
#import "KWQStringList.h"
+#import "WebCoreGraphicsBridge.h"
using DOM::DOMString;
-KWQClipboard::KWQClipboard(bool forDragging, NSPasteboard *pasteboard, AccessPolicy policy)
- : m_pasteboard([pasteboard retain]), m_forDragging(forDragging), m_policy(policy)
+KWQClipboard::KWQClipboard(bool forDragging, NSPasteboard *pasteboard, AccessPolicy policy, KWQKHTMLPart *part)
+ : m_pasteboard([pasteboard retain]), m_forDragging(forDragging),
+ m_dragImageElement(0), m_policy(policy), m_dragStarted(false), m_part(part)
{
m_changeCount = [m_pasteboard changeCount];
}
@@ -44,9 +48,16 @@ bool KWQClipboard::isForDragging() const
return m_forDragging;
}
-void KWQClipboard::becomeNumb()
+void KWQClipboard::setAccessPolicy(AccessPolicy policy)
{
- m_policy = Numb;
+ // once you go numb, can never go back
+ ASSERT(m_policy != Numb || policy == Numb);
+ m_policy = policy;
+}
+
+KWQClipboard::AccessPolicy KWQClipboard::accessPolicy() const
+{
+ return m_policy;
}
// FIXME hardwired for now, will use UTI
@@ -249,28 +260,70 @@ QPoint KWQClipboard::dragLocation() const
return m_dragLoc;
}
-void KWQClipboard::setDragLocation(const QPoint &p)
+QPixmap KWQClipboard::dragImage() const
{
- if (m_policy == Writable) {
- m_dragLoc = p;
- }
+ return m_dragImage;
}
-QPixmap KWQClipboard::dragImage() const
+void KWQClipboard::setDragImage(const QPixmap &pm, const QPoint &loc)
{
- return m_dragImage;
+ setDragImage(pm, DOM::Node(0), loc);
}
-void KWQClipboard::setDragImage(const QPixmap &pm)
+const DOM::Node KWQClipboard::dragImageElement()
{
- if (m_policy == Writable) {
+ return m_dragImageElement;
+}
+
+void KWQClipboard::setDragImageElement(const DOM::Node &node, const QPoint &loc)
+{
+ setDragImage(QPixmap(), node, loc);
+}
+
+void KWQClipboard::setDragImage(const QPixmap &pm, const DOM::Node &node, const QPoint &loc)
+{
+ if (m_policy == ImageWritable || m_policy == Writable) {
m_dragImage = pm;
+ m_dragLoc = loc;
+ m_dragImageElement = node;
+
+ if (m_dragStarted && m_changeCount == [m_pasteboard changeCount]) {
+ NSPoint cocoaLoc;
+ NSImage *cocoaImage = dragNSImage(&cocoaLoc);
+ if (cocoaImage) {
+ [[WebCoreGraphicsBridge sharedBridge] setDraggingImage:cocoaImage at:cocoaLoc];
+ }
+ }
+ // Else either 1) we haven't started dragging yet, so we rely on the part to install this drag image
+ // as part of getting the drag kicked off, or 2) Someone kept a ref to the clipboard and is trying to
+ // set the image way too late.
}
}
-NSImage *KWQClipboard::dragNSImage()
+NSImage *KWQClipboard::dragNSImage(NSPoint *loc)
{
- return m_dragImage.image();
+ NSImage *result = nil;
+ if (!m_dragImageElement.isNull()) {
+ if (m_part) {
+ NSRect imageRect;
+ NSRect elementRect;
+ result = m_part->elementImage(m_dragImageElement, &imageRect, &elementRect);
+ if (loc) {
+ // Client specifies point relative to element, not the whole image, which may include child
+ // layers spread out all over the place.
+ loc->x = elementRect.origin.x - imageRect.origin.x + m_dragLoc.x();
+ loc->y = elementRect.origin.y - imageRect.origin.y + m_dragLoc.y();
+ loc->y = imageRect.size.height - loc->y;
+ }
+ }
+ } else {
+ result = m_dragImage.image();
+ if (loc) {
+ *loc = NSPoint(m_dragLoc);
+ loc->y = [result size].height - loc->y;
+ }
+ }
+ return result;
}
DOM::DOMString KWQClipboard::dropEffect() const
diff --git a/WebCore/kwq/KWQKHTMLPart.h b/WebCore/kwq/KWQKHTMLPart.h
index 3486db6..0a86dce 100644
--- a/WebCore/kwq/KWQKHTMLPart.h
+++ b/WebCore/kwq/KWQKHTMLPart.h
@@ -43,6 +43,7 @@
#include "KWQDict.h"
class KHTMLPartPrivate;
+class KWQClipboard;
class KWQWindowWidget;
namespace khtml {
@@ -211,7 +212,7 @@ public:
QRect selectionRect() const;
NSRect visibleSelectionRect() const;
NSImage *selectionImage() const;
- NSImage *elementImage(DOM::Node node, NSRect *imageRect) const;
+ NSImage *elementImage(DOM::Node node, NSRect *imageRect, NSRect *elementRect) const;
NSFont *fontForCurrentPosition() const;
@@ -328,10 +329,12 @@ private:
static NSView *documentViewForNode(DOM::NodeImpl *);
bool dragHysteresisExceeded(float dragLocationX, float dragLocationY) const;
- bool dispatchDragSrcEvent(int eventId, const QPoint &loc, NSImage **dragImage, NSPoint *dragLoc, unsigned *op) const;
+ bool dispatchDragSrcEvent(int eventId, const QPoint &loc) const;
NSImage *KWQKHTMLPart::imageFromRect(NSRect rect) const;
+ void freeClipboard();
+
WebCoreBridge *_bridge;
KWQSignal _started;
@@ -378,6 +381,7 @@ private:
bool _dragSrcInSelection;
bool _dragSrcMayBeDHTML, _dragSrcMayBeUA; // Are DHTML and/or the UserAgent allowed to drag out?
bool _dragSrcIsDHTML;
+ KWQClipboard *_dragClipboard; // used on only the source side of dragging
mutable DOM::Node _elementToDraw;
};
diff --git a/WebCore/kwq/KWQKHTMLPart.mm b/WebCore/kwq/KWQKHTMLPart.mm
index c201f4e..f82304e 100644
--- a/WebCore/kwq/KWQKHTMLPart.mm
+++ b/WebCore/kwq/KWQKHTMLPart.mm
@@ -185,6 +185,7 @@ KWQKHTMLPart::KWQKHTMLPart()
, _bindingRoot(0)
, _windowScriptObject(0)
, _dragSrc(0)
+ , _dragClipboard(0)
, _elementToDraw(0)
{
// Must init the cache before connecting to any signals
@@ -205,6 +206,7 @@ KWQKHTMLPart::~KWQKHTMLPart()
if (d->m_view) {
d->m_view->deref();
}
+ freeClipboard();
// these are all basic Foundation classes and our own classes - we
// know they will not raise in dealloc, so no need to block
// exceptions.
@@ -216,6 +218,15 @@ KWQKHTMLPart::~KWQKHTMLPart()
delete _windowWidget;
}
+void KWQKHTMLPart::freeClipboard()
+{
+ if (_dragClipboard) {
+ _dragClipboard->setAccessPolicy(KWQClipboard::Numb);
+ _dragClipboard->deref();
+ _dragClipboard = 0;
+ }
+}
+
void KWQKHTMLPart::setSettings (KHTMLSettings *settings)
{
d->m_settings = settings;
@@ -1905,33 +1916,10 @@ bool KWQKHTMLPart::dragHysteresisExceeded(float dragLocationX, float dragLocatio
return deltaX >= threshold || deltaY >= threshold;
}
-// returns if we should continue "default processing", i.e., whether to start up the drag
-bool KWQKHTMLPart::dispatchDragSrcEvent(int eventId, const QPoint &loc, NSImage **dragImage, NSPoint *dragLoc, NSDragOperation *op) const
+// returns if we should continue "default processing", i.e., whether eventhandler canceled
+bool KWQKHTMLPart::dispatchDragSrcEvent(int eventId, const QPoint &loc) const
{
- KWQClipboard *clipboard = new KWQClipboard(true, [NSPasteboard pasteboardWithName:NSDragPboard], KWQClipboard::Writable);
- clipboard->ref();
- bool noDefaultProc = d->m_view->dispatchDragEvent(eventId, _dragSrc.handle(), loc, clipboard);
- clipboard->becomeNumb(); // invalidate clipboard here for security
-
- if (dragImage) {
- *dragImage = clipboard->dragNSImage();
- if (*dragImage) {
- [[*dragImage retain] autorelease]; // just in case clipboard takes the image with it
- // should be set in clipboard iff dragImage is set
- if (dragLoc) {
- *dragLoc = NSPoint(clipboard->dragLocation());
- // Web way is upper left, AppKit way is lower left
- dragLoc->y = [*dragImage size].height - dragLoc->y;
- }
- }
- }
-
- if (op) {
- // *op unchanged if no source op was set
- clipboard->sourceOperation(op);
- }
-
- clipboard->deref();
+ bool noDefaultProc = d->m_view->dispatchDragEvent(eventId, _dragSrc.handle(), loc, _dragClipboard);
return !noDefaultProc;
}
@@ -1984,41 +1972,67 @@ void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
NSPoint dragLocation = [_currentEvent locationInWindow];
if (dragHysteresisExceeded(dragLocation.x, dragLocation.y)) {
- NSImage *dragImage = nil;
+ NSImage *dragImage = nil; // we use these values if WC is out of the loop
NSPoint dragLoc = NSZeroPoint;
- NSDragOperation srcOp = NSDragOperationNone;
+ NSDragOperation srcOp = NSDragOperationNone;
BOOL wcWrotePasteboard = NO;
if (_dragSrcMayBeDHTML) {
NSPasteboard *pasteboard = [NSPasteboard pasteboardWithName:NSDragPboard];
// Must be done before ondragstart adds types and data to the pboard,
// also done for security, as it erases data from the last drag
[pasteboard declareTypes:[NSArray array] owner:nil];
+
+ freeClipboard(); // would only happen if we missed a dragEnd. Do it anyway, just
+ // to make sure it gets numbified
+ _dragClipboard = new KWQClipboard(true, pasteboard, KWQClipboard::Writable, this);
+ _dragClipboard->ref();
+
+ // If this is drag of an element, get set up to generate a default image. Otherwise
+ // WebKit will generate the default, the element doesn't override.
+ if (_dragSrcIsDHTML) {
+ int srcX, srcY;
+ _dragSrc.handle()->renderer()->absolutePosition(srcX, srcY);
+ _dragClipboard->setDragImageElement(_dragSrc, QPoint(_mouseDownX - srcX, _mouseDownY - srcY));
+ }
+
+ _mouseDownMayStartDrag = dispatchDragSrcEvent(EventImpl::DRAGSTART_EVENT, QPoint(dragLocation));
+ // Invalidate clipboard here against anymore pasteboard writing for security. The drag
+ // image can still be changed as we drag, but not the pasteboard data.
+ _dragClipboard->setAccessPolicy(KWQClipboard::ImageWritable);
+
+ if (_mouseDownMayStartDrag) {
+ // gather values from DHTML element, if it set any
+ _dragClipboard->sourceOperation(&srcOp);
- if (dispatchDragSrcEvent(EventImpl::DRAGSTART_EVENT, QPoint(dragLocation), &dragImage, &dragLoc, &srcOp)) {
NSArray *types = [pasteboard types];
wcWrotePasteboard = types && [types count] > 0;
- if (!dragImage && _dragSrcIsDHTML) {
- // Element accepted, but didn't supply an image, and WebKit won't be making one
- // either - so we make a default one
- NSRect imageRect;
- dragImage = elementImage(_dragSrc, &imageRect);
- dragLoc.x = _mouseDownX - imageRect.origin.x;
- dragLoc.y = imageRect.size.height - (_mouseDownY - imageRect.origin.y);
+ if (_dragSrcMayBeDHTML) {
+ dragImage = _dragClipboard->dragNSImage(&dragLoc);
}
- } else {
- _mouseDownMayStartDrag = false; // ondragstart makes us bail
+
+ // Yuck, dragSourceMovedTo() can be called as a result of kicking off the drag with
+ // dragImage! Because of that dumb reentrancy, we may think we've not started the
+ // drag when that happens. So we have to assume it's started before we kick it off.
+ _dragClipboard->setDragHasStarted();
}
}
-
+
if (_mouseDownMayStartDrag) {
if ([_bridge startDraggingImage:dragImage at:dragLoc operation:srcOp event:_currentEvent sourceIsDHTML:_dragSrcIsDHTML DHTMLWroteData:wcWrotePasteboard]) {
// Prevent click handling from taking place once we start dragging.
d->m_view->invalidateClick();
} else if (_dragSrcMayBeDHTML) {
// WebKit canned the drag at the last minute - we owe _dragSrc a DRAGEND event
- dispatchDragSrcEvent(EventImpl::DRAGEND_EVENT, QPoint(dragLocation), NULL, NULL, NULL);
+ dispatchDragSrcEvent(EventImpl::DRAGEND_EVENT, QPoint(dragLocation));
+ _mouseDownMayStartDrag = false;
}
+ }
+
+ if (!_mouseDownMayStartDrag) {
+ // something failed to start the drag, cleanup
+ freeClipboard();
+ _dragSrc = 0;
}
}
@@ -2051,13 +2065,8 @@ void KWQKHTMLPart::khtmlMouseMoveEvent(MouseMoveEvent *event)
void KWQKHTMLPart::dragSourceMovedTo(const QPoint &loc)
{
if (!_dragSrc.isNull() && _dragSrcMayBeDHTML) {
- NSImage *dragImage = nil;
- NSPoint dragLoc = NSZeroPoint;
// for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(EventImpl::DRAG_EVENT, loc, &dragImage, &dragLoc, NULL);
- if (dragImage) {
- [_bridge setDraggingImage:dragImage at:dragLoc];
- }
+ dispatchDragSrcEvent(EventImpl::DRAG_EVENT, loc);
}
}
@@ -2065,8 +2074,10 @@ void KWQKHTMLPart::dragSourceEndedAt(const QPoint &loc)
{
if (!_dragSrc.isNull() && _dragSrcMayBeDHTML) {
// for now we don't care if event handler cancels default behavior, since there is none
- dispatchDragSrcEvent(EventImpl::DRAGEND_EVENT, loc, NULL, NULL, NULL);
+ dispatchDragSrcEvent(EventImpl::DRAGEND_EVENT, loc);
}
+ freeClipboard();
+ _dragSrc = 0;
}
void KWQKHTMLPart::khtmlMouseReleaseEvent(MouseReleaseEvent *event)
@@ -2980,18 +2991,26 @@ NSImage *KWQKHTMLPart::selectionImage() const
return result;
}
-NSImage *KWQKHTMLPart::elementImage(DOM::Node node, NSRect *imageRect) const
+NSImage *KWQKHTMLPart::elementImage(DOM::Node node, NSRect *imageRect, NSRect *elementRect) const
{
RenderObject *renderer = node.handle()->renderer();
if (!renderer) {
return nil;
}
- *imageRect = renderer->paintingRootRect();
+ d->m_doc->updateRendering();
+ QRect topLevelRect;
+ NSRect paintingRect = renderer->paintingRootRect(topLevelRect);
_elementToDraw = node; // invoke special drawing mode
- NSImage *result = imageFromRect(*imageRect);
+ NSImage *result = imageFromRect(paintingRect);
_elementToDraw = 0;
+ if (elementRect) {
+ *elementRect = topLevelRect;
+ }
+ if (imageRect) {
+ *imageRect = paintingRect;
+ }
return result;
}
diff --git a/WebCore/kwq/WebCoreBridge.h b/WebCore/kwq/WebCoreBridge.h
index 38d5166..5aa9b6a 100644
--- a/WebCore/kwq/WebCoreBridge.h
+++ b/WebCore/kwq/WebCoreBridge.h
@@ -430,7 +430,6 @@ typedef enum {
- (void)allowDHTMLDrag:(BOOL *)flagDHTML UADrag:(BOOL *)flagUA;
- (BOOL)startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData;
-- (void)setDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc;
- (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
- (BOOL)mayStartDragWithMouseDragged:(NSEvent *)event;
diff --git a/WebCore/kwq/WebCoreBridge.mm b/WebCore/kwq/WebCoreBridge.mm
index 2f339b3..fa972cc 100644
--- a/WebCore/kwq/WebCoreBridge.mm
+++ b/WebCore/kwq/WebCoreBridge.mm
@@ -1581,7 +1581,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
op = NSDragOperationNone;
}
}
- clipboard->becomeNumb(); // invalidate clipboard here for security
+ clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
clipboard->deref();
v->deref();
@@ -1603,7 +1603,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
clipboard->ref();
v->cancelDragAndDrop(QPoint([info draggingLocation]), clipboard);
- clipboard->becomeNumb(); // invalidate clipboard here for security
+ clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
clipboard->deref();
v->deref();
@@ -1623,7 +1623,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
clipboard->ref();
BOOL result = v->performDragAndDrop(QPoint([info draggingLocation]), clipboard);
- clipboard->becomeNumb(); // invalidate clipboard here for security
+ clipboard->setAccessPolicy(KWQClipboard::Numb); // invalidate clipboard here for security
clipboard->deref();
v->deref();
diff --git a/WebCore/kwq/WebCoreGraphicsBridge.h b/WebCore/kwq/WebCoreGraphicsBridge.h
index 69e5f28..2f33436 100644
--- a/WebCore/kwq/WebCoreGraphicsBridge.h
+++ b/WebCore/kwq/WebCoreGraphicsBridge.h
@@ -29,5 +29,6 @@
+ (WebCoreGraphicsBridge *)sharedBridge;
- (void)setFocusRingStyle:(NSFocusRingPlacement)placement radius:(int)radius color:(NSColor *)color;
+- (void)setDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc;
@end
diff --git a/WebCore/kwq/WebCoreGraphicsBridge.m b/WebCore/kwq/WebCoreGraphicsBridge.m
index a67ca3b..5cd2114 100644
--- a/WebCore/kwq/WebCoreGraphicsBridge.m
+++ b/WebCore/kwq/WebCoreGraphicsBridge.m
@@ -50,4 +50,8 @@ static WebCoreGraphicsBridge *sharedBridge;
{
}
+- (void)setDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc
+{
+}
+
@end
diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index a8e4c13..5cd2f35 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,19 @@
+2004-06-12 Trey Matteson <trey at apple.com>
+
+ Small rearrangement to support dynamic changing of the drag
+ image during DHTML dragging.
+
+ Reviewed by John
+
+ * WebCoreSupport.subproj/WebBridge.m: Bridge glue moved to WebGraphicsBridge.
+ * WebCoreSupport.subproj/WebGraphicsBridge.m:
+ (FlipImageSpec): Code moved from WebHTMLView.m.
+ (-[WebGraphicsBridge setDraggingImage:at:]): Ditto. Plus, we've added a gross
+ event posting hack to force CG drag manager to update the display when we set
+ the drag image.
+ * WebView.subproj/WebHTMLView.m: Code moved to WebGraphicsBridge.
+ * WebView.subproj/WebHTMLViewPrivate.h:
+
2004-06-11 Chris Blumenberg <cblu at apple.com>
Implemented the remainder of the drag & drop API.
diff --git a/WebKit/WebCoreSupport.subproj/WebBridge.m b/WebKit/WebCoreSupport.subproj/WebBridge.m
index e83d46f..164e04e 100644
--- a/WebKit/WebCoreSupport.subproj/WebBridge.m
+++ b/WebKit/WebCoreSupport.subproj/WebBridge.m
@@ -1003,13 +1003,6 @@ static BOOL loggedObjectCacheSize = NO;
return [docView _startDraggingImage:dragImage at:dragLoc operation:op event:event sourceIsDHTML:flag DHTMLWroteData:dhtmlWroteData];
}
-- (void)setDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc
-{
- WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
- ASSERT([docView isKindOfClass:[WebHTMLView class]]);
- [docView _setDraggingImage:dragImage at:dragLoc];
-}
-
- (void)handleAutoscrollForMouseDragged:(NSEvent *)event;
{
WebHTMLView *docView = (WebHTMLView *)[[_frame frameView] documentView];
diff --git a/WebKit/WebCoreSupport.subproj/WebGraphicsBridge.m b/WebKit/WebCoreSupport.subproj/WebGraphicsBridge.m
index 2ba7041..040fc23 100644
--- a/WebKit/WebCoreSupport.subproj/WebGraphicsBridge.m
+++ b/WebKit/WebCoreSupport.subproj/WebGraphicsBridge.m
@@ -25,6 +25,9 @@
#import "WebGraphicsBridge.h"
+#import <HIServices/CoreDrag.h>
+#import <HIServices/CoreDragPriv.h>
+
#import "WebAssertions.h"
#ifndef USE_APPEARANCE
@@ -98,4 +101,100 @@
CGStyleRelease(focusRingStyleRef);
}
+static void FlipImageSpec(CoreDragImageSpec* imageSpec) {
+ // run through and swap each row. we'll need a temporary row to hold the swapped row
+ //
+ unsigned char* tempRow = malloc(imageSpec->bytesPerRow);
+ int planes = imageSpec->isPlanar ? imageSpec->samplesPerPixel : 1;
+
+ int p;
+ for (p = 0; p < planes; p++) {
+ unsigned char* topRow = (unsigned char*)imageSpec->data[p];
+ unsigned char* botRow = topRow + (imageSpec->pixelsHigh - 1) * imageSpec->bytesPerRow;
+ int i;
+ for (i = 0; i < imageSpec->pixelsHigh / 2; i++, topRow += imageSpec->bytesPerRow, botRow -= imageSpec->bytesPerRow) {
+ bcopy(topRow, tempRow, imageSpec->bytesPerRow);
+ bcopy(botRow, topRow, imageSpec->bytesPerRow);
+ bcopy(tempRow, botRow, imageSpec->bytesPerRow);
+ }
+ }
+ free(tempRow);
+}
+
+// Dashboard wants to set the drag image during dragging, but Cocoa does not allow this. Instead we drop
+// down to the CG API. Converting an NSImage to a CGImageSpec is copied from NSDragManager.
+- (void)setDraggingImage:(NSImage *)image at:(NSPoint)offset
+{
+ NSSize imageSize = [image size];
+ CGPoint imageOffset = {-offset.x, -(imageSize.height - offset.y)};
+ CGRect imageRect= CGRectMake(0, 0, imageSize.width, imageSize.height);
+ NSBitmapImageRep *bitmapImage;
+ CoreDragImageSpec imageSpec;
+ CGSRegionObj imageShape;
+ BOOL flipImage;
+ OSStatus error;
+
+ // if the image contains an NSBitmapImageRep, we are done
+ bitmapImage = (NSBitmapImageRep *)[image bestRepresentationForDevice:nil];
+ if (bitmapImage == nil || ![bitmapImage isKindOfClass:[NSBitmapImageRep class]] || !NSEqualSizes([bitmapImage size], imageSize)) {
+ // otherwise we need to render the image and get the bitmap data from it
+ [image lockFocus];
+ bitmapImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect:*(NSRect *)&imageRect];
+ [image unlockFocus];
+
+ // we may have to flip the bits we just read if the iamge was flipped since it means the cache was also
+ // and CoreDragSetImage can't take a transform for rendering.
+ flipImage = [image isFlipped];
+
+ } else {
+ flipImage = NO;
+ [bitmapImage retain];
+ }
+ ASSERT_WITH_MESSAGE(bitmapImage, "dragging image does not contain bitmap");
+
+ imageSpec.version = kCoreDragImageSpecVersionOne;
+ imageSpec.pixelsWide = [bitmapImage pixelsWide];
+ imageSpec.pixelsHigh = [bitmapImage pixelsHigh];
+ imageSpec.bitsPerSample = [bitmapImage bitsPerSample];
+ imageSpec.samplesPerPixel = [bitmapImage samplesPerPixel];
+ imageSpec.bitsPerPixel = [bitmapImage bitsPerPixel];
+ imageSpec.bytesPerRow = [bitmapImage bytesPerRow];
+ imageSpec.isPlanar = [bitmapImage isPlanar];
+ imageSpec.hasAlpha = [bitmapImage hasAlpha];
+ [bitmapImage getBitmapDataPlanes:(unsigned char **)imageSpec.data];
+
+ // if image was flipped, we have an upside down bitmap since the cache is rendered flipped
+ //
+ if (flipImage) {
+ FlipImageSpec(&imageSpec);
+ }
+
+ error = CGSNewRegionWithRect(&imageRect, &imageShape);
+ ASSERT_WITH_MESSAGE(error == kCGErrorSuccess, "Error getting shape for image: %d", error);
+ if (error != kCGErrorSuccess) {
+ [bitmapImage release];
+ return;
+ }
+
+ // make sure image has integer offset
+ //
+ imageOffset.x = floor(imageOffset.x + 0.5);
+ imageOffset.y = floor(imageOffset.y + 0.5);
+
+ // TODO: what is overallAlpha for window?
+ error = CoreDragSetImage(CoreDragGetCurrentDrag(), imageOffset, &imageSpec, imageShape, 1.0);
+ CGSReleaseRegion(imageShape);
+ ASSERT_WITH_MESSAGE(error == kCGErrorSuccess, "Error setting image for drag: %d", error);
+
+ [bitmapImage release];
+
+ // Hack: This incantation is how you post a flags-changed event through CG. In this case we're
+ // saying that the CAPSLOCK key was released, which doesn't seem to effect anything. We post it
+ // to wake up the NSDragManager, which is sitting in a nextEvent call up the stack from us because
+ // the CF drag manager is too lame to use the RunLoop by itself. If we're lucky for Tiger we can
+ // get the AppKit to listen for a completely innocuous event, which we can then post instead.
+ CGPostKeyboardEvent(0, 57, false);
+}
+
+
@end
diff --git a/WebKit/WebView.subproj/WebHTMLView.m b/WebKit/WebView.subproj/WebHTMLView.m
index f16a7a7..7bb56f9 100644
--- a/WebKit/WebView.subproj/WebHTMLView.m
+++ b/WebKit/WebView.subproj/WebHTMLView.m
@@ -51,9 +51,6 @@
#import <CoreGraphics/CGContextGState.h>
-#import <HIServices/CoreDrag.h>
-#import <HIServices/CoreDragPriv.h>
-
#define TextDragDelay 0.15
// By imaging to a width a little wider than the available pixels,
@@ -909,95 +906,6 @@ static WebHTMLView *lastHitView = nil;
return YES;
}
-static void FlipImageSpec(CoreDragImageSpec* imageSpec) {
- // run through and swap each row. we'll need a temporary row to hold the swapped row
- //
- unsigned char* tempRow = malloc(imageSpec->bytesPerRow);
- int planes = imageSpec->isPlanar ? imageSpec->samplesPerPixel : 1;
-
- int p;
- for (p = 0; p < planes; p++) {
- unsigned char* topRow = (unsigned char*)imageSpec->data[p];
- unsigned char* botRow = topRow + (imageSpec->pixelsHigh - 1) * imageSpec->bytesPerRow;
- int i;
- for (i = 0; i < imageSpec->pixelsHigh / 2; i++, topRow += imageSpec->bytesPerRow, botRow -= imageSpec->bytesPerRow) {
- bcopy(topRow, tempRow, imageSpec->bytesPerRow);
- bcopy(botRow, topRow, imageSpec->bytesPerRow);
- bcopy(tempRow, botRow, imageSpec->bytesPerRow);
- }
- }
- free(tempRow);
-}
-
-// Dashboard wants to set the drag image during dragging, but Cocoa does not allow this. Instead we drop
-// down to the CG API. Converting an NSImage to a CGImageSpec is copied from NSDragManager.
-- (void)_setDraggingImage:(NSImage *)image at:(NSPoint)offset
-{
- NSSize imageSize = [image size];
- CGPoint imageOffset = {-offset.x, -(imageSize.height - offset.y)};
- CGRect imageRect= CGRectMake(0, 0, imageSize.width, imageSize.height);
- NSBitmapImageRep *bitmapImage;
- CoreDragImageSpec imageSpec;
- CGSRegionObj imageShape;
- BOOL flipImage;
- OSStatus error;
-
- // if the image contains an NSBitmapImageRep, we are done
- bitmapImage = (NSBitmapImageRep *)[image bestRepresentationForDevice:nil];
- if (bitmapImage == nil || ![bitmapImage isKindOfClass:[NSBitmapImageRep class]] || !NSEqualSizes([bitmapImage size], imageSize)) {
- // otherwise we need to render the image and get the bitmap data from it
- [image lockFocus];
- bitmapImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect:*(NSRect *)&imageRect];
- [image unlockFocus];
-
- // we may have to flip the bits we just read if the iamge was flipped since it means the cache was also
- // and CoreDragSetImage can't take a transform for rendering.
- flipImage = [image isFlipped];
-
- } else {
- flipImage = NO;
- [bitmapImage retain];
- }
- ASSERT_WITH_MESSAGE(bitmapImage, "dragging image does not contain bitmap");
-
- imageSpec.version = kCoreDragImageSpecVersionOne;
- imageSpec.pixelsWide = [bitmapImage pixelsWide];
- imageSpec.pixelsHigh = [bitmapImage pixelsHigh];
- imageSpec.bitsPerSample = [bitmapImage bitsPerSample];
- imageSpec.samplesPerPixel = [bitmapImage samplesPerPixel];
- imageSpec.bitsPerPixel = [bitmapImage bitsPerPixel];
- imageSpec.bytesPerRow = [bitmapImage bytesPerRow];
- imageSpec.isPlanar = [bitmapImage isPlanar];
- imageSpec.hasAlpha = [bitmapImage hasAlpha];
- [bitmapImage getBitmapDataPlanes:(unsigned char **)imageSpec.data];
-
- // if image was flipped, we have an upside down bitmap since the cache is rendered flipped
- //
- if (flipImage) {
- FlipImageSpec(&imageSpec);
- }
-
- error = CGSNewRegionWithRect(&imageRect, &imageShape);
- ASSERT_WITH_MESSAGE(error == kCGErrorSuccess, "Error getting shape for image: %d", error);
- if (error != kCGErrorSuccess) {
- [bitmapImage release];
- return;
- }
-
- // make sure image has integer offset
- //
- imageOffset.x = floor(imageOffset.x + 0.5);
- imageOffset.y = floor(imageOffset.y + 0.5);
-
- // TODO: what is overallAlpha for window?
- error = CoreDragSetImage(CoreDragGetCurrentDrag(), imageOffset, &imageSpec, imageShape, 1.0);
- CGSReleaseRegion(imageShape);
- ASSERT_WITH_MESSAGE(error == kCGErrorSuccess, "Error setting image for drag: %d", error);
-
- [bitmapImage release];
-}
-
-
- (void)_handleAutoscrollForMouseDragged:(NSEvent *)event
{
[self autoscroll:event];
diff --git a/WebKit/WebView.subproj/WebHTMLViewPrivate.h b/WebKit/WebView.subproj/WebHTMLViewPrivate.h
index 444bd70..8d042f2 100644
--- a/WebKit/WebView.subproj/WebHTMLViewPrivate.h
+++ b/WebKit/WebView.subproj/WebHTMLViewPrivate.h
@@ -46,7 +46,6 @@
- (NSImage *)_dragImageForLinkElement:(NSDictionary *)element;
- (BOOL)_startDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc operation:(NSDragOperation)op event:(NSEvent *)event sourceIsDHTML:(BOOL)flag DHTMLWroteData:(BOOL)dhtmlWroteData;
-- (void)_setDraggingImage:(NSImage *)dragImage at:(NSPoint)dragLoc;
- (void)_handleAutoscrollForMouseDragged:(NSEvent *)event;
- (BOOL)_mayStartDragWithMouseDragged:(NSEvent *)event;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list