Merge changes from topic "winscope-ui-tweak"
* changes: Added a Favicon for better tab identification Make the timeline size relative to the parent Cleanup the UI for better visibility Move the Video to the top next to the timeline Migrate to new MaterialVue
This commit is contained in:
1
tools/winscope/.gitignore
vendored
1
tools/winscope/.gitignore
vendored
@@ -2,3 +2,4 @@ node_modules/
|
|||||||
adb_proxy/venv/
|
adb_proxy/venv/
|
||||||
.vscode/
|
.vscode/
|
||||||
dist/
|
dist/
|
||||||
|
yarn-error.log
|
||||||
@@ -10,13 +10,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vue": "^2.3.3",
|
"vue": "^2.3.3",
|
||||||
"vue-material": "0.8.1"
|
"vue-material": "^1.0.0-beta-11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.0.0",
|
"babel-core": "^6.0.0",
|
||||||
"babel-loader": "^6.0.0",
|
"babel-loader": "^6.0.0",
|
||||||
"babel-preset-env": "^1.5.1",
|
"babel-preset-env": "^1.5.1",
|
||||||
"cross-env": "^3.0.0",
|
"cross-env": "^7.0.2",
|
||||||
"css-loader": "^0.25.0",
|
"css-loader": "^0.25.0",
|
||||||
"file-loader": "^0.9.0",
|
"file-loader": "^0.9.0",
|
||||||
"html-webpack-inline-source-plugin": "^0.0.9",
|
"html-webpack-inline-source-plugin": "^0.0.9",
|
||||||
|
|||||||
@@ -14,40 +14,73 @@
|
|||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<md-whiteframe md-tag="md-toolbar">
|
<md-app>
|
||||||
|
<md-app-toolbar md-tag="md-toolbar">
|
||||||
<h1 class="md-title" style="flex: 1">{{title}}</h1>
|
<h1 class="md-title" style="flex: 1">{{title}}</h1>
|
||||||
<a class="md-button md-accent md-raised md-theme-default" @click="clear()" v-if="dataLoaded">Clear</a>
|
<md-button
|
||||||
</md-whiteframe>
|
class="md-accent md-raised md-theme-default"
|
||||||
<div class="main-content">
|
@click="clear()"
|
||||||
<md-layout v-if="!dataLoaded" class="m-2">
|
v-if="dataLoaded"
|
||||||
<dataadb ref="adb" :store="store" @dataReady="onDataReady" @statusChange="setStatus"/>
|
>Clear</md-button>
|
||||||
<datainput ref="input" :store="store" @dataReady="onDataReady" @statusChange="setStatus"/>
|
</md-app-toolbar>
|
||||||
</md-layout>
|
<md-app-content class="main-content">
|
||||||
<md-card v-if="dataLoaded">
|
<div class="md-layout m-2" v-if="!dataLoaded">
|
||||||
<md-whiteframe md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
<dataadb ref="adb" :store="store" @dataReady="onDataReady" @statusChange="setStatus" />
|
||||||
<h2 class="md-title">Timeline</h2>
|
<datainput ref="input" :store="store" @dataReady="onDataReady" @statusChange="setStatus" />
|
||||||
|
</div>
|
||||||
|
<div class="md-layout md-alignment-left-center " v-if="dataLoaded">
|
||||||
|
<div class="md-layout-item video" v-if="video">
|
||||||
|
<videoview :file="video" :ref="video.filename" />
|
||||||
|
</div>
|
||||||
|
<div class="md-layout-item">
|
||||||
|
<md-toolbar
|
||||||
|
md-elevation="0"
|
||||||
|
class="md-transparent">
|
||||||
|
<h2 class="md-title">Timeline </h2>
|
||||||
|
<span> {{seekTime}} </span>
|
||||||
<datafilter v-for="file in files" :key="file.filename" :store="store" :file="file" />
|
<datafilter v-for="file in files" :key="file.filename" :store="store" :file="file" />
|
||||||
</md-whiteframe>
|
</md-toolbar>
|
||||||
<md-list>
|
<md-list>
|
||||||
<md-list-item v-for="(file, idx) in files" :key="file.filename">
|
<md-list-item v-for="(file, idx) in files" :key="file.filename">
|
||||||
<md-icon>{{file.type.icon}}</md-icon>
|
<md-icon>
|
||||||
<timeline :items="file.timeline" :selected-index="file.selectedIndex" :scale="scale" @item-selected="onTimelineItemSelected($event, idx)" class="timeline" />
|
{{file.type.icon}}
|
||||||
|
<md-tooltip md-direction="right">{{file.type.name}}</md-tooltip>
|
||||||
|
</md-icon>
|
||||||
|
<timeline
|
||||||
|
:items="file.timeline"
|
||||||
|
:selected-index="file.selectedIndex"
|
||||||
|
:scale="scale"
|
||||||
|
@item-selected="onTimelineItemSelected($event, idx)"
|
||||||
|
class="timeline"
|
||||||
|
/>
|
||||||
</md-list-item>
|
</md-list-item>
|
||||||
</md-list>
|
</md-list>
|
||||||
</md-card>
|
|
||||||
<dataview v-for="file in files" :key="file.filename" :ref="file.filename" :store="store" :file="file" @focus="onDataViewFocus(file.filename)" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<dataview
|
||||||
|
v-for="file in files"
|
||||||
|
:key="file.filename"
|
||||||
|
:ref="file.filename"
|
||||||
|
:store="store"
|
||||||
|
:file="file"
|
||||||
|
@focus="onDataViewFocus(file.filename)"
|
||||||
|
/>
|
||||||
|
</md-app-content>
|
||||||
|
</md-app>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import TreeView from './TreeView.vue'
|
import TreeView from './TreeView.vue'
|
||||||
import Timeline from './Timeline.vue'
|
import Timeline from './Timeline.vue'
|
||||||
import Rects from './Rects.vue'
|
import Rects from './Rects.vue'
|
||||||
import DataView from './DataView.vue'
|
import DataView from './DataView.vue'
|
||||||
|
import VideoView from './VideoView.vue'
|
||||||
import DataInput from './DataInput.vue'
|
import DataInput from './DataInput.vue'
|
||||||
import LocalStore from './localstore.js'
|
import LocalStore from './localstore.js'
|
||||||
import DataAdb from './DataAdb.vue'
|
import DataAdb from './DataAdb.vue'
|
||||||
import DataFilter from './DataFilter.vue'
|
import DataFilter from './DataFilter.vue'
|
||||||
|
import FileType from './FileType.js'
|
||||||
|
import { nanos_to_string } from './transform.js'
|
||||||
|
|
||||||
const APP_NAME = "Winscope"
|
const APP_NAME = "Winscope"
|
||||||
|
|
||||||
@@ -68,9 +101,11 @@ function findLastMatchingSorted(array, predicate) {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'app',
|
name: 'app',
|
||||||
|
mixins: [FileType],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
files: [],
|
files: [],
|
||||||
|
video: null,
|
||||||
title: APP_NAME,
|
title: APP_NAME,
|
||||||
currentTimestamp: 0,
|
currentTimestamp: 0,
|
||||||
activeDataView: null,
|
activeDataView: null,
|
||||||
@@ -143,7 +178,13 @@ export default {
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
onDataReady(files) {
|
onDataReady(files) {
|
||||||
this.files = files;
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i];
|
||||||
|
if (this.isVideo(file)) {
|
||||||
|
this.video = file;
|
||||||
|
}
|
||||||
|
this.files.push(file);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setStatus(status) {
|
setStatus(status) {
|
||||||
if (status) {
|
if (status) {
|
||||||
@@ -151,7 +192,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.title = APP_NAME;
|
this.title = APP_NAME;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
prettyDump: function() { return JSON.stringify(this.dump, null, 2); },
|
prettyDump: function() { return JSON.stringify(this.dump, null, 2); },
|
||||||
@@ -166,6 +207,9 @@ export default {
|
|||||||
this.activeDataView = this.files[0].filename;
|
this.activeDataView = this.files[0].filename;
|
||||||
}
|
}
|
||||||
return this.activeDataView;
|
return this.activeDataView;
|
||||||
|
},
|
||||||
|
seekTime: function() {
|
||||||
|
return nanos_to_string(this.currentTimestamp);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -174,14 +218,14 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
'timeline': Timeline,
|
timeline: Timeline,
|
||||||
'dataview': DataView,
|
dataview: DataView,
|
||||||
'datainput': DataInput,
|
videoview: VideoView,
|
||||||
'dataadb': DataAdb,
|
datainput: DataInput,
|
||||||
'datafilter': DataFilter,
|
dataadb: DataAdb,
|
||||||
},
|
datafilter: DataFilter
|
||||||
}
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.main-content>* {
|
.main-content>* {
|
||||||
@@ -201,14 +245,14 @@ export default {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-layout > .md-card {
|
|
||||||
margin: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-button {
|
.md-button {
|
||||||
margin-top: 1em
|
margin-top: 1em
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.video {
|
||||||
|
flex-grow: 0;
|
||||||
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
h2 {
|
h2 {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@@ -227,5 +271,4 @@ li {
|
|||||||
a {
|
a {
|
||||||
color: #42b983;
|
color: #42b983;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<div class="md-title">ADB Connect</div>
|
<div class="md-title">ADB Connect</div>
|
||||||
</md-card-header>
|
</md-card-header>
|
||||||
<md-card-content v-if="status === STATES.CONNECTING">
|
<md-card-content v-if="status === STATES.CONNECTING">
|
||||||
<md-spinner md-indeterminate></md-spinner>
|
<md-progress-spinner md-indeterminate></md-progress-spinner>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
<md-card-content v-if="status === STATES.NO_PROXY">
|
<md-card-content v-if="status === STATES.NO_PROXY">
|
||||||
<md-icon class="md-accent">error</md-icon>
|
<md-icon class="md-accent">error</md-icon>
|
||||||
@@ -52,10 +52,10 @@
|
|||||||
<md-card-content v-if="status === STATES.UNAUTH">
|
<md-card-content v-if="status === STATES.UNAUTH">
|
||||||
<md-icon class="md-accent">lock</md-icon>
|
<md-icon class="md-accent">lock</md-icon>
|
||||||
<span class="md-subheading">Proxy authorisation required</span>
|
<span class="md-subheading">Proxy authorisation required</span>
|
||||||
<md-input-container>
|
<md-field>
|
||||||
<label>Enter Winscope proxy token</label>
|
<label>Enter Winscope proxy token</label>
|
||||||
<md-input v-model="adbStore.proxyKey"></md-input>
|
<md-input v-model="adbStore.proxyKey"></md-input>
|
||||||
</md-input-container>
|
</md-field>
|
||||||
<div class="md-body-2">The proxy token is printed to console on proxy launch, copy and paste it above.</div>
|
<div class="md-body-2">The proxy token is printed to console on proxy launch, copy and paste it above.</div>
|
||||||
<div class="md-layout md-gutter">
|
<div class="md-layout md-gutter">
|
||||||
<md-button class="md-accent md-raised" @click="restart">Connect</md-button>
|
<md-button class="md-accent md-raised" @click="restart">Connect</md-button>
|
||||||
@@ -65,15 +65,17 @@
|
|||||||
<div class="md-subheading">{{ Object.keys(devices).length > 0 ? "Connected devices:" : "No devices detected" }}</div>
|
<div class="md-subheading">{{ Object.keys(devices).length > 0 ? "Connected devices:" : "No devices detected" }}</div>
|
||||||
<md-list>
|
<md-list>
|
||||||
<md-list-item v-for="(device, id) in devices" :key="id" @click="selectDevice(id)" :disabled="!device.authorised">
|
<md-list-item v-for="(device, id) in devices" :key="id" @click="selectDevice(id)" :disabled="!device.authorised">
|
||||||
<md-icon>{{ device.authorised ? "smartphone" : "screen_lock_portrait" }}</md-icon><span>{{ device.authorised ? device.model : "unauthorised" }} ({{ id }})</span>
|
<md-icon>{{ device.authorised ? "smartphone" : "screen_lock_portrait" }}</md-icon>
|
||||||
|
<span class="md-list-item-text">{{ device.authorised ? device.model : "unauthorised" }} ({{ id }})</span>
|
||||||
</md-list-item>
|
</md-list-item>
|
||||||
</md-list>
|
</md-list>
|
||||||
<md-spinner :md-size="30" md-indeterminate></md-spinner>
|
<md-progress-spinner :md-size="30" md-indeterminate></md-progress-spinner>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
<md-card-content v-if="status === STATES.START_TRACE">
|
<md-card-content v-if="status === STATES.START_TRACE">
|
||||||
<md-list>
|
<md-list>
|
||||||
<md-list-item>
|
<md-list-item>
|
||||||
<md-icon>smartphone</md-icon><span>{{ devices[selectedDevice].model }} ({{ selectedDevice }})</span>
|
<md-icon>smartphone</md-icon>
|
||||||
|
<span class="md-list-item-text">{{ devices[selectedDevice].model }} ({{ selectedDevice }})</span>
|
||||||
</md-list-item>
|
</md-list-item>
|
||||||
</md-list>
|
</md-list>
|
||||||
<div>
|
<div>
|
||||||
@@ -84,7 +86,7 @@
|
|||||||
<p>Dump targets:</p>
|
<p>Dump targets:</p>
|
||||||
<md-checkbox v-for="file in DUMP_FILES" :key="file" v-model="adbStore[file]">{{FILE_TYPES[file].name}}</md-checkbox>
|
<md-checkbox v-for="file in DUMP_FILES" :key="file" v-model="adbStore[file]">{{FILE_TYPES[file].name}}</md-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-layout md-gutter">
|
<div class="md-layout">
|
||||||
<md-button class="md-accent md-raised" @click="startTrace">Start trace</md-button>
|
<md-button class="md-accent md-raised" @click="startTrace">Start trace</md-button>
|
||||||
<md-button class="md-accent md-raised" @click="dumpState">Dump state</md-button>
|
<md-button class="md-accent md-raised" @click="dumpState">Dump state</md-button>
|
||||||
<md-button class="md-raised" @click="resetLastDevice">Device list</md-button>
|
<md-button class="md-raised" @click="resetLastDevice">Device list</md-button>
|
||||||
@@ -100,14 +102,14 @@
|
|||||||
</md-card-content>
|
</md-card-content>
|
||||||
<md-card-content v-if="status === STATES.END_TRACE">
|
<md-card-content v-if="status === STATES.END_TRACE">
|
||||||
<span class="md-subheading">Tracing...</span>
|
<span class="md-subheading">Tracing...</span>
|
||||||
<md-progress md-indeterminate></md-progress>
|
<md-progress-bar md-mode="indeterminate"></md-progress-bar>
|
||||||
<div class="md-layout md-gutter">
|
<div class="md-layout">
|
||||||
<md-button class="md-accent md-raised" @click="endTrace">End trace</md-button>
|
<md-button class="md-accent md-raised" @click="endTrace">End trace</md-button>
|
||||||
</div>
|
</div>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
<md-card-content v-if="status === STATES.LOAD_DATA">
|
<md-card-content v-if="status === STATES.LOAD_DATA">
|
||||||
<span class="md-subheading">Loading data...</span>
|
<span class="md-subheading">Loading data...</span>
|
||||||
<md-progress :md-progress="loadProgress"></md-progress>
|
<md-progress-bar md-mode="determinate" :md-value="loadProgress"></md-progress-bar>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
</md-card>
|
</md-card>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="bounds" v-if="visible">
|
<div class="bounds" v-if="visible">
|
||||||
|
<md-field>
|
||||||
<md-select v-model="visibleTransactions" name="visibleTransactions" id="visibleTransactions"
|
<md-select v-model="visibleTransactions" name="visibleTransactions" id="visibleTransactions"
|
||||||
placeholder="Everything Turned Off" md-dense multiple @input="updateFilter()" >
|
placeholder="Everything Turned Off" md-dense multiple @input="updateFilter()" >
|
||||||
<md-option value="displayCreation, displayDeletion">Display</md-option>
|
<md-option value="displayCreation, displayDeletion">Display</md-option>
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
<md-option value="vsyncEvent">vsync</md-option>
|
<md-option value="vsyncEvent">vsync</md-option>
|
||||||
<md-option value="bufferUpdate">Buffer</md-option>
|
<md-option value="bufferUpdate">Buffer</md-option>
|
||||||
</md-select>
|
</md-select>
|
||||||
|
</md-field>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -37,15 +37,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="md-layout">
|
<div class="md-layout">
|
||||||
<div class="md-layout-item md-small-size-100">
|
<div class="md-layout-item md-small-size-100">
|
||||||
|
<md-field>
|
||||||
<md-select v-model="fileType" id="file-type" placeholder="File type">
|
<md-select v-model="fileType" id="file-type" placeholder="File type">
|
||||||
<md-option value="auto">Detect type</md-option>
|
<md-option value="auto">Detect type</md-option>
|
||||||
<md-option :value="k" v-for="(v,k) in FILE_TYPES" v-bind:key="v.name">{{v.name}}</md-option>
|
<md-option :value="k" v-for="(v,k) in FILE_TYPES" v-bind:key="v.name">{{v.name}}</md-option>
|
||||||
</md-select>
|
</md-select>
|
||||||
|
</md-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="md-layout md-gutter">
|
<div class="md-layout">
|
||||||
<input type="file" @change="onLoadFile" id="upload-file" v-show="false" />
|
<input type="file" @change="onLoadFile" ref="fileUpload" v-show="false" />
|
||||||
<label class="md-button md-accent md-raised md-theme-default" for="upload-file">Add File</label>
|
<md-button class="md-accent md-raised md-theme-default" @click="$refs.fileUpload.click()">Add File</md-button>
|
||||||
<md-button v-if="dataReady" @click="onSubmit" class="md-button md-primary md-raised md-theme-default">Submit</md-button>
|
<md-button v-if="dataReady" @click="onSubmit" class="md-button md-primary md-raised md-theme-default">Submit</md-button>
|
||||||
</div>
|
</div>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
|
|||||||
@@ -13,33 +13,32 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<md-card v-if="file">
|
<md-card v-if="(isLog(file) || isTrace(file))">
|
||||||
<md-card-header>
|
<md-card-header>
|
||||||
<md-card-header-text>
|
<md-card-header-text>
|
||||||
<div class="md-title">
|
<div class="md-title">
|
||||||
<md-icon>{{file.type.icon}}</md-icon> {{file.filename}}
|
<md-icon>{{file.type.icon}}</md-icon>
|
||||||
|
{{file.filename}}
|
||||||
</div>
|
</div>
|
||||||
</md-card-header-text>
|
</md-card-header-text>
|
||||||
<md-button :href="file.blobUrl" :download="file.filename" class="md-icon-button">
|
<md-button :href="file.blobUrl" :download="file.filename" class="md-icon-button">
|
||||||
<md-icon>save_alt</md-icon>
|
<md-icon>save_alt</md-icon>
|
||||||
</md-button>
|
</md-button>
|
||||||
</md-card-header>
|
</md-card-header>
|
||||||
<traceview v-if="isTrace" :store="store" :file="file" ref="view" />
|
<traceview v-if="isTrace(file)" :store="store" :file="file" ref="view" />
|
||||||
<videoview v-if="isVideo" :file="file" ref="view" />
|
<logview v-if="isLog(file)" :file="file" ref="view" />
|
||||||
<logview v-if="isLog" :file="file" ref="view" />
|
<div v-if="!(isTrace(file) || isVideo(file) || isLog(file))">
|
||||||
<div v-if="!(isTrace || isVideo || isLog)">
|
|
||||||
<h1 class="bad">Unrecognized DataType</h1>
|
<h1 class="bad">Unrecognized DataType</h1>
|
||||||
</div>
|
</div>
|
||||||
</md-card>
|
</md-card>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import TraceView from './TraceView.vue'
|
import TraceView from "./TraceView.vue";
|
||||||
import VideoView from './VideoView.vue'
|
import LogView from "./LogView.vue";
|
||||||
import LogView from './LogView.vue'
|
import FileType from "./FileType.js";
|
||||||
import { DATA_TYPES } from './decode.js'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'dataview',
|
name: "dataview",
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
@@ -49,32 +48,15 @@ export default {
|
|||||||
},
|
},
|
||||||
arrowDown() {
|
arrowDown() {
|
||||||
return this.$refs.view.arrowDown();
|
return this.$refs.view.arrowDown();
|
||||||
},
|
|
||||||
},
|
|
||||||
props: ['store', 'file'],
|
|
||||||
computed: {
|
|
||||||
isTrace() {
|
|
||||||
return this.file.type == DATA_TYPES.WINDOW_MANAGER ||
|
|
||||||
this.file.type == DATA_TYPES.SURFACE_FLINGER ||
|
|
||||||
this.file.type == DATA_TYPES.TRANSACTION ||
|
|
||||||
this.file.type == DATA_TYPES.WAYLAND ||
|
|
||||||
this.file.type == DATA_TYPES.SYSTEM_UI ||
|
|
||||||
this.file.type == DATA_TYPES.LAUNCHER
|
|
||||||
},
|
|
||||||
isVideo() {
|
|
||||||
return this.file.type == DATA_TYPES.SCREEN_RECORDING;
|
|
||||||
},
|
|
||||||
isLog() {
|
|
||||||
return this.file.type == DATA_TYPES.PROTO_LOG
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
props: ["store", "file"],
|
||||||
|
mixins: [FileType],
|
||||||
components: {
|
components: {
|
||||||
'traceview': TraceView,
|
traceview: TraceView,
|
||||||
'videoview': VideoView,
|
logview: LogView
|
||||||
'logview': LogView,
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.bad {
|
.bad {
|
||||||
|
|||||||
21
tools/winscope/src/FileType.js
Normal file
21
tools/winscope/src/FileType.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { DATA_TYPES } from './decode.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FileType',
|
||||||
|
methods: {
|
||||||
|
isTrace: function (file) {
|
||||||
|
return file.type == DATA_TYPES.WINDOW_MANAGER ||
|
||||||
|
file.type == DATA_TYPES.SURFACE_FLINGER ||
|
||||||
|
file.type == DATA_TYPES.TRANSACTION ||
|
||||||
|
file.type == DATA_TYPES.WAYLAND ||
|
||||||
|
file.type == DATA_TYPES.SYSTEM_UI ||
|
||||||
|
file.type == DATA_TYPES.LAUNCHER
|
||||||
|
},
|
||||||
|
isVideo(file) {
|
||||||
|
return file.type == DATA_TYPES.SCREEN_RECORDING;
|
||||||
|
},
|
||||||
|
isLog(file) {
|
||||||
|
return file.type == DATA_TYPES.PROTO_LOG
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,20 +15,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<md-card-content class="container">
|
<md-card-content class="container">
|
||||||
<md-table class="log-table">
|
<md-table class="log-table">
|
||||||
<md-table-header>
|
<md-table-row>
|
||||||
<md-table-head class="time-column-header">Time</md-table-head>
|
<md-table-head class="time-column-header">Time</md-table-head>
|
||||||
<md-table-head class="tag-column-header">Tag</md-table-head>
|
<md-table-head class="tag-column-header">Tag</md-table-head>
|
||||||
<md-table-head class="at-column-header">At</md-table-head>
|
<md-table-head class="at-column-header">At</md-table-head>
|
||||||
<md-table-head>Message</md-table-head>
|
<md-table-head>Message</md-table-head>
|
||||||
</md-table-header>
|
</md-table-row>
|
||||||
<md-table-body>
|
|
||||||
<md-table-row v-for="line in data" :key="line.timestamp">
|
<md-table-row v-for="line in data" :key="line.timestamp">
|
||||||
<md-table-cell class="time-column">{{line.time}}</md-table-cell>
|
<md-table-cell class="time-column">{{line.time}}</md-table-cell>
|
||||||
<md-table-cell class="tag-column">{{line.tag}}</md-table-cell>
|
<md-table-cell class="tag-column">{{line.tag}}</md-table-cell>
|
||||||
<md-table-cell class="at-column">{{line.at}}</md-table-cell>
|
<md-table-cell class="at-column">{{line.at}}</md-table-cell>
|
||||||
<md-table-cell>{{line.text}}</md-table-cell>
|
<md-table-cell>{{line.text}}</md-table-cell>
|
||||||
</md-table-row>
|
</md-table-row>
|
||||||
</md-table-body>
|
|
||||||
</md-table>
|
</md-table>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export default {
|
|||||||
props: ['bounds', 'rects', 'highlight'],
|
props: ['bounds', 'rects', 'highlight'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
desiredHeight: 800,
|
||||||
desiredWidth: 400,
|
desiredWidth: 400,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -50,7 +51,13 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
s(sourceCoordinate) { // translate source into target coordinates
|
s(sourceCoordinate) { // translate source into target coordinates
|
||||||
return sourceCoordinate / this.boundsC.width * this.desiredWidth;
|
var scale;
|
||||||
|
if(this.boundsC.width < this.boundsC.height) {
|
||||||
|
scale = this.desiredHeight / this.boundsC.height;
|
||||||
|
} else {
|
||||||
|
scale = this.desiredWidth / this.boundsC.width;
|
||||||
|
}
|
||||||
|
return sourceCoordinate * scale;
|
||||||
},
|
},
|
||||||
rectToStyle(r) {
|
rectToStyle(r) {
|
||||||
var x = this.s(r.left);
|
var x = this.s(r.left);
|
||||||
@@ -82,10 +89,10 @@ export default {
|
|||||||
}
|
}
|
||||||
.rect {
|
.rect {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
background-color: rgba(100, 100, 100, 0.8);
|
background-color: rgba(110, 114, 116, 0.8);
|
||||||
}
|
}
|
||||||
.highlight {
|
.highlight {
|
||||||
border: 2px solid red;
|
border: 2px solid rgb(235, 52, 52);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.label {
|
.label {
|
||||||
|
|||||||
@@ -13,17 +13,38 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<svg width="2000" height="20" viewBox="-5,0,2010,20">
|
<svg width="100%" height="20">
|
||||||
<circle :cx="position(item)" cy="10" r="5" v-for="(item, idx) in items" @click="onItemClick(idx)" />
|
<rect
|
||||||
<circle v-if="items.length" :cx="position(selected)" cy="10" r="5" class="selected" />
|
:x="position(item)"
|
||||||
|
y="0"
|
||||||
|
:width="pointWidth"
|
||||||
|
:height="pointHeight"
|
||||||
|
:rx="corner"
|
||||||
|
v-for="(item, idx) in items"
|
||||||
|
:key="item"
|
||||||
|
@click="onItemClick(idx)"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
v-if="items.length"
|
||||||
|
:x="position(selected)"
|
||||||
|
y="0"
|
||||||
|
:width="pointWidth"
|
||||||
|
:height="pointHeight"
|
||||||
|
:rx="corner"
|
||||||
|
class="selected"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'timeline',
|
name: "timeline",
|
||||||
props: ['items', 'selectedIndex', 'scale'],
|
props: ["items", "selectedIndex", "scale"],
|
||||||
data() {
|
data() {
|
||||||
return {};
|
return {
|
||||||
|
pointWidth: "1%",
|
||||||
|
pointHeight: 15,
|
||||||
|
corner: 2
|
||||||
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
position(item) {
|
position(item) {
|
||||||
@@ -34,11 +55,11 @@ export default {
|
|||||||
if (scale[0] >= scale[1]) {
|
if (scale[0] >= scale[1]) {
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
return (cx - scale[0]) / (scale[1] - scale[0]) * 2000;
|
return (((cx - scale[0]) / (scale[1] - scale[0])) * 100) + "%";
|
||||||
},
|
},
|
||||||
onItemClick(index) {
|
onItemClick(index) {
|
||||||
this.$emit('item-selected', index);
|
this.$emit("item-selected", index);
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
timestamps() {
|
timestamps() {
|
||||||
@@ -50,13 +71,11 @@ export default {
|
|||||||
selected() {
|
selected() {
|
||||||
return this.items[this.selectedIndex];
|
return this.items[this.selectedIndex];
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.selected {
|
.selected {
|
||||||
fill: red;
|
fill: rgb(240, 59, 59);
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -15,29 +15,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<md-card-content class="container">
|
<md-card-content class="container">
|
||||||
<md-card class="rects" v-if="hasScreenView">
|
<md-card class="rects" v-if="hasScreenView">
|
||||||
<md-whiteframe md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
<md-content md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
||||||
<h2 class="md-title">Screen</h2>
|
<h2 class="md-title">Screen</h2>
|
||||||
</md-whiteframe>
|
</md-content>
|
||||||
<md-whiteframe md-elevation="8">
|
<md-content class="md-elevation-8">
|
||||||
<rects :bounds="bounds" :rects="rects" :highlight="highlight" @rect-click="onRectClick" />
|
<rects :bounds="bounds" :rects="rects" :highlight="highlight" @rect-click="onRectClick" />
|
||||||
</md-whiteframe>
|
</md-content>
|
||||||
</md-card>
|
</md-card>
|
||||||
<md-card class="hierarchy">
|
<md-card class="hierarchy">
|
||||||
<md-whiteframe md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
<md-content md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
||||||
<h2 class="md-title" style="flex: 1;">Hierarchy</h2>
|
<h2 class="md-title" style="flex: 1;">Hierarchy</h2>
|
||||||
<md-checkbox v-model="store.onlyVisible">Only visible</md-checkbox>
|
<md-checkbox v-model="store.onlyVisible">Only visible</md-checkbox>
|
||||||
<md-checkbox v-model="store.flattened">Flat</md-checkbox>
|
<md-checkbox v-model="store.flattened">Flat</md-checkbox>
|
||||||
<input id="filter" type="search" placeholder="Filter..." v-model="hierarchyPropertyFilterString" />
|
<input id="filter" type="search" placeholder="Filter..." v-model="hierarchyPropertyFilterString" />
|
||||||
</md-whiteframe>
|
</md-content>
|
||||||
<tree-view class="data-card" :item="tree" @item-selected="itemSelected" :selected="hierarchySelected" :filter="hierarchyFilter" :flattened="store.flattened" ref="hierarchy" />
|
<tree-view class="data-card" :item="tree" @item-selected="itemSelected" :selected="hierarchySelected" :filter="hierarchyFilter" :flattened="store.flattened" ref="hierarchy" />
|
||||||
</md-card>
|
</md-card>
|
||||||
<md-card class="properties">
|
<md-card class="properties">
|
||||||
<md-whiteframe md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
<md-content md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
||||||
<h2 class="md-title" style="flex: 1">Properties</h2>
|
<h2 class="md-title" style="flex: 1">Properties</h2>
|
||||||
<div class="filter">
|
<div class="filter">
|
||||||
<input id="filter" type="search" placeholder="Filter..." v-model="propertyFilterString" />
|
<input id="filter" type="search" placeholder="Filter..." v-model="propertyFilterString" />
|
||||||
</div>
|
</div>
|
||||||
</md-whiteframe>
|
</md-content>
|
||||||
<tree-view class="pre-line-data-card" :item="selectedTree" :filter="propertyFilter" />
|
<tree-view class="pre-line-data-card" :item="selectedTree" :filter="propertyFilter" />
|
||||||
</md-card>
|
</md-card>
|
||||||
</md-card-content>
|
</md-card-content>
|
||||||
|
|||||||
@@ -14,28 +14,61 @@
|
|||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="tree-view">
|
<div class="tree-view">
|
||||||
<div @click="clicked" :class="computedClass">
|
<div @click="clicked" :class="computedClass" class="node">
|
||||||
<span class="kind">{{item.kind}}</span><span v-if="item.kind && item.name"> - </span><span>{{item.name}}</span>
|
<span class="kind">{{item.kind}}</span>
|
||||||
<div v-for="c in item.chips" :title="c.long" :class="chipClassForChip(c)">
|
<span v-if="item.kind && item.name">-</span>
|
||||||
{{c.short}}
|
<span>{{item.name}}</span>
|
||||||
</div>
|
<div
|
||||||
|
v-for="c in item.chips"
|
||||||
|
v-bind:key="c.long"
|
||||||
|
:title="c.long"
|
||||||
|
:class="chipClassForChip(c)"
|
||||||
|
>{{c.short}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="children" v-if="children">
|
<div class="children" v-if="children">
|
||||||
<tree-view v-for="(c,i) in children" :item="c" @item-selected="childItemSelected" :selected="selected" :key="i" :chip-class='chipClass' :filter="childFilter(c)" :flattened="flattened" :force-flattened="applyingFlattened" v-show="filterMatches(c)" ref='children' />
|
<tree-view
|
||||||
|
v-for="(c,i) in children"
|
||||||
|
:item="c"
|
||||||
|
@item-selected="childItemSelected"
|
||||||
|
:selected="selected"
|
||||||
|
:key="i"
|
||||||
|
:chip-class="chipClass"
|
||||||
|
:filter="childFilter(c)"
|
||||||
|
:flattened="flattened"
|
||||||
|
:force-flattened="applyingFlattened"
|
||||||
|
v-show="filterMatches(c)"
|
||||||
|
ref="children"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import jsonProtoDefs from 'frameworks/base/core/proto/android/server/windowmanagertrace.proto'
|
import jsonProtoDefs from "frameworks/base/core/proto/android/server/windowmanagertrace.proto";
|
||||||
import protobuf from 'protobufjs'
|
import protobuf from "protobufjs";
|
||||||
|
|
||||||
var protoDefs = protobuf.Root.fromJSON(jsonProtoDefs);
|
var protoDefs = protobuf.Root.fromJSON(jsonProtoDefs);
|
||||||
|
var TraceMessage = protoDefs.lookupType(
|
||||||
|
"com.android.server.wm.WindowManagerTraceFileProto"
|
||||||
|
);
|
||||||
|
var ServiceMessage = protoDefs.lookupType(
|
||||||
|
"com.android.server.wm.WindowManagerServiceDumpProto"
|
||||||
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'tree-view',
|
name: "tree-view",
|
||||||
props: ['item', 'selected', 'chipClass', 'filter', 'flattened', 'force-flattened'],
|
props: [
|
||||||
data() {
|
"item",
|
||||||
return {};
|
"selected",
|
||||||
|
"chipClass",
|
||||||
|
"filter",
|
||||||
|
"flattened",
|
||||||
|
"force-flattened"
|
||||||
|
],
|
||||||
|
data: function() {
|
||||||
|
return {
|
||||||
|
isChildSelected: false
|
||||||
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
selectNext(found, parent) {
|
selectNext(found, parent) {
|
||||||
@@ -43,7 +76,7 @@ export default {
|
|||||||
this.clicked();
|
this.clicked();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.selected === this.item) {
|
if (this.isCurrentSelected()) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (this.$refs.children) {
|
if (this.$refs.children) {
|
||||||
@@ -63,20 +96,23 @@ export default {
|
|||||||
this.clicked();
|
this.clicked();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this.selected === this.item) {
|
if (this.isCurrentSelected()) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
return found;
|
return found;
|
||||||
},
|
},
|
||||||
childItemSelected(item) {
|
childItemSelected(item) {
|
||||||
this.$emit('item-selected', item);
|
this.isChildSelected = true;
|
||||||
|
this.$emit("item-selected", item);
|
||||||
},
|
},
|
||||||
clicked() {
|
clicked() {
|
||||||
this.$emit('item-selected', this.item);
|
this.$emit("item-selected", this.item);
|
||||||
},
|
},
|
||||||
chipClassForChip(c) {
|
chipClassForChip(c) {
|
||||||
return ['tree-view-internal-chip', this.chipClassOrDefault,
|
return [
|
||||||
this.chipClassOrDefault + '-' + (c.class || 'default')
|
"tree-view-internal-chip",
|
||||||
|
this.chipClassOrDefault,
|
||||||
|
this.chipClassOrDefault + "-" + (c.class || "default")
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
filterMatches(c) {
|
filterMatches(c) {
|
||||||
@@ -99,40 +135,72 @@ export default {
|
|||||||
}
|
}
|
||||||
return this.filter;
|
return this.filter;
|
||||||
},
|
},
|
||||||
|
isCurrentSelected() {
|
||||||
|
return this.selected === this.item;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
computedClass() {
|
computedClass() {
|
||||||
return (this.item == this.selected) ? 'selected' : ''
|
return (this.item == this.selected) ? 'selected' : ''
|
||||||
},
|
},
|
||||||
chipClassOrDefault() {
|
chipClassOrDefault() {
|
||||||
return this.chipClass || 'tree-view-chip';
|
return this.chipClass || "tree-view-chip";
|
||||||
},
|
},
|
||||||
applyingFlattened() {
|
applyingFlattened() {
|
||||||
return this.flattened && this.item.flattened || this.forceFlattened;
|
return (this.flattened && this.item.flattened) || this.forceFlattened;
|
||||||
},
|
},
|
||||||
children() {
|
children() {
|
||||||
return this.applyingFlattened ? this.item.flattened : this.item.children;
|
return this.applyingFlattened ? this.item.flattened : this.item.children;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
.data-card > .tree-view {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-view {
|
||||||
|
display: block;
|
||||||
|
border-left: 1px solid rgb(238, 238, 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-view.tree-view {
|
||||||
|
margin: 0;
|
||||||
|
padding: 1px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-view .node {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-view .node:hover:not(.selected) {
|
||||||
|
background: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
.children {
|
.children {
|
||||||
margin-left: 24px;
|
margin-left: 8px;
|
||||||
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.kind {
|
.kind {
|
||||||
color: #333;
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
background-color: #3f51b5;
|
background-color: #365179;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.childSelected {
|
||||||
|
border-left: 1px solid rgb(233, 22, 22)
|
||||||
|
}
|
||||||
|
|
||||||
.selected .kind {
|
.selected .kind {
|
||||||
color: #ccc;
|
color: #e9e9e9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-view-internal-chip {
|
.tree-view-internal-chip {
|
||||||
|
|||||||
@@ -13,16 +13,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<md-card-content class="container">
|
<video class="md-elevation-2 screen" :id="file.filename" :src="file.data" />
|
||||||
<md-card class="rects">
|
|
||||||
<md-whiteframe md-tag="md-toolbar" md-elevation="0" class="card-toolbar md-transparent md-dense">
|
|
||||||
<h2 class="md-title">Screen</h2>
|
|
||||||
</md-whiteframe>
|
|
||||||
<md-whiteframe md-elevation="8">
|
|
||||||
<video :id="file.filename" class="screen" :src="file.data" />
|
|
||||||
</md-whiteframe>
|
|
||||||
</md-card>
|
|
||||||
</md-card-content>
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
const EPSILON = 0.00001
|
const EPSILON = 0.00001
|
||||||
@@ -70,6 +61,6 @@ export default {
|
|||||||
<style>
|
<style>
|
||||||
.screen {
|
.screen {
|
||||||
max-height: 50em;
|
max-height: 50em;
|
||||||
|
max-width: 50em;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -13,10 +13,11 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<html lang="en">
|
<html lang="en" class="md-scrollbar">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||||
|
<link rel="icon" type="image/svg" href="static/favicon.svg"/>
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>winscope</title>
|
<title>winscope</title>
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import Vue from 'vue'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
import 'style-loader!css-loader!vue-material/dist/vue-material.css'
|
import 'style-loader!css-loader!vue-material/dist/vue-material.css'
|
||||||
|
import 'style-loader!css-loader!vue-material/dist/theme/default.css'
|
||||||
|
|
||||||
import VueMaterial from 'vue-material'
|
import VueMaterial from 'vue-material'
|
||||||
Vue.use(VueMaterial);
|
Vue.use(VueMaterial);
|
||||||
|
|
||||||
|
|||||||
134
tools/winscope/static/favicon.svg
Normal file
134
tools/winscope/static/favicon.svg
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 135.46666 135.46667"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="winscope.svg">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient144">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#3ddb85;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop140" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#3ddb85;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop142" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient144"
|
||||||
|
id="linearGradient146"
|
||||||
|
x1="334.86557"
|
||||||
|
y1="288.25122"
|
||||||
|
x2="362.64478"
|
||||||
|
y2="405.42892"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient144"
|
||||||
|
id="linearGradient152"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="334.86557"
|
||||||
|
y1="288.25122"
|
||||||
|
x2="362.64478"
|
||||||
|
y2="405.42892" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4"
|
||||||
|
inkscape:cx="369.78115"
|
||||||
|
inkscape:cy="43.694507"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer2"
|
||||||
|
showgrid="false"
|
||||||
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1399"
|
||||||
|
inkscape:window-x="1440"
|
||||||
|
inkscape:window-y="20"
|
||||||
|
inkscape:window-maximized="0" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:inline"
|
||||||
|
transform="translate(0,-161.53331)">
|
||||||
|
<g
|
||||||
|
id="g60"
|
||||||
|
transform="matrix(1.4161793,0,0,1.4161793,-266.89731,76.345061)">
|
||||||
|
<path
|
||||||
|
id="path46"
|
||||||
|
d="m 254.98635,139.13116 c -4.3276,0 -7.84784,-3.71395 -7.84784,-8.27594 0,-4.56195 4.14824,-8.27278 7.84784,-8.27285 3.6996,-9e-5 7.84855,3.71014 7.84855,8.27285 0,4.56276 -3.52025,8.27594 -7.84855,8.27594 m -36.93749,-2.38905 c -3.0836,0 -5.59192,-2.64634 -5.59192,-5.89694 0,-3.25059 2.50784,-5.89476 5.59192,-5.89476 3.08358,0 5.5919,2.64364 5.5919,5.89476 0,3.25114 -2.50781,5.89694 -5.5919,5.89694 m 52.09761,-36.05821 11.17666,-20.405632 c 0.64058,-1.172551 0.25981,-2.670449 -0.85112,-3.348238 -1.11236,-0.674958 -2.53307,-0.273633 -3.17621,0.897219 l -11.31638,20.663525 c -8.6545,-4.162927 -18.37356,-6.482308 -28.74463,-6.482308 -10.37108,0 -20.09013,2.319381 -28.74411,6.482308 L 197.17379,77.827249 c -0.64314,-1.170852 -2.06385,-1.572177 -3.17621,-0.897219 -1.11167,0.677199 -1.49261,2.175808 -0.85113,3.348238 L 204.3231,100.6839 c -19.19192,11.00346 -32.318,31.48516 -34.23828,55.68305 h 134.29993 c -1.9218,-24.19736 -15.04789,-44.67959 -34.23828,-55.68357"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:#3ddb85;stroke-width:0.52547503"
|
||||||
|
sodipodi:nodetypes="csssccsssccccccscccccccc" />
|
||||||
|
<path
|
||||||
|
id="path48"
|
||||||
|
d="M -0.75490308,-4.3032616 H 466.2911 V 245.86074 H -0.75490308 Z"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:none" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="Layer 2"
|
||||||
|
transform="translate(0,-161.53331)"
|
||||||
|
style="display:inline">
|
||||||
|
<g
|
||||||
|
id="g150"
|
||||||
|
transform="matrix(1.2390981,0,0,1.2745122,-22.278191,-60.145091)">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="font-weight:400;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;text-transform:none;white-space:normal;display:inline;overflow:visible;opacity:0.92156863;isolation:auto;mix-blend-mode:normal;fill:#000000;stroke-width:3.05656147"
|
||||||
|
d="m 93.327473,227.20793 c -11.817096,0 -21.462353,9.58571 -21.462353,21.32967 0,11.74397 9.645257,21.32967 21.462353,21.32967 10.773667,0 19.717027,-7.97589 21.216847,-18.28256 h 2.56476 c 1.69335,1e-5 3.06608,-1.36423 3.06607,-3.04711 -1e-5,-1.68286 -1.37273,-3.04709 -3.06607,-3.04708 h -2.56476 c -1.49999,-10.3067 -10.44318,-18.28259 -21.216847,-18.28259 z m 0,6.09419 c 8.503037,0 15.330367,6.78508 15.330367,15.23548 0,8.45041 -6.82733,15.2355 -15.330367,15.2355 -8.503052,0 -15.330212,-6.78509 -15.330212,-15.2355 0,-8.45041 6.82716,-15.23548 15.330212,-15.23548 z m 23.781607,21.32968 c -1.69335,-2e-5 -3.06609,1.36422 -3.06609,3.0471 -1e-5,1.68288 1.37274,3.04713 3.06609,3.04711 1.69335,1e-5 3.06608,-1.36423 3.06607,-3.04711 0,-1.68287 -1.37273,-3.04711 -3.06607,-3.0471 z m 0,9.1413 c -1.69334,-2e-5 -3.06607,1.3642 -3.06609,3.04706 -1e-5,1.68288 1.37274,3.04713 3.06609,3.04711 1.69335,10e-6 3.06608,-1.36423 3.06607,-3.04711 -2e-5,-1.68286 -1.37274,-3.04707 -3.06607,-3.04706 z m 0,9.14127 c -1.69335,-2e-5 -3.06609,1.36421 -3.06609,3.04709 0,1.68288 1.37274,3.04712 3.06609,3.0471 1.69334,1e-5 3.06607,-1.36423 3.06607,-3.0471 0,-1.68287 -1.37273,-3.0471 -3.06607,-3.04709 z m 0,9.14129 c -1.69334,-2e-5 -3.06608,1.36421 -3.06609,3.04708 -1e-5,1.68288 1.37274,3.04713 3.06609,3.04711 1.69335,10e-6 3.06608,-1.36423 3.06607,-3.04711 -1e-5,-1.68286 -1.37273,-3.04709 -3.06607,-3.04708 z"
|
||||||
|
font-weight="400"
|
||||||
|
overflow="visible"
|
||||||
|
id="path62"
|
||||||
|
sodipodi:nodetypes="sssccsccsssssscccccccccccscsccscsc" />
|
||||||
|
<path
|
||||||
|
transform="matrix(0.26458333,0,0,0.26458333,0,161.53331)"
|
||||||
|
sodipodi:nodetypes="sssssscssscs"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path130"
|
||||||
|
d="m 346.52914,385.88304 c -9.74153,-1.15668 -19.18712,-4.7389 -27.36682,-10.3788 -4.29704,-2.96281 -11.19439,-9.96762 -14.26053,-14.48272 -3.09123,-4.55204 -6.34453,-11.66167 -7.89403,-17.2513 -1.63959,-5.91462 -2.25943,-17.8322 -1.2539,-24.10849 3.61484,-22.56303 20.01002,-40.31938 42.90934,-46.47177 4.28814,-1.1521 5.83599,-1.30305 13.67432,-1.33348 9.26661,-0.036 11.69398,0.2988 18.66447,2.5742 8.55206,2.79168 15.83504,7.31293 22.56577,14.00876 20.25076,20.14579 22.48959,52.06917 5.25566,74.94032 -8.89686,11.80702 -22.47121,19.85596 -37.24125,22.08226 -4.528,0.6825 -11.2641,0.87091 -15.05303,0.42102 z"
|
||||||
|
style="opacity:0.49673205;fill:url(#linearGradient152);fill-opacity:1;stroke:none;stroke-width:0.50507629" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.1 KiB |
5
tools/winscope/vue.config.js
Normal file
5
tools/winscope/vue.config.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
configureWebpack: {
|
||||||
|
devtool: 'source-map'
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user