From 9377a90b6a025d5cd0985721db2913473d08ca3d Mon Sep 17 00:00:00 2001
From: neauoire <aliceffekt@gmail.com>
Date: Sun, 10 Nov 2019 11:10:03 -0500
Subject: [PATCH] Fixed issue with window hiding on linux

---
 desktop/main.js                               |   6 +-
 desktop/sources/index.html                    |  10 +-
 .../sources/scripts/{ronin.js => client.js}   |  13 +-
 desktop/sources/scripts/commander.js          |  24 ++--
 desktop/sources/scripts/lib/theme.js          |  51 ++++---
 desktop/sources/scripts/library.js            | 126 +++++++++---------
 desktop/sources/scripts/surface.js            |  28 ++--
 index.html                                    |   8 +-
 8 files changed, 144 insertions(+), 122 deletions(-)
 rename desktop/sources/scripts/{ronin.js => client.js} (96%)

diff --git a/desktop/main.js b/desktop/main.js
index f7d60c4..0693125 100644
--- a/desktop/main.js
+++ b/desktop/main.js
@@ -60,8 +60,12 @@ app.toggleFullscreen = function () {
   app.win.setFullScreen(!app.win.isFullScreen())
 }
 
+app.toggleMenubar = function () {
+  app.win.setMenuBarVisibility(!app.win.isMenuBarVisible())
+}
+
 app.toggleVisible = function () {
-  if (process.platform === 'win32') {
+  if (process.platform !== 'darwin') {
     if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() }
   } else {
     if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() }
diff --git a/desktop/sources/index.html b/desktop/sources/index.html
index 49797f9..6401d4f 100644
--- a/desktop/sources/index.html
+++ b/desktop/sources/index.html
@@ -5,7 +5,7 @@
     <script type="text/javascript" src="scripts/lib/acels.js"></script>
     <script type="text/javascript" src="scripts/lib/lisp.js"></script>
     <script type="text/javascript" src="scripts/lib/source.js"></script>
-    <script type="text/javascript" src="scripts/ronin.js"></script>
+    <script type="text/javascript" src="scripts/client.js"></script>
     <script type="text/javascript" src="scripts/commander.js"></script>
     <script type="text/javascript" src="scripts/surface.js"></script>
     <script type="text/javascript" src="scripts/library.js"></script>
@@ -17,13 +17,13 @@
   </head>
   <body>
     <script type="text/javascript">
-      const ronin = new Ronin()
+      const client = new Client()
 
-      ronin.install(document.body)
+      client.install(document.body)
 
       window.addEventListener('load', () => { 
-        ronin.start() 
-        ronin.acels.inject('Ronin')
+        client.start() 
+        client.acels.inject('Ronin')
       })
     </script>
   </body>
diff --git a/desktop/sources/scripts/ronin.js b/desktop/sources/scripts/client.js
similarity index 96%
rename from desktop/sources/scripts/ronin.js
rename to desktop/sources/scripts/client.js
index 404d632..86f997e 100644
--- a/desktop/sources/scripts/ronin.js
+++ b/desktop/sources/scripts/client.js
@@ -10,7 +10,7 @@
 /* global Image */
 /* global requestAnimationFrame */
 
-function Ronin () {
+function Client () {
   this.el = document.createElement('div')
   this.el.id = 'ronin'
 
@@ -42,7 +42,6 @@ function Ronin () {
     this.acels.set('File', 'Save', 'CmdOrCtrl+S', () => { this.source.download('ronin', 'lisp', this.commander._input.value, 'text/plain') })
     this.acels.set('File', 'Export Image', 'CmdOrCtrl+E', () => { this.source.download('ronin', 'png', this.surface.el.toDataURL('image/png', 1.0), 'image/png') })
     this.acels.set('File', 'Open', 'CmdOrCtrl+O', () => { this.source.open('lisp', this.whenOpen) })
-    this.acels.set('File', 'Revert', 'CmdOrCtrl+W', () => { this.source.revert() })
 
     this.acels.add('Edit', 'cut')
     this.acels.add('Edit', 'copy')
@@ -56,7 +55,7 @@ function Ronin () {
     this.acels.set('Project', 'Reload Run', 'CmdOrCtrl+Shift+R', () => { this.source.revert(); this.commander.run() })
     this.acels.set('Project', 'Re-Indent', 'CmdOrCtrl+Shift+I', () => { this.commander.reindent() })
     this.acels.set('Project', 'Clean', 'Escape', () => { this.commander.cleanup() })
-    
+
     this.acels.install(window)
     this.acels.pipe(this)
   }
@@ -71,8 +70,8 @@ function Ronin () {
     this.loop()
   }
 
-  this.whenOpen = (file,res) => {
-    console.log(file,res)
+  this.whenOpen = (file, res) => {
+    console.log(file, res)
     this.commander.load(res)
     this.commander.show()
   }
@@ -175,7 +174,7 @@ function Ronin () {
 
     if (file.name.indexOf('.lisp') > -1) {
       this.source.read(file, this.whenOpen)
-      this.log('Loaded '+file.name)
+      this.log('Loaded ' + file.name)
     }
 
     if (file.type === 'image/jpeg' || file.type === 'image/png') {
@@ -183,7 +182,7 @@ function Ronin () {
       img.onload = () => {
         this.cache.set(file.name, img.src)
         this.commander.injectPath(file.name)
-        this.log('Loaded '+file.name)
+        this.log('Loaded ' + file.name)
       }
       img.src = URL.createObjectURL(file)
     }
diff --git a/desktop/sources/scripts/commander.js b/desktop/sources/scripts/commander.js
index f3565cb..c35cb07 100644
--- a/desktop/sources/scripts/commander.js
+++ b/desktop/sources/scripts/commander.js
@@ -1,4 +1,6 @@
-function Commander (ronin) {
+'use strict'
+
+function Commander (client) {
   this.el = document.createElement('div')
   this.el.id = 'commander'
   this._input = document.createElement('textarea')
@@ -38,11 +40,11 @@ function Commander (ronin) {
 
   this.run = (txt = this._input.value) => {
     if (this._input.value.indexOf('$') > -1) { txt = this.clean(txt) }
-    ronin.bindings = {}
+    client.bindings = {}
     if (this._input.value.trim() === '') {
-      ronin.surface.maximize()
+      client.surface.maximize()
     }
-    ronin.lisp.run(txt)
+    client.lisp.run(txt)
     this.feedback()
   }
 
@@ -77,7 +79,7 @@ function Commander (ronin) {
     let val = this._input.value.replace(/\n/g, '').replace(/ \)/g, ')').replace(/ +(?= )/g, '').replace(/\( \(/g, '((').replace(/\) \)/g, '))').trim()
     let depth = 0
     if (val.split('(').length !== val.split(')').length) {
-      ronin.log('Uneven number of parens.')
+      client.log('Uneven number of parens.')
       return
     }
     for (let i = 0; i < val.length; i++) {
@@ -183,14 +185,14 @@ function Commander (ronin) {
 
   this.show = function (expand = false) {
     if (this.isVisible === true) { return }
-    ronin.el.className = expand ? 'expand' : ''
+    client.el.className = expand ? 'expand' : ''
     this.isVisible = true
     this._input.focus()
   }
 
   this.hide = function () {
     if (this.isVisible !== true) { return }
-    ronin.el.className = 'hidden'
+    client.el.className = 'hidden'
     this.isVisible = false
     this._input.blur()
   }
@@ -222,8 +224,8 @@ function Commander (ronin) {
   this.getCurrentFunction = () => {
     const word = this.getCurrentWord()
     let mostSimilar = ''
-    if (ronin.library[word]) { return word }
-    for (const id of Object.keys(ronin.library)) {
+    if (client.library[word]) { return word }
+    for (const id of Object.keys(client.library)) {
       if (id.substr(0, word.length) === word) {
         mostSimilar = id
       }
@@ -233,7 +235,7 @@ function Commander (ronin) {
 
   this.getDocs = (id) => {
     const name = this.getCurrentFunction()
-    const fn = ronin.library[name]
+    const fn = client.library[name]
     if (!fn) { return }
     const fnString = fn.toString().replace('async ', '')
     if (fnString.indexOf(') => {') < 0) { return }
@@ -252,7 +254,7 @@ function Commander (ronin) {
 (def pos-y 
   (sub frame:m 150))
 (stroke 
-  (svg pos-x pos-y logo-path) theme:b_high 5)
+  (svg pos-x pos-y logo-path) theme:f_high 5)
 `
 
   function insert (str, add, i) {
diff --git a/desktop/sources/scripts/lib/theme.js b/desktop/sources/scripts/lib/theme.js
index 8856e47..0556fa0 100644
--- a/desktop/sources/scripts/lib/theme.js
+++ b/desktop/sources/scripts/lib/theme.js
@@ -10,17 +10,20 @@ function Theme (client) {
 
   this.active = {}
   this.default = {
-    background: '#eee',
-    f_high: '#000',
-    f_med: '#999',
-    f_low: '#ccc',
-    f_inv: '#000',
-    b_high: '#000',
-    b_med: '#888',
-    b_low: '#aaa',
+    background: '#eeeeee',
+    f_high: '#0a0a0a',
+    f_med: '#4a4a4a',
+    f_low: '#6a6a6a',
+    f_inv: '#111111',
+    b_high: '#a1a1a1',
+    b_med: '#c1c1c1',
+    b_low: '#ffffff',
     b_inv: '#ffb545'
   }
 
+  // Callbacks
+  this.onLoad = () => {}
+
   this.install = (host = document.body) => {
     window.addEventListener('dragover', this.drag)
     window.addEventListener('drop', this.drop)
@@ -67,12 +70,22 @@ function Theme (client) {
     }`
     localStorage.setItem('theme', JSON.stringify(theme))
     this.active = theme
+    if (this.onLoad) {
+      this.onLoad(data)
+    }
   }
 
   this.reset = () => {
     this.load(this.default)
   }
 
+  this.set = (key, val) => {
+    if (!val) { return }
+    const hex = (`${val}`.substr(0, 1) !== '#' ? '#' : '') + `${val}`
+    if (!isColor(hex)) { console.warn('Theme', `${hex} is not a valid color.`); return }
+    this.active[key] = hex
+  }
+
   this.read = (key) => {
     return this.active[key]
   }
@@ -131,18 +144,22 @@ function Theme (client) {
 
   function isValid (json) {
     if (!json) { return false }
-    if (!json.background) { return false }
-    if (!json.f_high) { return false }
-    if (!json.f_med) { return false }
-    if (!json.f_low) { return false }
-    if (!json.f_inv) { return false }
-    if (!json.b_high) { return false }
-    if (!json.b_med) { return false }
-    if (!json.b_low) { return false }
-    if (!json.b_inv) { return false }
+    if (!json.background || !isColor(json.background)) { return false }
+    if (!json.f_high || !isColor(json.f_high)) { return false }
+    if (!json.f_med || !isColor(json.f_med)) { return false }
+    if (!json.f_low || !isColor(json.f_low)) { return false }
+    if (!json.f_inv || !isColor(json.f_inv)) { return false }
+    if (!json.b_high || !isColor(json.b_high)) { return false }
+    if (!json.b_med || !isColor(json.b_med)) { return false }
+    if (!json.b_low || !isColor(json.b_low)) { return false }
+    if (!json.b_inv || !isColor(json.b_inv)) { return false }
     return true
   }
 
+  function isColor (hex) {
+    return /^#([0-9A-F]{3}){1,2}$/i.test(hex)
+  }
+
   function isJson (text) {
     try { JSON.parse(text); return true } catch (error) { return false }
   }
diff --git a/desktop/sources/scripts/library.js b/desktop/sources/scripts/library.js
index 42369a9..3964f87 100644
--- a/desktop/sources/scripts/library.js
+++ b/desktop/sources/scripts/library.js
@@ -2,18 +2,18 @@
 
 /* global Image */
 
-function Library (ronin) {
+function Library (client) {
   // IO
   this.import = async (name, shape, alpha = 1) => { // Imports a graphic file with format.
-    const src = ronin.cache.get(name)
-    if (!src) { ronin.log('No data for ' + name); return }
+    const src = client.cache.get(name)
+    if (!src) { client.log('No data for ' + name); return }
     const img = new Image()
     img.src = src
-    return ronin.surface.draw(img, shape, alpha)
+    return client.surface.draw(img, shape, alpha)
   }
 
   this.export = async (name = 'export', type = 'image/png', quality = 1.0) => { // Exports a graphic file with format.
-    const base64 = ronin.surface.el.toDataURL(type, quality)
+    const base64 = client.surface.el.toDataURL(type, quality)
     const link = document.createElement('a')
     link.setAttribute('href', base64)
     link.setAttribute('download', type === 'image/png' ? name + '.png' : name + '.jpg')
@@ -74,59 +74,59 @@ function Library (ronin) {
 
   // Frame
 
-  this.resize = async (w = ronin.surface.bounds().w, h = ronin.surface.bounds().h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
+  this.resize = async (w = client.surface.bounds().w, h = client.surface.bounds().h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
     if (w === this['get-frame']().w && h === this['get-frame']().h) { return }
     const rect = { x: 0, y: 0, w, h }
     const a = document.createElement('img')
     const b = document.createElement('img')
-    a.src = ronin.surface.el.toDataURL()
-    await ronin.surface.resizeImage(a, b)
-    ronin.surface.resize(rect, fit)
-    return ronin.surface.draw(b, rect)
+    a.src = client.surface.el.toDataURL()
+    await client.surface.resizeImage(a, b)
+    client.surface.resize(rect, fit)
+    return client.surface.draw(b, rect)
   }
 
   this.rescale = async (w = 1, h = 1) => { // Rescales the canvas to target ratio of w and h, returns the rect.
     const rect = { x: 0, y: 0, w: this['get-frame']().w * w, h: this['get-frame']().h * h }
     const a = document.createElement('img')
     const b = document.createElement('img')
-    a.src = ronin.surface.el.toDataURL()
-    await ronin.surface.resizeImage(a, b)
-    ronin.surface.resize(rect, true)
-    return ronin.surface.draw(b, rect)
+    a.src = client.surface.el.toDataURL()
+    await client.surface.resizeImage(a, b)
+    client.surface.resize(rect, true)
+    return client.surface.draw(b, rect)
   }
 
   this.crop = async (rect = this['get-frame']()) => { // Crop canvas to rect.
-    return ronin.surface.crop(rect)
+    return client.surface.crop(rect)
   }
 
   this.copy = async (rect = this['get-frame']()) => { // Copy a section of the canvas.
-    return ronin.surface.copy(rect)
+    return client.surface.copy(rect)
   }
 
   this.paste = async (copy, rect = this['get-frame']()) => { // Paste a section of the canvas.
-    return ronin.surface.paste(copy, rect)
+    return client.surface.paste(copy, rect)
   }
 
   this.drag = (rect = this['get-frame'](), line = this.line()) => { // Drag a part of the canvas.
     const pos = { x: line.b.x - line.a.x, y: line.b.y - line.a.y }
-    const crop = ronin.surface.copy(rect)
-    ronin.surface.clear(rect)
+    const crop = client.surface.copy(rect)
+    client.surface.clear(rect)
     this.guide({ a: { x: rect.x, y: rect.y }, b: { x: pos.x + rect.x, y: pos.y + rect.y } })
     this.guide(rect)
     this.guide(this.offset(rect, { x: pos.x, y: pos.y }))
-    ronin.surface.context.drawImage(crop, rect.x, rect.y)
+    client.surface.context.drawImage(crop, rect.x, rect.y)
   }
 
   this.view = (a, b) => { // View a part of the canvas.
     this.guide({ a: { x: a.x, y: a.y }, b: { x: b.x, y: b.y } })
     this.guide(a)
     this.guide(b)
-    ronin.surface.context.drawImage(this.copy(a), b.x, b.y, b.w, b.h)
+    client.surface.context.drawImage(this.copy(a), b.x, b.y, b.w, b.h)
   }
 
   this.pick = (shape = this['get-frame']()) => { // Returns the color of a pixel at pos, or of the average of the pixels in rect.
     const rect = shape.w && shape.h ? shape : this.rect(shape.x, shape.y, 1, 1)
-    const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
+    const img = client.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
     const sum = [0, 0, 0]
     const count = img.data.length / 4
     for (let i = 0, loop = img.data.length; i < loop; i += 4) {
@@ -143,32 +143,32 @@ function Library (ronin) {
     const mode = Math.floor(deg / 90) % 4
     const offset = { x: [0, 0, -frame.w, -frame.w], y: [0, -frame.h, -frame.h, 0] }
     const rect = { x: 0, y: 0, w: (mode === 1 || mode === 3 ? frame.h : frame.w), h: (mode === 1 || mode === 3 ? frame.w : frame.h) }
-    ronin.surface.resize(rect, false)
-    ronin.surface.context.save()
-    ronin.surface.context.rotate(this.rad(mode * 90))
-    ronin.surface.context.translate(offset.x[mode], offset.y[mode])
-    ronin.surface.context.drawImage(copy, 0, 0)
-    ronin.surface.context.restore()
+    client.surface.resize(rect, false)
+    client.surface.context.save()
+    client.surface.context.rotate(this.rad(mode * 90))
+    client.surface.context.translate(offset.x[mode], offset.y[mode])
+    client.surface.context.drawImage(copy, 0, 0)
+    client.surface.context.restore()
   }
 
   this.mirror = { // Mirror canvas, methods: `x`, `y`.
     x: async (j = 0) => {
       const copy = await this.copy()
       const frame = this['get-frame']()
-      ronin.surface.context.save()
-      ronin.surface.context.translate(frame.w, 0)
-      ronin.surface.context.scale(-1, 1)
-      ronin.surface.context.drawImage(copy, 0, 0)
-      ronin.surface.context.restore()
+      client.surface.context.save()
+      client.surface.context.translate(frame.w, 0)
+      client.surface.context.scale(-1, 1)
+      client.surface.context.drawImage(copy, 0, 0)
+      client.surface.context.restore()
     },
     y: async (j = 0) => {
       const copy = await this.copy()
       const frame = this['get-frame']()
-      ronin.surface.context.save()
-      ronin.surface.context.translate(0, frame.h)
-      ronin.surface.context.scale(1, -1)
-      ronin.surface.context.drawImage(copy, 0, 0)
-      ronin.surface.context.restore()
+      client.surface.context.save()
+      client.surface.context.translate(0, frame.h)
+      client.surface.context.scale(1, -1)
+      client.surface.context.drawImage(copy, 0, 0)
+      client.surface.context.restore()
     }
   }
 
@@ -176,52 +176,52 @@ function Library (ronin) {
 
   this.transform = { // The transform toolkit, methods `push`, `pop`, `reset`, `move`, `scale`, `rotate`.
     push: () => {
-      ronin.surface.context.save()
+      client.surface.context.save()
     },
     pop: () => {
-      ronin.surface.context.restore()
+      client.surface.context.restore()
     },
     reset: () => {
-      ronin.surface.context.resetTransform()
-      ronin.surface.guide.resetTransform()
+      client.surface.context.resetTransform()
+      client.surface.guide.resetTransform()
     },
     move: (x, y) => {
-      ronin.surface.context.translate(x, y)
+      client.surface.context.translate(x, y)
       this.guide(this.line(0, 0, x, y))
-      ronin.surface.guide.translate(x, y)
+      client.surface.guide.translate(x, y)
     },
     scale: (w, h) => {
-      ronin.surface.context.scale(w, h === undefined ? w : h)
+      client.surface.context.scale(w, h === undefined ? w : h)
       this.guide(this.rect(0, 0, 50 * w, 50 * h))
-      ronin.surface.guide.scale(w, h === undefined ? w : h)
+      client.surface.guide.scale(w, h === undefined ? w : h)
     },
     rotate: (a) => {
-      ronin.surface.context.rotate(a)
+      client.surface.context.rotate(a)
       this.guide(this.arc(0, 0, 50, 0, a))
-      ronin.surface.guide.rotate(a)
+      client.surface.guide.rotate(a)
     }
   }
 
   // Actions
 
   this.stroke = (shape, color, thickness = 2) => { // Strokes a shape.
-    ronin.surface.stroke(shape, color, thickness)
+    client.surface.stroke(shape, color, thickness)
     return shape
   }
 
   this.fill = (rect = this['get-frame'](), color) => { // Fills a shape.
-    ronin.surface.fill(rect, color)
+    client.surface.fill(rect, color)
     return rect
   }
 
   this.clear = (rect = this['get-frame']()) => { // Clears a rect.
-    ronin.surface.clearGuide(rect)
-    ronin.surface.clear(rect)
+    client.surface.clearGuide(rect)
+    client.surface.clear(rect)
     return rect
   }
 
   this.gradient = (line, colors = ['white', 'black']) => { // Defines a gradient color.
-    const gradient = ronin.surface.context.createLinearGradient(line.a.x, line.a.y, line.b.x, line.b.y)
+    const gradient = client.surface.context.createLinearGradient(line.a.x, line.a.y, line.b.x, line.b.y)
     colors.forEach((color, i) => {
       gradient.addColorStop(i * (1 / (colors.length - 1)), color)
     })
@@ -229,7 +229,7 @@ function Library (ronin) {
   }
 
   this.guide = (shape, color) => { // Draws a shape on the guide layer.
-    ronin.surface.drawGuide(shape, color)
+    client.surface.drawGuide(shape, color)
     return shape
   }
 
@@ -237,7 +237,7 @@ function Library (ronin) {
 
   this.pixels = async (fn, q = 1, rect = this['get-frame']()) => {
     if (!fn) { console.warn('Unknown function'); return rect }
-    const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
+    const img = client.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
     for (let i = 0, loop = img.data.length; i < loop; i += 4) {
       const pixel = [img.data[i], img.data[i + 1], img.data[i + 2], img.data[i + 3]]
       const processed = await fn(pixel, q)
@@ -246,7 +246,7 @@ function Library (ronin) {
       img.data[i + 2] = this.clamp(parseInt(processed[2]), 0, 255)
       img.data[i + 3] = this.clamp(parseInt(processed[3]), 0, 255)
     }
-    ronin.surface.context.putImageData(img, rect.x, rect.y)
+    client.surface.context.putImageData(img, rect.x, rect.y)
     return rect
   }
 
@@ -501,7 +501,7 @@ function Library (ronin) {
   this.convolve = (kernel, rect = this['get-frame']()) => {
     const sigma = kernel.flat().reduce((a, x) => (a + x))
     const kw = kernel[0].length; const kh = kernel.length
-    const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
+    const img = client.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
     const out = new Uint8ClampedArray(rect.w * 4 * rect.h)
     for (let i = 0, outer = img.data.length; i < outer; i++) { // bytes
       const ix = Math.floor(i / 4) % rect.w; const iy = Math.floor((i / 4) / rect.w)
@@ -516,7 +516,7 @@ function Library (ronin) {
       if (i % 4 === 3) out[i] = 255
     }
     img.data.set(out, 0)
-    ronin.surface.context.putImageData(img, rect.x, rect.y)
+    client.surface.context.putImageData(img, rect.x, rect.y)
     return rect
   }
 
@@ -552,7 +552,7 @@ function Library (ronin) {
     // return require('path').dirname(path)
   }
 
-  this.filepath = (path = ronin.source.path) => { // Returns the path of a file.
+  this.filepath = (path = client.source.path) => { // Returns the path of a file.
     // return path
   }
 
@@ -575,7 +575,7 @@ function Library (ronin) {
   }
 
   this.echo = (...args) => { // Print arguments to interface.
-    ronin.log(args)
+    client.log(args)
     return args
   }
 
@@ -593,7 +593,7 @@ function Library (ronin) {
   }
 
   this.on = (event, f) => { // Triggers on event.
-    ronin.bind(event, f)
+    client.bind(event, f)
   }
 
   this.test = (name, a, b) => {
@@ -615,10 +615,10 @@ function Library (ronin) {
   // Accessors
 
   this['get-theme'] = () => { // Get theme values.
-    return ronin.theme.active
+    return client.theme.active
   }
 
   this['get-frame'] = () => { // Get theme values.
-    return ronin.surface.getFrame()
+    return client.surface.getFrame()
   }
 }
diff --git a/desktop/sources/scripts/surface.js b/desktop/sources/scripts/surface.js
index 7782afb..38c3a9e 100644
--- a/desktop/sources/scripts/surface.js
+++ b/desktop/sources/scripts/surface.js
@@ -3,7 +3,7 @@
 /* global Path2D */
 /* global Image */
 
-function Surface (ronin) {
+function Surface (client) {
   this.el = document.createElement('canvas')
   this.el.id = 'surface'
   this._guide = document.createElement('canvas')
@@ -19,14 +19,14 @@ function Surface (ronin) {
     host.appendChild(this.el)
     host.appendChild(this._guide)
     window.addEventListener('resize', (e) => { this.onResize() }, false)
-    this._guide.addEventListener('mousedown', ronin.onMouseDown, false)
-    this._guide.addEventListener('mousemove', ronin.onMouseMove, false)
-    this._guide.addEventListener('mouseup', ronin.onMouseUp, false)
-    this._guide.addEventListener('mouseover', ronin.onMouseOver, false)
-    this._guide.addEventListener('mouseout', ronin.onMouseOut, false)
-    this._guide.addEventListener('keydown', ronin.onKeyDown, false)
-    this._guide.addEventListener('keyup', ronin.onKeyUp, false)
-    this._guide.addEventListener('keypress', ronin.onKeyPress, false)
+    this._guide.addEventListener('mousedown', client.onMouseDown, false)
+    this._guide.addEventListener('mousemove', client.onMouseMove, false)
+    this._guide.addEventListener('mouseup', client.onMouseUp, false)
+    this._guide.addEventListener('mouseover', client.onMouseOver, false)
+    this._guide.addEventListener('mouseout', client.onMouseOut, false)
+    this._guide.addEventListener('keydown', client.onKeyDown, false)
+    this._guide.addEventListener('keyup', client.onKeyUp, false)
+    this._guide.addEventListener('keypress', client.onKeyPress, false)
   }
 
   this.start = function () {
@@ -34,16 +34,16 @@ function Surface (ronin) {
   }
 
   this.onResize = function () {
-    if (ronin.commander._input.value === '') {
+    if (client.commander._input.value === '') {
       this.maximize()
     }
     const f = this.getFrame()
-    ronin.log(`resize ${f.w}x${f.h}`)
+    client.log(`resize ${f.w}x${f.h}`)
   }
 
   // Shape
 
-  this.stroke = (shape, color = ronin.theme.get('f_high'), width = 2, context = this.context) => {
+  this.stroke = (shape, color = client.theme.get('f_high'), width = 2, context = this.context) => {
     context.beginPath()
     this.trace(shape, context)
     context.lineWidth = width
@@ -66,7 +66,7 @@ function Surface (ronin) {
 
   // Fill
 
-  this.fill = (shape, color = ronin.theme.get('b_high'), context = this.context) => {
+  this.fill = (shape, color = client.theme.get('b_high'), context = this.context) => {
     context.beginPath()
     context.fillStyle = typeof color === 'object' && color.rgba ? color.rgba : color
     this.trace(shape, context)
@@ -210,7 +210,7 @@ function Surface (ronin) {
   }
 
   this.crop = function (rect) {
-    ronin.log(`Crop ${rect.w}x${rect.h} from ${rect.x}x${rect.y}`)
+    client.log(`Crop ${rect.w}x${rect.h} from ${rect.x}x${rect.y}`)
     const crop = this.copy(rect)
     this.resize(rect, true)
     this.context.drawImage(crop, 0, 0)
diff --git a/index.html b/index.html
index 962c134..53d6650 100644
--- a/index.html
+++ b/index.html
@@ -5,7 +5,7 @@
     <script type="text/javascript" src="desktop/sources/scripts/lib/acels.js"></script>
     <script type="text/javascript" src="desktop/sources/scripts/lib/lisp.js"></script>
     <script type="text/javascript" src="desktop/sources/scripts/lib/source.js"></script>
-    <script type="text/javascript" src="desktop/sources/scripts/ronin.js"></script>
+    <script type="text/javascript" src="desktop/sources/scripts/client.js"></script>
     <script type="text/javascript" src="desktop/sources/scripts/commander.js"></script>
     <script type="text/javascript" src="desktop/sources/scripts/surface.js"></script>
     <script type="text/javascript" src="desktop/sources/scripts/library.js"></script>
@@ -17,12 +17,12 @@
   </head>
   <body>
     <script type="text/javascript">
-      const ronin = new Ronin()
+      const client = new Client()
 
-      ronin.install(document.body)
+      client.install(document.body)
 
       window.addEventListener('load', () => { 
-        ronin.start() 
+        client.start() 
       })
     </script>
   </body>