1
0
mirror of https://github.com/fcwu/docker-ubuntu-vnc-desktop synced 2026-08-05 16:12:41 +02:00

Merge branch 'develop' into bionic-lxqt

This commit is contained in:
Doro Wu
2020-04-15 08:40:32 +08:00
66 changed files with 2211 additions and 837 deletions
+50
View File
@@ -0,0 +1,50 @@
server {
listen 80 default_server;
# listen [::]:80 default_server ipv6only=on;
#_SSL_PORT_#listen 443 ssl default_server;
#_SSL_PORT_#listen [::]:443 ssl default_server ipv6only=on;
#_SSL_PORT_#ssl_certificate /etc/nginx/ssl/nginx.crt;
#_SSL_PORT_#ssl_certificate_key /etc/nginx/ssl/nginx.key;
#_HTTP_PASSWORD_#auth_basic "Private Property";
#_HTTP_PASSWORD_#auth_basic_user_file /etc/nginx/.htpasswd;
root /usr/local/lib/web/frontend/;
index index.html index.htm;
location ~ /api/ {
try_files $uri @api;
}
location ~ /resize$ {
try_files $uri @api;
}
#_RELATIVE_URL_ROOT_location /_RELATIVE_URL_ROOT_/ {
#_RELATIVE_URL_ROOT_ rewrite /_RELATIVE_URL_ROOT_/(.*) /$1 break;
#_RELATIVE_URL_ROOT_ root /usr/local/lib/web/frontend/;
#_RELATIVE_URL_ROOT_}
location ~ /websockify$ {
#_RELATIVE_URL_ROOT_rewrite /_RELATIVE_URL_ROOT_/(.*) $1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_connect_timeout 7d;
proxy_send_timeout 7d;
proxy_read_timeout 7d;
proxy_pass http://127.0.0.1:6081;
}
location @api {
#_RELATIVE_URL_ROOT_rewrite /_RELATIVE_URL_ROOT_/(.*) $1 break;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:6079;
max_ranges 0;
}
}
@@ -0,0 +1,62 @@
[supervisord]
redirect_stderr=true
stopsignal=QUIT
autorestart=true
directory=/root
[program:nginx]
priority=10
command=nginx -c /etc/nginx/nginx.conf -g 'daemon off;'
[program:web]
priority=10
directory=/usr/local/lib/web/backend
command=/usr/local/lib/web/backend/run.py
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/1
stderr_logfile_maxbytes=0
[group:x]
# programs=xvfb,wm,lxpanel,pcmanfm,x11vnc,novnc
programs=xvfb,wm,lxpanel,x11vnc,novnc
[program:wm]
priority=15
command=/usr/bin/openbox
environment=DISPLAY=":1",HOME="/root",USER="root"
[program:lxpanel]
priority=15
directory=%HOME%
command=/usr/bin/startlxqt
user=%USER%
environment=DISPLAY=":1",HOME="%HOME%",USER="%USER%"
# [program:pcmanfm]
# priority=15
# directory=%HOME%
# command=/usr/bin/pcmanfm --desktop --profile LXDE
# user=%USER%
# environment=DISPLAY=":1",HOME="%HOME%",USER="%USER%"
[program:xvfb]
priority=10
command=/usr/local/bin/xvfb.sh
stopsignal=KILL
[program:x11vnc]
priority=20
command=x11vnc -display :1 -xkb -forever -shared -repeat
[program:novnc]
priority=25
directory=/usr/local/lib/web/frontend/static/novnc
command=bash /usr/local/lib/web/frontend/static/novnc/utils/launch.sh --listen 6081
stopasgroup=true
@@ -0,0 +1,86 @@
[supervisord]
redirect_stderr=true
stopsignal=QUIT
autorestart=true
directory=/root
[program:nginx]
priority=10
command=nginx -c /etc/nginx/nginx.conf -g 'daemon off;'
[program:web]
priority=10
directory=/usr/local/lib/web/backend
command=/usr/local/lib/web/backend/run.py
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/1
stderr_logfile_maxbytes=0
{% if desktop == "lxde" %}
[group:x]
programs=xvfb,wm,lxpanel,pcmanfm,x11vnc,novnc
[program:wm]
priority=15
command=/usr/bin/openbox
environment=DISPLAY=":1",HOME="/root",USER="root"
[program:lxpanel]
priority=15
directory=%HOME%
command=/usr/bin/lxpanel --profile LXDE
user=%USER%
environment=DISPLAY=":1",HOME="%HOME%",USER="%USER%"
[program:pcmanfm]
priority=15
directory=%HOME%
command=/usr/bin/pcmanfm --desktop --profile LXDE
user=%USER%
environment=DISPLAY=":1",HOME="%HOME%",USER="%USER%"
{% endif %}
{% if desktop == "lxqt" %}
[group:x]
programs=xvfb,wm,lxpanel,x11vnc,novnc
[program:wm]
priority=15
command=/usr/bin/openbox
environment=DISPLAY=":1",HOME="/root",USER="root"
[program:lxpanel]
priority=15
directory=%HOME%
command=/usr/bin/startlxqt
user=%USER%
environment=DISPLAY=":1",HOME="%HOME%",USER="%USER%"
{% endif %}
{% if desktop == "xfce4" %}
[group:x]
programs=xvfb,lxpanel,x11vnc,novnc
[program:lxpanel]
priority=15
directory=%HOME%
command=/usr/bin/startxfce4
user=%USER%
environment=DISPLAY=":1",HOME="%HOME%",USER="%USER%"
{% endif %}
[program:xvfb]
priority=10
command=/usr/local/bin/xvfb.sh
stopsignal=KILL
[program:x11vnc]
priority=20
command=x11vnc -display :1 -xkb -forever -shared -repeat
[program:novnc]
priority=25
directory=/usr/local/lib/web/frontend/static/novnc
command=bash /usr/local/lib/web/frontend/static/novnc/utils/launch.sh --listen 6081
stopasgroup=true
+4
View File
@@ -0,0 +1,4 @@
pcm.loop {
type plug
slave.pcm "hw:Loopback,2,0"
}
@@ -0,0 +1,187 @@
[General]
AllowGrabBaseKeypad=true
AllowGrabBaseSpecial=false
AllowGrabLocks=false
AllowGrabMiscKeypad=true
AllowGrabMiscSpecial=true
MultipleActionsBehaviour=first
[Alt%2BF1.1]
Comment=Show/hide main menu
Enabled=true
path=/panel/mainmenu/show_hide
[Alt%2BF2.2]
Comment=Show/hide runner dialog
Enabled=true
path=/runner/show_hide_dialog
[Control%2BAlt%2BD.3]
Comment=Show desktop
Enabled=true
path=/panel/showdesktop/show_hide
[Control%2BAlt%2BE.4]
Comment=Pcmanfm
Enabled=true
Exec=pcmanfm-qt
[Control%2BAlt%2BI.5]
Comment=Web browser
Enabled=true
Exec=xdg-open, about:blank
[Control%2BAlt%2BT.6]
Comment=QTerminal
Enabled=true
Exec=qterminal
[Control%2BF1.7]
Comment=Switch to desktop 1
Enabled=true
path=/panel/desktopswitch/desktop_1
[Control%2BF10.8]
Comment=Switch to desktop 10
Enabled=true
path=/panel/desktopswitch/desktop_10
[Control%2BF11.9]
Comment=Switch to desktop 11
Enabled=true
path=/panel/desktopswitch/desktop_11
[Control%2BF12.10]
Comment=Switch to desktop 12
Enabled=true
path=/panel/desktopswitch/desktop_12
[Control%2BF2.11]
Comment=Switch to desktop 2
Enabled=true
path=/panel/desktopswitch/desktop_2
[Control%2BF3.12]
Comment=Switch to desktop 3
Enabled=true
path=/panel/desktopswitch/desktop_3
[Control%2BF4.13]
Comment=Switch to desktop 4
Enabled=true
path=/panel/desktopswitch/desktop_4
[Control%2BF5.14]
Comment=Switch to desktop 5
Enabled=true
path=/panel/desktopswitch/desktop_5
[Control%2BF6.15]
Comment=Switch to desktop 6
Enabled=true
path=/panel/desktopswitch/desktop_6
[Control%2BF7.16]
Comment=Switch to desktop 7
Enabled=true
path=/panel/desktopswitch/desktop_7
[Control%2BF8.17]
Comment=Switch to desktop 8
Enabled=true
path=/panel/desktopswitch/desktop_8
[Control%2BF9.18]
Comment=Switch to desktop 9
Enabled=true
path=/panel/desktopswitch/desktop_9
[Meta%2B0.19]
Comment=Activate task 10
Enabled=true
path=/panel/taskbar/task_10
[Meta%2B1.20]
Comment=Activate task 1
Enabled=true
path=/panel/taskbar/task_1
[Meta%2B2.21]
Comment=Activate task 2
Enabled=true
path=/panel/taskbar/task_2
[Meta%2B3.22]
Comment=Activate task 3
Enabled=true
path=/panel/taskbar/task_3
[Meta%2B4.23]
Comment=Activate task 4
Enabled=true
path=/panel/taskbar/task_4
[Meta%2B5.24]
Comment=Activate task 5
Enabled=true
path=/panel/taskbar/task_5
[Meta%2B6.25]
Comment=Activate task 6
Enabled=true
path=/panel/taskbar/task_6
[Meta%2B7.26]
Comment=Activate task 7
Enabled=true
path=/panel/taskbar/task_7
[Meta%2B8.27]
Comment=Activate task 8
Enabled=true
path=/panel/taskbar/task_8
[Meta%2B9.28]
Comment=Activate task 9
Enabled=true
path=/panel/taskbar/task_9
[Print.29]
Comment=screen shot
Enabled=true
Exec=lximage-qt, -s
[Shift%2BControl%2BF6.30]
Comment=\x2600 \x2193
Enabled=true
Exec=lxqt-config-brightness, -d
[Shift%2BControl%2BF7.31]
Comment=\x2600 \x2191
Enabled=true
Exec=lxqt-config-brightness, -i
[XF86AudioLowerVolume.32]
Comment=Decrease sound volume
Enabled=true
path=/panel/volume/down
[XF86AudioMute.33]
Comment=Mute/unmute sound volume
Enabled=true
path=/panel/volume/mute
[XF86AudioRaiseVolume.34]
Comment=Increase sound volume
Enabled=true
path=/panel/volume/up
[XF86MonBrightnessDown.35]
Comment=\x2600 \x2193
Enabled=true
Exec=lxqt-config-brightness, -d
[XF86MonBrightnessUp.36]
Comment=\x2600 \x2191
Enabled=true
Exec=lxqt-config-brightness, -i
@@ -0,0 +1,6 @@
[General]
__userfile__=true
enableBatteryWatcher=false
enableIdlenessWatcher=true
enableLidWatcher=false
runCheckLevel=1
@@ -0,0 +1,2 @@
[General]
__userfile__=true
+4
View File
@@ -0,0 +1,4 @@
[General]
__userfile__=true
icon_theme=LoginIcons
theme=light
@@ -0,0 +1,2 @@
[General]
__userfile__=true
+46
View File
@@ -0,0 +1,46 @@
[General]
__userfile__=true
[desktopswitch]
alignment=Left
type=desktopswitch
[mainmenu]
alignment=Left
type=mainmenu
[panel1]
alignment=-1
animation-duration=0
background-color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0)
background-image=
desktop=0
font-color=@Variant(\0\0\0\x43\0\xff\xff\0\0\0\0\0\0\0\0)
hidable=false
iconSize=22
lineCount=1
lockPanel=false
opacity=100
panelSize=32
plugins=mainmenu, desktopswitch, quicklaunch, taskbar, clock, showdesktop
position=Bottom
reserve-space=true
show-delay=0
width=100
width-percent=true
[quicklaunch]
alignment=Left
apps\1\desktop=/usr/share/applications/chromium-browser.desktop
apps\2\desktop=/usr/share/applications/pcmanfm-qt.desktop
apps\3\desktop=/usr/share/applications/qterminal.desktop
apps\size=3
type=quicklaunch
[showdesktop]
alignment=Right
type=showdesktop
[taskbar]
alignment=Left
type=taskbar
+2
View File
@@ -0,0 +1,2 @@
[General]
__userfile__=true
+2
View File
@@ -0,0 +1,2 @@
[General]
__userfile__=true
+744
View File
@@ -0,0 +1,744 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Do not edit this file, it will be overwritten on install.
Copy the file to $HOME/.config/openbox/lxqt-rc.xml instead. -->
<openbox_config xmlns="http://openbox.org/3.4/rc"
xmlns:xi="http://www.w3.org/2001/XInclude">
<resistance>
<strength>10</strength>
<screen_edge_strength>20</screen_edge_strength>
</resistance>
<focus>
<focusNew>yes</focusNew>
<!-- always try to focus new windows when they appear. other rules do
apply -->
<followMouse>no</followMouse>
<!-- move focus to a window when you move the mouse into it -->
<focusLast>yes</focusLast>
<!-- focus the last used window when changing desktops, instead of the one
under the mouse pointer. when followMouse is enabled -->
<underMouse>no</underMouse>
<!-- move focus under the mouse, even when the mouse is not moving -->
<focusDelay>200</focusDelay>
<!-- when followMouse is enabled, the mouse must be inside the window for
this many milliseconds (1000 = 1 sec) before moving focus to it -->
<raiseOnFocus>no</raiseOnFocus>
<!-- when followMouse is enabled, and a window is given focus by moving the
mouse into it, also raise the window -->
</focus>
<placement>
<policy>Smart</policy>
<!-- 'Smart' or 'UnderMouse' -->
<center>yes</center>
<!-- whether to place windows in the center of the free area found or
the top left corner -->
<monitor>Primary</monitor>
<!-- with Smart placement on a multi-monitor system, try to place new windows
on: 'Any' - any monitor, 'Mouse' - where the mouse is, 'Active' - where
the active window is, 'Primary' - only on the primary monitor -->
<primaryMonitor>1</primaryMonitor>
<!-- The monitor where Openbox should place popup dialogs such as the
focus cycling popup, or the desktop switch popup. It can be an index
from 1, specifying a particular monitor. Or it can be one of the
following: 'Mouse' - where the mouse is, or
'Active' - where the active window is -->
</placement>
<theme>
<name>Onyx</name>
<titleLayout>NLIMC</titleLayout>
<!--
available characters are NDSLIMC, each can occur at most once.
N: window icon
L: window label (AKA title).
I: iconify
M: maximize
C: close
S: shade (roll up/down)
D: omnipresent (on all desktops).
-->
<keepBorder>yes</keepBorder>
<animateIconify>yes</animateIconify>
<font place="ActiveWindow">
<name>sans</name>
<size>10</size>
<!-- font size in points -->
<weight>bold</weight>
<!-- 'bold' or 'normal' -->
<slant>normal</slant>
<!-- 'italic' or 'normal' -->
</font>
<font place="InactiveWindow">
<name>sans</name>
<size>10</size>
<!-- font size in points -->
<weight>bold</weight>
<!-- 'bold' or 'normal' -->
<slant>normal</slant>
<!-- 'italic' or 'normal' -->
</font>
<font place="MenuHeader">
<name>sans</name>
<size>9</size>
<!-- font size in points -->
<weight>normal</weight>
<!-- 'bold' or 'normal' -->
<slant>normal</slant>
<!-- 'italic' or 'normal' -->
</font>
<font place="MenuItem">
<name>sans</name>
<size>9</size>
<!-- font size in points -->
<weight>normal</weight>
<!-- 'bold' or 'normal' -->
<slant>normal</slant>
<!-- 'italic' or 'normal' -->
</font>
<font place="ActiveOnScreenDisplay">
<name>sans</name>
<size>9</size>
<!-- font size in points -->
<weight>bold</weight>
<!-- 'bold' or 'normal' -->
<slant>normal</slant>
<!-- 'italic' or 'normal' -->
</font>
<font place="InactiveOnScreenDisplay">
<name>sans</name>
<size>9</size>
<!-- font size in points -->
<weight>bold</weight>
<!-- 'bold' or 'normal' -->
<slant>normal</slant>
<!-- 'italic' or 'normal' -->
</font>
</theme>
<desktops>
<!-- this stuff is only used at startup, pagers allow you to change them
during a session
these are default values to use when other ones are not already set
by other applications, or saved in your session
use obconf if you want to change these without having to log out
and back in -->
<number>2</number>
<firstdesk>1</firstdesk>
<names>
<!-- set names up here if you want to, like this:
<name>desktop 1</name>
<name>desktop 2</name>
-->
</names>
<popupTime>875</popupTime>
<!-- The number of milliseconds to show the popup for when switching
desktops. Set this to 0 to disable the popup. -->
</desktops>
<resize>
<drawContents>yes</drawContents>
<popupShow>Nonpixel</popupShow>
<!-- 'Always', 'Never', or 'Nonpixel' (xterms and such) -->
<popupPosition>Center</popupPosition>
<!-- 'Center', 'Top', or 'Fixed' -->
<popupFixedPosition>
<!-- these are used if popupPosition is set to 'Fixed' -->
<x>10</x>
<!-- positive number for distance from left edge, negative number for
distance from right edge, or 'Center' -->
<y>10</y>
<!-- positive number for distance from top edge, negative number for
distance from bottom edge, or 'Center' -->
</popupFixedPosition>
</resize>
<!-- You can reserve a portion of your screen where windows will not cover when
they are maximized, or when they are initially placed.
Many programs reserve space automatically, but you can use this in other
cases. -->
<margins>
<top>0</top>
<bottom>0</bottom>
<left>0</left>
<right>0</right>
</margins>
<dock>
<position>TopLeft</position>
<!-- (Top|Bottom)(Left|Right|)|Top|Bottom|Left|Right|Floating -->
<floatingX>0</floatingX>
<floatingY>0</floatingY>
<noStrut>no</noStrut>
<stacking>Above</stacking>
<!-- 'Above', 'Normal', or 'Below' -->
<direction>Vertical</direction>
<!-- 'Vertical' or 'Horizontal' -->
<autoHide>no</autoHide>
<hideDelay>300</hideDelay>
<!-- in milliseconds (1000 = 1 second) -->
<showDelay>300</showDelay>
<!-- in milliseconds (1000 = 1 second) -->
<moveButton>Middle</moveButton>
<!-- 'Left', 'Middle', 'Right' -->
</dock>
<keyboard>
<chainQuitKey>C-g</chainQuitKey>
<!-- Keybindings for desktop switching -->
<keybind key="C-A-Left">
<action name="GoToDesktop"><to>left</to><wrap>no</wrap></action>
</keybind>
<keybind key="C-A-Right">
<action name="GoToDesktop"><to>right</to><wrap>no</wrap></action>
</keybind>
<keybind key="C-A-Up">
<action name="GoToDesktop"><to>up</to><wrap>no</wrap></action>
</keybind>
<keybind key="C-A-Down">
<action name="GoToDesktop"><to>down</to><wrap>no</wrap></action>
</keybind>
<keybind key="S-A-Left">
<action name="SendToDesktop"><to>left</to><wrap>no</wrap></action>
</keybind>
<keybind key="S-A-Right">
<action name="SendToDesktop"><to>right</to><wrap>no</wrap></action>
</keybind>
<keybind key="S-A-Up">
<action name="SendToDesktop"><to>up</to><wrap>no</wrap></action>
</keybind>
<keybind key="S-A-Down">
<action name="SendToDesktop"><to>down</to><wrap>no</wrap></action>
</keybind>
<keybind key="W-F1">
<action name="GoToDesktop"><to>1</to></action>
</keybind>
<keybind key="W-F2">
<action name="GoToDesktop"><to>2</to></action>
</keybind>
<keybind key="W-F3">
<action name="GoToDesktop"><to>3</to></action>
</keybind>
<keybind key="W-F4">
<action name="GoToDesktop"><to>4</to></action>
</keybind>
<keybind key="W-d">
<action name="ToggleShowDesktop"/>
</keybind>
<!-- Keybindings for windows -->
<keybind key="A-F4">
<action name="Close"/>
</keybind>
<keybind key="A-Escape">
<action name="Lower"/>
<action name="FocusToBottom"/>
<action name="Unfocus"/>
</keybind>
<keybind key="A-space">
<action name="ShowMenu"><menu>client-menu</menu></action>
</keybind>
<!-- Keybindings for window switching -->
<keybind key="A-Tab">
<action name="NextWindow">
<finalactions>
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</finalactions>
</action>
</keybind>
<keybind key="A-S-Tab">
<action name="PreviousWindow">
<finalactions>
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</finalactions>
</action>
</keybind>
<keybind key="C-A-Tab">
<action name="NextWindow">
<panels>yes</panels><desktop>yes</desktop>
<finalactions>
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</finalactions>
</action>
</keybind>
<!-- Keybindings for window switching with the arrow keys -->
<keybind key="W-S-Right">
<action name="DirectionalCycleWindows">
<direction>right</direction>
</action>
</keybind>
<keybind key="W-S-Left">
<action name="DirectionalCycleWindows">
<direction>left</direction>
</action>
</keybind>
<keybind key="W-S-Up">
<action name="DirectionalCycleWindows">
<direction>up</direction>
</action>
</keybind>
<keybind key="W-S-Down">
<action name="DirectionalCycleWindows">
<direction>down</direction>
</action>
</keybind>
<!-- Keybindings for running applications.
Commented out as application shortcuts should be handled by lxqt-globalkeys in LXQt sessions.
<keybind key="W-q">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Qupzilla</name>
</startupnotify>
<command>qupzilla</command>
</action>
</keybind> -->
</keyboard>
<mouse>
<dragThreshold>1</dragThreshold>
<!-- number of pixels the mouse must move before a drag begins -->
<doubleClickTime>500</doubleClickTime>
<!-- in milliseconds (1000 = 1 second) -->
<screenEdgeWarpTime>400</screenEdgeWarpTime>
<!-- Time before changing desktops when the pointer touches the edge of the
screen while moving a window, in milliseconds (1000 = 1 second).
Set this to 0 to disable warping -->
<screenEdgeWarpMouse>false</screenEdgeWarpMouse>
<!-- Set this to TRUE to move the mouse pointer across the desktop when
switching due to hitting the edge of the screen -->
<context name="Frame">
<mousebind button="A-Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
<mousebind button="A-Left" action="Click">
<action name="Unshade"/>
</mousebind>
<mousebind button="A-Left" action="Drag">
<action name="Move"/>
</mousebind>
<mousebind button="A-Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="A-Right" action="Drag">
<action name="Resize"/>
</mousebind>
<mousebind button="A-Middle" action="Press">
<action name="Lower"/>
<action name="FocusToBottom"/>
<action name="Unfocus"/>
</mousebind>
<mousebind button="A-Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="A-Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
<mousebind button="C-A-Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="C-A-Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
<mousebind button="A-S-Up" action="Click">
<action name="SendToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="A-S-Down" action="Click">
<action name="SendToDesktop"><to>next</to></action>
</mousebind>
</context>
<context name="Titlebar">
<mousebind button="Left" action="Drag">
<action name="Move"/>
</mousebind>
<mousebind button="Left" action="DoubleClick">
<action name="ToggleMaximize"/>
</mousebind>
<mousebind button="Up" action="Click">
<action name="if">
<shaded>no</shaded>
<then>
<action name="Shade"/>
<action name="FocusToBottom"/>
<action name="Unfocus"/>
<action name="Lower"/>
</then>
</action>
</mousebind>
<mousebind button="Down" action="Click">
<action name="if">
<shaded>yes</shaded>
<then>
<action name="Unshade"/>
<action name="Raise"/>
</then>
</action>
</mousebind>
</context>
<context name="Titlebar Top Right Bottom Left TLCorner TRCorner BRCorner BLCorner">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Middle" action="Press">
<action name="Lower"/>
<action name="FocusToBottom"/>
<action name="Unfocus"/>
</mousebind>
<mousebind button="Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="ShowMenu"><menu>client-menu</menu></action>
</mousebind>
</context>
<context name="Top">
<mousebind button="Left" action="Drag">
<action name="Resize"><edge>top</edge></action>
</mousebind>
</context>
<context name="Left">
<mousebind button="Left" action="Drag">
<action name="Resize"><edge>left</edge></action>
</mousebind>
</context>
<context name="Right">
<mousebind button="Left" action="Drag">
<action name="Resize"><edge>right</edge></action>
</mousebind>
</context>
<context name="Bottom">
<mousebind button="Left" action="Drag">
<action name="Resize"><edge>bottom</edge></action>
</mousebind>
<mousebind button="Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="ShowMenu"><menu>client-menu</menu></action>
</mousebind>
</context>
<context name="TRCorner BRCorner TLCorner BLCorner">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Left" action="Drag">
<action name="Resize"/>
</mousebind>
</context>
<context name="Client">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
<mousebind button="Middle" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
<mousebind button="Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
</context>
<context name="Icon">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
<action name="ShowMenu"><menu>client-menu</menu></action>
</mousebind>
<mousebind button="Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="ShowMenu"><menu>client-menu</menu></action>
</mousebind>
</context>
<context name="AllDesktops">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Left" action="Click">
<action name="ToggleOmnipresent"/>
</mousebind>
</context>
<context name="Shade">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
<mousebind button="Left" action="Click">
<action name="ToggleShade"/>
</mousebind>
</context>
<context name="Iconify">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
<mousebind button="Left" action="Click">
<action name="Iconify"/>
</mousebind>
</context>
<context name="Maximize">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Middle" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Left" action="Click">
<action name="ToggleMaximize"/>
</mousebind>
<mousebind button="Middle" action="Click">
<action name="ToggleMaximize"><direction>vertical</direction></action>
</mousebind>
<mousebind button="Right" action="Click">
<action name="ToggleMaximize"><direction>horizontal</direction></action>
</mousebind>
</context>
<context name="Close">
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
<action name="Unshade"/>
</mousebind>
<mousebind button="Left" action="Click">
<action name="Close"/>
</mousebind>
</context>
<context name="Desktop">
<mousebind button="Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
<mousebind button="A-Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="A-Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
<mousebind button="C-A-Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="C-A-Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
<mousebind button="Left" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
<mousebind button="Right" action="Press">
<action name="Focus"/>
<action name="Raise"/>
</mousebind>
</context>
<context name="Root">
<!-- Menus -->
<mousebind button="Middle" action="Press">
<action name="ShowMenu"><menu>client-list-combined-menu</menu></action>
</mousebind>
<mousebind button="Right" action="Press">
<action name="ShowMenu"><menu>root-menu</menu></action>
</mousebind>
</context>
<context name="MoveResize">
<mousebind button="Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
<mousebind button="A-Up" action="Click">
<action name="GoToDesktop"><to>previous</to></action>
</mousebind>
<mousebind button="A-Down" action="Click">
<action name="GoToDesktop"><to>next</to></action>
</mousebind>
</context>
</mouse>
<menu>
<!-- You can specify more than one menu file in here and they are all loaded,
just don't make menu ids clash or, well, it'll be kind of pointless -->
<!-- default menu file (or custom one in $HOME/.config/openbox/) -->
<file>menu.xml</file>
<hideDelay>200</hideDelay>
<!-- if a press-release lasts longer than this setting (in milliseconds), the
menu is hidden again -->
<middle>no</middle>
<!-- center submenus vertically about the parent entry -->
<submenuShowDelay>100</submenuShowDelay>
<!-- time to delay before showing a submenu after hovering over the parent
entry.
if this is a negative value, then the delay is infinite and the
submenu will not be shown until it is clicked on -->
<submenuHideDelay>400</submenuHideDelay>
<!-- time to delay before hiding a submenu when selecting another
entry in parent menu
if this is a negative value, then the delay is infinite and the
submenu will not be hidden until a different submenu is opened -->
<showIcons>yes</showIcons>
<!-- controls if icons appear in the client-list-(combined-)menu -->
<manageDesktops>yes</manageDesktops>
<!-- show the manage desktops section in the client-list-(combined-)menu -->
</menu>
<applications>
<!--
# this is an example with comments through out. use these to make your
# own rules, but without the comments of course.
# you may use one or more of the name/class/role/title/type rules to specify
# windows to match
<application name="the window's _OB_APP_NAME property (see obxprop)"
class="the window's _OB_APP_CLASS property (see obxprop)"
groupname="the window's _OB_APP_GROUP_NAME property (see obxprop)"
groupclass="the window's _OB_APP_GROUP_CLASS property (see obxprop)"
role="the window's _OB_APP_ROLE property (see obxprop)"
title="the window's _OB_APP_TITLE property (see obxprop)"
type="the window's _OB_APP_TYPE property (see obxprob)..
(if unspecified, then it is 'dialog' for child windows)">
# you may set only one of name/class/role/title/type, or you may use more
# than one together to restrict your matches.
# the name, class, role, and title use simple wildcard matching such as those
# used by a shell. you can use * to match any characters and ? to match
# any single character.
# the type is one of: normal, dialog, splash, utility, menu, toolbar, dock,
# or desktop
# when multiple rules match a window, they will all be applied, in the
# order that they appear in this list
# each rule element can be left out or set to 'default' to specify to not
# change that attribute of the window
<decor>yes</decor>
# enable or disable window decorations
<shade>no</shade>
# make the window shaded when it appears, or not
<position force="no">
# the position is only used if both an x and y coordinate are provided
# (and not set to 'default')
# when force is "yes", then the window will be placed here even if it
# says you want it placed elsewhere. this is to override buggy
# applications who refuse to behave
<x>center</x>
# a number like 50, or 'center' to center on screen. use a negative number
# to start from the right (or bottom for <y>), ie -50 is 50 pixels from
# the right edge (or bottom). use 'default' to specify using value
# provided by the application, or chosen by openbox, instead.
<y>200</y>
<monitor>1</monitor>
# specifies the monitor in a xinerama setup.
# 1 is the first head, or 'mouse' for wherever the mouse is
</position>
<size>
# the size to make the window.
<width>20</width>
# a number like 20, or 'default' to use the size given by the application.
# you can use fractions such as 1/2 or percentages such as 75% in which
# case the value is relative to the size of the monitor that the window
# appears on.
<height>30%</height>
</size>
<focus>yes</focus>
# if the window should try be given focus when it appears. if this is set
# to yes it doesn't guarantee the window will be given focus. some
# restrictions may apply, but Openbox will try to
<desktop>1</desktop>
# 1 is the first desktop, 'all' for all desktops
<layer>normal</layer>
# 'above', 'normal', or 'below'
<iconic>no</iconic>
# make the window iconified when it appears, or not
<skip_pager>no</skip_pager>
# asks to not be shown in pagers
<skip_taskbar>no</skip_taskbar>
# asks to not be shown in taskbars. window cycling actions will also
# skip past such windows
<fullscreen>yes</fullscreen>
# make the window in fullscreen mode when it appears
<maximized>true</maximized>
# 'Horizontal', 'Vertical' or boolean (yes/no)
</application>
# end of the example
-->
</applications>
</openbox_config>
@@ -0,0 +1,98 @@
[Behavior]
AutoSelectionDelay=600
BookmarkOpenMethod=current_tab
ConfirmDelete=true
ConfirmTrash=false
NoUsbTrash=false
QuickExec=false
SingleClick=false
UseTrash=true
[Desktop]
BgColor=#000000
DesktopCellMargins=@Size(3 1)
DesktopIconSize=48
FgColor=#ffffff
Font="Sans Serif,10,-1,5,50,0,0,0,0,0"
LastSlide=
ShadowColor=#000000
ShowHidden=false
ShowWmMenu=false
SlideShowInterval=0
SortColumn=name
SortFolderFirst=true
SortOrder=ascending
Wallpaper=/usr/share/lxqt/themes/light/simple_blue_widescreen.png
WallpaperDirectory=
WallpaperMode=stretch
WallpaperRandomize=false
[FolderView]
BackupAsHidden=false
BigIconSize=48
FolderViewCellMargins=@Size(3 3)
Mode=icon
ShadowHidden=false
ShowFilter=false
ShowFullNames=false
ShowHidden=false
SidePaneIconSize=24
SmallIconSize=24
SortCaseSensitive=false
SortColumn=name
SortFolderFirst=true
SortOrder=ascending
ThumbnailIconSize=128
[Places]
PlacesApplications=true
PlacesComputer=true
PlacesDesktop=true
PlacesHome=true
PlacesNetwork=true
PlacesRoot=true
PlacesTrash=true
[Search]
searchContentCaseInsensitive=false
searchContentRegexp=true
searchNameCaseInsensitive=false
searchNameRegexp=true
searchRecursive=false
searchhHidden=false
[System]
Archiver=file-roller
FallbackIconThemeName=oxygen
OnlyUserTemplates=false
SIUnit=false
SuCommand=lxqt-sudo %s
TemplateRunApp=false
TemplateTypeOnce=false
Terminal=xterm
[Thumbnail]
MaxThumbnailFileSize=4096
ShowThumbnails=true
ThumbnailLocalFilesOnly=true
[Volume]
AutoRun=true
CloseOnUnmount=true
MountOnStartup=true
MountRemovable=true
[Window]
AlwaysShowTabs=false
FixedHeight=480
FixedWidth=640
FullWidthTabBar=true
LastWindowHeight=480
LastWindowMaximized=false
LastWindowWidth=640
PathBarButtons=true
RememberWindowSize=true
ShowMenuBar=true
ShowTabClose=true
SidePaneMode=places
SplitterPos=150
@@ -0,0 +1 @@
/usr/local/share/doro-lxde-wallpapers/desktop-items-0.conf
@@ -0,0 +1 @@
/tmp/pulse-PKdhtXMmr18n
@@ -0,0 +1,12 @@
[General]
HideTabBarWithOneTab=false
TerminalTransparency=0
version=0.8.0
[MainWindow]
ApplicationTransparency=0
pos=@Point(0 0)
size=@Size(640 480)
[Shortcuts]
Paste%20Clipboard=Ctrl+Shift+V
+20
View File
@@ -0,0 +1,20 @@
# DO NOT EDIT! This file will be overwritten by LXAppearance.
# Any customization should be done in ~/.gtkrc-2.0.mine instead.
include "/usr/share/themes/Arc/gtk-2.0/gtkrc"
gtk-theme-name="Arc"
gtk-icon-theme-name="nuoveXT2"
gtk-font-name="Sans 10"
gtk-cursor-theme-name="DMZ-White"
gtk-cursor-theme-size=18
gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
gtk-button-images=1
gtk-menu-images=1
gtk-enable-event-sounds=1
gtk-enable-input-feedback-sounds=1
gtk-xft-antialias=1
gtk-xft-hinting=1
gtk-xft-hintstyle="hintslight"
gtk-xft-rgba="rgb"
include "/root/.gtkrc-2.0.mine"
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
if [ -n "$VNC_PASSWORD" ]; then
echo -n "$VNC_PASSWORD" > /.password1
x11vnc -storepasswd $(cat /.password1) /.password2
chmod 400 /.password*
sed -i 's/^command=x11vnc.*/& -rfbauth \/.password2/' /etc/supervisor/conf.d/supervisord.conf
export VNC_PASSWORD=
fi
if [ -n "$X11VNC_ARGS" ]; then
sed -i "s/^command=x11vnc.*/& ${X11VNC_ARGS}/" /etc/supervisor/conf.d/supervisord.conf
fi
if [ -n "$OPENBOX_ARGS" ]; then
sed -i "s#^command=/usr/bin/openbox.*#& ${OPENBOX_ARGS}#" /etc/supervisor/conf.d/supervisord.conf
fi
if [ -n "$RESOLUTION" ]; then
sed -i "s/1024x768/$RESOLUTION/" /usr/local/bin/xvfb.sh
fi
USER=${USER:-root}
HOME=/root
if [ "$USER" != "root" ]; then
echo "* enable custom user: $USER"
useradd --create-home --shell /bin/bash --user-group --groups adm,sudo $USER
if [ -z "$PASSWORD" ]; then
echo " set default password to \"ubuntu\""
PASSWORD=ubuntu
fi
HOME=/home/$USER
echo "$USER:$PASSWORD" | chpasswd
cp -r /root/{.config,.gtkrc-2.0,.asoundrc} ${HOME}
[ -d "/dev/snd" ] && chgrp -R adm /dev/snd
fi
sed -i -e "s|%USER%|$USER|" -e "s|%HOME%|$HOME|" /etc/supervisor/conf.d/supervisord.conf
# home folder
if [ ! -x "$HOME/.config/pcmanfm/LXDE/" ]; then
mkdir -p $HOME/.config/pcmanfm/LXDE/
ln -sf /usr/local/share/doro-lxde-wallpapers/desktop-items-0.conf $HOME/.config/pcmanfm/LXDE/
chown -R $USER:$USER $HOME
fi
# nginx workers
sed -i 's|worker_processes .*|worker_processes 1;|' /etc/nginx/nginx.conf
# nginx ssl
if [ -n "$SSL_PORT" ] && [ -e "/etc/nginx/ssl/nginx.key" ]; then
echo "* enable SSL"
sed -i 's|#_SSL_PORT_#\(.*\)443\(.*\)|\1'$SSL_PORT'\2|' /etc/nginx/sites-enabled/default
sed -i 's|#_SSL_PORT_#||' /etc/nginx/sites-enabled/default
fi
# nginx http base authentication
if [ -n "$HTTP_PASSWORD" ]; then
echo "* enable HTTP base authentication"
htpasswd -bc /etc/nginx/.htpasswd $USER $HTTP_PASSWORD
sed -i 's|#_HTTP_PASSWORD_#||' /etc/nginx/sites-enabled/default
fi
# dynamic prefix path renaming
if [ -n "$RELATIVE_URL_ROOT" ]; then
echo "* enable RELATIVE_URL_ROOT: $RELATIVE_URL_ROOT"
sed -i 's|#_RELATIVE_URL_ROOT_||' /etc/nginx/sites-enabled/default
sed -i 's|_RELATIVE_URL_ROOT_|'$RELATIVE_URL_ROOT'|' /etc/nginx/sites-enabled/default
fi
# clearup
PASSWORD=
HTTP_PASSWORD=
exec /bin/tini -- supervisord -n -c /etc/supervisor/supervisord.conf
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
if [ -z "$ALSADEV" ]; then
zenity --error --text "To support audio, please read README.md and run container with --device /dev/snd -e ALSADEV=..."
exit 1
fi
exec /usr/bin/chromium-browser --no-sandbox --alsa-output-device="$ALSADEV" "$@"
+3
View File
@@ -0,0 +1,3 @@
#!/bin/sh
exec /usr/bin/Xvfb :1 -screen 0 1024x768x24
@@ -0,0 +1,11 @@
class Default(object):
DEBUG = True
class Development(Default):
PHASE = 'development'
class Production(Default):
PHASE = 'production'
DEBUG = False
@@ -0,0 +1,90 @@
#!/usr/bin/env python
import sys
import logging
import logging.handlers
# The terminal has 8 colors with codes from 0 to 7
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
# These are the sequences need to get colored ouput
RESET_SEQ = "\033[0m"
COLOR_SEQ = "\033[1;%dm"
BOLD_SEQ = "\033[1m"
# The background is set with 40 plus the number of the color,
# and the foreground with 30
COLORS = {
'WARNING': COLOR_SEQ % (30 + YELLOW) + 'WARN ' + RESET_SEQ,
'INFO': COLOR_SEQ % (30 + WHITE) + 'INFO ' + RESET_SEQ,
'DEBUG': COLOR_SEQ % (30 + BLUE) + 'DEBUG' + RESET_SEQ,
'CRITICAL': COLOR_SEQ % (30 + YELLOW) + 'CRITI' + RESET_SEQ,
'ERROR': COLOR_SEQ % (30 + RED) + 'ERROR' + RESET_SEQ,
}
class ColoredFormatter(logging.Formatter):
def __init__(self, msg, use_color=True):
logging.Formatter.__init__(self, msg)
self.use_color = use_color
def format(self, record):
if self.use_color:
record.levelname = COLORS.get(record.levelname, record.levelname)
return logging.Formatter.format(self, record)
class LoggingConfiguration(object):
COLOR_FORMAT = "%(asctime)s" + \
" %(levelname)s %(message)s " + \
"(" + BOLD_SEQ + "%(filename)s" + RESET_SEQ + ":%(lineno)d)"
NO_COLOR_FORMAT = "%(asctime)s %(levelname)s " + \
"%(message)s " + \
"(%(filename)s:%(lineno)d)"
FILE_FORMAT = "%(asctime)s %(levelname)s " + \
"%(message)s "
@classmethod
def set(cls, log_level, log_filename, append=None, **kwargs):
""" Configure a rotating file logging
"""
logger = logging.getLogger()
logger.setLevel(log_level)
COLOR_FORMAT = cls.COLOR_FORMAT
NO_COLOR_FORMAT = cls.NO_COLOR_FORMAT
FILE_FORMAT = cls.FILE_FORMAT
if 'name' in kwargs:
COLOR_FORMAT = COLOR_FORMAT.replace('%(threadName)-22s',
'%-22s' % (kwargs['name']))
NO_COLOR_FORMAT = NO_COLOR_FORMAT.replace(
'%(threadName)-22s', '%-22s' % (kwargs['name']))
FILE_FORMAT = FILE_FORMAT.replace(
'%(threadName)-22s', '%s' % (kwargs['name']))
# Log to rotating file
try:
fh = logging.handlers.RotatingFileHandler(
log_filename,
mode='a+',
backupCount=3
)
fh.setFormatter(ColoredFormatter(FILE_FORMAT, False))
fh.setLevel(log_level)
logger.addHandler(fh)
if not append:
# Create a new log file on every new
fh.doRollover()
except IOError as e:
print('ignore to log to {}: {}'.format(log_filename, e))
# Log to sys.stderr using log level passed through command line
if log_level != logging.NOTSET:
log_handler = logging.StreamHandler(sys.stdout)
if sys.platform.find('linux') >= 0:
formatter = ColoredFormatter(COLOR_FORMAT)
else:
formatter = ColoredFormatter(NO_COLOR_FORMAT, False)
log_handler.setFormatter(formatter)
log_handler.setLevel(log_level)
logger.addHandler(log_handler)
@@ -0,0 +1,20 @@
backports.ssl-match-hostname==3.7.0.1
certifi==2019.9.11
chardet==3.0.4
Click==7.0
Flask==1.1.1
Flask-Login==0.4.1
gevent==1.4.0
gevent-websocket==0.10.1
greenlet==0.4.15
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
meld3==2.0.0
requests==2.22.0
six==1.12.0
supervisor==4.1.0
urllib3==1.25.6
websocket-client==0.47.0
Werkzeug==0.16.0
+122
View File
@@ -0,0 +1,122 @@
#!/usr/bin/env python
from __future__ import (
absolute_import, division, print_function, with_statement
)
import os
import time
import sys
import subprocess
from vnc.util import ignored
def main():
def run_with_reloader(main_func, extra_files=None, interval=3):
"""Run the given function in an independent python interpreter."""
def find_files(directory="./"):
for root, dirs, files in os.walk(directory):
for basename in files:
if basename.endswith('.py'):
filename = os.path.join(root, basename)
yield filename
if os.environ.get('WERKZEUG_RUN_MAIN') == 'true':
try:
main_func()
except KeyboardInterrupt:
pass
return
proc = None
try:
while True:
log.info('Restarting with reloader {} {}'.format(
sys.executable,
' '.join(sys.argv))
)
args = [sys.executable] + sys.argv
new_environ = os.environ.copy()
new_environ['WERKZEUG_RUN_MAIN'] = 'true'
proc = subprocess.Popen(
args,
env=new_environ,
close_fds=True,
preexec_fn=os.setsid
)
mtimes = {}
restart = False
while not restart:
for filename in find_files():
try:
mtime = os.stat(filename).st_mtime
except OSError:
continue
old_time = mtimes.get(filename)
if old_time is None:
mtimes[filename] = mtime
continue
elif mtime > old_time:
log.info(
'Detected change in {}, reloading'.format(
filename
)
)
restart = True
proc.terminate()
break
time.sleep(interval)
except KeyboardInterrupt:
pass
finally:
with ignored(Exception):
proc.terminate()
def run_server():
import socket
from gevent.pywsgi import WSGIServer
from vnc.app import app
# websocket conflict: WebSocketHandler
if DEBUG:
# from werkzeug.debug import DebuggedApplication
app.debug = True
# app = DebuggedApplication(app, evalex=True)
try:
log.info('Listening on http://localhost:{}'.format(PORT))
http_server = WSGIServer(('localhost', PORT), app)
http_server.serve_forever()
# app.run(host='localhost', port=PORT)
except socket.error as e:
log.exception(e)
except KeyboardInterrupt:
pass
finally:
http_server.stop(timeout=10)
log.info('shutdown gracefully')
PORT = 6079
DEBUG = False
os.environ['CONFIG'] = 'config.Production'
entrypoint = run_server
if '--debug' in sys.argv:
DEBUG = True
os.environ['CONFIG'] = 'config.Development'
entrypoint = lambda: run_with_reloader(run_server)
# logging
import logging
from log.config import LoggingConfiguration
LoggingConfiguration.set(
logging.DEBUG if DEBUG else logging.INFO,
'/var/log/web.log'
)
logging.getLogger("werkzeug").setLevel(logging.WARNING)
log = logging.getLogger('novnc2')
entrypoint()
if __name__ == "__main__":
main()
+203
View File
@@ -0,0 +1,203 @@
from __future__ import (
absolute_import, division, print_function, with_statement
)
import re
import os
from flask import (
Flask,
request,
Response,
jsonify,
abort,
)
from gevent import subprocess as gsp, spawn, sleep
from geventwebsocket.exceptions import WebSocketError
from .response import httperror
from .util import ignored
from .state import state
from .log import log
# Flask app
app = Flask('novnc2')
app.config.from_object('config.Default')
app.config.from_object(os.environ.get('CONFIG') or 'config.Development')
@app.route('/api/state')
@httperror
def apistate():
state.wait(int(request.args.get('id', -1)), 30)
state.switch_video(request.args.get('video', 'false') == 'true')
mystate = state.to_dict()
return jsonify({
'code': 200,
'data': mystate,
})
@app.route('/api/health')
def apihealth():
if state.health:
return 'success'
abort(503, 'unhealthy')
@app.route('/api/reset')
def reset():
if 'w' in request.args and 'h' in request.args:
args = {
'w': int(request.args.get('w')),
'h': int(request.args.get('h')),
}
state.set_size(args['w'], args['h'])
state.apply_and_restart()
# check all running
for i in range(40):
if state.health:
break
sleep(1)
log.info('wait services is ready...')
else:
return jsonify({
'code': 500,
'errorMessage': 'service is not ready, please restart container'
})
return jsonify({'code': 200})
@app.route('/resize')
@httperror
def apiresize():
state.reset_size()
return '<html><head><script type = "text/javascript">var h=window.location.href;window.location.href=h.substring(0,h.length-6);</script></head></html>'
@app.route('/api/live.flv')
@httperror
def liveflv():
def generate():
xenvs = {
'DISPLAY': ':1',
}
bufsize = 1024 * 1
framerate = 20
# sound
sound_cmd_input = []
sound_cmd_parameters = []
zero_latency_make_sound_not_good = [
'-tune', 'zerolatency',
]
xenvs['X_WIDTH'] = state.w
xenvs['X_HEIGHT'] = state.h
xenvs['X_WIDTH'] -= state.w % 2
xenvs['X_HEIGHT'] -= state.h % 2
pixels_count = xenvs['X_WIDTH'] * xenvs['X_HEIGHT']
# factor (720p)
# 383: 2400k
# 300: 3000k
# 230: 4000k
factor = 265
maxbitrate_cmd = [
'-maxrate', str(int(pixels_count / factor)) + 'k',
'-bufsize', str(int(pixels_count / factor / 3)) + 'k'
]
# TODO move to global
# get default source
sound_cmd_input = [
'-f', 'alsa',
'-i', 'hw:2,1',
]
sound_cmd_parameters = [
'-ar', '44100',
'-c:a', 'mp3',
]
# flv.js report error if enabling hw acceleration
# hwaccel_dev = ['-vaapi_device', '/dev/dri/renderD128']
# hwaccel_if = ['-vf', 'format=nv12,hwupload']
# vcodec = 'h264_vaapi'
hwaccel_dev = []
hwaccel_if = []
vcodec = 'libx264'
# zero_latency_make_sound_not_good = []
# sound_cmd_parameters = []
# sound_cmd_input = []
cmd = ['/usr/local/ffmpeg/ffmpeg'] + sound_cmd_input + hwaccel_dev + [
'-video_size', '{X_WIDTH}x{X_HEIGHT}'.format(**xenvs),
'-framerate', '{}'.format(framerate),
'-f', 'x11grab', '-draw_mouse', '1',
'-i', '{DISPLAY}'.format(**xenvs),
] + hwaccel_if + [
'-r', '{}'.format(framerate),
'-g', '{}'.format(framerate),
'-flags:v', '+global_header',
'-vcodec', vcodec,
'-preset', 'ultrafast',
'-b_strategy', '0',
'-pix_fmt', 'yuv420p',
'-bsf:v', 'dump_extra=freq=e',
] + maxbitrate_cmd \
+ sound_cmd_parameters + zero_latency_make_sound_not_good + [
'-f', 'flv', 'pipe:1',
]
log.info('command: ' + ' '.join(cmd))
pobj = gsp.Popen(
cmd,
stdout=gsp.PIPE,
stderr=gsp.PIPE,
env={k: str(v) for k, v in xenvs.iteritems()},
)
def readerr(f):
reobj = re.compile(r'bitrate=(\S+)')
global av_bitrate
try:
while True:
buf = f.read(bufsize)
if len(buf) == 0:
break
patterns = reobj.findall(buf.decode('utf-8', 'ignore'))
if len(patterns) > 0:
av_bitrate = patterns[-1]
# log.info(str(buf))
except Exception as e:
log.exception(e)
preaderr = None
try:
preaderr = spawn(readerr, pobj.stderr)
try:
while True:
buf = pobj.stdout.read(bufsize)
if len(buf) == 0:
break
# ws.send(buf)
yield buf
except WebSocketError:
pass
except Exception as e:
log.exception(e)
finally:
with ignored(Exception):
pobj.kill()
preaderr.join()
except Exception as e:
log.exception(e)
finally:
log.info('exiting')
with ignored(Exception):
pobj.kill()
with ignored(Exception):
preaderr.kill()
log.info('exited')
return Response(generate(), mimetype='video/x-flv')
if __name__ == '__main__':
app.run(host=app.config['ADDRESS'], port=app.config['PORT'])
@@ -0,0 +1,2 @@
import logging
log = logging.getLogger('novnc2')
@@ -0,0 +1,40 @@
from __future__ import (
absolute_import, division, print_function, with_statement
)
from functools import wraps
import logging
from flask import jsonify
log = logging.getLogger()
class PermissionDenied(Exception):
pass
class BadRequest(Exception):
pass
def httperror(f):
@wraps(f)
def func(*args, **kwargs):
result = {
'code': 400,
'errorMessage': '',
}
try:
return f(*args, **kwargs)
except PermissionDenied as e:
result['code'] = 403
result['errorMessage'] = str(e)
except BadRequest as e:
result['code'] = 400
result['errorMessage'] = str(e)
except Exception as e:
logging.exception(e)
result['code'] = 500
result['errorMessage'] = str(e)
return jsonify(result)
return func
@@ -0,0 +1,133 @@
from __future__ import (
absolute_import, division, print_function, with_statement
)
from os import environ
from gevent.event import Event
from gevent import subprocess as gsp
from re import search as research
from .log import log
class State(object):
def __init__(self):
self._eid = 0
self._event = Event()
self._w = self._h = self._health = None
self.size_changed_count = 0
def wait(self, eid, timeout=5):
if eid < self._eid:
return
self._event.clear()
self._event.wait(timeout)
return self._eid
def notify(self):
self._eid += 1
self._event.set()
def _update_health(self):
health = True
output = gsp.check_output([
'supervisorctl', '-c', '/etc/supervisor/supervisord.conf',
'status'
])
for line in output.strip().split('\n'):
if not line.startswith('web') and line.find('RUNNING') < 0:
health = False
break
if self._health != health:
self._health = health
self.notify()
return self._health
def to_dict(self):
self._update_health()
state = {
'id': self._eid,
'config': {
'fixedResolution': 'RESOLUTION' in environ,
'sizeChangedCount': self.size_changed_count
}
}
self._update_size()
state.update({
'width': self.w,
'height': self.h,
})
return state
def set_size(self, w, h):
gsp.check_call((
'sed -i \'s#'
'^exec /usr/bin/Xvfb.*$'
'#'
'exec /usr/bin/Xvfb :1 -screen 0 {}x{}x16'
'#\' /usr/local/bin/xvfb.sh'
).format(w, h), shell=True)
self.size_changed_count += 1
def apply_and_restart(self):
gsp.check_call([
'supervisorctl', '-c', '/etc/supervisor/supervisord.conf',
'restart', 'x:'
])
self._w = self._h = self._health = None
self.notify()
def switch_video(self, onoff):
xenvs = {
'DISPLAY': ':1',
}
try:
cmd = 'nofb' if onoff else 'fb'
gsp.check_output(['x11vnc', '-remote', cmd], env=xenvs)
except gsp.CalledProcessError as e:
log.warn('failed to set x11vnc fb: ' + str(e))
def _update_size(self):
if self._w is not None and self._h is not None:
return
xenvs = {
'DISPLAY': ':1',
}
try:
output = gsp.check_output([
'x11vnc', '-query', 'dpy_x,dpy_y'
], env=xenvs).decode('utf-8')
mobj = research(r'dpy_x:(\d+).*dpy_y:(\d+)', output)
if mobj is not None:
w, h = int(mobj.group(1)), int(mobj.group(2))
changed = False
if self._w != w:
changed = True
self._w = w
if self._h != h:
changed = True
self._h = h
if changed:
self.notify()
except gsp.CalledProcessError as e:
log.warn('failed to get dispaly size: ' + str(e))
def reset_size(self):
self.size_changed_count = 0
@property
def w(self):
return self._w
@property
def h(self):
return self._h
@property
def health(self):
self._update_health()
return self._health
state = State()
@@ -0,0 +1,15 @@
from __future__ import (
absolute_import, division, print_function, with_statement
)
from contextlib import contextmanager
from gevent import GreenletExit
@contextmanager
def ignored(*exceptions):
try:
yield
except GreenletExit as e:
raise e
except exceptions:
pass
Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

@@ -0,0 +1,18 @@
[*]
wallpaper_mode=stretch
wallpaper_common=0
wallpapers_configured=4
wallpaper0=/usr/local/share/doro-lxde-wallpapers/bg1.jpg
wallpaper1=/usr/local/share/doro-lxde-wallpapers/bg2.jpg
wallpaper2=/usr/local/share/doro-lxde-wallpapers/bg3.jpg
wallpaper3=/usr/local/share/doro-lxde-wallpapers/bg4.jpg
desktop_bg=#000000
desktop_fg=#ffffff
desktop_shadow=#000000
desktop_font=Sans 12
show_wm_menu=0
sort=mtime;ascending;mingle;
show_documents=0
show_trash=0
show_mounts=0
@@ -0,0 +1,139 @@
[Desktop Entry]
Version=1.0
Name=Chromium Web Browser Sound
GenericName=Web Browser
GenericName[ar]=متصفح الشبكة
GenericName[ast]=Restolador web
GenericName[bg]=Уеб браузър
GenericName[bn]=ওয়েব ব্রাউজার
GenericName[bs]=Web preglednik
GenericName[ca]=Navegador web
GenericName[ca@valencia]=Navegador web
GenericName[cs]=WWW prohlížeč
GenericName[da]=Browser
GenericName[de]=Web-Browser
GenericName[el]=Περιηγητής ιστού
GenericName[en_AU]=Web Browser
GenericName[en_GB]=Web Browser
GenericName[eo]=Retfoliumilo
GenericName[es]=Navegador web
GenericName[et]=Veebibrauser
GenericName[eu]=Web-nabigatzailea
GenericName[fi]=WWW-selain
GenericName[fil]=Web Browser
GenericName[fr]=Navigateur Web
GenericName[gl]=Navegador web
GenericName[gu]=વેબ બ્રાઉઝર
GenericName[he]=דפדפן אינטרנט
GenericName[hi]=वेब ब्राउज़र
GenericName[hr]=Web preglednik
GenericName[hu]=Webböngésző
GenericName[hy]=Ոստայն զննարկիչ
GenericName[ia]=Navigator del Web
GenericName[id]=Peramban Web
GenericName[it]=Browser web
GenericName[ja]=ウェブ・ブラウザ
GenericName[ka]=ვებ ბრაუზერი
GenericName[kn]=ಜಾಲ ವೀಕ್ಷಕ
GenericName[ko]=웹 브라우저
GenericName[kw]=Peurel wias
GenericName[lt]=Žiniatinklio naršyklė
GenericName[lv]=Tīmekļa pārlūks
GenericName[ml]=വെബ് ബ്രൌസര്‍
GenericName[mr]=वेब ब्राऊजर
GenericName[ms]=Pelayar Web
GenericName[nb]=Nettleser
GenericName[nl]=Webbrowser
GenericName[or]=ଓ୍ବେବ ବ୍ରାଉଜର
GenericName[pl]=Przeglądarka WWW
GenericName[pt]=Navegador Web
GenericName[pt_BR]=Navegador web
GenericName[ro]=Navigator de Internet
GenericName[ru]=Веб-браузер
GenericName[sk]=WWW prehliadač
GenericName[sl]=Spletni brskalnik
GenericName[sr]=Интернет прегледник
GenericName[sv]=Webbläsare
GenericName[ta]=இணைய உலாவி
GenericName[te]=మహాతల అన్వేషి
GenericName[th]=เว็บเบราว์เซอร์
GenericName[tr]=Web Tarayıcı
GenericName[ug]=توركۆرگۈ
GenericName[uk]=Навігатор Тенет
GenericName[vi]=Bộ duyệt Web
GenericName[zh_CN]=网页浏览器
GenericName[zh_HK]=網頁瀏覽器
GenericName[zh_TW]=網頁瀏覽器
Comment=Access the Internet
Comment[ar]=الدخول إلى الإنترنت
Comment[ast]=Accesu a Internet
Comment[bg]=Достъп до интернет
Comment[bn]=ইন্টারনেটে প্রবেশ করুন
Comment[bs]=Pristup internetu
Comment[ca]=Accediu a Internet
Comment[ca@valencia]=Accediu a Internet
Comment[cs]=Přístup k internetu
Comment[da]=Få adgang til internettet
Comment[de]=Internetzugriff
Comment[el]=Πρόσβαση στο Διαδίκτυο
Comment[en_AU]=Access the Internet
Comment[en_GB]=Access the Internet
Comment[eo]=Akiri interreton
Comment[es]=Acceda a Internet
Comment[et]=Pääs Internetti
Comment[eu]=Sartu Internetera
Comment[fi]=Käytä internetiä
Comment[fil]=I-access ang Internet
Comment[fr]=Accéder à Internet
Comment[gl]=Acceda a Internet
Comment[gu]=ઇંટરનેટ ઍક્સેસ કરો
Comment[he]=גישה לאינטרנט
Comment[hi]=इंटरनेट तक पहुंच स्थापित करें
Comment[hr]=Pristupite Internetu
Comment[hu]=Az internet elérése
Comment[hy]=Մուտք համացանց
Comment[ia]=Accede a le Interrete
Comment[id]=Akses Internet
Comment[it]=Accesso a Internet
Comment[ja]=インターネットにアクセス
Comment[ka]=ინტერნეტში შესვლა
Comment[kn]=ಇಂಟರ್ನೆಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿ
Comment[ko]=인터넷에 연결합니다
Comment[kw]=Hedhes an Kesrosweyth
Comment[lt]=Interneto prieiga
Comment[lv]=Piekļūt internetam
Comment[ml]=ഇന്റര്‍‌നെറ്റ് ആക്‌സസ് ചെയ്യുക
Comment[mr]=इंटरनेटमध्ये प्रवेश करा
Comment[ms]=Mengakses Internet
Comment[nb]=Bruk internett
Comment[nl]=Verbinding maken met internet
Comment[or]=ଇଣ୍ଟର୍ନେଟ୍ ପ୍ରବେଶ କରନ୍ତୁ
Comment[pl]=Skorzystaj z internetu
Comment[pt]=Aceder à Internet
Comment[pt_BR]=Acessar a internet
Comment[ro]=Accesați Internetul
Comment[ru]=Доступ в Интернет
Comment[sk]=Prístup do siete Internet
Comment[sl]=Dostop do interneta
Comment[sr]=Приступите Интернету
Comment[sv]=Surfa på Internet
Comment[ta]=இணையத்தை அணுகுதல்
Comment[te]=ఇంటర్నెట్‌ను ఆక్సెస్ చెయ్యండి
Comment[th]=เข้าถึงอินเทอร์เน็ต
Comment[tr]=İnternet'e erişin
Comment[ug]=ئىنتېرنېت زىيارىتى
Comment[uk]=Доступ до Інтернету
Comment[vi]=Truy cập Internet
Comment[zh_CN]=访问互联网
Comment[zh_HK]=連線到網際網路
Comment[zh_TW]=連線到網際網路
Exec=/usr/local/bin/chromium-browser-sound.sh %U
Terminal=false
X-MultipleArgs=false
Type=Application
Icon=chromium-browser
Categories=Network;WebBrowser;
MimeType=text/html;text/xml;application/xhtml_xml;x-scheme-handler/http;x-scheme-handler/https;
StartupNotify=true
Actions=NewWindow;Incognito;TempProfile;
X-AppInstall-Package=chromium-browser
+23
View File
@@ -0,0 +1,23 @@
[General]
leave_confirmation=true
[Environment]
GTK_CSD=0
GTK_OVERLAY_SCROLLING=0
[Mouse]
cursor_size=18
cursor_theme=whiteglass
acc_factor=20
acc_threshold=10
left_handed=false
[Keyboard]
delay=500
interval=30
beep=false
[Font]
antialias=true
hinting=true
dpi=96