<!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>[242567] trunk/Source/WebInspectorUI</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/242567">242567</a></dd>
<dt>Author</dt> <dd>joepeck@webkit.org</dd>
<dt>Date</dt> <dd>2019-03-06 14:28:30 -0800 (Wed, 06 Mar 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: CPU Usage Timeline - Allow clicking a bar in the overview to select a tight time range around it
https://bugs.webkit.org/show_bug.cgi?id=195321

Reviewed by Devin Rousso.

* UserInterface/Models/Timeline.js:
(WI.Timeline.prototype.closestRecordTo):
Helper to get the closest record to a timestamp.

* UserInterface/Views/CPUTimelineOverviewGraph.css:
(.timeline-overview-graph.cpu > .stacked-column-chart):
(.timeline-overview-graph.cpu > .stacked-column-chart > svg > rect.selected):
Style a selected record with the active color.

* UserInterface/Views/CPUTimelineOverviewGraph.js:
(WI.CPUTimelineOverviewGraph):
(WI.CPUTimelineOverviewGraph.prototype.get samplingRatePerSecond):
(WI.CPUTimelineOverviewGraph.prototype.reset):
(WI.CPUTimelineOverviewGraph.prototype.layout):
(WI.CPUTimelineOverviewGraph.prototype.updateSelectedRecord):
(WI.CPUTimelineOverviewGraph.prototype._graphPositionForMouseEvent):
(WI.CPUTimelineOverviewGraph.prototype._handleGraphMouseClick):
A click in the overview which hits a rect triggers a selection of
the associated timeline record.

* UserInterface/Views/StackedColumnChart.js:
(WI.StackedColumnChart.prototype.addColumnSet):
(WI.StackedColumnChart.prototype.layout):
Allow setting an additional class name with a column set.
It will set the class name on each rect in that column.

* UserInterface/Views/TimelineOverview.js:
(WI.TimelineOverview.prototype._recordSelected):
When selecting a CPU record, make a selection range of 2 neighboring
columns in each direction.

* UserInterface/Views/TimelineRuler.js:
(WI.TimelineRuler.prototype._handleClick):
When a sub-element has handled the click stop further event propagation.

* UserInterface/Views/TimelineOverviewGraph.js:
(WI.TimelineOverviewGraph.prototype.get selected):
Drive-by style fix.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceModelsTimelinejs">trunk/Source/WebInspectorUI/UserInterface/Models/Timeline.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCPUTimelineOverviewGraphcss">trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsCPUTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsStackedColumnChartjs">trunk/Source/WebInspectorUI/UserInterface/Views/StackedColumnChart.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineOverviewjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverview.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineOverviewGraphjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverviewGraph.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineRecordBarjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineRulerjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRuler.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog    2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/ChangeLog       2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -1,5 +1,51 @@
</span><span class="cx"> 2019-03-06  Joseph Pecoraro  <pecoraro@apple.com>
</span><span class="cx"> 
</span><ins>+        Web Inspector: CPU Usage Timeline - Allow clicking a bar in the overview to select a tight time range around it
+        https://bugs.webkit.org/show_bug.cgi?id=195321
+
+        Reviewed by Devin Rousso.
+
+        * UserInterface/Models/Timeline.js:
+        (WI.Timeline.prototype.closestRecordTo):
+        Helper to get the closest record to a timestamp.
+
+        * UserInterface/Views/CPUTimelineOverviewGraph.css:
+        (.timeline-overview-graph.cpu > .stacked-column-chart):
+        (.timeline-overview-graph.cpu > .stacked-column-chart > svg > rect.selected):
+        Style a selected record with the active color.
+
+        * UserInterface/Views/CPUTimelineOverviewGraph.js:
+        (WI.CPUTimelineOverviewGraph):
+        (WI.CPUTimelineOverviewGraph.prototype.get samplingRatePerSecond):
+        (WI.CPUTimelineOverviewGraph.prototype.reset):
+        (WI.CPUTimelineOverviewGraph.prototype.layout):
+        (WI.CPUTimelineOverviewGraph.prototype.updateSelectedRecord):
+        (WI.CPUTimelineOverviewGraph.prototype._graphPositionForMouseEvent):
+        (WI.CPUTimelineOverviewGraph.prototype._handleGraphMouseClick):
+        A click in the overview which hits a rect triggers a selection of
+        the associated timeline record.
+
+        * UserInterface/Views/StackedColumnChart.js:
+        (WI.StackedColumnChart.prototype.addColumnSet):
+        (WI.StackedColumnChart.prototype.layout):
+        Allow setting an additional class name with a column set.
+        It will set the class name on each rect in that column.
+
+        * UserInterface/Views/TimelineOverview.js:
+        (WI.TimelineOverview.prototype._recordSelected):
+        When selecting a CPU record, make a selection range of 2 neighboring
+        columns in each direction.
+
+        * UserInterface/Views/TimelineRuler.js:
+        (WI.TimelineRuler.prototype._handleClick):
+        When a sub-element has handled the click stop further event propagation.
+
+        * UserInterface/Views/TimelineOverviewGraph.js:
+        (WI.TimelineOverviewGraph.prototype.get selected):
+        Drive-by style fix.
+
+2019-03-06  Joseph Pecoraro  <pecoraro@apple.com>
+
</ins><span class="cx">         Web Inspector: TimelineOverview clicks do not always behave as expected
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=195319
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceModelsTimelinejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Timeline.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Models/Timeline.js     2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Timeline.js        2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -93,6 +93,24 @@
</span><span class="cx">         this.dispatchEventToListeners(WI.Timeline.Event.Refreshed);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    closestRecordTo(timestamp)
+    {
+        let lowerIndex = this._records.lowerBound(timestamp, (time, record) => time - record.endTime);
+
+        let recordBefore = this._records[lowerIndex - 1];
+        let recordAfter = this._records[lowerIndex];
+        if (!recordBefore && !recordAfter)
+            return null;
+        if (!recordBefore && recordAfter)
+            return recordAfter;
+        if (!recordAfter && recordBefore)
+            return recordBefore;
+
+        let before = Math.abs(recordBefore.endTime - timestamp);
+        let after = Math.abs(recordAfter.startTime - timestamp);
+        return (before < after) ? recordBefore : recordAfter;
+    }
+
</ins><span class="cx">     recordsOverlappingTimeRange(startTime, endTime)
</span><span class="cx">     {
</span><span class="cx">         let lowerIndex = this._records.lowerBound(startTime, (time, record) => time - record.endTime);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCPUTimelineOverviewGraphcss"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.css (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.css     2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.css        2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -74,6 +74,13 @@
</span><span class="cx">     fill: var(--cpu-worker-thread-fill-color);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+.timeline-overview-graph.cpu > .stacked-column-chart > svg > rect.selected {
+    fill: var(--selected-background-color) !important;
+    fill-opacity: 0.5;
+    stroke: var(--selected-background-color-active) !important;
+    stroke-opacity: 0.8;
+}
+
</ins><span class="cx"> /* LegacyCPUTimeline */
</span><span class="cx"> .timeline-overview-graph.cpu > .column-chart > svg > rect {
</span><span class="cx">     stroke: var(--cpu-stroke-color);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsCPUTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.js      2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.js 2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -46,12 +46,24 @@
</span><span class="cx">         this.addSubview(this._chart);
</span><span class="cx">         this.element.appendChild(this._chart.element);
</span><span class="cx"> 
</span><ins>+        this._chart.element.addEventListener("click", this._handleChartClick.bind(this));
+
</ins><span class="cx">         this._legendElement = this.element.appendChild(document.createElement("div"));
</span><span class="cx">         this._legendElement.classList.add("legend");
</span><span class="cx"> 
</span><ins>+        this._lastSelectedRecordInLayout = null;
+
</ins><span class="cx">         this.reset();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Static
+
+    static get samplingRatePerSecond()
+    {
+        // 500ms. This matches the ResourceUsageThread sampling frequency in the backend.
+        return 0.5;
+    }
+
</ins><span class="cx">     // Protected
</span><span class="cx"> 
</span><span class="cx">     get height()
</span><span class="lines">@@ -65,6 +77,7 @@
</span><span class="cx"> 
</span><span class="cx">         this._maxUsage = 0;
</span><span class="cx">         this._cachedMaxUsage = undefined;
</span><ins>+        this._lastSelectedRecordInLayout = null;
</ins><span class="cx"> 
</span><span class="cx">         this._updateLegend();
</span><span class="cx">         this._chart.clear();
</span><span class="lines">@@ -83,6 +96,8 @@
</span><span class="cx">         if (isNaN(graphWidth))
</span><span class="cx">             return;
</span><span class="cx"> 
</span><ins>+        this._lastSelectedRecordInLayout = this.selectedRecord;
+
</ins><span class="cx">         if (this._chart.size.width !== graphWidth || this._chart.size.height !== this.height)
</span><span class="cx">             this._chart.size = new WI.Size(graphWidth, this.height);
</span><span class="cx"> 
</span><span class="lines">@@ -91,9 +106,6 @@
</span><span class="cx">         let secondsPerPixel = this.timelineOverview.secondsPerPixel;
</span><span class="cx">         let maxCapacity = Math.max(20, this._maxUsage * 1.05); // Add 5% for padding.
</span><span class="cx"> 
</span><del>-        // 500ms. This matches the ResourceUsageThread sampling frequency in the backend.
-        const samplingRatePerSecond = 0.5;
-
</del><span class="cx">         function xScale(time) {
</span><span class="cx">             return (time - graphStartTime) / secondsPerPixel;
</span><span class="cx">         }
</span><span class="lines">@@ -104,7 +116,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         const includeRecordBeforeStart = true;
</span><del>-        let visibleRecords = this._cpuTimeline.recordsInTimeRange(graphStartTime, visibleEndTime + (samplingRatePerSecond / 2), includeRecordBeforeStart);
</del><ins>+        let visibleRecords = this._cpuTimeline.recordsInTimeRange(graphStartTime, visibleEndTime + (CPUTimelineOverviewGraph.samplingRatePerSecond / 2), includeRecordBeforeStart);
</ins><span class="cx">         if (!visibleRecords.length)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><span class="lines">@@ -112,7 +124,7 @@
</span><span class="cx">             return yScale(record.usage);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        let intervalWidth = (samplingRatePerSecond / secondsPerPixel);
</del><ins>+        let intervalWidth = (CPUTimelineOverviewGraph.samplingRatePerSecond / secondsPerPixel);
</ins><span class="cx">         const minimumDisplayHeight = 4;
</span><span class="cx"> 
</span><span class="cx">         // Bars for each record.
</span><span class="lines">@@ -119,16 +131,29 @@
</span><span class="cx">         for (let record of visibleRecords) {
</span><span class="cx">             let w = intervalWidth;
</span><span class="cx">             let h3 = Math.max(minimumDisplayHeight, yScale(record.usage));
</span><del>-            let x = xScale(record.startTime - (samplingRatePerSecond / 2));
</del><ins>+            let x = xScale(record.startTime - (CPUTimelineOverviewGraph.samplingRatePerSecond / 2));
</ins><span class="cx">             if (WI.settings.experimentalEnableCPUUsageEnhancements.value) {
</span><ins>+                let additionalClass = record === this.selectedRecord ? "selected" : undefined;
</ins><span class="cx">                 let h1 = Math.max(minimumDisplayHeight, yScale(record.mainThreadUsage));
</span><span class="cx">                 let h2 = Math.max(minimumDisplayHeight, yScale(record.mainThreadUsage + record.workerThreadUsage));
</span><del>-                this._chart.addColumnSet(x, height, w, [h1, h2, h3]);
</del><ins>+                this._chart.addColumnSet(x, height, w, [h1, h2, h3], additionalClass);
</ins><span class="cx">             } else
</span><span class="cx">                 this._chart.addColumn(x, height - h3, w, h3);
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    updateSelectedRecord()
+    {
+        super.updateSelectedRecord();
+
+        if (this._lastSelectedRecordInLayout !== this.selectedRecord) {
+            // Since we don't have the exact element to re-style with a selected appearance
+            // we trigger another layout to re-layout the graph and provide additional
+            // styles for the column for the selected record.
+            this.needsLayout();
+        }
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _updateLegend()
</span><span class="lines">@@ -147,6 +172,48 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    _graphPositionForMouseEvent(event)
+    {
+        // Only trigger if clicking on a rect, not anywhere in the graph.
+        let elements = document.elementsFromPoint(event.pageX, event.pageY);
+        let rectElement = elements.find((x) => x.localName === "rect");
+        if (!rectElement)
+            return NaN;
+
+        let chartElement = rectElement.closest(".stacked-column-chart");
+        if (!chartElement)
+            return NaN;
+
+        let rect = chartElement.getBoundingClientRect();
+        let position = event.pageX - rect.left;
+
+        if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL)
+            return rect.width - position;
+        return position;
+    }
+
+    _handleChartClick(event)
+    {
+        let position = this._graphPositionForMouseEvent(event);
+        if (isNaN(position))
+            return;
+
+        let secondsPerPixel = this.timelineOverview.secondsPerPixel;
+        let graphClickTime = position * secondsPerPixel;
+        let graphStartTime = this.startTime;
+
+        let clickTime = graphStartTime + graphClickTime;
+        let record = this._cpuTimeline.closestRecordTo(clickTime);
+        if (!record)
+            return;
+
+        // Ensure that the container "click" listener added by `WI.TimelineOverview` isn't called.
+        event.__timelineRecordClickEventHandled = true;
+
+        this.selectedRecord = record;
+        this.needsLayout();
+    }
+
</ins><span class="cx">     _cpuTimelineRecordAdded(event)
</span><span class="cx">     {
</span><span class="cx">         let cpuTimelineRecord = event.data.record;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsStackedColumnChartjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/StackedColumnChart.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/StackedColumnChart.js    2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/StackedColumnChart.js       2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -84,11 +84,11 @@
</span><span class="cx">         this._sections = sectionClassNames;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    addColumnSet(x, totalHeight, width, heights)
</del><ins>+    addColumnSet(x, totalHeight, width, heights, additionalClass)
</ins><span class="cx">     {
</span><span class="cx">         console.assert(heights.length === this._sections.length, "Wrong number of sections in columns set", heights.length, this._sections.length);
</span><span class="cx"> 
</span><del>-        this._columns.push({x, totalHeight, width, heights});
</del><ins>+        this._columns.push({x, totalHeight, width, heights, additionalClass});
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     clear()
</span><span class="lines">@@ -107,7 +107,7 @@
</span><span class="cx"> 
</span><span class="cx">         this._svgElement.removeChildren();
</span><span class="cx"> 
</span><del>-        for (let {x, totalHeight, width, heights} of this._columns) {
</del><ins>+        for (let {x, totalHeight, width, heights, additionalClass} of this._columns) {
</ins><span class="cx">             for (let i = heights.length - 1; i >= 0; --i) {
</span><span class="cx">                 let height = heights[i];
</span><span class="cx">                 // Next rect will be identical, skip this one.
</span><span class="lines">@@ -116,6 +116,8 @@
</span><span class="cx">                 let y = totalHeight - height;
</span><span class="cx">                 let rect = this._svgElement.appendChild(createSVGElement("rect"));
</span><span class="cx">                 rect.classList.add(this._sections[i]);
</span><ins>+                if (additionalClass)
+                    rect.classList.add(additionalClass);
</ins><span class="cx">                 rect.setAttribute("width", width);
</span><span class="cx">                 rect.setAttribute("height", height);
</span><span class="cx">                 rect.setAttribute("x", x);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineOverviewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverview.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverview.js      2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverview.js 2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -688,7 +688,7 @@
</span><span class="cx">     _handleGraphsContainerClick(event)
</span><span class="cx">     {
</span><span class="cx">         // Set when a WI.TimelineRecordBar receives the "click" first and is about to be selected.
</span><del>-        if (event.__timelineRecordBarClick)
</del><ins>+        if (event.__timelineRecordClickEventHandled)
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         this._recordSelected(null, null);
</span><span class="lines">@@ -766,7 +766,11 @@
</span><span class="cx">             let startTime = firstRecord instanceof WI.RenderingFrameTimelineRecord ? firstRecord.frameIndex : firstRecord.startTime;
</span><span class="cx">             let endTime = lastRecord instanceof WI.RenderingFrameTimelineRecord ? lastRecord.frameIndex : lastRecord.endTime;
</span><span class="cx"> 
</span><del>-            if (startTime < this.selectionStartTime || endTime > this.selectionStartTime + this.selectionDuration) {
</del><ins>+            if (firstRecord instanceof WI.CPUTimelineRecord) {
+                let selectionPadding = WI.CPUTimelineOverviewGraph.samplingRatePerSecond * 2.25;
+                this.selectionStartTime = startTime - selectionPadding;
+                this.selectionDuration = endTime - startTime + (selectionPadding * 2);
+            } else if (startTime < this.selectionStartTime || endTime > this.selectionStartTime + this.selectionDuration) {
</ins><span class="cx">                 let selectionPadding = this.secondsPerPixel * 10;
</span><span class="cx">                 this.selectionStartTime = startTime - selectionPadding;
</span><span class="cx">                 this.selectionDuration = endTime - startTime + (selectionPadding * 2);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineOverviewGraphjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverviewGraph.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverviewGraph.js 2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineOverviewGraph.js    2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -204,7 +204,10 @@
</span><span class="cx">         return 36;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    get selected() { return this._selected; }
</del><ins>+    get selected()
+    {
+        return this._selected;
+    }
</ins><span class="cx"> 
</span><span class="cx">     set selected(x)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineRecordBarjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js     2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.js        2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -389,7 +389,7 @@
</span><span class="cx">     _handleClick(event)
</span><span class="cx">     {
</span><span class="cx">         // Ensure that the container "click" listener added by `WI.TimelineOverview` isn't called.
</span><del>-        event.__timelineRecordBarClick = true;
</del><ins>+        event.__timelineRecordClickEventHandled = true;
</ins><span class="cx"> 
</span><span class="cx">         if (this._delegate.timelineRecordBarClicked)
</span><span class="cx">             this._delegate.timelineRecordBarClicked(this);
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineRulerjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRuler.js (242566 => 242567)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRuler.js 2019-03-06 22:28:27 UTC (rev 242566)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRuler.js    2019-03-06 22:28:30 UTC (rev 242567)
</span><span class="lines">@@ -774,7 +774,10 @@
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><span class="cx">             // Clone the event to dispatch it on the new element.
</span><del>-            newTarget.dispatchEvent(new event.constructor(event.type, event));
</del><ins>+            let newEvent = new event.constructor(event.type, event);
+            newTarget.dispatchEvent(newEvent);
+            if (newEvent.__timelineRecordClickEventHandled)
+                event.stop();
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>