bfg-common 1.5.686 → 1.5.688

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/CODE_STYLE.md +109 -109
  2. package/assets/img/icons/icons-sprite-dark-3.svg +227 -227
  3. package/assets/img/icons/icons-sprite-dark-5.svg +488 -488
  4. package/assets/img/icons/icons-sprite-light-3.svg +227 -227
  5. package/assets/img/icons/icons-sprite-light-5.svg +488 -488
  6. package/assets/localization/local_be.json +3783 -3782
  7. package/assets/localization/local_en.json +3787 -3786
  8. package/assets/localization/local_hy.json +1 -0
  9. package/assets/localization/local_kk.json +1 -0
  10. package/assets/localization/local_ru.json +1 -0
  11. package/assets/localization/local_zh.json +1 -0
  12. package/assets/scss/components/auth.scss +5 -15
  13. package/components/atoms/TheIcon3.vue +50 -50
  14. package/components/atoms/collapse/CollapseNav.vue +170 -170
  15. package/components/atoms/perPage/PerPage.vue +58 -58
  16. package/components/atoms/table/dataGrid/DataGrid.vue +1718 -1718
  17. package/components/atoms/table/dataGrid/DataGridPagination.vue +97 -97
  18. package/components/atoms/table/dataGrid/lib/config/settingsTable.ts +94 -94
  19. package/components/atoms/table/dataGrid/lib/utils/export.ts +16 -16
  20. package/components/common/backup/storage/actions/add/lib/utils.ts +51 -51
  21. package/components/common/browse/blocks/contents/filesNew/Skeleton.vue +18 -18
  22. package/components/common/diagramMain/modals/lib/config/vCenterModal.ts +48 -48
  23. package/components/common/diagramMain/port/Port.vue +580 -580
  24. package/components/common/layout/theHeader/TheHeaderNew.vue +315 -315
  25. package/components/common/layout/theHeader/TheHeaderOld.vue +262 -262
  26. package/components/common/layout/theHeader/helpMenu/About.vue +79 -79
  27. package/components/common/layout/theHeader/helpMenu/aboutOld/AboutOld.vue +79 -79
  28. package/components/common/layout/theHeader/userMenu/modals/preferences/PreferencesNew.vue +115 -102
  29. package/components/common/layout/theHeader/userMenu/modals/preferences/PreferencesOld.vue +144 -144
  30. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/ChangeLanguage.vue +108 -115
  31. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/{ChangeLanguageNew.vue → New.vue} +88 -89
  32. package/components/common/layout/theHeader/userMenu/modals/preferences/changeLanguage/{ChangeLanguageOld.vue → Old.vue} +89 -91
  33. package/components/common/layout/theHeader/userMenu/modals/preferences/defaultConsole/DefaultConsole.vue +43 -42
  34. package/components/common/layout/theHeader/userMenu/modals/preferences/defaultConsole/{DefaultConsoleNew.vue → New.vue} +53 -53
  35. package/components/common/layout/theHeader/userMenu/modals/preferences/defaultConsole/{DefaultConsoleOld.vue → Old.vue} +49 -49
  36. package/components/common/layout/theHeader/userMenu/modals/preferences/inventory/Inventory.vue +31 -32
  37. package/components/common/layout/theHeader/userMenu/modals/preferences/inventory/{InventoryNew.vue → New.vue} +36 -35
  38. package/components/common/layout/theHeader/userMenu/modals/preferences/inventory/{InventoryOld.vue → Old.vue} +31 -31
  39. package/components/common/layout/theHeader/userMenu/modals/preferences/lib/models/types.ts +7 -7
  40. package/components/common/layout/theHeader/userMenu/modals/preferences/security/New.vue +34 -17
  41. package/components/common/layout/theHeader/userMenu/modals/preferences/security/Old.vue +216 -216
  42. package/components/common/layout/theHeader/userMenu/modals/preferences/security/Security.vue +31 -31
  43. package/components/common/layout/theHeader/userMenu/modals/preferences/timeFormat/{TimeFormatNew.vue → New.vue} +52 -52
  44. package/components/common/layout/theHeader/userMenu/modals/preferences/timeFormat/{TimeFormatOld.vue → Old.vue} +45 -45
  45. package/components/common/layout/theHeader/userMenu/modals/preferences/timeFormat/TimeFormat.vue +54 -54
  46. package/components/common/layout/theHeader/userMenu/modals/preferences/view/{ViewNew.vue → New.vue} +47 -38
  47. package/components/common/layout/theHeader/userMenu/modals/preferences/view/{ViewOld.vue → Old.vue} +112 -112
  48. package/components/common/layout/theHeader/userMenu/modals/preferences/view/View.vue +46 -45
  49. package/components/common/pages/backups/DetailView.vue +52 -52
  50. package/components/common/pages/backups/lib/models/interfaces.ts +36 -36
  51. package/components/common/pages/backups/modals/Modals.vue +243 -243
  52. package/components/common/pages/backups/modals/createBackup/configuration/maxBandwidth/lib/config/options.ts +6 -6
  53. package/components/common/pages/backups/modals/createBackup/lib/config/readyToCompleteOptions.ts +69 -69
  54. package/components/common/pages/backups/modals/lib/config/restore.ts +115 -115
  55. package/components/common/pages/backups/modals/lib/models/interfaces.ts +186 -186
  56. package/components/common/pages/backups/modals/restore/name/lib/models/interfaces.ts +6 -6
  57. package/components/common/pages/home/lib/models/interfaces.ts +48 -48
  58. package/components/common/pages/home/widgets/hosts/Hosts.vue +27 -27
  59. package/components/common/pages/home/widgets/hosts/lib/config/items.ts +23 -23
  60. package/components/common/pages/home/widgets/vms/VmsOld.vue +35 -35
  61. package/components/common/pages/home/widgets/vms/lib/config/items.ts +19 -19
  62. package/components/common/pages/scheduledTasks/lib/utils/utils.ts +84 -84
  63. package/components/common/qr/Qr.vue +57 -57
  64. package/components/common/readyToComplete/ReadyToComplete.vue +17 -17
  65. package/components/common/select/radio/RadioGroup.vue +137 -137
  66. package/components/common/spiceConsole/Drawer.vue +420 -420
  67. package/components/common/spiceConsole/SpiceConsole.vue +184 -184
  68. package/components/common/spiceConsole/lib/models/interfaces.ts +5 -5
  69. package/components/common/tools/Actions.vue +207 -207
  70. package/components/common/treeView/TreeView.vue +52 -52
  71. package/components/common/vm/actions/clone/lib/config/steps.ts +295 -295
  72. package/components/common/vm/actions/clone/new/New.vue +438 -438
  73. package/components/common/vm/actions/common/customizeHardware/virtualHardware/VirtualHardware.vue +706 -706
  74. package/components/common/vm/actions/common/customizeHardware/virtualHardware/cpu/shares/lib/config/options.ts +28 -28
  75. package/components/common/vm/actions/common/customizeHardware/virtualHardware/memory/Memory.vue +283 -283
  76. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newHardDisk/NewHardDisk.vue +489 -489
  77. package/components/common/vm/actions/common/customizeHardware/virtualHardware/newPciDevice/NewPciDevice.vue +253 -253
  78. package/components/common/vm/actions/common/customizeHardware/vmoptions/bootOptions/order/Order.vue +156 -156
  79. package/components/common/vm/actions/common/select/compatibility/Old.vue +107 -107
  80. package/components/common/vm/actions/common/select/createType/lib/models/interfaces.ts +5 -5
  81. package/components/common/vm/actions/common/select/options/New.vue +264 -264
  82. package/components/common/vm/actions/common/select/options/Old.vue +109 -109
  83. package/components/common/vm/actions/common/select/options/Options.vue +58 -58
  84. package/components/common/vm/actions/common/select/storage/Old.vue +125 -125
  85. package/components/common/vm/actions/common/select/storage/new/New.vue +311 -311
  86. package/components/common/vm/actions/common/select/storage/new/lib/models/interfaces.ts +5 -5
  87. package/components/common/vm/actions/common/select/storage/new/lib/utils/utils.ts +21 -21
  88. package/components/common/vm/actions/common/select/template/old/Old.vue +50 -50
  89. package/components/common/vm/actions/editSettings/new/Skeleton.vue +88 -88
  90. package/components/common/wizards/common/compatibility/Compatibility.vue +35 -35
  91. package/components/common/wizards/common/compatibility/New.vue +99 -99
  92. package/components/common/wizards/common/compatibility/Old.vue +53 -53
  93. package/components/common/wizards/common/steps/computeResource/New.vue +93 -93
  94. package/components/common/wizards/common/steps/name/Name.vue +178 -178
  95. package/components/common/wizards/common/steps/name/New.vue +221 -221
  96. package/components/common/wizards/common/steps/name/Old.vue +121 -121
  97. package/components/common/wizards/common/steps/name/lib/models/interfaces.ts +4 -4
  98. package/components/common/wizards/common/steps/name/location/New.vue +40 -40
  99. package/components/common/wizards/datastore/add/Add.vue +228 -228
  100. package/components/common/wizards/datastore/add/lib/utils.ts +85 -85
  101. package/components/common/wizards/datastore/add/steps/nameAndDevice/NameAndDeviceNew.vue +232 -232
  102. package/components/common/wizards/datastore/add/steps/nameAndDevice/NameAndDeviceOld.vue +231 -231
  103. package/components/common/wizards/datastore/add/steps/nameAndDevice/advancedOptions/AdvancedOptions.vue +43 -43
  104. package/components/common/wizards/datastore/add/steps/nameAndDevice/advancedOptions/New.vue +101 -101
  105. package/components/common/wizards/datastore/add/steps/nameAndDevice/advancedOptions/Old.vue +101 -101
  106. package/components/common/wizards/datastore/add/steps/typeMode/lib/config/typeOptions.ts +43 -43
  107. package/composables/useAppVersion.ts +21 -21
  108. package/composables/useEnvLanguage.ts +22 -22
  109. package/composables/useLocal.ts +6 -6
  110. package/composables/useLocalCommon.ts +39 -39
  111. package/package.json +2 -2
  112. package/plugins/console.ts +21 -21
  113. package/plugins/mouse.ts +21 -21
  114. package/plugins/panelStates.ts +70 -70
  115. package/plugins/text.ts +59 -59
  116. package/public/spice-console/application/clientgui.js +854 -854
  117. package/public/spice-console/application/packetfactory.js +211 -211
  118. package/public/spice-console/application/virtualmouse.js +147 -147
  119. package/public/spice-console/lib/images/bitmap.js +203 -203
  120. package/public/spice-console/network/spicechannel.js +440 -440
  121. package/public/spice-console/process/cursorprocess.js +128 -128
  122. package/public/spice-console/process/inputprocess.js +227 -227
  123. package/public/spice-console/process/mainprocess.js +212 -212
  124. package/public/spice-console/run.js +210 -210
  125. package/store/main/mutations.ts +7 -7
  126. package/store/main/state.ts +7 -7
  127. package/store/tasks/mappers/recentTasks.ts +123 -123
  128. package/store/tasks/mutations.ts +82 -82
@@ -1,854 +1,854 @@
1
- /*
2
- Copyright (c) 2016 eyeOS
3
-
4
- This file is part of Open365.
5
-
6
- Open365 is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU Affero General Public License as
8
- published by the Free Software Foundation, either version 3 of the
9
- License, or (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU Affero General Public License for more details.
15
-
16
- You should have received a copy of the GNU Affero General Public License
17
- along with this program. If not, see <http://www.gnu.org/licenses/>.
18
- */
19
-
20
- wdi.SPICE_INPUT_MOTION_ACK_BUNCH = 8
21
-
22
- wdi.ClientGui = $.spcExtend(wdi.EventObject.prototype, {
23
- width: null,
24
- height: null,
25
- canvas: null,
26
- ack_wait: 0,
27
- mouse_mode: 0,
28
- mouse_status: 0,
29
- eventLayer: null,
30
- counter: 0,
31
- mainCanvas: 0,
32
- firstTime: true,
33
- clientOffsetX: 0,
34
- clientOffsetY: 0,
35
- magnifier: null,
36
- magnifierBackground: null,
37
- firstMove: true,
38
- isMagnified: true,
39
- isMouseDown: false,
40
- soundStarted: false,
41
- canvasMarginY: 0,
42
- canvasMarginX: 0,
43
- stuckKeysHandler: null,
44
- isKeyboardEnabled: false,
45
-
46
- subCanvas: {},
47
- inputManager: null,
48
- clipboardEnabled: true,
49
- layer: null,
50
- freezeClass: 'freeze',
51
- app: {},
52
-
53
- init: function (c) {
54
- this.time = Date.now()
55
- this.canvas = {}
56
- this.contexts = {}
57
- this.superInit()
58
- this.magnifier = window
59
- .$('<canvas/>')
60
- .attr({
61
- width: 150,
62
- height: 150,
63
- })
64
- .css({
65
- position: 'absolute',
66
- left: '0px',
67
- top: '0px',
68
- })
69
- this.stuckKeysHandler = c.stuckKeysHandler || new wdi.StuckKeysHandler()
70
- this.settings = c.settings || {}
71
- this.stuckKeysHandler.addListener(
72
- 'inputStuck',
73
- this._sendInput.bind(this),
74
- this
75
- )
76
-
77
- //load magnifier background
78
- this.magnifierBackground = window.$('<img/>')
79
- this.magnifierBackground.attr(
80
- 'src',
81
- '/spice-console/resources/magnifier.png'
82
- )
83
- this.initSound()
84
- this.inputManager =
85
- c.inputManager ||
86
- new wdi.InputManager({
87
- stuckKeysHandler: this.stuckKeysHandler,
88
- window: $(window),
89
- })
90
- this.inputManager.setCurrentWindow(window)
91
- this.clipBoardDataParser =
92
- c.clipBoardDataParser || new wdi.ClipboardDataParser({})
93
- this.localClipboard =
94
- c.localClipboard || new wdi.LocalClipboard({ clientGui: this })
95
- this.app = c.app
96
-
97
- var self = this
98
- this.eventHandlers = {
99
- hide: function () {
100
- self.stuckKeysHandler.releaseAllKeys()
101
- },
102
- }
103
- window.$(document).on(this.eventHandlers)
104
- },
105
-
106
- dispose: function () {
107
- wdi.Debug.log('Disposing ClientGui')
108
- $(document).off(this.eventHandlers)
109
- this.unbindDOM()
110
- this.removeAllCanvases()
111
- this.inputManager.dispose()
112
- this.stuckKeysHandler.dispose()
113
- this.localClipboard.dispose()
114
-
115
- this.width = null
116
- this.height = null
117
- this.canvas = null
118
- this.ack_wait = 0
119
- this.mouse_mode = 0
120
- this.mouse_status = 0
121
- this.eventLayer = null
122
- this.counter = 0
123
- this.mainCanvas = 0
124
- this.firstTime = true
125
- this.clientOffsetX = 0
126
- this.clientOffsetY = 0
127
- this.magnifier = null
128
- this.magnifierBackground = null
129
- this.firstMove = true
130
- this.isMagnified = true
131
- this.isMouseDown = false
132
- this.soundStarted = false
133
- this.canvasMarginY = 0
134
- this.canvasMarginX = 0
135
- this.stuckKeysHandler = null
136
- this.subCanvas = {}
137
- this.inputManager = null
138
- this.clipboardEnabled = true
139
- this.layer = null
140
- clearInterval(self.rightClickTimer) //cancel, this is not a right click
141
- clearInterval(self.mouseDownTimer) //cancel
142
- },
143
-
144
- removeAllCanvases: function () {
145
- var self = this
146
- Object.keys(this.canvas).forEach(function (key) {
147
- $(self.canvas[key]).remove()
148
- delete self.canvas[key]
149
- delete self.contexts[key]
150
- })
151
- $(this.eventLayer).remove()
152
- this.eventLayer = null
153
- },
154
-
155
- unbindDOM: function () {
156
- if (this.eventLayer) {
157
- var events = [
158
- 'touchstart',
159
- 'touchmove',
160
- 'touchend',
161
- 'mouseup',
162
- 'mousedown',
163
- 'mousemove',
164
- 'contextmenu',
165
- 'mousewheel',
166
- ]
167
- events.forEach(function (event) {
168
- $(this.eventLayer).unbind(event)
169
- })
170
- }
171
- },
172
-
173
- freeze: function () {
174
- if (this.canvas[0]) {
175
- var image = new Image()
176
- var cnv = this.canvas[0]
177
- var $cnv = $(cnv)
178
- $(image).attr('style', $cnv.attr('style'))
179
- $(image).attr('class', this.freezeClass)
180
- image.src = cnv.toDataURL('image/png')
181
- $cnv.parent().append($(image))
182
- }
183
- },
184
-
185
- cancelFreeze: function () {
186
- $('.' + this.freezeClass).remove()
187
- },
188
-
189
- setLayer: function (layer) {
190
- this.layer = layer
191
- },
192
-
193
- disableClipboard: function () {
194
- this.clipboardEnabled = false
195
- },
196
-
197
- _sendInput: function (params) {
198
- var data = params
199
- var type = data[0]
200
- var event = data[1]
201
- this.fire('input', [type, event])
202
- },
203
-
204
- releaseAllKeys: function () {
205
- this.stuckKeysHandler.releaseAllKeys()
206
- },
207
-
208
- getContext: function (surface_id) {
209
- return this.contexts[surface_id]
210
- },
211
-
212
- getCanvas: function (surface_id) {
213
- return this.canvas[surface_id]
214
- },
215
-
216
- checkFeatures: function () {
217
- if (!Modernizr.canvas || !Modernizr.websockets) {
218
- alert(
219
- 'Your Browser is not compatible with WDI. Visit ... for a list of compatible browsers'
220
- )
221
- return false
222
- }
223
- return true
224
- },
225
-
226
- deleteSubCanvas: function (window) {
227
- var obj = this.subCanvas[window['hwnd']]
228
- this.subCanvas[window['hwnd']] = null
229
- return obj
230
- },
231
-
232
- moveSubCanvas: function (window) {
233
- var obj = this.subCanvas[window['hwnd']]
234
- obj['info'] = window
235
- this._fillSubCanvasFromWindow(window)
236
- return obj
237
- },
238
-
239
- resizeSubCanvas: function (window) {
240
- var obj = this.subCanvas[window['hwnd']]
241
- $([obj['canvas'], obj['eventLayer']]).attr({
242
- width: window['width'],
243
- height: window['height'],
244
- })
245
- obj['info'] = window
246
- this._fillSubCanvasFromWindow(window)
247
- return obj
248
- },
249
-
250
- _fillSubCanvasFromWindow: function (window) {
251
- var top = parseInt(window.top, 10)
252
- var left = parseInt(window.left, 10)
253
- var width = parseInt(window.width, 10)
254
- var height = parseInt(window.height, 10)
255
- this.fillSubCanvas({
256
- top: top,
257
- left: left,
258
- right: left + width,
259
- bottom: top + height,
260
- })
261
- },
262
-
263
- createNewSubCanvas: function (window) {
264
- var evtlayer = this.createEventLayer(
265
- window['hwnd'] + '_event',
266
- window['width'],
267
- window['height']
268
- )
269
- this.subCanvas[window['hwnd']] = {
270
- canvas: $('<canvas/>')
271
- .attr({
272
- width: window['width'],
273
- height: window['height'],
274
- })
275
- .css({
276
- display: window['iconic'] ? 'none' : 'block',
277
- })[0],
278
- eventLayer: evtlayer,
279
- info: window,
280
- position: 0,
281
- }
282
- //we have the main area drawn?
283
- if (this.canvas[this.mainCanvas]) {
284
- this._fillSubCanvasFromWindow(window)
285
- }
286
- return [this.subCanvas[window['hwnd']]]
287
- },
288
-
289
- fillSubCanvas: function (filterPosition) {
290
- var canvas = this.canvas[this.mainCanvas]
291
- var info = null
292
- for (var i in this.subCanvas) {
293
- if (
294
- this.subCanvas[i] != null &&
295
- this.subCanvas[i] !== undefined &&
296
- this.subCanvas.hasOwnProperty(i)
297
- ) {
298
- info = this.subCanvas[i]['info']
299
- if (filterPosition != null || filterPosition != undefined) {
300
- var top = parseInt(info['top'], 10)
301
- var left = parseInt(info['left'], 10)
302
- var width = parseInt(info['width'], 10)
303
- var height = parseInt(info['height'], 10)
304
- var position = {
305
- top: top,
306
- left: left,
307
- right: left + width,
308
- bottom: top + height,
309
- }
310
- if (
311
- wdi.CollisionDetector.thereIsBoxCollision(position, filterPosition)
312
- ) {
313
- this._doDrawSubCanvas(canvas, this.subCanvas[i], info)
314
- }
315
- } else {
316
- this._doDrawSubCanvas(canvas, this.subCanvas[i], info)
317
- }
318
- }
319
- }
320
- },
321
-
322
- _doDrawSubCanvas: function (canvas, subCanvas, info) {
323
- if (
324
- this.canvas[this.mainCanvas] == null ||
325
- this.canvas[this.mainCanvas] == undefined
326
- ) {
327
- return
328
- }
329
- var destCtx = null
330
- if (info['iconic'] === 0) {
331
- var destCanvas = subCanvas['canvas']
332
- destCtx = destCanvas.getContext('2d')
333
-
334
- var x = 0
335
- var y = 0
336
- var width = +info.width
337
- var height = +info.height
338
- var left = +info['left']
339
- var top = +info['top']
340
-
341
- if (left < 0) {
342
- width = width + left
343
- x = -left
344
- left = 0
345
- }
346
-
347
- if (top < 0) {
348
- height = height + top
349
- y = -top
350
- top = 0
351
- }
352
-
353
- try {
354
- // if width or height are less than 1 or a float
355
- // drawImage fails in firefox (ERROR: IndexSizeError)
356
- width = Math.max(1, Math.floor(width))
357
- height = Math.max(1, Math.floor(height))
358
- if (width > canvas.width) width = canvas.width
359
- if (height > canvas.height) height = canvas.height
360
- destCtx.drawImage(canvas, left, top, width, height, x, y, width, height)
361
- } catch (err) {
362
- wdi.Debug.error(err)
363
- }
364
- }
365
- },
366
-
367
- removeCanvas: function (spiceMessage) {
368
- var surface = spiceMessage.args
369
- if (surface.surface_id === this.mainCanvas) {
370
- $(this.eventLayer).remove()
371
- this.eventLayer = null
372
- }
373
-
374
- this.canvas[surface.surface_id].keepAlive = false
375
- delete this.canvas[surface.surface_id]
376
- delete this.contexts[surface.surface_id]
377
- },
378
-
379
- drawCanvas: function (spiceMessage) {
380
- wdi.Debug.log('clientgui time: ', this.time)
381
- var surface = spiceMessage.args
382
-
383
- // // Custom code
384
- // // Проверяем если ширина вм-а меньше ширины окна, вставляем по центру
385
- // if (surface.width < window.innerWidth) {
386
- // const x = (window.innerWidth - surface.width) / 2
387
- // this.setCanvasMargin({
388
- // x,
389
- // y: this.canvasMarginY,
390
- // })
391
- // this.setClientOffset(-x, this.canvasMarginY)
392
- // }
393
- // // Custom code End
394
-
395
- var cnv = wdi.GlobalPool.create('Canvas')
396
- cnv.keepAlive = true //prevent this canvas to return to the pool by packetfilter
397
-
398
- cnv.id = 'canvas_' + surface.surface_id
399
- cnv.width = surface.width * this.pixelRatio
400
- cnv.height = surface.height * this.pixelRatio
401
- cnv.style.position = 'absolute'
402
- cnv.style.top = this.canvasMarginY + 'px'
403
- cnv.style.left = this.canvasMarginX + 'px'
404
- cnv.style.width = surface.width + 'px'
405
- cnv.style.height = surface.height + 'px'
406
-
407
- this.canvas[surface.surface_id] = cnv
408
- this.contexts[surface.surface_id] = cnv.getContext('2d')
409
-
410
- if (surface.flags && !wdi.SeamlessIntegration) {
411
- this.mainCanvas = surface.surface_id
412
-
413
- this.eventLayer = this.createEventLayer(
414
- 'eventLayer',
415
- surface.width,
416
- surface.height
417
- )
418
-
419
- var evLayer = $(this.eventLayer).css({
420
- position: 'absolute',
421
- top: this.canvasMarginY + 'px',
422
- left: this.canvasMarginX + 'px',
423
- })[0]
424
-
425
- if (this.layer) {
426
- this.layer.appendChild(cnv)
427
- this.layer.appendChild(evLayer)
428
- } else {
429
- document.body.appendChild(cnv)
430
- document.body.appendChild(evLayer)
431
- }
432
- !this.isKeyboardEnabled && this.enableKeyboard()
433
- }
434
-
435
- //this goes here?
436
- if (this.firstTime && this.clipboardEnabled) {
437
- var self = this
438
- var PASTES_PER_SECOND = this.settings.PASTES_PER_SECOND || 5
439
-
440
- var firePaste = _.throttle(function (data) {
441
- self.fire('paste', data)
442
- }, 1000 / PASTES_PER_SECOND)
443
-
444
- $(document).bind('paste', function (event) {
445
- self.clipBoardDataParser.parse(
446
- event.originalEvent.clipboardData,
447
- firePaste
448
- )
449
- })
450
-
451
- $(document).bind('copy', function (e) {
452
- self.app.sendShortcut(wdi.keyShortcutsHandled.CTRLC)
453
- })
454
-
455
- this.firstTime = false
456
- }
457
-
458
- //notify about resolution
459
- if (surface.flags) {
460
- this.fire('resolution', [
461
- this.canvas[surface.surface_id].width,
462
- this.canvas[surface.surface_id].height,
463
- ])
464
- }
465
- },
466
-
467
- disableKeyboard: function () {
468
- var documentDOM = window.$(window.document)
469
- documentDOM.unbind('keydown', this.handleKey)
470
- documentDOM.unbind('keyup', this.handleKey)
471
- documentDOM.unbind('keypress', this.handleKey)
472
- this.inputManager.disable()
473
- },
474
-
475
- enableKeyboard: function () {
476
- var self = this,
477
- documentDOM = window.$(window.document)
478
- documentDOM['keydown']([self], this.handleKey)
479
- documentDOM['keypress']([self], this.handleKey)
480
- documentDOM['keyup']([self], this.handleKey)
481
- this.inputManager.enable()
482
- !this.isKeyboardEnabled && (this.isKeyboardEnabled = true)
483
- },
484
-
485
- setCanvasMargin: function (canvasMargin) {
486
- this.canvasMarginX = canvasMargin.x
487
- this.canvasMarginY = canvasMargin.y
488
- },
489
-
490
- createEventLayer: function (event_id, width, height) {
491
- var self = this
492
-
493
- var eventLayer = $('<canvas/>')
494
- .css({
495
- cursor: 'default',
496
- position: 'absolute',
497
- })
498
- .attr({
499
- id: event_id,
500
- // width: window.innerWidth,
501
- // height: window.innerHeight
502
- // Правильнее слой события делать с размером самого вм-а
503
- width, // Custom code
504
- height, // Custom code
505
- })
506
-
507
- if (window['bowser']['firefox']) {
508
- eventLayer.attr('contentEditable', true)
509
- }
510
-
511
- eventLayer.bind('touchstart', function (event) {
512
- event.preventDefault()
513
- var touch =
514
- event.originalEvent.touches[0] || event.originalEvent.changedTouches[0]
515
- var x = touch.pageX
516
- var y = touch.pageY
517
- self.generateEvent.call(self, 'mousemove', [
518
- x + self.clientOffsetX,
519
- y + self.clientOffsetY,
520
- self.mouse_status,
521
- ])
522
- if (event.originalEvent.touches.length === 1) {
523
- self.enabledTouchMove = true
524
- self.launchRightClick.call(self, x, y)
525
- } else if (event.originalEvent.touches.length === 2) {
526
- self.touchX = x
527
- self.touchY = y
528
- self.enabledTouchMove = false
529
- } else if (event.originalEvent.touches.length === 3) {
530
- self.touchY3 = y
531
- self.enabledTouchMove = false
532
- }
533
- })
534
-
535
- eventLayer.bind('touchmove', function (event) {
536
- var touch =
537
- event.originalEvent.touches[0] || event.originalEvent.changedTouches[0]
538
- var x = touch.pageX
539
- var y = touch.pageY
540
- //TODO: ignore first move
541
- if (event.originalEvent.touches.length === 1 && self.enabledTouchMove) {
542
- self.isMagnified = true //magnified!
543
- clearInterval(self.rightClickTimer) //cancel, this is not a right click
544
-
545
- if (!self.isMouseDown) {
546
- clearInterval(self.mouseDownTimer) //cancel, not enough time to send mousedown
547
- self.launchMouseDown() //fire again
548
- }
549
-
550
- self.generateEvent.call(self, 'mousemove', [
551
- x + self.clientOffsetX,
552
- y + self.clientOffsetY - 80,
553
- self.mouse_status,
554
- ])
555
- var pos = $(this).offset()
556
- var myX = x - pos.left
557
- var myY = y - pos.top
558
-
559
- //draw magnifier
560
- if (self.firstMove) {
561
- $('body').append(self.magnifier) //TODO: append to body?
562
- self.firstMove = false
563
- }
564
-
565
- var posX = myX - 75
566
- var posY = myY - 160
567
-
568
- self.magnifier.css({
569
- left: posX,
570
- top: posY,
571
- })
572
-
573
- //fill magnifier
574
- var ctx = self.magnifier[0].getContext('2d')
575
- ctx.clearRect(0, 0, 150, 150)
576
- ctx.save()
577
- ctx.beginPath()
578
- ctx.arc(75, 75, 75, 0, 2 * Math.PI, false)
579
- ctx.clip()
580
- ctx.drawImage(
581
- self.getCanvas(0),
582
- myX - 50, //-50 because we are going to get
583
- myY - 50 - 80, //100 px and we want the finder to be the center
584
- //-80 becasue the magnifier is 160px up (160/2)
585
- //we need to clean all this after the demo
586
- //is working
587
- 100,
588
- 100,
589
- 0,
590
- 0,
591
- 150,
592
- 150
593
- )
594
- // //draw the background
595
- ctx.drawImage(self.magnifierBackground[0], 0, 0)
596
- ctx.restore()
597
- //empty magnifier
598
- } else if (event.originalEvent.touches.length === 2) {
599
- var delta = self.touchY - y
600
- if (Math.abs(delta) > 10) {
601
- var button = delta > 0 ? 4 : 3
602
- self.touchX = x
603
- self.touchY = y
604
- self.generateEvent.call(self, 'mousedown', button)
605
- self.generateEvent.call(self, 'mouseup', button)
606
- }
607
- } else if (event.originalEvent.touches.length === 3) {
608
- var delta = self.touchY3 - y
609
- if (delta > 100) {
610
- document.getElementById('hiddeninput').select()
611
- }
612
- }
613
- event.preventDefault()
614
- })
615
-
616
- eventLayer.bind('touchend', function (event) {
617
- if (self.enabledTouchMove) {
618
- var touch =
619
- event.originalEvent.touches[0] ||
620
- event.originalEvent.changedTouches[0]
621
- var x = touch.pageX
622
- var y = touch.pageY
623
- if (!self.isMouseDown) {
624
- self.generateEvent.call(self, 'mousedown', 0)
625
- }
626
- self.isMouseDown = false
627
- self.generateEvent.call(self, 'mouseup', 0)
628
- var pos = $(this).offset()
629
-
630
- self.enabledTouchMove = false
631
- self.firstMove = true
632
- if (self.isMagnified) {
633
- self.magnifier.remove()
634
- }
635
- self.isMagnified = false
636
- }
637
- clearInterval(self.rightClickTimer) //cancel, this is not a right click
638
- clearInterval(self.mouseDownTimer) //cancel
639
- })
640
-
641
- //if (!Modernizr.touch) {
642
- eventLayer['mouseup'](function (event) {
643
- var button = event.button
644
-
645
- self.generateEvent.call(self, 'mouseup', button)
646
- self.mouse_status = 0
647
- event.preventDefault()
648
- })
649
-
650
- eventLayer['mousedown'](function (event) {
651
- var button = event.button
652
-
653
- self.generateEvent.call(self, 'mousedown', button)
654
- self.mouse_status = 1
655
- event.preventDefault()
656
- })
657
-
658
- eventLayer['mousemove'](function (event) {
659
- if (
660
- self.mouse_mode === wdi.SpiceMouseModeTypes.SPICE_MOUSE_MODE_SERVER &&
661
- event.bubbles
662
- )
663
- return // Custom code // TODO refactoring. event.bubbles используется так как если переключить mouseMode на серверную то mousemove срабатывает дважды
664
- var x = event.pageX
665
- var y = event.pageY
666
- // self.generateEvent.call(self, 'mousemove', [
667
- // (x + self.clientOffsetX) * self.pixelRatio,
668
- // (y + self.clientOffsetY) * self.pixelRatio,
669
- // self.mouse_status,
670
- // ])
671
- // Custom code
672
- self.generateEvent.call(self, 'mousemove', [
673
- (x + self.clientOffsetX - self.eventLayer.offsetLeft) * self.pixelRatio,
674
- (y + self.clientOffsetY - self.eventLayer.offsetTop) * self.pixelRatio,
675
- self.mouse_status,
676
- ])
677
- // Custom code End
678
- event.preventDefault()
679
- })
680
-
681
- eventLayer.bind('contextmenu', function (event) {
682
- event.preventDefault()
683
- return false
684
- })
685
- //}
686
-
687
- var mouseEventPause = false
688
-
689
- var fireWheel = _.throttle(function (event, delta) {
690
- var button = delta > 0 ? 3 : 4
691
-
692
- self.generateEvent.call(self, 'mousedown', button)
693
- self.generateEvent.call(self, 'mouseup', button)
694
-
695
- return false
696
- }, 60)
697
-
698
- eventLayer.bind('mousewheel', fireWheel)
699
-
700
- this.fire('eventLayerCreated', eventLayer[0])
701
-
702
- wdi.VirtualMouse.setEventLayer(eventLayer[0], 0, 0, width, height, 1)
703
- return eventLayer[0]
704
- },
705
-
706
- launchRightClick: function (x, y) {
707
- var self = this
708
- this.rightClickTimer = setTimeout(function () {
709
- self.generateEvent.call(self, 'mousedown', 2)
710
- self.generateEvent.call(self, 'mouseup', 2)
711
- self.enabledTouchMove = false
712
- }, 400)
713
- },
714
-
715
- launchMouseDown: function (x, y) {
716
- var self = this
717
- this.mouseDownTimer = setTimeout(function () {
718
- self.isMouseDown = true
719
- self.generateEvent.call(self, 'mousedown', 0)
720
- }, 1500)
721
- },
722
-
723
- showError: function (message) {
724
- wdi.Debug.warn(message)
725
- $('<div/>', {
726
- id: 'error',
727
- })
728
- .html(message)
729
- .css({
730
- 'background-color': '#ff4141',
731
- })
732
- .appendTo('body')
733
-
734
- setTimeout("$('#error').remove()", 2000)
735
- },
736
-
737
- generateEvent: function (event, params) {
738
- if (event === 'mousemove' || event === 'joystick') {
739
- if (this.ack_wait < wdi.SPICE_INPUT_MOTION_ACK_BUNCH) {
740
- this.ack_wait++
741
- this.fire('input', [event, params])
742
- }
743
- } else {
744
- if (event.indexOf('key') > -1) {
745
- // it's a keyEvent
746
- this.stuckKeysHandler.checkSpecialKey(event, params[0]['keyCode'])
747
- if (!this.shouldGenerateKeyEvents(params[0]['keyCode'])) {
748
- // Special keys should not generate keyEvents
749
- return
750
- }
751
- var val = event === 'keypress' ? this.inputManager.getValue() : ''
752
-
753
- event === 'keypress' && $('#inputmanager').val('')
754
-
755
- if (val) {
756
- params = this.inputManager.manageChar(val, params)
757
- }
758
- }
759
- this.fire('input', [event, params])
760
- }
761
- },
762
-
763
- shouldGenerateKeyEvents: function (keyCode) {
764
- return !this.inputManager.isSpecialKey(keyCode)
765
- },
766
-
767
- motion_ack: function () {
768
- this.ack_wait = 0
769
- },
770
-
771
- setMouseMode: function (mode) {
772
- this.mouse_mode = mode
773
- },
774
-
775
- handleKey: function (e) {
776
- e.data[0].generateEvent.call(e.data[0], e.type, [e])
777
-
778
- if (wdi.Keymap.isInKeymap(e.keyCode) && e.type !== 'keypress') {
779
- e.preventDefault()
780
- }
781
- },
782
-
783
- setClientOffset: function (x, y) {
784
- this.clientOffsetX = x
785
- this.clientOffsetY = y
786
- },
787
-
788
- setClipBoardData: function (data) {
789
- //we have received new clipboard data
790
- //show to the user
791
- //TODO: create a new dialog with buttons to copy the data directly
792
- //from the textbox
793
- //prompt("New clipboard data available, press ctrl+c to copy it", data);
794
- navigator.clipboard.writeText(data)
795
- },
796
-
797
- setToLocalClipboard: function (data) {
798
- this.localClipboard.updateClipboardBuffer(data.value)
799
- },
800
-
801
- getStuckKeysHandler: function () {
802
- return this.stuckKeysHandler
803
- },
804
-
805
- initSound: function () {
806
- var self = this
807
- if (!Modernizr.touch) {
808
- this.soundStarted = true
809
- window.setTimeout(function () {
810
- self.fire('startAudio')
811
- }, 100)
812
- } else {
813
- var $button = $('<button>Start</button>', { id: 'startAudio' })
814
- .css({
815
- padding: '10px 25px',
816
- fontSize: '25px',
817
- fontFamily: 'Verdana',
818
- cursor: 'pointer',
819
- margin: '0 auto',
820
- })
821
- .click(function () {
822
- self.soundStarted = true
823
- self.fire('startAudio')
824
- $('#soundButtonContainer').remove()
825
- })
826
-
827
- var $messageContainer = $(
828
- '<div id="messageContainer"><p>Click to start using your virtual session:</p></div>'
829
- ).css({
830
- color: 'white',
831
- textAlign: 'center',
832
- fontSize: '25px',
833
- fontFamily: 'Verdana',
834
- marginTop: '75px',
835
- })
836
-
837
- var $container = $('<div></div>', { id: 'soundButtonContainer' })
838
-
839
- $button.appendTo($messageContainer)
840
- $messageContainer.appendTo($container)
841
- $container.appendTo('body')
842
-
843
- $container.css({
844
- position: 'absolute',
845
- zIndex: 999999999,
846
- top: 0,
847
- left: 0,
848
- width: '100%',
849
- height: document.height,
850
- backgroundColor: 'black',
851
- })
852
- }
853
- },
854
- })
1
+ /*
2
+ Copyright (c) 2016 eyeOS
3
+
4
+ This file is part of Open365.
5
+
6
+ Open365 is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU Affero General Public License as
8
+ published by the Free Software Foundation, either version 3 of the
9
+ License, or (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU Affero General Public License for more details.
15
+
16
+ You should have received a copy of the GNU Affero General Public License
17
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+ wdi.SPICE_INPUT_MOTION_ACK_BUNCH = 8
21
+
22
+ wdi.ClientGui = $.spcExtend(wdi.EventObject.prototype, {
23
+ width: null,
24
+ height: null,
25
+ canvas: null,
26
+ ack_wait: 0,
27
+ mouse_mode: 0,
28
+ mouse_status: 0,
29
+ eventLayer: null,
30
+ counter: 0,
31
+ mainCanvas: 0,
32
+ firstTime: true,
33
+ clientOffsetX: 0,
34
+ clientOffsetY: 0,
35
+ magnifier: null,
36
+ magnifierBackground: null,
37
+ firstMove: true,
38
+ isMagnified: true,
39
+ isMouseDown: false,
40
+ soundStarted: false,
41
+ canvasMarginY: 0,
42
+ canvasMarginX: 0,
43
+ stuckKeysHandler: null,
44
+ isKeyboardEnabled: false,
45
+
46
+ subCanvas: {},
47
+ inputManager: null,
48
+ clipboardEnabled: true,
49
+ layer: null,
50
+ freezeClass: 'freeze',
51
+ app: {},
52
+
53
+ init: function (c) {
54
+ this.time = Date.now()
55
+ this.canvas = {}
56
+ this.contexts = {}
57
+ this.superInit()
58
+ this.magnifier = window
59
+ .$('<canvas/>')
60
+ .attr({
61
+ width: 150,
62
+ height: 150,
63
+ })
64
+ .css({
65
+ position: 'absolute',
66
+ left: '0px',
67
+ top: '0px',
68
+ })
69
+ this.stuckKeysHandler = c.stuckKeysHandler || new wdi.StuckKeysHandler()
70
+ this.settings = c.settings || {}
71
+ this.stuckKeysHandler.addListener(
72
+ 'inputStuck',
73
+ this._sendInput.bind(this),
74
+ this
75
+ )
76
+
77
+ //load magnifier background
78
+ this.magnifierBackground = window.$('<img/>')
79
+ this.magnifierBackground.attr(
80
+ 'src',
81
+ '/spice-console/resources/magnifier.png'
82
+ )
83
+ this.initSound()
84
+ this.inputManager =
85
+ c.inputManager ||
86
+ new wdi.InputManager({
87
+ stuckKeysHandler: this.stuckKeysHandler,
88
+ window: $(window),
89
+ })
90
+ this.inputManager.setCurrentWindow(window)
91
+ this.clipBoardDataParser =
92
+ c.clipBoardDataParser || new wdi.ClipboardDataParser({})
93
+ this.localClipboard =
94
+ c.localClipboard || new wdi.LocalClipboard({ clientGui: this })
95
+ this.app = c.app
96
+
97
+ var self = this
98
+ this.eventHandlers = {
99
+ hide: function () {
100
+ self.stuckKeysHandler.releaseAllKeys()
101
+ },
102
+ }
103
+ window.$(document).on(this.eventHandlers)
104
+ },
105
+
106
+ dispose: function () {
107
+ wdi.Debug.log('Disposing ClientGui')
108
+ $(document).off(this.eventHandlers)
109
+ this.unbindDOM()
110
+ this.removeAllCanvases()
111
+ this.inputManager.dispose()
112
+ this.stuckKeysHandler.dispose()
113
+ this.localClipboard.dispose()
114
+
115
+ this.width = null
116
+ this.height = null
117
+ this.canvas = null
118
+ this.ack_wait = 0
119
+ this.mouse_mode = 0
120
+ this.mouse_status = 0
121
+ this.eventLayer = null
122
+ this.counter = 0
123
+ this.mainCanvas = 0
124
+ this.firstTime = true
125
+ this.clientOffsetX = 0
126
+ this.clientOffsetY = 0
127
+ this.magnifier = null
128
+ this.magnifierBackground = null
129
+ this.firstMove = true
130
+ this.isMagnified = true
131
+ this.isMouseDown = false
132
+ this.soundStarted = false
133
+ this.canvasMarginY = 0
134
+ this.canvasMarginX = 0
135
+ this.stuckKeysHandler = null
136
+ this.subCanvas = {}
137
+ this.inputManager = null
138
+ this.clipboardEnabled = true
139
+ this.layer = null
140
+ clearInterval(self.rightClickTimer) //cancel, this is not a right click
141
+ clearInterval(self.mouseDownTimer) //cancel
142
+ },
143
+
144
+ removeAllCanvases: function () {
145
+ var self = this
146
+ Object.keys(this.canvas).forEach(function (key) {
147
+ $(self.canvas[key]).remove()
148
+ delete self.canvas[key]
149
+ delete self.contexts[key]
150
+ })
151
+ $(this.eventLayer).remove()
152
+ this.eventLayer = null
153
+ },
154
+
155
+ unbindDOM: function () {
156
+ if (this.eventLayer) {
157
+ var events = [
158
+ 'touchstart',
159
+ 'touchmove',
160
+ 'touchend',
161
+ 'mouseup',
162
+ 'mousedown',
163
+ 'mousemove',
164
+ 'contextmenu',
165
+ 'mousewheel',
166
+ ]
167
+ events.forEach(function (event) {
168
+ $(this.eventLayer).unbind(event)
169
+ })
170
+ }
171
+ },
172
+
173
+ freeze: function () {
174
+ if (this.canvas[0]) {
175
+ var image = new Image()
176
+ var cnv = this.canvas[0]
177
+ var $cnv = $(cnv)
178
+ $(image).attr('style', $cnv.attr('style'))
179
+ $(image).attr('class', this.freezeClass)
180
+ image.src = cnv.toDataURL('image/png')
181
+ $cnv.parent().append($(image))
182
+ }
183
+ },
184
+
185
+ cancelFreeze: function () {
186
+ $('.' + this.freezeClass).remove()
187
+ },
188
+
189
+ setLayer: function (layer) {
190
+ this.layer = layer
191
+ },
192
+
193
+ disableClipboard: function () {
194
+ this.clipboardEnabled = false
195
+ },
196
+
197
+ _sendInput: function (params) {
198
+ var data = params
199
+ var type = data[0]
200
+ var event = data[1]
201
+ this.fire('input', [type, event])
202
+ },
203
+
204
+ releaseAllKeys: function () {
205
+ this.stuckKeysHandler.releaseAllKeys()
206
+ },
207
+
208
+ getContext: function (surface_id) {
209
+ return this.contexts[surface_id]
210
+ },
211
+
212
+ getCanvas: function (surface_id) {
213
+ return this.canvas[surface_id]
214
+ },
215
+
216
+ checkFeatures: function () {
217
+ if (!Modernizr.canvas || !Modernizr.websockets) {
218
+ alert(
219
+ 'Your Browser is not compatible with WDI. Visit ... for a list of compatible browsers'
220
+ )
221
+ return false
222
+ }
223
+ return true
224
+ },
225
+
226
+ deleteSubCanvas: function (window) {
227
+ var obj = this.subCanvas[window['hwnd']]
228
+ this.subCanvas[window['hwnd']] = null
229
+ return obj
230
+ },
231
+
232
+ moveSubCanvas: function (window) {
233
+ var obj = this.subCanvas[window['hwnd']]
234
+ obj['info'] = window
235
+ this._fillSubCanvasFromWindow(window)
236
+ return obj
237
+ },
238
+
239
+ resizeSubCanvas: function (window) {
240
+ var obj = this.subCanvas[window['hwnd']]
241
+ $([obj['canvas'], obj['eventLayer']]).attr({
242
+ width: window['width'],
243
+ height: window['height'],
244
+ })
245
+ obj['info'] = window
246
+ this._fillSubCanvasFromWindow(window)
247
+ return obj
248
+ },
249
+
250
+ _fillSubCanvasFromWindow: function (window) {
251
+ var top = parseInt(window.top, 10)
252
+ var left = parseInt(window.left, 10)
253
+ var width = parseInt(window.width, 10)
254
+ var height = parseInt(window.height, 10)
255
+ this.fillSubCanvas({
256
+ top: top,
257
+ left: left,
258
+ right: left + width,
259
+ bottom: top + height,
260
+ })
261
+ },
262
+
263
+ createNewSubCanvas: function (window) {
264
+ var evtlayer = this.createEventLayer(
265
+ window['hwnd'] + '_event',
266
+ window['width'],
267
+ window['height']
268
+ )
269
+ this.subCanvas[window['hwnd']] = {
270
+ canvas: $('<canvas/>')
271
+ .attr({
272
+ width: window['width'],
273
+ height: window['height'],
274
+ })
275
+ .css({
276
+ display: window['iconic'] ? 'none' : 'block',
277
+ })[0],
278
+ eventLayer: evtlayer,
279
+ info: window,
280
+ position: 0,
281
+ }
282
+ //we have the main area drawn?
283
+ if (this.canvas[this.mainCanvas]) {
284
+ this._fillSubCanvasFromWindow(window)
285
+ }
286
+ return [this.subCanvas[window['hwnd']]]
287
+ },
288
+
289
+ fillSubCanvas: function (filterPosition) {
290
+ var canvas = this.canvas[this.mainCanvas]
291
+ var info = null
292
+ for (var i in this.subCanvas) {
293
+ if (
294
+ this.subCanvas[i] != null &&
295
+ this.subCanvas[i] !== undefined &&
296
+ this.subCanvas.hasOwnProperty(i)
297
+ ) {
298
+ info = this.subCanvas[i]['info']
299
+ if (filterPosition != null || filterPosition != undefined) {
300
+ var top = parseInt(info['top'], 10)
301
+ var left = parseInt(info['left'], 10)
302
+ var width = parseInt(info['width'], 10)
303
+ var height = parseInt(info['height'], 10)
304
+ var position = {
305
+ top: top,
306
+ left: left,
307
+ right: left + width,
308
+ bottom: top + height,
309
+ }
310
+ if (
311
+ wdi.CollisionDetector.thereIsBoxCollision(position, filterPosition)
312
+ ) {
313
+ this._doDrawSubCanvas(canvas, this.subCanvas[i], info)
314
+ }
315
+ } else {
316
+ this._doDrawSubCanvas(canvas, this.subCanvas[i], info)
317
+ }
318
+ }
319
+ }
320
+ },
321
+
322
+ _doDrawSubCanvas: function (canvas, subCanvas, info) {
323
+ if (
324
+ this.canvas[this.mainCanvas] == null ||
325
+ this.canvas[this.mainCanvas] == undefined
326
+ ) {
327
+ return
328
+ }
329
+ var destCtx = null
330
+ if (info['iconic'] === 0) {
331
+ var destCanvas = subCanvas['canvas']
332
+ destCtx = destCanvas.getContext('2d')
333
+
334
+ var x = 0
335
+ var y = 0
336
+ var width = +info.width
337
+ var height = +info.height
338
+ var left = +info['left']
339
+ var top = +info['top']
340
+
341
+ if (left < 0) {
342
+ width = width + left
343
+ x = -left
344
+ left = 0
345
+ }
346
+
347
+ if (top < 0) {
348
+ height = height + top
349
+ y = -top
350
+ top = 0
351
+ }
352
+
353
+ try {
354
+ // if width or height are less than 1 or a float
355
+ // drawImage fails in firefox (ERROR: IndexSizeError)
356
+ width = Math.max(1, Math.floor(width))
357
+ height = Math.max(1, Math.floor(height))
358
+ if (width > canvas.width) width = canvas.width
359
+ if (height > canvas.height) height = canvas.height
360
+ destCtx.drawImage(canvas, left, top, width, height, x, y, width, height)
361
+ } catch (err) {
362
+ wdi.Debug.error(err)
363
+ }
364
+ }
365
+ },
366
+
367
+ removeCanvas: function (spiceMessage) {
368
+ var surface = spiceMessage.args
369
+ if (surface.surface_id === this.mainCanvas) {
370
+ $(this.eventLayer).remove()
371
+ this.eventLayer = null
372
+ }
373
+
374
+ this.canvas[surface.surface_id].keepAlive = false
375
+ delete this.canvas[surface.surface_id]
376
+ delete this.contexts[surface.surface_id]
377
+ },
378
+
379
+ drawCanvas: function (spiceMessage) {
380
+ wdi.Debug.log('clientgui time: ', this.time)
381
+ var surface = spiceMessage.args
382
+
383
+ // // Custom code
384
+ // // Проверяем если ширина вм-а меньше ширины окна, вставляем по центру
385
+ // if (surface.width < window.innerWidth) {
386
+ // const x = (window.innerWidth - surface.width) / 2
387
+ // this.setCanvasMargin({
388
+ // x,
389
+ // y: this.canvasMarginY,
390
+ // })
391
+ // this.setClientOffset(-x, this.canvasMarginY)
392
+ // }
393
+ // // Custom code End
394
+
395
+ var cnv = wdi.GlobalPool.create('Canvas')
396
+ cnv.keepAlive = true //prevent this canvas to return to the pool by packetfilter
397
+
398
+ cnv.id = 'canvas_' + surface.surface_id
399
+ cnv.width = surface.width * this.pixelRatio
400
+ cnv.height = surface.height * this.pixelRatio
401
+ cnv.style.position = 'absolute'
402
+ cnv.style.top = this.canvasMarginY + 'px'
403
+ cnv.style.left = this.canvasMarginX + 'px'
404
+ cnv.style.width = surface.width + 'px'
405
+ cnv.style.height = surface.height + 'px'
406
+
407
+ this.canvas[surface.surface_id] = cnv
408
+ this.contexts[surface.surface_id] = cnv.getContext('2d')
409
+
410
+ if (surface.flags && !wdi.SeamlessIntegration) {
411
+ this.mainCanvas = surface.surface_id
412
+
413
+ this.eventLayer = this.createEventLayer(
414
+ 'eventLayer',
415
+ surface.width,
416
+ surface.height
417
+ )
418
+
419
+ var evLayer = $(this.eventLayer).css({
420
+ position: 'absolute',
421
+ top: this.canvasMarginY + 'px',
422
+ left: this.canvasMarginX + 'px',
423
+ })[0]
424
+
425
+ if (this.layer) {
426
+ this.layer.appendChild(cnv)
427
+ this.layer.appendChild(evLayer)
428
+ } else {
429
+ document.body.appendChild(cnv)
430
+ document.body.appendChild(evLayer)
431
+ }
432
+ !this.isKeyboardEnabled && this.enableKeyboard()
433
+ }
434
+
435
+ //this goes here?
436
+ if (this.firstTime && this.clipboardEnabled) {
437
+ var self = this
438
+ var PASTES_PER_SECOND = this.settings.PASTES_PER_SECOND || 5
439
+
440
+ var firePaste = _.throttle(function (data) {
441
+ self.fire('paste', data)
442
+ }, 1000 / PASTES_PER_SECOND)
443
+
444
+ $(document).bind('paste', function (event) {
445
+ self.clipBoardDataParser.parse(
446
+ event.originalEvent.clipboardData,
447
+ firePaste
448
+ )
449
+ })
450
+
451
+ $(document).bind('copy', function (e) {
452
+ self.app.sendShortcut(wdi.keyShortcutsHandled.CTRLC)
453
+ })
454
+
455
+ this.firstTime = false
456
+ }
457
+
458
+ //notify about resolution
459
+ if (surface.flags) {
460
+ this.fire('resolution', [
461
+ this.canvas[surface.surface_id].width,
462
+ this.canvas[surface.surface_id].height,
463
+ ])
464
+ }
465
+ },
466
+
467
+ disableKeyboard: function () {
468
+ var documentDOM = window.$(window.document)
469
+ documentDOM.unbind('keydown', this.handleKey)
470
+ documentDOM.unbind('keyup', this.handleKey)
471
+ documentDOM.unbind('keypress', this.handleKey)
472
+ this.inputManager.disable()
473
+ },
474
+
475
+ enableKeyboard: function () {
476
+ var self = this,
477
+ documentDOM = window.$(window.document)
478
+ documentDOM['keydown']([self], this.handleKey)
479
+ documentDOM['keypress']([self], this.handleKey)
480
+ documentDOM['keyup']([self], this.handleKey)
481
+ this.inputManager.enable()
482
+ !this.isKeyboardEnabled && (this.isKeyboardEnabled = true)
483
+ },
484
+
485
+ setCanvasMargin: function (canvasMargin) {
486
+ this.canvasMarginX = canvasMargin.x
487
+ this.canvasMarginY = canvasMargin.y
488
+ },
489
+
490
+ createEventLayer: function (event_id, width, height) {
491
+ var self = this
492
+
493
+ var eventLayer = $('<canvas/>')
494
+ .css({
495
+ cursor: 'default',
496
+ position: 'absolute',
497
+ })
498
+ .attr({
499
+ id: event_id,
500
+ // width: window.innerWidth,
501
+ // height: window.innerHeight
502
+ // Правильнее слой события делать с размером самого вм-а
503
+ width, // Custom code
504
+ height, // Custom code
505
+ })
506
+
507
+ if (window['bowser']['firefox']) {
508
+ eventLayer.attr('contentEditable', true)
509
+ }
510
+
511
+ eventLayer.bind('touchstart', function (event) {
512
+ event.preventDefault()
513
+ var touch =
514
+ event.originalEvent.touches[0] || event.originalEvent.changedTouches[0]
515
+ var x = touch.pageX
516
+ var y = touch.pageY
517
+ self.generateEvent.call(self, 'mousemove', [
518
+ x + self.clientOffsetX,
519
+ y + self.clientOffsetY,
520
+ self.mouse_status,
521
+ ])
522
+ if (event.originalEvent.touches.length === 1) {
523
+ self.enabledTouchMove = true
524
+ self.launchRightClick.call(self, x, y)
525
+ } else if (event.originalEvent.touches.length === 2) {
526
+ self.touchX = x
527
+ self.touchY = y
528
+ self.enabledTouchMove = false
529
+ } else if (event.originalEvent.touches.length === 3) {
530
+ self.touchY3 = y
531
+ self.enabledTouchMove = false
532
+ }
533
+ })
534
+
535
+ eventLayer.bind('touchmove', function (event) {
536
+ var touch =
537
+ event.originalEvent.touches[0] || event.originalEvent.changedTouches[0]
538
+ var x = touch.pageX
539
+ var y = touch.pageY
540
+ //TODO: ignore first move
541
+ if (event.originalEvent.touches.length === 1 && self.enabledTouchMove) {
542
+ self.isMagnified = true //magnified!
543
+ clearInterval(self.rightClickTimer) //cancel, this is not a right click
544
+
545
+ if (!self.isMouseDown) {
546
+ clearInterval(self.mouseDownTimer) //cancel, not enough time to send mousedown
547
+ self.launchMouseDown() //fire again
548
+ }
549
+
550
+ self.generateEvent.call(self, 'mousemove', [
551
+ x + self.clientOffsetX,
552
+ y + self.clientOffsetY - 80,
553
+ self.mouse_status,
554
+ ])
555
+ var pos = $(this).offset()
556
+ var myX = x - pos.left
557
+ var myY = y - pos.top
558
+
559
+ //draw magnifier
560
+ if (self.firstMove) {
561
+ $('body').append(self.magnifier) //TODO: append to body?
562
+ self.firstMove = false
563
+ }
564
+
565
+ var posX = myX - 75
566
+ var posY = myY - 160
567
+
568
+ self.magnifier.css({
569
+ left: posX,
570
+ top: posY,
571
+ })
572
+
573
+ //fill magnifier
574
+ var ctx = self.magnifier[0].getContext('2d')
575
+ ctx.clearRect(0, 0, 150, 150)
576
+ ctx.save()
577
+ ctx.beginPath()
578
+ ctx.arc(75, 75, 75, 0, 2 * Math.PI, false)
579
+ ctx.clip()
580
+ ctx.drawImage(
581
+ self.getCanvas(0),
582
+ myX - 50, //-50 because we are going to get
583
+ myY - 50 - 80, //100 px and we want the finder to be the center
584
+ //-80 becasue the magnifier is 160px up (160/2)
585
+ //we need to clean all this after the demo
586
+ //is working
587
+ 100,
588
+ 100,
589
+ 0,
590
+ 0,
591
+ 150,
592
+ 150
593
+ )
594
+ // //draw the background
595
+ ctx.drawImage(self.magnifierBackground[0], 0, 0)
596
+ ctx.restore()
597
+ //empty magnifier
598
+ } else if (event.originalEvent.touches.length === 2) {
599
+ var delta = self.touchY - y
600
+ if (Math.abs(delta) > 10) {
601
+ var button = delta > 0 ? 4 : 3
602
+ self.touchX = x
603
+ self.touchY = y
604
+ self.generateEvent.call(self, 'mousedown', button)
605
+ self.generateEvent.call(self, 'mouseup', button)
606
+ }
607
+ } else if (event.originalEvent.touches.length === 3) {
608
+ var delta = self.touchY3 - y
609
+ if (delta > 100) {
610
+ document.getElementById('hiddeninput').select()
611
+ }
612
+ }
613
+ event.preventDefault()
614
+ })
615
+
616
+ eventLayer.bind('touchend', function (event) {
617
+ if (self.enabledTouchMove) {
618
+ var touch =
619
+ event.originalEvent.touches[0] ||
620
+ event.originalEvent.changedTouches[0]
621
+ var x = touch.pageX
622
+ var y = touch.pageY
623
+ if (!self.isMouseDown) {
624
+ self.generateEvent.call(self, 'mousedown', 0)
625
+ }
626
+ self.isMouseDown = false
627
+ self.generateEvent.call(self, 'mouseup', 0)
628
+ var pos = $(this).offset()
629
+
630
+ self.enabledTouchMove = false
631
+ self.firstMove = true
632
+ if (self.isMagnified) {
633
+ self.magnifier.remove()
634
+ }
635
+ self.isMagnified = false
636
+ }
637
+ clearInterval(self.rightClickTimer) //cancel, this is not a right click
638
+ clearInterval(self.mouseDownTimer) //cancel
639
+ })
640
+
641
+ //if (!Modernizr.touch) {
642
+ eventLayer['mouseup'](function (event) {
643
+ var button = event.button
644
+
645
+ self.generateEvent.call(self, 'mouseup', button)
646
+ self.mouse_status = 0
647
+ event.preventDefault()
648
+ })
649
+
650
+ eventLayer['mousedown'](function (event) {
651
+ var button = event.button
652
+
653
+ self.generateEvent.call(self, 'mousedown', button)
654
+ self.mouse_status = 1
655
+ event.preventDefault()
656
+ })
657
+
658
+ eventLayer['mousemove'](function (event) {
659
+ if (
660
+ self.mouse_mode === wdi.SpiceMouseModeTypes.SPICE_MOUSE_MODE_SERVER &&
661
+ event.bubbles
662
+ )
663
+ return // Custom code // TODO refactoring. event.bubbles используется так как если переключить mouseMode на серверную то mousemove срабатывает дважды
664
+ var x = event.pageX
665
+ var y = event.pageY
666
+ // self.generateEvent.call(self, 'mousemove', [
667
+ // (x + self.clientOffsetX) * self.pixelRatio,
668
+ // (y + self.clientOffsetY) * self.pixelRatio,
669
+ // self.mouse_status,
670
+ // ])
671
+ // Custom code
672
+ self.generateEvent.call(self, 'mousemove', [
673
+ (x + self.clientOffsetX - self.eventLayer.offsetLeft) * self.pixelRatio,
674
+ (y + self.clientOffsetY - self.eventLayer.offsetTop) * self.pixelRatio,
675
+ self.mouse_status,
676
+ ])
677
+ // Custom code End
678
+ event.preventDefault()
679
+ })
680
+
681
+ eventLayer.bind('contextmenu', function (event) {
682
+ event.preventDefault()
683
+ return false
684
+ })
685
+ //}
686
+
687
+ var mouseEventPause = false
688
+
689
+ var fireWheel = _.throttle(function (event, delta) {
690
+ var button = delta > 0 ? 3 : 4
691
+
692
+ self.generateEvent.call(self, 'mousedown', button)
693
+ self.generateEvent.call(self, 'mouseup', button)
694
+
695
+ return false
696
+ }, 60)
697
+
698
+ eventLayer.bind('mousewheel', fireWheel)
699
+
700
+ this.fire('eventLayerCreated', eventLayer[0])
701
+
702
+ wdi.VirtualMouse.setEventLayer(eventLayer[0], 0, 0, width, height, 1)
703
+ return eventLayer[0]
704
+ },
705
+
706
+ launchRightClick: function (x, y) {
707
+ var self = this
708
+ this.rightClickTimer = setTimeout(function () {
709
+ self.generateEvent.call(self, 'mousedown', 2)
710
+ self.generateEvent.call(self, 'mouseup', 2)
711
+ self.enabledTouchMove = false
712
+ }, 400)
713
+ },
714
+
715
+ launchMouseDown: function (x, y) {
716
+ var self = this
717
+ this.mouseDownTimer = setTimeout(function () {
718
+ self.isMouseDown = true
719
+ self.generateEvent.call(self, 'mousedown', 0)
720
+ }, 1500)
721
+ },
722
+
723
+ showError: function (message) {
724
+ wdi.Debug.warn(message)
725
+ $('<div/>', {
726
+ id: 'error',
727
+ })
728
+ .html(message)
729
+ .css({
730
+ 'background-color': '#ff4141',
731
+ })
732
+ .appendTo('body')
733
+
734
+ setTimeout("$('#error').remove()", 2000)
735
+ },
736
+
737
+ generateEvent: function (event, params) {
738
+ if (event === 'mousemove' || event === 'joystick') {
739
+ if (this.ack_wait < wdi.SPICE_INPUT_MOTION_ACK_BUNCH) {
740
+ this.ack_wait++
741
+ this.fire('input', [event, params])
742
+ }
743
+ } else {
744
+ if (event.indexOf('key') > -1) {
745
+ // it's a keyEvent
746
+ this.stuckKeysHandler.checkSpecialKey(event, params[0]['keyCode'])
747
+ if (!this.shouldGenerateKeyEvents(params[0]['keyCode'])) {
748
+ // Special keys should not generate keyEvents
749
+ return
750
+ }
751
+ var val = event === 'keypress' ? this.inputManager.getValue() : ''
752
+
753
+ event === 'keypress' && $('#inputmanager').val('')
754
+
755
+ if (val) {
756
+ params = this.inputManager.manageChar(val, params)
757
+ }
758
+ }
759
+ this.fire('input', [event, params])
760
+ }
761
+ },
762
+
763
+ shouldGenerateKeyEvents: function (keyCode) {
764
+ return !this.inputManager.isSpecialKey(keyCode)
765
+ },
766
+
767
+ motion_ack: function () {
768
+ this.ack_wait = 0
769
+ },
770
+
771
+ setMouseMode: function (mode) {
772
+ this.mouse_mode = mode
773
+ },
774
+
775
+ handleKey: function (e) {
776
+ e.data[0].generateEvent.call(e.data[0], e.type, [e])
777
+
778
+ if (wdi.Keymap.isInKeymap(e.keyCode) && e.type !== 'keypress') {
779
+ e.preventDefault()
780
+ }
781
+ },
782
+
783
+ setClientOffset: function (x, y) {
784
+ this.clientOffsetX = x
785
+ this.clientOffsetY = y
786
+ },
787
+
788
+ setClipBoardData: function (data) {
789
+ //we have received new clipboard data
790
+ //show to the user
791
+ //TODO: create a new dialog with buttons to copy the data directly
792
+ //from the textbox
793
+ //prompt("New clipboard data available, press ctrl+c to copy it", data);
794
+ navigator.clipboard.writeText(data)
795
+ },
796
+
797
+ setToLocalClipboard: function (data) {
798
+ this.localClipboard.updateClipboardBuffer(data.value)
799
+ },
800
+
801
+ getStuckKeysHandler: function () {
802
+ return this.stuckKeysHandler
803
+ },
804
+
805
+ initSound: function () {
806
+ var self = this
807
+ if (!Modernizr.touch) {
808
+ this.soundStarted = true
809
+ window.setTimeout(function () {
810
+ self.fire('startAudio')
811
+ }, 100)
812
+ } else {
813
+ var $button = $('<button>Start</button>', { id: 'startAudio' })
814
+ .css({
815
+ padding: '10px 25px',
816
+ fontSize: '25px',
817
+ fontFamily: 'Verdana',
818
+ cursor: 'pointer',
819
+ margin: '0 auto',
820
+ })
821
+ .click(function () {
822
+ self.soundStarted = true
823
+ self.fire('startAudio')
824
+ $('#soundButtonContainer').remove()
825
+ })
826
+
827
+ var $messageContainer = $(
828
+ '<div id="messageContainer"><p>Click to start using your virtual session:</p></div>'
829
+ ).css({
830
+ color: 'white',
831
+ textAlign: 'center',
832
+ fontSize: '25px',
833
+ fontFamily: 'Verdana',
834
+ marginTop: '75px',
835
+ })
836
+
837
+ var $container = $('<div></div>', { id: 'soundButtonContainer' })
838
+
839
+ $button.appendTo($messageContainer)
840
+ $messageContainer.appendTo($container)
841
+ $container.appendTo('body')
842
+
843
+ $container.css({
844
+ position: 'absolute',
845
+ zIndex: 999999999,
846
+ top: 0,
847
+ left: 0,
848
+ width: '100%',
849
+ height: document.height,
850
+ backgroundColor: 'black',
851
+ })
852
+ }
853
+ },
854
+ })