summaryrefslogtreecommitdiffstats
path: root/WebKit/mac/Misc/WebNSViewExtras.m
diff options
context:
space:
mode:
authorUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
committerUpstream <upstream-import@none>1970-01-12 13:46:40 +0000
commitd8543bb6618c17b12da906afa77d216f58cf4058 (patch)
treec58dc05ed86825bd0ef8d305d58c8205106b540f /WebKit/mac/Misc/WebNSViewExtras.m
downloadexternal_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.zip
external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.gz
external_webkit-d8543bb6618c17b12da906afa77d216f58cf4058.tar.bz2
external/webkit r30707
Diffstat (limited to 'WebKit/mac/Misc/WebNSViewExtras.m')
-rw-r--r--WebKit/mac/Misc/WebNSViewExtras.m243
1 files changed, 243 insertions, 0 deletions
diff --git a/WebKit/mac/Misc/WebNSViewExtras.m b/WebKit/mac/Misc/WebNSViewExtras.m
new file mode 100644
index 0000000..70ff68a
--- /dev/null
+++ b/WebKit/mac/Misc/WebNSViewExtras.m
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebKit/WebNSViewExtras.h>
+
+#import <WebKit/DOMExtensions.h>
+#import <WebKit/WebDataSource.h>
+#import <WebKit/WebFramePrivate.h>
+#import <WebKit/WebFrameViewInternal.h>
+#import <WebKit/WebNSImageExtras.h>
+#import <WebKit/WebNSPasteboardExtras.h>
+#import <WebKit/WebNSURLExtras.h>
+#import <WebKit/WebView.h>
+
+#define WebDragStartHysteresisX 5.0f
+#define WebDragStartHysteresisY 5.0f
+#define WebMaxDragImageSize NSMakeSize(400.0f, 400.0f)
+#define WebMaxOriginalImageArea (1500.0f * 1500.0f)
+#define WebDragIconRightInset 7.0f
+#define WebDragIconBottomInset 3.0f
+
+@implementation NSView (WebExtras)
+
+- (NSView *)_web_superviewOfClass:(Class)class
+{
+ NSView *view = [self superview];
+ while (view && ![view isKindOfClass:class])
+ view = [view superview];
+ return view;
+}
+
+- (WebFrameView *)_web_parentWebFrameView
+{
+ return (WebFrameView *)[self _web_superviewOfClass:[WebFrameView class]];
+}
+
+// FIXME: Mail is the only client of _webView, remove this method once no versions of Mail need it.
+- (WebView *)_webView
+{
+ return (WebView *)[self _web_superviewOfClass:[WebView class]];
+}
+
+/* Determine whether a mouse down should turn into a drag; started as copy of NSTableView code */
+- (BOOL)_web_dragShouldBeginFromMouseDown:(NSEvent *)mouseDownEvent
+ withExpiration:(NSDate *)expiration
+ xHysteresis:(float)xHysteresis
+ yHysteresis:(float)yHysteresis
+{
+ NSEvent *nextEvent, *firstEvent, *dragEvent, *mouseUp;
+ BOOL dragIt;
+
+ if ([mouseDownEvent type] != NSLeftMouseDown) {
+ return NO;
+ }
+
+ nextEvent = nil;
+ firstEvent = nil;
+ dragEvent = nil;
+ mouseUp = nil;
+ dragIt = NO;
+
+ while ((nextEvent = [[self window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask)
+ untilDate:expiration
+ inMode:NSEventTrackingRunLoopMode
+ dequeue:YES]) != nil) {
+ if (firstEvent == nil) {
+ firstEvent = nextEvent;
+ }
+
+ if ([nextEvent type] == NSLeftMouseDragged) {
+ float deltax = ABS([nextEvent locationInWindow].x - [mouseDownEvent locationInWindow].x);
+ float deltay = ABS([nextEvent locationInWindow].y - [mouseDownEvent locationInWindow].y);
+ dragEvent = nextEvent;
+
+ if (deltax >= xHysteresis) {
+ dragIt = YES;
+ break;
+ }
+
+ if (deltay >= yHysteresis) {
+ dragIt = YES;
+ break;
+ }
+ } else if ([nextEvent type] == NSLeftMouseUp) {
+ mouseUp = nextEvent;
+ break;
+ }
+ }
+
+ // Since we've been dequeuing the events (If we don't, we'll never see the mouse up...),
+ // we need to push some of the events back on. It makes sense to put the first and last
+ // drag events and the mouse up if there was one.
+ if (mouseUp != nil) {
+ [NSApp postEvent:mouseUp atStart:YES];
+ }
+ if (dragEvent != nil) {
+ [NSApp postEvent:dragEvent atStart:YES];
+ }
+ if (firstEvent != mouseUp && firstEvent != dragEvent) {
+ [NSApp postEvent:firstEvent atStart:YES];
+ }
+
+ return dragIt;
+}
+
+- (BOOL)_web_dragShouldBeginFromMouseDown:(NSEvent *)mouseDownEvent
+ withExpiration:(NSDate *)expiration
+{
+ return [self _web_dragShouldBeginFromMouseDown:mouseDownEvent
+ withExpiration:expiration
+ xHysteresis:WebDragStartHysteresisX
+ yHysteresis:WebDragStartHysteresisY];
+}
+
+
+- (NSDragOperation)_web_dragOperationForDraggingInfo:(id <NSDraggingInfo>)sender
+{
+ if (![NSApp modalWindow] &&
+ ![[self window] attachedSheet] &&
+ [sender draggingSource] != self &&
+ [[sender draggingPasteboard] _web_bestURL]) {
+
+ return NSDragOperationCopy;
+ }
+
+ return NSDragOperationNone;
+}
+
+- (void)_web_DragImageForElement:(DOMElement *)element
+ rect:(NSRect)rect
+ event:(NSEvent *)event
+ pasteboard:(NSPasteboard *)pasteboard
+ source:(id)source
+ offset:(NSPoint *)dragImageOffset
+{
+ NSPoint mouseDownPoint = [self convertPoint:[event locationInWindow] fromView:nil];
+ NSImage *dragImage;
+ NSPoint origin;
+
+ NSImage *image = [element image];
+ if (image != nil && [image size].height * [image size].width <= WebMaxOriginalImageArea) {
+ NSSize originalSize = rect.size;
+ origin = rect.origin;
+
+ dragImage = [[image copy] autorelease];
+ [dragImage setScalesWhenResized:YES];
+ [dragImage setSize:originalSize];
+
+ [dragImage _web_scaleToMaxSize:WebMaxDragImageSize];
+ NSSize newSize = [dragImage size];
+
+ [dragImage _web_dissolveToFraction:WebDragImageAlpha];
+
+ // Properly orient the drag image and orient it differently if it's smaller than the original
+ origin.x = mouseDownPoint.x - (((mouseDownPoint.x - origin.x) / originalSize.width) * newSize.width);
+ origin.y = origin.y + originalSize.height;
+ origin.y = mouseDownPoint.y - (((mouseDownPoint.y - origin.y) / originalSize.height) * newSize.height);
+ } else {
+ // FIXME: This has been broken for a while.
+ // There's no way to get the MIME type for the image from a DOM element.
+ // The old code used WKGetPreferredExtensionForMIMEType([image MIMEType]);
+ NSString *extension = @"";
+ dragImage = [[NSWorkspace sharedWorkspace] iconForFileType:extension];
+ NSSize offset = NSMakeSize([dragImage size].width - WebDragIconRightInset, -WebDragIconBottomInset);
+ origin = NSMakePoint(mouseDownPoint.x - offset.width, mouseDownPoint.y - offset.height);
+ }
+
+ // This is the offset from the lower left corner of the image to the mouse location. Because we
+ // are a flipped view the calculation of Y is inverted.
+ if (dragImageOffset) {
+ dragImageOffset->x = mouseDownPoint.x - origin.x;
+ dragImageOffset->y = origin.y - mouseDownPoint.y;
+ }
+
+ // Per kwebster, offset arg is ignored
+ [self dragImage:dragImage at:origin offset:NSZeroSize event:event pasteboard:pasteboard source:source slideBack:YES];
+}
+
+- (BOOL)_web_firstResponderIsSelfOrDescendantView
+{
+ NSResponder *responder = [[self window] firstResponder];
+ return (responder &&
+ (responder == self ||
+ ([responder isKindOfClass:[NSView class]] && [(NSView *)responder isDescendantOf:self])));
+}
+
+- (NSRect)_web_convertRect:(NSRect)aRect toView:(NSView *)aView
+{
+ // Converting to this view's window; let -convertRect:toView: handle it
+ if (aView == nil)
+ return [self convertRect:aRect toView:nil];
+
+ // This view must be in a window. Do whatever weird thing -convertRect:toView: does in this situation.
+ NSWindow *thisWindow = [self window];
+ if (!thisWindow)
+ return [self convertRect:aRect toView:aView];
+
+ // The other view must be in a window, too.
+ NSWindow *otherWindow = [aView window];
+ if (!otherWindow)
+ return [self convertRect:aRect toView:aView];
+
+ // Convert to this window's coordinates
+ NSRect convertedRect = [self convertRect:aRect toView:nil];
+
+ // Convert to screen coordinates
+ convertedRect.origin = [thisWindow convertBaseToScreen:convertedRect.origin];
+
+ // Convert to other window's coordinates
+ convertedRect.origin = [otherWindow convertScreenToBase:convertedRect.origin];
+
+ // Convert to other view's coordinates
+ convertedRect = [aView convertRect:convertedRect fromView:nil];
+
+ return convertedRect;
+}
+
+@end