first commit

main
root 2023-10-17 10:03:51 +02:00
commit 73bd0f460c
2265 changed files with 384897 additions and 0 deletions

107
README.md 100644
View File

@ -0,0 +1,107 @@
# Hype²
```mermaid
graph LR
Webpage[Web page] <--Flask--> Server[Server]
Server[Server] <----> Qemu((Qemu))
Server[Server] <----> LXC((LXC))
```
## Install requirement
1 - Update and Install packages :
```sh
apt-get update -y -qq
apt-get install lxc lxcfs lxc-templates qemu qemu-utils qemu-kvm virtinst bridge-utils virt-manager libvirt-daemon libvirt-daemon-system virt-viewer libvirt-clients libosinfo-bin websockify sqlite3 novnc
apt-get install python3 python3-flask python3-flask-login python3-flask-sqlalchemy python3-requests python3-lxc python3-libvirt python3-psutil python3-werkzeug python3-websockify python3-novnc
```
2 - Configure Libvirst to start on boot
```sh
systemctl --quiet enable --now libvirtd
systemctl --quiet start libvirtd
```
3 - Create a bridge nework
```sh
cp ./bridged.xml /usr/share/libvirt/networks/
virsh net-define bridged.xml
virsh net-start bridged
virsh net-autostart bridged
```
## Create Database for user
```sh
sqlite3 db.db
CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT, username NVARCHAR(200) NULL, email NVARCHAR(200) NULL, password NVARCHAR(200) NULL;
```
## Create first user
1 - Generate encrypted password :
```sh
python3
import app
app.encrypt('Password')
```
2 - Fill Database with user info :
```sh
sqlite3 db.db
INSERT INTO user (id,username,email,password) VALUES (1,'<you_username>','<your_email>','<your_previous_encrypted_password');
```
## Configure Reverse Proxy to get access to Consoles
```sh
ProxyPass /websockify ws://<server_ip>:6080/websockify retry=3
ProxyPassReverse /websockify ws://<server_ip>:6080/websockify retry=3
ProxyPass /socket.io ws://<server_ip>:5008/socket.io retry=3
ProxyPassReverse /socket.io ws://<server_ip>:5008/socket.io retry=3
```
## Run and use
```sh
python3 app
and go to https://<server_ip>:5007 with your credentials (mail and normal password)
```
## Systemd
You can manage hype using Systemd management:
```sh
[Unit]
Description= Hype2 service
After=multi-user.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/python3 <path_to_change>/app.py
[Install]
WantedBy=multi-user.target
```
put this file in /etc/systemd/system/ and you can then enable it for autostart on boot and/or start/stop the app.
## Configuration
You can also change some configuration in the file *configuration.py* such as flask port, storage location...use it at your own risk.

546
app.py 100644
View File

@ -0,0 +1,546 @@
import os
import json
import requests
from flask import Flask , redirect , render_template, request, Response, stream_with_context, url_for, make_response, flash
from werkzeug.utils import secure_filename
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager , UserMixin , login_required ,login_user, logout_user,current_user
from werkzeug.security import generate_password_hash, check_password_hash
from config import *
from functions.fhost import *
from functions.flxc import *
from functions.fiso import *
from functions.fvm import *
from functions.fvnc import *
from functions.fbackup import *
from functions.fpool import *
app = Flask(__name__,static_url_path='',static_folder='static',template_folder='templates')
###########################
## DROPZONE ##
###########################
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 * 1024
app.config['UPLOAD_EXTENSIONS'] = ['.iso']
app.config['UPLOAD_PATH'] = iso_path
############################
## LOGIN ##
############################
#Database (see base.sql for creation user table)
app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///'+os.path.join(path,'db.db')
app.config['SECRET_KEY']='619619'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=True
db = SQLAlchemy(app)
#Login init (login_view => default login page)
login_manager = LoginManager()
login_manager.login_view = "/login"
login_manager.init_app(app)
#Database search
class User(UserMixin,db.Model):
id = db.Column(db.Integer,primary_key=True,autoincrement=True)
username = db.Column(db.String(200))
email = db.Column(db.String(200))
password = db.Column(db.String(200))
@login_manager.user_loader
def get(id):
return User.query.get(id)
#Pass encrypt
def encrypt(password):
hashed_pass=generate_password_hash(password)
return hashed_pass
#Page for login
@app.route('/login',methods=['GET'])
def get_login():
return render_template('login.html')
#Page for user creation (secured)
@app.route('/signup',methods=['GET'])
@login_required
def get_signup():
return render_template('signup.html')
#Page for login, adding user and logout
@app.route('/login',methods=['POST'])
def login_post():
email = request.form['email']
password = request.form['password']
user = User.query.filter_by(email=email).first()
if user and check_password_hash(user.password, password):
login_user(user)
return redirect('/')
return redirect('/')
@app.route('/signup',methods=['POST'])
@login_required
def signup_post():
username = request.form['username']
email = request.form['email']
password = encrypt(request.form['password'])
user = User(username=username,email=email,password=password)
try:
db.session.add(user)
db.session.commit()
flash(user+' added', category='success')
except Exception as e:
flash('Error on adding user :'+str(e), category='danger')
return redirect('param')
@app.route('/logout',methods=['GET'])
def logout():
logout_user()
return redirect('/login')
############################
## INDEX ##
############################
@app.route('/',methods=['GET'])
@login_required
def get_home():
lxc_up = len(get_lxc_activ())
lxc_down = len(get_lxc_inactiv())
vm_up = len(get_vm_activ())
vm_down = len(get_vm_inactiv())
full = get_host_full()
return render_template('index.html', host=Host(), full = full, lxc_up=lxc_up, lxc_down=lxc_down, vm_up=vm_up, vm_down=vm_down)
def get_ressources():
while True:
full = get_host_full()
json_data = json.dumps(
{
"time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"cpu_percent": full['cpu']['percent'],
"mem_percent": full['mem']['percent'],
"swap_percent": full['swap']['percent'],
"cpu_time_user": full['cpu']['time_user'],
"cpu_time_nice": full['cpu']['time_nice'],
"cpu_time_system": full['cpu']['time_system'],
"cpu_time_idle": full['cpu']['time_idle'],
"cpu_time_iowait": full['cpu']['time_iowait'],
"cpu_time_irq": full['cpu']['time_irq'],
"cpu_time_softirq": full['cpu']['time_softirq'],
"cpu_time_steal": full['cpu']['time_steal'],
"cpu_time_guest": full['cpu']['time_guest'],
"cpu_time_guest_nice": full['cpu']['time_nice'],
"mem_total": full['mem']['total'],
"mem_available": full['mem']['available'],
"mem_used": full['mem']['used'],
"mem_free": full['mem']['free'],
"mem_active": full['mem']['active'],
"mem_inactive": full['mem']['inactive'],
"mem_buffers": full['mem']['buffers'],
"mem_cached": full['mem']['cached'],
"mem_shared": full['mem']['shared'],
"mem_slab": full['mem']['slab'],
"swap_total": full['swap']['total'],
"swap_used": full['swap']['used'],
"swap_free": full['swap']['free'],
"swap_sin": full['swap']['sin'],
"swap_sout": full['swap']['sout'],
}
)
yield f"data:{json_data}\n\n"
time.sleep(1)
@app.route('/chart-ressources/')
def chart_data() -> Response:
response = Response(stream_with_context(get_ressources()), mimetype="text/event-stream")
response.headers["Cache-Control"] = "no-cache"
response.headers["X-Accel-Buffering"] = "no"
return response
############################
## POOL ##
############################
@app.route('/pool',methods=['GET'])
@login_required
def get_pool():
return render_template('pool.html',list_pool_full = get_full_pool())
@app.route('/del_volume',methods=['POST'])
@login_required
def delvol():
pool_name = request.form['pool_name']
volume_name = request.form['volume_name']
try:
del_pool_vol(pool_name,volume_name)
flash(volume_name+' deleted', category='success')
except Exception as e:
flash('Error on deleting '+volume_name+':'+str(e), category='danger')
return redirect(url_for('get_pool'))
############################
## VNC ##
############################
####### TEST
####### ENDTEST
@app.route('/vnc',methods=['GET','POST',"DELETE"])
def vnc_connect():
if request.method=='GET':
resp = requests.get('http://localhost:6080/vnc.html')
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for (name, value) in resp.raw.headers.items() if name.lower() not in excluded_headers]
response = Response(resp.content, resp.status_code, headers)
return response
elif request.method=='POST':
resp = requests.post('http://localhost:6080/vnc.html',json=request.get_json())
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for (name, value) in resp.raw.headers.items() if name.lower() not in excluded_headers]
response = Response(resp.content, resp.status_code, headers)
return response
elif request.method=='DELETE':
resp = requests.delete('http://localhost:6080/vnc.html').content
response = Response(resp.content, resp.status_code, headers)
return response
##TEST
@app.route('/ter',methods=['GET','POST',"DELETE"])
def ter_connect():
if request.method=='GET':
resp = requests.get('http://localhost:5008/')
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for (name, value) in resp.raw.headers.items() if name.lower() not in excluded_headers]
response = Response(resp.content, resp.status_code, headers)
return response
elif request.method=='POST':
resp = requests.post('http://localhost:5008/',json=request.get_json())
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
headers = [(name, value) for (name, value) in resp.raw.headers.items() if name.lower() not in excluded_headers]
response = Response(resp.content, resp.status_code, headers)
return response
elif request.method=='DELETE':
resp = requests.delete('http://localhost:5008/').content
response = Response(resp.content, resp.status_code, headers)
return response
##ENDTEST
@app.route('/console_lxc',methods=['GET','POST','DELETE'])
@login_required
def consolelxc():
lxc_name = request.form['lxc_name']
try:
pyxterm_connect(lxc_name)
time.sleep(2)
return render_template('terminal.html')
except Exception as e:
flash('Error starting Terminal :'+str(e), category='danger')
return redirect(url_for('state'))
@app.route('/console_vm',methods=['POST'])
@login_required
def consolevm():
vm_name = request.form['vm_name']
try:
socket_connect(vm_name)
return render_template('vnc.html')
except Exception as e:
flash('Error starting VNC :'+str(e), category='danger')
return redirect(url_for('state'))
############################
## PARAMETERS ##
############################
def get_users():
users = User.query.all()
list_users=[]
for uni in users:
single=[]
single.append(uni.username)
single.append(uni.email)
list_users.append(single)
return list_users
@app.route('/param',methods=['GET'])
@login_required
def param():
return render_template('param.html',users_list = get_users())
@app.route('/deluser',methods=['POST'])
@login_required
def deluser():
username = request.form['username']
email = request.form['email']
try:
User.query.filter_by(username=username,email=email).delete()
db.session.commit()
flash(username+' deleted', category='success')
except Exception as e:
flash('Error on deleting '+username+':'+str(e), category='danger')
return redirect('param')
############################
## ISO ##
############################
@app.route('/iso',methods=['GET'])
@login_required
def iso():
return render_template('iso.html', list_iso = get_iso_list(), list_vm = get_vm_list(), list_iso_mount = get_iso_list())
@app.route('/deliso',methods=['POST'])
@login_required
def delete_iso():
file=request.form['fichier']
path=os.path.join(iso_path, file)
try:
os.remove(path)
flash(file+' deleted', category='success')
except Exception as e:
flash('Error on deleting '+file+':'+str(e), category='danger')
return render_template('iso.html', list_iso = get_iso_list(), list_vm = get_vm_list(), list_iso_mount = get_iso_list())
@app.route('/mountiso', methods=['POST'])
@login_required
def mountiso():
vm_name=request.form['vm']
if request.form['iso'] == '':
iso_name = ''
else:
iso_name=iso_path+request.form['iso']
try:
mount_iso(vm_name,iso_name)
flash(iso_name+' mounted', category='success')
except Exception as e:
flash('Error on mounting '+iso_name+':'+str(e), category='danger')
return redirect(url_for('state'))
@app.route('/ejectiso', methods = ['POST'])
@login_required
def eject_iso():
vm_name=request.form['ejectisovm']
state = check_iso_is_mounted(vm_name)
while state != 0:
iso_file='';
mount_iso(vm_name,iso_name)
state = check_iso_is_mounted(vm_name)
@app.route('/iso', methods=['POST'])
@login_required
def upload_files():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
file_ext = os.path.splitext(filename)[1]
if file_ext not in app.config['UPLOAD_EXTENSIONS']:
return "Invalid image", 400
uploaded_file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return '', 204
############################
## BACKUP ##
############################
@app.route('/backup')
@login_required
def backup():
full_snap_lxc=[]
full_snap_vm=[]
for lxc_name in get_lxc_list():
if get_snap_list_lxc(lxc_name):
full_snap_lxc.append(get_snap_list_lxc(lxc_name))
else:
full_snap_lxc.append('')
for vm_name in get_vm_list():
if get_snap_list_vm(vm_name):
full_snap_vm.append(get_snap_list_vm(vm_name))
else:
full_snap_vm.append('')
list_snap_lxc = zip(get_lxc_list(), full_snap_lxc)
list_snap_vm = zip(get_vm_list(), full_snap_vm)
return render_template('backup.html',list_snap_lxc=list_snap_lxc,list_snap_vm=list_snap_vm)
@app.route('/snaplxc', methods = ['POST'])
@login_required
def snaplxc():
lxc_name=request.form['snap']
try:
create_snap_lxc(lxc_name)
flash('Snapshot '+lxc_name+' done', category='success')
except Exception as e:
flash('Error on snapshoting '+lxc_name+':'+str(e), category='danger')
return redirect(url_for('backup'))
@app.route('/del_snap_lxc', methods = ['POST'])
@login_required
def delsnaplxc():
lxc_name=request.form['lxc_name']
item=request.form['item']
try:
del_snap_lxc(lxc_name,item)
flash(item+' deleted', category='success')
except Exception as e:
flash('Error on deleting '+item+':'+str(e), category='danger')
return redirect(url_for('backup'))
@app.route('/rest_snap_lxc', methods = ['POST'])
@login_required
def restsnap_lxc():
lxc_name=request.form['lxc_name']
item=request.form['item']
try:
rest_snap_lxc(lxc_name,item)
flash('Restore '+item+' done', category='success')
except Exception as e:
flash('Error restoring '+item+':'+str(e), category='danger')
return redirect(url_for('backup'))
############################
## BUILD ##
############################
@app.route('/build',methods=['GET'])
@login_required
def build_lxc():
return render_template('build.html', list_lxc_os=list_distrib(), list_profiles=get_os_profile_list(), list_net=conn.listNetworks(),list_iso = get_iso_list())
@app.route("/creation", methods=['POST'])
@login_required
def create_ct():
lxc_ip = request.form['ip']
try:
create_lxc(request.form['nom'],request.form['os'])
flash(request.form['nom']+' created', category='success')
except Exception as e:
flash('Error on creating '+request.form['nom']+':'+str(e), category='danger')
if lxc_ip:
set_lxc_ip(lxc_ip)
return redirect(url_for('state'))
@app.route('/creationvm', methods=['POST'])
@login_required
def create_VM():
#VNC Version
nom = request.form['vm_name']
ram = request.form['ram']
cpu = request.form['cpu']
ose = request.form['os']
iso = request.form['iso']
iso = iso_path+iso
net = request.form['net']
disk = request.form['disk']
creationcmd='--name '+str(nom)+' --ram '+str(ram)+' --disk pool=default,size='+str(disk)+',bus=virtio,format=qcow2 --vcpus '+str(cpu)+' --os-type linux --os-variant '+str(ose)+' --network network:bridged --graphics vnc,listen=0.0.0.0 --noautoconsole --console pty,target_type=serial --cdrom '+str(iso)+' --force --debug '
try:
os.system('virt-install '+creationcmd+' ')
flash(str(nom)+' created', category='success')
except Exception as e:
flash('Error on creating '+str(nom)+':'+str(e),category='danger')
return redirect(url_for('state'))
############################
## STATE ##
############################
@app.route('/state',methods=['GET'])
@login_required
def state():
ips_lxc=[]
for lxc_name in get_lxc_activ():
ips_lxc.append(get_lxc_ip(lxc_name))
activ_lxc=zip(get_lxc_activ(),ips_lxc)
state_act_vm = []
ips_vm = []
for vm_name in get_vm_activ():
state_act_vm.append(check_iso_is_mounted(vm_name))
ips_vm.append(get_vm_ips(vm_name))
activ_vm=zip(get_vm_activ(),state_act_vm,ips_vm)
state_inact_vm = []
for vm_name in get_vm_inactiv():
state_inact_vm.append(check_iso_is_mounted(vm_name))
inactiv_vm=zip(get_vm_inactiv(),state_inact_vm)
return render_template('state.html', activ_vm=activ_vm, inactiv_vm=inactiv_vm,activ_lxc=activ_lxc,inactiv_lxc=get_lxc_inactiv())
############################
## LXC ##
############################
@app.route('/start_lxc',methods=['POST'])
@login_required
def startct():
lxc_name = request.form['start']
try:
start_lxc(lxc_name)
flash(lxc_name+' started', category='success')
except Exception as e:
flash('Error starting '+lxc_name+':'+str(e), category='danger')
return redirect(url_for('state'))
@app.route('/stop_lxc',methods=['POST'])
@login_required
def stopct():
lxc_name = request.form['stop']
try:
stop_lxc(lxc_name)
flash(lxc_name+' stoped', category='success')
except Exception as e:
flash('Error stoping '+lxc_name+':'+str(e), category='danger')
return redirect(url_for('state'))
@app.route('/destroy_lxc',methods=['POST'])
@login_required
def destroyct():
lxc_name = request.form['destroy']
try:
destroy_lxc(lxc_name)
flash(lxc_name+' destroyed', category='success')
except Exception as e:
flash('Error destroying '+lxc_name+':'+str(e), category='danger')
return redirect(url_for('state'))
############################
## VM ##
############################
@app.route('/start_vm',methods=['POST'])
@login_required
def startvm():
vm_name = request.form['start']
try:
start_vm(vm_name)
flash(vm_name+' started', category='success')
except Exception as e:
flash('Error starting '+vm_name+':'+str(e), category='danger')
return redirect(url_for('state'))
@app.route('/stop_vm',methods=['POST'])
@login_required
def stopvm():
vm_name = request.form['stop']
try:
stop_vm(vm_name)
flash(vm_name+' stoped', category='success')
except Exception as e:
flash('Error stoping '+vm_name+':'+str(e), category='danger')
return redirect(url_for('state'))
@app.route('/destroy_vm',methods=['POST'])
@login_required
def destroyvm():
vm_name = request.form['destroy']
try:
destroy_vm(vm_name)
flash(vm_name+' destroyed', category='success')
except Exception as e:
flash('Error destroying '+vm_name+':'+str(e), category='danger')
return redirect(url_for('state'))
############################
## LOGIN ##
############################
#Self certificate page
if __name__=='__main__':
app.run(host=flask_config.host, port=flask_config.port, threaded=flask_config.thread, debug=flask_config.debug, ssl_context='adhoc')

5
bridged.xml 100644
View File

@ -0,0 +1,5 @@
<network>
<name>bridged</name>
<forward mode="bridge" />
<bridge name="br0" />
</network>

61
config.py 100644
View File

@ -0,0 +1,61 @@
import os
import libvirt
import math
#Flask config
class flask_config:
port=5007
host='0.0.0.0'
thread=True
debug=False
#Path
path = os.path.abspath(os.path.dirname(__file__))
iso_path= path+'/storage/iso/'
#Qemu connection
try:
conn = libvirt.open("qemu:///system")
except:
exit(1)
#Convert
units_map = [
(1<<50, ' PB'),
(1<<40, ' TB'),
(1<<30, ' GB'),
(1<<20, ' MB'),
(1<<10, ' KB'),
(1, (' byte', ' bytes')),
]
def human_size(bytes, units=units_map):
for factor, suffix in units:
if bytes >= factor:
break
amount = int(bytes / factor)
if isinstance(suffix, tuple):
singular, multiple = suffix
if amount == 1:
suffix = singular
else:
suffix = multiple
return str(amount) + suffix
#Debug for Ct actions
def mount_pts():
os.system('mount -o remount,rw /dev/pts')
#LXC Os list
def list_distrib():
link_list = ['debian','ubuntu','centos','busybox','ubuntu-cloud','cirros','sabayon']
name_list = ['Debian','Ubuntu','Centos','Busybox','Ubuntu-cloud','Cirros','Sabayon']
listd = zip(name_list, link_list)
return listd
#VM Os list
def get_os_profile_list():
list_profile=[]
for profile in os.popen("osinfo-query os | awk '{ print $1 }' | awk 'NR > 2 { print }'"):
list_profile.append(str(profile))
return list_profile

View File

@ -0,0 +1,52 @@
import lxc
from datetime import datetime
from config import *
## LXC
def create_snap_lxc(lxc_name):
cont=lxc.Container(lxc_name)
cont.snapshot()
def get_snap_list_lxc(lxc_name):
dom=lxc.Container(lxc_name)
list_snap_lxc = dom.snapshot_list()
out=[]
for snap in list_snap_lxc:
nom_snap=snap[0]
date_snap=datetime.strptime(snap[2], '%Y:%m:%d %H:%M:%S')
date_snap=date_snap.strftime("%d%m%Y%H%M")
concat_name=dom.name+"_"+date_snap+"_"+nom_snap
out.append(concat_name)
return out
def del_snap_lxc(lxc_name,item):
conn=lxc.Container(lxc_name)
item=item.split('_')[2]
conn.snapshot_destroy(item)
def rest_snap_lxc(lxc_name,item):
conn=lxc.Container(lxc_name)
item=item.split('_')[2]
conn.snapshot_restore(item)
## VM
def create_snap_vm(vm_name):
dom=conn.lookupByName(vm_name)
actual_date=datetime.now()
actual_date=actual_date.strftime("%d%m%Y%H%M")
snapshot_name= dom.name()+"_"+actual_date+"_snap"
SNAPSHOT_XML_TEMPLATE = """<domainsnapshot>
<name>{snapshot_name}</name>
</domainsnapshot>"""
dom.snapshotCreateXML(SNAPSHOT_XML_TEMPLATE.format(snapshot_name=snapshot_name),libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_ATOMIC)
def get_snap_list_vm(vm_name):
dom=conn.lookupByName(vm_name)
list_snap_vm=dom.snapshotListNames()
list_snap_vm.reverse()
out=[]
for snap in list_snap_vm:
out.append(snap)
return out

147
functions/fhost.py 100644
View File

@ -0,0 +1,147 @@
from config import *
import re
import os
import psutil
from datetime import datetime
units_map = [
(1<<50, ' PB'),
(1<<40, ' TB'),
(1<<30, ' GB'),
(1<<20, ' MB'),
(1<<10, ' KB'),
(1, (' byte', ' bytes')),
]
def human_size(bytes, units=units_map):
for factor, suffix in units:
if bytes >= factor:
break
amount = int(bytes / factor)
if isinstance(suffix, tuple):
singular, multiple = suffix
if amount == 1:
suffix = singular
else:
suffix = multiple
return str(amount) + suffix
class Host:
def __init__(self):
self.hostname = psutil.os.uname().nodename
self.cpu_number = psutil.cpu_count(logical=False)
self.vcpu = psutil.cpu_count()
self.mem_max = human_size(psutil.virtual_memory().total)
self.boot_time = datetime.fromtimestamp(psutil.boot_time() - 60)
self.cpu_usage = psutil.cpu_percent(interval=0.0, percpu=False)
self.mem_usage = psutil.virtual_memory().percent
self.swap_usage = psutil.swap_memory().percent
class ENV:
def __init__(self):
self.hostname = psutil.os.uname().nodename
self.cpu_number = psutil.cpu_count(logical=False)
self.vcpu = psutil.cpu_count()
self.mem_max = human_size(psutil.virtual_memory().total)
self.boot_time = psutil.boot_time()
class CPU:
def __init__(self):
self.cpu = {}
self.cpu['percent'] = psutil.cpu_percent(interval=0.0, percpu=False)
self.cpu['time_user'] = psutil.cpu_times_percent().user
self.cpu['time_nice'] = psutil.cpu_times_percent().nice
self.cpu['time_system'] = psutil.cpu_times_percent().system
self.cpu['time_idle'] = psutil.cpu_times_percent().idle
self.cpu['time_iowait'] = psutil.cpu_times_percent().iowait
self.cpu['time_irq'] = psutil.cpu_times_percent().irq
self.cpu['time_softirq'] = psutil.cpu_times_percent().softirq
self.cpu['time_steal'] = psutil.cpu_times_percent().steal
self.cpu['time_guest'] = psutil.cpu_times_percent().guest
self.cpu['time_guest_nice'] = psutil.cpu_times_percent().guest_nice
class Memory:
def __init__(self):
self.mem = {}
self.mem['total'] = human_size(psutil.virtual_memory().total)
self.mem['available'] = human_size(psutil.virtual_memory().available)
self.mem['percent'] = psutil.virtual_memory().percent
self.mem['used'] = human_size(psutil.virtual_memory().used)
self.mem['free'] = human_size(psutil.virtual_memory().free)
self.mem['active'] = human_size(psutil.virtual_memory().active)
self.mem['inactive'] = human_size(psutil.virtual_memory().inactive)
self.mem['buffers'] = human_size(psutil.virtual_memory().buffers)
self.mem['cached'] = human_size(psutil.virtual_memory().cached)
self.mem['shared'] = human_size(psutil.virtual_memory().shared)
self.mem['slab'] = human_size(psutil.virtual_memory().slab)
class Swap:
def __init__(self):
self.swap = {}
self.swap['total'] = human_size(psutil.swap_memory().total)
self.swap['used'] = human_size(psutil.swap_memory().used)
self.swap['free'] = human_size(psutil.swap_memory().free)
self.swap['percent'] = psutil.swap_memory().percent
self.swap['sin'] = human_size(psutil.swap_memory().sin)
self.swap['sout'] = human_size(psutil.swap_memory().sout)
class Disks:
def __init__(self):
num=0
for i in psutil.disk_partitions():
exec("self.disk_"+str(num)+" = {}")
exec("self.disk_"+str(num)+"['device'] = '"+str(i.device)+"'")
exec("self.disk_"+str(num)+"['mountpoint'] = '"+str(i.mountpoint)+"'")
exec("self.disk_"+str(num)+"['fstype'] = '"+str(i.fstype)+"'")
exec("self.disk_"+str(num)+"['opts'] = '"+str(i.opts)+"'")
exec("self.disk_"+str(num)+"['maxfile'] = '"+str(i.maxfile)+"'")
exec("self.disk_"+str(num)+"['maxpath'] = '"+str(i.maxpath)+"'")
exec("self.disk_"+str(num)+"['size_total'] = '"+str(human_size(psutil.disk_usage(i.mountpoint).total))+"'")
exec("self.disk_"+str(num)+"['size_used'] = '"+str(human_size(psutil.disk_usage(i.mountpoint).used))+"'")
exec("self.disk_"+str(num)+"['size_free'] = '"+str(human_size(psutil.disk_usage(i.mountpoint).free))+"'")
exec("self.disk_"+str(num)+"['size_percent'] = '"+str(psutil.disk_usage(i.mountpoint).percent)+"'")
num+=1
class Network:
def __init__(self):
num=0
for interface in psutil.net_if_addrs():
exec("self.net_"+str(num)+" = {}")
interface_usage = psutil.net_io_counters(pernic=True)
for detail in psutil.net_if_addrs()[interface]:
exec("self.net_"+str(num)+"['name'] = '"+str(interface)+"'")
exec("self.net_"+str(num)+"['bytes_sent'] = '"+str(human_size(interface_usage[interface].bytes_sent))+"'")
exec("self.net_"+str(num)+"['bytes_recv'] = '"+str(human_size(interface_usage[interface].bytes_recv))+"'")
ip_pattern = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
if ip_pattern.match(detail.address):
exec("self.net_"+str(num)+"['address_v4'] = '"+str(detail.address)+"'")
else:
exec("self.net_"+str(num)+"['address_v6'] = '"+str(detail.address)+"'")
if detail.netmask:
if ip_pattern.match(detail.netmask):
exec("self.net_"+str(num)+"['netmask_v4'] = '"+str(detail.netmask)+"'")
else:
exec("self.net_"+str(num)+"['netmask_v6'] = '"+str(detail.netmask)+"'")
num+=1
class Monit:
def __init__(self):
self.env = ENV()
self.cpu = CPU()
self.mem = Memory()
self.swap = Swap()
self.disks = Disks()
self.network = Network()
def get_host_full():
Localhost = Monit()
host_full = {}
host_full.update(vars(Localhost.env))
host_full.update(vars(Localhost.cpu))
host_full.update(vars(Localhost.mem))
host_full.update(vars(Localhost.swap))
host_full.update(vars(Localhost.disks))
host_full.update(vars(Localhost.network))
return host_full

71
functions/fiso.py 100644
View File

@ -0,0 +1,71 @@
import os
from config import *
from xml.dom import minidom
def get_xml(vm_name):
dom=conn.lookupByName(vm_name)
raw_xml = dom.XMLDesc()
xml = minidom.parseString(raw_xml)
return xml
def get_iso_list():
list_iso_path= []
list_iso_size= []
for file in os.listdir(iso_path):
if file.endswith(".iso"):
size=os.path.getsize(iso_path+file)
size=human_size(size)
list_iso_size.append(str(size))
list_iso_path.append(str(file))
list_iso=zip(list_iso_path, list_iso_size)
return list_iso
def get_cdrom_attribut(vm_name):
xml = get_xml(vm_name)
diskTypes = xml.getElementsByTagName('disk')
for disk_xml in diskTypes:
if disk_xml.getAttribute('device') == 'cdrom':
target_tag = disk_xml.getElementsByTagName('target')
address_tag = disk_xml.getElementsByTagName('address')
target_dev = target_tag[0].getAttribute('dev')
target_bus = target_tag[0].getAttribute('bus')
address_type = address_tag[0].getAttribute('type')
address_controller = address_tag[0].getAttribute('controller')
address_bus = address_tag[0].getAttribute('bus')
address_target = address_tag[0].getAttribute('target')
address_unit = address_tag[0].getAttribute('unit')
return target_dev, target_bus, address_type, address_controller, address_bus, address_target, address_unit
def mount_iso(vm_name,iso_name):
dom = conn.lookupByName(vm_name)
target_dev, target_bus, address_type, address_controller, address_bus, address_target, address_unit = get_cdrom_attribut(vm_name)
diskFile = iso_name
diskXML = """ <disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='""" + diskFile + """'/>
<target dev='""" + target_dev + """' bus='""" + target_bus + """'/>
<address type='""" + address_type + """' controller='""" + address_controller + """' bus='""" + address_bus + """' target='""" + address_target + """' unit='""" + address_unit + """'/>
</disk>"""
dom.updateDeviceFlags(diskXML, 0)
def check_iso_is_mounted(vm_name):
dom = conn.lookupByName(vm_name)
raw_xml = dom.XMLDesc()
xml = minidom.parseString(raw_xml)
diskTypes = xml.getElementsByTagName('disk')
for disk_xml in diskTypes:
disk = None
source = disk_xml.getElementsByTagName('source')
if disk_xml.getAttribute('device') == 'cdrom':
try:
gotdata= source[0].getAttribute('file')
if source[0].getAttribute('file'):
state = 1
else:
state = 0
except IndexError:
state = 0
#Return 1 if mounted or 0 if not mounted
return state

63
functions/flxc.py 100644
View File

@ -0,0 +1,63 @@
import lxc
from config import *
### LISTS
def get_lxc_list():
full_ct=lxc.list_containers()
full_ct = list(full_ct)
return full_ct
def get_lxc_activ():
activ_ct = []
for ct_name in get_lxc_list():
ct_state=lxc.Container(ct_name)
if ( ct_state.state == "RUNNING"):
activ_ct.append(ct_name)
return activ_ct
def get_lxc_inactiv():
inactiv_ct = []
for ct_name in get_lxc_list():
ct_state=lxc.Container(ct_name)
if ( ct_state.state != "RUNNING"):
inactiv_ct.append(ct_name)
return inactiv_ct
### ACTIONS
def start_lxc(lxc_name):
mount_pts()
container=lxc.Container(lxc_name)
container.start()
container.wait("RUNNING", 3)
def stop_lxc(lxc_name):
mount_pts()
container=lxc.Container(lxc_name)
container.stop()
container.wait("STOPPED", 3)
def get_lxc_ip(lxc_name):
ct_state=lxc.Container(lxc_name)
lxc_ip = str(ct_state.get_ips()).replace('(', '').replace(')', '').replace(',', '').replace('\'', '')
return lxc_ip
## CREATE
def create_lxc(lxc_name,lxc_os):
mount_pts()
container=lxc.Container(lxc_name)
resultats=container.create(lxc_os)
def set_lxc_ip(lxc_ip):
file_object = open('/var/lib/lxc/'+lxc_name+'/config', 'a')
file_object.write('lxc.net.0.ipv4.address = '+lxc_ip+'\n')
file_object.write('lxc.net.0.ipv4.gateway = auto')
file_object.close()
## DESTROY
def destroy_lxc(lxc_name):
container=lxc.Container(lxc_name)
container.destroy()

64
functions/fpool.py 100644
View File

@ -0,0 +1,64 @@
from config import *
def refresh_pool():
for refresh_pool in conn.listAllStoragePools():
refresh_pool.refresh(0)
def get_pool_list():
list_pools = []
for pools in conn.listStoragePools():
pool = conn.storagePoolLookupByName(pools)
list_pools.append(pool.name())
return list_pools
def get_full_pool():
refresh_pool()
list_pool_full = []
for pools in get_pool_list():
pool_info = get_pool_info(pools)
pool_info.append(get_pool_volumes(pools))
list_pool_full.append(pool_info)
return list_pool_full
# Name,UUID,Active,Total,Used,Free,Percent
def get_pool_info(pool_name):
refresh_pool()
pool_info = []
pool = conn.storagePoolLookupByName(pool_name)
pool_info.append(pool.name())
pool_info.append(pool.UUIDString())
pool_info.append(str(pool.isActive()))
pool_info.append(str(human_size(pool.info()[1])))
pool_info.append(str(human_size(pool.info()[2])))
pool_info.append(str(human_size(pool.info()[3])))
if pool.info()[1]==0:
pool_info.append(str(0))
else:
pool_info.append(str(round((pool.info()[2]*100)/pool.info()[1],2)))
return pool_info
#Name,Total,Used,Percent
def get_pool_volumes(pool_name):
refresh_pool()
volumes_list = []
pool = conn.storagePoolLookupByName(pool_name)
for volume in pool.listVolumes():
volume_info=[]
vol = pool.storageVolLookupByName(volume)
volume_info.append(volume)
volume_info.append(human_size(vol.info()[1]))
volume_info.append(human_size(vol.info()[2]))
if vol.info()[1]==0:
vol_used=0
else:
vol_used=round((vol.info()[2]*100)/vol.info()[1],2)
volume_info.append(vol_used)
volumes_list.append(volume_info)
return volumes_list
def del_pool_vol(pool_name,volume_name):
refresh_pool()
pools=conn.storagePoolLookupByName(pool_name)
vlm=pools.storageVolLookupByName(volume_name)
vlm.delete()

70
functions/fvm.py 100644
View File

@ -0,0 +1,70 @@
from config import *
import time
def get_vm_activ():
list_run_id=conn.listDomainsID()
activ_vm=[]
for id in list_run_id:
dom=conn.lookupByID(id)
activ_vm.append(dom.name())
return activ_vm
def get_vm_inactiv():
inactiv_vm=conn.listDefinedDomains()
return inactiv_vm
def get_vm_list():
full_vm = get_vm_activ() + get_vm_inactiv()
return full_vm
def start_vm(vm_name):
dom = conn.lookupByName(vm_name)
dom.create()
time.sleep(3)
alive=0
while alive < 3:
if dom.isActive():
alive=4
else:
time.sleep(3)
alive+=1
def stop_vm(vm_name):
dom = conn.lookupByName(vm_name)
dom.shutdown()
time.sleep(3)
alive=0
while alive < 5:
if dom.isActive():
time.sleep(3)
alive+=1
else:
alive=6
if dom.isActive():
dom.destroy()
def get_vm_ips(vm_name):
dom=conn.lookupByName(vm_name)
if not dom:
raise SystemExit("Failed to connect to Dom")
try:
ifaces = dom.interfaceAddresses(libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)
except:
ifaces = None
result="--.--.--.--"
if ifaces is None:
result="--.--.--.--"
else:
for (name, val) in ifaces.items():
if val['addrs']:
for addr in val['addrs']:
if addr['addr']:
result=str(addr['addr'])+"/"+str(addr['prefix'])
break
else:
result="-"
return result
def destroy_vm(vm_name):
dom=conn.lookupByName(vm_name)
dom.undefine()

25
functions/fvnc.py 100644
View File

@ -0,0 +1,25 @@
from config import *
from xml.etree import ElementTree as ET
from flask import request, Response
import os
def get_vnc_port(vm_name):
dom = conn.lookupByName(vm_name)
vm_xml = dom.XMLDesc(0)
et_xml = ET.fromstring(vm_xml)
graphics = et_xml.find('./devices/graphics')
vnc_port = graphics.get('port')
return vnc_port
def kill_consoles():
os.system('kill -9 $(ps -edf | grep websockify | grep -v grep | awk \'{ print $2 }\')')
os.system('for i in $(ps -edf | grep pyxterm | grep -v grep | awk \'{ print $2 }\');do kill -9 $i;done')
def socket_connect(vm_name):
kill_consoles()
vm_port = get_vnc_port(vm_name)
os.system('websockify -D --web=/usr/share/novnc/ 6080 localhost:'+vm_port)
def pyxterm_connect(lxc_name):
kill_consoles()
os.system('python3 pyxterm.py --command \'lxc-attach\' --cmd-args \''+lxc_name+'\' &')

92
pyxterm.py 100644
View File

@ -0,0 +1,92 @@
#!/usr/bin/env python3
import argparse
from flask import Flask, render_template
from flask_socketio import SocketIO
import pty
import os
import subprocess
import select
import termios
import struct
import fcntl
import shlex
import sys
app = Flask(__name__, template_folder="templates", static_folder=".", static_url_path="")
app.config["SECRET_KEY"] = "secret!"
app.config["fd"] = None
app.config["child_pid"] = None
socketio = SocketIO(app)
def set_winsize(fd, row, col, xpix=0, ypix=0):
winsize = struct.pack("HHHH", row, col, xpix, ypix)
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
def read_and_forward_pty_output():
max_read_bytes = 1024 * 20
while True:
socketio.sleep(0.01)
if app.config["fd"]:
timeout_sec = 0
(data_ready, _, _) = select.select([app.config["fd"]], [], [], timeout_sec)
if data_ready:
output = os.read(app.config["fd"], max_read_bytes).decode(
errors="ignore"
)
socketio.emit("pty-output", {"output": output}, namespace="/pty")
@app.route("/")
def index():
return render_template("pyxterm.html")
@socketio.on("pty-input", namespace="/pty")
def pty_input(data):
if app.config["fd"]:
os.write(app.config["fd"], data["input"].encode())
@socketio.on("resize", namespace="/pty")
def resize(data):
if app.config["fd"]:
set_winsize(app.config["fd"], data["rows"], data["cols"])
@socketio.on("connect", namespace="/pty")
def connect():
if app.config["child_pid"]:
return
(child_pid, fd) = pty.fork()
if child_pid == 0:
subprocess.run(app.config["cmd"])
else:
app.config["fd"] = fd
app.config["child_pid"] = child_pid
set_winsize(fd, 50, 50)
cmd = " ".join(shlex.quote(c) for c in app.config["cmd"])
socketio.start_background_task(target=read_and_forward_pty_output)
def main():
parser = argparse.ArgumentParser(
description=(
),
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"--command", default="bash", help="Command to run in the terminal"
)
parser.add_argument(
"--cmd-args",
default="",
)
args = parser.parse_args()
app.config["cmd"] = [args.command] + shlex.split(args.cmd_args)
green = "\033[92m"
end = "\033[0m"
socketio.run(app, port=5008, host='0.0.0.0')
if __name__ == "__main__":
main()

1
static/Chart.min.css vendored 100644
View File

@ -0,0 +1 @@
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}

7
static/Chart.min.js vendored 100644

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,66 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
// NB: this should *not* be included as a module until we have
// native support in the browsers, so that our error handler
// can catch script-loading errors.
// No ES6 can be used in this file since it's used for the translation
/* eslint-disable prefer-arrow-callback */
(function _scope() {
"use strict";
// Fallback for all uncought errors
function handleError(event, err) {
try {
const msg = document.getElementById('noVNC_fallback_errormsg');
// Only show the initial error
if (msg.hasChildNodes()) {
return false;
}
let div = document.createElement("div");
div.classList.add('noVNC_message');
div.appendChild(document.createTextNode(event.message));
msg.appendChild(div);
if (event.filename) {
div = document.createElement("div");
div.className = 'noVNC_location';
let text = event.filename;
if (event.lineno !== undefined) {
text += ":" + event.lineno;
if (event.colno !== undefined) {
text += ":" + event.colno;
}
}
div.appendChild(document.createTextNode(text));
msg.appendChild(div);
}
if (err && err.stack) {
div = document.createElement("div");
div.className = 'noVNC_stack';
div.appendChild(document.createTextNode(err.stack));
msg.appendChild(div);
}
document.getElementById('noVNC_fallback_error')
.classList.add("noVNC_open");
} catch (exc) {
document.write("noVNC encountered an error.");
}
// Don't return true since this would prevent the error
// from being printed to the browser console.
return false;
}
window.addEventListener('error', function onerror(evt) { handleError(evt, evt.error); });
window.addEventListener('unhandledrejection', function onreject(evt) { handleError(evt.reason, evt.reason); });
})();

View File

@ -0,0 +1,92 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="alt.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="18.205425"
inkscape:cy="17.531398"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text5290">
<path
d="m 9.9560547,1042.3329 -2.9394531,0 -0.4638672,1.3281 -1.8896485,0 2.7001953,-7.29 2.241211,0 2.7001958,7.29 -1.889649,0 -0.4589843,-1.3281 z m -2.4707031,-1.3526 1.9970703,0 -0.9960938,-2.9003 -1.0009765,2.9003 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5340" />
<path
d="m 13.188477,1036.0634 1.748046,0 0,7.5976 -1.748046,0 0,-7.5976 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5342" />
<path
d="m 18.535156,1036.6395 0,1.5528 1.801758,0 0,1.25 -1.801758,0 0,2.3193 q 0,0.3809 0.151367,0.5176 0.151368,0.1318 0.600586,0.1318 l 0.898438,0 0,1.25 -1.499024,0 q -1.035156,0 -1.469726,-0.4297 -0.429688,-0.4345 -0.429688,-1.4697 l 0,-2.3193 -0.86914,0 0,-1.25 0.86914,0 0,-1.5528 1.748047,0 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5344" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,106 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="clipboard.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="15.366606"
inkscape:cy="16.42981"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 9,6 6,6 C 5.4459889,6 5,6.4459889 5,7 l 0,13 c 0,0.554011 0.4459889,1 1,1 l 13,0 c 0.554011,0 1,-0.445989 1,-1 L 20,7 C 20,6.4459889 19.554011,6 19,6 l -3,0"
transform="translate(0,1027.3622)"
id="rect6083"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssssssc" />
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect6085"
width="7"
height="4"
x="9"
y="1031.3622"
ry="1.00002" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
d="m 8.5071212,1038.8622 7.9999998,0"
id="path6087"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
d="m 8.5071212,1041.8622 3.9999998,0"
id="path6089"
inkscape:connector-curvature="0" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.50196081"
d="m 8.5071212,1044.8622 5.9999998,0"
id="path6091"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,96 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="connect.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="37.14834"
inkscape:cy="1.9525926"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
id="g5103"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-729.15757,315.8823)">
<path
sodipodi:nodetypes="cssssc"
inkscape:connector-curvature="0"
id="rect5096"
d="m 11,1040.3622 -5,0 c -1.108,0 -2,-0.892 -2,-2 l 0,-4 c 0,-1.108 0.892,-2 2,-2 l 5,0"
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 14,1032.3622 5,0 c 1.108,0 2,0.892 2,2 l 0,4 c 0,1.108 -0.892,2 -2,2 l -5,0"
id="path5099"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssssc" />
<path
inkscape:connector-curvature="0"
id="path5101"
d="m 9,1036.3622 7,0"
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,96 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ctrl.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="18.205425"
inkscape:cy="17.531398"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text5290">
<path
d="m 9.1210938,1043.1898 q -0.5175782,0.2686 -1.0791016,0.4053 -0.5615235,0.1367 -1.171875,0.1367 -1.8212891,0 -2.8857422,-1.0156 -1.0644531,-1.0205 -1.0644531,-2.7637 0,-1.748 1.0644531,-2.7637 1.0644531,-1.0205 2.8857422,-1.0205 0.6103515,0 1.171875,0.1368 0.5615234,0.1367 1.0791016,0.4052 l 0,1.5088 q -0.522461,-0.3564 -1.0302735,-0.5224 -0.5078125,-0.1661 -1.0693359,-0.1661 -1.0058594,0 -1.5820313,0.6446 -0.5761719,0.6445 -0.5761719,1.7773 0,1.1279 0.5761719,1.7725 0.5761719,0.6445 1.5820313,0.6445 0.5615234,0 1.0693359,-0.166 0.5078125,-0.166 1.0302735,-0.5225 l 0,1.5088 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5370" />
<path
d="m 12.514648,1036.5687 0,1.5528 1.801758,0 0,1.25 -1.801758,0 0,2.3193 q 0,0.3809 0.151368,0.5176 0.151367,0.1318 0.600586,0.1318 l 0.898437,0 0,1.25 -1.499023,0 q -1.035157,0 -1.469727,-0.4297 -0.429687,-0.4345 -0.429687,-1.4697 l 0,-2.3193 -0.8691411,0 0,-1.25 0.8691411,0 0,-1.5528 1.748046,0 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5372" />
<path
d="m 19.453125,1039.6107 q -0.229492,-0.1074 -0.458984,-0.1562 -0.22461,-0.054 -0.454102,-0.054 -0.673828,0 -1.040039,0.4345 -0.361328,0.4297 -0.361328,1.2354 l 0,2.5195 -1.748047,0 0,-5.4687 1.748047,0 0,0.8984 q 0.336914,-0.5371 0.771484,-0.7813 0.439453,-0.249 1.049805,-0.249 0.08789,0 0.19043,0.01 0.102539,0 0.297851,0.029 l 0.0049,1.582 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5374" />
<path
d="m 20.332031,1035.9926 1.748047,0 0,7.5976 -1.748047,0 0,-7.5976 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5376" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,100 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="ctrlaltdel.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="11.135667"
inkscape:cy="16.407428"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5253"
width="5"
height="5.0000172"
x="16"
y="1031.3622"
ry="1.0000174" />
<rect
y="1043.3622"
x="4"
height="5.0000172"
width="5"
id="rect5255"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
ry="1.0000174" />
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5257"
width="5"
height="5.0000172"
x="13"
y="1043.3622"
ry="1.0000174" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,94 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="disconnect.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="25.05707"
inkscape:cy="11.594858"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
id="g5171"
transform="translate(-24.062499,-6.15775e-4)">
<path
id="path5110"
transform="translate(0,1027.3622)"
d="m 39.744141,3.4960938 c -0.769923,0 -1.539607,0.2915468 -2.121094,0.8730468 l -2.566406,2.5664063 1.414062,1.4140625 2.566406,-2.5664063 c 0.403974,-0.404 1.010089,-0.404 1.414063,0 l 2.828125,2.828125 c 0.40398,0.4039 0.403907,1.0101621 0,1.4140629 l -2.566406,2.566406 1.414062,1.414062 2.566406,-2.566406 c 1.163041,-1.1629 1.162968,-3.0791874 0,-4.2421874 L 41.865234,4.3691406 C 41.283747,3.7876406 40.514063,3.4960937 39.744141,3.4960938 Z M 39.017578,9.015625 a 1.0001,1.0001 0 0 0 -0.6875,0.3027344 l -0.445312,0.4453125 1.414062,1.4140621 0.445313,-0.445312 A 1.0001,1.0001 0 0 0 39.017578,9.015625 Z m -6.363281,0.7070312 a 1.0001,1.0001 0 0 0 -0.6875,0.3027348 L 28.431641,13.5625 c -1.163042,1.163 -1.16297,3.079187 0,4.242188 l 2.828125,2.828124 c 1.162974,1.163101 3.079213,1.163101 4.242187,0 l 3.535156,-3.535156 a 1.0001,1.0001 0 1 0 -1.414062,-1.414062 l -3.535156,3.535156 c -0.403974,0.404 -1.010089,0.404 -1.414063,0 l -2.828125,-2.828125 c -0.403981,-0.404 -0.403908,-1.010162 0,-1.414063 l 3.535156,-3.537109 A 1.0001,1.0001 0 0 0 32.654297,9.7226562 Z m 3.109375,2.1621098 -2.382813,2.384765 a 1.0001,1.0001 0 1 0 1.414063,1.414063 l 2.382812,-2.384766 -1.414062,-1.414062 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;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;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:connector-curvature="0" />
<rect
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,0,0)"
y="752.29541"
x="-712.31262"
height="18.000017"
width="3"
id="rect5116"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,76 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="drag.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="9.8789407"
inkscape:cy="9.5008608"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 7.039733,1049.3037 c -0.4309106,-0.1233 -0.7932634,-0.4631 -0.9705434,-0.9103 -0.04922,-0.1241 -0.057118,-0.2988 -0.071321,-1.5771 l -0.015972,-1.4375 -0.328125,-0.082 c -0.7668138,-0.1927 -1.1897046,-0.4275 -1.7031253,-0.9457 -0.4586773,-0.4629 -0.6804297,-0.8433 -0.867034,-1.4875 -0.067215,-0.232 -0.068001,-0.2642 -0.078682,-3.2188 -0.012078,-3.341 -0.020337,-3.2012 0.2099452,-3.5555 0.2246623,-0.3458 0.5798271,-0.5892 0.9667343,-0.6626 0.092506,-0.017 0.531898,-0.032 0.9764271,-0.032 l 0.8082347,0 1.157e-4,1.336 c 1.125e-4,1.2779 0.00281,1.3403 0.062214,1.4378 0.091785,0.1505 0.2357707,0.226 0.4314082,0.2261 0.285389,2e-4 0.454884,-0.1352 0.5058962,-0.4042 0.019355,-0.102 0.031616,-0.982 0.031616,-2.269 0,-1.9756 0.00357,-2.1138 0.059205,-2.2926 0.1645475,-0.5287 0.6307616,-0.9246 1.19078,-1.0113 0.8000572,-0.1238 1.5711277,0.4446 1.6860387,1.2429 0.01732,0.1203 0.03177,0.8248 0.03211,1.5657 6.19e-4,1.3449 7.22e-4,1.347 0.07093,1.4499 0.108355,0.1587 0.255268,0.2248 0.46917,0.2108 0.204069,-0.013 0.316116,-0.08 0.413642,-0.2453 0.06028,-0.1024 0.06307,-0.1778 0.07862,-2.1218 0.01462,-1.8283 0.02124,-2.0285 0.07121,-2.1549 0.260673,-0.659 0.934894,-1.0527 1.621129,-0.9465 0.640523,0.099 1.152269,0.6104 1.243187,1.2421 0.01827,0.1269 0.03175,0.9943 0.03211,2.0657 l 6.19e-4,1.8469 0.07031,0.103 c 0.108355,0.1587 0.255267,0.2248 0.46917,0.2108 0.204069,-0.013 0.316115,-0.08 0.413642,-0.2453 0.05951,-0.1011 0.06329,-0.1786 0.07907,-1.6218 0.01469,-1.3438 0.02277,-1.5314 0.07121,-1.6549 0.257975,-0.6576 0.934425,-1.0527 1.620676,-0.9465 0.640522,0.099 1.152269,0.6104 1.243186,1.2421 0.0186,0.1292 0.03179,1.0759 0.03222,2.3125 7.15e-4,2.0335 0.0025,2.0966 0.06283,2.1956 0.09178,0.1505 0.235771,0.226 0.431409,0.2261 0.285388,2e-4 0.454884,-0.1352 0.505897,-0.4042 0.01874,-0.099 0.03161,-0.8192 0.03161,-1.769 0,-1.4848 0.0043,-1.6163 0.0592,-1.7926 0.164548,-0.5287 0.630762,-0.9246 1.19078,-1.0113 0.800057,-0.1238 1.571128,0.4446 1.686039,1.2429 0.04318,0.2999 0.04372,9.1764 5.78e-4,9.4531 -0.04431,0.2841 -0.217814,0.6241 -0.420069,0.8232 -0.320102,0.315 -0.63307,0.4268 -1.194973,0.4268 l -0.35281,0 -2.51e-4,1.2734 c -1.25e-4,0.7046 -0.01439,1.3642 -0.03191,1.4766 -0.06665,0.4274 -0.372966,0.8704 -0.740031,1.0702 -0.349999,0.1905 0.01748,0.18 -6.242199,0.1776 -5.3622439,0 -5.7320152,-0.01 -5.9121592,-0.057 l 1.4e-5,0 z"
id="path4379"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -0,0 +1,81 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="error.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="14.00357"
inkscape:cy="12.443398"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 7 3 C 4.7839905 3 3 4.7839905 3 7 L 3 18 C 3 20.21601 4.7839905 22 7 22 L 18 22 C 20.21601 22 22 20.21601 22 18 L 22 7 C 22 4.7839905 20.21601 3 18 3 L 7 3 z M 7.6992188 6 A 1.6916875 1.6924297 0 0 1 8.9121094 6.5117188 L 12.5 10.101562 L 16.087891 6.5117188 A 1.6916875 1.6924297 0 0 1 17.251953 6 A 1.6916875 1.6924297 0 0 1 18.480469 8.90625 L 14.892578 12.496094 L 18.480469 16.085938 A 1.6916875 1.6924297 0 1 1 16.087891 18.478516 L 12.5 14.888672 L 8.9121094 18.478516 A 1.6916875 1.6924297 0 1 1 6.5214844 16.085938 L 10.109375 12.496094 L 6.5214844 8.90625 A 1.6916875 1.6924297 0 0 1 7.6992188 6 z "
transform="translate(0,1027.3622)"
id="rect4135" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,92 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="esc.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="18.205425"
inkscape:cy="17.531398"
inkscape:document-units="px"
inkscape:current-layer="text5290"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:48px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text5290">
<path
d="m 3.9331055,1036.1464 5.0732422,0 0,1.4209 -3.1933594,0 0,1.3574 3.0029297,0 0,1.4209 -3.0029297,0 0,1.6699 3.3007812,0 0,1.4209 -5.180664,0 0,-7.29 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5314" />
<path
d="m 14.963379,1038.1385 0,1.3282 q -0.561524,-0.2344 -1.083984,-0.3516 -0.522461,-0.1172 -0.986329,-0.1172 -0.498046,0 -0.742187,0.127 -0.239258,0.122 -0.239258,0.3808 0,0.21 0.180664,0.3223 0.185547,0.1123 0.65918,0.166 l 0.307617,0.044 q 1.342773,0.1709 1.806641,0.5615 0.463867,0.3906 0.463867,1.2256 0,0.874 -0.644531,1.3134 -0.644532,0.4395 -1.923829,0.4395 -0.541992,0 -1.123046,-0.088 -0.576172,-0.083 -1.186524,-0.2539 l 0,-1.3281 q 0.522461,0.2539 1.069336,0.3808 0.551758,0.127 1.118164,0.127 0.512695,0 0.771485,-0.1416 0.258789,-0.1416 0.258789,-0.4199 0,-0.2344 -0.180664,-0.3467 -0.175782,-0.1172 -0.708008,-0.1807 l -0.307617,-0.039 q -1.166993,-0.1465 -1.635743,-0.542 -0.46875,-0.3955 -0.46875,-1.2012 0,-0.8691 0.595703,-1.2891 0.595704,-0.4199 1.826172,-0.4199 0.483399,0 1.015625,0.073 0.532227,0.073 1.157227,0.2294 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5316" />
<path
d="m 21.066895,1038.1385 0,1.4258 q -0.356446,-0.2441 -0.717774,-0.3613 -0.356445,-0.1172 -0.742187,-0.1172 -0.732422,0 -1.142579,0.4297 -0.405273,0.4248 -0.405273,1.1914 0,0.7666 0.405273,1.1963 0.410157,0.4248 1.142579,0.4248 0.410156,0 0.776367,-0.1221 0.371094,-0.122 0.683594,-0.3613 l 0,1.4307 q -0.410157,0.1513 -0.834961,0.2246 -0.419922,0.078 -0.844727,0.078 -1.479492,0 -2.314453,-0.7568 -0.834961,-0.7618 -0.834961,-2.1143 0,-1.3525 0.834961,-2.1094 0.834961,-0.7617 2.314453,-0.7617 0.429688,0 0.844727,0.078 0.419921,0.073 0.834961,0.2246 z"
style="font-size:10px;fill:#ffffff;fill-opacity:1"
id="path5318" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,69 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="9"
height="10"
viewBox="0 0 9 10"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="expander.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="45.254834"
inkscape:cx="9.8737281"
inkscape:cy="6.4583132"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-object-midpoints="false"
inkscape:object-nodes="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1042.3622)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;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;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 2.0800781,1042.3633 A 2.0002,2.0002 0 0 0 0,1044.3613 l 0,6 a 2.0002,2.0002 0 0 0 3.0292969,1.7168 l 5,-3 a 2.0002,2.0002 0 0 0 0,-3.4316 l -5,-3 a 2.0002,2.0002 0 0 0 -0.9492188,-0.2832 z"
id="path4138"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,93 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="fullscreen.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="16.400723"
inkscape:cy="15.083758"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<rect
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5006"
width="17"
height="17.000017"
x="4"
y="1031.3622"
ry="3.0000174" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
d="m 7.5,1044.8622 4,0 -1.5,-1.5 1.5,-1.5 -1,-1 -1.5,1.5 -1.5,-1.5 0,4 z"
id="path5017"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
id="path5025"
d="m 17.5,1034.8622 -4,0 1.5,1.5 -1.5,1.5 1,1 1.5,-1.5 1.5,1.5 0,-4 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,82 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="5"
height="6"
viewBox="0 0 5 6"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="handle.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="1.3551778"
inkscape:cy="8.7800329"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1046.3622)">
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.0000803,1049.3622 -3,-2 0,4 z"
id="path4247"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,172 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="15"
height="50"
viewBox="0 0 15 50"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="handle_bg.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="-10.001409"
inkscape:cy="24.512566"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1002.3622)">
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4249"
width="1"
height="1.0000174"
x="9.5"
y="1008.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1013.8622"
x="9.5"
height="1.0000174"
width="1"
id="rect4255"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
ry="1.7382812e-05"
y="1008.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4261"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4263"
width="1"
height="1.0000174"
x="4.5"
y="1013.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1039.8622"
x="9.5"
height="1.0000174"
width="1"
id="rect4265"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4267"
width="1"
height="1.0000174"
x="9.5"
y="1044.8622"
ry="1.7382812e-05" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4269"
width="1"
height="1.0000174"
x="4.5"
y="1039.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1044.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4271"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4273"
width="1"
height="1.0000174"
x="9.5"
y="1018.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1018.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4275"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4277"
width="1"
height="1.0000174"
x="9.5"
y="1034.8622"
ry="1.7382812e-05" />
<rect
ry="1.7382812e-05"
y="1034.8622"
x="4.5"
height="1.0000174"
width="1"
id="rect4279"
style="opacity:0.25;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,42 @@
ICONS := \
novnc-16x16.png \
novnc-24x24.png \
novnc-32x32.png \
novnc-48x48.png \
novnc-64x64.png
ANDROID_LAUNCHER := \
novnc-48x48.png \
novnc-72x72.png \
novnc-96x96.png \
novnc-144x144.png \
novnc-192x192.png
IPHONE_LAUNCHER := \
novnc-60x60.png \
novnc-120x120.png
IPAD_LAUNCHER := \
novnc-76x76.png \
novnc-152x152.png
ALL_ICONS := $(ICONS) $(ANDROID_LAUNCHER) $(IPHONE_LAUNCHER) $(IPAD_LAUNCHER)
all: $(ALL_ICONS)
novnc-16x16.png: novnc-icon-sm.svg
convert -density 90 \
-background transparent "$<" "$@"
novnc-24x24.png: novnc-icon-sm.svg
convert -density 135 \
-background transparent "$<" "$@"
novnc-32x32.png: novnc-icon-sm.svg
convert -density 180 \
-background transparent "$<" "$@"
novnc-%.png: novnc-icon.svg
convert -density $$[`echo $* | cut -d x -f 1` * 90 / 48] \
-background transparent "$<" "$@"
clean:
rm -f *.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1000 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,163 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 16 16"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="novnc-icon-sm.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="45.254834"
inkscape:cx="9.722703"
inkscape:cy="5.5311896"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4169" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3621)">
<rect
style="opacity:1;fill:#494949;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4167"
width="16"
height="15.999992"
x="0"
y="1036.3622"
ry="2.6666584" />
<path
style="opacity:1;fill:#313131;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 2.6666667,1036.3621 C 1.1893373,1036.3621 0,1037.5515 0,1039.0288 l 0,10.6666 c 0,1.4774 1.1893373,2.6667 2.6666667,2.6667 l 4,0 C 11.837333,1052.3621 16,1046.7128 16,1039.6955 l 0,-0.6667 c 0,-1.4773 -1.189337,-2.6667 -2.666667,-2.6667 l -10.6666663,0 z"
id="rect4173"
inkscape:connector-curvature="0" />
<g
id="g4381">
<g
transform="translate(0.25,0.25)"
style="fill:#000000;fill-opacity:1"
id="g4365">
<g
style="fill:#000000;fill-opacity:1"
id="g4367">
<path
inkscape:connector-curvature="0"
id="path4369"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 4.3289754,1039.3621 c 0.1846149,0 0.3419956,0.071 0.4716623,0.2121 C 4.933546,1039.7121 5,1039.8793 5,1040.0759 l 0,3.2862 -1,0 0,-2.964 c 0,-0.024 -0.011592,-0.036 -0.034038,-0.036 l -1.931924,0 C 2.011349,1040.3621 2,1040.3741 2,1040.3981 l 0,2.964 -1,0 0,-4 z"
sodipodi:nodetypes="scsccsssscccs" />
<path
inkscape:connector-curvature="0"
id="path4371"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 6.6710244,1039.3621 2.6579513,0 c 0.184775,0 0.3419957,0.071 0.471662,0.2121 C 9.933546,1039.7121 10,1039.8793 10,1040.0759 l 0,2.5724 c 0,0.1966 -0.066454,0.3655 -0.1993623,0.5069 -0.1296663,0.1379 -0.286887,0.2069 -0.471662,0.2069 l -2.6579513,0 c -0.184775,0 -0.3436164,-0.069 -0.4765247,-0.2069 C 6.0648334,1043.0138 6,1042.8449 6,1042.6483 l 0,-2.5724 c 0,-0.1966 0.064833,-0.3638 0.1944997,-0.5017 0.1329083,-0.1414 0.2917497,-0.2121 0.4765247,-0.2121 z m 2.2949386,1 -1.931926,0 C 7.011344,1040.3621 7,1040.3741 7,1040.3981 l 0,1.928 c 0,0.024 0.011347,0.036 0.034037,0.036 l 1.931926,0 c 0.02269,0 0.034037,-0.012 0.034037,-0.036 l 0,-1.928 c 0,-0.024 -0.011347,-0.036 -0.034037,-0.036 z"
sodipodi:nodetypes="sscsscsscsscssssssssss" />
</g>
<g
style="fill:#000000;fill-opacity:1"
id="g4373">
<path
inkscape:connector-curvature="0"
id="path4375"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 3,1047.1121 1,-2.75 1,0 -1.5,4 -1,0 -1.5,-4 1,0 z"
sodipodi:nodetypes="cccccccc" />
<path
inkscape:connector-curvature="0"
id="path4377"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 9,1046.8621 0,-2.5 1,0 0,4 -1,0 -2,-2.5 0,2.5 -1,0 0,-4 1,0 z"
sodipodi:nodetypes="ccccccccccc" />
<path
inkscape:connector-curvature="0"
id="path4379"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 15,1045.3621 -2.96596,0 c -0.02269,0 -0.03404,0.012 -0.03404,0.036 l 0,1.928 c 0,0.024 0.01135,0.036 0.03404,0.036 l 2.96596,0 0,1 -3.324113,0 c -0.188017,0 -0.348479,-0.068 -0.481388,-0.2037 C 11.064833,1048.0192 11,1047.8511 11,1047.6542 l 0,-2.5842 c 0,-0.1969 0.06483,-0.3633 0.194499,-0.4991 0.132909,-0.1392 0.293371,-0.2088 0.481388,-0.2088 l 3.324113,0 z"
sodipodi:nodetypes="cssssccscsscscc" />
</g>
</g>
<g
id="g4356">
<g
id="g4347">
<path
sodipodi:nodetypes="scsccsssscccs"
d="m 4.3289754,1039.3621 c 0.1846149,0 0.3419956,0.071 0.4716623,0.2121 C 4.933546,1039.7121 5,1039.8793 5,1040.0759 l 0,3.2862 -1,0 0,-2.964 c 0,-0.024 -0.011592,-0.036 -0.034038,-0.036 l -1.931924,0 c -0.022689,0 -0.034038,0.012 -0.034038,0.036 l 0,2.964 -1,0 0,-4 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4143"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="sscsscsscsscssssssssss"
d="m 6.6710244,1039.3621 2.6579513,0 c 0.184775,0 0.3419957,0.071 0.471662,0.2121 C 9.933546,1039.7121 10,1039.8793 10,1040.0759 l 0,2.5724 c 0,0.1966 -0.066454,0.3655 -0.1993623,0.5069 -0.1296663,0.1379 -0.286887,0.2069 -0.471662,0.2069 l -2.6579513,0 c -0.184775,0 -0.3436164,-0.069 -0.4765247,-0.2069 C 6.0648334,1043.0138 6,1042.8449 6,1042.6483 l 0,-2.5724 c 0,-0.1966 0.064833,-0.3638 0.1944997,-0.5017 0.1329083,-0.1414 0.2917497,-0.2121 0.4765247,-0.2121 z m 2.2949386,1 -1.931926,0 C 7.011344,1040.3621 7,1040.3741 7,1040.3981 l 0,1.928 c 0,0.024 0.011347,0.036 0.034037,0.036 l 1.931926,0 c 0.02269,0 0.034037,-0.012 0.034037,-0.036 l 0,-1.928 c 0,-0.024 -0.011347,-0.036 -0.034037,-0.036 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4145"
inkscape:connector-curvature="0" />
</g>
<g
id="g4351">
<path
sodipodi:nodetypes="cccccccc"
d="m 3,1047.1121 1,-2.75 1,0 -1.5,4 -1,0 -1.5,-4 1,0 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4147"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccccccccc"
d="m 9,1046.8621 0,-2.5 1,0 0,4 -1,0 -2,-2.5 0,2.5 -1,0 0,-4 1,0 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4149"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cssssccscsscscc"
d="m 15,1045.3621 -2.96596,0 c -0.02269,0 -0.03404,0.012 -0.03404,0.036 l 0,1.928 c 0,0.024 0.01135,0.036 0.03404,0.036 l 2.96596,0 0,1 -3.324113,0 c -0.188017,0 -0.348479,-0.068 -0.481388,-0.2037 C 11.064833,1048.0192 11,1047.8511 11,1047.6542 l 0,-2.5842 c 0,-0.1969 0.06483,-0.3633 0.194499,-0.4991 0.132909,-0.1392 0.293371,-0.2088 0.481388,-0.2088 l 3.324113,0 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4151"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,163 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
viewBox="0 0 48 48.000001"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="novnc-icon.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
inkscape:cx="27.187245"
inkscape:cy="17.700974"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:object-nodes="true"
inkscape:snap-smooth-nodes="true"
inkscape:snap-midpoints="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4169" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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"
transform="translate(0,-1004.3621)">
<rect
style="opacity:1;fill:#494949;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4167"
width="48"
height="48"
x="0"
y="1004.3621"
ry="7.9999785" />
<path
style="opacity:1;fill:#313131;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 8,1004.3621 c -4.4319881,0 -8,3.568 -8,8 l 0,32 c 0,4.432 3.5680119,8 8,8 l 12,0 c 15.512,0 28,-16.948 28,-38 l 0,-2 c 0,-4.432 -3.568012,-8 -8,-8 l -32,0 z"
id="rect4173"
inkscape:connector-curvature="0" />
<g
id="g4300"
style="fill:#000000;fill-opacity:1;stroke:none"
transform="translate(0.5,0.5)">
<g
id="g4302"
style="fill:#000000;fill-opacity:1;stroke:none">
<path
sodipodi:nodetypes="scsccsssscccs"
d="m 11.986926,1016.3621 c 0.554325,0 1.025987,0.2121 1.414987,0.6362 0.398725,0.4138 0.600909,0.9155 0.598087,1.5052 l 0,6.8586 -2,0 0,-6.8914 c 0,-0.072 -0.03404,-0.1086 -0.102113,-0.1086 l -4.7957745,0 C 7.0340375,1018.3621 7,1018.3983 7,1018.4707 l 0,6.8914 -2,0 0,-9 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4304"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="sscsscsscsscssssssssss"
d="m 17.013073,1016.3621 4.973854,0 c 0.554325,0 1.025987,0.2121 1.414986,0.6362 0.398725,0.4138 0.598087,0.9155 0.598087,1.5052 l 0,4.7172 c 0,0.5897 -0.199362,1.0966 -0.598087,1.5207 -0.388999,0.4138 -0.860661,0.6207 -1.414986,0.6207 l -4.973854,0 c -0.554325,0 -1.030849,-0.2069 -1.429574,-0.6207 C 15.1945,1024.3173 15,1023.8104 15,1023.2207 l 0,-4.7172 c 0,-0.5897 0.1945,-1.0914 0.583499,-1.5052 0.398725,-0.4241 0.875249,-0.6362 1.429574,-0.6362 z m 4.884815,2 -4.795776,0 c -0.06808,0 -0.102112,0.036 -0.102112,0.1086 l 0,4.7828 c 0,0.072 0.03404,0.1086 0.102112,0.1086 l 4.795776,0 c 0.06807,0 0.102112,-0.036 0.102112,-0.1086 l 0,-4.7828 c 0,-0.072 -0.03404,-0.1086 -0.102112,-0.1086 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4306"
inkscape:connector-curvature="0" />
</g>
<g
id="g4308"
style="fill:#000000;fill-opacity:1;stroke:none">
<path
sodipodi:nodetypes="cccccccc"
d="m 12,1036.9177 4.768114,-8.5556 2.231886,0 -6,11 -2,0 -6,-11 2.2318854,0 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4310"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccccccccccc"
d="m 29,1036.3621 0,-8 2,0 0,11 -2,0 -7,-8 0,8 -2,0 0,-11 2,0 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4312"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="cssssccscsscscc"
d="m 43,1030.3621 -8.897887,0 c -0.06808,0 -0.102113,0.036 -0.102113,0.1069 l 0,6.7862 c 0,0.071 0.03404,0.1069 0.102113,0.1069 l 8.897887,0 0,2 -8.972339,0 c -0.56405,0 -1.045437,-0.2037 -1.444162,-0.6111 C 32.1945,1038.3334 32,1037.8292 32,1037.2385 l 0,-6.7528 c 0,-0.5907 0.1945,-1.0898 0.583499,-1.4972 0.398725,-0.4176 0.880112,-0.6264 1.444162,-0.6264 l 8.972339,0 z"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="path4314"
inkscape:connector-curvature="0" />
</g>
</g>
<g
id="g4291"
style="stroke:none">
<g
id="g4282"
style="stroke:none">
<path
inkscape:connector-curvature="0"
id="path4143"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 11.986926,1016.3621 c 0.554325,0 1.025987,0.2121 1.414987,0.6362 0.398725,0.4138 0.600909,0.9155 0.598087,1.5052 l 0,6.8586 -2,0 0,-6.8914 c 0,-0.072 -0.03404,-0.1086 -0.102113,-0.1086 l -4.7957745,0 C 7.0340375,1018.3621 7,1018.3983 7,1018.4707 l 0,6.8914 -2,0 0,-9 z"
sodipodi:nodetypes="scsccsssscccs" />
<path
inkscape:connector-curvature="0"
id="path4145"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#008000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 17.013073,1016.3621 4.973854,0 c 0.554325,0 1.025987,0.2121 1.414986,0.6362 0.398725,0.4138 0.598087,0.9155 0.598087,1.5052 l 0,4.7172 c 0,0.5897 -0.199362,1.0966 -0.598087,1.5207 -0.388999,0.4138 -0.860661,0.6207 -1.414986,0.6207 l -4.973854,0 c -0.554325,0 -1.030849,-0.2069 -1.429574,-0.6207 C 15.1945,1024.3173 15,1023.8104 15,1023.2207 l 0,-4.7172 c 0,-0.5897 0.1945,-1.0914 0.583499,-1.5052 0.398725,-0.4241 0.875249,-0.6362 1.429574,-0.6362 z m 4.884815,2 -4.795776,0 c -0.06808,0 -0.102112,0.036 -0.102112,0.1086 l 0,4.7828 c 0,0.072 0.03404,0.1086 0.102112,0.1086 l 4.795776,0 c 0.06807,0 0.102112,-0.036 0.102112,-0.1086 l 0,-4.7828 c 0,-0.072 -0.03404,-0.1086 -0.102112,-0.1086 z"
sodipodi:nodetypes="sscsscsscsscssssssssss" />
</g>
<g
id="g4286"
style="stroke:none">
<path
inkscape:connector-curvature="0"
id="path4147"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 12,1036.9177 4.768114,-8.5556 2.231886,0 -6,11 -2,0 -6,-11 2.2318854,0 z"
sodipodi:nodetypes="cccccccc" />
<path
inkscape:connector-curvature="0"
id="path4149"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 29,1036.3621 0,-8 2,0 0,11 -2,0 -7,-8 0,8 -2,0 0,-11 2,0 z"
sodipodi:nodetypes="ccccccccccc" />
<path
inkscape:connector-curvature="0"
id="path4151"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:medium;line-height:125%;font-family:Orbitron;-inkscape-font-specification:'Orbitron Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffff00;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 43,1030.3621 -8.897887,0 c -0.06808,0 -0.102113,0.036 -0.102113,0.1069 l 0,6.7862 c 0,0.071 0.03404,0.1069 0.102113,0.1069 l 8.897887,0 0,2 -8.972339,0 c -0.56405,0 -1.045437,-0.2037 -1.444162,-0.6111 C 32.1945,1038.3334 32,1037.8292 32,1037.2385 l 0,-6.7528 c 0,-0.5907 0.1945,-1.0898 0.583499,-1.4972 0.398725,-0.4176 0.880112,-0.6264 1.444162,-0.6264 l 8.972339,0 z"
sodipodi:nodetypes="cssssccscsscscc" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,81 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="info.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="15.720838"
inkscape:cy="8.9111233"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 12.5 3 A 9.5 9.4999914 0 0 0 3 12.5 A 9.5 9.4999914 0 0 0 12.5 22 A 9.5 9.4999914 0 0 0 22 12.5 A 9.5 9.4999914 0 0 0 12.5 3 z M 12.5 5 A 1.5 1.5000087 0 0 1 14 6.5 A 1.5 1.5000087 0 0 1 12.5 8 A 1.5 1.5000087 0 0 1 11 6.5 A 1.5 1.5000087 0 0 1 12.5 5 z M 10.521484 8.9785156 L 12.521484 8.9785156 A 1.50015 1.50015 0 0 1 14.021484 10.478516 L 14.021484 15.972656 A 1.50015 1.50015 0 0 1 14.498047 18.894531 C 14.498047 18.894531 13.74301 19.228309 12.789062 18.912109 C 12.312092 18.754109 11.776235 18.366625 11.458984 17.828125 C 11.141734 17.289525 11.021484 16.668469 11.021484 15.980469 L 11.021484 11.980469 L 10.521484 11.980469 A 1.50015 1.50015 0 1 1 10.521484 8.9804688 L 10.521484 8.9785156 z "
transform="translate(0,1027.3622)"
id="path4136" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,88 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="keyboard.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/keyboard.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#717171"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="31.285341"
inkscape:cy="8.8028469"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:snap-bbox-midpoints="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="true"
inkscape:object-nodes="true"
inkscape:snap-midpoints="true"
inkscape:snap-smooth-nodes="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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"
transform="translate(0,-1027.3622)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;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;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 7,3 C 4.8012876,3 3,4.8013 3,7 3,11.166667 3,15.333333 3,19.5 3,20.8764 4.1236413,22 5.5,22 l 14,0 C 20.876358,22 22,20.8764 22,19.5 22,15.333333 22,11.166667 22,7 22,4.8013 20.198712,3 18,3 Z m 0,2 11,0 c 1.125307,0 2,0.8747 2,2 L 20,12 5,12 5,7 C 5,5.8747 5.8746931,5 7,5 Z M 6.5,14 C 6.777,14 7,14.223 7,14.5 7,14.777 6.777,15 6.5,15 6.223,15 6,14.777 6,14.5 6,14.223 6.223,14 6.5,14 Z m 2,0 C 8.777,14 9,14.223 9,14.5 9,14.777 8.777,15 8.5,15 8.223,15 8,14.777 8,14.5 8,14.223 8.223,14 8.5,14 Z m 2,0 C 10.777,14 11,14.223 11,14.5 11,14.777 10.777,15 10.5,15 10.223,15 10,14.777 10,14.5 10,14.223 10.223,14 10.5,14 Z m 2,0 C 12.777,14 13,14.223 13,14.5 13,14.777 12.777,15 12.5,15 12.223,15 12,14.777 12,14.5 12,14.223 12.223,14 12.5,14 Z m 2,0 C 14.777,14 15,14.223 15,14.5 15,14.777 14.777,15 14.5,15 14.223,15 14,14.777 14,14.5 14,14.223 14.223,14 14.5,14 Z m 2,0 C 16.777,14 17,14.223 17,14.5 17,14.777 16.777,15 16.5,15 16.223,15 16,14.777 16,14.5 16,14.223 16.223,14 16.5,14 Z m 2,0 C 18.777,14 19,14.223 19,14.5 19,14.777 18.777,15 18.5,15 18.223,15 18,14.777 18,14.5 18,14.223 18.223,14 18.5,14 Z m -13,2 C 5.777,16 6,16.223 6,16.5 6,16.777 5.777,17 5.5,17 5.223,17 5,16.777 5,16.5 5,16.223 5.223,16 5.5,16 Z m 2,0 C 7.777,16 8,16.223 8,16.5 8,16.777 7.777,17 7.5,17 7.223,17 7,16.777 7,16.5 7,16.223 7.223,16 7.5,16 Z m 2,0 C 9.777,16 10,16.223 10,16.5 10,16.777 9.777,17 9.5,17 9.223,17 9,16.777 9,16.5 9,16.223 9.223,16 9.5,16 Z m 2,0 C 11.777,16 12,16.223 12,16.5 12,16.777 11.777,17 11.5,17 11.223,17 11,16.777 11,16.5 11,16.223 11.223,16 11.5,16 Z m 2,0 C 13.777,16 14,16.223 14,16.5 14,16.777 13.777,17 13.5,17 13.223,17 13,16.777 13,16.5 13,16.223 13.223,16 13.5,16 Z m 2,0 C 15.777,16 16,16.223 16,16.5 16,16.777 15.777,17 15.5,17 15.223,17 15,16.777 15,16.5 15,16.223 15.223,16 15.5,16 Z m 2,0 C 17.777,16 18,16.223 18,16.5 18,16.777 17.777,17 17.5,17 17.223,17 17,16.777 17,16.5 17,16.223 17.223,16 17.5,16 Z m 2,0 C 19.777,16 20,16.223 20,16.5 20,16.777 19.777,17 19.5,17 19.223,17 19,16.777 19,16.5 19,16.223 19.223,16 19.5,16 Z M 6,18 c 0.554,0 1,0.446 1,1 0,0.554 -0.446,1 -1,1 -0.554,0 -1,-0.446 -1,-1 0,-0.554 0.446,-1 1,-1 z m 2.8261719,0 7.3476561,0 C 16.631643,18 17,18.368372 17,18.826172 l 0,0.347656 C 17,19.631628 16.631643,20 16.173828,20 L 8.8261719,20 C 8.3683573,20 8,19.631628 8,19.173828 L 8,18.826172 C 8,18.368372 8.3683573,18 8.8261719,18 Z m 10.1113281,0 0.125,0 C 19.581551,18 20,18.4184 20,18.9375 l 0,0.125 C 20,19.5816 19.581551,20 19.0625,20 l -0.125,0 C 18.418449,20 18,19.5816 18,19.0625 l 0,-0.125 C 18,18.4184 18.418449,18 18.9375,18 Z"
transform="translate(0,1027.3622)"
id="rect4160"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sccssccsssssccssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss" />
<path
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 12.499929,1033.8622 -2,2 1.500071,0 0,2 1,0 0,-2 1.499929,0 z"
id="path4150"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -0,0 +1,87 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="power.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="9.3159849"
inkscape:cy="13.436208"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;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;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 9 6.8183594 C 6.3418164 8.1213032 4.5 10.849161 4.5 14 C 4.5 18.4065 8.0935666 22 12.5 22 C 16.906433 22 20.5 18.4065 20.5 14 C 20.5 10.849161 18.658184 8.1213032 16 6.8183594 L 16 9.125 C 17.514327 10.211757 18.5 11.984508 18.5 14 C 18.5 17.3256 15.825553 20 12.5 20 C 9.1744469 20 6.5 17.3256 6.5 14 C 6.5 11.984508 7.4856727 10.211757 9 9.125 L 9 6.8183594 z "
transform="translate(0,1027.3622)"
id="path6140" />
<path
style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 12.5,1031.8836 0,6.4786"
id="path6142"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,76 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="settings.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="14.69683"
inkscape:cy="8.8039511"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 11 3 L 11 5.1601562 A 7.5 7.5 0 0 0 8.3671875 6.2460938 L 6.84375 4.7226562 L 4.7226562 6.84375 L 6.2480469 8.3691406 A 7.5 7.5 0 0 0 5.1523438 11 L 3 11 L 3 14 L 5.1601562 14 A 7.5 7.5 0 0 0 6.2460938 16.632812 L 4.7226562 18.15625 L 6.84375 20.277344 L 8.3691406 18.751953 A 7.5 7.5 0 0 0 11 19.847656 L 11 22 L 14 22 L 14 19.839844 A 7.5 7.5 0 0 0 16.632812 18.753906 L 18.15625 20.277344 L 20.277344 18.15625 L 18.751953 16.630859 A 7.5 7.5 0 0 0 19.847656 14 L 22 14 L 22 11 L 19.839844 11 A 7.5 7.5 0 0 0 18.753906 8.3671875 L 20.277344 6.84375 L 18.15625 4.7226562 L 16.630859 6.2480469 A 7.5 7.5 0 0 0 14 5.1523438 L 14 3 L 11 3 z M 12.5 10 A 2.5 2.5 0 0 1 15 12.5 A 2.5 2.5 0 0 1 12.5 15 A 2.5 2.5 0 0 1 10 12.5 A 2.5 2.5 0 0 1 12.5 10 z "
transform="translate(0,1027.3622)"
id="rect4967" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,86 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="tab.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="16"
inkscape:cx="11.67335"
inkscape:cy="17.881696"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="true"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 3,1031.3622 0,8 2,0 0,-4 0,-4 -2,0 z m 2,4 4,4 0,-3 13,0 0,-2 -13,0 0,-3 -4,4 z"
id="rect5194"
inkscape:connector-curvature="0" />
<path
id="path5211"
d="m 22,1048.3622 0,-8 -2,0 0,4 0,4 2,0 z m -2,-4 -4,-4 0,3 -13,0 0,2 13,0 0,3 4,-4 z"
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,90 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="extrakeys.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="15.234555"
inkscape:cy="9.9710826"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="false">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;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;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 8,1031.3622 c -2.1987124,0 -4,1.8013 -4,4 l 0,8.9996 c 0,2.1987 1.8012876,4 4,4 l 9,0 c 2.198712,0 4,-1.8013 4,-4 l 0,-8.9996 c 0,-2.1987 -1.801288,-4 -4,-4 z m 0,2 9,0 c 1.125307,0 2,0.8747 2,2 l 0,7.0005 c 0,1.1253 -0.874693,2 -2,2 l -9,0 c -1.1253069,0 -2,-0.8747 -2,-2 l 0,-7.0005 c 0,-1.1253 0.8746931,-2 2,-2 z"
id="rect5006"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ssssssssssssssssss" />
<g
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10px;line-height:125%;font-family:'DejaVu Sans';-inkscape-font-specification:'Sans Bold';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text4167"
transform="matrix(0.96021948,0,0,0.96021948,0.18921715,41.80659)">
<path
d="m 14.292969,1040.6791 -2.939453,0 -0.463868,1.3281 -1.889648,0 2.700195,-7.29 2.241211,0 2.700196,7.29 -1.889649,0 -0.458984,-1.3281 z m -2.470703,-1.3526 1.99707,0 -0.996094,-2.9004 -1.000976,2.9004 z"
id="path4172"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,81 @@
<?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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="25"
height="25"
viewBox="0 0 25 25"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="warning.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="16.457343"
inkscape:cy="12.179552"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-paths="true"
showguides="false"
inkscape:window-width="1920"
inkscape:window-height="1136"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:object-nodes="true"
inkscape:snap-intersection-paths="true"
inkscape:snap-nodes="true"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid4136" />
</sodipodi:namedview>
<metadata
id="metadata7">
<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></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1027.3622)">
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;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;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 12.513672 3.0019531 C 11.751609 2.9919531 11.052563 3.4242687 10.710938 4.1054688 L 3.2109375 19.105469 C 2.5461937 20.435369 3.5132277 21.9999 5 22 L 20 22 C 21.486772 21.9999 22.453806 20.435369 21.789062 19.105469 L 14.289062 4.1054688 C 13.951849 3.4330688 13.265888 3.0066531 12.513672 3.0019531 z M 12.478516 6.9804688 A 1.50015 1.50015 0 0 1 14 8.5 L 14 14.5 A 1.50015 1.50015 0 1 1 11 14.5 L 11 8.5 A 1.50015 1.50015 0 0 1 12.478516 6.9804688 z M 12.5 17 A 1.5 1.5 0 0 1 14 18.5 A 1.5 1.5 0 0 1 12.5 20 A 1.5 1.5 0 0 1 11 18.5 A 1.5 1.5 0 0 1 12.5 17 z "
transform="translate(0,1027.3622)"
id="path4208" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
inkscape:export-ydpi="90"
inkscape:export-xdpi="90"
sodipodi:docname="windows.svg"
inkscape:export-filename="/home/ossman/devel/noVNC/images/drag.png"
inkscape:version="0.92.4 (unknown)"
x="0px"
y="0px"
viewBox="-293 384 25 25"
xml:space="preserve"
width="25"
height="25"><metadata
id="metadata21"><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></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs19" /><sodipodi:namedview
pagecolor="#959595"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1136"
id="namedview17"
showgrid="true"
inkscape:pagecheckerboard="false"
inkscape:zoom="32"
inkscape:cx="3.926913"
inkscape:cy="13.255959"
inkscape:window-x="1920"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"><inkscape:grid
type="xygrid"
id="grid818" /></sodipodi:namedview>
<style
type="text/css"
id="style2">
.st0{fill:#FFFFFF;}
</style>
<path
style="fill:#ffffff;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="M 21 4 L 11 5.1757812 L 11 12 L 21 12 L 21 4 z M 10 5.2949219 L 4 6 L 4 12 L 10 12 L 10 5.2949219 z "
transform="translate(-293,384)"
id="path853" /><path
id="path858"
d="m -272,405 -10,-1.17578 V 397 h 10 z M -283,403.70508 -289,403 v -6 h 6 z"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
DO NOT MODIFY THE FILES IN THIS FOLDER, THEY ARE AUTOMATICALLY GENERATED FROM THE PO-FILES.

View File

@ -0,0 +1,71 @@
{
"Connecting...": "Připojení...",
"Disconnecting...": "Odpojení...",
"Reconnecting...": "Obnova připojení...",
"Internal error": "Vnitřní chyba",
"Must set host": "Hostitel musí být nastavení",
"Connected (encrypted) to ": "Připojení (šifrované) k ",
"Connected (unencrypted) to ": "Připojení (nešifrované) k ",
"Something went wrong, connection is closed": "Něco se pokazilo, odpojeno",
"Failed to connect to server": "Chyba připojení k serveru",
"Disconnected": "Odpojeno",
"New connection has been rejected with reason: ": "Nové připojení bylo odmítnuto s odůvodněním: ",
"New connection has been rejected": "Nové připojení bylo odmítnuto",
"Password is required": "Je vyžadováno heslo",
"noVNC encountered an error:": "noVNC narazilo na chybu:",
"Hide/Show the control bar": "Skrýt/zobrazit ovládací panel",
"Move/Drag Viewport": "Přesunout/přetáhnout výřez",
"viewport drag": "přesun výřezu",
"Active Mouse Button": "Aktivní tlačítka myši",
"No mousebutton": "Žádné",
"Left mousebutton": "Levé tlačítko myši",
"Middle mousebutton": "Prostřední tlačítko myši",
"Right mousebutton": "Pravé tlačítko myši",
"Keyboard": "Klávesnice",
"Show Keyboard": "Zobrazit klávesnici",
"Extra keys": "Extra klávesy",
"Show Extra Keys": "Zobrazit extra klávesy",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Přepnout Ctrl",
"Alt": "Alt",
"Toggle Alt": "Přepnout Alt",
"Send Tab": "Odeslat tabulátor",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Odeslat Esc",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Poslat Ctrl-Alt-Del",
"Shutdown/Reboot": "Vypnutí/Restart",
"Shutdown/Reboot...": "Vypnutí/Restart...",
"Power": "Napájení",
"Shutdown": "Vypnout",
"Reboot": "Restart",
"Reset": "Reset",
"Clipboard": "Schránka",
"Clear": "Vymazat",
"Fullscreen": "Celá obrazovka",
"Settings": "Nastavení",
"Shared Mode": "Sdílený režim",
"View Only": "Pouze prohlížení",
"Clip to Window": "Přizpůsobit oknu",
"Scaling Mode:": "Přizpůsobení velikosti",
"None": "Žádné",
"Local Scaling": "Místní",
"Remote Resizing": "Vzdálené",
"Advanced": "Pokročilé",
"Repeater ID:": "ID opakovače",
"WebSocket": "WebSocket",
"Encrypt": "Šifrování:",
"Host:": "Hostitel:",
"Port:": "Port:",
"Path:": "Cesta",
"Automatic Reconnect": "Automatická obnova připojení",
"Reconnect Delay (ms):": "Zpoždění připojení (ms)",
"Show Dot when No Cursor": "Tečka místo chybějícího kurzoru myši",
"Logging:": "Logování:",
"Disconnect": "Odpojit",
"Connect": "Připojit",
"Password:": "Heslo",
"Send Password": "Odeslat heslo",
"Cancel": "Zrušit"
}

View File

@ -0,0 +1,69 @@
{
"Connecting...": "Verbinden...",
"Disconnecting...": "Verbindung trennen...",
"Reconnecting...": "Verbindung wiederherstellen...",
"Internal error": "Interner Fehler",
"Must set host": "Richten Sie den Server ein",
"Connected (encrypted) to ": "Verbunden mit (verschlüsselt) ",
"Connected (unencrypted) to ": "Verbunden mit (unverschlüsselt) ",
"Something went wrong, connection is closed": "Etwas lief schief, Verbindung wurde getrennt",
"Disconnected": "Verbindung zum Server getrennt",
"New connection has been rejected with reason: ": "Verbindung wurde aus folgendem Grund abgelehnt: ",
"New connection has been rejected": "Verbindung wurde abgelehnt",
"Password is required": "Passwort ist erforderlich",
"noVNC encountered an error:": "Ein Fehler ist aufgetreten:",
"Hide/Show the control bar": "Kontrollleiste verstecken/anzeigen",
"Move/Drag Viewport": "Ansichtsfenster verschieben/ziehen",
"viewport drag": "Ansichtsfenster ziehen",
"Active Mouse Button": "Aktive Maustaste",
"No mousebutton": "Keine Maustaste",
"Left mousebutton": "Linke Maustaste",
"Middle mousebutton": "Mittlere Maustaste",
"Right mousebutton": "Rechte Maustaste",
"Keyboard": "Tastatur",
"Show Keyboard": "Tastatur anzeigen",
"Extra keys": "Zusatztasten",
"Show Extra Keys": "Zusatztasten anzeigen",
"Ctrl": "Strg",
"Toggle Ctrl": "Strg umschalten",
"Alt": "Alt",
"Toggle Alt": "Alt umschalten",
"Send Tab": "Tab senden",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Escape senden",
"Ctrl+Alt+Del": "Strg+Alt+Entf",
"Send Ctrl-Alt-Del": "Strg+Alt+Entf senden",
"Shutdown/Reboot": "Herunterfahren/Neustarten",
"Shutdown/Reboot...": "Herunterfahren/Neustarten...",
"Power": "Energie",
"Shutdown": "Herunterfahren",
"Reboot": "Neustarten",
"Reset": "Zurücksetzen",
"Clipboard": "Zwischenablage",
"Clear": "Löschen",
"Fullscreen": "Vollbild",
"Settings": "Einstellungen",
"Shared Mode": "Geteilter Modus",
"View Only": "Nur betrachten",
"Clip to Window": "Auf Fenster begrenzen",
"Scaling Mode:": "Skalierungsmodus:",
"None": "Keiner",
"Local Scaling": "Lokales skalieren",
"Remote Resizing": "Serverseitiges skalieren",
"Advanced": "Erweitert",
"Repeater ID:": "Repeater ID:",
"WebSocket": "WebSocket",
"Encrypt": "Verschlüsselt",
"Host:": "Server:",
"Port:": "Port:",
"Path:": "Pfad:",
"Automatic Reconnect": "Automatisch wiederverbinden",
"Reconnect Delay (ms):": "Wiederverbindungsverzögerung (ms):",
"Logging:": "Protokollierung:",
"Disconnect": "Verbindung trennen",
"Connect": "Verbinden",
"Password:": "Passwort:",
"Cancel": "Abbrechen",
"Canvas not supported.": "Canvas nicht unterstützt."
}

View File

@ -0,0 +1,69 @@
{
"Connecting...": "Συνδέεται...",
"Disconnecting...": "Aποσυνδέεται...",
"Reconnecting...": "Επανασυνδέεται...",
"Internal error": "Εσωτερικό σφάλμα",
"Must set host": "Πρέπει να οριστεί ο διακομιστής",
"Connected (encrypted) to ": "Συνδέθηκε (κρυπτογραφημένα) με το ",
"Connected (unencrypted) to ": "Συνδέθηκε (μη κρυπτογραφημένα) με το ",
"Something went wrong, connection is closed": "Κάτι πήγε στραβά, η σύνδεση διακόπηκε",
"Disconnected": "Αποσυνδέθηκε",
"New connection has been rejected with reason: ": "Η νέα σύνδεση απορρίφθηκε διότι: ",
"New connection has been rejected": "Η νέα σύνδεση απορρίφθηκε ",
"Password is required": "Απαιτείται ο κωδικός πρόσβασης",
"noVNC encountered an error:": "το noVNC αντιμετώπισε ένα σφάλμα:",
"Hide/Show the control bar": "Απόκρυψη/Εμφάνιση γραμμής ελέγχου",
"Move/Drag Viewport": "Μετακίνηση/Σύρσιμο Θεατού πεδίου",
"viewport drag": "σύρσιμο θεατού πεδίου",
"Active Mouse Button": "Ενεργό Πλήκτρο Ποντικιού",
"No mousebutton": "Χωρίς Πλήκτρο Ποντικιού",
"Left mousebutton": "Αριστερό Πλήκτρο Ποντικιού",
"Middle mousebutton": "Μεσαίο Πλήκτρο Ποντικιού",
"Right mousebutton": "Δεξί Πλήκτρο Ποντικιού",
"Keyboard": "Πληκτρολόγιο",
"Show Keyboard": "Εμφάνιση Πληκτρολογίου",
"Extra keys": "Επιπλέον πλήκτρα",
"Show Extra Keys": "Εμφάνιση Επιπλέον Πλήκτρων",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Εναλλαγή Ctrl",
"Alt": "Alt",
"Toggle Alt": "Εναλλαγή Alt",
"Send Tab": "Αποστολή Tab",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Αποστολή Escape",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Αποστολή Ctrl-Alt-Del",
"Shutdown/Reboot": "Κλείσιμο/Επανεκκίνηση",
"Shutdown/Reboot...": "Κλείσιμο/Επανεκκίνηση...",
"Power": "Απενεργοποίηση",
"Shutdown": "Κλείσιμο",
"Reboot": "Επανεκκίνηση",
"Reset": "Επαναφορά",
"Clipboard": "Πρόχειρο",
"Clear": "Καθάρισμα",
"Fullscreen": "Πλήρης Οθόνη",
"Settings": "Ρυθμίσεις",
"Shared Mode": "Κοινόχρηστη Λειτουργία",
"View Only": "Μόνο Θέαση",
"Clip to Window": "Αποκοπή στο όριο του Παράθυρου",
"Scaling Mode:": "Λειτουργία Κλιμάκωσης:",
"None": "Καμία",
"Local Scaling": "Τοπική Κλιμάκωση",
"Remote Resizing": "Απομακρυσμένη Αλλαγή μεγέθους",
"Advanced": "Για προχωρημένους",
"Repeater ID:": "Repeater ID:",
"WebSocket": "WebSocket",
"Encrypt": "Κρυπτογράφηση",
"Host:": "Όνομα διακομιστή:",
"Port:": "Πόρτα διακομιστή:",
"Path:": "Διαδρομή:",
"Automatic Reconnect": "Αυτόματη επανασύνδεση",
"Reconnect Delay (ms):": "Καθυστέρηση επανασύνδεσης (ms):",
"Logging:": "Καταγραφή:",
"Disconnect": "Αποσύνδεση",
"Connect": "Σύνδεση",
"Password:": "Κωδικός Πρόσβασης:",
"Cancel": "Ακύρωση",
"Canvas not supported.": "Δεν υποστηρίζεται το στοιχείο Canvas"
}

View File

@ -0,0 +1,68 @@
{
"Connecting...": "Conectando...",
"Connected (encrypted) to ": "Conectado (con encriptación) a",
"Connected (unencrypted) to ": "Conectado (sin encriptación) a",
"Disconnecting...": "Desconectando...",
"Disconnected": "Desconectado",
"Must set host": "Se debe configurar el host",
"Reconnecting...": "Reconectando...",
"Password is required": "La contraseña es obligatoria",
"Disconnect timeout": "Tiempo de desconexión agotado",
"noVNC encountered an error:": "noVNC ha encontrado un error:",
"Hide/Show the control bar": "Ocultar/Mostrar la barra de control",
"Move/Drag Viewport": "Mover/Arrastrar la ventana",
"viewport drag": "Arrastrar la ventana",
"Active Mouse Button": "Botón activo del ratón",
"No mousebutton": "Ningún botón del ratón",
"Left mousebutton": "Botón izquierdo del ratón",
"Middle mousebutton": "Botón central del ratón",
"Right mousebutton": "Botón derecho del ratón",
"Keyboard": "Teclado",
"Show Keyboard": "Mostrar teclado",
"Extra keys": "Teclas adicionales",
"Show Extra Keys": "Mostrar Teclas Adicionales",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Pulsar/Soltar Ctrl",
"Alt": "Alt",
"Toggle Alt": "Pulsar/Soltar Alt",
"Send Tab": "Enviar Tabulación",
"Tab": "Tabulación",
"Esc": "Esc",
"Send Escape": "Enviar Escape",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Enviar Ctrl+Alt+Del",
"Shutdown/Reboot": "Apagar/Reiniciar",
"Shutdown/Reboot...": "Apagar/Reiniciar...",
"Power": "Encender",
"Shutdown": "Apagar",
"Reboot": "Reiniciar",
"Reset": "Restablecer",
"Clipboard": "Portapapeles",
"Clear": "Vaciar",
"Fullscreen": "Pantalla Completa",
"Settings": "Configuraciones",
"Encrypt": "Encriptar",
"Shared Mode": "Modo Compartido",
"View Only": "Solo visualización",
"Clip to Window": "Recortar al tamaño de la ventana",
"Scaling Mode:": "Modo de escalado:",
"None": "Ninguno",
"Local Scaling": "Escalado Local",
"Local Downscaling": "Reducción de escala local",
"Remote Resizing": "Cambio de tamaño remoto",
"Advanced": "Avanzado",
"Local Cursor": "Cursor Local",
"Repeater ID:": "ID del Repetidor:",
"WebSocket": "WebSocket",
"Host:": "Host:",
"Port:": "Puerto:",
"Path:": "Ruta:",
"Automatic Reconnect": "Reconexión automática",
"Reconnect Delay (ms):": "Retraso en la reconexión (ms):",
"Logging:": "Registrando:",
"Disconnect": "Desconectar",
"Connect": "Conectar",
"Password:": "Contraseña:",
"Cancel": "Cancelar",
"Canvas not supported.": "Canvas no soportado."
}

View File

@ -0,0 +1,72 @@
{
"Connecting...": "En cours de connexion...",
"Disconnecting...": "Déconnexion en cours...",
"Reconnecting...": "Reconnexion en cours...",
"Internal error": "Erreur interne",
"Must set host": "Doit définir l'hôte",
"Connected (encrypted) to ": "Connecté (crypté) à ",
"Connected (unencrypted) to ": "Connecté (non crypté) à ",
"Something went wrong, connection is closed": "Quelque chose est arrivé, la connexion est fermée",
"Failed to connect to server": "Échec de connexion au serveur",
"Disconnected": "Déconnecté",
"New connection has been rejected with reason: ": "Une nouvelle connexion a été rejetée avec raison: ",
"New connection has been rejected": "Une nouvelle connexion a été rejetée",
"Credentials are required": "Les identifiants sont requis",
"noVNC encountered an error:": "noVNC a rencontré une erreur:",
"Hide/Show the control bar": "Masquer/Afficher la barre de contrôle",
"Drag": "Faire glisser",
"Move/Drag Viewport": "Déplacer/faire glisser Viewport",
"Keyboard": "Clavier",
"Show Keyboard": "Afficher le clavier",
"Extra keys": "Touches supplémentaires",
"Show Extra Keys": "Afficher les touches supplémentaires",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Basculer Ctrl",
"Alt": "Alt",
"Toggle Alt": "Basculer Alt",
"Toggle Windows": "Basculer Windows",
"Windows": "Windows",
"Send Tab": "Envoyer l'onglet",
"Tab": "l'onglet",
"Esc": "Esc",
"Send Escape": "Envoyer Escape",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Envoyer Ctrl-Alt-Del",
"Shutdown/Reboot": "Arrêter/Redémarrer",
"Shutdown/Reboot...": "Arrêter/Redémarrer...",
"Power": "Alimentation",
"Shutdown": "Arrêter",
"Reboot": "Redémarrer",
"Reset": "Réinitialiser",
"Clipboard": "Presse-papiers",
"Clear": "Effacer",
"Fullscreen": "Plein écran",
"Settings": "Paramètres",
"Shared Mode": "Mode partagé",
"View Only": "Afficher uniquement",
"Clip to Window": "Clip à fenêtre",
"Scaling Mode:": "Mode mise à l'échelle:",
"None": "Aucun",
"Local Scaling": "Mise à l'échelle locale",
"Remote Resizing": "Redimensionnement à distance",
"Advanced": "Avancé",
"Quality:": "Qualité:",
"Compression level:": "Niveau de compression:",
"Repeater ID:": "ID Répéteur:",
"WebSocket": "WebSocket",
"Encrypt": "Crypter",
"Host:": "Hôte:",
"Port:": "Port:",
"Path:": "Chemin:",
"Automatic Reconnect": "Reconnecter automatiquemen",
"Reconnect Delay (ms):": "Délai de reconnexion (ms):",
"Show Dot when No Cursor": "Afficher le point lorsqu'il n'y a pas de curseur",
"Logging:": "Se connecter:",
"Version:": "Version:",
"Disconnect": "Déconnecter",
"Connect": "Connecter",
"Username:": "Nom d'utilisateur:",
"Password:": "Mot de passe:",
"Send Credentials": "Envoyer les identifiants",
"Cancel": "Annuler"
}

View File

@ -0,0 +1,72 @@
{
"Connecting...": "接続しています...",
"Disconnecting...": "切断しています...",
"Reconnecting...": "再接続しています...",
"Internal error": "内部エラー",
"Must set host": "ホストを設定する必要があります",
"Connected (encrypted) to ": "接続しました (暗号化済み): ",
"Connected (unencrypted) to ": "接続しました (暗号化されていません): ",
"Something went wrong, connection is closed": "何らかの問題で、接続が閉じられました",
"Failed to connect to server": "サーバーへの接続に失敗しました",
"Disconnected": "切断しました",
"New connection has been rejected with reason: ": "新規接続は次の理由で拒否されました: ",
"New connection has been rejected": "新規接続は拒否されました",
"Credentials are required": "資格情報が必要です",
"noVNC encountered an error:": "noVNC でエラーが発生しました:",
"Hide/Show the control bar": "コントロールバーを隠す/表示する",
"Drag": "ドラッグ",
"Move/Drag Viewport": "ビューポートを移動/ドラッグ",
"Keyboard": "キーボード",
"Show Keyboard": "キーボードを表示",
"Extra keys": "追加キー",
"Show Extra Keys": "追加キーを表示",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Ctrl キーを切り替え",
"Alt": "Alt",
"Toggle Alt": "Alt キーを切り替え",
"Toggle Windows": "Windows キーを切り替え",
"Windows": "Windows",
"Send Tab": "Tab キーを送信",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Escape キーを送信",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Ctrl-Alt-Del を送信",
"Shutdown/Reboot": "シャットダウン/再起動",
"Shutdown/Reboot...": "シャットダウン/再起動...",
"Power": "電源",
"Shutdown": "シャットダウン",
"Reboot": "再起動",
"Reset": "リセット",
"Clipboard": "クリップボード",
"Clear": "クリア",
"Fullscreen": "全画面表示",
"Settings": "設定",
"Shared Mode": "共有モード",
"View Only": "表示のみ",
"Clip to Window": "ウィンドウにクリップ",
"Scaling Mode:": "スケーリングモード:",
"None": "なし",
"Local Scaling": "ローカルスケーリング",
"Remote Resizing": "リモートでリサイズ",
"Advanced": "高度",
"Quality:": "品質:",
"Compression level:": "圧縮レベル:",
"Repeater ID:": "リピーター ID:",
"WebSocket": "WebSocket",
"Encrypt": "暗号化",
"Host:": "ホスト:",
"Port:": "ポート:",
"Path:": "パス:",
"Automatic Reconnect": "自動再接続",
"Reconnect Delay (ms):": "再接続する遅延 (ミリ秒):",
"Show Dot when No Cursor": "カーソルがないときにドットを表示",
"Logging:": "ロギング:",
"Version:": "バージョン:",
"Disconnect": "切断",
"Connect": "接続",
"Username:": "ユーザー名:",
"Password:": "パスワード:",
"Send Credentials": "資格情報を送信",
"Cancel": "キャンセル"
}

View File

@ -0,0 +1,70 @@
{
"Connecting...": "연결중...",
"Disconnecting...": "연결 해제중...",
"Reconnecting...": "재연결중...",
"Internal error": "내부 오류",
"Must set host": "호스트는 설정되어야 합니다.",
"Connected (encrypted) to ": "다음과 (암호화되어) 연결되었습니다:",
"Connected (unencrypted) to ": "다음과 (암호화 없이) 연결되었습니다:",
"Something went wrong, connection is closed": "무언가 잘못되었습니다, 연결이 닫혔습니다.",
"Failed to connect to server": "서버에 연결하지 못했습니다.",
"Disconnected": "연결이 해제되었습니다.",
"New connection has been rejected with reason: ": "새 연결이 다음 이유로 거부되었습니다:",
"New connection has been rejected": "새 연결이 거부되었습니다.",
"Password is required": "비밀번호가 필요합니다.",
"noVNC encountered an error:": "noVNC에 오류가 발생했습니다:",
"Hide/Show the control bar": "컨트롤 바 숨기기/보이기",
"Move/Drag Viewport": "움직이기/드래그 뷰포트",
"viewport drag": "뷰포트 드래그",
"Active Mouse Button": "마우스 버튼 활성화",
"No mousebutton": "마우스 버튼 없음",
"Left mousebutton": "왼쪽 마우스 버튼",
"Middle mousebutton": "중간 마우스 버튼",
"Right mousebutton": "오른쪽 마우스 버튼",
"Keyboard": "키보드",
"Show Keyboard": "키보드 보이기",
"Extra keys": "기타 키들",
"Show Extra Keys": "기타 키들 보이기",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Ctrl 켜기/끄기",
"Alt": "Alt",
"Toggle Alt": "Alt 켜기/끄기",
"Send Tab": "Tab 보내기",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Esc 보내기",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Ctrl+Alt+Del 보내기",
"Shutdown/Reboot": "셧다운/리붓",
"Shutdown/Reboot...": "셧다운/리붓...",
"Power": "전원",
"Shutdown": "셧다운",
"Reboot": "리붓",
"Reset": "리셋",
"Clipboard": "클립보드",
"Clear": "지우기",
"Fullscreen": "전체화면",
"Settings": "설정",
"Shared Mode": "공유 모드",
"View Only": "보기 전용",
"Clip to Window": "창에 클립",
"Scaling Mode:": "스케일링 모드:",
"None": "없음",
"Local Scaling": "로컬 스케일링",
"Remote Resizing": "원격 크기 조절",
"Advanced": "고급",
"Repeater ID:": "중계 ID",
"WebSocket": "웹소켓",
"Encrypt": "암호화",
"Host:": "호스트:",
"Port:": "포트:",
"Path:": "위치:",
"Automatic Reconnect": "자동 재연결",
"Reconnect Delay (ms):": "재연결 지연 시간 (ms)",
"Logging:": "로깅",
"Disconnect": "연결 해제",
"Connect": "연결",
"Password:": "비밀번호:",
"Send Password": "비밀번호 전송",
"Cancel": "취소"
}

View File

@ -0,0 +1,73 @@
{
"Connecting...": "Verbinden...",
"Disconnecting...": "Verbinding verbreken...",
"Reconnecting...": "Opnieuw verbinding maken...",
"Internal error": "Interne fout",
"Must set host": "Host moeten worden ingesteld",
"Connected (encrypted) to ": "Verbonden (versleuteld) met ",
"Connected (unencrypted) to ": "Verbonden (onversleuteld) met ",
"Something went wrong, connection is closed": "Er iets fout gelopen, verbinding werd verbroken",
"Failed to connect to server": "Verbinding maken met server is mislukt",
"Disconnected": "Verbinding verbroken",
"New connection has been rejected with reason: ": "Nieuwe verbinding is geweigerd omwille van de volgende reden: ",
"New connection has been rejected": "Nieuwe verbinding is geweigerd",
"Password is required": "Wachtwoord is vereist",
"noVNC encountered an error:": "noVNC heeft een fout bemerkt:",
"Hide/Show the control bar": "Verberg/Toon de bedieningsbalk",
"Move/Drag Viewport": "Verplaats/Versleep Kijkvenster",
"viewport drag": "kijkvenster slepen",
"Active Mouse Button": "Actieve Muisknop",
"No mousebutton": "Geen muisknop",
"Left mousebutton": "Linker muisknop",
"Middle mousebutton": "Middelste muisknop",
"Right mousebutton": "Rechter muisknop",
"Keyboard": "Toetsenbord",
"Show Keyboard": "Toon Toetsenbord",
"Extra keys": "Extra toetsen",
"Show Extra Keys": "Toon Extra Toetsen",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Ctrl omschakelen",
"Alt": "Alt",
"Toggle Alt": "Alt omschakelen",
"Toggle Windows": "Windows omschakelen",
"Windows": "Windows",
"Send Tab": "Tab Sturen",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Escape Sturen",
"Ctrl+Alt+Del": "Ctrl-Alt-Del",
"Send Ctrl-Alt-Del": "Ctrl-Alt-Del Sturen",
"Shutdown/Reboot": "Uitschakelen/Herstarten",
"Shutdown/Reboot...": "Uitschakelen/Herstarten...",
"Power": "Systeem",
"Shutdown": "Uitschakelen",
"Reboot": "Herstarten",
"Reset": "Resetten",
"Clipboard": "Klembord",
"Clear": "Wissen",
"Fullscreen": "Volledig Scherm",
"Settings": "Instellingen",
"Shared Mode": "Gedeelde Modus",
"View Only": "Alleen Kijken",
"Clip to Window": "Randen buiten venster afsnijden",
"Scaling Mode:": "Schaalmodus:",
"None": "Geen",
"Local Scaling": "Lokaal Schalen",
"Remote Resizing": "Op Afstand Formaat Wijzigen",
"Advanced": "Geavanceerd",
"Repeater ID:": "Repeater ID:",
"WebSocket": "WebSocket",
"Encrypt": "Versleutelen",
"Host:": "Host:",
"Port:": "Poort:",
"Path:": "Pad:",
"Automatic Reconnect": "Automatisch Opnieuw Verbinden",
"Reconnect Delay (ms):": "Vertraging voor Opnieuw Verbinden (ms):",
"Show Dot when No Cursor": "Geef stip weer indien geen cursor",
"Logging:": "Logmeldingen:",
"Disconnect": "Verbinding verbreken",
"Connect": "Verbinden",
"Password:": "Wachtwoord:",
"Send Password": "Verzend Wachtwoord:",
"Cancel": "Annuleren"
}

View File

@ -0,0 +1,69 @@
{
"Connecting...": "Łączenie...",
"Disconnecting...": "Rozłączanie...",
"Reconnecting...": "Łączenie...",
"Internal error": "Błąd wewnętrzny",
"Must set host": "Host i port są wymagane",
"Connected (encrypted) to ": "Połączenie (szyfrowane) z ",
"Connected (unencrypted) to ": "Połączenie (nieszyfrowane) z ",
"Something went wrong, connection is closed": "Coś poszło źle, połączenie zostało zamknięte",
"Disconnected": "Rozłączony",
"New connection has been rejected with reason: ": "Nowe połączenie zostało odrzucone z powodu: ",
"New connection has been rejected": "Nowe połączenie zostało odrzucone",
"Password is required": "Hasło jest wymagane",
"noVNC encountered an error:": "noVNC napotkało błąd:",
"Hide/Show the control bar": "Pokaż/Ukryj pasek ustawień",
"Move/Drag Viewport": "Ruszaj/Przeciągaj Viewport",
"viewport drag": "przeciągnij viewport",
"Active Mouse Button": "Aktywny Przycisk Myszy",
"No mousebutton": "Brak przycisku myszy",
"Left mousebutton": "Lewy przycisk myszy",
"Middle mousebutton": "Środkowy przycisk myszy",
"Right mousebutton": "Prawy przycisk myszy",
"Keyboard": "Klawiatura",
"Show Keyboard": "Pokaż klawiaturę",
"Extra keys": "Przyciski dodatkowe",
"Show Extra Keys": "Pokaż przyciski dodatkowe",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Przełącz Ctrl",
"Alt": "Alt",
"Toggle Alt": "Przełącz Alt",
"Send Tab": "Wyślij Tab",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Wyślij Escape",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Wyślij Ctrl-Alt-Del",
"Shutdown/Reboot": "Wyłącz/Uruchom ponownie",
"Shutdown/Reboot...": "Wyłącz/Uruchom ponownie...",
"Power": "Włączony",
"Shutdown": "Wyłącz",
"Reboot": "Uruchom ponownie",
"Reset": "Resetuj",
"Clipboard": "Schowek",
"Clear": "Wyczyść",
"Fullscreen": "Pełny ekran",
"Settings": "Ustawienia",
"Shared Mode": "Tryb Współdzielenia",
"View Only": "Tylko Podgląd",
"Clip to Window": "Przytnij do Okna",
"Scaling Mode:": "Tryb Skalowania:",
"None": "Brak",
"Local Scaling": "Skalowanie lokalne",
"Remote Resizing": "Skalowanie zdalne",
"Advanced": "Zaawansowane",
"Repeater ID:": "ID Repeatera:",
"WebSocket": "WebSocket",
"Encrypt": "Szyfrowanie",
"Host:": "Host:",
"Port:": "Port:",
"Path:": "Ścieżka:",
"Automatic Reconnect": "Automatycznie wznawiaj połączenie",
"Reconnect Delay (ms):": "Opóźnienie wznawiania (ms):",
"Logging:": "Poziom logowania:",
"Disconnect": "Rozłącz",
"Connect": "Połącz",
"Password:": "Hasło:",
"Cancel": "Anuluj",
"Canvas not supported.": "Element Canvas nie jest wspierany."
}

View File

@ -0,0 +1,72 @@
{
"Connecting...": "Conectando...",
"Disconnecting...": "Desconectando...",
"Reconnecting...": "Reconectando...",
"Internal error": "Erro interno",
"Must set host": "É necessário definir o host",
"Connected (encrypted) to ": "Conectado (com criptografia) a ",
"Connected (unencrypted) to ": "Conectado (sem criptografia) a ",
"Something went wrong, connection is closed": "Algo deu errado. A conexão foi encerrada.",
"Failed to connect to server": "Falha ao conectar-se ao servidor",
"Disconnected": "Desconectado",
"New connection has been rejected with reason: ": "A nova conexão foi rejeitada pelo motivo: ",
"New connection has been rejected": "A nova conexão foi rejeitada",
"Credentials are required": "Credenciais são obrigatórias",
"noVNC encountered an error:": "O noVNC encontrou um erro:",
"Hide/Show the control bar": "Esconder/mostrar a barra de controles",
"Drag": "Arrastar",
"Move/Drag Viewport": "Mover/arrastar a janela",
"Keyboard": "Teclado",
"Show Keyboard": "Mostrar teclado",
"Extra keys": "Teclas adicionais",
"Show Extra Keys": "Mostar teclas adicionais",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Pressionar/soltar Ctrl",
"Alt": "Alt",
"Toggle Alt": "Pressionar/soltar Alt",
"Toggle Windows": "Pressionar/soltar Windows",
"Windows": "Windows",
"Send Tab": "Enviar Tab",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Enviar Esc",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Enviar Ctrl-Alt-Del",
"Shutdown/Reboot": "Desligar/reiniciar",
"Shutdown/Reboot...": "Desligar/reiniciar...",
"Power": "Ligar",
"Shutdown": "Desligar",
"Reboot": "Reiniciar",
"Reset": "Reiniciar (forçado)",
"Clipboard": "Área de transferência",
"Clear": "Limpar",
"Fullscreen": "Tela cheia",
"Settings": "Configurações",
"Shared Mode": "Modo compartilhado",
"View Only": "Apenas visualizar",
"Clip to Window": "Recortar à janela",
"Scaling Mode:": "Modo de dimensionamento:",
"None": "Nenhum",
"Local Scaling": "Local",
"Remote Resizing": "Remoto",
"Advanced": "Avançado",
"Quality:": "Qualidade:",
"Compression level:": "Nível de compressão:",
"Repeater ID:": "ID do repetidor:",
"WebSocket": "WebSocket",
"Encrypt": "Criptografar",
"Host:": "Host:",
"Port:": "Porta:",
"Path:": "Caminho:",
"Automatic Reconnect": "Reconexão automática",
"Reconnect Delay (ms):": "Atraso da reconexão (ms)",
"Show Dot when No Cursor": "Mostrar ponto quando não há cursor",
"Logging:": "Registros:",
"Version:": "Versão:",
"Disconnect": "Desconectar",
"Connect": "Conectar",
"Username:": "Nome de usuário:",
"Password:": "Senha:",
"Send Credentials": "Enviar credenciais",
"Cancel": "Cancelar"
}

View File

@ -0,0 +1,72 @@
{
"Connecting...": "Подключение...",
"Disconnecting...": "Отключение...",
"Reconnecting...": "Переподключение...",
"Internal error": "Внутренняя ошибка",
"Must set host": "Задайте имя сервера или IP",
"Connected (encrypted) to ": "Подключено (с шифрованием) к ",
"Connected (unencrypted) to ": "Подключено (без шифрования) к ",
"Something went wrong, connection is closed": "Что-то пошло не так, подключение разорвано",
"Failed to connect to server": "Ошибка подключения к серверу",
"Disconnected": "Отключено",
"New connection has been rejected with reason: ": "Новое соединение отклонено по причине: ",
"New connection has been rejected": "Новое соединение отклонено",
"Credentials are required": "Требуются учетные данные",
"noVNC encountered an error:": "Ошибка noVNC: ",
"Hide/Show the control bar": "Скрыть/Показать контрольную панель",
"Drag": "Переместить",
"Move/Drag Viewport": "Переместить окно",
"Keyboard": "Клавиатура",
"Show Keyboard": "Показать клавиатуру",
"Extra keys": "Дополнительные Кнопки",
"Show Extra Keys": "Показать Дополнительные Кнопки",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Переключение нажатия Ctrl",
"Alt": "Alt",
"Toggle Alt": "Переключение нажатия Alt",
"Toggle Windows": "Переключение вкладок",
"Windows": "Вкладка",
"Send Tab": "Передать нажатие Tab",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Передать нажатие Escape",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Передать нажатие Ctrl-Alt-Del",
"Shutdown/Reboot": "Выключить/Перезагрузить",
"Shutdown/Reboot...": "Выключить/Перезагрузить...",
"Power": "Питание",
"Shutdown": "Выключить",
"Reboot": "Перезагрузить",
"Reset": "Сброс",
"Clipboard": "Буфер обмена",
"Clear": "Очистить",
"Fullscreen": "Во весь экран",
"Settings": "Настройки",
"Shared Mode": "Общий режим",
"View Only": "Только Просмотр",
"Clip to Window": "В окно",
"Scaling Mode:": "Масштаб:",
"None": "Нет",
"Local Scaling": "Локльный масштаб",
"Remote Resizing": "Удаленная перенастройка размера",
"Advanced": "Дополнительно",
"Quality:": "Качество",
"Compression level:": "Уровень Сжатия",
"Repeater ID:": "Идентификатор ID:",
"WebSocket": "WebSocket",
"Encrypt": "Шифрование",
"Host:": "Сервер:",
"Port:": "Порт:",
"Path:": "Путь:",
"Automatic Reconnect": "Автоматическое переподключение",
"Reconnect Delay (ms):": "Задержка переподключения (мс):",
"Show Dot when No Cursor": "Показать точку вместо курсора",
"Logging:": "Лог:",
"Version:": "Версия",
"Disconnect": "Отключение",
"Connect": "Подключение",
"Username:": "Имя Пользователя",
"Password:": "Пароль:",
"Send Credentials": "Передача Учетных Данных",
"Cancel": "Выход"
}

View File

@ -0,0 +1,72 @@
{
"Connecting...": "Ansluter...",
"Disconnecting...": "Kopplar ner...",
"Reconnecting...": "Återansluter...",
"Internal error": "Internt fel",
"Must set host": "Du måste specifiera en värd",
"Connected (encrypted) to ": "Ansluten (krypterat) till ",
"Connected (unencrypted) to ": "Ansluten (okrypterat) till ",
"Something went wrong, connection is closed": "Något gick fel, anslutningen avslutades",
"Failed to connect to server": "Misslyckades att ansluta till servern",
"Disconnected": "Frånkopplad",
"New connection has been rejected with reason: ": "Ny anslutning har blivit nekad med följande skäl: ",
"New connection has been rejected": "Ny anslutning har blivit nekad",
"Credentials are required": "Användaruppgifter krävs",
"noVNC encountered an error:": "noVNC stötte på ett problem:",
"Hide/Show the control bar": "Göm/Visa kontrollbaren",
"Drag": "Dra",
"Move/Drag Viewport": "Flytta/Dra Vyn",
"Keyboard": "Tangentbord",
"Show Keyboard": "Visa Tangentbord",
"Extra keys": "Extraknappar",
"Show Extra Keys": "Visa Extraknappar",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Växla Ctrl",
"Alt": "Alt",
"Toggle Alt": "Växla Alt",
"Toggle Windows": "Växla Windows",
"Windows": "Windows",
"Send Tab": "Skicka Tab",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "Skicka Escape",
"Ctrl+Alt+Del": "Ctrl+Alt+Del",
"Send Ctrl-Alt-Del": "Skicka Ctrl-Alt-Del",
"Shutdown/Reboot": "Stäng av/Boota om",
"Shutdown/Reboot...": "Stäng av/Boota om...",
"Power": "Ström",
"Shutdown": "Stäng av",
"Reboot": "Boota om",
"Reset": "Återställ",
"Clipboard": "Urklipp",
"Clear": "Rensa",
"Fullscreen": "Fullskärm",
"Settings": "Inställningar",
"Shared Mode": "Delat Läge",
"View Only": "Endast Visning",
"Clip to Window": "Begränsa till Fönster",
"Scaling Mode:": "Skalningsläge:",
"None": "Ingen",
"Local Scaling": "Lokal Skalning",
"Remote Resizing": "Ändra Storlek",
"Advanced": "Avancerat",
"Quality:": "Kvalitet:",
"Compression level:": "Kompressionsnivå:",
"Repeater ID:": "Repeater-ID:",
"WebSocket": "WebSocket",
"Encrypt": "Kryptera",
"Host:": "Värd:",
"Port:": "Port:",
"Path:": "Sökväg:",
"Automatic Reconnect": "Automatisk Återanslutning",
"Reconnect Delay (ms):": "Fördröjning (ms):",
"Show Dot when No Cursor": "Visa prick när ingen muspekare finns",
"Logging:": "Loggning:",
"Version:": "Version:",
"Disconnect": "Koppla från",
"Connect": "Anslut",
"Username:": "Användarnamn:",
"Password:": "Lösenord:",
"Send Credentials": "Skicka Användaruppgifter",
"Cancel": "Avbryt"
}

View File

@ -0,0 +1,69 @@
{
"Connecting...": "Bağlanıyor...",
"Disconnecting...": "Bağlantı kesiliyor...",
"Reconnecting...": "Yeniden bağlantı kuruluyor...",
"Internal error": "İç hata",
"Must set host": "Sunucuyu kur",
"Connected (encrypted) to ": "Bağlı (şifrelenmiş)",
"Connected (unencrypted) to ": "Bağlandı (şifrelenmemiş)",
"Something went wrong, connection is closed": "Bir şeyler ters gitti, bağlantı kesildi",
"Disconnected": "Bağlantı kesildi",
"New connection has been rejected with reason: ": "Bağlantı aşağıdaki nedenlerden dolayı reddedildi: ",
"New connection has been rejected": "Bağlantı reddedildi",
"Password is required": "Şifre gerekli",
"noVNC encountered an error:": "Bir hata oluştu:",
"Hide/Show the control bar": "Denetim masasını Gizle/Göster",
"Move/Drag Viewport": "Görünümü Taşı/Sürükle",
"viewport drag": "Görüntü penceresini sürükle",
"Active Mouse Button": "Aktif Fare Düğmesi",
"No mousebutton": "Fare düğmesi yok",
"Left mousebutton": "Farenin sol düğmesi",
"Middle mousebutton": "Farenin orta düğmesi",
"Right mousebutton": "Farenin sağ düğmesi",
"Keyboard": "Klavye",
"Show Keyboard": "Klavye Düzenini Göster",
"Extra keys": "Ekstra tuşlar",
"Show Extra Keys": "Ekstra tuşları göster",
"Ctrl": "Ctrl",
"Toggle Ctrl": "Ctrl Değiştir ",
"Alt": "Alt",
"Toggle Alt": "Alt Değiştir",
"Send Tab": "Sekme Gönder",
"Tab": "Sekme",
"Esc": "Esc",
"Send Escape": "Boşluk Gönder",
"Ctrl+Alt+Del": "Ctrl + Alt + Del",
"Send Ctrl-Alt-Del": "Ctrl-Alt-Del Gönder",
"Shutdown/Reboot": "Kapat/Yeniden Başlat",
"Shutdown/Reboot...": "Kapat/Yeniden Başlat...",
"Power": "Güç",
"Shutdown": "Kapat",
"Reboot": "Yeniden Başlat",
"Reset": "Sıfırla",
"Clipboard": "Pano",
"Clear": "Temizle",
"Fullscreen": "Tam Ekran",
"Settings": "Ayarlar",
"Shared Mode": "Paylaşım Modu",
"View Only": "Sadece Görüntüle",
"Clip to Window": "Pencereye Tıkla",
"Scaling Mode:": "Ölçekleme Modu:",
"None": "Bilinmeyen",
"Local Scaling": "Yerel Ölçeklendirme",
"Remote Resizing": "Uzaktan Yeniden Boyutlandırma",
"Advanced": "Gelişmiş",
"Repeater ID:": "Tekralayıcı ID:",
"WebSocket": "WebSocket",
"Encrypt": "Şifrele",
"Host:": "Ana makine:",
"Port:": "Port:",
"Path:": "Yol:",
"Automatic Reconnect": "Otomatik Yeniden Bağlan",
"Reconnect Delay (ms):": "Yeniden Bağlanma Süreci (ms):",
"Logging:": "Giriş yapılıyor:",
"Disconnect": "Bağlantıyı Kes",
"Connect": "Bağlan",
"Password:": "Parola:",
"Cancel": "Vazgeç",
"Canvas not supported.": "Tuval desteklenmiyor."
}

View File

@ -0,0 +1,69 @@
{
"Connecting...": "连接中...",
"Disconnecting...": "正在断开连接...",
"Reconnecting...": "重新连接中...",
"Internal error": "内部错误",
"Must set host": "请提供主机名",
"Connected (encrypted) to ": "已连接到(加密)",
"Connected (unencrypted) to ": "已连接到(未加密)",
"Something went wrong, connection is closed": "发生错误,连接已关闭",
"Failed to connect to server": "无法连接到服务器",
"Disconnected": "已断开连接",
"New connection has been rejected with reason: ": "连接被拒绝,原因:",
"New connection has been rejected": "连接被拒绝",
"Password is required": "请提供密码",
"noVNC encountered an error:": "noVNC 遇到一个错误:",
"Hide/Show the control bar": "显示/隐藏控制栏",
"Move/Drag Viewport": "拖放显示范围",
"viewport drag": "显示范围拖放",
"Active Mouse Button": "启动鼠标按鍵",
"No mousebutton": "禁用鼠标按鍵",
"Left mousebutton": "鼠标左鍵",
"Middle mousebutton": "鼠标中鍵",
"Right mousebutton": "鼠标右鍵",
"Keyboard": "键盘",
"Show Keyboard": "显示键盘",
"Extra keys": "额外按键",
"Show Extra Keys": "显示额外按键",
"Ctrl": "Ctrl",
"Toggle Ctrl": "切换 Ctrl",
"Alt": "Alt",
"Toggle Alt": "切换 Alt",
"Send Tab": "发送 Tab 键",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "发送 Escape 键",
"Ctrl+Alt+Del": "Ctrl-Alt-Del",
"Send Ctrl-Alt-Del": "发送 Ctrl-Alt-Del 键",
"Shutdown/Reboot": "关机/重新启动",
"Shutdown/Reboot...": "关机/重新启动...",
"Power": "电源",
"Shutdown": "关机",
"Reboot": "重新启动",
"Reset": "重置",
"Clipboard": "剪贴板",
"Clear": "清除",
"Fullscreen": "全屏",
"Settings": "设置",
"Shared Mode": "分享模式",
"View Only": "仅查看",
"Clip to Window": "限制/裁切窗口大小",
"Scaling Mode:": "缩放模式:",
"None": "无",
"Local Scaling": "本地缩放",
"Remote Resizing": "远程调整大小",
"Advanced": "高级",
"Repeater ID:": "中继站 ID",
"WebSocket": "WebSocket",
"Encrypt": "加密",
"Host:": "主机:",
"Port:": "端口:",
"Path:": "路径:",
"Automatic Reconnect": "自动重新连接",
"Reconnect Delay (ms):": "重新连接间隔 (ms)",
"Logging:": "日志级别:",
"Disconnect": "中断连接",
"Connect": "连接",
"Password:": "密码:",
"Cancel": "取消"
}

View File

@ -0,0 +1,69 @@
{
"Connecting...": "連線中...",
"Disconnecting...": "正在中斷連線...",
"Reconnecting...": "重新連線中...",
"Internal error": "內部錯誤",
"Must set host": "請提供主機資訊",
"Connected (encrypted) to ": "已加密連線到",
"Connected (unencrypted) to ": "未加密連線到",
"Something went wrong, connection is closed": "發生錯誤,連線已關閉",
"Failed to connect to server": "無法連線到伺服器",
"Disconnected": "連線已中斷",
"New connection has been rejected with reason: ": "連線被拒絕,原因:",
"New connection has been rejected": "連線被拒絕",
"Password is required": "請提供密碼",
"noVNC encountered an error:": "noVNC 遇到一個錯誤:",
"Hide/Show the control bar": "顯示/隱藏控制列",
"Move/Drag Viewport": "拖放顯示範圍",
"viewport drag": "顯示範圍拖放",
"Active Mouse Button": "啟用滑鼠按鍵",
"No mousebutton": "無滑鼠按鍵",
"Left mousebutton": "滑鼠左鍵",
"Middle mousebutton": "滑鼠中鍵",
"Right mousebutton": "滑鼠右鍵",
"Keyboard": "鍵盤",
"Show Keyboard": "顯示鍵盤",
"Extra keys": "額外按鍵",
"Show Extra Keys": "顯示額外按鍵",
"Ctrl": "Ctrl",
"Toggle Ctrl": "切換 Ctrl",
"Alt": "Alt",
"Toggle Alt": "切換 Alt",
"Send Tab": "送出 Tab 鍵",
"Tab": "Tab",
"Esc": "Esc",
"Send Escape": "送出 Escape 鍵",
"Ctrl+Alt+Del": "Ctrl-Alt-Del",
"Send Ctrl-Alt-Del": "送出 Ctrl-Alt-Del 快捷鍵",
"Shutdown/Reboot": "關機/重新啟動",
"Shutdown/Reboot...": "關機/重新啟動...",
"Power": "電源",
"Shutdown": "關機",
"Reboot": "重新啟動",
"Reset": "重設",
"Clipboard": "剪貼簿",
"Clear": "清除",
"Fullscreen": "全螢幕",
"Settings": "設定",
"Shared Mode": "分享模式",
"View Only": "僅檢視",
"Clip to Window": "限制/裁切視窗大小",
"Scaling Mode:": "縮放模式:",
"None": "無",
"Local Scaling": "本機縮放",
"Remote Resizing": "遠端調整大小",
"Advanced": "進階",
"Repeater ID:": "中繼站 ID",
"WebSocket": "WebSocket",
"Encrypt": "加密",
"Host:": "主機:",
"Port:": "連接埠:",
"Path:": "路徑:",
"Automatic Reconnect": "自動重新連線",
"Reconnect Delay (ms):": "重新連線間隔 (ms)",
"Logging:": "日誌級別:",
"Disconnect": "中斷連線",
"Connect": "連線",
"Password:": "密碼:",
"Cancel": "取消"
}

View File

@ -0,0 +1,172 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
/*
* Localization Utilities
*/
export class Localizer {
constructor() {
// Currently configured language
this.language = 'en';
// Current dictionary of translations
this.dictionary = undefined;
}
// Configure suitable language based on user preferences
setup(supportedLanguages) {
this.language = 'en'; // Default: US English
/*
* Navigator.languages only available in Chrome (32+) and FireFox (32+)
* Fall back to navigator.language for other browsers
*/
let userLanguages;
if (typeof window.navigator.languages == 'object') {
userLanguages = window.navigator.languages;
} else {
userLanguages = [navigator.language || navigator.userLanguage];
}
for (let i = 0;i < userLanguages.length;i++) {
const userLang = userLanguages[i]
.toLowerCase()
.replace("_", "-")
.split("-");
// Built-in default?
if ((userLang[0] === 'en') &&
((userLang[1] === undefined) || (userLang[1] === 'us'))) {
return;
}
// First pass: perfect match
for (let j = 0; j < supportedLanguages.length; j++) {
const supLang = supportedLanguages[j]
.toLowerCase()
.replace("_", "-")
.split("-");
if (userLang[0] !== supLang[0]) {
continue;
}
if (userLang[1] !== supLang[1]) {
continue;
}
this.language = supportedLanguages[j];
return;
}
// Second pass: fallback
for (let j = 0;j < supportedLanguages.length;j++) {
const supLang = supportedLanguages[j]
.toLowerCase()
.replace("_", "-")
.split("-");
if (userLang[0] !== supLang[0]) {
continue;
}
if (supLang[1] !== undefined) {
continue;
}
this.language = supportedLanguages[j];
return;
}
}
}
// Retrieve localised text
get(id) {
if (typeof this.dictionary !== 'undefined' && this.dictionary[id]) {
return this.dictionary[id];
} else {
return id;
}
}
// Traverses the DOM and translates relevant fields
// See https://html.spec.whatwg.org/multipage/dom.html#attr-translate
translateDOM() {
const self = this;
function process(elem, enabled) {
function isAnyOf(searchElement, items) {
return items.indexOf(searchElement) !== -1;
}
function translateAttribute(elem, attr) {
const str = self.get(elem.getAttribute(attr));
elem.setAttribute(attr, str);
}
function translateTextNode(node) {
const str = self.get(node.data.trim());
node.data = str;
}
if (elem.hasAttribute("translate")) {
if (isAnyOf(elem.getAttribute("translate"), ["", "yes"])) {
enabled = true;
} else if (isAnyOf(elem.getAttribute("translate"), ["no"])) {
enabled = false;
}
}
if (enabled) {
if (elem.hasAttribute("abbr") &&
elem.tagName === "TH") {
translateAttribute(elem, "abbr");
}
if (elem.hasAttribute("alt") &&
isAnyOf(elem.tagName, ["AREA", "IMG", "INPUT"])) {
translateAttribute(elem, "alt");
}
if (elem.hasAttribute("download") &&
isAnyOf(elem.tagName, ["A", "AREA"])) {
translateAttribute(elem, "download");
}
if (elem.hasAttribute("label") &&
isAnyOf(elem.tagName, ["MENUITEM", "MENU", "OPTGROUP",
"OPTION", "TRACK"])) {
translateAttribute(elem, "label");
}
// FIXME: Should update "lang"
if (elem.hasAttribute("placeholder") &&
isAnyOf(elem.tagName, ["INPUT", "TEXTAREA"])) {
translateAttribute(elem, "placeholder");
}
if (elem.hasAttribute("title")) {
translateAttribute(elem, "title");
}
if (elem.hasAttribute("value") &&
elem.tagName === "INPUT" &&
isAnyOf(elem.getAttribute("type"), ["reset", "button", "submit"])) {
translateAttribute(elem, "value");
}
}
for (let i = 0; i < elem.childNodes.length; i++) {
const node = elem.childNodes[i];
if (node.nodeType === node.ELEMENT_NODE) {
process(node, enabled);
} else if (node.nodeType === node.TEXT_NODE && enabled) {
translateTextNode(node);
}
}
}
process(document.body, true);
}
}
export const l10n = new Localizer();
export default l10n.get.bind(l10n);

View File

@ -0,0 +1,4 @@
bell
Copyright: Dr. Richard Boulanger et al
URL: http://www.archive.org/details/Berklee44v12
License: CC-BY Attribution 3.0 Unported

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,970 @@
/*
* noVNC base CSS
* Copyright (C) 2019 The noVNC Authors
* noVNC is licensed under the MPL 2.0 (see LICENSE.txt)
* This file is licensed under the 2-Clause BSD license (see LICENSE.txt).
*/
/*
* Z index layers:
*
* 0: Main screen
* 10: Control bar
* 50: Transition blocker
* 60: Connection popups
* 100: Status bar
* ...
* 1000: Javascript crash
* ...
* 10000: Max (used for polyfills)
*/
body {
margin:0;
padding:0;
font-family: Helvetica;
/*Background image with light grey curve.*/
background-color:#494949;
background-repeat:no-repeat;
background-position:right bottom;
height:100%;
touch-action: none;
}
html {
height:100%;
}
.noVNC_only_touch.noVNC_hidden {
display: none;
}
.noVNC_disabled {
color: rgb(128, 128, 128);
}
/* ----------------------------------------
* Spinner
* ----------------------------------------
*/
.noVNC_spinner {
position: relative;
}
.noVNC_spinner, .noVNC_spinner::before, .noVNC_spinner::after {
width: 10px;
height: 10px;
border-radius: 2px;
box-shadow: -60px 10px 0 rgba(255, 255, 255, 0);
animation: noVNC_spinner 1.0s linear infinite;
}
.noVNC_spinner::before {
content: "";
position: absolute;
left: 0px;
top: 0px;
animation-delay: -0.1s;
}
.noVNC_spinner::after {
content: "";
position: absolute;
top: 0px;
left: 0px;
animation-delay: 0.1s;
}
@keyframes noVNC_spinner {
0% { box-shadow: -60px 10px 0 rgba(255, 255, 255, 0); width: 20px; }
25% { box-shadow: 20px 10px 0 rgba(255, 255, 255, 1); width: 10px; }
50% { box-shadow: 60px 10px 0 rgba(255, 255, 255, 0); width: 10px; }
}
/* ----------------------------------------
* Input Elements
* ----------------------------------------
*/
input:not([type]),
input[type=date],
input[type=datetime-local],
input[type=email],
input[type=month],
input[type=number],
input[type=password],
input[type=search],
input[type=tel],
input[type=text],
input[type=time],
input[type=url],
input[type=week],
textarea {
/* Disable default rendering */
-webkit-appearance: none;
-moz-appearance: none;
background: none;
margin: 2px;
padding: 2px;
border: 1px solid rgb(192, 192, 192);
border-radius: 5px;
color: black;
background: linear-gradient(to top, rgb(255, 255, 255) 80%, rgb(240, 240, 240));
}
input[type=button],
input[type=color],
input[type=reset],
input[type=submit],
select {
/* Disable default rendering */
-webkit-appearance: none;
-moz-appearance: none;
background: none;
margin: 2px;
padding: 2px;
border: 1px solid rgb(192, 192, 192);
border-bottom-width: 2px;
border-radius: 5px;
color: black;
background: linear-gradient(to top, rgb(255, 255, 255), rgb(240, 240, 240));
/* This avoids it jumping around when :active */
vertical-align: middle;
}
input[type=button],
input[type=color],
input[type=reset],
input[type=submit] {
padding-left: 20px;
padding-right: 20px;
}
option {
color: black;
background: white;
}
input:not([type]):focus,
input[type=button]:focus,
input[type=color]:focus,
input[type=date]:focus,
input[type=datetime-local]:focus,
input[type=email]:focus,
input[type=month]:focus,
input[type=number]:focus,
input[type=password]:focus,
input[type=reset]:focus,
input[type=search]:focus,
input[type=submit]:focus,
input[type=tel]:focus,
input[type=text]:focus,
input[type=time]:focus,
input[type=url]:focus,
input[type=week]:focus,
select:focus,
textarea:focus {
box-shadow: 0px 0px 3px rgba(74, 144, 217, 0.5);
border-color: rgb(74, 144, 217);
outline: none;
}
input[type=button]::-moz-focus-inner,
input[type=color]::-moz-focus-inner,
input[type=reset]::-moz-focus-inner,
input[type=submit]::-moz-focus-inner {
border: none;
}
input:not([type]):disabled,
input[type=button]:disabled,
input[type=color]:disabled,
input[type=date]:disabled,
input[type=datetime-local]:disabled,
input[type=email]:disabled,
input[type=month]:disabled,
input[type=number]:disabled,
input[type=password]:disabled,
input[type=reset]:disabled,
input[type=search]:disabled,
input[type=submit]:disabled,
input[type=tel]:disabled,
input[type=text]:disabled,
input[type=time]:disabled,
input[type=url]:disabled,
input[type=week]:disabled,
select:disabled,
textarea:disabled {
color: rgb(128, 128, 128);
background: rgb(240, 240, 240);
}
input[type=button]:active,
input[type=color]:active,
input[type=reset]:active,
input[type=submit]:active,
select:active {
border-bottom-width: 1px;
margin-top: 3px;
}
:root:not(.noVNC_touch) input[type=button]:hover:not(:disabled),
:root:not(.noVNC_touch) input[type=color]:hover:not(:disabled),
:root:not(.noVNC_touch) input[type=reset]:hover:not(:disabled),
:root:not(.noVNC_touch) input[type=submit]:hover:not(:disabled),
:root:not(.noVNC_touch) select:hover:not(:disabled) {
background: linear-gradient(to top, rgb(255, 255, 255), rgb(250, 250, 250));
}
/* ----------------------------------------
* WebKit centering hacks
* ----------------------------------------
*/
.noVNC_center {
/*
* This is a workaround because webkit misrenders transforms and
* uses non-integer coordinates, resulting in blurry content.
* Ideally we'd use "top: 50%; transform: translateY(-50%);" on
* the objects instead.
*/
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.noVNC_center > * {
pointer-events: auto;
}
.noVNC_vcenter {
display: flex;
flex-direction: column;
justify-content: center;
position: fixed;
top: 0;
left: 0;
height: 100%;
pointer-events: none;
}
.noVNC_vcenter > * {
pointer-events: auto;
}
/* ----------------------------------------
* Layering
* ----------------------------------------
*/
.noVNC_connect_layer {
z-index: 60;
}
/* ----------------------------------------
* Fallback error
* ----------------------------------------
*/
#noVNC_fallback_error {
z-index: 1000;
visibility: hidden;
}
#noVNC_fallback_error.noVNC_open {
visibility: visible;
}
#noVNC_fallback_error > div {
max-width: 90%;
padding: 15px;
transition: 0.5s ease-in-out;
transform: translateY(-50px);
opacity: 0;
text-align: center;
font-weight: bold;
color: #fff;
border-radius: 10px;
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
background: rgba(200,55,55,0.8);
}
#noVNC_fallback_error.noVNC_open > div {
transform: translateY(0);
opacity: 1;
}
#noVNC_fallback_errormsg {
font-weight: normal;
}
#noVNC_fallback_errormsg .noVNC_message {
display: inline-block;
text-align: left;
font-family: monospace;
white-space: pre-wrap;
}
#noVNC_fallback_error .noVNC_location {
font-style: italic;
font-size: 0.8em;
color: rgba(255, 255, 255, 0.8);
}
#noVNC_fallback_error .noVNC_stack {
max-height: 50vh;
padding: 10px;
margin: 10px;
font-size: 0.8em;
text-align: left;
font-family: monospace;
white-space: pre;
border: 1px solid rgba(0, 0, 0, 0.5);
background: rgba(0, 0, 0, 0.2);
overflow: auto;
}
/* ----------------------------------------
* Control Bar
* ----------------------------------------
*/
#noVNC_control_bar_anchor {
/* The anchor is needed to get z-stacking to work */
position: fixed;
z-index: 10;
transition: 0.5s ease-in-out;
/* Edge misrenders animations wihthout this */
transform: translateX(0);
}
:root.noVNC_connected #noVNC_control_bar_anchor.noVNC_idle {
opacity: 0.8;
}
#noVNC_control_bar_anchor.noVNC_right {
left: auto;
right: 0;
}
#noVNC_control_bar {
position: relative;
left: -100%;
transition: 0.5s ease-in-out;
background-color: rgb(110, 132, 163);
border-radius: 0 10px 10px 0;
}
#noVNC_control_bar.noVNC_open {
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
left: 0;
}
#noVNC_control_bar::before {
/* This extra element is to get a proper shadow */
content: "";
position: absolute;
z-index: -1;
height: 100%;
width: 30px;
left: -30px;
transition: box-shadow 0.5s ease-in-out;
}
#noVNC_control_bar.noVNC_open::before {
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
}
.noVNC_right #noVNC_control_bar {
left: 100%;
border-radius: 10px 0 0 10px;
}
.noVNC_right #noVNC_control_bar.noVNC_open {
left: 0;
}
.noVNC_right #noVNC_control_bar::before {
visibility: hidden;
}
#noVNC_control_bar_handle {
position: absolute;
left: -15px;
top: 0;
transform: translateY(35px);
width: calc(100% + 30px);
height: 50px;
z-index: -1;
cursor: pointer;
border-radius: 5px;
background-color: rgb(83, 99, 122);
background-image: url("../images/handle_bg.svg");
background-repeat: no-repeat;
background-position: right;
box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.5);
}
#noVNC_control_bar_handle:after {
content: "";
transition: transform 0.5s ease-in-out;
background: url("../images/handle.svg");
position: absolute;
top: 22px; /* (50px-6px)/2 */
right: 5px;
width: 5px;
height: 6px;
}
#noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
transform: translateX(1px) rotate(180deg);
}
:root:not(.noVNC_connected) #noVNC_control_bar_handle {
display: none;
}
.noVNC_right #noVNC_control_bar_handle {
background-position: left;
}
.noVNC_right #noVNC_control_bar_handle:after {
left: 5px;
right: 0;
transform: translateX(1px) rotate(180deg);
}
.noVNC_right #noVNC_control_bar.noVNC_open #noVNC_control_bar_handle:after {
transform: none;
}
#noVNC_control_bar_handle div {
position: absolute;
right: -35px;
top: 0;
width: 50px;
height: 50px;
}
:root:not(.noVNC_touch) #noVNC_control_bar_handle div {
display: none;
}
.noVNC_right #noVNC_control_bar_handle div {
left: -35px;
right: auto;
}
#noVNC_control_bar .noVNC_scroll {
max-height: 100vh; /* Chrome is buggy with 100% */
overflow-x: hidden;
overflow-y: auto;
padding: 0 10px 0 5px;
}
.noVNC_right #noVNC_control_bar .noVNC_scroll {
padding: 0 5px 0 10px;
}
/* Control bar hint */
#noVNC_control_bar_hint {
position: fixed;
left: calc(100vw - 50px);
right: auto;
top: 50%;
transform: translateY(-50%) scale(0);
width: 100px;
height: 50%;
max-height: 600px;
visibility: hidden;
opacity: 0;
transition: 0.2s ease-in-out;
background: transparent;
box-shadow: 0 0 10px black, inset 0 0 10px 10px rgba(110, 132, 163, 0.8);
border-radius: 10px;
transition-delay: 0s;
}
#noVNC_control_bar_anchor.noVNC_right #noVNC_control_bar_hint{
left: auto;
right: calc(100vw - 50px);
}
#noVNC_control_bar_hint.noVNC_active {
visibility: visible;
opacity: 1;
transition-delay: 0.2s;
transform: translateY(-50%) scale(1);
}
/* General button style */
.noVNC_button {
display: block;
padding: 4px 4px;
margin: 10px 0;
vertical-align: middle;
border:1px solid rgba(255, 255, 255, 0.2);
border-radius: 6px;
}
.noVNC_button.noVNC_selected {
border-color: rgba(0, 0, 0, 0.8);
background: rgba(0, 0, 0, 0.5);
}
.noVNC_button:disabled {
opacity: 0.4;
}
.noVNC_button:focus {
outline: none;
}
.noVNC_button:active {
padding-top: 5px;
padding-bottom: 3px;
}
/* Android browsers don't properly update hover state if touch events
* are intercepted, but focus should be safe to display */
:root:not(.noVNC_touch) .noVNC_button.noVNC_selected:hover,
.noVNC_button.noVNC_selected:focus {
border-color: rgba(0, 0, 0, 0.4);
background: rgba(0, 0, 0, 0.2);
}
:root:not(.noVNC_touch) .noVNC_button:hover,
.noVNC_button:focus {
background: rgba(255, 255, 255, 0.2);
}
.noVNC_button.noVNC_hidden {
display: none;
}
/* Panels */
.noVNC_panel {
transform: translateX(25px);
transition: 0.5s ease-in-out;
max-height: 100vh; /* Chrome is buggy with 100% */
overflow-x: hidden;
overflow-y: auto;
visibility: hidden;
opacity: 0;
padding: 15px;
background: #fff;
border-radius: 10px;
color: #000;
border: 2px solid #E0E0E0;
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
}
.noVNC_panel.noVNC_open {
visibility: visible;
opacity: 1;
transform: translateX(75px);
}
.noVNC_right .noVNC_vcenter {
left: auto;
right: 0;
}
.noVNC_right .noVNC_panel {
transform: translateX(-25px);
}
.noVNC_right .noVNC_panel.noVNC_open {
transform: translateX(-75px);
}
.noVNC_panel hr {
border: none;
border-top: 1px solid rgb(192, 192, 192);
}
.noVNC_panel label {
display: block;
white-space: nowrap;
}
.noVNC_panel .noVNC_heading {
background-color: rgb(110, 132, 163);
border-radius: 5px;
padding: 5px;
/* Compensate for padding in image */
padding-right: 8px;
color: white;
font-size: 20px;
margin-bottom: 10px;
white-space: nowrap;
}
.noVNC_panel .noVNC_heading img {
vertical-align: bottom;
}
.noVNC_submit {
float: right;
}
/* Expanders */
.noVNC_expander {
cursor: pointer;
}
.noVNC_expander::before {
content: url("../images/expander.svg");
display: inline-block;
margin-right: 5px;
transition: 0.2s ease-in-out;
}
.noVNC_expander.noVNC_open::before {
transform: rotateZ(90deg);
}
.noVNC_expander ~ * {
margin: 5px;
margin-left: 10px;
padding: 5px;
background: rgba(0, 0, 0, 0.05);
border-radius: 5px;
}
.noVNC_expander:not(.noVNC_open) ~ * {
display: none;
}
/* Control bar content */
#noVNC_control_bar .noVNC_logo {
font-size: 13px;
}
:root:not(.noVNC_connected) #noVNC_view_drag_button {
display: none;
}
/* noVNC Touch Device only buttons */
:root:not(.noVNC_connected) #noVNC_mobile_buttons {
display: none;
}
:root:not(.noVNC_touch) #noVNC_mobile_buttons {
display: none;
}
/* Extra manual keys */
:root:not(.noVNC_connected) #noVNC_toggle_extra_keys_button {
display: none;
}
#noVNC_modifiers {
background-color: rgb(92, 92, 92);
border: none;
padding: 0 10px;
}
/* Shutdown/Reboot */
:root:not(.noVNC_connected) #noVNC_power_button {
display: none;
}
#noVNC_power {
}
#noVNC_power_buttons {
display: none;
}
#noVNC_power input[type=button] {
width: 100%;
}
/* Clipboard */
:root:not(.noVNC_connected) #noVNC_clipboard_button {
display: none;
}
#noVNC_clipboard {
/* Full screen, minus padding and left and right margins */
max-width: calc(100vw - 2*15px - 75px - 25px);
}
#noVNC_clipboard_text {
width: 500px;
max-width: 100%;
}
/* Settings */
#noVNC_settings {
}
#noVNC_settings ul {
list-style: none;
margin: 0px;
padding: 0px;
}
#noVNC_setting_port {
width: 80px;
}
#noVNC_setting_path {
width: 100px;
}
/* Version */
.noVNC_version_wrapper {
font-size: small;
}
.noVNC_version {
margin-left: 1rem;
}
/* Connection Controls */
:root:not(.noVNC_connected) #noVNC_disconnect_button {
display: none;
}
/* ----------------------------------------
* Status Dialog
* ----------------------------------------
*/
#noVNC_status {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 100;
transform: translateY(-100%);
cursor: pointer;
transition: 0.5s ease-in-out;
visibility: hidden;
opacity: 0;
padding: 5px;
display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
line-height: 25px;
word-wrap: break-word;
color: #fff;
border-bottom: 1px solid rgba(0, 0, 0, 0.9);
}
#noVNC_status.noVNC_open {
transform: translateY(0);
visibility: visible;
opacity: 1;
}
#noVNC_status::before {
content: "";
display: inline-block;
width: 25px;
height: 25px;
margin-right: 5px;
}
#noVNC_status.noVNC_status_normal {
background: rgba(128,128,128,0.9);
}
#noVNC_status.noVNC_status_normal::before {
content: url("../images/info.svg") " ";
}
#noVNC_status.noVNC_status_error {
background: rgba(200,55,55,0.9);
}
#noVNC_status.noVNC_status_error::before {
content: url("../images/error.svg") " ";
}
#noVNC_status.noVNC_status_warn {
background: rgba(180,180,30,0.9);
}
#noVNC_status.noVNC_status_warn::before {
content: url("../images/warning.svg") " ";
}
/* ----------------------------------------
* Connect Dialog
* ----------------------------------------
*/
#noVNC_connect_dlg {
transition: 0.5s ease-in-out;
transform: scale(0, 0);
visibility: hidden;
opacity: 0;
}
#noVNC_connect_dlg.noVNC_open {
transform: scale(1, 1);
visibility: visible;
opacity: 1;
}
#noVNC_connect_dlg .noVNC_logo {
transition: 0.5s ease-in-out;
padding: 10px;
margin-bottom: 10px;
font-size: 80px;
text-align: center;
border-radius: 5px;
}
@media (max-width: 440px) {
#noVNC_connect_dlg {
max-width: calc(100vw - 100px);
}
#noVNC_connect_dlg .noVNC_logo {
font-size: calc(25vw - 30px);
}
}
#noVNC_connect_button {
cursor: pointer;
padding: 10px;
color: white;
background-color: rgb(110, 132, 163);
border-radius: 12px;
text-align: center;
font-size: 20px;
box-shadow: 6px 6px 0px rgba(0, 0, 0, 0.5);
}
#noVNC_connect_button div {
margin: 2px;
padding: 5px 30px;
border: 1px solid rgb(83, 99, 122);
border-bottom-width: 2px;
border-radius: 5px;
background: linear-gradient(to top, rgb(110, 132, 163), rgb(99, 119, 147));
/* This avoids it jumping around when :active */
vertical-align: middle;
}
#noVNC_connect_button div:active {
border-bottom-width: 1px;
margin-top: 3px;
}
:root:not(.noVNC_touch) #noVNC_connect_button div:hover {
background: linear-gradient(to top, rgb(110, 132, 163), rgb(105, 125, 155));
}
#noVNC_connect_button img {
vertical-align: bottom;
height: 1.3em;
}
/* ----------------------------------------
* Password Dialog
* ----------------------------------------
*/
#noVNC_credentials_dlg {
position: relative;
transform: translateY(-50px);
}
#noVNC_credentials_dlg.noVNC_open {
transform: translateY(0);
}
#noVNC_credentials_dlg ul {
list-style: none;
margin: 0px;
padding: 0px;
}
.noVNC_hidden {
display: none;
}
/* ----------------------------------------
* Main Area
* ----------------------------------------
*/
/* Transition screen */
#noVNC_transition {
display: none;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
color: white;
background: rgba(0, 0, 0, 0.5);
z-index: 50;
/*display: flex;*/
align-items: center;
justify-content: center;
flex-direction: column;
}
:root.noVNC_loading #noVNC_transition,
:root.noVNC_connecting #noVNC_transition,
:root.noVNC_disconnecting #noVNC_transition,
:root.noVNC_reconnecting #noVNC_transition {
display: flex;
}
:root:not(.noVNC_reconnecting) #noVNC_cancel_reconnect_button {
display: none;
}
#noVNC_transition_text {
font-size: 1.5em;
}
/* Main container */
#noVNC_container {
width: 100%;
height: 100%;
background-color: #313131;
border-bottom-right-radius: 800px 600px;
/*border-top-left-radius: 800px 600px;*/
}
#noVNC_keyboardinput {
width: 1px;
height: 1px;
background-color: #fff;
color: #fff;
border: 0;
position: absolute;
left: -40px;
z-index: -1;
ime-mode: disabled;
}
/*Default noVNC logo.*/
/* From: http://fonts.googleapis.com/css?family=Orbitron:700 */
@font-face {
font-family: 'Orbitron';
font-style: normal;
font-weight: 700;
src: local('?'), url('Orbitron700.woff') format('woff'),
url('Orbitron700.ttf') format('truetype');
}
.noVNC_logo {
color:yellow;
font-family: 'Orbitron', 'OrbitronTTF', sans-serif;
line-height:90%;
text-shadow: 0.1em 0.1em 0 black;
}
.noVNC_logo span{
color:green;
}
#noVNC_bell {
display: none;
}
/* ----------------------------------------
* Media sizing
* ----------------------------------------
*/
@media screen and (max-width: 640px){
#noVNC_logo {
font-size: 150px;
}
}
@media screen and (min-width: 321px) and (max-width: 480px) {
#noVNC_logo {
font-size: 110px;
}
}
@media screen and (max-width: 320px) {
#noVNC_logo {
font-size: 90px;
}
}

1715
static/app/ui.js 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
import { initLogging as mainInitLogging } from '../core/util/logging.js';
// init log level reading the logging HTTP param
export function initLogging(level) {
"use strict";
if (typeof level !== "undefined") {
mainInitLogging(level);
} else {
const param = document.location.href.match(/logging=([A-Za-z0-9._-]*)/);
mainInitLogging(param || undefined);
}
}
// Read a query string variable
// A URL with a query parameter can look like this (But will most probably get logged on the http server):
// https://www.example.com?myqueryparam=myvalue
//
// For privacy (Using a hastag #, the parameters will not be sent to the server)
// the url can be requested in the following way:
// https://www.example.com#myqueryparam=myvalue&password=secreatvalue
//
// Even Mixing public and non public parameters will work:
// https://www.example.com?nonsecretparam=example.com#password=secreatvalue
export function getQueryVar(name, defVal) {
"use strict";
const re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
match = ''.concat(document.location.href, window.location.hash).match(re);
if (typeof defVal === 'undefined') { defVal = null; }
if (match) {
return decodeURIComponent(match[1]);
}
return defVal;
}
// Read a hash fragment variable
export function getHashVar(name, defVal) {
"use strict";
const re = new RegExp('.*[&#]' + name + '=([^&]*)'),
match = document.location.hash.match(re);
if (typeof defVal === 'undefined') { defVal = null; }
if (match) {
return decodeURIComponent(match[1]);
}
return defVal;
}
// Read a variable from the fragment or the query string
// Fragment takes precedence
export function getConfigVar(name, defVal) {
"use strict";
const val = getHashVar(name);
if (val === null) {
return getQueryVar(name, defVal);
}
return val;
}
/*
* Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
*/
// No days means only for this browser session
export function createCookie(name, value, days) {
"use strict";
let date, expires;
if (days) {
date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toGMTString();
} else {
expires = "";
}
let secure;
if (document.location.protocol === "https:") {
secure = "; secure";
} else {
secure = "";
}
document.cookie = name + "=" + value + expires + "; path=/" + secure;
}
export function readCookie(name, defaultValue) {
"use strict";
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i += 1) {
let c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) === 0) {
return c.substring(nameEQ.length, c.length);
}
}
return (typeof defaultValue !== 'undefined') ? defaultValue : null;
}
export function eraseCookie(name) {
"use strict";
createCookie(name, "", -1);
}
/*
* Setting handling.
*/
let settings = {};
export function initSettings() {
if (!window.chrome || !window.chrome.storage) {
settings = {};
return Promise.resolve();
}
return new Promise(resolve => window.chrome.storage.sync.get(resolve))
.then((cfg) => { settings = cfg; });
}
// Update the settings cache, but do not write to permanent storage
export function setSetting(name, value) {
settings[name] = value;
}
// No days means only for this browser session
export function writeSetting(name, value) {
"use strict";
if (settings[name] === value) return;
settings[name] = value;
if (window.chrome && window.chrome.storage) {
window.chrome.storage.sync.set(settings);
} else {
localStorage.setItem(name, value);
}
}
export function readSetting(name, defaultValue) {
"use strict";
let value;
if ((name in settings) || (window.chrome && window.chrome.storage)) {
value = settings[name];
} else {
value = localStorage.getItem(name);
settings[name] = value;
}
if (typeof value === "undefined") {
value = null;
}
if (value === null && typeof defaultValue !== "undefined") {
return defaultValue;
}
return value;
}
export function eraseSetting(name) {
"use strict";
// Deleting here means that next time the setting is read when using local
// storage, it will be pulled from local storage again.
// If the setting in local storage is changed (e.g. in another tab)
// between this delete and the next read, it could lead to an unexpected
// value change.
delete settings[name];
if (window.chrome && window.chrome.storage) {
window.chrome.storage.sync.remove(name);
} else {
localStorage.removeItem(name);
}
}

7
static/bootstrap.bundle.min.js vendored 100644

File diff suppressed because one or more lines are too long

6
static/bootstrap.min.css vendored 100644

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,104 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// From: http://hg.mozilla.org/mozilla-central/raw-file/ec10630b1a54/js/src/devtools/jint/sunspider/string-base64.js
import * as Log from './util/logging.js';
export default {
/* Convert data (an array of integers) to a Base64 string. */
toBase64Table: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''),
base64Pad: '=',
encode(data) {
"use strict";
let result = '';
const length = data.length;
const lengthpad = (length % 3);
// Convert every three bytes to 4 ascii characters.
for (let i = 0; i < (length - 2); i += 3) {
result += this.toBase64Table[data[i] >> 2];
result += this.toBase64Table[((data[i] & 0x03) << 4) + (data[i + 1] >> 4)];
result += this.toBase64Table[((data[i + 1] & 0x0f) << 2) + (data[i + 2] >> 6)];
result += this.toBase64Table[data[i + 2] & 0x3f];
}
// Convert the remaining 1 or 2 bytes, pad out to 4 characters.
const j = length - lengthpad;
if (lengthpad === 2) {
result += this.toBase64Table[data[j] >> 2];
result += this.toBase64Table[((data[j] & 0x03) << 4) + (data[j + 1] >> 4)];
result += this.toBase64Table[(data[j + 1] & 0x0f) << 2];
result += this.toBase64Table[64];
} else if (lengthpad === 1) {
result += this.toBase64Table[data[j] >> 2];
result += this.toBase64Table[(data[j] & 0x03) << 4];
result += this.toBase64Table[64];
result += this.toBase64Table[64];
}
return result;
},
/* Convert Base64 data to a string */
/* eslint-disable comma-spacing */
toBinaryTable: [
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
],
/* eslint-enable comma-spacing */
decode(data, offset = 0) {
let dataLength = data.indexOf('=') - offset;
if (dataLength < 0) { dataLength = data.length - offset; }
/* Every four characters is 3 resulting numbers */
const resultLength = (dataLength >> 2) * 3 + Math.floor((dataLength % 4) / 1.5);
const result = new Array(resultLength);
// Convert one by one.
let leftbits = 0; // number of bits decoded, but yet to be appended
let leftdata = 0; // bits decoded, but yet to be appended
for (let idx = 0, i = offset; i < data.length; i++) {
const c = this.toBinaryTable[data.charCodeAt(i) & 0x7f];
const padding = (data.charAt(i) === this.base64Pad);
// Skip illegal characters and whitespace
if (c === -1) {
Log.Error("Illegal character code " + data.charCodeAt(i) + " at position " + i);
continue;
}
// Collect data into leftdata, update bitcount
leftdata = (leftdata << 6) | c;
leftbits += 6;
// If we have 8 or more bits, append 8 bits to the result
if (leftbits >= 8) {
leftbits -= 8;
// Append if not padding.
if (!padding) {
result[idx++] = (leftdata >> leftbits) & 0xff;
}
leftdata &= (1 << leftbits) - 1;
}
}
// If there are any bits left, the base64 string was corrupted
if (leftbits) {
const err = new Error('Corrupted base64 string');
err.name = 'Base64-Error';
throw err;
}
return result;
}
}; /* End of Base64 namespace */

View File

@ -0,0 +1,27 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
export default class CopyRectDecoder {
decodeRect(x, y, width, height, sock, display, depth) {
if (sock.rQwait("COPYRECT", 4)) {
return false;
}
let deltaX = sock.rQshift16();
let deltaY = sock.rQshift16();
if ((width === 0) || (height === 0)) {
return true;
}
display.copyImage(deltaX, deltaY, x, y, width, height);
return true;
}
}

View File

@ -0,0 +1,191 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
import * as Log from '../util/logging.js';
export default class HextileDecoder {
constructor() {
this._tiles = 0;
this._lastsubencoding = 0;
this._tileBuffer = new Uint8Array(16 * 16 * 4);
}
decodeRect(x, y, width, height, sock, display, depth) {
if (this._tiles === 0) {
this._tilesX = Math.ceil(width / 16);
this._tilesY = Math.ceil(height / 16);
this._totalTiles = this._tilesX * this._tilesY;
this._tiles = this._totalTiles;
}
while (this._tiles > 0) {
let bytes = 1;
if (sock.rQwait("HEXTILE", bytes)) {
return false;
}
let rQ = sock.rQ;
let rQi = sock.rQi;
let subencoding = rQ[rQi]; // Peek
if (subencoding > 30) { // Raw
throw new Error("Illegal hextile subencoding (subencoding: " +
subencoding + ")");
}
const currTile = this._totalTiles - this._tiles;
const tileX = currTile % this._tilesX;
const tileY = Math.floor(currTile / this._tilesX);
const tx = x + tileX * 16;
const ty = y + tileY * 16;
const tw = Math.min(16, (x + width) - tx);
const th = Math.min(16, (y + height) - ty);
// Figure out how much we are expecting
if (subencoding & 0x01) { // Raw
bytes += tw * th * 4;
} else {
if (subencoding & 0x02) { // Background
bytes += 4;
}
if (subencoding & 0x04) { // Foreground
bytes += 4;
}
if (subencoding & 0x08) { // AnySubrects
bytes++; // Since we aren't shifting it off
if (sock.rQwait("HEXTILE", bytes)) {
return false;
}
let subrects = rQ[rQi + bytes - 1]; // Peek
if (subencoding & 0x10) { // SubrectsColoured
bytes += subrects * (4 + 2);
} else {
bytes += subrects * 2;
}
}
}
if (sock.rQwait("HEXTILE", bytes)) {
return false;
}
// We know the encoding and have a whole tile
rQi++;
if (subencoding === 0) {
if (this._lastsubencoding & 0x01) {
// Weird: ignore blanks are RAW
Log.Debug(" Ignoring blank after RAW");
} else {
display.fillRect(tx, ty, tw, th, this._background);
}
} else if (subencoding & 0x01) { // Raw
let pixels = tw * th;
// Max sure the image is fully opaque
for (let i = 0;i < pixels;i++) {
rQ[rQi + i * 4 + 3] = 255;
}
display.blitImage(tx, ty, tw, th, rQ, rQi);
rQi += bytes - 1;
} else {
if (subencoding & 0x02) { // Background
this._background = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
rQi += 4;
}
if (subencoding & 0x04) { // Foreground
this._foreground = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
rQi += 4;
}
this._startTile(tx, ty, tw, th, this._background);
if (subencoding & 0x08) { // AnySubrects
let subrects = rQ[rQi];
rQi++;
for (let s = 0; s < subrects; s++) {
let color;
if (subencoding & 0x10) { // SubrectsColoured
color = [rQ[rQi], rQ[rQi + 1], rQ[rQi + 2], rQ[rQi + 3]];
rQi += 4;
} else {
color = this._foreground;
}
const xy = rQ[rQi];
rQi++;
const sx = (xy >> 4);
const sy = (xy & 0x0f);
const wh = rQ[rQi];
rQi++;
const sw = (wh >> 4) + 1;
const sh = (wh & 0x0f) + 1;
this._subTile(sx, sy, sw, sh, color);
}
}
this._finishTile(display);
}
sock.rQi = rQi;
this._lastsubencoding = subencoding;
this._tiles--;
}
return true;
}
// start updating a tile
_startTile(x, y, width, height, color) {
this._tileX = x;
this._tileY = y;
this._tileW = width;
this._tileH = height;
const red = color[0];
const green = color[1];
const blue = color[2];
const data = this._tileBuffer;
for (let i = 0; i < width * height * 4; i += 4) {
data[i] = red;
data[i + 1] = green;
data[i + 2] = blue;
data[i + 3] = 255;
}
}
// update sub-rectangle of the current tile
_subTile(x, y, w, h, color) {
const red = color[0];
const green = color[1];
const blue = color[2];
const xend = x + w;
const yend = y + h;
const data = this._tileBuffer;
const width = this._tileW;
for (let j = y; j < yend; j++) {
for (let i = x; i < xend; i++) {
const p = (i + (j * width)) * 4;
data[p] = red;
data[p + 1] = green;
data[p + 2] = blue;
data[p + 3] = 255;
}
}
}
// draw the current tile to the screen
_finishTile(display) {
display.blitImage(this._tileX, this._tileY,
this._tileW, this._tileH,
this._tileBuffer, 0);
}
}

View File

@ -0,0 +1,66 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
export default class RawDecoder {
constructor() {
this._lines = 0;
}
decodeRect(x, y, width, height, sock, display, depth) {
if ((width === 0) || (height === 0)) {
return true;
}
if (this._lines === 0) {
this._lines = height;
}
const pixelSize = depth == 8 ? 1 : 4;
const bytesPerLine = width * pixelSize;
if (sock.rQwait("RAW", bytesPerLine)) {
return false;
}
const curY = y + (height - this._lines);
const currHeight = Math.min(this._lines,
Math.floor(sock.rQlen / bytesPerLine));
const pixels = width * currHeight;
let data = sock.rQ;
let index = sock.rQi;
// Convert data if needed
if (depth == 8) {
const newdata = new Uint8Array(pixels * 4);
for (let i = 0; i < pixels; i++) {
newdata[i * 4 + 0] = ((data[index + i] >> 0) & 0x3) * 255 / 3;
newdata[i * 4 + 1] = ((data[index + i] >> 2) & 0x3) * 255 / 3;
newdata[i * 4 + 2] = ((data[index + i] >> 4) & 0x3) * 255 / 3;
newdata[i * 4 + 3] = 255;
}
data = newdata;
index = 0;
}
// Max sure the image is fully opaque
for (let i = 0; i < pixels; i++) {
data[i * 4 + 3] = 255;
}
display.blitImage(x, curY, width, currHeight, data, index);
sock.rQskipBytes(currHeight * bytesPerLine);
this._lines -= currHeight;
if (this._lines > 0) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,44 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
export default class RREDecoder {
constructor() {
this._subrects = 0;
}
decodeRect(x, y, width, height, sock, display, depth) {
if (this._subrects === 0) {
if (sock.rQwait("RRE", 4 + 4)) {
return false;
}
this._subrects = sock.rQshift32();
let color = sock.rQshiftBytes(4); // Background
display.fillRect(x, y, width, height, color);
}
while (this._subrects > 0) {
if (sock.rQwait("RRE", 4 + 8)) {
return false;
}
let color = sock.rQshiftBytes(4);
let sx = sock.rQshift16();
let sy = sock.rQshift16();
let swidth = sock.rQshift16();
let sheight = sock.rQshift16();
display.fillRect(x + sx, y + sy, swidth, sheight, color);
this._subrects--;
}
return true;
}
}

View File

@ -0,0 +1,331 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* (c) 2012 Michael Tinglof, Joe Balaz, Les Piech (Mercuri.ca)
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
import * as Log from '../util/logging.js';
import Inflator from "../inflator.js";
export default class TightDecoder {
constructor() {
this._ctl = null;
this._filter = null;
this._numColors = 0;
this._palette = new Uint8Array(1024); // 256 * 4 (max palette size * max bytes-per-pixel)
this._len = 0;
this._zlibs = [];
for (let i = 0; i < 4; i++) {
this._zlibs[i] = new Inflator();
}
}
decodeRect(x, y, width, height, sock, display, depth) {
if (this._ctl === null) {
if (sock.rQwait("TIGHT compression-control", 1)) {
return false;
}
this._ctl = sock.rQshift8();
// Reset streams if the server requests it
for (let i = 0; i < 4; i++) {
if ((this._ctl >> i) & 1) {
this._zlibs[i].reset();
Log.Info("Reset zlib stream " + i);
}
}
// Figure out filter
this._ctl = this._ctl >> 4;
}
let ret;
if (this._ctl === 0x08) {
ret = this._fillRect(x, y, width, height,
sock, display, depth);
} else if (this._ctl === 0x09) {
ret = this._jpegRect(x, y, width, height,
sock, display, depth);
} else if (this._ctl === 0x0A) {
ret = this._pngRect(x, y, width, height,
sock, display, depth);
} else if ((this._ctl & 0x08) == 0) {
ret = this._basicRect(this._ctl, x, y, width, height,
sock, display, depth);
} else {
throw new Error("Illegal tight compression received (ctl: " +
this._ctl + ")");
}
if (ret) {
this._ctl = null;
}
return ret;
}
_fillRect(x, y, width, height, sock, display, depth) {
if (sock.rQwait("TIGHT", 3)) {
return false;
}
const rQi = sock.rQi;
const rQ = sock.rQ;
display.fillRect(x, y, width, height,
[rQ[rQi], rQ[rQi + 1], rQ[rQi + 2]], false);
sock.rQskipBytes(3);
return true;
}
_jpegRect(x, y, width, height, sock, display, depth) {
let data = this._readData(sock);
if (data === null) {
return false;
}
display.imageRect(x, y, width, height, "image/jpeg", data);
return true;
}
_pngRect(x, y, width, height, sock, display, depth) {
throw new Error("PNG received in standard Tight rect");
}
_basicRect(ctl, x, y, width, height, sock, display, depth) {
if (this._filter === null) {
if (ctl & 0x4) {
if (sock.rQwait("TIGHT", 1)) {
return false;
}
this._filter = sock.rQshift8();
} else {
// Implicit CopyFilter
this._filter = 0;
}
}
let streamId = ctl & 0x3;
let ret;
switch (this._filter) {
case 0: // CopyFilter
ret = this._copyFilter(streamId, x, y, width, height,
sock, display, depth);
break;
case 1: // PaletteFilter
ret = this._paletteFilter(streamId, x, y, width, height,
sock, display, depth);
break;
case 2: // GradientFilter
ret = this._gradientFilter(streamId, x, y, width, height,
sock, display, depth);
break;
default:
throw new Error("Illegal tight filter received (ctl: " +
this._filter + ")");
}
if (ret) {
this._filter = null;
}
return ret;
}
_copyFilter(streamId, x, y, width, height, sock, display, depth) {
const uncompressedSize = width * height * 3;
let data;
if (uncompressedSize === 0) {
return true;
}
if (uncompressedSize < 12) {
if (sock.rQwait("TIGHT", uncompressedSize)) {
return false;
}
data = sock.rQshiftBytes(uncompressedSize);
} else {
data = this._readData(sock);
if (data === null) {
return false;
}
this._zlibs[streamId].setInput(data);
data = this._zlibs[streamId].inflate(uncompressedSize);
this._zlibs[streamId].setInput(null);
}
let rgbx = new Uint8Array(width * height * 4);
for (let i = 0, j = 0; i < width * height * 4; i += 4, j += 3) {
rgbx[i] = data[j];
rgbx[i + 1] = data[j + 1];
rgbx[i + 2] = data[j + 2];
rgbx[i + 3] = 255; // Alpha
}
display.blitImage(x, y, width, height, rgbx, 0, false);
return true;
}
_paletteFilter(streamId, x, y, width, height, sock, display, depth) {
if (this._numColors === 0) {
if (sock.rQwait("TIGHT palette", 1)) {
return false;
}
const numColors = sock.rQpeek8() + 1;
const paletteSize = numColors * 3;
if (sock.rQwait("TIGHT palette", 1 + paletteSize)) {
return false;
}
this._numColors = numColors;
sock.rQskipBytes(1);
sock.rQshiftTo(this._palette, paletteSize);
}
const bpp = (this._numColors <= 2) ? 1 : 8;
const rowSize = Math.floor((width * bpp + 7) / 8);
const uncompressedSize = rowSize * height;
let data;
if (uncompressedSize === 0) {
return true;
}
if (uncompressedSize < 12) {
if (sock.rQwait("TIGHT", uncompressedSize)) {
return false;
}
data = sock.rQshiftBytes(uncompressedSize);
} else {
data = this._readData(sock);
if (data === null) {
return false;
}
this._zlibs[streamId].setInput(data);
data = this._zlibs[streamId].inflate(uncompressedSize);
this._zlibs[streamId].setInput(null);
}
// Convert indexed (palette based) image data to RGB
if (this._numColors == 2) {
this._monoRect(x, y, width, height, data, this._palette, display);
} else {
this._paletteRect(x, y, width, height, data, this._palette, display);
}
this._numColors = 0;
return true;
}
_monoRect(x, y, width, height, data, palette, display) {
// Convert indexed (palette based) image data to RGB
// TODO: reduce number of calculations inside loop
const dest = this._getScratchBuffer(width * height * 4);
const w = Math.floor((width + 7) / 8);
const w1 = Math.floor(width / 8);
for (let y = 0; y < height; y++) {
let dp, sp, x;
for (x = 0; x < w1; x++) {
for (let b = 7; b >= 0; b--) {
dp = (y * width + x * 8 + 7 - b) * 4;
sp = (data[y * w + x] >> b & 1) * 3;
dest[dp] = palette[sp];
dest[dp + 1] = palette[sp + 1];
dest[dp + 2] = palette[sp + 2];
dest[dp + 3] = 255;
}
}
for (let b = 7; b >= 8 - width % 8; b--) {
dp = (y * width + x * 8 + 7 - b) * 4;
sp = (data[y * w + x] >> b & 1) * 3;
dest[dp] = palette[sp];
dest[dp + 1] = palette[sp + 1];
dest[dp + 2] = palette[sp + 2];
dest[dp + 3] = 255;
}
}
display.blitImage(x, y, width, height, dest, 0, false);
}
_paletteRect(x, y, width, height, data, palette, display) {
// Convert indexed (palette based) image data to RGB
const dest = this._getScratchBuffer(width * height * 4);
const total = width * height * 4;
for (let i = 0, j = 0; i < total; i += 4, j++) {
const sp = data[j] * 3;
dest[i] = palette[sp];
dest[i + 1] = palette[sp + 1];
dest[i + 2] = palette[sp + 2];
dest[i + 3] = 255;
}
display.blitImage(x, y, width, height, dest, 0, false);
}
_gradientFilter(streamId, x, y, width, height, sock, display, depth) {
throw new Error("Gradient filter not implemented");
}
_readData(sock) {
if (this._len === 0) {
if (sock.rQwait("TIGHT", 3)) {
return null;
}
let byte;
byte = sock.rQshift8();
this._len = byte & 0x7f;
if (byte & 0x80) {
byte = sock.rQshift8();
this._len |= (byte & 0x7f) << 7;
if (byte & 0x80) {
byte = sock.rQshift8();
this._len |= byte << 14;
}
}
}
if (sock.rQwait("TIGHT", this._len)) {
return null;
}
let data = sock.rQshiftBytes(this._len);
this._len = 0;
return data;
}
_getScratchBuffer(size) {
if (!this._scratchBuffer || (this._scratchBuffer.length < size)) {
this._scratchBuffer = new Uint8Array(size);
}
return this._scratchBuffer;
}
}

View File

@ -0,0 +1,27 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
import TightDecoder from './tight.js';
export default class TightPNGDecoder extends TightDecoder {
_pngRect(x, y, width, height, sock, display, depth) {
let data = this._readData(sock);
if (data === null) {
return false;
}
display.imageRect(x, y, width, height, "image/png", data);
return true;
}
_basicRect(ctl, x, y, width, height, sock, display, depth) {
throw new Error("BasicCompression received in TightPNG rect");
}
}

View File

@ -0,0 +1,85 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2020 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
import { deflateInit, deflate } from "../vendor/pako/lib/zlib/deflate.js";
import { Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js";
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
export default class Deflator {
constructor() {
this.strm = new ZStream();
this.chunkSize = 1024 * 10 * 10;
this.outputBuffer = new Uint8Array(this.chunkSize);
this.windowBits = 5;
deflateInit(this.strm, this.windowBits);
}
deflate(inData) {
/* eslint-disable camelcase */
this.strm.input = inData;
this.strm.avail_in = this.strm.input.length;
this.strm.next_in = 0;
this.strm.output = this.outputBuffer;
this.strm.avail_out = this.chunkSize;
this.strm.next_out = 0;
/* eslint-enable camelcase */
let lastRet = deflate(this.strm, Z_FULL_FLUSH);
let outData = new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
if (lastRet < 0) {
throw new Error("zlib deflate failed");
}
if (this.strm.avail_in > 0) {
// Read chunks until done
let chunks = [outData];
let totalLen = outData.length;
do {
/* eslint-disable camelcase */
this.strm.output = new Uint8Array(this.chunkSize);
this.strm.next_out = 0;
this.strm.avail_out = this.chunkSize;
/* eslint-enable camelcase */
lastRet = deflate(this.strm, Z_FULL_FLUSH);
if (lastRet < 0) {
throw new Error("zlib deflate failed");
}
let chunk = new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
totalLen += chunk.length;
chunks.push(chunk);
} while (this.strm.avail_in > 0);
// Combine chunks into a single data
let newData = new Uint8Array(totalLen);
let offset = 0;
for (let i = 0; i < chunks.length; i++) {
newData.set(chunks[i], offset);
offset += chunks[i].length;
}
outData = newData;
}
/* eslint-disable camelcase */
this.strm.input = null;
this.strm.avail_in = 0;
this.strm.next_in = 0;
/* eslint-enable camelcase */
return outData;
}
}

266
static/core/des.js 100644
View File

@ -0,0 +1,266 @@
/*
* Ported from Flashlight VNC ActionScript implementation:
* http://www.wizhelp.com/flashlight-vnc/
*
* Full attribution follows:
*
* -------------------------------------------------------------------------
*
* This DES class has been extracted from package Acme.Crypto for use in VNC.
* The unnecessary odd parity code has been removed.
*
* These changes are:
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* DesCipher - the DES encryption method
*
* The meat of this code is by Dave Zimmerman <dzimm@widget.com>, and is:
*
* Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and
* without fee is hereby granted, provided that this copyright notice is kept
* intact.
*
* WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
* OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE
* FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*
* THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE
* CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
* PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
* NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
* SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE
* SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE
* PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP
* SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR
* HIGH RISK ACTIVITIES.
*
*
* The rest is:
*
* Copyright (C) 1996 by Jef Poskanzer <jef@acme.com>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Visit the ACME Labs Java page for up-to-date versions of this and other
* fine Java utilities: http://www.acme.com/java/
*/
/* eslint-disable comma-spacing */
// Tables, permutations, S-boxes, etc.
const PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3,
25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39,
50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ],
totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28];
const z = 0x0;
let a,b,c,d,e,f;
a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e;
const SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d,
z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z,
a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f,
c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d];
a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e;
const SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d,
a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f,
z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z,
z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e];
a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e;
const SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f,
b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z,
c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d,
b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e];
a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e;
const SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d,
z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f,
b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e,
c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e];
a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e;
const SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z,
a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f,
z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e,
c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d];
a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e;
const SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f,
z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z,
b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z,
a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f];
a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e;
const SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f,
b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e,
b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e,
z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d];
a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e;
const SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d,
c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z,
a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f,
z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e];
/* eslint-enable comma-spacing */
export default class DES {
constructor(password) {
this.keys = [];
// Set the key.
const pc1m = [], pcr = [], kn = [];
for (let j = 0, l = 56; j < 56; ++j, l -= 8) {
l += l < -5 ? 65 : l < -3 ? 31 : l < -1 ? 63 : l === 27 ? 35 : 0; // PC1
const m = l & 0x7;
pc1m[j] = ((password[l >>> 3] & (1<<m)) !== 0) ? 1: 0;
}
for (let i = 0; i < 16; ++i) {
const m = i << 1;
const n = m + 1;
kn[m] = kn[n] = 0;
for (let o = 28; o < 59; o += 28) {
for (let j = o - 28; j < o; ++j) {
const l = j + totrot[i];
pcr[j] = l < o ? pc1m[l] : pc1m[l - 28];
}
}
for (let j = 0; j < 24; ++j) {
if (pcr[PC2[j]] !== 0) {
kn[m] |= 1 << (23 - j);
}
if (pcr[PC2[j + 24]] !== 0) {
kn[n] |= 1 << (23 - j);
}
}
}
// cookey
for (let i = 0, rawi = 0, KnLi = 0; i < 16; ++i) {
const raw0 = kn[rawi++];
const raw1 = kn[rawi++];
this.keys[KnLi] = (raw0 & 0x00fc0000) << 6;
this.keys[KnLi] |= (raw0 & 0x00000fc0) << 10;
this.keys[KnLi] |= (raw1 & 0x00fc0000) >>> 10;
this.keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6;
++KnLi;
this.keys[KnLi] = (raw0 & 0x0003f000) << 12;
this.keys[KnLi] |= (raw0 & 0x0000003f) << 16;
this.keys[KnLi] |= (raw1 & 0x0003f000) >>> 4;
this.keys[KnLi] |= (raw1 & 0x0000003f);
++KnLi;
}
}
// Encrypt 8 bytes of text
enc8(text) {
const b = text.slice();
let i = 0, l, r, x; // left, right, accumulator
// Squash 8 bytes to 2 ints
l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++];
r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++];
x = ((l >>> 4) ^ r) & 0x0f0f0f0f;
r ^= x;
l ^= (x << 4);
x = ((l >>> 16) ^ r) & 0x0000ffff;
r ^= x;
l ^= (x << 16);
x = ((r >>> 2) ^ l) & 0x33333333;
l ^= x;
r ^= (x << 2);
x = ((r >>> 8) ^ l) & 0x00ff00ff;
l ^= x;
r ^= (x << 8);
r = (r << 1) | ((r >>> 31) & 1);
x = (l ^ r) & 0xaaaaaaaa;
l ^= x;
r ^= x;
l = (l << 1) | ((l >>> 31) & 1);
for (let i = 0, keysi = 0; i < 8; ++i) {
x = (r << 28) | (r >>> 4);
x ^= this.keys[keysi++];
let fval = SP7[x & 0x3f];
fval |= SP5[(x >>> 8) & 0x3f];
fval |= SP3[(x >>> 16) & 0x3f];
fval |= SP1[(x >>> 24) & 0x3f];
x = r ^ this.keys[keysi++];
fval |= SP8[x & 0x3f];
fval |= SP6[(x >>> 8) & 0x3f];
fval |= SP4[(x >>> 16) & 0x3f];
fval |= SP2[(x >>> 24) & 0x3f];
l ^= fval;
x = (l << 28) | (l >>> 4);
x ^= this.keys[keysi++];
fval = SP7[x & 0x3f];
fval |= SP5[(x >>> 8) & 0x3f];
fval |= SP3[(x >>> 16) & 0x3f];
fval |= SP1[(x >>> 24) & 0x3f];
x = l ^ this.keys[keysi++];
fval |= SP8[x & 0x0000003f];
fval |= SP6[(x >>> 8) & 0x3f];
fval |= SP4[(x >>> 16) & 0x3f];
fval |= SP2[(x >>> 24) & 0x3f];
r ^= fval;
}
r = (r << 31) | (r >>> 1);
x = (l ^ r) & 0xaaaaaaaa;
l ^= x;
r ^= x;
l = (l << 31) | (l >>> 1);
x = ((l >>> 8) ^ r) & 0x00ff00ff;
r ^= x;
l ^= (x << 8);
x = ((l >>> 2) ^ r) & 0x33333333;
r ^= x;
l ^= (x << 2);
x = ((r >>> 16) ^ l) & 0x0000ffff;
l ^= x;
r ^= (x << 16);
x = ((r >>> 4) ^ l) & 0x0f0f0f0f;
l ^= x;
r ^= (x << 4);
// Spread ints to bytes
x = [r, l];
for (i = 0; i < 8; i++) {
b[i] = (x[i>>>2] >>> (8 * (3 - (i % 4)))) % 256;
if (b[i] < 0) { b[i] += 256; } // unsigned
}
return b;
}
// Encrypt 16 bytes of text using passwd as key
encrypt(t) {
return this.enc8(t.slice(0, 8)).concat(this.enc8(t.slice(8, 16)));
}
}

View File

@ -0,0 +1,513 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
import * as Log from './util/logging.js';
import Base64 from "./base64.js";
import { toSigned32bit } from './util/int.js';
export default class Display {
constructor(target) {
this._drawCtx = null;
this._renderQ = []; // queue drawing actions for in-oder rendering
this._flushing = false;
// the full frame buffer (logical canvas) size
this._fbWidth = 0;
this._fbHeight = 0;
this._prevDrawStyle = "";
Log.Debug(">> Display.constructor");
// The visible canvas
this._target = target;
if (!this._target) {
throw new Error("Target must be set");
}
if (typeof this._target === 'string') {
throw new Error('target must be a DOM element');
}
if (!this._target.getContext) {
throw new Error("no getContext method");
}
this._targetCtx = this._target.getContext('2d');
// the visible canvas viewport (i.e. what actually gets seen)
this._viewportLoc = { 'x': 0, 'y': 0, 'w': this._target.width, 'h': this._target.height };
// The hidden canvas, where we do the actual rendering
this._backbuffer = document.createElement('canvas');
this._drawCtx = this._backbuffer.getContext('2d');
this._damageBounds = { left: 0, top: 0,
right: this._backbuffer.width,
bottom: this._backbuffer.height };
Log.Debug("User Agent: " + navigator.userAgent);
Log.Debug("<< Display.constructor");
// ===== PROPERTIES =====
this._scale = 1.0;
this._clipViewport = false;
// ===== EVENT HANDLERS =====
this.onflush = () => {}; // A flush request has finished
}
// ===== PROPERTIES =====
get scale() { return this._scale; }
set scale(scale) {
this._rescale(scale);
}
get clipViewport() { return this._clipViewport; }
set clipViewport(viewport) {
this._clipViewport = viewport;
// May need to readjust the viewport dimensions
const vp = this._viewportLoc;
this.viewportChangeSize(vp.w, vp.h);
this.viewportChangePos(0, 0);
}
get width() {
return this._fbWidth;
}
get height() {
return this._fbHeight;
}
// ===== PUBLIC METHODS =====
viewportChangePos(deltaX, deltaY) {
const vp = this._viewportLoc;
deltaX = Math.floor(deltaX);
deltaY = Math.floor(deltaY);
if (!this._clipViewport) {
deltaX = -vp.w; // clamped later of out of bounds
deltaY = -vp.h;
}
const vx2 = vp.x + vp.w - 1;
const vy2 = vp.y + vp.h - 1;
// Position change
if (deltaX < 0 && vp.x + deltaX < 0) {
deltaX = -vp.x;
}
if (vx2 + deltaX >= this._fbWidth) {
deltaX -= vx2 + deltaX - this._fbWidth + 1;
}
if (vp.y + deltaY < 0) {
deltaY = -vp.y;
}
if (vy2 + deltaY >= this._fbHeight) {
deltaY -= (vy2 + deltaY - this._fbHeight + 1);
}
if (deltaX === 0 && deltaY === 0) {
return;
}
Log.Debug("viewportChange deltaX: " + deltaX + ", deltaY: " + deltaY);
vp.x += deltaX;
vp.y += deltaY;
this._damage(vp.x, vp.y, vp.w, vp.h);
this.flip();
}
viewportChangeSize(width, height) {
if (!this._clipViewport ||
typeof(width) === "undefined" ||
typeof(height) === "undefined") {
Log.Debug("Setting viewport to full display region");
width = this._fbWidth;
height = this._fbHeight;
}
width = Math.floor(width);
height = Math.floor(height);
if (width > this._fbWidth) {
width = this._fbWidth;
}
if (height > this._fbHeight) {
height = this._fbHeight;
}
const vp = this._viewportLoc;
if (vp.w !== width || vp.h !== height) {
vp.w = width;
vp.h = height;
const canvas = this._target;
canvas.width = width;
canvas.height = height;
// The position might need to be updated if we've grown
this.viewportChangePos(0, 0);
this._damage(vp.x, vp.y, vp.w, vp.h);
this.flip();
// Update the visible size of the target canvas
this._rescale(this._scale);
}
}
absX(x) {
if (this._scale === 0) {
return 0;
}
return toSigned32bit(x / this._scale + this._viewportLoc.x);
}
absY(y) {
if (this._scale === 0) {
return 0;
}
return toSigned32bit(y / this._scale + this._viewportLoc.y);
}
resize(width, height) {
this._prevDrawStyle = "";
this._fbWidth = width;
this._fbHeight = height;
const canvas = this._backbuffer;
if (canvas.width !== width || canvas.height !== height) {
// We have to save the canvas data since changing the size will clear it
let saveImg = null;
if (canvas.width > 0 && canvas.height > 0) {
saveImg = this._drawCtx.getImageData(0, 0, canvas.width, canvas.height);
}
if (canvas.width !== width) {
canvas.width = width;
}
if (canvas.height !== height) {
canvas.height = height;
}
if (saveImg) {
this._drawCtx.putImageData(saveImg, 0, 0);
}
}
// Readjust the viewport as it may be incorrectly sized
// and positioned
const vp = this._viewportLoc;
this.viewportChangeSize(vp.w, vp.h);
this.viewportChangePos(0, 0);
}
// Track what parts of the visible canvas that need updating
_damage(x, y, w, h) {
if (x < this._damageBounds.left) {
this._damageBounds.left = x;
}
if (y < this._damageBounds.top) {
this._damageBounds.top = y;
}
if ((x + w) > this._damageBounds.right) {
this._damageBounds.right = x + w;
}
if ((y + h) > this._damageBounds.bottom) {
this._damageBounds.bottom = y + h;
}
}
// Update the visible canvas with the contents of the
// rendering canvas
flip(fromQueue) {
if (this._renderQ.length !== 0 && !fromQueue) {
this._renderQPush({
'type': 'flip'
});
} else {
let x = this._damageBounds.left;
let y = this._damageBounds.top;
let w = this._damageBounds.right - x;
let h = this._damageBounds.bottom - y;
let vx = x - this._viewportLoc.x;
let vy = y - this._viewportLoc.y;
if (vx < 0) {
w += vx;
x -= vx;
vx = 0;
}
if (vy < 0) {
h += vy;
y -= vy;
vy = 0;
}
if ((vx + w) > this._viewportLoc.w) {
w = this._viewportLoc.w - vx;
}
if ((vy + h) > this._viewportLoc.h) {
h = this._viewportLoc.h - vy;
}
if ((w > 0) && (h > 0)) {
// FIXME: We may need to disable image smoothing here
// as well (see copyImage()), but we haven't
// noticed any problem yet.
this._targetCtx.drawImage(this._backbuffer,
x, y, w, h,
vx, vy, w, h);
}
this._damageBounds.left = this._damageBounds.top = 65535;
this._damageBounds.right = this._damageBounds.bottom = 0;
}
}
pending() {
return this._renderQ.length > 0;
}
flush() {
if (this._renderQ.length === 0) {
this.onflush();
} else {
this._flushing = true;
}
}
fillRect(x, y, width, height, color, fromQueue) {
if (this._renderQ.length !== 0 && !fromQueue) {
this._renderQPush({
'type': 'fill',
'x': x,
'y': y,
'width': width,
'height': height,
'color': color
});
} else {
this._setFillColor(color);
this._drawCtx.fillRect(x, y, width, height);
this._damage(x, y, width, height);
}
}
copyImage(oldX, oldY, newX, newY, w, h, fromQueue) {
if (this._renderQ.length !== 0 && !fromQueue) {
this._renderQPush({
'type': 'copy',
'oldX': oldX,
'oldY': oldY,
'x': newX,
'y': newY,
'width': w,
'height': h,
});
} else {
// Due to this bug among others [1] we need to disable the image-smoothing to
// avoid getting a blur effect when copying data.
//
// 1. https://bugzilla.mozilla.org/show_bug.cgi?id=1194719
//
// We need to set these every time since all properties are reset
// when the the size is changed
this._drawCtx.mozImageSmoothingEnabled = false;
this._drawCtx.webkitImageSmoothingEnabled = false;
this._drawCtx.msImageSmoothingEnabled = false;
this._drawCtx.imageSmoothingEnabled = false;
this._drawCtx.drawImage(this._backbuffer,
oldX, oldY, w, h,
newX, newY, w, h);
this._damage(newX, newY, w, h);
}
}
imageRect(x, y, width, height, mime, arr) {
/* The internal logic cannot handle empty images, so bail early */
if ((width === 0) || (height === 0)) {
return;
}
const img = new Image();
img.src = "data: " + mime + ";base64," + Base64.encode(arr);
this._renderQPush({
'type': 'img',
'img': img,
'x': x,
'y': y,
'width': width,
'height': height
});
}
blitImage(x, y, width, height, arr, offset, fromQueue) {
if (this._renderQ.length !== 0 && !fromQueue) {
// NB(directxman12): it's technically more performant here to use preallocated arrays,
// but it's a lot of extra work for not a lot of payoff -- if we're using the render queue,
// this probably isn't getting called *nearly* as much
const newArr = new Uint8Array(width * height * 4);
newArr.set(new Uint8Array(arr.buffer, 0, newArr.length));
this._renderQPush({
'type': 'blit',
'data': newArr,
'x': x,
'y': y,
'width': width,
'height': height,
});
} else {
// NB(directxman12): arr must be an Type Array view
let data = new Uint8ClampedArray(arr.buffer,
arr.byteOffset + offset,
width * height * 4);
let img = new ImageData(data, width, height);
this._drawCtx.putImageData(img, x, y);
this._damage(x, y, width, height);
}
}
drawImage(img, x, y) {
this._drawCtx.drawImage(img, x, y);
this._damage(x, y, img.width, img.height);
}
autoscale(containerWidth, containerHeight) {
let scaleRatio;
if (containerWidth === 0 || containerHeight === 0) {
scaleRatio = 0;
} else {
const vp = this._viewportLoc;
const targetAspectRatio = containerWidth / containerHeight;
const fbAspectRatio = vp.w / vp.h;
if (fbAspectRatio >= targetAspectRatio) {
scaleRatio = containerWidth / vp.w;
} else {
scaleRatio = containerHeight / vp.h;
}
}
this._rescale(scaleRatio);
}
// ===== PRIVATE METHODS =====
_rescale(factor) {
this._scale = factor;
const vp = this._viewportLoc;
// NB(directxman12): If you set the width directly, or set the
// style width to a number, the canvas is cleared.
// However, if you set the style width to a string
// ('NNNpx'), the canvas is scaled without clearing.
const width = factor * vp.w + 'px';
const height = factor * vp.h + 'px';
if ((this._target.style.width !== width) ||
(this._target.style.height !== height)) {
this._target.style.width = width;
this._target.style.height = height;
}
}
_setFillColor(color) {
const newStyle = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')';
if (newStyle !== this._prevDrawStyle) {
this._drawCtx.fillStyle = newStyle;
this._prevDrawStyle = newStyle;
}
}
_renderQPush(action) {
this._renderQ.push(action);
if (this._renderQ.length === 1) {
// If this can be rendered immediately it will be, otherwise
// the scanner will wait for the relevant event
this._scanRenderQ();
}
}
_resumeRenderQ() {
// "this" is the object that is ready, not the
// display object
this.removeEventListener('load', this._noVNCDisplay._resumeRenderQ);
this._noVNCDisplay._scanRenderQ();
}
_scanRenderQ() {
let ready = true;
while (ready && this._renderQ.length > 0) {
const a = this._renderQ[0];
switch (a.type) {
case 'flip':
this.flip(true);
break;
case 'copy':
this.copyImage(a.oldX, a.oldY, a.x, a.y, a.width, a.height, true);
break;
case 'fill':
this.fillRect(a.x, a.y, a.width, a.height, a.color, true);
break;
case 'blit':
this.blitImage(a.x, a.y, a.width, a.height, a.data, 0, true);
break;
case 'img':
if (a.img.complete) {
if (a.img.width !== a.width || a.img.height !== a.height) {
Log.Error("Decoded image has incorrect dimensions. Got " +
a.img.width + "x" + a.img.height + ". Expected " +
a.width + "x" + a.height + ".");
return;
}
this.drawImage(a.img, a.x, a.y);
} else {
a.img._noVNCDisplay = this;
a.img.addEventListener('load', this._resumeRenderQ);
// We need to wait for this image to 'load'
// to keep things in-order
ready = false;
}
break;
}
if (ready) {
this._renderQ.shift();
}
}
if (this._renderQ.length === 0 && this._flushing) {
this._flushing = false;
this.onflush();
}
}
}

View File

@ -0,0 +1,44 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
export const encodings = {
encodingRaw: 0,
encodingCopyRect: 1,
encodingRRE: 2,
encodingHextile: 5,
encodingTight: 7,
encodingTightPNG: -260,
pseudoEncodingQualityLevel9: -23,
pseudoEncodingQualityLevel0: -32,
pseudoEncodingDesktopSize: -223,
pseudoEncodingLastRect: -224,
pseudoEncodingCursor: -239,
pseudoEncodingQEMUExtendedKeyEvent: -258,
pseudoEncodingDesktopName: -307,
pseudoEncodingExtendedDesktopSize: -308,
pseudoEncodingXvp: -309,
pseudoEncodingFence: -312,
pseudoEncodingContinuousUpdates: -313,
pseudoEncodingCompressLevel9: -247,
pseudoEncodingCompressLevel0: -256,
pseudoEncodingVMwareCursor: 0x574d5664,
pseudoEncodingExtendedClipboard: 0xc0a1e5ce
};
export function encodingName(num) {
switch (num) {
case encodings.encodingRaw: return "Raw";
case encodings.encodingCopyRect: return "CopyRect";
case encodings.encodingRRE: return "RRE";
case encodings.encodingHextile: return "Hextile";
case encodings.encodingTight: return "Tight";
case encodings.encodingTightPNG: return "TightPNG";
default: return "[unknown encoding " + num + "]";
}
}

View File

@ -0,0 +1,66 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2020 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*/
import { inflateInit, inflate, inflateReset } from "../vendor/pako/lib/zlib/inflate.js";
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
export default class Inflate {
constructor() {
this.strm = new ZStream();
this.chunkSize = 1024 * 10 * 10;
this.strm.output = new Uint8Array(this.chunkSize);
this.windowBits = 5;
inflateInit(this.strm, this.windowBits);
}
setInput(data) {
if (!data) {
//FIXME: flush remaining data.
/* eslint-disable camelcase */
this.strm.input = null;
this.strm.avail_in = 0;
this.strm.next_in = 0;
} else {
this.strm.input = data;
this.strm.avail_in = this.strm.input.length;
this.strm.next_in = 0;
/* eslint-enable camelcase */
}
}
inflate(expected) {
// resize our output buffer if it's too small
// (we could just use multiple chunks, but that would cause an extra
// allocation each time to flatten the chunks)
if (expected > this.chunkSize) {
this.chunkSize = expected;
this.strm.output = new Uint8Array(this.chunkSize);
}
/* eslint-disable camelcase */
this.strm.next_out = 0;
this.strm.avail_out = expected;
/* eslint-enable camelcase */
let ret = inflate(this.strm, 0); // Flush argument not used.
if (ret < 0) {
throw new Error("zlib inflate failed");
}
if (this.strm.next_out != expected) {
throw new Error("Incomplete zlib block");
}
return new Uint8Array(this.strm.output.buffer, 0, this.strm.next_out);
}
reset() {
inflateReset(this.strm);
}
}

View File

@ -0,0 +1,311 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
*/
import KeyTable from "./keysym.js";
/*
* Mapping between HTML key values and VNC/X11 keysyms for "special"
* keys that cannot be handled via their Unicode codepoint.
*
* See https://www.w3.org/TR/uievents-key/ for possible values.
*/
const DOMKeyTable = {};
function addStandard(key, standard) {
if (standard === undefined) throw new Error("Undefined keysym for key \"" + key + "\"");
if (key in DOMKeyTable) throw new Error("Duplicate entry for key \"" + key + "\"");
DOMKeyTable[key] = [standard, standard, standard, standard];
}
function addLeftRight(key, left, right) {
if (left === undefined) throw new Error("Undefined keysym for key \"" + key + "\"");
if (right === undefined) throw new Error("Undefined keysym for key \"" + key + "\"");
if (key in DOMKeyTable) throw new Error("Duplicate entry for key \"" + key + "\"");
DOMKeyTable[key] = [left, left, right, left];
}
function addNumpad(key, standard, numpad) {
if (standard === undefined) throw new Error("Undefined keysym for key \"" + key + "\"");
if (numpad === undefined) throw new Error("Undefined keysym for key \"" + key + "\"");
if (key in DOMKeyTable) throw new Error("Duplicate entry for key \"" + key + "\"");
DOMKeyTable[key] = [standard, standard, standard, numpad];
}
// 3.2. Modifier Keys
addLeftRight("Alt", KeyTable.XK_Alt_L, KeyTable.XK_Alt_R);
addStandard("AltGraph", KeyTable.XK_ISO_Level3_Shift);
addStandard("CapsLock", KeyTable.XK_Caps_Lock);
addLeftRight("Control", KeyTable.XK_Control_L, KeyTable.XK_Control_R);
// - Fn
// - FnLock
addLeftRight("Meta", KeyTable.XK_Super_L, KeyTable.XK_Super_R);
addStandard("NumLock", KeyTable.XK_Num_Lock);
addStandard("ScrollLock", KeyTable.XK_Scroll_Lock);
addLeftRight("Shift", KeyTable.XK_Shift_L, KeyTable.XK_Shift_R);
// - Symbol
// - SymbolLock
// - Hyper
// - Super
// 3.3. Whitespace Keys
addNumpad("Enter", KeyTable.XK_Return, KeyTable.XK_KP_Enter);
addStandard("Tab", KeyTable.XK_Tab);
addNumpad(" ", KeyTable.XK_space, KeyTable.XK_KP_Space);
// 3.4. Navigation Keys
addNumpad("ArrowDown", KeyTable.XK_Down, KeyTable.XK_KP_Down);
addNumpad("ArrowLeft", KeyTable.XK_Left, KeyTable.XK_KP_Left);
addNumpad("ArrowRight", KeyTable.XK_Right, KeyTable.XK_KP_Right);
addNumpad("ArrowUp", KeyTable.XK_Up, KeyTable.XK_KP_Up);
addNumpad("End", KeyTable.XK_End, KeyTable.XK_KP_End);
addNumpad("Home", KeyTable.XK_Home, KeyTable.XK_KP_Home);
addNumpad("PageDown", KeyTable.XK_Next, KeyTable.XK_KP_Next);
addNumpad("PageUp", KeyTable.XK_Prior, KeyTable.XK_KP_Prior);
// 3.5. Editing Keys
addStandard("Backspace", KeyTable.XK_BackSpace);
// Browsers send "Clear" for the numpad 5 without NumLock because
// Windows uses VK_Clear for that key. But Unix expects KP_Begin for
// that scenario.
addNumpad("Clear", KeyTable.XK_Clear, KeyTable.XK_KP_Begin);
addStandard("Copy", KeyTable.XF86XK_Copy);
// - CrSel
addStandard("Cut", KeyTable.XF86XK_Cut);
addNumpad("Delete", KeyTable.XK_Delete, KeyTable.XK_KP_Delete);
// - EraseEof
// - ExSel
addNumpad("Insert", KeyTable.XK_Insert, KeyTable.XK_KP_Insert);
addStandard("Paste", KeyTable.XF86XK_Paste);
addStandard("Redo", KeyTable.XK_Redo);
addStandard("Undo", KeyTable.XK_Undo);
// 3.6. UI Keys
// - Accept
// - Again (could just be XK_Redo)
// - Attn
addStandard("Cancel", KeyTable.XK_Cancel);
addStandard("ContextMenu", KeyTable.XK_Menu);
addStandard("Escape", KeyTable.XK_Escape);
addStandard("Execute", KeyTable.XK_Execute);
addStandard("Find", KeyTable.XK_Find);
addStandard("Help", KeyTable.XK_Help);
addStandard("Pause", KeyTable.XK_Pause);
// - Play
// - Props
addStandard("Select", KeyTable.XK_Select);
addStandard("ZoomIn", KeyTable.XF86XK_ZoomIn);
addStandard("ZoomOut", KeyTable.XF86XK_ZoomOut);
// 3.7. Device Keys
addStandard("BrightnessDown", KeyTable.XF86XK_MonBrightnessDown);
addStandard("BrightnessUp", KeyTable.XF86XK_MonBrightnessUp);
addStandard("Eject", KeyTable.XF86XK_Eject);
addStandard("LogOff", KeyTable.XF86XK_LogOff);
addStandard("Power", KeyTable.XF86XK_PowerOff);
addStandard("PowerOff", KeyTable.XF86XK_PowerDown);
addStandard("PrintScreen", KeyTable.XK_Print);
addStandard("Hibernate", KeyTable.XF86XK_Hibernate);
addStandard("Standby", KeyTable.XF86XK_Standby);
addStandard("WakeUp", KeyTable.XF86XK_WakeUp);
// 3.8. IME and Composition Keys
addStandard("AllCandidates", KeyTable.XK_MultipleCandidate);
addStandard("Alphanumeric", KeyTable.XK_Eisu_toggle);
addStandard("CodeInput", KeyTable.XK_Codeinput);
addStandard("Compose", KeyTable.XK_Multi_key);
addStandard("Convert", KeyTable.XK_Henkan);
// - Dead
// - FinalMode
addStandard("GroupFirst", KeyTable.XK_ISO_First_Group);
addStandard("GroupLast", KeyTable.XK_ISO_Last_Group);
addStandard("GroupNext", KeyTable.XK_ISO_Next_Group);
addStandard("GroupPrevious", KeyTable.XK_ISO_Prev_Group);
// - ModeChange (XK_Mode_switch is often used for AltGr)
// - NextCandidate
addStandard("NonConvert", KeyTable.XK_Muhenkan);
addStandard("PreviousCandidate", KeyTable.XK_PreviousCandidate);
// - Process
addStandard("SingleCandidate", KeyTable.XK_SingleCandidate);
addStandard("HangulMode", KeyTable.XK_Hangul);
addStandard("HanjaMode", KeyTable.XK_Hangul_Hanja);
addStandard("JunjaMode", KeyTable.XK_Hangul_Jeonja);
addStandard("Eisu", KeyTable.XK_Eisu_toggle);
addStandard("Hankaku", KeyTable.XK_Hankaku);
addStandard("Hiragana", KeyTable.XK_Hiragana);
addStandard("HiraganaKatakana", KeyTable.XK_Hiragana_Katakana);
addStandard("KanaMode", KeyTable.XK_Kana_Shift); // could also be _Kana_Lock
addStandard("KanjiMode", KeyTable.XK_Kanji);
addStandard("Katakana", KeyTable.XK_Katakana);
addStandard("Romaji", KeyTable.XK_Romaji);
addStandard("Zenkaku", KeyTable.XK_Zenkaku);
addStandard("ZenkakuHankaku", KeyTable.XK_Zenkaku_Hankaku);
// 3.9. General-Purpose Function Keys
addStandard("F1", KeyTable.XK_F1);
addStandard("F2", KeyTable.XK_F2);
addStandard("F3", KeyTable.XK_F3);
addStandard("F4", KeyTable.XK_F4);
addStandard("F5", KeyTable.XK_F5);
addStandard("F6", KeyTable.XK_F6);
addStandard("F7", KeyTable.XK_F7);
addStandard("F8", KeyTable.XK_F8);
addStandard("F9", KeyTable.XK_F9);
addStandard("F10", KeyTable.XK_F10);
addStandard("F11", KeyTable.XK_F11);
addStandard("F12", KeyTable.XK_F12);
addStandard("F13", KeyTable.XK_F13);
addStandard("F14", KeyTable.XK_F14);
addStandard("F15", KeyTable.XK_F15);
addStandard("F16", KeyTable.XK_F16);
addStandard("F17", KeyTable.XK_F17);
addStandard("F18", KeyTable.XK_F18);
addStandard("F19", KeyTable.XK_F19);
addStandard("F20", KeyTable.XK_F20);
addStandard("F21", KeyTable.XK_F21);
addStandard("F22", KeyTable.XK_F22);
addStandard("F23", KeyTable.XK_F23);
addStandard("F24", KeyTable.XK_F24);
addStandard("F25", KeyTable.XK_F25);
addStandard("F26", KeyTable.XK_F26);
addStandard("F27", KeyTable.XK_F27);
addStandard("F28", KeyTable.XK_F28);
addStandard("F29", KeyTable.XK_F29);
addStandard("F30", KeyTable.XK_F30);
addStandard("F31", KeyTable.XK_F31);
addStandard("F32", KeyTable.XK_F32);
addStandard("F33", KeyTable.XK_F33);
addStandard("F34", KeyTable.XK_F34);
addStandard("F35", KeyTable.XK_F35);
// - Soft1...
// 3.10. Multimedia Keys
// - ChannelDown
// - ChannelUp
addStandard("Close", KeyTable.XF86XK_Close);
addStandard("MailForward", KeyTable.XF86XK_MailForward);
addStandard("MailReply", KeyTable.XF86XK_Reply);
addStandard("MailSend", KeyTable.XF86XK_Send);
// - MediaClose
addStandard("MediaFastForward", KeyTable.XF86XK_AudioForward);
addStandard("MediaPause", KeyTable.XF86XK_AudioPause);
addStandard("MediaPlay", KeyTable.XF86XK_AudioPlay);
// - MediaPlayPause
addStandard("MediaRecord", KeyTable.XF86XK_AudioRecord);
addStandard("MediaRewind", KeyTable.XF86XK_AudioRewind);
addStandard("MediaStop", KeyTable.XF86XK_AudioStop);
addStandard("MediaTrackNext", KeyTable.XF86XK_AudioNext);
addStandard("MediaTrackPrevious", KeyTable.XF86XK_AudioPrev);
addStandard("New", KeyTable.XF86XK_New);
addStandard("Open", KeyTable.XF86XK_Open);
addStandard("Print", KeyTable.XK_Print);
addStandard("Save", KeyTable.XF86XK_Save);
addStandard("SpellCheck", KeyTable.XF86XK_Spell);
// 3.11. Multimedia Numpad Keys
// - Key11
// - Key12
// 3.12. Audio Keys
// - AudioBalanceLeft
// - AudioBalanceRight
// - AudioBassBoostDown
// - AudioBassBoostToggle
// - AudioBassBoostUp
// - AudioFaderFront
// - AudioFaderRear
// - AudioSurroundModeNext
// - AudioTrebleDown
// - AudioTrebleUp
addStandard("AudioVolumeDown", KeyTable.XF86XK_AudioLowerVolume);
addStandard("AudioVolumeUp", KeyTable.XF86XK_AudioRaiseVolume);
addStandard("AudioVolumeMute", KeyTable.XF86XK_AudioMute);
// - MicrophoneToggle
// - MicrophoneVolumeDown
// - MicrophoneVolumeUp
addStandard("MicrophoneVolumeMute", KeyTable.XF86XK_AudioMicMute);
// 3.13. Speech Keys
// - SpeechCorrectionList
// - SpeechInputToggle
// 3.14. Application Keys
addStandard("LaunchApplication1", KeyTable.XF86XK_MyComputer);
addStandard("LaunchApplication2", KeyTable.XF86XK_Calculator);
addStandard("LaunchCalendar", KeyTable.XF86XK_Calendar);
// - LaunchContacts
addStandard("LaunchMail", KeyTable.XF86XK_Mail);
addStandard("LaunchMediaPlayer", KeyTable.XF86XK_AudioMedia);
addStandard("LaunchMusicPlayer", KeyTable.XF86XK_Music);
addStandard("LaunchPhone", KeyTable.XF86XK_Phone);
addStandard("LaunchScreenSaver", KeyTable.XF86XK_ScreenSaver);
addStandard("LaunchSpreadsheet", KeyTable.XF86XK_Excel);
addStandard("LaunchWebBrowser", KeyTable.XF86XK_WWW);
addStandard("LaunchWebCam", KeyTable.XF86XK_WebCam);
addStandard("LaunchWordProcessor", KeyTable.XF86XK_Word);
// 3.15. Browser Keys
addStandard("BrowserBack", KeyTable.XF86XK_Back);
addStandard("BrowserFavorites", KeyTable.XF86XK_Favorites);
addStandard("BrowserForward", KeyTable.XF86XK_Forward);
addStandard("BrowserHome", KeyTable.XF86XK_HomePage);
addStandard("BrowserRefresh", KeyTable.XF86XK_Refresh);
addStandard("BrowserSearch", KeyTable.XF86XK_Search);
addStandard("BrowserStop", KeyTable.XF86XK_Stop);
// 3.16. Mobile Phone Keys
// - A whole bunch...
// 3.17. TV Keys
// - A whole bunch...
// 3.18. Media Controller Keys
// - A whole bunch...
addStandard("Dimmer", KeyTable.XF86XK_BrightnessAdjust);
addStandard("MediaAudioTrack", KeyTable.XF86XK_AudioCycleTrack);
addStandard("RandomToggle", KeyTable.XF86XK_AudioRandomPlay);
addStandard("SplitScreenToggle", KeyTable.XF86XK_SplitScreen);
addStandard("Subtitle", KeyTable.XF86XK_Subtitle);
addStandard("VideoModeNext", KeyTable.XF86XK_Next_VMode);
// Extra: Numpad
addNumpad("=", KeyTable.XK_equal, KeyTable.XK_KP_Equal);
addNumpad("+", KeyTable.XK_plus, KeyTable.XK_KP_Add);
addNumpad("-", KeyTable.XK_minus, KeyTable.XK_KP_Subtract);
addNumpad("*", KeyTable.XK_asterisk, KeyTable.XK_KP_Multiply);
addNumpad("/", KeyTable.XK_slash, KeyTable.XK_KP_Divide);
addNumpad(".", KeyTable.XK_period, KeyTable.XK_KP_Decimal);
addNumpad(",", KeyTable.XK_comma, KeyTable.XK_KP_Separator);
addNumpad("0", KeyTable.XK_0, KeyTable.XK_KP_0);
addNumpad("1", KeyTable.XK_1, KeyTable.XK_KP_1);
addNumpad("2", KeyTable.XK_2, KeyTable.XK_KP_2);
addNumpad("3", KeyTable.XK_3, KeyTable.XK_KP_3);
addNumpad("4", KeyTable.XK_4, KeyTable.XK_KP_4);
addNumpad("5", KeyTable.XK_5, KeyTable.XK_KP_5);
addNumpad("6", KeyTable.XK_6, KeyTable.XK_KP_6);
addNumpad("7", KeyTable.XK_7, KeyTable.XK_KP_7);
addNumpad("8", KeyTable.XK_8, KeyTable.XK_KP_8);
addNumpad("9", KeyTable.XK_9, KeyTable.XK_KP_9);
export default DOMKeyTable;

View File

@ -0,0 +1,129 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
*/
/*
* Fallback mapping between HTML key codes (physical keys) and
* HTML key values. This only works for keys that don't vary
* between layouts. We also omit those who manage fine by mapping the
* Unicode representation.
*
* See https://www.w3.org/TR/uievents-code/ for possible codes.
* See https://www.w3.org/TR/uievents-key/ for possible values.
*/
/* eslint-disable key-spacing */
export default {
// 3.1.1.1. Writing System Keys
'Backspace': 'Backspace',
// 3.1.1.2. Functional Keys
'AltLeft': 'Alt',
'AltRight': 'Alt', // This could also be 'AltGraph'
'CapsLock': 'CapsLock',
'ContextMenu': 'ContextMenu',
'ControlLeft': 'Control',
'ControlRight': 'Control',
'Enter': 'Enter',
'MetaLeft': 'Meta',
'MetaRight': 'Meta',
'ShiftLeft': 'Shift',
'ShiftRight': 'Shift',
'Tab': 'Tab',
// FIXME: Japanese/Korean keys
// 3.1.2. Control Pad Section
'Delete': 'Delete',
'End': 'End',
'Help': 'Help',
'Home': 'Home',
'Insert': 'Insert',
'PageDown': 'PageDown',
'PageUp': 'PageUp',
// 3.1.3. Arrow Pad Section
'ArrowDown': 'ArrowDown',
'ArrowLeft': 'ArrowLeft',
'ArrowRight': 'ArrowRight',
'ArrowUp': 'ArrowUp',
// 3.1.4. Numpad Section
'NumLock': 'NumLock',
'NumpadBackspace': 'Backspace',
'NumpadClear': 'Clear',
// 3.1.5. Function Section
'Escape': 'Escape',
'F1': 'F1',
'F2': 'F2',
'F3': 'F3',
'F4': 'F4',
'F5': 'F5',
'F6': 'F6',
'F7': 'F7',
'F8': 'F8',
'F9': 'F9',
'F10': 'F10',
'F11': 'F11',
'F12': 'F12',
'F13': 'F13',
'F14': 'F14',
'F15': 'F15',
'F16': 'F16',
'F17': 'F17',
'F18': 'F18',
'F19': 'F19',
'F20': 'F20',
'F21': 'F21',
'F22': 'F22',
'F23': 'F23',
'F24': 'F24',
'F25': 'F25',
'F26': 'F26',
'F27': 'F27',
'F28': 'F28',
'F29': 'F29',
'F30': 'F30',
'F31': 'F31',
'F32': 'F32',
'F33': 'F33',
'F34': 'F34',
'F35': 'F35',
'PrintScreen': 'PrintScreen',
'ScrollLock': 'ScrollLock',
'Pause': 'Pause',
// 3.1.6. Media Keys
'BrowserBack': 'BrowserBack',
'BrowserFavorites': 'BrowserFavorites',
'BrowserForward': 'BrowserForward',
'BrowserHome': 'BrowserHome',
'BrowserRefresh': 'BrowserRefresh',
'BrowserSearch': 'BrowserSearch',
'BrowserStop': 'BrowserStop',
'Eject': 'Eject',
'LaunchApp1': 'LaunchMyComputer',
'LaunchApp2': 'LaunchCalendar',
'LaunchMail': 'LaunchMail',
'MediaPlayPause': 'MediaPlay',
'MediaStop': 'MediaStop',
'MediaTrackNext': 'MediaTrackNext',
'MediaTrackPrevious': 'MediaTrackPrevious',
'Power': 'Power',
'Sleep': 'Sleep',
'AudioVolumeDown': 'AudioVolumeDown',
'AudioVolumeMute': 'AudioVolumeMute',
'AudioVolumeUp': 'AudioVolumeUp',
'WakeUp': 'WakeUp',
};

View File

@ -0,0 +1,567 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2020 The noVNC Authors
* Licensed under MPL 2.0 (see LICENSE.txt)
*
* See README.md for usage and integration instructions.
*
*/
const GH_NOGESTURE = 0;
const GH_ONETAP = 1;
const GH_TWOTAP = 2;
const GH_THREETAP = 4;
const GH_DRAG = 8;
const GH_LONGPRESS = 16;
const GH_TWODRAG = 32;
const GH_PINCH = 64;
const GH_INITSTATE = 127;
const GH_MOVE_THRESHOLD = 50;
const GH_ANGLE_THRESHOLD = 90; // Degrees
// Timeout when waiting for gestures (ms)
const GH_MULTITOUCH_TIMEOUT = 250;
// Maximum time between press and release for a tap (ms)
const GH_TAP_TIMEOUT = 1000;
// Timeout when waiting for longpress (ms)
const GH_LONGPRESS_TIMEOUT = 1000;
// Timeout when waiting to decide between PINCH and TWODRAG (ms)
const GH_TWOTOUCH_TIMEOUT = 50;
export default class GestureHandler {
constructor() {
this._target = null;
this._state = GH_INITSTATE;
this._tracked = [];
this._ignored = [];
this._waitingRelease = false;
this._releaseStart = 0.0;
this._longpressTimeoutId = null;
this._twoTouchTimeoutId = null;
this._boundEventHandler = this._eventHandler.bind(this);
}
attach(target) {
this.detach();
this._target = target;
this._target.addEventListener('touchstart',
this._boundEventHandler);
this._target.addEventListener('touchmove',
this._boundEventHandler);
this._target.addEventListener('touchend',
this._boundEventHandler);
this._target.addEventListener('touchcancel',
this._boundEventHandler);
}
detach() {
if (!this._target) {
return;
}
this._stopLongpressTimeout();
this._stopTwoTouchTimeout();
this._target.removeEventListener('touchstart',
this._boundEventHandler);
this._target.removeEventListener('touchmove',
this._boundEventHandler);
this._target.removeEventListener('touchend',
this._boundEventHandler);
this._target.removeEventListener('touchcancel',
this._boundEventHandler);
this._target = null;
}
_eventHandler(e) {
let fn;
e.stopPropagation();
e.preventDefault();
switch (e.type) {
case 'touchstart':
fn = this._touchStart;
break;
case 'touchmove':
fn = this._touchMove;
break;
case 'touchend':
case 'touchcancel':
fn = this._touchEnd;
break;
}
for (let i = 0; i < e.changedTouches.length; i++) {
let touch = e.changedTouches[i];
fn.call(this, touch.identifier, touch.clientX, touch.clientY);
}
}
_touchStart(id, x, y) {
// Ignore any new touches if there is already an active gesture,
// or we're in a cleanup state
if (this._hasDetectedGesture() || (this._state === GH_NOGESTURE)) {
this._ignored.push(id);
return;
}
// Did it take too long between touches that we should no longer
// consider this a single gesture?
if ((this._tracked.length > 0) &&
((Date.now() - this._tracked[0].started) > GH_MULTITOUCH_TIMEOUT)) {
this._state = GH_NOGESTURE;
this._ignored.push(id);
return;
}
// If we're waiting for fingers to release then we should no longer
// recognize new touches
if (this._waitingRelease) {
this._state = GH_NOGESTURE;
this._ignored.push(id);
return;
}
this._tracked.push({
id: id,
started: Date.now(),
active: true,
firstX: x,
firstY: y,
lastX: x,
lastY: y,
angle: 0
});
switch (this._tracked.length) {
case 1:
this._startLongpressTimeout();
break;
case 2:
this._state &= ~(GH_ONETAP | GH_DRAG | GH_LONGPRESS);
this._stopLongpressTimeout();
break;
case 3:
this._state &= ~(GH_TWOTAP | GH_TWODRAG | GH_PINCH);
break;
default:
this._state = GH_NOGESTURE;
}
}
_touchMove(id, x, y) {
let touch = this._tracked.find(t => t.id === id);
// If this is an update for a touch we're not tracking, ignore it
if (touch === undefined) {
return;
}
// Update the touches last position with the event coordinates
touch.lastX = x;
touch.lastY = y;
let deltaX = x - touch.firstX;
let deltaY = y - touch.firstY;
// Update angle when the touch has moved
if ((touch.firstX !== touch.lastX) ||
(touch.firstY !== touch.lastY)) {
touch.angle = Math.atan2(deltaY, deltaX) * 180 / Math.PI;
}
if (!this._hasDetectedGesture()) {
// Ignore moves smaller than the minimum threshold
if (Math.hypot(deltaX, deltaY) < GH_MOVE_THRESHOLD) {
return;
}
// Can't be a tap or long press as we've seen movement
this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS);
this._stopLongpressTimeout();
if (this._tracked.length !== 1) {
this._state &= ~(GH_DRAG);
}
if (this._tracked.length !== 2) {
this._state &= ~(GH_TWODRAG | GH_PINCH);
}
// We need to figure out which of our different two touch gestures
// this might be
if (this._tracked.length === 2) {
// The other touch is the one where the id doesn't match
let prevTouch = this._tracked.find(t => t.id !== id);
// How far the previous touch point has moved since start
let prevDeltaMove = Math.hypot(prevTouch.firstX - prevTouch.lastX,
prevTouch.firstY - prevTouch.lastY);
// We know that the current touch moved far enough,
// but unless both touches moved further than their
// threshold we don't want to disqualify any gestures
if (prevDeltaMove > GH_MOVE_THRESHOLD) {
// The angle difference between the direction of the touch points
let deltaAngle = Math.abs(touch.angle - prevTouch.angle);
deltaAngle = Math.abs(((deltaAngle + 180) % 360) - 180);
// PINCH or TWODRAG can be eliminated depending on the angle
if (deltaAngle > GH_ANGLE_THRESHOLD) {
this._state &= ~GH_TWODRAG;
} else {
this._state &= ~GH_PINCH;
}
if (this._isTwoTouchTimeoutRunning()) {
this._stopTwoTouchTimeout();
}
} else if (!this._isTwoTouchTimeoutRunning()) {
// We can't determine the gesture right now, let's
// wait and see if more events are on their way
this._startTwoTouchTimeout();
}
}
if (!this._hasDetectedGesture()) {
return;
}
this._pushEvent('gesturestart');
}
this._pushEvent('gesturemove');
}
_touchEnd(id, x, y) {
// Check if this is an ignored touch
if (this._ignored.indexOf(id) !== -1) {
// Remove this touch from ignored
this._ignored.splice(this._ignored.indexOf(id), 1);
// And reset the state if there are no more touches
if ((this._ignored.length === 0) &&
(this._tracked.length === 0)) {
this._state = GH_INITSTATE;
this._waitingRelease = false;
}
return;
}
// We got a touchend before the timer triggered,
// this cannot result in a gesture anymore.
if (!this._hasDetectedGesture() &&
this._isTwoTouchTimeoutRunning()) {
this._stopTwoTouchTimeout();
this._state = GH_NOGESTURE;
}
// Some gestures don't trigger until a touch is released
if (!this._hasDetectedGesture()) {
// Can't be a gesture that relies on movement
this._state &= ~(GH_DRAG | GH_TWODRAG | GH_PINCH);
// Or something that relies on more time
this._state &= ~GH_LONGPRESS;
this._stopLongpressTimeout();
if (!this._waitingRelease) {
this._releaseStart = Date.now();
this._waitingRelease = true;
// Can't be a tap that requires more touches than we current have
switch (this._tracked.length) {
case 1:
this._state &= ~(GH_TWOTAP | GH_THREETAP);
break;
case 2:
this._state &= ~(GH_ONETAP | GH_THREETAP);
break;
}
}
}
// Waiting for all touches to release? (i.e. some tap)
if (this._waitingRelease) {
// Were all touches released at roughly the same time?
if ((Date.now() - this._releaseStart) > GH_MULTITOUCH_TIMEOUT) {
this._state = GH_NOGESTURE;
}
// Did too long time pass between press and release?
if (this._tracked.some(t => (Date.now() - t.started) > GH_TAP_TIMEOUT)) {
this._state = GH_NOGESTURE;
}
let touch = this._tracked.find(t => t.id === id);
touch.active = false;
// Are we still waiting for more releases?
if (this._hasDetectedGesture()) {
this._pushEvent('gesturestart');
} else {
// Have we reached a dead end?
if (this._state !== GH_NOGESTURE) {
return;
}
}
}
if (this._hasDetectedGesture()) {
this._pushEvent('gestureend');
}
// Ignore any remaining touches until they are ended
for (let i = 0; i < this._tracked.length; i++) {
if (this._tracked[i].active) {
this._ignored.push(this._tracked[i].id);
}
}
this._tracked = [];
this._state = GH_NOGESTURE;
// Remove this touch from ignored if it's in there
if (this._ignored.indexOf(id) !== -1) {
this._ignored.splice(this._ignored.indexOf(id), 1);
}
// We reset the state if ignored is empty
if ((this._ignored.length === 0)) {
this._state = GH_INITSTATE;
this._waitingRelease = false;
}
}
_hasDetectedGesture() {
if (this._state === GH_NOGESTURE) {
return false;
}
// Check to see if the bitmask value is a power of 2
// (i.e. only one bit set). If it is, we have a state.
if (this._state & (this._state - 1)) {
return false;
}
// For taps we also need to have all touches released
// before we've fully detected the gesture
if (this._state & (GH_ONETAP | GH_TWOTAP | GH_THREETAP)) {
if (this._tracked.some(t => t.active)) {
return false;
}
}
return true;
}
_startLongpressTimeout() {
this._stopLongpressTimeout();
this._longpressTimeoutId = setTimeout(() => this._longpressTimeout(),
GH_LONGPRESS_TIMEOUT);
}
_stopLongpressTimeout() {
clearTimeout(this._longpressTimeoutId);
this._longpressTimeoutId = null;
}
_longpressTimeout() {
if (this._hasDetectedGesture()) {
throw new Error("A longpress gesture failed, conflict with a different gesture");
}
this._state = GH_LONGPRESS;
this._pushEvent('gesturestart');
}
_startTwoTouchTimeout() {
this._stopTwoTouchTimeout();
this._twoTouchTimeoutId = setTimeout(() => this._twoTouchTimeout(),
GH_TWOTOUCH_TIMEOUT);
}
_stopTwoTouchTimeout() {
clearTimeout(this._twoTouchTimeoutId);
this._twoTouchTimeoutId = null;
}
_isTwoTouchTimeoutRunning() {
return this._twoTouchTimeoutId !== null;
}
_twoTouchTimeout() {
if (this._tracked.length === 0) {
throw new Error("A pinch or two drag gesture failed, no tracked touches");
}
// How far each touch point has moved since start
let avgM = this._getAverageMovement();
let avgMoveH = Math.abs(avgM.x);
let avgMoveV = Math.abs(avgM.y);
// The difference in the distance between where
// the touch points started and where they are now
let avgD = this._getAverageDistance();
let deltaTouchDistance = Math.abs(Math.hypot(avgD.first.x, avgD.first.y) -
Math.hypot(avgD.last.x, avgD.last.y));
if ((avgMoveV < deltaTouchDistance) &&
(avgMoveH < deltaTouchDistance)) {
this._state = GH_PINCH;
} else {
this._state = GH_TWODRAG;
}
this._pushEvent('gesturestart');
this._pushEvent('gesturemove');
}
_pushEvent(type) {
let detail = { type: this._stateToGesture(this._state) };
// For most gesture events the current (average) position is the
// most useful
let avg = this._getPosition();
let pos = avg.last;
// However we have a slight distance to detect gestures, so for the
// first gesture event we want to use the first positions we saw
if (type === 'gesturestart') {
pos = avg.first;
}
// For these gestures, we always want the event coordinates
// to be where the gesture began, not the current touch location.
switch (this._state) {
case GH_TWODRAG:
case GH_PINCH:
pos = avg.first;
break;
}
detail['clientX'] = pos.x;
detail['clientY'] = pos.y;
// FIXME: other coordinates?
// Some gestures also have a magnitude
if (this._state === GH_PINCH) {
let distance = this._getAverageDistance();
if (type === 'gesturestart') {
detail['magnitudeX'] = distance.first.x;
detail['magnitudeY'] = distance.first.y;
} else {
detail['magnitudeX'] = distance.last.x;
detail['magnitudeY'] = distance.last.y;
}
} else if (this._state === GH_TWODRAG) {
if (type === 'gesturestart') {
detail['magnitudeX'] = 0.0;
detail['magnitudeY'] = 0.0;
} else {
let movement = this._getAverageMovement();
detail['magnitudeX'] = movement.x;
detail['magnitudeY'] = movement.y;
}
}
let gev = new CustomEvent(type, { detail: detail });
this._target.dispatchEvent(gev);
}
_stateToGesture(state) {
switch (state) {
case GH_ONETAP:
return 'onetap';
case GH_TWOTAP:
return 'twotap';
case GH_THREETAP:
return 'threetap';
case GH_DRAG:
return 'drag';
case GH_LONGPRESS:
return 'longpress';
case GH_TWODRAG:
return 'twodrag';
case GH_PINCH:
return 'pinch';
}
throw new Error("Unknown gesture state: " + state);
}
_getPosition() {
if (this._tracked.length === 0) {
throw new Error("Failed to get gesture position, no tracked touches");
}
let size = this._tracked.length;
let fx = 0, fy = 0, lx = 0, ly = 0;
for (let i = 0; i < this._tracked.length; i++) {
fx += this._tracked[i].firstX;
fy += this._tracked[i].firstY;
lx += this._tracked[i].lastX;
ly += this._tracked[i].lastY;
}
return { first: { x: fx / size,
y: fy / size },
last: { x: lx / size,
y: ly / size } };
}
_getAverageMovement() {
if (this._tracked.length === 0) {
throw new Error("Failed to get gesture movement, no tracked touches");
}
let totalH, totalV;
totalH = totalV = 0;
let size = this._tracked.length;
for (let i = 0; i < this._tracked.length; i++) {
totalH += this._tracked[i].lastX - this._tracked[i].firstX;
totalV += this._tracked[i].lastY - this._tracked[i].firstY;
}
return { x: totalH / size,
y: totalV / size };
}
_getAverageDistance() {
if (this._tracked.length === 0) {
throw new Error("Failed to get gesture distance, no tracked touches");
}
// Distance between the first and last tracked touches
let first = this._tracked[0];
let last = this._tracked[this._tracked.length - 1];
let fdx = Math.abs(last.firstX - first.firstX);
let fdy = Math.abs(last.firstY - first.firstY);
let ldx = Math.abs(last.lastX - first.lastX);
let ldy = Math.abs(last.lastY - first.lastY);
return { first: { x: fdx, y: fdy },
last: { x: ldx, y: ldy } };
}
}

View File

@ -0,0 +1,273 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2019 The noVNC Authors
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
*/
import * as Log from '../util/logging.js';
import { stopEvent } from '../util/events.js';
import * as KeyboardUtil from "./util.js";
import KeyTable from "./keysym.js";
import * as browser from "../util/browser.js";
//
// Keyboard event handler
//
export default class Keyboard {
constructor(target) {
this._target = target || null;
this._keyDownList = {}; // List of depressed keys
// (even if they are happy)
this._altGrArmed = false; // Windows AltGr detection
// keep these here so we can refer to them later
this._eventHandlers = {
'keyup': this._handleKeyUp.bind(this),
'keydown': this._handleKeyDown.bind(this),
'blur': this._allKeysUp.bind(this),
};
// ===== EVENT HANDLERS =====
this.onkeyevent = () => {}; // Handler for key press/release
}
// ===== PRIVATE METHODS =====
_sendKeyEvent(keysym, code, down) {
if (down) {
this._keyDownList[code] = keysym;
} else {
// Do we really think this key is down?
if (!(code in this._keyDownList)) {
return;
}
delete this._keyDownList[code];
}
Log.Debug("onkeyevent " + (down ? "down" : "up") +
", keysym: " + keysym, ", code: " + code);
this.onkeyevent(keysym, code, down);
}
_getKeyCode(e) {
const code = KeyboardUtil.getKeycode(e);
if (code !== 'Unidentified') {
return code;
}
// Unstable, but we don't have anything else to go on
if (e.keyCode) {
// 229 is used for composition events
if (e.keyCode !== 229) {
return 'Platform' + e.keyCode;
}
}
// A precursor to the final DOM3 standard. Unfortunately it
// is not layout independent, so it is as bad as using keyCode
if (e.keyIdentifier) {
// Non-character key?
if (e.keyIdentifier.substr(0, 2) !== 'U+') {
return e.keyIdentifier;
}
const codepoint = parseInt(e.keyIdentifier.substr(2), 16);
const char = String.fromCharCode(codepoint).toUpperCase();
return 'Platform' + char.charCodeAt();
}
return 'Unidentified';
}
_handleKeyDown(e) {
const code = this._getKeyCode(e);
let keysym = KeyboardUtil.getKeysym(e);
// Windows doesn't have a proper AltGr, but handles it using
// fake Ctrl+Alt. However the remote end might not be Windows,
// so we need to merge those in to a single AltGr event. We
// detect this case by seeing the two key events directly after
// each other with a very short time between them (<50ms).
if (this._altGrArmed) {
this._altGrArmed = false;
clearTimeout(this._altGrTimeout);
if ((code === "AltRight") &&
((e.timeStamp - this._altGrCtrlTime) < 50)) {
// FIXME: We fail to detect this if either Ctrl key is
// first manually pressed as Windows then no
// longer sends the fake Ctrl down event. It
// does however happily send real Ctrl events
// even when AltGr is already down. Some
// browsers detect this for us though and set the
// key to "AltGraph".
keysym = KeyTable.XK_ISO_Level3_Shift;
} else {
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
}
}
// We cannot handle keys we cannot track, but we also need
// to deal with virtual keyboards which omit key info
if (code === 'Unidentified') {
if (keysym) {
// If it's a virtual keyboard then it should be
// sufficient to just send press and release right
// after each other
this._sendKeyEvent(keysym, code, true);
this._sendKeyEvent(keysym, code, false);
}
stopEvent(e);
return;
}
// Alt behaves more like AltGraph on macOS, so shuffle the
// keys around a bit to make things more sane for the remote
// server. This method is used by RealVNC and TigerVNC (and
// possibly others).
if (browser.isMac() || browser.isIOS()) {
switch (keysym) {
case KeyTable.XK_Super_L:
keysym = KeyTable.XK_Alt_L;
break;
case KeyTable.XK_Super_R:
keysym = KeyTable.XK_Super_L;
break;
case KeyTable.XK_Alt_L:
keysym = KeyTable.XK_Mode_switch;
break;
case KeyTable.XK_Alt_R:
keysym = KeyTable.XK_ISO_Level3_Shift;
break;
}
}
// Is this key already pressed? If so, then we must use the
// same keysym or we'll confuse the server
if (code in this._keyDownList) {
keysym = this._keyDownList[code];
}
// macOS doesn't send proper key events for modifiers, only
// state change events. That gets extra confusing for CapsLock
// which toggles on each press, but not on release. So pretend
// it was a quick press and release of the button.
if ((browser.isMac() || browser.isIOS()) && (code === 'CapsLock')) {
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', true);
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', false);
stopEvent(e);
return;
}
// Windows doesn't send proper key releases for a bunch of
// Japanese IM keys so we have to fake the release right away
const jpBadKeys = [ KeyTable.XK_Zenkaku_Hankaku,
KeyTable.XK_Eisu_toggle,
KeyTable.XK_Katakana,
KeyTable.XK_Hiragana,
KeyTable.XK_Romaji ];
if (browser.isWindows() && jpBadKeys.includes(keysym)) {
this._sendKeyEvent(keysym, code, true);
this._sendKeyEvent(keysym, code, false);
stopEvent(e);
return;
}
stopEvent(e);
// Possible start of AltGr sequence? (see above)
if ((code === "ControlLeft") && browser.isWindows() &&
!("ControlLeft" in this._keyDownList)) {
this._altGrArmed = true;
this._altGrTimeout = setTimeout(this._handleAltGrTimeout.bind(this), 100);
this._altGrCtrlTime = e.timeStamp;
return;
}
this._sendKeyEvent(keysym, code, true);
}
_handleKeyUp(e) {
stopEvent(e);
const code = this._getKeyCode(e);
// We can't get a release in the middle of an AltGr sequence, so
// abort that detection
if (this._altGrArmed) {
this._altGrArmed = false;
clearTimeout(this._altGrTimeout);
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
}
// See comment in _handleKeyDown()
if ((browser.isMac() || browser.isIOS()) && (code === 'CapsLock')) {
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', true);
this._sendKeyEvent(KeyTable.XK_Caps_Lock, 'CapsLock', false);
return;
}
this._sendKeyEvent(this._keyDownList[code], code, false);
// Windows has a rather nasty bug where it won't send key
// release events for a Shift button if the other Shift is still
// pressed
if (browser.isWindows() && ((code === 'ShiftLeft') ||
(code === 'ShiftRight'))) {
if ('ShiftRight' in this._keyDownList) {
this._sendKeyEvent(this._keyDownList['ShiftRight'],
'ShiftRight', false);
}
if ('ShiftLeft' in this._keyDownList) {
this._sendKeyEvent(this._keyDownList['ShiftLeft'],
'ShiftLeft', false);
}
}
}
_handleAltGrTimeout() {
this._altGrArmed = false;
clearTimeout(this._altGrTimeout);
this._sendKeyEvent(KeyTable.XK_Control_L, "ControlLeft", true);
}
_allKeysUp() {
Log.Debug(">> Keyboard.allKeysUp");
for (let code in this._keyDownList) {
this._sendKeyEvent(this._keyDownList[code], code, false);
}
Log.Debug("<< Keyboard.allKeysUp");
}
// ===== PUBLIC METHODS =====
grab() {
//Log.Debug(">> Keyboard.grab");
this._target.addEventListener('keydown', this._eventHandlers.keydown);
this._target.addEventListener('keyup', this._eventHandlers.keyup);
// Release (key up) if window loses focus
window.addEventListener('blur', this._eventHandlers.blur);
//Log.Debug("<< Keyboard.grab");
}
ungrab() {
//Log.Debug(">> Keyboard.ungrab");
this._target.removeEventListener('keydown', this._eventHandlers.keydown);
this._target.removeEventListener('keyup', this._eventHandlers.keyup);
window.removeEventListener('blur', this._eventHandlers.blur);
// Release (key up) all keys that are in a down state
this._allKeysUp();
//Log.Debug(">> Keyboard.ungrab");
}
}

View File

@ -0,0 +1,616 @@
/* eslint-disable key-spacing */
export default {
XK_VoidSymbol: 0xffffff, /* Void symbol */
XK_BackSpace: 0xff08, /* Back space, back char */
XK_Tab: 0xff09,
XK_Linefeed: 0xff0a, /* Linefeed, LF */
XK_Clear: 0xff0b,
XK_Return: 0xff0d, /* Return, enter */
XK_Pause: 0xff13, /* Pause, hold */
XK_Scroll_Lock: 0xff14,
XK_Sys_Req: 0xff15,
XK_Escape: 0xff1b,
XK_Delete: 0xffff, /* Delete, rubout */
/* International & multi-key character composition */
XK_Multi_key: 0xff20, /* Multi-key character compose */
XK_Codeinput: 0xff37,
XK_SingleCandidate: 0xff3c,
XK_MultipleCandidate: 0xff3d,
XK_PreviousCandidate: 0xff3e,
/* Japanese keyboard support */
XK_Kanji: 0xff21, /* Kanji, Kanji convert */
XK_Muhenkan: 0xff22, /* Cancel Conversion */
XK_Henkan_Mode: 0xff23, /* Start/Stop Conversion */
XK_Henkan: 0xff23, /* Alias for Henkan_Mode */
XK_Romaji: 0xff24, /* to Romaji */
XK_Hiragana: 0xff25, /* to Hiragana */
XK_Katakana: 0xff26, /* to Katakana */
XK_Hiragana_Katakana: 0xff27, /* Hiragana/Katakana toggle */
XK_Zenkaku: 0xff28, /* to Zenkaku */
XK_Hankaku: 0xff29, /* to Hankaku */
XK_Zenkaku_Hankaku: 0xff2a, /* Zenkaku/Hankaku toggle */
XK_Touroku: 0xff2b, /* Add to Dictionary */
XK_Massyo: 0xff2c, /* Delete from Dictionary */
XK_Kana_Lock: 0xff2d, /* Kana Lock */
XK_Kana_Shift: 0xff2e, /* Kana Shift */
XK_Eisu_Shift: 0xff2f, /* Alphanumeric Shift */
XK_Eisu_toggle: 0xff30, /* Alphanumeric toggle */
XK_Kanji_Bangou: 0xff37, /* Codeinput */
XK_Zen_Koho: 0xff3d, /* Multiple/All Candidate(s) */
XK_Mae_Koho: 0xff3e, /* Previous Candidate */
/* Cursor control & motion */
XK_Home: 0xff50,
XK_Left: 0xff51, /* Move left, left arrow */
XK_Up: 0xff52, /* Move up, up arrow */
XK_Right: 0xff53, /* Move right, right arrow */
XK_Down: 0xff54, /* Move down, down arrow */
XK_Prior: 0xff55, /* Prior, previous */
XK_Page_Up: 0xff55,
XK_Next: 0xff56, /* Next */
XK_Page_Down: 0xff56,
XK_End: 0xff57, /* EOL */
XK_Begin: 0xff58, /* BOL */
/* Misc functions */
XK_Select: 0xff60, /* Select, mark */
XK_Print: 0xff61,
XK_Execute: 0xff62, /* Execute, run, do */
XK_Insert: 0xff63, /* Insert, insert here */
XK_Undo: 0xff65,
XK_Redo: 0xff66, /* Redo, again */
XK_Menu: 0xff67,
XK_Find: 0xff68, /* Find, search */
XK_Cancel: 0xff69, /* Cancel, stop, abort, exit */
XK_Help: 0xff6a, /* Help */
XK_Break: 0xff6b,
XK_Mode_switch: 0xff7e, /* Character set switch */
XK_script_switch: 0xff7e, /* Alias for mode_switch */
XK_Num_Lock: 0xff7f,
/* Keypad functions, keypad numbers cleverly chosen to map to ASCII */
XK_KP_Space: 0xff80, /* Space */
XK_KP_Tab: 0xff89,
XK_KP_Enter: 0xff8d, /* Enter */
XK_KP_F1: 0xff91, /* PF1, KP_A, ... */
XK_KP_F2: 0xff92,
XK_KP_F3: 0xff93,
XK_KP_F4: 0xff94,
XK_KP_Home: 0xff95,
XK_KP_Left: 0xff96,
XK_KP_Up: 0xff97,
XK_KP_Right: 0xff98,
XK_KP_Down: 0xff99,
XK_KP_Prior: 0xff9a,
XK_KP_Page_Up: 0xff9a,
XK_KP_Next: 0xff9b,
XK_KP_Page_Down: 0xff9b,
XK_KP_End: 0xff9c,
XK_KP_Begin: 0xff9d,
XK_KP_Insert: 0xff9e,
XK_KP_Delete: 0xff9f,
XK_KP_Equal: 0xffbd, /* Equals */
XK_KP_Multiply: 0xffaa,
XK_KP_Add: 0xffab,
XK_KP_Separator: 0xffac, /* Separator, often comma */
XK_KP_Subtract: 0xffad,
XK_KP_Decimal: 0xffae,
XK_KP_Divide: 0xffaf,
XK_KP_0: 0xffb0,
XK_KP_1: 0xffb1,
XK_KP_2: 0xffb2,
XK_KP_3: 0xffb3,
XK_KP_4: 0xffb4,
XK_KP_5: 0xffb5,
XK_KP_6: 0xffb6,
XK_KP_7: 0xffb7,
XK_KP_8: 0xffb8,
XK_KP_9: 0xffb9,
/*
* Auxiliary functions; note the duplicate definitions for left and right
* function keys; Sun keyboards and a few other manufacturers have such
* function key groups on the left and/or right sides of the keyboard.
* We've not found a keyboard with more than 35 function keys total.
*/
XK_F1: 0xffbe,
XK_F2: 0xffbf,
XK_F3: 0xffc0,
XK_F4: 0xffc1,
XK_F5: 0xffc2,
XK_F6: 0xffc3,
XK_F7: 0xffc4,
XK_F8: 0xffc5,
XK_F9: 0xffc6,
XK_F10: 0xffc7,
XK_F11: 0xffc8,
XK_L1: 0xffc8,
XK_F12: 0xffc9,
XK_L2: 0xffc9,
XK_F13: 0xffca,
XK_L3: 0xffca,
XK_F14: 0xffcb,
XK_L4: 0xffcb,
XK_F15: 0xffcc,
XK_L5: 0xffcc,
XK_F16: 0xffcd,
XK_L6: 0xffcd,
XK_F17: 0xffce,
XK_L7: 0xffce,
XK_F18: 0xffcf,
XK_L8: 0xffcf,
XK_F19: 0xffd0,
XK_L9: 0xffd0,
XK_F20: 0xffd1,
XK_L10: 0xffd1,
XK_F21: 0xffd2,
XK_R1: 0xffd2,
XK_F22: 0xffd3,
XK_R2: 0xffd3,
XK_F23: 0xffd4,
XK_R3: 0xffd4,
XK_F24: 0xffd5,
XK_R4: 0xffd5,
XK_F25: 0xffd6,
XK_R5: 0xffd6,
XK_F26: 0xffd7,
XK_R6: 0xffd7,
XK_F27: 0xffd8,
XK_R7: 0xffd8,
XK_F28: 0xffd9,
XK_R8: 0xffd9,
XK_F29: 0xffda,
XK_R9: 0xffda,
XK_F30: 0xffdb,
XK_R10: 0xffdb,
XK_F31: 0xffdc,
XK_R11: 0xffdc,
XK_F32: 0xffdd,
XK_R12: 0xffdd,
XK_F33: 0xffde,
XK_R13: 0xffde,
XK_F34: 0xffdf,
XK_R14: 0xffdf,
XK_F35: 0xffe0,
XK_R15: 0xffe0,
/* Modifiers */
XK_Shift_L: 0xffe1, /* Left shift */
XK_Shift_R: 0xffe2, /* Right shift */
XK_Control_L: 0xffe3, /* Left control */
XK_Control_R: 0xffe4, /* Right control */
XK_Caps_Lock: 0xffe5, /* Caps lock */
XK_Shift_Lock: 0xffe6, /* Shift lock */
XK_Meta_L: 0xffe7, /* Left meta */
XK_Meta_R: 0xffe8, /* Right meta */
XK_Alt_L: 0xffe9, /* Left alt */
XK_Alt_R: 0xffea, /* Right alt */
XK_Super_L: 0xffeb, /* Left super */
XK_Super_R: 0xffec, /* Right super */
XK_Hyper_L: 0xffed, /* Left hyper */
XK_Hyper_R: 0xffee, /* Right hyper */
/*
* Keyboard (XKB) Extension function and modifier keys
* (from Appendix C of "The X Keyboard Extension: Protocol Specification")
* Byte 3 = 0xfe
*/
XK_ISO_Level3_Shift: 0xfe03, /* AltGr */
XK_ISO_Next_Group: 0xfe08,
XK_ISO_Prev_Group: 0xfe0a,
XK_ISO_First_Group: 0xfe0c,
XK_ISO_Last_Group: 0xfe0e,
/*
* Latin 1
* (ISO/IEC 8859-1: Unicode U+0020..U+00FF)
* Byte 3: 0
*/
XK_space: 0x0020, /* U+0020 SPACE */
XK_exclam: 0x0021, /* U+0021 EXCLAMATION MARK */
XK_quotedbl: 0x0022, /* U+0022 QUOTATION MARK */
XK_numbersign: 0x0023, /* U+0023 NUMBER SIGN */
XK_dollar: 0x0024, /* U+0024 DOLLAR SIGN */
XK_percent: 0x0025, /* U+0025 PERCENT SIGN */
XK_ampersand: 0x0026, /* U+0026 AMPERSAND */
XK_apostrophe: 0x0027, /* U+0027 APOSTROPHE */
XK_quoteright: 0x0027, /* deprecated */
XK_parenleft: 0x0028, /* U+0028 LEFT PARENTHESIS */
XK_parenright: 0x0029, /* U+0029 RIGHT PARENTHESIS */
XK_asterisk: 0x002a, /* U+002A ASTERISK */
XK_plus: 0x002b, /* U+002B PLUS SIGN */
XK_comma: 0x002c, /* U+002C COMMA */
XK_minus: 0x002d, /* U+002D HYPHEN-MINUS */
XK_period: 0x002e, /* U+002E FULL STOP */
XK_slash: 0x002f, /* U+002F SOLIDUS */
XK_0: 0x0030, /* U+0030 DIGIT ZERO */
XK_1: 0x0031, /* U+0031 DIGIT ONE */
XK_2: 0x0032, /* U+0032 DIGIT TWO */
XK_3: 0x0033, /* U+0033 DIGIT THREE */
XK_4: 0x0034, /* U+0034 DIGIT FOUR */
XK_5: 0x0035, /* U+0035 DIGIT FIVE */
XK_6: 0x0036, /* U+0036 DIGIT SIX */
XK_7: 0x0037, /* U+0037 DIGIT SEVEN */
XK_8: 0x0038, /* U+0038 DIGIT EIGHT */
XK_9: 0x0039, /* U+0039 DIGIT NINE */
XK_colon: 0x003a, /* U+003A COLON */
XK_semicolon: 0x003b, /* U+003B SEMICOLON */
XK_less: 0x003c, /* U+003C LESS-THAN SIGN */
XK_equal: 0x003d, /* U+003D EQUALS SIGN */
XK_greater: 0x003e, /* U+003E GREATER-THAN SIGN */
XK_question: 0x003f, /* U+003F QUESTION MARK */
XK_at: 0x0040, /* U+0040 COMMERCIAL AT */
XK_A: 0x0041, /* U+0041 LATIN CAPITAL LETTER A */
XK_B: 0x0042, /* U+0042 LATIN CAPITAL LETTER B */
XK_C: 0x0043, /* U+0043 LATIN CAPITAL LETTER C */
XK_D: 0x0044, /* U+0044 LATIN CAPITAL LETTER D */
XK_E: 0x0045, /* U+0045 LATIN CAPITAL LETTER E */
XK_F: 0x0046, /* U+0046 LATIN CAPITAL LETTER F */
XK_G: 0x0047, /* U+0047 LATIN CAPITAL LETTER G */
XK_H: 0x0048, /* U+0048 LATIN CAPITAL LETTER H */
XK_I: 0x0049, /* U+0049 LATIN CAPITAL LETTER I */
XK_J: 0x004a, /* U+004A LATIN CAPITAL LETTER J */
XK_K: 0x004b, /* U+004B LATIN CAPITAL LETTER K */
XK_L: 0x004c, /* U+004C LATIN CAPITAL LETTER L */
XK_M: 0x004d, /* U+004D LATIN CAPITAL LETTER M */
XK_N: 0x004e, /* U+004E LATIN CAPITAL LETTER N */
XK_O: 0x004f, /* U+004F LATIN CAPITAL LETTER O */
XK_P: 0x0050, /* U+0050 LATIN CAPITAL LETTER P */
XK_Q: 0x0051, /* U+0051 LATIN CAPITAL LETTER Q */
XK_R: 0x0052, /* U+0052 LATIN CAPITAL LETTER R */
XK_S: 0x0053, /* U+0053 LATIN CAPITAL LETTER S */
XK_T: 0x0054, /* U+0054 LATIN CAPITAL LETTER T */
XK_U: 0x0055, /* U+0055 LATIN CAPITAL LETTER U */
XK_V: 0x0056, /* U+0056 LATIN CAPITAL LETTER V */
XK_W: 0x0057, /* U+0057 LATIN CAPITAL LETTER W */
XK_X: 0x0058, /* U+0058 LATIN CAPITAL LETTER X */
XK_Y: 0x0059, /* U+0059 LATIN CAPITAL LETTER Y */
XK_Z: 0x005a, /* U+005A LATIN CAPITAL LETTER Z */
XK_bracketleft: 0x005b, /* U+005B LEFT SQUARE BRACKET */
XK_backslash: 0x005c, /* U+005C REVERSE SOLIDUS */
XK_bracketright: 0x005d, /* U+005D RIGHT SQUARE BRACKET */
XK_asciicircum: 0x005e, /* U+005E CIRCUMFLEX ACCENT */
XK_underscore: 0x005f, /* U+005F LOW LINE */
XK_grave: 0x0060, /* U+0060 GRAVE ACCENT */
XK_quoteleft: 0x0060, /* deprecated */
XK_a: 0x0061, /* U+0061 LATIN SMALL LETTER A */
XK_b: 0x0062, /* U+0062 LATIN SMALL LETTER B */
XK_c: 0x0063, /* U+0063 LATIN SMALL LETTER C */
XK_d: 0x0064, /* U+0064 LATIN SMALL LETTER D */
XK_e: 0x0065, /* U+0065 LATIN SMALL LETTER E */
XK_f: 0x0066, /* U+0066 LATIN SMALL LETTER F */
XK_g: 0x0067, /* U+0067 LATIN SMALL LETTER G */
XK_h: 0x0068, /* U+0068 LATIN SMALL LETTER H */
XK_i: 0x0069, /* U+0069 LATIN SMALL LETTER I */
XK_j: 0x006a, /* U+006A LATIN SMALL LETTER J */
XK_k: 0x006b, /* U+006B LATIN SMALL LETTER K */
XK_l: 0x006c, /* U+006C LATIN SMALL LETTER L */
XK_m: 0x006d, /* U+006D LATIN SMALL LETTER M */
XK_n: 0x006e, /* U+006E LATIN SMALL LETTER N */
XK_o: 0x006f, /* U+006F LATIN SMALL LETTER O */
XK_p: 0x0070, /* U+0070 LATIN SMALL LETTER P */
XK_q: 0x0071, /* U+0071 LATIN SMALL LETTER Q */
XK_r: 0x0072, /* U+0072 LATIN SMALL LETTER R */
XK_s: 0x0073, /* U+0073 LATIN SMALL LETTER S */
XK_t: 0x0074, /* U+0074 LATIN SMALL LETTER T */
XK_u: 0x0075, /* U+0075 LATIN SMALL LETTER U */
XK_v: 0x0076, /* U+0076 LATIN SMALL LETTER V */
XK_w: 0x0077, /* U+0077 LATIN SMALL LETTER W */
XK_x: 0x0078, /* U+0078 LATIN SMALL LETTER X */
XK_y: 0x0079, /* U+0079 LATIN SMALL LETTER Y */
XK_z: 0x007a, /* U+007A LATIN SMALL LETTER Z */
XK_braceleft: 0x007b, /* U+007B LEFT CURLY BRACKET */
XK_bar: 0x007c, /* U+007C VERTICAL LINE */
XK_braceright: 0x007d, /* U+007D RIGHT CURLY BRACKET */
XK_asciitilde: 0x007e, /* U+007E TILDE */
XK_nobreakspace: 0x00a0, /* U+00A0 NO-BREAK SPACE */
XK_exclamdown: 0x00a1, /* U+00A1 INVERTED EXCLAMATION MARK */
XK_cent: 0x00a2, /* U+00A2 CENT SIGN */
XK_sterling: 0x00a3, /* U+00A3 POUND SIGN */
XK_currency: 0x00a4, /* U+00A4 CURRENCY SIGN */
XK_yen: 0x00a5, /* U+00A5 YEN SIGN */
XK_brokenbar: 0x00a6, /* U+00A6 BROKEN BAR */
XK_section: 0x00a7, /* U+00A7 SECTION SIGN */
XK_diaeresis: 0x00a8, /* U+00A8 DIAERESIS */
XK_copyright: 0x00a9, /* U+00A9 COPYRIGHT SIGN */
XK_ordfeminine: 0x00aa, /* U+00AA FEMININE ORDINAL INDICATOR */
XK_guillemotleft: 0x00ab, /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
XK_notsign: 0x00ac, /* U+00AC NOT SIGN */
XK_hyphen: 0x00ad, /* U+00AD SOFT HYPHEN */
XK_registered: 0x00ae, /* U+00AE REGISTERED SIGN */
XK_macron: 0x00af, /* U+00AF MACRON */
XK_degree: 0x00b0, /* U+00B0 DEGREE SIGN */
XK_plusminus: 0x00b1, /* U+00B1 PLUS-MINUS SIGN */
XK_twosuperior: 0x00b2, /* U+00B2 SUPERSCRIPT TWO */
XK_threesuperior: 0x00b3, /* U+00B3 SUPERSCRIPT THREE */
XK_acute: 0x00b4, /* U+00B4 ACUTE ACCENT */
XK_mu: 0x00b5, /* U+00B5 MICRO SIGN */
XK_paragraph: 0x00b6, /* U+00B6 PILCROW SIGN */
XK_periodcentered: 0x00b7, /* U+00B7 MIDDLE DOT */
XK_cedilla: 0x00b8, /* U+00B8 CEDILLA */
XK_onesuperior: 0x00b9, /* U+00B9 SUPERSCRIPT ONE */
XK_masculine: 0x00ba, /* U+00BA MASCULINE ORDINAL INDICATOR */
XK_guillemotright: 0x00bb, /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
XK_onequarter: 0x00bc, /* U+00BC VULGAR FRACTION ONE QUARTER */
XK_onehalf: 0x00bd, /* U+00BD VULGAR FRACTION ONE HALF */
XK_threequarters: 0x00be, /* U+00BE VULGAR FRACTION THREE QUARTERS */
XK_questiondown: 0x00bf, /* U+00BF INVERTED QUESTION MARK */
XK_Agrave: 0x00c0, /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */
XK_Aacute: 0x00c1, /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */
XK_Acircumflex: 0x00c2, /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
XK_Atilde: 0x00c3, /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */
XK_Adiaeresis: 0x00c4, /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */
XK_Aring: 0x00c5, /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */
XK_AE: 0x00c6, /* U+00C6 LATIN CAPITAL LETTER AE */
XK_Ccedilla: 0x00c7, /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */
XK_Egrave: 0x00c8, /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */
XK_Eacute: 0x00c9, /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */
XK_Ecircumflex: 0x00ca, /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
XK_Ediaeresis: 0x00cb, /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */
XK_Igrave: 0x00cc, /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */
XK_Iacute: 0x00cd, /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */
XK_Icircumflex: 0x00ce, /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
XK_Idiaeresis: 0x00cf, /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */
XK_ETH: 0x00d0, /* U+00D0 LATIN CAPITAL LETTER ETH */
XK_Eth: 0x00d0, /* deprecated */
XK_Ntilde: 0x00d1, /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */
XK_Ograve: 0x00d2, /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */
XK_Oacute: 0x00d3, /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */
XK_Ocircumflex: 0x00d4, /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
XK_Otilde: 0x00d5, /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */
XK_Odiaeresis: 0x00d6, /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */
XK_multiply: 0x00d7, /* U+00D7 MULTIPLICATION SIGN */
XK_Oslash: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
XK_Ooblique: 0x00d8, /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */
XK_Ugrave: 0x00d9, /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */
XK_Uacute: 0x00da, /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */
XK_Ucircumflex: 0x00db, /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
XK_Udiaeresis: 0x00dc, /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */
XK_Yacute: 0x00dd, /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */
XK_THORN: 0x00de, /* U+00DE LATIN CAPITAL LETTER THORN */
XK_Thorn: 0x00de, /* deprecated */
XK_ssharp: 0x00df, /* U+00DF LATIN SMALL LETTER SHARP S */
XK_agrave: 0x00e0, /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */
XK_aacute: 0x00e1, /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */
XK_acircumflex: 0x00e2, /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */
XK_atilde: 0x00e3, /* U+00E3 LATIN SMALL LETTER A WITH TILDE */
XK_adiaeresis: 0x00e4, /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */
XK_aring: 0x00e5, /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */
XK_ae: 0x00e6, /* U+00E6 LATIN SMALL LETTER AE */
XK_ccedilla: 0x00e7, /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */
XK_egrave: 0x00e8, /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */
XK_eacute: 0x00e9, /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */
XK_ecircumflex: 0x00ea, /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */
XK_ediaeresis: 0x00eb, /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */
XK_igrave: 0x00ec, /* U+00EC LATIN SMALL LETTER I WITH GRAVE */
XK_iacute: 0x00ed, /* U+00ED LATIN SMALL LETTER I WITH ACUTE */
XK_icircumflex: 0x00ee, /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */
XK_idiaeresis: 0x00ef, /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */
XK_eth: 0x00f0, /* U+00F0 LATIN SMALL LETTER ETH */
XK_ntilde: 0x00f1, /* U+00F1 LATIN SMALL LETTER N WITH TILDE */
XK_ograve: 0x00f2, /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */
XK_oacute: 0x00f3, /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */
XK_ocircumflex: 0x00f4, /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */
XK_otilde: 0x00f5, /* U+00F5 LATIN SMALL LETTER O WITH TILDE */
XK_odiaeresis: 0x00f6, /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */
XK_division: 0x00f7, /* U+00F7 DIVISION SIGN */
XK_oslash: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
XK_ooblique: 0x00f8, /* U+00F8 LATIN SMALL LETTER O WITH STROKE */
XK_ugrave: 0x00f9, /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */
XK_uacute: 0x00fa, /* U+00FA LATIN SMALL LETTER U WITH ACUTE */
XK_ucircumflex: 0x00fb, /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */
XK_udiaeresis: 0x00fc, /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */
XK_yacute: 0x00fd, /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */
XK_thorn: 0x00fe, /* U+00FE LATIN SMALL LETTER THORN */
XK_ydiaeresis: 0x00ff, /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */
/*
* Korean
* Byte 3 = 0x0e
*/
XK_Hangul: 0xff31, /* Hangul start/stop(toggle) */
XK_Hangul_Hanja: 0xff34, /* Start Hangul->Hanja Conversion */
XK_Hangul_Jeonja: 0xff38, /* Jeonja mode */
/*
* XFree86 vendor specific keysyms.
*
* The XFree86 keysym range is 0x10080001 - 0x1008FFFF.
*/
XF86XK_ModeLock: 0x1008FF01,
XF86XK_MonBrightnessUp: 0x1008FF02,
XF86XK_MonBrightnessDown: 0x1008FF03,
XF86XK_KbdLightOnOff: 0x1008FF04,
XF86XK_KbdBrightnessUp: 0x1008FF05,
XF86XK_KbdBrightnessDown: 0x1008FF06,
XF86XK_Standby: 0x1008FF10,
XF86XK_AudioLowerVolume: 0x1008FF11,
XF86XK_AudioMute: 0x1008FF12,
XF86XK_AudioRaiseVolume: 0x1008FF13,
XF86XK_AudioPlay: 0x1008FF14,
XF86XK_AudioStop: 0x1008FF15,
XF86XK_AudioPrev: 0x1008FF16,
XF86XK_AudioNext: 0x1008FF17,
XF86XK_HomePage: 0x1008FF18,
XF86XK_Mail: 0x1008FF19,
XF86XK_Start: 0x1008FF1A,
XF86XK_Search: 0x1008FF1B,
XF86XK_AudioRecord: 0x1008FF1C,
XF86XK_Calculator: 0x1008FF1D,
XF86XK_Memo: 0x1008FF1E,
XF86XK_ToDoList: 0x1008FF1F,
XF86XK_Calendar: 0x1008FF20,
XF86XK_PowerDown: 0x1008FF21,
XF86XK_ContrastAdjust: 0x1008FF22,
XF86XK_RockerUp: 0x1008FF23,
XF86XK_RockerDown: 0x1008FF24,
XF86XK_RockerEnter: 0x1008FF25,
XF86XK_Back: 0x1008FF26,
XF86XK_Forward: 0x1008FF27,
XF86XK_Stop: 0x1008FF28,
XF86XK_Refresh: 0x1008FF29,
XF86XK_PowerOff: 0x1008FF2A,
XF86XK_WakeUp: 0x1008FF2B,
XF86XK_Eject: 0x1008FF2C,
XF86XK_ScreenSaver: 0x1008FF2D,
XF86XK_WWW: 0x1008FF2E,
XF86XK_Sleep: 0x1008FF2F,
XF86XK_Favorites: 0x1008FF30,
XF86XK_AudioPause: 0x1008FF31,
XF86XK_AudioMedia: 0x1008FF32,
XF86XK_MyComputer: 0x1008FF33,
XF86XK_VendorHome: 0x1008FF34,
XF86XK_LightBulb: 0x1008FF35,
XF86XK_Shop: 0x1008FF36,
XF86XK_History: 0x1008FF37,
XF86XK_OpenURL: 0x1008FF38,
XF86XK_AddFavorite: 0x1008FF39,
XF86XK_HotLinks: 0x1008FF3A,
XF86XK_BrightnessAdjust: 0x1008FF3B,
XF86XK_Finance: 0x1008FF3C,
XF86XK_Community: 0x1008FF3D,
XF86XK_AudioRewind: 0x1008FF3E,
XF86XK_BackForward: 0x1008FF3F,
XF86XK_Launch0: 0x1008FF40,
XF86XK_Launch1: 0x1008FF41,
XF86XK_Launch2: 0x1008FF42,
XF86XK_Launch3: 0x1008FF43,
XF86XK_Launch4: 0x1008FF44,
XF86XK_Launch5: 0x1008FF45,
XF86XK_Launch6: 0x1008FF46,
XF86XK_Launch7: 0x1008FF47,
XF86XK_Launch8: 0x1008FF48,
XF86XK_Launch9: 0x1008FF49,
XF86XK_LaunchA: 0x1008FF4A,
XF86XK_LaunchB: 0x1008FF4B,
XF86XK_LaunchC: 0x1008FF4C,
XF86XK_LaunchD: 0x1008FF4D,
XF86XK_LaunchE: 0x1008FF4E,
XF86XK_LaunchF: 0x1008FF4F,
XF86XK_ApplicationLeft: 0x1008FF50,
XF86XK_ApplicationRight: 0x1008FF51,
XF86XK_Book: 0x1008FF52,
XF86XK_CD: 0x1008FF53,
XF86XK_Calculater: 0x1008FF54,
XF86XK_Clear: 0x1008FF55,
XF86XK_Close: 0x1008FF56,
XF86XK_Copy: 0x1008FF57,
XF86XK_Cut: 0x1008FF58,
XF86XK_Display: 0x1008FF59,
XF86XK_DOS: 0x1008FF5A,
XF86XK_Documents: 0x1008FF5B,
XF86XK_Excel: 0x1008FF5C,
XF86XK_Explorer: 0x1008FF5D,
XF86XK_Game: 0x1008FF5E,
XF86XK_Go: 0x1008FF5F,
XF86XK_iTouch: 0x1008FF60,
XF86XK_LogOff: 0x1008FF61,
XF86XK_Market: 0x1008FF62,
XF86XK_Meeting: 0x1008FF63,
XF86XK_MenuKB: 0x1008FF65,
XF86XK_MenuPB: 0x1008FF66,
XF86XK_MySites: 0x1008FF67,
XF86XK_New: 0x1008FF68,
XF86XK_News: 0x1008FF69,
XF86XK_OfficeHome: 0x1008FF6A,
XF86XK_Open: 0x1008FF6B,
XF86XK_Option: 0x1008FF6C,
XF86XK_Paste: 0x1008FF6D,
XF86XK_Phone: 0x1008FF6E,
XF86XK_Q: 0x1008FF70,
XF86XK_Reply: 0x1008FF72,
XF86XK_Reload: 0x1008FF73,
XF86XK_RotateWindows: 0x1008FF74,
XF86XK_RotationPB: 0x1008FF75,
XF86XK_RotationKB: 0x1008FF76,
XF86XK_Save: 0x1008FF77,
XF86XK_ScrollUp: 0x1008FF78,
XF86XK_ScrollDown: 0x1008FF79,
XF86XK_ScrollClick: 0x1008FF7A,
XF86XK_Send: 0x1008FF7B,
XF86XK_Spell: 0x1008FF7C,
XF86XK_SplitScreen: 0x1008FF7D,
XF86XK_Support: 0x1008FF7E,
XF86XK_TaskPane: 0x1008FF7F,
XF86XK_Terminal: 0x1008FF80,
XF86XK_Tools: 0x1008FF81,
XF86XK_Travel: 0x1008FF82,
XF86XK_UserPB: 0x1008FF84,
XF86XK_User1KB: 0x1008FF85,
XF86XK_User2KB: 0x1008FF86,
XF86XK_Video: 0x1008FF87,
XF86XK_WheelButton: 0x1008FF88,
XF86XK_Word: 0x1008FF89,
XF86XK_Xfer: 0x1008FF8A,
XF86XK_ZoomIn: 0x1008FF8B,
XF86XK_ZoomOut: 0x1008FF8C,
XF86XK_Away: 0x1008FF8D,
XF86XK_Messenger: 0x1008FF8E,
XF86XK_WebCam: 0x1008FF8F,
XF86XK_MailForward: 0x1008FF90,
XF86XK_Pictures: 0x1008FF91,
XF86XK_Music: 0x1008FF92,
XF86XK_Battery: 0x1008FF93,
XF86XK_Bluetooth: 0x1008FF94,
XF86XK_WLAN: 0x1008FF95,
XF86XK_UWB: 0x1008FF96,
XF86XK_AudioForward: 0x1008FF97,
XF86XK_AudioRepeat: 0x1008FF98,
XF86XK_AudioRandomPlay: 0x1008FF99,
XF86XK_Subtitle: 0x1008FF9A,
XF86XK_AudioCycleTrack: 0x1008FF9B,
XF86XK_CycleAngle: 0x1008FF9C,
XF86XK_FrameBack: 0x1008FF9D,
XF86XK_FrameForward: 0x1008FF9E,
XF86XK_Time: 0x1008FF9F,
XF86XK_Select: 0x1008FFA0,
XF86XK_View: 0x1008FFA1,
XF86XK_TopMenu: 0x1008FFA2,
XF86XK_Red: 0x1008FFA3,
XF86XK_Green: 0x1008FFA4,
XF86XK_Yellow: 0x1008FFA5,
XF86XK_Blue: 0x1008FFA6,
XF86XK_Suspend: 0x1008FFA7,
XF86XK_Hibernate: 0x1008FFA8,
XF86XK_TouchpadToggle: 0x1008FFA9,
XF86XK_TouchpadOn: 0x1008FFB0,
XF86XK_TouchpadOff: 0x1008FFB1,
XF86XK_AudioMicMute: 0x1008FFB2,
XF86XK_Switch_VT_1: 0x1008FE01,
XF86XK_Switch_VT_2: 0x1008FE02,
XF86XK_Switch_VT_3: 0x1008FE03,
XF86XK_Switch_VT_4: 0x1008FE04,
XF86XK_Switch_VT_5: 0x1008FE05,
XF86XK_Switch_VT_6: 0x1008FE06,
XF86XK_Switch_VT_7: 0x1008FE07,
XF86XK_Switch_VT_8: 0x1008FE08,
XF86XK_Switch_VT_9: 0x1008FE09,
XF86XK_Switch_VT_10: 0x1008FE0A,
XF86XK_Switch_VT_11: 0x1008FE0B,
XF86XK_Switch_VT_12: 0x1008FE0C,
XF86XK_Ungrab: 0x1008FE20,
XF86XK_ClearGrab: 0x1008FE21,
XF86XK_Next_VMode: 0x1008FE22,
XF86XK_Prev_VMode: 0x1008FE23,
XF86XK_LogWindowTree: 0x1008FE24,
XF86XK_LogGrabInfo: 0x1008FE25,
};

View File

@ -0,0 +1,688 @@
/*
* Mapping from Unicode codepoints to X11/RFB keysyms
*
* This file was automatically generated from keysymdef.h
* DO NOT EDIT!
*/
/* Functions at the bottom */
const codepoints = {
0x0100: 0x03c0, // XK_Amacron
0x0101: 0x03e0, // XK_amacron
0x0102: 0x01c3, // XK_Abreve
0x0103: 0x01e3, // XK_abreve
0x0104: 0x01a1, // XK_Aogonek
0x0105: 0x01b1, // XK_aogonek
0x0106: 0x01c6, // XK_Cacute
0x0107: 0x01e6, // XK_cacute
0x0108: 0x02c6, // XK_Ccircumflex
0x0109: 0x02e6, // XK_ccircumflex
0x010a: 0x02c5, // XK_Cabovedot
0x010b: 0x02e5, // XK_cabovedot
0x010c: 0x01c8, // XK_Ccaron
0x010d: 0x01e8, // XK_ccaron
0x010e: 0x01cf, // XK_Dcaron
0x010f: 0x01ef, // XK_dcaron
0x0110: 0x01d0, // XK_Dstroke
0x0111: 0x01f0, // XK_dstroke
0x0112: 0x03aa, // XK_Emacron
0x0113: 0x03ba, // XK_emacron
0x0116: 0x03cc, // XK_Eabovedot
0x0117: 0x03ec, // XK_eabovedot
0x0118: 0x01ca, // XK_Eogonek
0x0119: 0x01ea, // XK_eogonek
0x011a: 0x01cc, // XK_Ecaron
0x011b: 0x01ec, // XK_ecaron
0x011c: 0x02d8, // XK_Gcircumflex
0x011d: 0x02f8, // XK_gcircumflex
0x011e: 0x02ab, // XK_Gbreve
0x011f: 0x02bb, // XK_gbreve
0x0120: 0x02d5, // XK_Gabovedot
0x0121: 0x02f5, // XK_gabovedot
0x0122: 0x03ab, // XK_Gcedilla
0x0123: 0x03bb, // XK_gcedilla
0x0124: 0x02a6, // XK_Hcircumflex
0x0125: 0x02b6, // XK_hcircumflex
0x0126: 0x02a1, // XK_Hstroke
0x0127: 0x02b1, // XK_hstroke
0x0128: 0x03a5, // XK_Itilde
0x0129: 0x03b5, // XK_itilde
0x012a: 0x03cf, // XK_Imacron
0x012b: 0x03ef, // XK_imacron
0x012e: 0x03c7, // XK_Iogonek
0x012f: 0x03e7, // XK_iogonek
0x0130: 0x02a9, // XK_Iabovedot
0x0131: 0x02b9, // XK_idotless
0x0134: 0x02ac, // XK_Jcircumflex
0x0135: 0x02bc, // XK_jcircumflex
0x0136: 0x03d3, // XK_Kcedilla
0x0137: 0x03f3, // XK_kcedilla
0x0138: 0x03a2, // XK_kra
0x0139: 0x01c5, // XK_Lacute
0x013a: 0x01e5, // XK_lacute
0x013b: 0x03a6, // XK_Lcedilla
0x013c: 0x03b6, // XK_lcedilla
0x013d: 0x01a5, // XK_Lcaron
0x013e: 0x01b5, // XK_lcaron
0x0141: 0x01a3, // XK_Lstroke
0x0142: 0x01b3, // XK_lstroke
0x0143: 0x01d1, // XK_Nacute
0x0144: 0x01f1, // XK_nacute
0x0145: 0x03d1, // XK_Ncedilla
0x0146: 0x03f1, // XK_ncedilla
0x0147: 0x01d2, // XK_Ncaron
0x0148: 0x01f2, // XK_ncaron
0x014a: 0x03bd, // XK_ENG
0x014b: 0x03bf, // XK_eng
0x014c: 0x03d2, // XK_Omacron
0x014d: 0x03f2, // XK_omacron
0x0150: 0x01d5, // XK_Odoubleacute
0x0151: 0x01f5, // XK_odoubleacute
0x0152: 0x13bc, // XK_OE
0x0153: 0x13bd, // XK_oe
0x0154: 0x01c0, // XK_Racute
0x0155: 0x01e0, // XK_racute
0x0156: 0x03a3, // XK_Rcedilla
0x0157: 0x03b3, // XK_rcedilla
0x0158: 0x01d8, // XK_Rcaron
0x0159: 0x01f8, // XK_rcaron
0x015a: 0x01a6, // XK_Sacute
0x015b: 0x01b6, // XK_sacute
0x015c: 0x02de, // XK_Scircumflex
0x015d: 0x02fe, // XK_scircumflex
0x015e: 0x01aa, // XK_Scedilla
0x015f: 0x01ba, // XK_scedilla
0x0160: 0x01a9, // XK_Scaron
0x0161: 0x01b9, // XK_scaron
0x0162: 0x01de, // XK_Tcedilla
0x0163: 0x01fe, // XK_tcedilla
0x0164: 0x01ab, // XK_Tcaron
0x0165: 0x01bb, // XK_tcaron
0x0166: 0x03ac, // XK_Tslash
0x0167: 0x03bc, // XK_tslash
0x0168: 0x03dd, // XK_Utilde
0x0169: 0x03fd, // XK_utilde
0x016a: 0x03de, // XK_Umacron
0x016b: 0x03fe, // XK_umacron
0x016c: 0x02dd, // XK_Ubreve
0x016d: 0x02fd, // XK_ubreve
0x016e: 0x01d9, // XK_Uring
0x016f: 0x01f9, // XK_uring
0x0170: 0x01db, // XK_Udoubleacute
0x0171: 0x01fb, // XK_udoubleacute
0x0172: 0x03d9, // XK_Uogonek
0x0173: 0x03f9, // XK_uogonek
0x0178: 0x13be, // XK_Ydiaeresis
0x0179: 0x01ac, // XK_Zacute
0x017a: 0x01bc, // XK_zacute
0x017b: 0x01af, // XK_Zabovedot
0x017c: 0x01bf, // XK_zabovedot
0x017d: 0x01ae, // XK_Zcaron
0x017e: 0x01be, // XK_zcaron
0x0192: 0x08f6, // XK_function
0x01d2: 0x10001d1, // XK_Ocaron
0x02c7: 0x01b7, // XK_caron
0x02d8: 0x01a2, // XK_breve
0x02d9: 0x01ff, // XK_abovedot
0x02db: 0x01b2, // XK_ogonek
0x02dd: 0x01bd, // XK_doubleacute
0x0385: 0x07ae, // XK_Greek_accentdieresis
0x0386: 0x07a1, // XK_Greek_ALPHAaccent
0x0388: 0x07a2, // XK_Greek_EPSILONaccent
0x0389: 0x07a3, // XK_Greek_ETAaccent
0x038a: 0x07a4, // XK_Greek_IOTAaccent
0x038c: 0x07a7, // XK_Greek_OMICRONaccent
0x038e: 0x07a8, // XK_Greek_UPSILONaccent
0x038f: 0x07ab, // XK_Greek_OMEGAaccent
0x0390: 0x07b6, // XK_Greek_iotaaccentdieresis
0x0391: 0x07c1, // XK_Greek_ALPHA
0x0392: 0x07c2, // XK_Greek_BETA
0x0393: 0x07c3, // XK_Greek_GAMMA
0x0394: 0x07c4, // XK_Greek_DELTA
0x0395: 0x07c5, // XK_Greek_EPSILON
0x0396: 0x07c6, // XK_Greek_ZETA
0x0397: 0x07c7, // XK_Greek_ETA
0x0398: 0x07c8, // XK_Greek_THETA
0x0399: 0x07c9, // XK_Greek_IOTA
0x039a: 0x07ca, // XK_Greek_KAPPA
0x039b: 0x07cb, // XK_Greek_LAMDA
0x039c: 0x07cc, // XK_Greek_MU
0x039d: 0x07cd, // XK_Greek_NU
0x039e: 0x07ce, // XK_Greek_XI
0x039f: 0x07cf, // XK_Greek_OMICRON
0x03a0: 0x07d0, // XK_Greek_PI
0x03a1: 0x07d1, // XK_Greek_RHO
0x03a3: 0x07d2, // XK_Greek_SIGMA
0x03a4: 0x07d4, // XK_Greek_TAU
0x03a5: 0x07d5, // XK_Greek_UPSILON
0x03a6: 0x07d6, // XK_Greek_PHI
0x03a7: 0x07d7, // XK_Greek_CHI
0x03a8: 0x07d8, // XK_Greek_PSI
0x03a9: 0x07d9, // XK_Greek_OMEGA
0x03aa: 0x07a5, // XK_Greek_IOTAdieresis
0x03ab: 0x07a9, // XK_Greek_UPSILONdieresis
0x03ac: 0x07b1, // XK_Greek_alphaaccent
0x03ad: 0x07b2, // XK_Greek_epsilonaccent
0x03ae: 0x07b3, // XK_Greek_etaaccent
0x03af: 0x07b4, // XK_Greek_iotaaccent
0x03b0: 0x07ba, // XK_Greek_upsilonaccentdieresis
0x03b1: 0x07e1, // XK_Greek_alpha
0x03b2: 0x07e2, // XK_Greek_beta
0x03b3: 0x07e3, // XK_Greek_gamma
0x03b4: 0x07e4, // XK_Greek_delta
0x03b5: 0x07e5, // XK_Greek_epsilon
0x03b6: 0x07e6, // XK_Greek_zeta
0x03b7: 0x07e7, // XK_Greek_eta
0x03b8: 0x07e8, // XK_Greek_theta
0x03b9: 0x07e9, // XK_Greek_iota
0x03ba: 0x07ea, // XK_Greek_kappa
0x03bb: 0x07eb, // XK_Greek_lamda
0x03bc: 0x07ec, // XK_Greek_mu
0x03bd: 0x07ed, // XK_Greek_nu
0x03be: 0x07ee, // XK_Greek_xi
0x03bf: 0x07ef, // XK_Greek_omicron
0x03c0: 0x07f0, // XK_Greek_pi
0x03c1: 0x07f1, // XK_Greek_rho
0x03c2: 0x07f3, // XK_Greek_finalsmallsigma
0x03c3: 0x07f2, // XK_Greek_sigma
0x03c4: 0x07f4, // XK_Greek_tau
0x03c5: 0x07f5, // XK_Greek_upsilon
0x03c6: 0x07f6, // XK_Greek_phi
0x03c7: 0x07f7, // XK_Greek_chi
0x03c8: 0x07f8, // XK_Greek_psi
0x03c9: 0x07f9, // XK_Greek_omega
0x03ca: 0x07b5, // XK_Greek_iotadieresis
0x03cb: 0x07b9, // XK_Greek_upsilondieresis
0x03cc: 0x07b7, // XK_Greek_omicronaccent
0x03cd: 0x07b8, // XK_Greek_upsilonaccent
0x03ce: 0x07bb, // XK_Greek_omegaaccent
0x0401: 0x06b3, // XK_Cyrillic_IO
0x0402: 0x06b1, // XK_Serbian_DJE
0x0403: 0x06b2, // XK_Macedonia_GJE
0x0404: 0x06b4, // XK_Ukrainian_IE
0x0405: 0x06b5, // XK_Macedonia_DSE
0x0406: 0x06b6, // XK_Ukrainian_I
0x0407: 0x06b7, // XK_Ukrainian_YI
0x0408: 0x06b8, // XK_Cyrillic_JE
0x0409: 0x06b9, // XK_Cyrillic_LJE
0x040a: 0x06ba, // XK_Cyrillic_NJE
0x040b: 0x06bb, // XK_Serbian_TSHE
0x040c: 0x06bc, // XK_Macedonia_KJE
0x040e: 0x06be, // XK_Byelorussian_SHORTU
0x040f: 0x06bf, // XK_Cyrillic_DZHE
0x0410: 0x06e1, // XK_Cyrillic_A
0x0411: 0x06e2, // XK_Cyrillic_BE
0x0412: 0x06f7, // XK_Cyrillic_VE
0x0413: 0x06e7, // XK_Cyrillic_GHE
0x0414: 0x06e4, // XK_Cyrillic_DE
0x0415: 0x06e5, // XK_Cyrillic_IE
0x0416: 0x06f6, // XK_Cyrillic_ZHE
0x0417: 0x06fa, // XK_Cyrillic_ZE
0x0418: 0x06e9, // XK_Cyrillic_I
0x0419: 0x06ea, // XK_Cyrillic_SHORTI
0x041a: 0x06eb, // XK_Cyrillic_KA
0x041b: 0x06ec, // XK_Cyrillic_EL
0x041c: 0x06ed, // XK_Cyrillic_EM
0x041d: 0x06ee, // XK_Cyrillic_EN
0x041e: 0x06ef, // XK_Cyrillic_O
0x041f: 0x06f0, // XK_Cyrillic_PE
0x0420: 0x06f2, // XK_Cyrillic_ER
0x0421: 0x06f3, // XK_Cyrillic_ES
0x0422: 0x06f4, // XK_Cyrillic_TE
0x0423: 0x06f5, // XK_Cyrillic_U
0x0424: 0x06e6, // XK_Cyrillic_EF
0x0425: 0x06e8, // XK_Cyrillic_HA
0x0426: 0x06e3, // XK_Cyrillic_TSE
0x0427: 0x06fe, // XK_Cyrillic_CHE
0x0428: 0x06fb, // XK_Cyrillic_SHA
0x0429: 0x06fd, // XK_Cyrillic_SHCHA
0x042a: 0x06ff, // XK_Cyrillic_HARDSIGN
0x042b: 0x06f9, // XK_Cyrillic_YERU
0x042c: 0x06f8, // XK_Cyrillic_SOFTSIGN
0x042d: 0x06fc, // XK_Cyrillic_E
0x042e: 0x06e0, // XK_Cyrillic_YU
0x042f: 0x06f1, // XK_Cyrillic_YA
0x0430: 0x06c1, // XK_Cyrillic_a
0x0431: 0x06c2, // XK_Cyrillic_be
0x0432: 0x06d7, // XK_Cyrillic_ve
0x0433: 0x06c7, // XK_Cyrillic_ghe
0x0434: 0x06c4, // XK_Cyrillic_de
0x0435: 0x06c5, // XK_Cyrillic_ie
0x0436: 0x06d6, // XK_Cyrillic_zhe
0x0437: 0x06da, // XK_Cyrillic_ze
0x0438: 0x06c9, // XK_Cyrillic_i
0x0439: 0x06ca, // XK_Cyrillic_shorti
0x043a: 0x06cb, // XK_Cyrillic_ka
0x043b: 0x06cc, // XK_Cyrillic_el
0x043c: 0x06cd, // XK_Cyrillic_em
0x043d: 0x06ce, // XK_Cyrillic_en
0x043e: 0x06cf, // XK_Cyrillic_o
0x043f: 0x06d0, // XK_Cyrillic_pe
0x0440: 0x06d2, // XK_Cyrillic_er
0x0441: 0x06d3, // XK_Cyrillic_es
0x0442: 0x06d4, // XK_Cyrillic_te
0x0443: 0x06d5, // XK_Cyrillic_u
0x0444: 0x06c6, // XK_Cyrillic_ef
0x0445: 0x06c8, // XK_Cyrillic_ha
0x0446: 0x06c3, // XK_Cyrillic_tse
0x0447: 0x06de, // XK_Cyrillic_che
0x0448: 0x06db, // XK_Cyrillic_sha
0x0449: 0x06dd, // XK_Cyrillic_shcha
0x044a: 0x06df, // XK_Cyrillic_hardsign
0x044b: 0x06d9, // XK_Cyrillic_yeru
0x044c: 0x06d8, // XK_Cyrillic_softsign
0x044d: 0x06dc, // XK_Cyrillic_e
0x044e: 0x06c0, // XK_Cyrillic_yu
0x044f: 0x06d1, // XK_Cyrillic_ya
0x0451: 0x06a3, // XK_Cyrillic_io
0x0452: 0x06a1, // XK_Serbian_dje
0x0453: 0x06a2, // XK_Macedonia_gje
0x0454: 0x06a4, // XK_Ukrainian_ie
0x0455: 0x06a5, // XK_Macedonia_dse
0x0456: 0x06a6, // XK_Ukrainian_i
0x0457: 0x06a7, // XK_Ukrainian_yi
0x0458: 0x06a8, // XK_Cyrillic_je
0x0459: 0x06a9, // XK_Cyrillic_lje
0x045a: 0x06aa, // XK_Cyrillic_nje
0x045b: 0x06ab, // XK_Serbian_tshe
0x045c: 0x06ac, // XK_Macedonia_kje
0x045e: 0x06ae, // XK_Byelorussian_shortu
0x045f: 0x06af, // XK_Cyrillic_dzhe
0x0490: 0x06bd, // XK_Ukrainian_GHE_WITH_UPTURN
0x0491: 0x06ad, // XK_Ukrainian_ghe_with_upturn
0x05d0: 0x0ce0, // XK_hebrew_aleph
0x05d1: 0x0ce1, // XK_hebrew_bet
0x05d2: 0x0ce2, // XK_hebrew_gimel
0x05d3: 0x0ce3, // XK_hebrew_dalet
0x05d4: 0x0ce4, // XK_hebrew_he
0x05d5: 0x0ce5, // XK_hebrew_waw
0x05d6: 0x0ce6, // XK_hebrew_zain
0x05d7: 0x0ce7, // XK_hebrew_chet
0x05d8: 0x0ce8, // XK_hebrew_tet
0x05d9: 0x0ce9, // XK_hebrew_yod
0x05da: 0x0cea, // XK_hebrew_finalkaph
0x05db: 0x0ceb, // XK_hebrew_kaph
0x05dc: 0x0cec, // XK_hebrew_lamed
0x05dd: 0x0ced, // XK_hebrew_finalmem
0x05de: 0x0cee, // XK_hebrew_mem
0x05df: 0x0cef, // XK_hebrew_finalnun
0x05e0: 0x0cf0, // XK_hebrew_nun
0x05e1: 0x0cf1, // XK_hebrew_samech
0x05e2: 0x0cf2, // XK_hebrew_ayin
0x05e3: 0x0cf3, // XK_hebrew_finalpe
0x05e4: 0x0cf4, // XK_hebrew_pe
0x05e5: 0x0cf5, // XK_hebrew_finalzade
0x05e6: 0x0cf6, // XK_hebrew_zade
0x05e7: 0x0cf7, // XK_hebrew_qoph
0x05e8: 0x0cf8, // XK_hebrew_resh
0x05e9: 0x0cf9, // XK_hebrew_shin
0x05ea: 0x0cfa, // XK_hebrew_taw
0x060c: 0x05ac, // XK_Arabic_comma
0x061b: 0x05bb, // XK_Arabic_semicolon
0x061f: 0x05bf, // XK_Arabic_question_mark
0x0621: 0x05c1, // XK_Arabic_hamza
0x0622: 0x05c2, // XK_Arabic_maddaonalef
0x0623: 0x05c3, // XK_Arabic_hamzaonalef
0x0624: 0x05c4, // XK_Arabic_hamzaonwaw
0x0625: 0x05c5, // XK_Arabic_hamzaunderalef
0x0626: 0x05c6, // XK_Arabic_hamzaonyeh
0x0627: 0x05c7, // XK_Arabic_alef
0x0628: 0x05c8, // XK_Arabic_beh
0x0629: 0x05c9, // XK_Arabic_tehmarbuta
0x062a: 0x05ca, // XK_Arabic_teh
0x062b: 0x05cb, // XK_Arabic_theh
0x062c: 0x05cc, // XK_Arabic_jeem
0x062d: 0x05cd, // XK_Arabic_hah
0x062e: 0x05ce, // XK_Arabic_khah
0x062f: 0x05cf, // XK_Arabic_dal
0x0630: 0x05d0, // XK_Arabic_thal
0x0631: 0x05d1, // XK_Arabic_ra
0x0632: 0x05d2, // XK_Arabic_zain
0x0633: 0x05d3, // XK_Arabic_seen
0x0634: 0x05d4, // XK_Arabic_sheen
0x0635: 0x05d5, // XK_Arabic_sad
0x0636: 0x05d6, // XK_Arabic_dad
0x0637: 0x05d7, // XK_Arabic_tah
0x0638: 0x05d8, // XK_Arabic_zah
0x0639: 0x05d9, // XK_Arabic_ain
0x063a: 0x05da, // XK_Arabic_ghain
0x0640: 0x05e0, // XK_Arabic_tatweel
0x0641: 0x05e1, // XK_Arabic_feh
0x0642: 0x05e2, // XK_Arabic_qaf
0x0643: 0x05e3, // XK_Arabic_kaf
0x0644: 0x05e4, // XK_Arabic_lam
0x0645: 0x05e5, // XK_Arabic_meem
0x0646: 0x05e6, // XK_Arabic_noon
0x0647: 0x05e7, // XK_Arabic_ha
0x0648: 0x05e8, // XK_Arabic_waw
0x0649: 0x05e9, // XK_Arabic_alefmaksura
0x064a: 0x05ea, // XK_Arabic_yeh
0x064b: 0x05eb, // XK_Arabic_fathatan
0x064c: 0x05ec, // XK_Arabic_dammatan
0x064d: 0x05ed, // XK_Arabic_kasratan
0x064e: 0x05ee, // XK_Arabic_fatha
0x064f: 0x05ef, // XK_Arabic_damma
0x0650: 0x05f0, // XK_Arabic_kasra
0x0651: 0x05f1, // XK_Arabic_shadda
0x0652: 0x05f2, // XK_Arabic_sukun
0x0e01: 0x0da1, // XK_Thai_kokai
0x0e02: 0x0da2, // XK_Thai_khokhai
0x0e03: 0x0da3, // XK_Thai_khokhuat
0x0e04: 0x0da4, // XK_Thai_khokhwai
0x0e05: 0x0da5, // XK_Thai_khokhon
0x0e06: 0x0da6, // XK_Thai_khorakhang
0x0e07: 0x0da7, // XK_Thai_ngongu
0x0e08: 0x0da8, // XK_Thai_chochan
0x0e09: 0x0da9, // XK_Thai_choching
0x0e0a: 0x0daa, // XK_Thai_chochang
0x0e0b: 0x0dab, // XK_Thai_soso
0x0e0c: 0x0dac, // XK_Thai_chochoe
0x0e0d: 0x0dad, // XK_Thai_yoying
0x0e0e: 0x0dae, // XK_Thai_dochada
0x0e0f: 0x0daf, // XK_Thai_topatak
0x0e10: 0x0db0, // XK_Thai_thothan
0x0e11: 0x0db1, // XK_Thai_thonangmontho
0x0e12: 0x0db2, // XK_Thai_thophuthao
0x0e13: 0x0db3, // XK_Thai_nonen
0x0e14: 0x0db4, // XK_Thai_dodek
0x0e15: 0x0db5, // XK_Thai_totao
0x0e16: 0x0db6, // XK_Thai_thothung
0x0e17: 0x0db7, // XK_Thai_thothahan
0x0e18: 0x0db8, // XK_Thai_thothong
0x0e19: 0x0db9, // XK_Thai_nonu
0x0e1a: 0x0dba, // XK_Thai_bobaimai
0x0e1b: 0x0dbb, // XK_Thai_popla
0x0e1c: 0x0dbc, // XK_Thai_phophung
0x0e1d: 0x0dbd, // XK_Thai_fofa
0x0e1e: 0x0dbe, // XK_Thai_phophan
0x0e1f: 0x0dbf, // XK_Thai_fofan
0x0e20: 0x0dc0, // XK_Thai_phosamphao
0x0e21: 0x0dc1, // XK_Thai_moma
0x0e22: 0x0dc2, // XK_Thai_yoyak
0x0e23: 0x0dc3, // XK_Thai_rorua
0x0e24: 0x0dc4, // XK_Thai_ru
0x0e25: 0x0dc5, // XK_Thai_loling
0x0e26: 0x0dc6, // XK_Thai_lu
0x0e27: 0x0dc7, // XK_Thai_wowaen
0x0e28: 0x0dc8, // XK_Thai_sosala
0x0e29: 0x0dc9, // XK_Thai_sorusi
0x0e2a: 0x0dca, // XK_Thai_sosua
0x0e2b: 0x0dcb, // XK_Thai_hohip
0x0e2c: 0x0dcc, // XK_Thai_lochula
0x0e2d: 0x0dcd, // XK_Thai_oang
0x0e2e: 0x0dce, // XK_Thai_honokhuk
0x0e2f: 0x0dcf, // XK_Thai_paiyannoi
0x0e30: 0x0dd0, // XK_Thai_saraa
0x0e31: 0x0dd1, // XK_Thai_maihanakat
0x0e32: 0x0dd2, // XK_Thai_saraaa
0x0e33: 0x0dd3, // XK_Thai_saraam
0x0e34: 0x0dd4, // XK_Thai_sarai
0x0e35: 0x0dd5, // XK_Thai_saraii
0x0e36: 0x0dd6, // XK_Thai_saraue
0x0e37: 0x0dd7, // XK_Thai_sarauee
0x0e38: 0x0dd8, // XK_Thai_sarau
0x0e39: 0x0dd9, // XK_Thai_sarauu
0x0e3a: 0x0dda, // XK_Thai_phinthu
0x0e3f: 0x0ddf, // XK_Thai_baht
0x0e40: 0x0de0, // XK_Thai_sarae
0x0e41: 0x0de1, // XK_Thai_saraae
0x0e42: 0x0de2, // XK_Thai_sarao
0x0e43: 0x0de3, // XK_Thai_saraaimaimuan
0x0e44: 0x0de4, // XK_Thai_saraaimaimalai
0x0e45: 0x0de5, // XK_Thai_lakkhangyao
0x0e46: 0x0de6, // XK_Thai_maiyamok
0x0e47: 0x0de7, // XK_Thai_maitaikhu
0x0e48: 0x0de8, // XK_Thai_maiek
0x0e49: 0x0de9, // XK_Thai_maitho
0x0e4a: 0x0dea, // XK_Thai_maitri
0x0e4b: 0x0deb, // XK_Thai_maichattawa
0x0e4c: 0x0dec, // XK_Thai_thanthakhat
0x0e4d: 0x0ded, // XK_Thai_nikhahit
0x0e50: 0x0df0, // XK_Thai_leksun
0x0e51: 0x0df1, // XK_Thai_leknung
0x0e52: 0x0df2, // XK_Thai_leksong
0x0e53: 0x0df3, // XK_Thai_leksam
0x0e54: 0x0df4, // XK_Thai_leksi
0x0e55: 0x0df5, // XK_Thai_lekha
0x0e56: 0x0df6, // XK_Thai_lekhok
0x0e57: 0x0df7, // XK_Thai_lekchet
0x0e58: 0x0df8, // XK_Thai_lekpaet
0x0e59: 0x0df9, // XK_Thai_lekkao
0x2002: 0x0aa2, // XK_enspace
0x2003: 0x0aa1, // XK_emspace
0x2004: 0x0aa3, // XK_em3space
0x2005: 0x0aa4, // XK_em4space
0x2007: 0x0aa5, // XK_digitspace
0x2008: 0x0aa6, // XK_punctspace
0x2009: 0x0aa7, // XK_thinspace
0x200a: 0x0aa8, // XK_hairspace
0x2012: 0x0abb, // XK_figdash
0x2013: 0x0aaa, // XK_endash
0x2014: 0x0aa9, // XK_emdash
0x2015: 0x07af, // XK_Greek_horizbar
0x2017: 0x0cdf, // XK_hebrew_doublelowline
0x2018: 0x0ad0, // XK_leftsinglequotemark
0x2019: 0x0ad1, // XK_rightsinglequotemark
0x201a: 0x0afd, // XK_singlelowquotemark
0x201c: 0x0ad2, // XK_leftdoublequotemark
0x201d: 0x0ad3, // XK_rightdoublequotemark
0x201e: 0x0afe, // XK_doublelowquotemark
0x2020: 0x0af1, // XK_dagger
0x2021: 0x0af2, // XK_doubledagger
0x2022: 0x0ae6, // XK_enfilledcircbullet
0x2025: 0x0aaf, // XK_doubbaselinedot
0x2026: 0x0aae, // XK_ellipsis
0x2030: 0x0ad5, // XK_permille
0x2032: 0x0ad6, // XK_minutes
0x2033: 0x0ad7, // XK_seconds
0x2038: 0x0afc, // XK_caret
0x203e: 0x047e, // XK_overline
0x20a9: 0x0eff, // XK_Korean_Won
0x20ac: 0x20ac, // XK_EuroSign
0x2105: 0x0ab8, // XK_careof
0x2116: 0x06b0, // XK_numerosign
0x2117: 0x0afb, // XK_phonographcopyright
0x211e: 0x0ad4, // XK_prescription
0x2122: 0x0ac9, // XK_trademark
0x2153: 0x0ab0, // XK_onethird
0x2154: 0x0ab1, // XK_twothirds
0x2155: 0x0ab2, // XK_onefifth
0x2156: 0x0ab3, // XK_twofifths
0x2157: 0x0ab4, // XK_threefifths
0x2158: 0x0ab5, // XK_fourfifths
0x2159: 0x0ab6, // XK_onesixth
0x215a: 0x0ab7, // XK_fivesixths
0x215b: 0x0ac3, // XK_oneeighth
0x215c: 0x0ac4, // XK_threeeighths
0x215d: 0x0ac5, // XK_fiveeighths
0x215e: 0x0ac6, // XK_seveneighths
0x2190: 0x08fb, // XK_leftarrow
0x2191: 0x08fc, // XK_uparrow
0x2192: 0x08fd, // XK_rightarrow
0x2193: 0x08fe, // XK_downarrow
0x21d2: 0x08ce, // XK_implies
0x21d4: 0x08cd, // XK_ifonlyif
0x2202: 0x08ef, // XK_partialderivative
0x2207: 0x08c5, // XK_nabla
0x2218: 0x0bca, // XK_jot
0x221a: 0x08d6, // XK_radical
0x221d: 0x08c1, // XK_variation
0x221e: 0x08c2, // XK_infinity
0x2227: 0x08de, // XK_logicaland
0x2228: 0x08df, // XK_logicalor
0x2229: 0x08dc, // XK_intersection
0x222a: 0x08dd, // XK_union
0x222b: 0x08bf, // XK_integral
0x2234: 0x08c0, // XK_therefore
0x223c: 0x08c8, // XK_approximate
0x2243: 0x08c9, // XK_similarequal
0x2245: 0x1002248, // XK_approxeq
0x2260: 0x08bd, // XK_notequal
0x2261: 0x08cf, // XK_identical
0x2264: 0x08bc, // XK_lessthanequal
0x2265: 0x08be, // XK_greaterthanequal
0x2282: 0x08da, // XK_includedin
0x2283: 0x08db, // XK_includes
0x22a2: 0x0bfc, // XK_righttack
0x22a3: 0x0bdc, // XK_lefttack
0x22a4: 0x0bc2, // XK_downtack
0x22a5: 0x0bce, // XK_uptack
0x2308: 0x0bd3, // XK_upstile
0x230a: 0x0bc4, // XK_downstile
0x2315: 0x0afa, // XK_telephonerecorder
0x2320: 0x08a4, // XK_topintegral
0x2321: 0x08a5, // XK_botintegral
0x2395: 0x0bcc, // XK_quad
0x239b: 0x08ab, // XK_topleftparens
0x239d: 0x08ac, // XK_botleftparens
0x239e: 0x08ad, // XK_toprightparens
0x23a0: 0x08ae, // XK_botrightparens
0x23a1: 0x08a7, // XK_topleftsqbracket
0x23a3: 0x08a8, // XK_botleftsqbracket
0x23a4: 0x08a9, // XK_toprightsqbracket
0x23a6: 0x08aa, // XK_botrightsqbracket
0x23a8: 0x08af, // XK_leftmiddlecurlybrace
0x23ac: 0x08b0, // XK_rightmiddlecurlybrace
0x23b7: 0x08a1, // XK_leftradical
0x23ba: 0x09ef, // XK_horizlinescan1
0x23bb: 0x09f0, // XK_horizlinescan3
0x23bc: 0x09f2, // XK_horizlinescan7
0x23bd: 0x09f3, // XK_horizlinescan9
0x2409: 0x09e2, // XK_ht
0x240a: 0x09e5, // XK_lf
0x240b: 0x09e9, // XK_vt
0x240c: 0x09e3, // XK_ff
0x240d: 0x09e4, // XK_cr
0x2423: 0x0aac, // XK_signifblank
0x2424: 0x09e8, // XK_nl
0x2500: 0x08a3, // XK_horizconnector
0x2502: 0x08a6, // XK_vertconnector
0x250c: 0x08a2, // XK_topleftradical
0x2510: 0x09eb, // XK_uprightcorner
0x2514: 0x09ed, // XK_lowleftcorner
0x2518: 0x09ea, // XK_lowrightcorner
0x251c: 0x09f4, // XK_leftt
0x2524: 0x09f5, // XK_rightt
0x252c: 0x09f7, // XK_topt
0x2534: 0x09f6, // XK_bott
0x253c: 0x09ee, // XK_crossinglines
0x2592: 0x09e1, // XK_checkerboard
0x25aa: 0x0ae7, // XK_enfilledsqbullet
0x25ab: 0x0ae1, // XK_enopensquarebullet
0x25ac: 0x0adb, // XK_filledrectbullet
0x25ad: 0x0ae2, // XK_openrectbullet
0x25ae: 0x0adf, // XK_emfilledrect
0x25af: 0x0acf, // XK_emopenrectangle
0x25b2: 0x0ae8, // XK_filledtribulletup
0x25b3: 0x0ae3, // XK_opentribulletup
0x25b6: 0x0add, // XK_filledrighttribullet
0x25b7: 0x0acd, // XK_rightopentriangle
0x25bc: 0x0ae9, // XK_filledtribulletdown
0x25bd: 0x0ae4, // XK_opentribulletdown
0x25c0: 0x0adc, // XK_filledlefttribullet
0x25c1: 0x0acc, // XK_leftopentriangle
0x25c6: 0x09e0, // XK_soliddiamond
0x25cb: 0x0ace, // XK_emopencircle
0x25cf: 0x0ade, // XK_emfilledcircle
0x25e6: 0x0ae0, // XK_enopencircbullet
0x2606: 0x0ae5, // XK_openstar
0x260e: 0x0af9, // XK_telephone
0x2613: 0x0aca, // XK_signaturemark
0x261c: 0x0aea, // XK_leftpointer
0x261e: 0x0aeb, // XK_rightpointer
0x2640: 0x0af8, // XK_femalesymbol
0x2642: 0x0af7, // XK_malesymbol
0x2663: 0x0aec, // XK_club
0x2665: 0x0aee, // XK_heart
0x2666: 0x0aed, // XK_diamond
0x266d: 0x0af6, // XK_musicalflat
0x266f: 0x0af5, // XK_musicalsharp
0x2713: 0x0af3, // XK_checkmark
0x2717: 0x0af4, // XK_ballotcross
0x271d: 0x0ad9, // XK_latincross
0x2720: 0x0af0, // XK_maltesecross
0x27e8: 0x0abc, // XK_leftanglebracket
0x27e9: 0x0abe, // XK_rightanglebracket
0x3001: 0x04a4, // XK_kana_comma
0x3002: 0x04a1, // XK_kana_fullstop
0x300c: 0x04a2, // XK_kana_openingbracket
0x300d: 0x04a3, // XK_kana_closingbracket
0x309b: 0x04de, // XK_voicedsound
0x309c: 0x04df, // XK_semivoicedsound
0x30a1: 0x04a7, // XK_kana_a
0x30a2: 0x04b1, // XK_kana_A
0x30a3: 0x04a8, // XK_kana_i
0x30a4: 0x04b2, // XK_kana_I
0x30a5: 0x04a9, // XK_kana_u
0x30a6: 0x04b3, // XK_kana_U
0x30a7: 0x04aa, // XK_kana_e
0x30a8: 0x04b4, // XK_kana_E
0x30a9: 0x04ab, // XK_kana_o
0x30aa: 0x04b5, // XK_kana_O
0x30ab: 0x04b6, // XK_kana_KA
0x30ad: 0x04b7, // XK_kana_KI
0x30af: 0x04b8, // XK_kana_KU
0x30b1: 0x04b9, // XK_kana_KE
0x30b3: 0x04ba, // XK_kana_KO
0x30b5: 0x04bb, // XK_kana_SA
0x30b7: 0x04bc, // XK_kana_SHI
0x30b9: 0x04bd, // XK_kana_SU
0x30bb: 0x04be, // XK_kana_SE
0x30bd: 0x04bf, // XK_kana_SO
0x30bf: 0x04c0, // XK_kana_TA
0x30c1: 0x04c1, // XK_kana_CHI
0x30c3: 0x04af, // XK_kana_tsu
0x30c4: 0x04c2, // XK_kana_TSU
0x30c6: 0x04c3, // XK_kana_TE
0x30c8: 0x04c4, // XK_kana_TO
0x30ca: 0x04c5, // XK_kana_NA
0x30cb: 0x04c6, // XK_kana_NI
0x30cc: 0x04c7, // XK_kana_NU
0x30cd: 0x04c8, // XK_kana_NE
0x30ce: 0x04c9, // XK_kana_NO
0x30cf: 0x04ca, // XK_kana_HA
0x30d2: 0x04cb, // XK_kana_HI
0x30d5: 0x04cc, // XK_kana_FU
0x30d8: 0x04cd, // XK_kana_HE
0x30db: 0x04ce, // XK_kana_HO
0x30de: 0x04cf, // XK_kana_MA
0x30df: 0x04d0, // XK_kana_MI
0x30e0: 0x04d1, // XK_kana_MU
0x30e1: 0x04d2, // XK_kana_ME
0x30e2: 0x04d3, // XK_kana_MO
0x30e3: 0x04ac, // XK_kana_ya
0x30e4: 0x04d4, // XK_kana_YA
0x30e5: 0x04ad, // XK_kana_yu
0x30e6: 0x04d5, // XK_kana_YU
0x30e7: 0x04ae, // XK_kana_yo
0x30e8: 0x04d6, // XK_kana_YO
0x30e9: 0x04d7, // XK_kana_RA
0x30ea: 0x04d8, // XK_kana_RI
0x30eb: 0x04d9, // XK_kana_RU
0x30ec: 0x04da, // XK_kana_RE
0x30ed: 0x04db, // XK_kana_RO
0x30ef: 0x04dc, // XK_kana_WA
0x30f2: 0x04a6, // XK_kana_WO
0x30f3: 0x04dd, // XK_kana_N
0x30fb: 0x04a5, // XK_kana_conjunctive
0x30fc: 0x04b0, // XK_prolongedsound
};
export default {
lookup(u) {
// Latin-1 is one-to-one mapping
if ((u >= 0x20) && (u <= 0xff)) {
return u;
}
// Lookup table (fairly random)
const keysym = codepoints[u];
if (keysym !== undefined) {
return keysym;
}
// General mapping as final fallback
return 0x01000000 | u;
},
};

View File

@ -0,0 +1,191 @@
import KeyTable from "./keysym.js";
import keysyms from "./keysymdef.js";
import vkeys from "./vkeys.js";
import fixedkeys from "./fixedkeys.js";
import DOMKeyTable from "./domkeytable.js";
import * as browser from "../util/browser.js";
// Get 'KeyboardEvent.code', handling legacy browsers
export function getKeycode(evt) {
// Are we getting proper key identifiers?
// (unfortunately Firefox and Chrome are crappy here and gives
// us an empty string on some platforms, rather than leaving it
// undefined)
if (evt.code) {
// Mozilla isn't fully in sync with the spec yet
switch (evt.code) {
case 'OSLeft': return 'MetaLeft';
case 'OSRight': return 'MetaRight';
}
return evt.code;
}
// The de-facto standard is to use Windows Virtual-Key codes
// in the 'keyCode' field for non-printable characters
if (evt.keyCode in vkeys) {
let code = vkeys[evt.keyCode];
// macOS has messed up this code for some reason
if (browser.isMac() && (code === 'ContextMenu')) {
code = 'MetaRight';
}
// The keyCode doesn't distinguish between left and right
// for the standard modifiers
if (evt.location === 2) {
switch (code) {
case 'ShiftLeft': return 'ShiftRight';
case 'ControlLeft': return 'ControlRight';
case 'AltLeft': return 'AltRight';
}
}
// Nor a bunch of the numpad keys
if (evt.location === 3) {
switch (code) {
case 'Delete': return 'NumpadDecimal';
case 'Insert': return 'Numpad0';
case 'End': return 'Numpad1';
case 'ArrowDown': return 'Numpad2';
case 'PageDown': return 'Numpad3';
case 'ArrowLeft': return 'Numpad4';
case 'ArrowRight': return 'Numpad6';
case 'Home': return 'Numpad7';
case 'ArrowUp': return 'Numpad8';
case 'PageUp': return 'Numpad9';
case 'Enter': return 'NumpadEnter';
}
}
return code;
}
return 'Unidentified';
}
// Get 'KeyboardEvent.key', handling legacy browsers
export function getKey(evt) {
// Are we getting a proper key value?
if (evt.key !== undefined) {
// Mozilla isn't fully in sync with the spec yet
switch (evt.key) {
case 'OS': return 'Meta';
case 'LaunchMyComputer': return 'LaunchApplication1';
case 'LaunchCalculator': return 'LaunchApplication2';
}
// iOS leaks some OS names
switch (evt.key) {
case 'UIKeyInputUpArrow': return 'ArrowUp';
case 'UIKeyInputDownArrow': return 'ArrowDown';
case 'UIKeyInputLeftArrow': return 'ArrowLeft';
case 'UIKeyInputRightArrow': return 'ArrowRight';
case 'UIKeyInputEscape': return 'Escape';
}
// Broken behaviour in Chrome
if ((evt.key === '\x00') && (evt.code === 'NumpadDecimal')) {
return 'Delete';
}
return evt.key;
}
// Try to deduce it based on the physical key
const code = getKeycode(evt);
if (code in fixedkeys) {
return fixedkeys[code];
}
// If that failed, then see if we have a printable character
if (evt.charCode) {
return String.fromCharCode(evt.charCode);
}
// At this point we have nothing left to go on
return 'Unidentified';
}
// Get the most reliable keysym value we can get from a key event
export function getKeysym(evt) {
const key = getKey(evt);
if (key === 'Unidentified') {
return null;
}
// First look up special keys
if (key in DOMKeyTable) {
let location = evt.location;
// Safari screws up location for the right cmd key
if ((key === 'Meta') && (location === 0)) {
location = 2;
}
// And for Clear
if ((key === 'Clear') && (location === 3)) {
let code = getKeycode(evt);
if (code === 'NumLock') {
location = 0;
}
}
if ((location === undefined) || (location > 3)) {
location = 0;
}
// The original Meta key now gets confused with the Windows key
// https://bugs.chromium.org/p/chromium/issues/detail?id=1020141
// https://bugzilla.mozilla.org/show_bug.cgi?id=1232918
if (key === 'Meta') {
let code = getKeycode(evt);
if (code === 'AltLeft') {
return KeyTable.XK_Meta_L;
} else if (code === 'AltRight') {
return KeyTable.XK_Meta_R;
}
}
// macOS has Clear instead of NumLock, but the remote system is
// probably not macOS, so lying here is probably best...
if (key === 'Clear') {
let code = getKeycode(evt);
if (code === 'NumLock') {
return KeyTable.XK_Num_Lock;
}
}
// Windows sends alternating symbols for some keys when using a
// Japanese layout. We have no way of synchronising with the IM
// running on the remote system, so we send some combined keysym
// instead and hope for the best.
if (browser.isWindows()) {
switch (key) {
case 'Zenkaku':
case 'Hankaku':
return KeyTable.XK_Zenkaku_Hankaku;
case 'Romaji':
case 'KanaMode':
return KeyTable.XK_Romaji;
}
}
return DOMKeyTable[key][location];
}
// Now we need to look at the Unicode symbol instead
// Special key? (FIXME: Should have been caught earlier)
if (key.length !== 1) {
return null;
}
const codepoint = key.charCodeAt();
if (codepoint) {
return keysyms.lookup(codepoint);
}
return null;
}

View File

@ -0,0 +1,116 @@
/*
* noVNC: HTML5 VNC client
* Copyright (C) 2018 The noVNC Authors
* Licensed under MPL 2.0 or any later version (see LICENSE.txt)
*/
/*
* Mapping between Microsoft® Windows® Virtual-Key codes and
* HTML key codes.
*/
export default {
0x08: 'Backspace',
0x09: 'Tab',
0x0a: 'NumpadClear',
0x0d: 'Enter',
0x10: 'ShiftLeft',
0x11: 'ControlLeft',
0x12: 'AltLeft',
0x13: 'Pause',
0x14: 'CapsLock',
0x15: 'Lang1',
0x19: 'Lang2',
0x1b: 'Escape',
0x1c: 'Convert',
0x1d: 'NonConvert',
0x20: 'Space',
0x21: 'PageUp',
0x22: 'PageDown',
0x23: 'End',
0x24: 'Home',
0x25: 'ArrowLeft',
0x26: 'ArrowUp',
0x27: 'ArrowRight',
0x28: 'ArrowDown',
0x29: 'Select',
0x2c: 'PrintScreen',
0x2d: 'Insert',
0x2e: 'Delete',
0x2f: 'Help',
0x30: 'Digit0',
0x31: 'Digit1',
0x32: 'Digit2',
0x33: 'Digit3',
0x34: 'Digit4',
0x35: 'Digit5',
0x36: 'Digit6',
0x37: 'Digit7',
0x38: 'Digit8',
0x39: 'Digit9',
0x5b: 'MetaLeft',
0x5c: 'MetaRight',
0x5d: 'ContextMenu',
0x5f: 'Sleep',
0x60: 'Numpad0',
0x61: 'Numpad1',
0x62: 'Numpad2',
0x63: 'Numpad3',
0x64: 'Numpad4',
0x65: 'Numpad5',
0x66: 'Numpad6',
0x67: 'Numpad7',
0x68: 'Numpad8',
0x69: 'Numpad9',
0x6a: 'NumpadMultiply',
0x6b: 'NumpadAdd',
0x6c: 'NumpadDecimal',
0x6d: 'NumpadSubtract',
0x6e: 'NumpadDecimal', // Duplicate, because buggy on Windows
0x6f: 'NumpadDivide',
0x70: 'F1',
0x71: 'F2',
0x72: 'F3',
0x73: 'F4',
0x74: 'F5',
0x75: 'F6',
0x76: 'F7',
0x77: 'F8',
0x78: 'F9',
0x79: 'F10',
0x7a: 'F11',
0x7b: 'F12',
0x7c: 'F13',
0x7d: 'F14',
0x7e: 'F15',
0x7f: 'F16',
0x80: 'F17',
0x81: 'F18',
0x82: 'F19',
0x83: 'F20',
0x84: 'F21',
0x85: 'F22',
0x86: 'F23',
0x87: 'F24',
0x90: 'NumLock',
0x91: 'ScrollLock',
0xa6: 'BrowserBack',
0xa7: 'BrowserForward',
0xa8: 'BrowserRefresh',
0xa9: 'BrowserStop',
0xaa: 'BrowserSearch',
0xab: 'BrowserFavorites',
0xac: 'BrowserHome',
0xad: 'AudioVolumeMute',
0xae: 'AudioVolumeDown',
0xaf: 'AudioVolumeUp',
0xb0: 'MediaTrackNext',
0xb1: 'MediaTrackPrevious',
0xb2: 'MediaStop',
0xb3: 'MediaPlayPause',
0xb4: 'LaunchMail',
0xb5: 'MediaSelect',
0xb6: 'LaunchApp1',
0xb7: 'LaunchApp2',
0xe1: 'AltRight', // Only when it is AltGraph
};

View File

@ -0,0 +1,173 @@
/*
* This file is auto-generated from keymaps.csv
* Database checksum sha256(76d68c10e97d37fe2ea459e210125ae41796253fb217e900bf2983ade13a7920)
* To re-generate, run:
* keymap-gen code-map --lang=js keymaps.csv html atset1
*/
export default {
"Again": 0xe005, /* html:Again (Again) -> linux:129 (KEY_AGAIN) -> atset1:57349 */
"AltLeft": 0x38, /* html:AltLeft (AltLeft) -> linux:56 (KEY_LEFTALT) -> atset1:56 */
"AltRight": 0xe038, /* html:AltRight (AltRight) -> linux:100 (KEY_RIGHTALT) -> atset1:57400 */
"ArrowDown": 0xe050, /* html:ArrowDown (ArrowDown) -> linux:108 (KEY_DOWN) -> atset1:57424 */
"ArrowLeft": 0xe04b, /* html:ArrowLeft (ArrowLeft) -> linux:105 (KEY_LEFT) -> atset1:57419 */
"ArrowRight": 0xe04d, /* html:ArrowRight (ArrowRight) -> linux:106 (KEY_RIGHT) -> atset1:57421 */
"ArrowUp": 0xe048, /* html:ArrowUp (ArrowUp) -> linux:103 (KEY_UP) -> atset1:57416 */
"AudioVolumeDown": 0xe02e, /* html:AudioVolumeDown (AudioVolumeDown) -> linux:114 (KEY_VOLUMEDOWN) -> atset1:57390 */
"AudioVolumeMute": 0xe020, /* html:AudioVolumeMute (AudioVolumeMute) -> linux:113 (KEY_MUTE) -> atset1:57376 */
"AudioVolumeUp": 0xe030, /* html:AudioVolumeUp (AudioVolumeUp) -> linux:115 (KEY_VOLUMEUP) -> atset1:57392 */
"Backquote": 0x29, /* html:Backquote (Backquote) -> linux:41 (KEY_GRAVE) -> atset1:41 */
"Backslash": 0x2b, /* html:Backslash (Backslash) -> linux:43 (KEY_BACKSLASH) -> atset1:43 */
"Backspace": 0xe, /* html:Backspace (Backspace) -> linux:14 (KEY_BACKSPACE) -> atset1:14 */
"BracketLeft": 0x1a, /* html:BracketLeft (BracketLeft) -> linux:26 (KEY_LEFTBRACE) -> atset1:26 */
"BracketRight": 0x1b, /* html:BracketRight (BracketRight) -> linux:27 (KEY_RIGHTBRACE) -> atset1:27 */
"BrowserBack": 0xe06a, /* html:BrowserBack (BrowserBack) -> linux:158 (KEY_BACK) -> atset1:57450 */
"BrowserFavorites": 0xe066, /* html:BrowserFavorites (BrowserFavorites) -> linux:156 (KEY_BOOKMARKS) -> atset1:57446 */
"BrowserForward": 0xe069, /* html:BrowserForward (BrowserForward) -> linux:159 (KEY_FORWARD) -> atset1:57449 */
"BrowserHome": 0xe032, /* html:BrowserHome (BrowserHome) -> linux:172 (KEY_HOMEPAGE) -> atset1:57394 */
"BrowserRefresh": 0xe067, /* html:BrowserRefresh (BrowserRefresh) -> linux:173 (KEY_REFRESH) -> atset1:57447 */
"BrowserSearch": 0xe065, /* html:BrowserSearch (BrowserSearch) -> linux:217 (KEY_SEARCH) -> atset1:57445 */
"BrowserStop": 0xe068, /* html:BrowserStop (BrowserStop) -> linux:128 (KEY_STOP) -> atset1:57448 */
"CapsLock": 0x3a, /* html:CapsLock (CapsLock) -> linux:58 (KEY_CAPSLOCK) -> atset1:58 */
"Comma": 0x33, /* html:Comma (Comma) -> linux:51 (KEY_COMMA) -> atset1:51 */
"ContextMenu": 0xe05d, /* html:ContextMenu (ContextMenu) -> linux:127 (KEY_COMPOSE) -> atset1:57437 */
"ControlLeft": 0x1d, /* html:ControlLeft (ControlLeft) -> linux:29 (KEY_LEFTCTRL) -> atset1:29 */
"ControlRight": 0xe01d, /* html:ControlRight (ControlRight) -> linux:97 (KEY_RIGHTCTRL) -> atset1:57373 */
"Convert": 0x79, /* html:Convert (Convert) -> linux:92 (KEY_HENKAN) -> atset1:121 */
"Copy": 0xe078, /* html:Copy (Copy) -> linux:133 (KEY_COPY) -> atset1:57464 */
"Cut": 0xe03c, /* html:Cut (Cut) -> linux:137 (KEY_CUT) -> atset1:57404 */
"Delete": 0xe053, /* html:Delete (Delete) -> linux:111 (KEY_DELETE) -> atset1:57427 */
"Digit0": 0xb, /* html:Digit0 (Digit0) -> linux:11 (KEY_0) -> atset1:11 */
"Digit1": 0x2, /* html:Digit1 (Digit1) -> linux:2 (KEY_1) -> atset1:2 */
"Digit2": 0x3, /* html:Digit2 (Digit2) -> linux:3 (KEY_2) -> atset1:3 */
"Digit3": 0x4, /* html:Digit3 (Digit3) -> linux:4 (KEY_3) -> atset1:4 */
"Digit4": 0x5, /* html:Digit4 (Digit4) -> linux:5 (KEY_4) -> atset1:5 */
"Digit5": 0x6, /* html:Digit5 (Digit5) -> linux:6 (KEY_5) -> atset1:6 */
"Digit6": 0x7, /* html:Digit6 (Digit6) -> linux:7 (KEY_6) -> atset1:7 */
"Digit7": 0x8, /* html:Digit7 (Digit7) -> linux:8 (KEY_7) -> atset1:8 */
"Digit8": 0x9, /* html:Digit8 (Digit8) -> linux:9 (KEY_8) -> atset1:9 */
"Digit9": 0xa, /* html:Digit9 (Digit9) -> linux:10 (KEY_9) -> atset1:10 */
"Eject": 0xe07d, /* html:Eject (Eject) -> linux:162 (KEY_EJECTCLOSECD) -> atset1:57469 */
"End": 0xe04f, /* html:End (End) -> linux:107 (KEY_END) -> atset1:57423 */
"Enter": 0x1c, /* html:Enter (Enter) -> linux:28 (KEY_ENTER) -> atset1:28 */
"Equal": 0xd, /* html:Equal (Equal) -> linux:13 (KEY_EQUAL) -> atset1:13 */
"Escape": 0x1, /* html:Escape (Escape) -> linux:1 (KEY_ESC) -> atset1:1 */
"F1": 0x3b, /* html:F1 (F1) -> linux:59 (KEY_F1) -> atset1:59 */
"F10": 0x44, /* html:F10 (F10) -> linux:68 (KEY_F10) -> atset1:68 */
"F11": 0x57, /* html:F11 (F11) -> linux:87 (KEY_F11) -> atset1:87 */
"F12": 0x58, /* html:F12 (F12) -> linux:88 (KEY_F12) -> atset1:88 */
"F13": 0x5d, /* html:F13 (F13) -> linux:183 (KEY_F13) -> atset1:93 */
"F14": 0x5e, /* html:F14 (F14) -> linux:184 (KEY_F14) -> atset1:94 */
"F15": 0x5f, /* html:F15 (F15) -> linux:185 (KEY_F15) -> atset1:95 */
"F16": 0x55, /* html:F16 (F16) -> linux:186 (KEY_F16) -> atset1:85 */
"F17": 0xe003, /* html:F17 (F17) -> linux:187 (KEY_F17) -> atset1:57347 */
"F18": 0xe077, /* html:F18 (F18) -> linux:188 (KEY_F18) -> atset1:57463 */
"F19": 0xe004, /* html:F19 (F19) -> linux:189 (KEY_F19) -> atset1:57348 */
"F2": 0x3c, /* html:F2 (F2) -> linux:60 (KEY_F2) -> atset1:60 */
"F20": 0x5a, /* html:F20 (F20) -> linux:190 (KEY_F20) -> atset1:90 */
"F21": 0x74, /* html:F21 (F21) -> linux:191 (KEY_F21) -> atset1:116 */
"F22": 0xe079, /* html:F22 (F22) -> linux:192 (KEY_F22) -> atset1:57465 */
"F23": 0x6d, /* html:F23 (F23) -> linux:193 (KEY_F23) -> atset1:109 */
"F24": 0x6f, /* html:F24 (F24) -> linux:194 (KEY_F24) -> atset1:111 */
"F3": 0x3d, /* html:F3 (F3) -> linux:61 (KEY_F3) -> atset1:61 */
"F4": 0x3e, /* html:F4 (F4) -> linux:62 (KEY_F4) -> atset1:62 */
"F5": 0x3f, /* html:F5 (F5) -> linux:63 (KEY_F5) -> atset1:63 */
"F6": 0x40, /* html:F6 (F6) -> linux:64 (KEY_F6) -> atset1:64 */
"F7": 0x41, /* html:F7 (F7) -> linux:65 (KEY_F7) -> atset1:65 */
"F8": 0x42, /* html:F8 (F8) -> linux:66 (KEY_F8) -> atset1:66 */
"F9": 0x43, /* html:F9 (F9) -> linux:67 (KEY_F9) -> atset1:67 */
"Find": 0xe041, /* html:Find (Find) -> linux:136 (KEY_FIND) -> atset1:57409 */
"Help": 0xe075, /* html:Help (Help) -> linux:138 (KEY_HELP) -> atset1:57461 */
"Hiragana": 0x77, /* html:Hiragana (Lang4) -> linux:91 (KEY_HIRAGANA) -> atset1:119 */
"Home": 0xe047, /* html:Home (Home) -> linux:102 (KEY_HOME) -> atset1:57415 */
"Insert": 0xe052, /* html:Insert (Insert) -> linux:110 (KEY_INSERT) -> atset1:57426 */
"IntlBackslash": 0x56, /* html:IntlBackslash (IntlBackslash) -> linux:86 (KEY_102ND) -> atset1:86 */
"IntlRo": 0x73, /* html:IntlRo (IntlRo) -> linux:89 (KEY_RO) -> atset1:115 */
"IntlYen": 0x7d, /* html:IntlYen (IntlYen) -> linux:124 (KEY_YEN) -> atset1:125 */
"KanaMode": 0x70, /* html:KanaMode (KanaMode) -> linux:93 (KEY_KATAKANAHIRAGANA) -> atset1:112 */
"Katakana": 0x78, /* html:Katakana (Lang3) -> linux:90 (KEY_KATAKANA) -> atset1:120 */
"KeyA": 0x1e, /* html:KeyA (KeyA) -> linux:30 (KEY_A) -> atset1:30 */
"KeyB": 0x30, /* html:KeyB (KeyB) -> linux:48 (KEY_B) -> atset1:48 */
"KeyC": 0x2e, /* html:KeyC (KeyC) -> linux:46 (KEY_C) -> atset1:46 */
"KeyD": 0x20, /* html:KeyD (KeyD) -> linux:32 (KEY_D) -> atset1:32 */
"KeyE": 0x12, /* html:KeyE (KeyE) -> linux:18 (KEY_E) -> atset1:18 */
"KeyF": 0x21, /* html:KeyF (KeyF) -> linux:33 (KEY_F) -> atset1:33 */
"KeyG": 0x22, /* html:KeyG (KeyG) -> linux:34 (KEY_G) -> atset1:34 */
"KeyH": 0x23, /* html:KeyH (KeyH) -> linux:35 (KEY_H) -> atset1:35 */
"KeyI": 0x17, /* html:KeyI (KeyI) -> linux:23 (KEY_I) -> atset1:23 */
"KeyJ": 0x24, /* html:KeyJ (KeyJ) -> linux:36 (KEY_J) -> atset1:36 */
"KeyK": 0x25, /* html:KeyK (KeyK) -> linux:37 (KEY_K) -> atset1:37 */
"KeyL": 0x26, /* html:KeyL (KeyL) -> linux:38 (KEY_L) -> atset1:38 */
"KeyM": 0x32, /* html:KeyM (KeyM) -> linux:50 (KEY_M) -> atset1:50 */
"KeyN": 0x31, /* html:KeyN (KeyN) -> linux:49 (KEY_N) -> atset1:49 */
"KeyO": 0x18, /* html:KeyO (KeyO) -> linux:24 (KEY_O) -> atset1:24 */
"KeyP": 0x19, /* html:KeyP (KeyP) -> linux:25 (KEY_P) -> atset1:25 */
"KeyQ": 0x10, /* html:KeyQ (KeyQ) -> linux:16 (KEY_Q) -> atset1:16 */
"KeyR": 0x13, /* html:KeyR (KeyR) -> linux:19 (KEY_R) -> atset1:19 */
"KeyS": 0x1f, /* html:KeyS (KeyS) -> linux:31 (KEY_S) -> atset1:31 */
"KeyT": 0x14, /* html:KeyT (KeyT) -> linux:20 (KEY_T) -> atset1:20 */
"KeyU": 0x16, /* html:KeyU (KeyU) -> linux:22 (KEY_U) -> atset1:22 */
"KeyV": 0x2f, /* html:KeyV (KeyV) -> linux:47 (KEY_V) -> atset1:47 */
"KeyW": 0x11, /* html:KeyW (KeyW) -> linux:17 (KEY_W) -> atset1:17 */
"KeyX": 0x2d, /* html:KeyX (KeyX) -> linux:45 (KEY_X) -> atset1:45 */
"KeyY": 0x15, /* html:KeyY (KeyY) -> linux:21 (KEY_Y) -> atset1:21 */
"KeyZ": 0x2c, /* html:KeyZ (KeyZ) -> linux:44 (KEY_Z) -> atset1:44 */
"Lang1": 0x72, /* html:Lang1 (Lang1) -> linux:122 (KEY_HANGEUL) -> atset1:114 */
"Lang2": 0x71, /* html:Lang2 (Lang2) -> linux:123 (KEY_HANJA) -> atset1:113 */
"Lang3": 0x78, /* html:Lang3 (Lang3) -> linux:90 (KEY_KATAKANA) -> atset1:120 */
"Lang4": 0x77, /* html:Lang4 (Lang4) -> linux:91 (KEY_HIRAGANA) -> atset1:119 */
"Lang5": 0x76, /* html:Lang5 (Lang5) -> linux:85 (KEY_ZENKAKUHANKAKU) -> atset1:118 */
"LaunchApp1": 0xe06b, /* html:LaunchApp1 (LaunchApp1) -> linux:157 (KEY_COMPUTER) -> atset1:57451 */
"LaunchApp2": 0xe021, /* html:LaunchApp2 (LaunchApp2) -> linux:140 (KEY_CALC) -> atset1:57377 */
"LaunchMail": 0xe06c, /* html:LaunchMail (LaunchMail) -> linux:155 (KEY_MAIL) -> atset1:57452 */
"MediaPlayPause": 0xe022, /* html:MediaPlayPause (MediaPlayPause) -> linux:164 (KEY_PLAYPAUSE) -> atset1:57378 */
"MediaSelect": 0xe06d, /* html:MediaSelect (MediaSelect) -> linux:226 (KEY_MEDIA) -> atset1:57453 */
"MediaStop": 0xe024, /* html:MediaStop (MediaStop) -> linux:166 (KEY_STOPCD) -> atset1:57380 */
"MediaTrackNext": 0xe019, /* html:MediaTrackNext (MediaTrackNext) -> linux:163 (KEY_NEXTSONG) -> atset1:57369 */
"MediaTrackPrevious": 0xe010, /* html:MediaTrackPrevious (MediaTrackPrevious) -> linux:165 (KEY_PREVIOUSSONG) -> atset1:57360 */
"MetaLeft": 0xe05b, /* html:MetaLeft (MetaLeft) -> linux:125 (KEY_LEFTMETA) -> atset1:57435 */
"MetaRight": 0xe05c, /* html:MetaRight (MetaRight) -> linux:126 (KEY_RIGHTMETA) -> atset1:57436 */
"Minus": 0xc, /* html:Minus (Minus) -> linux:12 (KEY_MINUS) -> atset1:12 */
"NonConvert": 0x7b, /* html:NonConvert (NonConvert) -> linux:94 (KEY_MUHENKAN) -> atset1:123 */
"NumLock": 0x45, /* html:NumLock (NumLock) -> linux:69 (KEY_NUMLOCK) -> atset1:69 */
"Numpad0": 0x52, /* html:Numpad0 (Numpad0) -> linux:82 (KEY_KP0) -> atset1:82 */
"Numpad1": 0x4f, /* html:Numpad1 (Numpad1) -> linux:79 (KEY_KP1) -> atset1:79 */
"Numpad2": 0x50, /* html:Numpad2 (Numpad2) -> linux:80 (KEY_KP2) -> atset1:80 */
"Numpad3": 0x51, /* html:Numpad3 (Numpad3) -> linux:81 (KEY_KP3) -> atset1:81 */
"Numpad4": 0x4b, /* html:Numpad4 (Numpad4) -> linux:75 (KEY_KP4) -> atset1:75 */
"Numpad5": 0x4c, /* html:Numpad5 (Numpad5) -> linux:76 (KEY_KP5) -> atset1:76 */
"Numpad6": 0x4d, /* html:Numpad6 (Numpad6) -> linux:77 (KEY_KP6) -> atset1:77 */
"Numpad7": 0x47, /* html:Numpad7 (Numpad7) -> linux:71 (KEY_KP7) -> atset1:71 */
"Numpad8": 0x48, /* html:Numpad8 (Numpad8) -> linux:72 (KEY_KP8) -> atset1:72 */
"Numpad9": 0x49, /* html:Numpad9 (Numpad9) -> linux:73 (KEY_KP9) -> atset1:73 */
"NumpadAdd": 0x4e, /* html:NumpadAdd (NumpadAdd) -> linux:78 (KEY_KPPLUS) -> atset1:78 */
"NumpadComma": 0x7e, /* html:NumpadComma (NumpadComma) -> linux:121 (KEY_KPCOMMA) -> atset1:126 */
"NumpadDecimal": 0x53, /* html:NumpadDecimal (NumpadDecimal) -> linux:83 (KEY_KPDOT) -> atset1:83 */
"NumpadDivide": 0xe035, /* html:NumpadDivide (NumpadDivide) -> linux:98 (KEY_KPSLASH) -> atset1:57397 */
"NumpadEnter": 0xe01c, /* html:NumpadEnter (NumpadEnter) -> linux:96 (KEY_KPENTER) -> atset1:57372 */
"NumpadEqual": 0x59, /* html:NumpadEqual (NumpadEqual) -> linux:117 (KEY_KPEQUAL) -> atset1:89 */
"NumpadMultiply": 0x37, /* html:NumpadMultiply (NumpadMultiply) -> linux:55 (KEY_KPASTERISK) -> atset1:55 */
"NumpadParenLeft": 0xe076, /* html:NumpadParenLeft (NumpadParenLeft) -> linux:179 (KEY_KPLEFTPAREN) -> atset1:57462 */
"NumpadParenRight": 0xe07b, /* html:NumpadParenRight (NumpadParenRight) -> linux:180 (KEY_KPRIGHTPAREN) -> atset1:57467 */
"NumpadSubtract": 0x4a, /* html:NumpadSubtract (NumpadSubtract) -> linux:74 (KEY_KPMINUS) -> atset1:74 */
"Open": 0x64, /* html:Open (Open) -> linux:134 (KEY_OPEN) -> atset1:100 */
"PageDown": 0xe051, /* html:PageDown (PageDown) -> linux:109 (KEY_PAGEDOWN) -> atset1:57425 */
"PageUp": 0xe049, /* html:PageUp (PageUp) -> linux:104 (KEY_PAGEUP) -> atset1:57417 */
"Paste": 0x65, /* html:Paste (Paste) -> linux:135 (KEY_PASTE) -> atset1:101 */
"Pause": 0xe046, /* html:Pause (Pause) -> linux:119 (KEY_PAUSE) -> atset1:57414 */
"Period": 0x34, /* html:Period (Period) -> linux:52 (KEY_DOT) -> atset1:52 */
"Power": 0xe05e, /* html:Power (Power) -> linux:116 (KEY_POWER) -> atset1:57438 */
"PrintScreen": 0x54, /* html:PrintScreen (PrintScreen) -> linux:99 (KEY_SYSRQ) -> atset1:84 */
"Props": 0xe006, /* html:Props (Props) -> linux:130 (KEY_PROPS) -> atset1:57350 */
"Quote": 0x28, /* html:Quote (Quote) -> linux:40 (KEY_APOSTROPHE) -> atset1:40 */
"ScrollLock": 0x46, /* html:ScrollLock (ScrollLock) -> linux:70 (KEY_SCROLLLOCK) -> atset1:70 */
"Semicolon": 0x27, /* html:Semicolon (Semicolon) -> linux:39 (KEY_SEMICOLON) -> atset1:39 */
"ShiftLeft": 0x2a, /* html:ShiftLeft (ShiftLeft) -> linux:42 (KEY_LEFTSHIFT) -> atset1:42 */
"ShiftRight": 0x36, /* html:ShiftRight (ShiftRight) -> linux:54 (KEY_RIGHTSHIFT) -> atset1:54 */
"Slash": 0x35, /* html:Slash (Slash) -> linux:53 (KEY_SLASH) -> atset1:53 */
"Sleep": 0xe05f, /* html:Sleep (Sleep) -> linux:142 (KEY_SLEEP) -> atset1:57439 */
"Space": 0x39, /* html:Space (Space) -> linux:57 (KEY_SPACE) -> atset1:57 */
"Suspend": 0xe025, /* html:Suspend (Suspend) -> linux:205 (KEY_SUSPEND) -> atset1:57381 */
"Tab": 0xf, /* html:Tab (Tab) -> linux:15 (KEY_TAB) -> atset1:15 */
"Undo": 0xe007, /* html:Undo (Undo) -> linux:131 (KEY_UNDO) -> atset1:57351 */
"WakeUp": 0xe063, /* html:WakeUp (WakeUp) -> linux:143 (KEY_WAKEUP) -> atset1:57443 */
};

Some files were not shown because too many files have changed in this diff Show More