loleaflet/dist/leaflet.css | 20 +++++- loleaflet/src/core/Socket.js | 5 + loleaflet/src/layer/tile/CalcTileLayer.js | 6 + loleaflet/src/layer/tile/ImpressTileLayer.js | 6 + loleaflet/src/layer/tile/TileLayer.js | 82 +++++++++++++++++++++++---- loleaflet/src/layer/tile/WriterTileLayer.js | 7 +- loleaflet/src/map/handler/Map.Keyboard.js | 8 ++ loolwsd/ClientSession.cpp | 6 + loolwsd/protocol.txt | 4 + 9 files changed, 124 insertions(+), 20 deletions(-)
New commits: commit 459b5e585c36fd4a281d730e45d2a4be95982f37 Author: László Németh <laszlo.nem...@collabora.com> Date: Tue Sep 27 20:29:10 2016 +0200 loleaflet: show latency and other data in tile debugging mode - show best, average, worst, last times of - server ping round trip - times between key press and invalidation message - tile based and total tile update latencies - show data of the last five invalidation: - tilecombine messages, if they exist - otherwise the invalidation message - border of the last five invalidation rectangles - visual fixes: - more transparent red color for better text typing - small letters over tiles with transparent background - black attribution text instead of gray + bottomleft position diff --git a/loleaflet/dist/leaflet.css b/loleaflet/dist/leaflet.css index 2febea3..41c7abd 100644 --- a/loleaflet/dist/leaflet.css +++ b/loleaflet/dist/leaflet.css @@ -410,7 +410,7 @@ a.leaflet-control-buttons:hover:first-child { .leaflet-control-attribution, .leaflet-control-scale-line { padding: 0 5px; - color: #333; + color: #000; } .leaflet-control-attribution a { text-decoration: none; @@ -566,18 +566,30 @@ a.leaflet-control-buttons:hover:first-child { pointer-events: none; } +.debug .leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 0px; + } + .debug .leaflet-popup-content { margin: 1px 1px; - font: 28px/24px Tahoma, Verdana, sans-serif; + font: 9px/8px Tahoma, Verdana, sans-serif; line-height: 1; background: rgba(0, 0, 0, 0); pointer-events: none; } -.debug .leaflet-popup-content-wrapper, +.debug .leaflet-popup-content-wrapper { + background: rgba(255, 255, 255, 0.6); + color: #000; + box-shadow: none; + pointer-events: none; + } + .debug .leaflet-popup-tip { background: rgba(255, 255, 255, 0); - color: #f70; + color: #000; box-shadow: none; pointer-events: none; } diff --git a/loleaflet/src/core/Socket.js b/loleaflet/src/core/Socket.js index e9a64f5..73c54fb 100644 --- a/loleaflet/src/core/Socket.js +++ b/loleaflet/src/core/Socket.js @@ -188,6 +188,11 @@ L.Socket = L.Class.extend({ else if (textMsg.startsWith('error:') && !this._map._docLayer) { this.fail = true; } + else if (textMsg === 'pong' && this._map._docLayer && this._map._docLayer._debug) { + var times = this._map._docLayer._debugTimePING; + var timeText = this._map._docLayer._debugSetTimes(times, +new Date() - times.date); + this._map._docLayer._debugDataPING.setPrefix('Server ping time: ' + timeText); + } else if (textMsg.startsWith('statusindicator:')) { //FIXME: We should get statusindicator when saving too, no? this._map.showBusy(_('Connecting...'), false); diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js b/loleaflet/src/layer/tile/CalcTileLayer.js index a493c7c..c14cd5f 100644 --- a/loleaflet/src/layer/tile/CalcTileLayer.js +++ b/loleaflet/src/layer/tile/CalcTileLayer.js @@ -34,7 +34,7 @@ L.CalcTileLayer = L.TileLayer.extend({ var offset = new L.Point(command.width, command.height); var bottomRightTwips = topLeftTwips.add(offset); if (this._debug) { - this._debugAddInvalidationRectangle(topLeftTwips, bottomRightTwips); + this._debugAddInvalidationRectangle(topLeftTwips, bottomRightTwips, textMsg); } var invalidBounds = new L.Bounds(topLeftTwips, bottomRightTwips); var visibleTopLeft = this._latLngToTwips(this._map.getBounds().getNorthWest()); @@ -69,7 +69,9 @@ L.CalcTileLayer = L.TileLayer.extend({ needsNewTiles = true; if (this._debug && this._tiles[key]._debugTile) { this._tiles[key]._debugTile.setStyle({fillOpacity: 0.5}); + this._tiles[key]._debugTime.date = +new Date(); this._tiles[key]._debugInvalidateCount++; + this._debugInvalidateCount++; } } else { @@ -93,7 +95,7 @@ L.CalcTileLayer = L.TileLayer.extend({ this._map._socket.sendMessage(message, ''); if (this._debug) { - this._debugDataTileCombine.setPrefix(message); + this._debugAddInvalidationMessage(message); } } diff --git a/loleaflet/src/layer/tile/ImpressTileLayer.js b/loleaflet/src/layer/tile/ImpressTileLayer.js index 522ba09..677e592 100644 --- a/loleaflet/src/layer/tile/ImpressTileLayer.js +++ b/loleaflet/src/layer/tile/ImpressTileLayer.js @@ -18,7 +18,7 @@ L.ImpressTileLayer = L.TileLayer.extend({ var offset = new L.Point(command.width, command.height); var bottomRightTwips = topLeftTwips.add(offset); if (this._debug) { - this._debugAddInvalidationRectangle(topLeftTwips, bottomRightTwips); + this._debugAddInvalidationRectangle(topLeftTwips, bottomRightTwips, textMsg); } var invalidBounds = new L.Bounds(topLeftTwips, bottomRightTwips); var visibleTopLeft = this._latLngToTwips(this._map.getBounds().getNorthWest()); @@ -53,7 +53,9 @@ L.ImpressTileLayer = L.TileLayer.extend({ needsNewTiles = true; if (this._debug && this._tiles[key]._debugTile) { this._tiles[key]._debugTile.setStyle({fillOpacity: 0.5}); + this._tiles[key]._debugTime.date = +new Date(); this._tiles[key]._debugInvalidateCount++; + this._debugInvalidateCount++; } } else { @@ -77,7 +79,7 @@ L.ImpressTileLayer = L.TileLayer.extend({ this._map._socket.sendMessage(message, ''); if (this._debug) { - this._debugDataTileCombine.setPrefix(message); + this._debugAddInvalidationMessage(message); } } diff --git a/loleaflet/src/layer/tile/TileLayer.js b/loleaflet/src/layer/tile/TileLayer.js index 3ea0829..62cae49 100644 --- a/loleaflet/src/layer/tile/TileLayer.js +++ b/loleaflet/src/layer/tile/TileLayer.js @@ -384,8 +384,10 @@ L.TileLayer = L.GridLayer.extend({ this._map.removeLayer(this._debugInfo); } if (!this._debug) { + this._debugDataPING.setPrefix(''); this._debugDataCancelledTiles.setPrefix(''); this._debugDataTileCombine.setPrefix(''); + this._debugDataFromKeyInputToInvalidate.setPrefix(''); } this._debugInit(); this._onMessage('invalidatetiles: EMPTY', null); @@ -1000,6 +1002,7 @@ L.TileLayer = L.GridLayer.extend({ if (this._debug && tile) { if (tile._debugLoadCount) { tile._debugLoadCount++; + this._debugLoadCount++; } else { tile._debugLoadCount = 1; tile._debugInvalidateCount = 1; @@ -1007,15 +1010,22 @@ L.TileLayer = L.GridLayer.extend({ if (!tile._debugPopup) { var tileBound = this._keyToBounds(key); tile._debugPopup = L.popup({className: 'debug', offset: new L.Point(0, 0), autoPan: false, closeButton: false, closeOnClick: false}) - .setLatLng(new L.LatLng(tileBound.getSouth(), tileBound.getWest() + (tileBound.getEast() - tileBound.getWest())/4)).setContent('-'); + .setLatLng(new L.LatLng(tileBound.getSouth(), tileBound.getWest() + (tileBound.getEast() - tileBound.getWest())/5)); this._debugInfo.addLayer(tile._debugPopup); tile._debugTile = L.rectangle(tileBound, {color: 'blue', weight: 1, fillOpacity: 0, pointerEvents: 'none'}); + tile._debugTime = this._debugGetTimeArray(); this._debugInfo.addLayer(tile._debugTile); } - tile._debugPopup.setContent('' + this._tiles[key]._debugLoadCount + '/' + this._tiles[key]._debugInvalidateCount); + if (tile._debugTime.date === 0) { + tile._debugPopup.setContent('requested: ' + this._tiles[key]._debugInvalidateCount + '<br>received: ' + this._tiles[key]._debugLoadCount); + } else { + tile._debugPopup.setContent('requested: ' + this._tiles[key]._debugInvalidateCount + '<br>received: ' + this._tiles[key]._debugLoadCount + + '<br>' + this._debugSetTimes(tile._debugTime, +new Date() - tile._debugTime.date).replace(/, /g, '<br>')); + } if (tile._debugTile) { tile._debugTile.setStyle({fillOpacity: 0}); } + this._debugDataLoadCount.setPrefix('Total of requested tiles: ' + this._debugInvalidateCount + ', received: ' + this._debugLoadCount); } if (command.id !== undefined) { this._map.fire('tilepreview', { @@ -1758,28 +1768,76 @@ L.TileLayer = L.GridLayer.extend({ this._clientVisibleArea = true; }, + _debugGetTimeArray: function() { + return {count: 0, ms: 0, best: Number.MAX_SAFE_INTEGER, worst: 0, last: 0, date: 0}; + }, + _debugInit: function() { if (this._debug) { this._debugInfo = new L.LayerGroup(); map.addLayer(this._debugInfo); this._debugInvalidBounds = {}; + this._debugInvalidBoundsMessage = {}; this._debugTimeout(); this._debugId = 0; this._debugCancelledTiles = 0; + this._debugLoadCount = 0; + this._debugInvalidateCount = 0; if (!this._debugDataCancelledTiles) { - this._debugDataTileCombine = L.control.attribution({prefix: '[tilecombine message]'}).addTo(map); - this._debugDataCancelledTiles = L.control.attribution({prefix: 'Cancelled tiles: 0'}).addTo(map); + this._debugDataTileCombine = L.control.attribution({prefix: '', position: 'bottomleft'}).addTo(map); + this._debugDataCancelledTiles = L.control.attribution({prefix: '', position: 'bottomleft'}).addTo(map); + this._debugDataFromKeyInputToInvalidate = L.control.attribution({prefix: '', position: 'bottomleft'}).addTo(map); + this._debugDataPING = L.control.attribution({prefix: '', position: 'bottomleft'}).addTo(map); + this._debugDataLoadCount = L.control.attribution({prefix: '', position: 'bottomleft'}).addTo(map); + } + this._debugTimePING = this._debugGetTimeArray(); + this._debugTimeKeypress = this._debugGetTimeArray(); + this._debugKeypressQueue = []; + } + }, + + _debugSetTimes: function(times, value) { + times.last = value; + if (value < times.best) { + times.best = value; + } + if (value > times.worst) { + times.worst = value; } + times.ms += value; + times.count++; + return 'best: ' + times.best + ' ms, avg: ' + Math.round(times.ms/times.count) + ' ms, worst: ' + times.worst + ' ms, last: ' + value + ' ms'; }, - _debugAddInvalidationRectangle: function(topLeftTwips, bottomRightTwips) { + _debugAddInvalidationRectangle: function(topLeftTwips, bottomRightTwips, command) { + var now = +new Date(); + var invalidBoundCoords = new L.LatLngBounds(this._twipsToLatLng(topLeftTwips, this._tileZoom), this._twipsToLatLng(bottomRightTwips, this._tileZoom)); - var rect = L.rectangle(invalidBoundCoords, {color: 'red', weight: 1, fillOpacity: 0.5, pointerEvents: 'none'}); + var rect = L.rectangle(invalidBoundCoords, {color: 'red', weight: 1, opacity: 1, fillOpacity: 0.4, pointerEvents: 'none'}); this._debugInvalidBounds[this._debugId] = rect; + this._debugInvalidBoundsMessage[this._debugId] = command; this._debugId++; this._debugInfo.addLayer(rect); + + var oldestKeypress = this._debugKeypressQueue.shift(); + if (oldestKeypress) { + var timeText = this._debugSetTimes(this._debugTimeKeypress, now - oldestKeypress); + this._debugDataFromKeyInputToInvalidate.setPrefix('Elapsed time between key input and next invalidate: ' + timeText); + } + }, + + _debugAddInvalidationMessage: function(message) { + this._debugInvalidBoundsMessage[this._debugId - 1] = message; + var messages = ''; + for (var i = this._debugId - 1; i > this._debugId - 6; i--) { + if (i >= 0 && this._debugInvalidBoundsMessage[i]) { + messages += '' + i + ': ' + this._debugInvalidBoundsMessage[i] + ' <br>'; + } + } + this._debugDataTileCombine.setPrefix(messages); + this._debugDataLoadCount.setPrefix('Total of requested tiles: ' + this._debugInvalidateCount + ', received: ' + this._debugLoadCount); }, _debugTimeout: function() { @@ -1787,11 +1845,15 @@ L.TileLayer = L.GridLayer.extend({ for (var key in this._debugInvalidBounds) { var rect = this._debugInvalidBounds[key]; var opac = rect.options.fillOpacity; - if (opac < 0.1) { - this._debugInfo.removeLayer(rect); - delete this._debugInvalidBounds[key]; + if (opac <= 0.04) { + rect.setStyle({fillOpacity: 0}); + if (key < this._debugId - 5) { + this._debugInfo.removeLayer(rect); + delete this._debugInvalidBounds[key]; + delete this._debugInvalidBoundsMessage[key]; + } } else { - rect.setStyle({opacity: opac - 0.05, fillOpacity: opac - 0.05}); + rect.setStyle({fillOpacity: opac - 0.04}); } } this._debugTimeoutId = setTimeout(function () { map._docLayer._debugTimeout() }, 50); diff --git a/loleaflet/src/layer/tile/WriterTileLayer.js b/loleaflet/src/layer/tile/WriterTileLayer.js index 910e9fa..f5299dc 100644 --- a/loleaflet/src/layer/tile/WriterTileLayer.js +++ b/loleaflet/src/layer/tile/WriterTileLayer.js @@ -19,7 +19,7 @@ L.WriterTileLayer = L.TileLayer.extend({ var offset = new L.Point(command.width, command.height); var bottomRightTwips = topLeftTwips.add(offset); if (this._debug) { - this._debugAddInvalidationRectangle(topLeftTwips, bottomRightTwips); + this._debugAddInvalidationRectangle(topLeftTwips, bottomRightTwips, textMsg); } var invalidBounds = new L.Bounds(topLeftTwips, bottomRightTwips); var visibleTopLeft = this._latLngToTwips(this._map.getBounds().getNorthWest()); @@ -52,7 +52,9 @@ L.WriterTileLayer = L.TileLayer.extend({ needsNewTiles = true; if (this._debug && this._tiles[key]._debugTile) { this._tiles[key]._debugTile.setStyle({fillOpacity: 0.5}); + this._tiles[key]._debugTime.date = +new Date(); this._tiles[key]._debugInvalidateCount++; + this._debugInvalidateCount++; } } else { @@ -78,8 +80,9 @@ L.WriterTileLayer = L.TileLayer.extend({ 'tileheight=' + this._tileHeightTwips; this._map._socket.sendMessage(message, ''); + if (this._debug) { - this._debugDataTileCombine.setPrefix(message); + this._debugAddInvalidationMessage(message); } } diff --git a/loleaflet/src/map/handler/Map.Keyboard.js b/loleaflet/src/map/handler/Map.Keyboard.js index 817130c..5872247 100644 --- a/loleaflet/src/map/handler/Map.Keyboard.js +++ b/loleaflet/src/map/handler/Map.Keyboard.js @@ -301,6 +301,7 @@ L.Map.Keyboard = L.Handler.extend({ if (this._map._permission === 'edit') { docLayer._resetPreFetching(); + if (e.type === 'keydown' && this.handleOnKeyDown[keyCode] && charCode === 0) { docLayer._postKeyboardEvent('input', charCode, unoKeyCode); } @@ -312,6 +313,13 @@ L.Map.Keyboard = L.Handler.extend({ keyCode = 0; unoKeyCode = this._toUNOKeyCode(keyCode); } + if (docLayer._debug) { + // query server ping time at key press + this._map._docLayer._debugTimePING.date = +new Date(); + this._map._socket.sendMessage('ping'); + // key press times will be paired with the invalidation messages + docLayer._debugKeypressQueue.push(+new Date()); + } docLayer._postKeyboardEvent('input', charCode, unoKeyCode); } else if (e.type === 'keyup') { commit 9c9c98b89fecb2636dccaeb3df00cef1daa33ab8 Author: László Németh <laszlo.nem...@collabora.com> Date: Tue Sep 27 20:22:09 2016 +0200 loolwsd: add ping support to the protocol The client message 'ping' requests a 'pong' server message. diff --git a/loolwsd/ClientSession.cpp b/loolwsd/ClientSession.cpp index 43d712b..9884178 100644 --- a/loolwsd/ClientSession.cpp +++ b/loolwsd/ClientSession.cpp @@ -114,6 +114,7 @@ bool ClientSession::_handleInput(const char *buffer, int length) tokens[0] != "key" && tokens[0] != "mouse" && tokens[0] != "partpagerectangles" && + tokens[0] != "ping" && tokens[0] != "renderfont" && tokens[0] != "requestloksession" && tokens[0] != "resetselection" && @@ -150,6 +151,11 @@ bool ClientSession::_handleInput(const char *buffer, int length) { return getPartPageRectangles(buffer, length); } + else if (tokens[0] == "ping") + { + sendTextFrame("pong"); + return true; + } else if (tokens[0] == "renderfont") { return sendFontRendering(buffer, length, tokens); diff --git a/loolwsd/protocol.txt b/loolwsd/protocol.txt index 64bdf73..a507a32 100644 --- a/loolwsd/protocol.txt +++ b/loolwsd/protocol.txt @@ -84,6 +84,10 @@ mouse type=<type> x=<x> y=<y> count=<count> <type> is 'buttondown', 'buttonup' or 'move', others are numbers. +ping + + requests a 'pong' server message. + renderfont font=<font> requests the rendering of the given font.
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits