<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[176429] trunk/Source/WebKit2</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/176429">176429</a></dd>
<dt>Author</dt> <dd>bdakin@apple.com</dd>
<dt>Date</dt> <dd>2014-11-20 17:52:41 -0800 (Thu, 20 Nov 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Preview popover needs minimum and maximum sizes
https://bugs.webkit.org/show_bug.cgi?id=138943
-and corresponding-
rdar://problem/18904651

Reviewed by Tim Horton.

This patch enforces minimum and maximum popover sizes. If the popover needs to be 
sized up to be above the minimum, it will end up covering some of the 
_hitTestResult, so we should compute a new origin rect based on the original 
event location. 
* UIProcess/mac/WKActionMenuController.h:
* UIProcess/mac/WKActionMenuController.mm:
(-[WKActionMenuController prepareForMenu:withEvent:]):
(-[WKActionMenuController _previewURLFromActionMenu:]):
(-[WKActionMenuController _createPreviewPopover]):
(-[WKActionMenuController largestPopoverSize]):
(-[WKActionMenuController _preferredPopoverSize]):
(-[WKActionMenuController _preferredSizeForPopoverPresentedFromOriginRect:]): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacWKActionMenuControllerh">trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessmacWKActionMenuControllermm">trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (176428 => 176429)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-11-21 00:57:53 UTC (rev 176428)
+++ trunk/Source/WebKit2/ChangeLog        2014-11-21 01:52:41 UTC (rev 176429)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2014-11-20  Beth Dakin  &lt;bdakin@apple.com&gt;
+
+        Preview popover needs minimum and maximum sizes
+        https://bugs.webkit.org/show_bug.cgi?id=138943
+        -and corresponding-
+        rdar://problem/18904651
+
+        Reviewed by Tim Horton.
+
+        This patch enforces minimum and maximum popover sizes. If the popover needs to be 
+        sized up to be above the minimum, it will end up covering some of the 
+        _hitTestResult, so we should compute a new origin rect based on the original 
+        event location. 
+        * UIProcess/mac/WKActionMenuController.h:
+        * UIProcess/mac/WKActionMenuController.mm:
+        (-[WKActionMenuController prepareForMenu:withEvent:]):
+        (-[WKActionMenuController _previewURLFromActionMenu:]):
+        (-[WKActionMenuController _createPreviewPopover]):
+        (-[WKActionMenuController largestPopoverSize]):
+        (-[WKActionMenuController _preferredPopoverSize]):
+        (-[WKActionMenuController _preferredSizeForPopoverPresentedFromOriginRect:]): Deleted.
+
</ins><span class="cx"> 2014-11-20  Conrad Shultz  &lt;conrad_shultz@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clicks on previews can be recognized multiple times
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacWKActionMenuControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.h (176428 => 176429)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.h        2014-11-21 00:57:53 UTC (rev 176428)
+++ trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.h        2014-11-21 01:52:41 UTC (rev 176429)
</span><span class="lines">@@ -61,7 +61,10 @@
</span><span class="cx">     RefPtr&lt;API::Object&gt; _userData;
</span><span class="cx">     _WKActionMenuType _type;
</span><span class="cx">     RetainPtr&lt;NSSharingServicePicker&gt; _sharingServicePicker;
</span><ins>+
</ins><span class="cx">     RetainPtr&lt;NSPopover&gt; _previewPopover;
</span><ins>+    NSPoint _eventLocationInView;
+    NSRect _popoverOriginRect;
</ins><span class="cx"> 
</span><span class="cx">     BOOL _isShowingTextIndicator;
</span><span class="cx">     BOOL _shouldKeepPreviewPopoverOpen;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessmacWKActionMenuControllermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.mm (176428 => 176429)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.mm        2014-11-21 00:57:53 UTC (rev 176428)
+++ trunk/Source/WebKit2/UIProcess/mac/WKActionMenuController.mm        2014-11-21 01:52:41 UTC (rev 176429)
</span><span class="lines">@@ -175,7 +175,8 @@
</span><span class="cx"> 
</span><span class="cx">     [self dismissActionMenuPopovers];
</span><span class="cx"> 
</span><del>-    _page-&gt;performActionMenuHitTestAtLocation([_wkView convertPoint:event.locationInWindow fromView:nil]);
</del><ins>+    _eventLocationInView = [_wkView convertPoint:event.locationInWindow fromView:nil];
+    _page-&gt;performActionMenuHitTestAtLocation(_eventLocationInView);
</ins><span class="cx"> 
</span><span class="cx">     _state = ActionMenuState::Pending;
</span><span class="cx">     [self _updateActionMenuItems];
</span><span class="lines">@@ -330,17 +331,16 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;WebHitTestResult&gt; hitTestResult = [self _webHitTestResult];
</span><del>-    NSRect originRect = hitTestResult-&gt;elementBoundingBox();
-    [_previewPopover showRelativeToRect:originRect ofView:_wkView preferredEdge:NSMaxYEdge];
</del><ins>+    [_previewPopover showRelativeToRect:_popoverOriginRect ofView:_wkView preferredEdge:NSMaxYEdge];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_createPreviewPopover
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;WebHitTestResult&gt; hitTestResult = [self _webHitTestResult];
</span><span class="cx">     NSURL *url = [NSURL _web_URLWithWTFString:hitTestResult-&gt;absoluteLinkURL()];
</span><del>-    NSRect originRect = hitTestResult-&gt;elementBoundingBox();
</del><ins>+    _popoverOriginRect = hitTestResult-&gt;elementBoundingBox();
</ins><span class="cx"> 
</span><del>-    NSSize popoverSize = [self _preferredSizeForPopoverPresentedFromOriginRect:originRect];
</del><ins>+    NSSize popoverSize = [self _preferredPopoverSize];
</ins><span class="cx">     CGFloat actualPopoverToViewScale = popoverSize.width / NSWidth(_wkView.bounds);
</span><span class="cx">     _previewViewController = adoptNS([[WKPagePreviewViewController alloc] initWithPageURL:url mainViewSize:_wkView.bounds.size popoverToViewScale:actualPopoverToViewScale]);
</span><span class="cx">     _previewViewController-&gt;_delegate = self;
</span><span class="lines">@@ -358,32 +358,59 @@
</span><span class="cx">     return targetSize.width &lt;= availableSpace.width &amp;&amp; targetSize.height &lt;= availableSpace.height;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (NSSize)_preferredSizeForPopoverPresentedFromOriginRect:(NSRect)originRect
</del><ins>+- (NSSize)largestPopoverSize
</ins><span class="cx"> {
</span><ins>+    NSSize screenSize = [[NSScreen mainScreen] frame].size;
+
+    if (screenSize.width == 1280 &amp;&amp; screenSize.height == 800)
+        return NSMakeSize(1240, 674);
+
+    if (screenSize.width == 1366 &amp;&amp; screenSize.height == 768)
+        return NSMakeSize(1264, 642);
+
+    if (screenSize.width == 1440 &amp;&amp; screenSize.height == 900)
+        return NSMakeSize(1264, 760);
+
+    if (screenSize.width == 1680 &amp;&amp; screenSize.height == 1050)
+        return NSMakeSize(1324, 910);
+
+    return NSMakeSize(1324, 940);
+}
+
+- (NSSize)_preferredPopoverSize
+{
</ins><span class="cx">     static const CGFloat preferredPopoverToViewScale = 0.75;
</span><span class="cx">     static const CGFloat screenPadding = 40;
</span><ins>+    static const NSSize smallestPopoverSize = NSMakeSize(500, 300);
</ins><span class="cx"> 
</span><span class="cx">     NSWindow *window = _wkView.window;
</span><del>-    NSRect originScreenRect = [window convertRectToScreen:[_wkView convertRect:originRect toView:nil]];
</del><ins>+    NSRect originScreenRect = [window convertRectToScreen:[_wkView convertRect:_popoverOriginRect toView:nil]];
</ins><span class="cx">     NSRect screenFrame = window.screen.visibleFrame;
</span><span class="cx"> 
</span><span class="cx">     NSRect wkViewBounds = _wkView.bounds;
</span><span class="cx">     NSSize targetSize = NSMakeSize(NSWidth(wkViewBounds) * preferredPopoverToViewScale, NSHeight(wkViewBounds) * preferredPopoverToViewScale);
</span><ins>+    NSSize largestPopoverSize = [self largestPopoverSize];
</ins><span class="cx"> 
</span><span class="cx">     CGFloat availableSpaceAbove = NSMaxY(screenFrame) - NSMaxY(originScreenRect);
</span><span class="cx">     CGFloat availableSpaceBelow = NSMinY(originScreenRect) - NSMinY(screenFrame);
</span><span class="cx">     CGFloat maxAvailableVerticalSpace = fmax(availableSpaceAbove, availableSpaceBelow) - screenPadding;
</span><span class="cx">     NSSize maxSpaceAvailableOnYEdge = NSMakeSize(screenFrame.size.width - screenPadding, maxAvailableVerticalSpace);
</span><del>-    if (targetSizeFitsInAvailableSpace(targetSize, maxSpaceAvailableOnYEdge))
</del><ins>+    if (targetSizeFitsInAvailableSpace(targetSize, maxSpaceAvailableOnYEdge) &amp;&amp; targetSizeFitsInAvailableSpace(targetSize, largestPopoverSize))
</ins><span class="cx">         return targetSize;
</span><span class="cx"> 
</span><span class="cx">     CGFloat availableSpaceAtLeft = NSMinX(originScreenRect) - NSMinX(screenFrame);
</span><span class="cx">     CGFloat availableSpaceAtRight = NSMaxX(screenFrame) - NSMaxX(originScreenRect);
</span><span class="cx">     CGFloat maxAvailableHorizontalSpace = fmax(availableSpaceAtLeft, availableSpaceAtRight) - screenPadding;
</span><span class="cx">     NSSize maxSpaceAvailableOnXEdge = NSMakeSize(maxAvailableHorizontalSpace, screenFrame.size.height - screenPadding);
</span><del>-    if (targetSizeFitsInAvailableSpace(targetSize, maxSpaceAvailableOnXEdge))
</del><ins>+    if (targetSizeFitsInAvailableSpace(targetSize, maxSpaceAvailableOnXEdge) &amp;&amp; targetSizeFitsInAvailableSpace(targetSize, largestPopoverSize))
</ins><span class="cx">         return targetSize;
</span><span class="cx"> 
</span><ins>+    // Adjust the maximum space available if it is larger than the largest popover size.
+    if (maxSpaceAvailableOnYEdge.width &gt; largestPopoverSize.width &amp;&amp; maxSpaceAvailableOnYEdge.height &gt; largestPopoverSize.height)
+        maxSpaceAvailableOnYEdge = largestPopoverSize;
+    if (maxSpaceAvailableOnXEdge.width &gt; largestPopoverSize.width &amp;&amp; maxSpaceAvailableOnXEdge.height &gt; largestPopoverSize.height)
+        maxSpaceAvailableOnXEdge = largestPopoverSize;
+
</ins><span class="cx">     // If the target size doesn't fit anywhere, we'll find the largest rect that does fit that also maintains the original view's aspect ratio.
</span><span class="cx">     CGFloat aspectRatio = wkViewBounds.size.width / wkViewBounds.size.height;
</span><span class="cx">     FloatRect maxVerticalTargetSizePreservingAspectRatioRect = largestRectWithAspectRatioInsideRect(aspectRatio, FloatRect(0, 0, maxSpaceAvailableOnYEdge.width, maxSpaceAvailableOnYEdge.height));
</span><span class="lines">@@ -392,9 +419,26 @@
</span><span class="cx">     NSSize maxVerticalTargetSizePreservingAspectRatio = NSMakeSize(maxVerticalTargetSizePreservingAspectRatioRect.width(), maxVerticalTargetSizePreservingAspectRatioRect.height());
</span><span class="cx">     NSSize maxHortizontalTargetSizePreservingAspectRatio = NSMakeSize(maxHorizontalTargetSizePreservingAspectRatioRect.width(), maxHorizontalTargetSizePreservingAspectRatioRect.height());
</span><span class="cx"> 
</span><ins>+    NSSize computedTargetSize;
</ins><span class="cx">     if ((maxVerticalTargetSizePreservingAspectRatio.width * maxVerticalTargetSizePreservingAspectRatio.height) &gt; (maxHortizontalTargetSizePreservingAspectRatio.width * maxHortizontalTargetSizePreservingAspectRatio.height))
</span><del>-        return maxVerticalTargetSizePreservingAspectRatio;
-    return maxHortizontalTargetSizePreservingAspectRatio;
</del><ins>+        computedTargetSize = maxVerticalTargetSizePreservingAspectRatio;
+    computedTargetSize = maxHortizontalTargetSizePreservingAspectRatio;
+
+    // Now make sure what we've computed isn't too small.
+    if (computedTargetSize.width &lt; smallestPopoverSize.width &amp;&amp; computedTargetSize.height &lt; smallestPopoverSize.height) {
+        float limitWidth = smallestPopoverSize.width &gt; computedTargetSize.width ? smallestPopoverSize.width : computedTargetSize.width;
+        float limitHeight = smallestPopoverSize.height &gt; computedTargetSize.height ? smallestPopoverSize.height : computedTargetSize.height;
+        FloatRect targetRectLargerThanMinSize = largestRectWithAspectRatioInsideRect(aspectRatio, FloatRect(0, 0, limitWidth, limitHeight));
+        computedTargetSize = NSMakeSize(targetRectLargerThanMinSize.size().width(), targetRectLargerThanMinSize.size().height());
+
+        // If our orignal computedTargetSize was so small that we had to get here and make a new computedTargetSize that is
+        // larger than the minimum, then the elementBoundingBox of the _hitTestResult is probably huge. So we should use
+        // the event origin as the popover origin in this case and not worry about obscuring the _hitTestResult.
+        _popoverOriginRect.origin = _eventLocationInView;
+        _popoverOriginRect.size = NSMakeSize(1, 1);
+    }
+
+    return computedTargetSize;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // WK_API_ENABLED
</span></span></pre>
</div>
</div>

</body>
</html>