Showing preview only (4,325K chars total). Download the full file or copy to clipboard to get everything.
Repository: m1k1o/neko
Branch: master
Commit: a2f5f7ec79b4
Files: 563
Total size: 4.0 MB
Directory structure:
gitextract_7wv1b94k/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── client_build.yml
│ ├── client_test.yml
│ ├── dockerhub.yml
│ ├── ghcr.yml
│ ├── ghcr_intel.yml
│ ├── ghcr_nvidia.yml
│ ├── image_app.yml
│ ├── image_base.yml
│ ├── server_test.yml
│ ├── webpage_build.yml
│ ├── webpage_deploy.yml
│ └── webpage_test.yml
├── .gitignore
├── .vscode/
│ ├── launch.json
│ └── settings.json
├── Dockerfile.tmpl
├── LICENSE
├── README.md
├── SECURITY.md
├── apps/
│ ├── brave/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── chromium/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ ├── supervisord.nvidia.conf
│ │ └── widevinecdm.sh
│ ├── firefox/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── autoconfig.js
│ │ ├── neko.js
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── profiles.ini
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── google-chrome/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── kde/
│ │ ├── Dockerfile
│ │ └── supervisord.conf
│ ├── microsoft-edge/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── opera/
│ │ ├── Dockerfile
│ │ ├── fix-ffmpeg-widevine.sh
│ │ ├── openbox.xml
│ │ └── supervisord.conf
│ ├── remmina/
│ │ ├── Dockerfile
│ │ ├── rdp.remmina
│ │ ├── remmina.pref
│ │ ├── run-remmina.sh
│ │ ├── spice.remmina
│ │ ├── supervisord.conf
│ │ └── vnc.remmina
│ ├── tor-browser/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ └── supervisord.conf
│ ├── ungoogled-chromium/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── widevinecdm.sh
│ ├── vivaldi/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ └── supervisord.conf
│ ├── vlc/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ └── supervisord.conf
│ ├── waterfox/
│ │ ├── Dockerfile
│ │ ├── autoconfig.js
│ │ ├── neko.js
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── profiles.ini
│ │ └── supervisord.conf
│ └── xfce/
│ ├── Dockerfile
│ └── supervisord.conf
├── build
├── client/
│ ├── .babelrc
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .eslintrc
│ ├── .prettierrc
│ ├── .vscode/
│ │ └── settings.json
│ ├── Dockerfile
│ ├── dev/
│ │ ├── build
│ │ ├── exec
│ │ ├── npm
│ │ └── serve
│ ├── package.json
│ ├── public/
│ │ ├── browserconfig.xml
│ │ ├── emoji.json
│ │ ├── index.html
│ │ ├── keyboard_layouts.json
│ │ └── site.webmanifest
│ ├── src/
│ │ ├── app.vue
│ │ ├── assets/
│ │ │ └── styles/
│ │ │ ├── _reset.scss
│ │ │ ├── _variables.scss
│ │ │ ├── main.scss
│ │ │ └── vendor/
│ │ │ ├── _emoji.scss
│ │ │ ├── _emote.scss
│ │ │ ├── _font-awesome.scss
│ │ │ ├── _font-whitney.scss
│ │ │ ├── _github.scss
│ │ │ ├── _swal.scss
│ │ │ └── _tooltip.scss
│ │ ├── components/
│ │ │ ├── about.vue
│ │ │ ├── avatar.vue
│ │ │ ├── chat.vue
│ │ │ ├── clipboard.vue
│ │ │ ├── connect.vue
│ │ │ ├── context.vue
│ │ │ ├── controls.vue
│ │ │ ├── emoji.vue
│ │ │ ├── emote.vue
│ │ │ ├── emotes.vue
│ │ │ ├── files.vue
│ │ │ ├── header.vue
│ │ │ ├── markdown.ts
│ │ │ ├── members.vue
│ │ │ ├── menu.vue
│ │ │ ├── resolution.vue
│ │ │ ├── settings.vue
│ │ │ ├── side.vue
│ │ │ ├── unsupported.vue
│ │ │ └── video.vue
│ │ ├── lib.ts
│ │ ├── locale/
│ │ │ ├── de-de.ts
│ │ │ ├── en-us.ts
│ │ │ ├── es-sp.ts
│ │ │ ├── fi-fi.ts
│ │ │ ├── fr-fr.ts
│ │ │ ├── id-id.ts
│ │ │ ├── index.ts
│ │ │ ├── ja-jp.ts
│ │ │ ├── ko-kr.ts
│ │ │ ├── nb-no.ts
│ │ │ ├── pl-pl.ts
│ │ │ ├── ru-ru.ts
│ │ │ ├── sk-sk.ts
│ │ │ ├── sv-se.ts
│ │ │ ├── zh-cn.ts
│ │ │ └── zh-tw.ts
│ │ ├── main.ts
│ │ ├── neko/
│ │ │ ├── base.ts
│ │ │ ├── data.ts
│ │ │ ├── events.ts
│ │ │ ├── index.ts
│ │ │ ├── messages.ts
│ │ │ └── types.ts
│ │ ├── plugins/
│ │ │ ├── anime.ts
│ │ │ ├── axios.ts
│ │ │ ├── i18n.ts
│ │ │ ├── log.ts
│ │ │ ├── neko.ts
│ │ │ └── swal.ts
│ │ ├── store/
│ │ │ ├── chat.ts
│ │ │ ├── client.ts
│ │ │ ├── emoji.ts
│ │ │ ├── files.ts
│ │ │ ├── index.ts
│ │ │ ├── remote.ts
│ │ │ ├── settings.ts
│ │ │ ├── user.ts
│ │ │ └── video.ts
│ │ ├── types/
│ │ │ ├── eventemitter3.d.ts
│ │ │ ├── navigator.keyboard.d.ts
│ │ │ ├── shims-scss.d.ts
│ │ │ ├── shims-tsx.d.ts
│ │ │ └── shims-vue.d.ts
│ │ └── utils/
│ │ ├── guacamole-keyboard.js
│ │ ├── guacamole-keyboard.ts
│ │ ├── index.ts
│ │ └── localstorage.ts
│ ├── tools/
│ │ ├── emoji.ts
│ │ ├── emoji_custom.ts
│ │ └── tsconfig.json
│ ├── tsconfig.json
│ └── vue.config.js
├── config.yml
├── docker-compose.yaml
├── neko.code-workspace
├── runtime/
│ ├── .Xresources
│ ├── Dockerfile
│ ├── Dockerfile.bookworm
│ ├── Dockerfile.intel
│ ├── Dockerfile.intel.bookworm
│ ├── Dockerfile.nvidia
│ ├── Dockerfile.nvidia.bookworm
│ ├── dbus
│ ├── default.pa
│ ├── fontconfig/
│ │ └── 75-emoji.conf
│ ├── fonts/
│ │ └── .gitkeep
│ ├── icon-theme/
│ │ └── .gitkeep
│ ├── intel/
│ │ ├── add-render-group.sh
│ │ └── supervisord.rendergroup.conf
│ ├── nvidia/
│ │ └── entrypoint.sh
│ ├── supervisord.conf
│ ├── supervisord.dbus.conf
│ └── xorg.conf
├── server/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Dockerfile.bookworm
│ ├── build
│ ├── cmd/
│ │ ├── neko/
│ │ │ └── main.go
│ │ ├── plugins.go
│ │ ├── root.go
│ │ └── serve.go
│ ├── dev/
│ │ ├── build
│ │ ├── exec
│ │ ├── fmt
│ │ ├── go
│ │ ├── lint
│ │ ├── rebuild
│ │ ├── rebuild.input
│ │ ├── runtime/
│ │ │ ├── Dockerfile
│ │ │ ├── config.nvidia.yml
│ │ │ ├── config.yml
│ │ │ └── supervisord.conf
│ │ └── start
│ ├── go.mod
│ ├── go.sum
│ ├── internal/
│ │ ├── api/
│ │ │ ├── members/
│ │ │ │ ├── bluk.go
│ │ │ │ ├── controler.go
│ │ │ │ └── handler.go
│ │ │ ├── room/
│ │ │ │ ├── broadcast.go
│ │ │ │ ├── clipboard.go
│ │ │ │ ├── control.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── keyboard.go
│ │ │ │ ├── screen.go
│ │ │ │ ├── settings.go
│ │ │ │ └── upload.go
│ │ │ ├── router.go
│ │ │ ├── session.go
│ │ │ └── sessions/
│ │ │ ├── controller.go
│ │ │ └── handler.go
│ │ ├── capture/
│ │ │ ├── broadcast.go
│ │ │ ├── manager.go
│ │ │ ├── screencast.go
│ │ │ ├── streamselector.go
│ │ │ ├── streamsink.go
│ │ │ └── streamsrc.go
│ │ ├── config/
│ │ │ ├── capture.go
│ │ │ ├── capture_pipeline.go
│ │ │ ├── config.go
│ │ │ ├── desktop.go
│ │ │ ├── member.go
│ │ │ ├── plugins.go
│ │ │ ├── root.go
│ │ │ ├── server.go
│ │ │ ├── session.go
│ │ │ └── webrtc.go
│ │ ├── desktop/
│ │ │ ├── clipboard.go
│ │ │ ├── drop.go
│ │ │ ├── filechooserdialog.go
│ │ │ ├── manager.go
│ │ │ ├── xevent.go
│ │ │ ├── xinput.go
│ │ │ └── xorg.go
│ │ ├── http/
│ │ │ ├── batch.go
│ │ │ ├── debug.go
│ │ │ ├── legacy/
│ │ │ │ ├── event/
│ │ │ │ │ └── events.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── message/
│ │ │ │ │ └── messages.go
│ │ │ │ ├── session.go
│ │ │ │ ├── types/
│ │ │ │ │ └── types.go
│ │ │ │ ├── wstobackend.go
│ │ │ │ └── wstoclient.go
│ │ │ ├── logger.go
│ │ │ ├── manager.go
│ │ │ └── router.go
│ │ ├── member/
│ │ │ ├── file/
│ │ │ │ ├── provider.go
│ │ │ │ ├── provider_test.go
│ │ │ │ └── types.go
│ │ │ ├── manager.go
│ │ │ ├── multiuser/
│ │ │ │ ├── provider.go
│ │ │ │ └── types.go
│ │ │ ├── noauth/
│ │ │ │ └── provider.go
│ │ │ └── object/
│ │ │ ├── provider.go
│ │ │ └── types.go
│ │ ├── plugins/
│ │ │ ├── chat/
│ │ │ │ ├── config.go
│ │ │ │ ├── manager.go
│ │ │ │ ├── plugin.go
│ │ │ │ └── types.go
│ │ │ ├── dependency.go
│ │ │ ├── dependency_test.go
│ │ │ ├── filetransfer/
│ │ │ │ ├── config.go
│ │ │ │ ├── manager.go
│ │ │ │ ├── plugin.go
│ │ │ │ ├── types.go
│ │ │ │ └── utils.go
│ │ │ └── manager.go
│ │ ├── session/
│ │ │ ├── auth.go
│ │ │ ├── manager.go
│ │ │ ├── serialize.go
│ │ │ └── session.go
│ │ ├── webrtc/
│ │ │ ├── cursor/
│ │ │ │ ├── image.go
│ │ │ │ └── position.go
│ │ │ ├── handler.go
│ │ │ ├── legacyhandler.go
│ │ │ ├── manager.go
│ │ │ ├── metrics.go
│ │ │ ├── payload/
│ │ │ │ ├── receive.go
│ │ │ │ ├── send.go
│ │ │ │ └── types.go
│ │ │ ├── peer.go
│ │ │ ├── pionlog/
│ │ │ │ ├── factory.go
│ │ │ │ ├── logger.go
│ │ │ │ └── nullog.go
│ │ │ └── track.go
│ │ └── websocket/
│ │ ├── filechooserdialog.go
│ │ ├── handler/
│ │ │ ├── clipboard.go
│ │ │ ├── control.go
│ │ │ ├── handler.go
│ │ │ ├── keyboard.go
│ │ │ ├── screen.go
│ │ │ ├── send.go
│ │ │ ├── session.go
│ │ │ ├── signal.go
│ │ │ └── system.go
│ │ ├── manager.go
│ │ └── peer.go
│ ├── neko.go
│ ├── openapi.yaml
│ ├── pkg/
│ │ ├── auth/
│ │ │ ├── auth.go
│ │ │ └── auth_test.go
│ │ ├── drop/
│ │ │ ├── drop.c
│ │ │ ├── drop.go
│ │ │ └── drop.h
│ │ ├── gst/
│ │ │ ├── gst.c
│ │ │ ├── gst.go
│ │ │ └── gst.h
│ │ ├── types/
│ │ │ ├── api.go
│ │ │ ├── capture.go
│ │ │ ├── codec/
│ │ │ │ └── codecs.go
│ │ │ ├── desktop.go
│ │ │ ├── event/
│ │ │ │ └── events.go
│ │ │ ├── http.go
│ │ │ ├── member.go
│ │ │ ├── message/
│ │ │ │ └── messages.go
│ │ │ ├── plugins.go
│ │ │ ├── session.go
│ │ │ ├── webrtc.go
│ │ │ └── websocket.go
│ │ ├── utils/
│ │ │ ├── array.go
│ │ │ ├── color.go
│ │ │ ├── deocde.go
│ │ │ ├── http.go
│ │ │ ├── image.go
│ │ │ ├── request.go
│ │ │ ├── trenddetector.go
│ │ │ ├── uid.go
│ │ │ └── zip.go
│ │ ├── xevent/
│ │ │ ├── xevent.c
│ │ │ ├── xevent.go
│ │ │ └── xevent.h
│ │ ├── xinput/
│ │ │ ├── dummy.go
│ │ │ ├── types.go
│ │ │ └── xinput.go
│ │ └── xorg/
│ │ ├── keysymdef.go
│ │ ├── keysymdef.sh
│ │ ├── xorg.c
│ │ ├── xorg.go
│ │ └── xorg.h
│ └── plugins/
│ └── .gitkeep
├── tsconfig.json
├── utils/
│ ├── docker/
│ │ ├── go.mod
│ │ └── main.go
│ └── xorg-deps/
│ ├── Dockerfile
│ ├── xf86-input-neko/
│ │ ├── .gitignore
│ │ ├── 80-neko.conf
│ │ ├── COPYING
│ │ ├── Dockerfile
│ │ ├── Makefile.am
│ │ ├── README.md
│ │ ├── autogen-clean.sh
│ │ ├── autogen.sh
│ │ ├── configure.ac
│ │ ├── m4/
│ │ │ └── .gitkeep
│ │ ├── release.sh
│ │ ├── src/
│ │ │ ├── Makefile.am
│ │ │ └── neko.c
│ │ └── xorg-neko.pc.in
│ └── xf86-video-dummy/
│ ├── 01_v0.3.8_xdummy-randr.patch
│ ├── README.md
│ └── v0.3.8/
│ ├── COPYING
│ ├── ChangeLog
│ ├── Makefile.am
│ ├── Makefile.in
│ ├── README
│ ├── aclocal.m4
│ ├── compile
│ ├── config.guess
│ ├── config.h.in
│ ├── config.sub
│ ├── configure
│ ├── configure.ac
│ ├── depcomp
│ ├── install-sh
│ ├── ltmain.sh
│ ├── missing
│ └── src/
│ ├── Makefile.am
│ ├── Makefile.in
│ ├── compat-api.h
│ ├── dummy.h
│ ├── dummy_cursor.c
│ ├── dummy_dga.c
│ └── dummy_driver.c
└── webpage/
├── .gitignore
├── README.md
├── docs/
│ ├── api/
│ │ ├── README.mdx
│ │ ├── batch.api.mdx
│ │ ├── broadcast-start.api.mdx
│ │ ├── broadcast-status.api.mdx
│ │ ├── broadcast-stop.api.mdx
│ │ ├── clipboard-get-image.api.mdx
│ │ ├── clipboard-get-text.api.mdx
│ │ ├── clipboard-set-text.api.mdx
│ │ ├── control-give.api.mdx
│ │ ├── control-release.api.mdx
│ │ ├── control-request.api.mdx
│ │ ├── control-reset.api.mdx
│ │ ├── control-status.api.mdx
│ │ ├── control-take.api.mdx
│ │ ├── current-session.tag.mdx
│ │ ├── general.tag.mdx
│ │ ├── healthcheck.api.mdx
│ │ ├── keyboard-map-get.api.mdx
│ │ ├── keyboard-map-set.api.mdx
│ │ ├── keyboard-modifiers-get.api.mdx
│ │ ├── keyboard-modifiers-set.api.mdx
│ │ ├── login.api.mdx
│ │ ├── logout.api.mdx
│ │ ├── members-bulk-delete.api.mdx
│ │ ├── members-bulk-update.api.mdx
│ │ ├── members-create.api.mdx
│ │ ├── members-get-profile.api.mdx
│ │ ├── members-list.api.mdx
│ │ ├── members-remove.api.mdx
│ │ ├── members-update-password.api.mdx
│ │ ├── members-update-profile.api.mdx
│ │ ├── members.tag.mdx
│ │ ├── metrics.api.mdx
│ │ ├── profile.api.mdx
│ │ ├── room-broadcast.tag.mdx
│ │ ├── room-clipboard.tag.mdx
│ │ ├── room-control.tag.mdx
│ │ ├── room-keyboard.tag.mdx
│ │ ├── room-screen.tag.mdx
│ │ ├── room-settings.tag.mdx
│ │ ├── room-upload.tag.mdx
│ │ ├── schemas/
│ │ │ └── memberprofile.schema.mdx
│ │ ├── screen-cast-image.api.mdx
│ │ ├── screen-configuration-change.api.mdx
│ │ ├── screen-configuration.api.mdx
│ │ ├── screen-configurations-list.api.mdx
│ │ ├── screen-shot-image.api.mdx
│ │ ├── session-disconnect.api.mdx
│ │ ├── session-get.api.mdx
│ │ ├── session-remove.api.mdx
│ │ ├── sessions-get.api.mdx
│ │ ├── sessions.tag.mdx
│ │ ├── settings-get.api.mdx
│ │ ├── settings-set.api.mdx
│ │ ├── sidebar.ts
│ │ ├── stats.api.mdx
│ │ ├── upload-dialog-close.api.mdx
│ │ ├── upload-dialog.api.mdx
│ │ ├── upload-drop.api.mdx
│ │ └── whoami.api.mdx
│ ├── configuration/
│ │ ├── README.md
│ │ ├── authentication.md
│ │ ├── capture.md
│ │ ├── desktop.md
│ │ ├── help.json
│ │ ├── help.txt
│ │ ├── plugins.md
│ │ └── webrtc.md
│ ├── customization/
│ │ ├── README.md
│ │ ├── browsers.json
│ │ ├── browsers.md
│ │ ├── browsers.tsx
│ │ ├── networking.md
│ │ ├── projects.md
│ │ └── ui.md
│ ├── developer-guide/
│ │ ├── README.md
│ │ ├── build.md
│ │ └── repository-structure.md
│ ├── faq.md
│ ├── hardware-acceleration/
│ │ ├── amd-gpu-support.md
│ │ ├── gpu-acceleration-overview.md
│ │ ├── intel-qsv.md
│ │ ├── nvidia-gpu-support.md
│ │ └── raspberry-pi.md
│ ├── installation/
│ │ ├── README.md
│ │ ├── docker-images.md
│ │ └── examples.md
│ ├── introduction.md
│ ├── migration-from-v2/
│ │ ├── README.md
│ │ ├── help.json
│ │ └── help.txt
│ ├── quick-start.md
│ ├── release-notes.md
│ ├── reverse-proxy-setup.md
│ ├── roadmap.md
│ └── troubleshooting.md
├── docusaurus.config.ts
├── package.json
├── scripts/
│ ├── gen-api-docs.sh
│ └── gen-config.sh
├── sidebars.ts
├── src/
│ ├── components/
│ │ ├── Anchor.tsx
│ │ ├── AppIcon.tsx
│ │ ├── Configuration/
│ │ │ ├── generate.js
│ │ │ └── index.tsx
│ │ ├── HomepageFeatures/
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ ├── HomepageShowcase/
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ └── HomepageUseCases/
│ │ ├── index.tsx
│ │ └── styles.module.css
│ ├── css/
│ │ └── custom.css
│ └── pages/
│ ├── contact.md
│ ├── contributing.md
│ ├── index.module.css
│ ├── index.tsx
│ └── non-goals.md
├── static/
│ ├── .nojekyll
│ ├── .well-known/
│ │ └── security.txt
│ └── CNAME
├── tsconfig.json
├── versioned_docs/
│ └── version-v2/
│ ├── README.md
│ ├── configuration.md
│ ├── examples.md
│ ├── faq.md
│ ├── quick-start.md
│ ├── reverse-proxy.md
│ └── troubleshooting.md
├── versioned_sidebars/
│ └── version-v2-sidebars.json
└── versions.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
================================================
FILE: .gitattributes
================================================
* text=auto
*.css text
*.js text
*.ts text
*.json text
*.htm text
*.html text
*.env text
*.xml text
*.svg text
*.txt text
*.ini text
*.sql text
*.sh text
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.mov binary
*.mp4 binary
*.mp3 binary
================================================
FILE: .github/FUNDING.yml
================================================
github: [ m1k1o ]
================================================
FILE: .github/workflows/client_build.yml
================================================
name: Build Client
on:
workflow_call:
inputs:
with-artifact:
required: false
type: boolean
default: true
description: |
If true, the build artifacts will be uploaded as a GitHub Actions artifact.
This is useful for debugging and testing purposes. If false, the artifacts
will not be uploaded. This is useful for test builds where you don't need
the artifacts.
jobs:
build-client:
name: Build Client
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
cache-dependency-path: client/package-lock.json
- name: Install dependencies
working-directory: ./client
run: npm ci
- name: Build client
working-directory: ./client
run: npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v4
if: ${{ inputs.with-artifact }}
with:
name: client
path: client/dist
================================================
FILE: .github/workflows/client_test.yml
================================================
name: Test Client
on:
pull_request:
branches:
- master
paths:
- client/**
- .github/workflows/client_build.yml
- .github/workflows/client_test.yml
jobs:
test-client:
name: Test Client
uses: ./.github/workflows/client_build.yml
with:
# Do not upload artifacts for test builds
with-artifact: false
secrets: inherit
================================================
FILE: .github/workflows/dockerhub.yml
================================================
name: Build and Push to Docker Hub
on:
push:
branches:
- master
paths-ignore:
- 'webpage/**'
#
# Run this action periodically to keep browsers up-to-date
# even if there is no activity in this repo.
#
schedule:
- cron: "43 2 * * 1"
# allow only one workflow to run at a time
# and cancel in-progress jobs if a new one is triggered
concurrency:
group: "dockerhub"
cancel-in-progress: true
env:
DOCKER_IMAGE: m1k1o/neko
jobs:
build-base:
name: Base Image
runs-on: ubuntu-latest
#
# do not run on forks
#
if: github.repository_owner == 'm1k1o'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata (tags, labels) for Docker
uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.DOCKER_IMAGE }}
tags: |
type=raw,value=base
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ github.actor }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Generate base Dockerfile
run: go run utils/docker/main.go -i Dockerfile.tmpl -o Dockerfile
- name: Build and push
uses: docker/build-push-action@v6
with:
context: ./
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-app:
name: App Image
runs-on: ubuntu-latest
#
# do not run on forks
#
if: github.repository_owner == 'm1k1o'
needs: build-base
strategy:
# Will build all images even if some fail.
fail-fast: false
matrix:
tag:
- firefox
# Temporarily disabled due to Cloudflare blocked download link
#- waterfox
- chromium
- google-chrome
- ungoogled-chromium
- microsoft-edge
- brave
- vivaldi
- opera
- tor-browser
- remmina
- vlc
- xfce
- kde
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata (tags, labels) for Docker
uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.DOCKER_IMAGE }}
tags: |
type=raw,value=latest,enable=${{ matrix.tag == 'firefox' }}
type=raw,value=${{ matrix.tag }}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ github.actor }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: apps/${{ matrix.tag }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
BASE_IMAGE=${{ env.DOCKER_IMAGE }}:base
cache-from: type=gha
cache-to: type=gha,mode=max
================================================
FILE: .github/workflows/ghcr.yml
================================================
name: Build and Push to GHCR
on:
push:
tags:
- 'v*'
jobs:
build-base:
name: Base Image
uses: ./.github/workflows/image_base.yml
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
secrets: inherit
build-app:
name: App Image
uses: ./.github/workflows/image_app.yml
needs: build-base
strategy:
# Will build all images even if some fail.
fail-fast: false
matrix:
include:
- name: firefox
platforms: linux/amd64,linux/arm64,linux/arm/v7
# Temporarily disabled due to Cloudflare blocked download link
#- name: waterfox
# platforms: linux/amd64
- name: chromium
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: google-chrome
platforms: linux/amd64
- name: ungoogled-chromium
platforms: linux/amd64
- name: microsoft-edge
platforms: linux/amd64
- name: brave
platforms: linux/amd64,linux/arm64
- name: vivaldi
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: opera
platforms: linux/amd64
- name: tor-browser
platforms: linux/amd64
- name: remmina
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: vlc
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: xfce
platforms: linux/amd64,linux/arm64,linux/arm/v7
- name: kde
platforms: linux/amd64,linux/arm64,linux/arm/v7
with:
name: ${{ matrix.name }}
platforms: ${{ matrix.platforms }}
secrets: inherit
================================================
FILE: .github/workflows/ghcr_intel.yml
================================================
name: Build and Push to GHCR for Intel
on:
push:
tags:
- 'v*'
jobs:
build-base:
name: Base Image
uses: ./.github/workflows/image_base.yml
with:
flavor: intel
platforms: linux/amd64
dockerfile: Dockerfile.intel
secrets: inherit
build-app:
name: App Image
uses: ./.github/workflows/image_app.yml
needs: build-base
strategy:
# Will build all images even if some fail.
fail-fast: false
matrix:
include:
- name: firefox
# Temporarily disabled due to Cloudflare blocked download link
#- name: waterfox
- name: chromium
- name: google-chrome
- name: ungoogled-chromium
- name: microsoft-edge
- name: brave
- name: vivaldi
- name: opera
- name: tor-browser
- name: remmina
- name: vlc
- name: xfce
- name: kde
with:
name: ${{ matrix.name }}
flavor: intel
platforms: ${{ matrix.platforms }}
dockerfile: ${{ matrix.dockerfile }}
secrets: inherit
================================================
FILE: .github/workflows/ghcr_nvidia.yml
================================================
name: Build and Push to GHCR for Nvidia
on:
push:
tags:
- 'v*'
jobs:
build-base:
name: Base Image
uses: ./.github/workflows/image_base.yml
with:
flavor: nvidia
platforms: linux/amd64
dockerfile: Dockerfile.nvidia
secrets: inherit
build-app:
name: App Image
uses: ./.github/workflows/image_app.yml
needs: build-base
strategy:
# Will build all images even if some fail.
fail-fast: false
matrix:
include:
- name: firefox
dockerfile: Dockerfile.nvidia
- name: brave
dockerfile: Dockerfile.nvidia
- name: chromium
dockerfile: Dockerfile.nvidia
- name: google-chrome
dockerfile: Dockerfile.nvidia
- name: microsoft-edge
dockerfile: Dockerfile.nvidia
with:
name: ${{ matrix.name }}
flavor: nvidia
platforms: ${{ matrix.platforms }}
dockerfile: ${{ matrix.dockerfile }}
secrets: inherit
================================================
FILE: .github/workflows/image_app.yml
================================================
name: Build App Image
on:
workflow_call:
inputs:
name:
required: true
type: string
description: "The name of the app to build."
flavor:
required: false
type: string
default: ""
description: "The flavor of the image to build."
platforms:
required: false
type: string
default: "linux/amd64"
description: "The platforms to build for."
dockerfile:
required: false
type: string
default: "Dockerfile"
description: "The Dockerfile to use for building the image."
env:
FLAVOR_PREFIX: ${{ inputs.flavor && format('{0}-', inputs.flavor) || '' }}
jobs:
build-app:
name: Build App Image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata (tags, labels) for Docker
uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}/${{ env.FLAVOR_PREFIX }}${{ inputs.name }}
tags: |
type=edge,branch=master
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,format=long
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_ACCESS_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: apps/${{ inputs.name }}
file: apps/${{ inputs.name }}/${{ inputs.dockerfile || 'Dockerfile' }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
BASE_IMAGE=ghcr.io/${{ github.repository }}/${{ env.FLAVOR_PREFIX }}base:sha-${{ github.sha }}
platforms: ${{ inputs.platforms || 'linux/amd64' }}
cache-from: type=gha
cache-to: type=gha,mode=max
================================================
FILE: .github/workflows/image_base.yml
================================================
name: Build Base Image
on:
workflow_call:
inputs:
flavor:
required: false
type: string
default: ""
description: "The flavor of the image to build. This is used to determine the base image and the Dockerfile to use."
platforms:
required: false
type: string
default: "linux/amd64"
description: "The platforms to build for."
dockerfile:
required: false
type: string
default: "Dockerfile"
description: "The Dockerfile to use for building the image."
env:
FLAVOR_PREFIX: ${{ inputs.flavor && format('{0}-', inputs.flavor) || '' }}
jobs:
build-client:
name: Build Client Artifacts
uses: ./.github/workflows/client_build.yml
build-base:
name: Build Base Image
runs-on: ubuntu-latest
needs: build-client
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download client dist
uses: actions/download-artifact@v4
with:
name: client
path: client/dist
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata (tags, labels) for Docker
uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}/${{ env.FLAVOR_PREFIX }}base
tags: |
type=edge,branch=master
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,format=long
- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GHCR_ACCESS_TOKEN }}
- name: Generate base Dockerfile
env:
RUNTIME_DOCKERFILE: ${{ inputs.dockerfile || 'Dockerfile' }}
run: go run utils/docker/main.go -i Dockerfile.tmpl -o Dockerfile -client client/dist
- name: Build and push
uses: docker/build-push-action@v6
with:
context: ./
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ inputs.platforms || 'linux/amd64' }}
cache-from: type=gha
cache-to: type=gha,mode=max
================================================
FILE: .github/workflows/server_test.yml
================================================
name: Test Server
on:
pull_request:
branches:
- master
paths:
- server/**
- .github/workflows/server_test.yml
jobs:
build-amd64:
name: Build amd64
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: ./server
platforms: linux/amd64
build-arm64:
name: Build arm64
runs-on: ubuntu-24.04-arm
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: ./server
platforms: linux/arm64
================================================
FILE: .github/workflows/webpage_build.yml
================================================
name: Build Webpage
on:
workflow_call:
inputs:
with-artifact:
required: false
type: boolean
default: true
description: |
If true, the build artifacts will be uploaded as a GitHub Actions artifact.
This is useful for debugging and testing purposes. If false, the artifacts
will not be uploaded. This is useful for test builds where you don't need
the artifacts.
jobs:
build-webpage:
name: Build Webpage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
cache-dependency-path: webpage/package-lock.json
- name: Install dependencies
working-directory: ./webpage
run: npm ci
- name: Build webpage
working-directory: ./webpage
run: npm run build
- if: ${{ inputs.with-artifact }}
name: Upload artifacts
uses: actions/upload-pages-artifact@v3
with:
artifact-name: github-pages
path: ./webpage/build
================================================
FILE: .github/workflows/webpage_deploy.yml
================================================
name: Build and Deploy Webpage to GitHub Pages
on:
# Runs on pushes targeting the default branch
push:
branches:
- master
paths:
- webpage/**
- .github/workflows/webpage_build.yml
- .github/workflows/webpage_deploy.yml
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build-webpage:
name: Build Webpage
uses: ./.github/workflows/webpage_build.yml
secrets: inherit
deploy-webpage:
name: Deploy to GitHub Pages
needs: build-webpage
# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
================================================
FILE: .github/workflows/webpage_test.yml
================================================
name: Test Webpage
on:
pull_request:
branches:
- master
paths:
- webpage/**
- .github/workflows/webpage_build.yml
- .github/workflows/webpage_test.yml
jobs:
test-webpage:
name: Test Webpage
uses: ./.github/workflows/webpage_build.yml
with:
# Do not upload artifacts for test builds
with-artifact: false
secrets: inherit
================================================
FILE: .gitignore
================================================
# OS files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Log/Temp files
.tmp/
tmp/
*.tmp
.logs/
logs/
*.log
core
.build
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# TypeScript incremental compilation cache
*.tsbuildinfo
# Node modules
node_modules
dist
bin
# Environment files
*.env
.env.development
# Code Editors
.idea
runtime/fonts/*
!runtime/fonts/.gitkeep
runtime/icon-theme/*
!runtime/icon-theme/.gitkeep
# root Dockerfile is generated from the Dockerfile.tmpl
/Dockerfile
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "launch",
"type": "go",
"debugAdapter": "dlv-dap",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/server/cmd/neko",
"output": "${workspaceFolder}/server/bin/debug/neko",
"cwd": "${workspaceFolder}/server/",
"args": ["serve", "-d", "-c", "dev/runtime/config.yml"],
"env": {
"DISPLAY": ":99.0",
"PION_LOG_TRACE": "all",
}
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"go.inferGopath": false,
"go.autocompleteUnimportedPackages": true,
"go.delveConfig": {
"useApiV1": false
},
"[go]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
}
================================================
FILE: Dockerfile.tmpl
================================================
# This Dockerfile is pre-processed by the ./utils/docker script, it is not meant to be used directly.
FROM ./server/ AS server
FROM ./client/ AS client
FROM ./utils/xorg-deps/ AS xorg-deps
FROM ./runtime/$RUNTIME_DOCKERFILE AS runtime
# tells neko-rooms which version of the API to use
LABEL net.m1k1o.neko.api-version=3
COPY --from=server /src/bin/plugins/ /etc/neko/plugins/
COPY --from=server /src/bin/neko /usr/bin/neko
COPY --from=client /src/dist/ /var/www
COPY --from=xorg-deps /usr/local/lib/xorg/modules/drivers/dummy_drv.so /usr/lib/xorg/modules/drivers/dummy_drv.so
COPY --from=xorg-deps /usr/local/lib/xorg/modules/input/neko_drv.so /usr/lib/xorg/modules/input/neko_drv.so
COPY config.yml /etc/neko/neko.yaml
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2020 Nurdism <nurdism.io@gmail.com>
Copyright (C) 2020-2024 m1k1o & Demodesk GmbH
Copyright (C) 2024- m1k1o
All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
<div align="center">
<a href="https://github.com/m1k1o/neko" title="Neko's Github repository.">
<img src="https://neko.m1k1o.net/img/logo.png" width="400" height="auto"/>
</a>
<p align="center">
<a href="https://github.com/m1k1o/neko/releases">
<img src="https://img.shields.io/github/v/release/m1k1o/neko" alt="release">
</a>
<a href="https://github.com/m1k1o/neko/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/m1k1o/neko" alt="license">
</a>
<a href="https://hub.docker.com/r/m1k1o/neko">
<img src="https://img.shields.io/docker/pulls/m1k1o/neko" alt="pulls">
</a>
<a href="https://github.com/m1k1o/neko/issues">
<img src="https://img.shields.io/github/issues/m1k1o/neko" alt="issues">
</a>
<a href="https://github.com/sponsors/m1k1o">
<img src="https://img.shields.io/badge/-sponsor-red" alt="issues">
</a>
<a href="https://discord.gg/HXQJmqNJMz">
<img src="https://discordapp.com/api/guilds/665851821906067466/widget.png" alt="Chat on discord">
</a>
<a href="https://hellogithub.com/repository/4536d4546af24196af3f08a023dfa007" target="_blank">
<img src="https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=4536d4546af24196af3f08a023dfa007&claim_uid=0x19e4dJwD83aW2&theme=small" alt="Featured|HelloGitHub" />
</a>
<a href="https://github.com/m1k1o/neko/actions">
<img src="https://github.com/m1k1o/neko/actions/workflows/ghcr.yml/badge.svg" alt="build">
</a>
</p>
<img src="https://neko.m1k1o.net/img/intro.gif" width="650" height="auto"/>
</div>
# n.eko
Welcome to Neko, a self-hosted virtual browser that runs in Docker and uses WebRTC technology. Neko is a powerful tool that allows you to **run a fully-functional browser in a virtual environment**, giving you the ability to **access the internet securely and privately from anywhere**. With Neko, you can browse the web, **run applications**, and perform other tasks just as you would on a regular browser, all within a **secure and isolated environment**. Whether you are a developer looking to test web applications, a **privacy-conscious user seeking a secure browsing experience**, or simply someone who wants to take advantage of the **convenience and flexibility of a virtual browser**, Neko is the perfect solution.
In addition to its security and privacy features, Neko offers the **ability for multiple users to access it simultaneously**. This makes it an ideal solution for teams or organizations that need to share access to a browser, as well as for individuals who want to use **multiple devices to access the same virtual environment**. With Neko, you can **easily and securely share access to a browser with others**, without having to worry about maintaining separate configurations or settings. Whether you need to **collaborate on a project**, access shared resources, or simply want to **share access to a browser with friends or family**, Neko makes it easy to do so.
Neko is also a great tool for **hosting watch parties** and interactive presentations. With its virtual browser capabilities, Neko allows you to host watch parties and presentations that are **accessible from anywhere**, without the need for in-person gatherings. This makes it easy to **stay connected with friends and colleagues**, even when you are unable to meet in person. With Neko, you can easily host a watch party or give an **interactive presentation**, whether it's for leisure or work. Simply invite your guests to join the virtual environment, and you can share the screen and **interact with them in real-time**.
## About
This app uses WebRTC to stream a desktop inside of a docker container, original author made this because [rabb.it](https://en.wikipedia.org/wiki/Rabb.it) went under and his internet could not handle streaming and discord kept crashing when his friend attempted to. He just wanted to watch anime with his friends ლ(ಠ益ಠლ) so he started digging throughout the internet and found a few *kinda* clones, but none of them had the virtual browser, then he found [Turtus](https://github.com/Khauri/Turtus) and he was able to figure out the rest.
Then I found [this](https://github.com/nurdism/neko) project and started to dig into it. I really liked the idea of having collaborative browser browsing together with multiple people, so I created a fork. Initially, I wanted to merge my changes to the upstream repository, but the original author did not have time for this project anymore and it got eventually archived.
## Use-cases and comparison
Neko started as a virtual browser that is streamed using WebRTC to multiple users.
- It is **not only limited to a browser**; it can run anything that runs on linux (e.g. VLC). Browser only happens to be the most popular and widely used use-case.
- In fact, it is not limited to a single program either; you can install a full desktop environment (e.g. XFCE, KDE).
- Speaking of limits, it does not need to run in a container; you could install neko on your host, connect to your X server and control your whole VM.
- Theoretically it is not limited to only X server, anything that can be controlled and scraped periodically for images could be used instead.
- Like implementing RDP or VNC protocol, where neko would only act as WebRTC relay server. This is currently only future.
Primary use case is connecting with multiple people, leveraging real time synchronization and interactivity:
- **Watch party** - watching video content together with multiple people and reacting to it (chat, emotes) - open source alternative to [giggl.app](https://giggl.app/) or [hyperbeam](https://watch.hyperbeam.com).
- **Interactive presentation** - not only screen sharing, but others can control the screen.
- **Collaborative tool** - brainstorming ideas, cobrowsing, code debugging together.
- **Support/Teaching** - interactively guiding people in controlled environment.
- **Embed anything** - embed virtual browser in your web app - open source alternative to [hyperbeam API](https://hyperbeam.com/).
- open any third-party website or application, synchronize audio and video flawlessly among multiple participants.
- request rooms using API with [neko-rooms](https://github.com/m1k1o/neko-rooms).
- [**Neko inside VR Chat**](https://github.com/jameskitt616/vrchat_streaming) - watch remote browser together with friends in VR.
Other use cases that benefit from single-user:
- **Personal workspace** - streaming containerized apps and desktops to end-users - similar to [kasm](https://www.kasmweb.com/).
- **Persistent browser** - own browser with persistent cookies available anywhere - similar to [mightyapp](https://www.mightyapp.com/).
- no state is left on the host browser after terminating the connection.
- sensitive data like cookies are not transferred - only video is shared.
- **Throwaway browser** - a better solution for planning secret parties and buying birthday gifts off the internet.
- use Tor Browser and [VPN](https://github.com/m1k1o/neko-vpn) for additional anonymity.
- mitigates risk of OS fingerprinting and browser vulnerabilities by running in container.
- **Session broadcasting** - broadcast room content using RTMP (to e.g. twitch or youtube...).
- **Session recording** - broadcast RTMP can be saved to a file using e.g. [nginx-rtmp](https://www.nginx.com/products/nginx/modules/rtmp-media-streaming/)
- have clean environment when recording tutorials.
- no need to hide bookmarks or use incognito mode.
- **Jump host** - access your internal applications securely without the need for VPN.
- **Automated browser** - you can install [playwright](https://playwright.dev/) or [puppeteer](https://pptr.dev/) and automate tasks while being able to actively intercept them.
Compared to clientless remote desktop gateway (e.g. [Apache Guacamole](https://guacamole.apache.org/) or [websockify](https://github.com/novnc/websockify) with [noVNC](https://novnc.com/)), installed with remote desktop server along with desired program (e.g. [linuxserver/firefox](https://docs.linuxserver.io/images/docker-firefox)) provides neko additionally:
- **Smooth video** because it uses WebRTC and not images sent over WebSockets.
- **Built in audio** support, what is not part of Apache Guacamole or noVNC.
- **Multi-participant control**, what is not natively supported by Apache Guacamole or noVNC.
### Supported browsers
<div align="center">
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#firefox">
<img src="https://neko.m1k1o.net/img/icons/firefox.svg" title="ghcr.io/m1k1o/neko/firefox" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#tor-browser">
<img src="https://neko.m1k1o.net/img/icons/tor-browser.svg" title="ghcr.io/m1k1o/neko/tor-browser" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#waterfox">
<img src="https://neko.m1k1o.net/img/icons/waterfox.svg" title="ghcr.io/m1k1o/neko/waterfox" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#chromium">
<img src="https://neko.m1k1o.net/img/icons/chromium.svg" title="ghcr.io/m1k1o/neko/chromium" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#google-chrome">
<img src="https://neko.m1k1o.net/img/icons/google-chrome.svg" title="ghcr.io/m1k1o/neko/google-chrome" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#ungoogled-chromium">
<img src="https://neko.m1k1o.net/img/icons/ungoogled-chromium.svg" title="ghcr.io/m1k1o/neko/google-chrome" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#microsoft-edge">
<img src="https://neko.m1k1o.net/img/icons/microsoft-edge.svg" title="ghcr.io/m1k1o/neko/microsoft-edge" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#brave">
<img src="https://neko.m1k1o.net/img/icons/brave.svg" title="ghcr.io/m1k1o/neko/brave" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#vivaldi">
<img src="https://neko.m1k1o.net/img/icons/vivaldi.svg" title="ghcr.io/m1k1o/neko/vivaldi" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#opera">
<img src="https://neko.m1k1o.net/img/icons/opera.svg" title="ghcr.io/m1k1o/neko/opera" width="60" height="auto"/>
</a>
... see [all available images](https://neko.m1k1o.net/docs/v3/installation/docker-images)
</div>
### Other applications
<div align="center">
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#xfce">
<img src="https://neko.m1k1o.net/img/icons/xfce.svg" title="ghcr.io/m1k1o/neko/xfce" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#kde">
<img src="https://neko.m1k1o.net/img/icons/kde.svg" title="ghcr.io/m1k1o/neko/kde" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#remmina">
<img src="https://neko.m1k1o.net/img/icons/remmina.svg" title="ghcr.io/m1k1o/neko/remmina" width="60" height="auto"/>
</a>
<a href="https://neko.m1k1o.net/docs/v3/installation/docker-images#vlc">
<img src="https://neko.m1k1o.net/img/icons/vlc.svg" title="ghcr.io/m1k1o/neko/vlc" width="60" height="auto"/>
</a>
... others in <a href="https://github.com/m1k1o/neko-apps">m1k1o/neko-apps</a>
</div>
### Why neko?
I like cats 🐱 (`Neko` is the Japanese word for cat), I'm a weeb/nerd.
***But why the cat butt?*** Because cats are *assholes*, but you love them anyways.
## Multiple rooms
For neko room management software, visit [neko-rooms](https://github.com/m1k1o/neko-rooms).
It also offers [Zero-knowledge installation (with HTTPS)](https://github.com/m1k1o/neko-rooms/?tab=readme-ov-file#zero-knowledge-installation-with-https).
## Documentation
Full documentation is available at [neko.m1k1o.net](https://neko.m1k1o.net/). Key sections include:
- [Migration from V2](https://neko.m1k1o.net/docs/v3/migration-from-v2)
- [Getting Started](https://neko.m1k1o.net/docs/v3/quick-start)
- [Installation](https://neko.m1k1o.net/docs/v3/installation)
- [Examples](https://neko.m1k1o.net/docs/v3/installation/examples)
- [Configuration](https://neko.m1k1o.net/docs/v3/configuration)
- [Frequently Asked Questions](https://neko.m1k1o.net/docs/v3/faq)
- [Troubleshooting](https://neko.m1k1o.net/docs/v3/troubleshooting)
## How to Contribute
Contributions are welcome! Check the [Contributing Guide](https://neko.m1k1o.net/contributing) for details.
## Support
If you find Neko useful, consider supporting the project via [GitHub Sponsors](https://github.com/sponsors/m1k1o).
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Reporting a Vulnerability
If there are any vulnerabilities in **m1k1o/neko**, don't hesitate to _report them_.
1. Send an email to `security@m1k1o.net`.
2. Describe the vulnerability.
If you have a fix, that is most welcome -- please attach or summarize it in your message!
3. We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report.
Please **do not disclose the vulnerability publicly** until a fix is released!
4. Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it.
We appreciate your help in keeping Neko secure.
================================================
FILE: apps/brave/Dockerfile
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends apt-transport-https curl openbox; \
#
# install brave browser
ARCH=$(dpkg --print-architecture); \
curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg; \
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg arch=${ARCH}] https://brave-browser-apt-release.s3.brave.com/ stable main" \
| tee /etc/apt/sources.list.d/brave-browser-release.list; \
apt-get update; \
apt-get install -y --no-install-recommends brave-browser; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.conf /etc/neko/supervisord/brave.conf
COPY --chown=neko preferences.json /home/neko/.config/brave/Default/Preferences
COPY policies.json /etc/brave/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/brave/Dockerfile.nvidia
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest
FROM $BASE_IMAGE
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends apt-transport-https curl openbox; \
#
# install brave browser
curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg; \
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg arch=amd64] https://brave-browser-apt-release.s3.brave.com/ stable main" \
| tee /etc/apt/sources.list.d/brave-browser-release.list; \
apt-get update; \
apt-get install -y --no-install-recommends brave-browser; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.nvidia.conf /etc/neko/supervisord/brave.conf
COPY --chown=neko preferences.json /home/neko/.config/brave/Default/Preferences
COPY policies.json /etc/brave/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/brave/openbox.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Default openbox config but all window decorations are moved
thereby making it harder to accidentally close the virtual browser -->
<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>
<applications>
<!-- Match all windows and remove their decorations (obxprop | grep "^_OB_APP") -->
<application class="Brave-browser*" name="brave-browser*" role="browser">
<decor>no</decor>
<maximized>true</maximized>
<focus>yes</focus>
<layer>normal</layer>
</application>
</applications>
<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>Clearlooks</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>8</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>8</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>1</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>
<!-- Take a screenshot of the current window with scrot when Alt+Print are pressed -->
<keybind key="A-Print">
<action name="Execute"><command>scrot -s</command></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 -->
<keybind key="W-e">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Konqueror</name>
</startupnotify>
<command>kfmclient openProfile filemanagement</command>
</action>
</keybind>
<!-- Launch scrot when Print is pressed -->
<keybind key="Print">
<action name="Execute"><command>scrot</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/) -->
<!-- system menu files on Debian systems -->
<!--file>/var/lib/openbox/debian-menu.xml</file-->
<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>
================================================
FILE: apps/brave/policies.json
================================================
{
"AutofillAddressEnabled": false,
"AutofillCreditCardEnabled": false,
"BrowserSignin": 0,
"DefaultNotificationsSetting": 2,
"DeveloperToolsAvailability": 2,
"EditBookmarksEnabled": false,
"FullscreenAllowed": true,
"IncognitoModeAvailability": 1,
"SyncDisabled": true,
"AutoplayAllowed": true,
"BrowserAddPersonEnabled": false,
"BrowserGuestModeEnabled": false,
"DefaultPopupsSetting": 2,
"DownloadRestrictions": 3,
"VideoCaptureAllowed": true,
"AllowFileSelectionDialogs": false,
"PromptForDownloadLocation": false,
"BookmarkBarEnabled": false,
"PasswordManagerEnabled": false,
"URLAllowlist": [
"file:///home/neko/Downloads"
],
"URLBlocklist": [
"file://*",
"chrome://policy"
],
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx",
"mnjggcdmjocbbbhaepdhchncahnbgone;https://clients2.google.com/service/update2/crx"
],
"ExtensionInstallAllowlist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm",
"mnjggcdmjocbbbhaepdhchncahnbgone"
],
"ExtensionInstallBlocklist": [
"*"
]
}
================================================
FILE: apps/brave/preferences.json
================================================
{
"homepage": "http://www.google.com",
"homepage_is_newtabpage": false,
"first_run_tabs": [
"https://www.google.com/_/chrome/newtab?ie=UTF-8"
],
"custom_links": {
"initialized": true,
"list": [
{
"title": "YouTube",
"url": "https://www.youtube.com/"
},
{
"title": "Netflix",
"url": "https://netflix.com"
},
{
"title": "Hulu",
"url": "https://www.hulu.com/"
},
{
"title": "9Anime",
"url": "https://9anime.to/"
},
{
"title": "Crunchy Roll",
"url": "https://www.crunchyroll.com/"
},
{
"title": "Funimation",
"url": "https://www.funimation.com/"
},
{
"title": "Disney+",
"url": "https://www.disneyplus.com/"
},
{
"title": "HBO Now",
"url": "https://play.hbonow.com/"
},
{
"title": "Amazon Video",
"url": "https://www.amazon.com/Amazon-Video/b?node=2858778011"
},
{
"title": "VRV",
"url": "https://vrv.co/"
},
{
"title": "Twitch",
"url": "https://www.twitch.tv/"
},
{
"title": "Mixer",
"url": "https://mixer.com/"
}
]
},
"browser": {
"custom_chrome_frame": false,
"show_home_button": true,
"window_placement": {
"maximized": true
}
},
"bookmark_bar": {
"show_on_all_tabs": false
},
"sync_promo": {
"show_on_first_run_allowed": false
},
"distribution": {
"import_bookmarks_from_file": "bookmarks.html",
"import_bookmarks": true,
"import_history": true,
"import_home_page": true,
"import_search_engine": true,
"ping_delay": 60,
"do_not_create_desktop_shortcut": true,
"do_not_create_quick_launch_shortcut": true,
"do_not_create_taskbar_shortcut": true,
"do_not_launch_chrome": true,
"do_not_register_for_update_launch": true,
"make_chrome_default": true,
"make_chrome_default_for_user": true,
"system_level": false,
"verbose_logging": false
},
"profile": {
"avatar_index": 19,
"default_content_setting_values": {
"clipboard": 2,
"cookies": 4,
"geolocation": 2,
"media_stream_camera": 2,
"media_stream_mic": 2,
"midi_sysex": 2,
"payment_handler": 2,
"usb_guard": 2
},
"name": "neko",
"using_default_avatar": false,
"using_default_name": false,
"using_gaia_avatar": false
},
"signin": {
"allowed": false
}
}
================================================
FILE: apps/brave/supervisord.conf
================================================
[program:brave]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/brave-browser
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/brave
--no-first-run
--start-maximized
--bwsi
--force-dark-mode
--disable-file-system
--disable-gpu
--disable-software-rasterizer
--disable-dev-shm-usage
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/brave.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/brave/supervisord.nvidia.conf
================================================
[program:brave]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/bin/entrypoint.sh /usr/bin/brave-browser
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/brave
--no-first-run
--start-maximized
--bwsi
--force-dark-mode
--disable-file-system
--enable-features=Vulkan,UseSkiaRenderer,VaapiVideoEncoder,VaapiVideoDecoder,CanvasOopRasterization
--ignore-gpu-blocklist
--disable-seccomp-filter-sandbox
--use-angle=vulkan
--disable-software-rasterizer
--disable-dev-shm-usage
--disable-vulkan-surface
--enable-unsafe-webgpu
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/brave.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/chromium/Dockerfile
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
COPY ./widevinecdm.sh /widevine.sh
#
# install neko chromium
RUN set -eux; \
echo "deb http://ftp.de.debian.org/debian bookworm main" >> /etc/apt/sources.list; \
apt-get update; \
apt-get install -y --no-install-recommends chromium chromium-common chromium-sandbox openbox; \
#
# install widevine module (only for amd64)
CHROMIUM_DIR="/usr/lib/chromium"; \
ARCH=$(dpkg --print-architecture); \
if [ "${ARCH}" = "amd64" ]; then \
apt-get install -y --no-install-recommends xz-utils; \
./widevine.sh "${CHROMIUM_DIR}/WidevineCdm"; \
rm -f /widevine.sh; \
apt-get --purge autoremove -y xz-utils; \
else \
echo "Widevine is not supported on ${ARCH}"; \
fi; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.conf /etc/neko/supervisord/chromium.conf
COPY --chown=neko preferences.json /home/neko/.config/chromium/Default/Preferences
COPY policies.json /etc/chromium/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/chromium/Dockerfile.nvidia
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest
FROM $BASE_IMAGE
COPY ./widevinecdm.sh /widevine.sh
#
# install neko chromium
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends software-properties-common; \
# chromium-browser from default repo needs snap to be installed
# and nvidia base is ubuntu not debian
add-apt-repository ppa:system76/pop; \
apt-get update; \
apt-get install -y --no-install-recommends xz-utils chromium openbox; \
#
# install widevine module
CHROMIUM_DIR="/usr/lib/chromium"; \
./widevine.sh "${CHROMIUM_DIR}/WidevineCdm"; \
rm -f /widevine.sh; \
#
# clean up
apt-get --purge autoremove -y xz-utils; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.nvidia.conf /etc/neko/supervisord/chromium.conf
COPY --chown=neko preferences.json /home/neko/.config/chromium/Default/Preferences
COPY policies.json /etc/chromium/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/chromium/openbox.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Default openbox config but all window decorations are moved
thereby making it harder to accidentally close the virtual browser -->
<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>
<applications>
<!-- Match all windows and remove their decorations (obxprop | grep "^_OB_APP") -->
<application class="Chromium*" name="chromium*" role="browser">
<decor>no</decor>
<maximized>true</maximized>
<focus>yes</focus>
<layer>normal</layer>
</application>
</applications>
<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>Clearlooks</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>8</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>8</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>1</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>
<!-- Take a screenshot of the current window with scrot when Alt+Print are pressed -->
<keybind key="A-Print">
<action name="Execute"><command>scrot -s</command></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 -->
<keybind key="W-e">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Konqueror</name>
</startupnotify>
<command>kfmclient openProfile filemanagement</command>
</action>
</keybind>
<!-- Launch scrot when Print is pressed -->
<keybind key="Print">
<action name="Execute"><command>scrot</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/) -->
<!-- system menu files on Debian systems -->
<!--file>/var/lib/openbox/debian-menu.xml</file-->
<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>
================================================
FILE: apps/chromium/policies.json
================================================
{
"AutofillAddressEnabled": false,
"AutofillCreditCardEnabled": false,
"BrowserSignin": 0,
"DefaultNotificationsSetting": 2,
"DeveloperToolsAvailability": 2,
"EditBookmarksEnabled": false,
"FullscreenAllowed": true,
"IncognitoModeAvailability": 1,
"SyncDisabled": true,
"AutoplayAllowed": true,
"BrowserAddPersonEnabled": false,
"BrowserGuestModeEnabled": false,
"DefaultPopupsSetting": 2,
"DownloadRestrictions": 3,
"VideoCaptureAllowed": true,
"AllowFileSelectionDialogs": false,
"PromptForDownloadLocation": false,
"BookmarkBarEnabled": false,
"PasswordManagerEnabled": false,
"BrowserLabsEnabled": false,
"URLAllowlist": [
"file:///home/neko/Downloads"
],
"URLBlocklist": [
"file://*",
"chrome://policy"
],
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx",
"mnjggcdmjocbbbhaepdhchncahnbgone;https://clients2.google.com/service/update2/crx"
],
"ExtensionInstallAllowlist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm",
"mnjggcdmjocbbbhaepdhchncahnbgone"
],
"ExtensionInstallBlocklist": [
"*"
]
}
================================================
FILE: apps/chromium/preferences.json
================================================
{
"homepage": "http://www.google.com",
"homepage_is_newtabpage": false,
"first_run_tabs": [
"https://www.google.com/_/chrome/newtab?ie=UTF-8"
],
"custom_links": {
"initialized": true,
"list": [
{
"title": "YouTube",
"url": "https://www.youtube.com/"
},
{
"title": "Netflix",
"url": "https://netflix.com"
},
{
"title": "Hulu",
"url": "https://www.hulu.com/"
},
{
"title": "9Anime",
"url": "https://9anime.to/"
},
{
"title": "Crunchy Roll",
"url": "https://www.crunchyroll.com/"
},
{
"title": "Funimation",
"url": "https://www.funimation.com/"
},
{
"title": "Disney+",
"url": "https://www.disneyplus.com/"
},
{
"title": "HBO Now",
"url": "https://play.hbonow.com/"
},
{
"title": "Amazon Video",
"url": "https://www.amazon.com/Amazon-Video/b?node=2858778011"
},
{
"title": "VRV",
"url": "https://vrv.co/"
},
{
"title": "Twitch",
"url": "https://www.twitch.tv/"
},
{
"title": "Mixer",
"url": "https://mixer.com/"
}
]
},
"browser": {
"custom_chrome_frame": false,
"show_home_button": true,
"window_placement": {
"maximized": true
}
},
"bookmark_bar": {
"show_on_all_tabs": false
},
"sync_promo": {
"show_on_first_run_allowed": false
},
"distribution": {
"import_bookmarks_from_file": "bookmarks.html",
"import_bookmarks": true,
"import_history": true,
"import_home_page": true,
"import_search_engine": true,
"ping_delay": 60,
"do_not_create_desktop_shortcut": true,
"do_not_create_quick_launch_shortcut": true,
"do_not_create_taskbar_shortcut": true,
"do_not_launch_chrome": true,
"do_not_register_for_update_launch": true,
"make_chrome_default": true,
"make_chrome_default_for_user": true,
"system_level": false,
"verbose_logging": false
},
"profile": {
"avatar_index": 19,
"default_content_setting_values": {
"clipboard": 2,
"cookies": 4,
"geolocation": 2,
"media_stream_camera": 2,
"media_stream_mic": 2,
"midi_sysex": 2,
"payment_handler": 2,
"usb_guard": 2
},
"name": "neko",
"using_default_avatar": false,
"using_default_name": false,
"using_gaia_avatar": false
},
"signin": {
"allowed": false
}
}
================================================
FILE: apps/chromium/supervisord.conf
================================================
[program:chromium]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/chromium
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/chromium
--no-first-run
--start-maximized
--bwsi
--force-dark-mode
--disable-file-system
--disable-gpu
--disable-software-rasterizer
--disable-dev-shm-usage
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/chromium.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/chromium/supervisord.nvidia.conf
================================================
[program:chromium]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/bin/entrypoint.sh /usr/bin/chromium
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/chromium
--no-first-run
--start-maximized
--bwsi
--force-dark-mode
--disable-file-system
--enable-features=Vulkan,UseSkiaRenderer,VaapiVideoEncoder,VaapiVideoDecoder,CanvasOopRasterization
--ignore-gpu-blocklist
--disable-seccomp-filter-sandbox
--use-angle=vulkan
--disable-software-rasterizer
--disable-dev-shm-usage
--disable-vulkan-surface
--enable-unsafe-webgpu
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/chromium.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/chromium/widevinecdm.sh
================================================
#!/usr/bin/env bash
set -e
TARGET_DIR="$(realpath "$1")"
if [ -z "$TARGET_DIR" ]; then
echo "Usage: $0 /path/to/install/WidevineCdm"
exit 1
fi
TMPDIR=$(mktemp -d)
cd "$TMPDIR"
function cleanup {
rm -rf "$TMPDIR"
}
trap cleanup EXIT
# Fetch manifest and extract URL
URL=$(python3 -c "
import json, urllib.request
data = json.load(urllib.request.urlopen('https://raw.githubusercontent.com/mozilla/gecko-dev/master/toolkit/content/gmp-sources/widevinecdm.json'))
for v in data['vendors'].values():
for k, p in v['platforms'].items():
if 'Linux_x86_64-gcc3' in k:
print(p['fileUrl'])
break
")
# Download CRX
curl -L -o widevinecdm.crx "$URL"
# Install go-crx3
echo "Fetching latest go-crx3 version..."
VERSION=$(curl -s https://api.github.com/repos/m1k1o/go-crx3/releases/latest | grep 'tag_name' | cut -d '"' -f4)
ARTIFACT="go-crx3_${VERSION#v}_linux_amd64.tar.gz"
URL="https://github.com/m1k1o/go-crx3/releases/download/${VERSION}/${ARTIFACT}"
echo "Downloading $URL"
curl -L -o "$ARTIFACT" "$URL"
tar -xzf "$ARTIFACT"
# Unpack with go-crx3
./go-crx3 unpack widevinecdm.crx
mkdir -p "$TARGET_DIR"
cp -ar widevinecdm/* "$TARGET_DIR"
================================================
FILE: apps/firefox/Dockerfile
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
#
# install firefox
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends openbox; \
ARCH=$(dpkg --print-architecture); \
if [ "${ARCH}" = "armhf" ]; then \
#
# install firefox-esr for armhf
apt-get install -y --no-install-recommends firefox-esr; \
ln -s /usr/lib/firefox-esr /usr/lib/firefox; \
#
# install extensions
mkdir -p /usr/lib/firefox-esr/distribution/extensions; \
wget -O '/usr/lib/firefox-esr/distribution/extensions/uBlock0@raymondhill.net.xpi' https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi; \
wget -O '/usr/lib/firefox-esr/distribution/extensions/sponsorBlocker@ajay.app.xpi' https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi; \
else \
#
# fetch latest release (for amd64 and arm64)
if [ "${ARCH}" = "amd64" ]; then \
SRC_URL="https://download.mozilla.org/?product=firefox-latest&os=linux64&lang=en-US"; \
elif [ "${ARCH}" = "arm64" ]; then \
SRC_URL="https://download.mozilla.org/?product=firefox-latest&os=linux64-aarch64&lang=en-US"; \
fi; \
if [ ! -z "${SRC_URL}" ]; then \
apt-get install -y --no-install-recommends xz-utils libgtk-3-0 libdbus-glib-1-2; \
wget -O /tmp/firefox-setup.tar.xz "${SRC_URL}"; \
mkdir /usr/lib/firefox; \
tar -xvf /tmp/firefox-setup.tar.xz -C /usr/lib; \
rm -f /tmp/firefox-setup.tar.xz; \
ln -s /usr/lib/firefox/firefox /usr/bin/firefox; \
apt-get --purge autoremove -y xz-utils; \
else \
echo "Unsupported architecture: ${ARCH}"; \
exit 1; \
fi; \
fi; \
#
# create a profile directory
mkdir -p /home/neko/.mozilla/firefox/profile.default/extensions; \
chown -R neko:neko /home/neko/.mozilla/firefox/profile.default; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.conf /etc/neko/supervisord/firefox.conf
COPY neko.js /usr/lib/firefox/mozilla.cfg
COPY autoconfig.js /usr/lib/firefox/defaults/pref/autoconfig.js
COPY policies.json /usr/lib/firefox/distribution/policies.json
COPY --chown=neko profiles.ini /home/neko/.mozilla/firefox/profiles.ini
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/firefox/Dockerfile.nvidia
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest
FROM $BASE_IMAGE
ARG SRC_URL="https://download.mozilla.org/?product=firefox-latest&os=linux64&lang=en-US"
#
# install firefox
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends openbox \
xz-utils libgtk-3-0 libdbus-glib-1-2; \
#
# fetch latest release
wget -O /tmp/firefox-setup.tar.xz "${SRC_URL}"; \
mkdir /usr/lib/firefox; \
tar -xvf /tmp/firefox-setup.tar.xz -C /usr/lib; \
rm -f /tmp/firefox-setup.tar.xz; \
ln -s /usr/lib/firefox/firefox /usr/bin/firefox; \
#
# create a profile directory
mkdir -p /home/neko/.mozilla/firefox/profile.default/extensions; \
chown -R neko:neko /home/neko/.mozilla/firefox/profile.default; \
#
# clean up
apt-get --purge autoremove -y xz-utils; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.nvidia.conf /etc/neko/supervisord/firefox.conf
COPY neko.js /usr/lib/firefox/mozilla.cfg
COPY autoconfig.js /usr/lib/firefox/defaults/pref/autoconfig.js
COPY policies.json /usr/lib/firefox/distribution/policies.json
COPY --chown=neko profiles.ini /home/neko/.mozilla/firefox/profiles.ini
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/firefox/autoconfig.js
================================================
pref("general.config.obscure_value", 0);
pref("general.config.filename", "mozilla.cfg");
================================================
FILE: apps/firefox/neko.js
================================================
// firefox config for neko
lockPref("browser.tabs.closeWindowWithLastTab", false);
lockPref("app.update.auto", false);
lockPref("app.update.enabled", false);
lockPref("app.update.silent", true);
lockPref("browser.cache.disk.capacity", 1000);
lockPref("browser.download.useDownloadDir", false);
lockPref("browser.rights.3.shown", true);
lockPref("browser.search.update", false);
lockPref("browser.shell.checkDefaultBrowser", false);
lockPref("extensions.update.enabled", false);
lockPref("plugin.default_plugin_disabled", false);
lockPref("plugin.scan.plid.all", true);
lockPref("plugins.hide_infobar_for_missing_plugin", true);
lockPref("profile.allow_automigration", false);
lockPref("signon.prefillForms", false);
lockPref("signon.rememberSignons", false);
//lockPref("xpinstall.enabled", false);
//lockPref("xpinstall.whitelist.required", true);
lockPref("browser.download.manager.retention", 0);
lockPref("browser.download.folderList", 2);
lockPref("browser.download.forbid_open_with", true);
lockPref("browser.safebrowsing.downloads.enabled", false);
lockPref("browser.safebrowsing.downloads.remote.enabled", false);
lockPref("browser.helperApps.alwaysAsk.force", false);
lockPref("browser.helperApps.neverAsk.saveToDisk", "application/zip,application/octet-stream,image/jpeg,application/vnd.ms-outlook,text/html,application/pdf");
lockPref("browser.helperApps.neverAsk.openFile", "application/zip,application/octet-stream,image/jpeg,application/vnd.ms-outlook,text/html,application/pdf");
lockPref("browser.newtabpage.activity-stream.default.sites", "https://ipleak.net/,https://www.youtube.com/,https://www.google.com/");
// dark mode
lockPref("reader.color_scheme", "dark");
lockPref("devtools.theme", "dark");
lockPref("ui.systemUsesDarkTheme", 1);
lockPref("lightweightThemes.usedThemes","[]");
lockPref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org");
lockPref("extensions.activeThemeID", "firefox-compact-dark@mozilla.org");
lockPref("browser.theme.toolbar-theme", 0);
lockPref("browser.in-content.dark-mode", true);
================================================
FILE: apps/firefox/openbox.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Default openbox config but all window decorations are moved
thereby making it harder to accidentally close the virtual browser -->
<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>
<applications>
<!-- Match all windows and remove their decorations (obxprop | grep "^_OB_APP") -->
<application class="firefox" name="Navigator" role="browser">
<decor>no</decor>
<maximized>true</maximized>
<focus>yes</focus>
<layer>normal</layer>
</application>
</applications>
<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>Clearlooks</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>8</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>8</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>1</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>
<!-- Take a screenshot of the current window with scrot when Alt+Print are pressed -->
<keybind key="A-Print">
<action name="Execute"><command>scrot -s</command></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 -->
<keybind key="W-e">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Konqueror</name>
</startupnotify>
<command>kfmclient openProfile filemanagement</command>
</action>
</keybind>
<!-- Launch scrot when Print is pressed -->
<keybind key="Print">
<action name="Execute"><command>scrot</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/) -->
<!-- system menu files on Debian systems -->
<!--file>/var/lib/openbox/debian-menu.xml</file-->
<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>
================================================
FILE: apps/firefox/policies.json
================================================
{
"policies": {
"BlockAboutAddons": false,
"BlockAboutConfig": true,
"BlockAboutProfiles": true,
"BlockAboutSupport": true,
"Bookmarks": [
{
"Title": "IPLeak",
"URL": "https://ipleak.net/",
"Favicon": "https://ipleak.net/favicon.ico",
"Folder": "Pages",
"Placement": "toolbar"
},
{
"Title": "YouTube",
"URL": "https://www.youtube.com/",
"Favicon": "https://www.youtube.com/favicon.ico",
"Folder": "Pages",
"Placement": "toolbar"
},
{
"Title": "Google",
"URL": "https://www.google.com/",
"Favicon": "https://www.google.com/favicon.ico",
"Folder": "Pages",
"Placement": "toolbar"
}
],
"CaptivePortal": false,
"DisableAppUpdate": true,
"DisableBuiltinPDFViewer": true,
"DisableDeveloperTools": false,
"DisableFeedbackCommands": true,
"DisableFirefoxAccounts": true,
"DisableFirefoxScreenshots": true,
"DisableFirefoxStudies": true,
"DisableForgetButton": true,
"DisableMasterPasswordCreation": true,
"DisablePocket": true,
"DisablePrivateBrowsing": true,
"DisableProfileImport": true,
"DisableProfileRefresh": true,
"DisableSafeMode": true,
"DisableSetDesktopBackground": true,
"DisableSystemAddonUpdate": true,
"DisableTelemetry": true,
"DisplayBookmarksToolbar": false,
"DontCheckDefaultBrowser": true,
"EnableTrackingProtection": {
"Cryptomining": true,
"Fingerprinting": true,
"Value": true
},
"ExtensionSettings": {
"*": {
"installation_mode": "blocked"
},
"sponsorBlocker@ajay.app": {
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/sponsorblock/latest.xpi",
"installation_mode": "force_installed"
},
"uBlock0@raymondhill.net": {
"install_url": "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi",
"installation_mode": "force_installed"
}
},
"ExtensionUpdate": false,
"FirefoxHome": {
"Highlights": false,
"Pocket": false,
"Search": true,
"Snippets": false,
"TopSites": true
},
"FlashPlugin": {},
"HardwareAcceleration": false,
"Homepage": {
"Additional": [],
"StartPage": "home"
},
"NewTabPage": true,
"NoDefaultBookmarks": true,
"OfferToSaveLogins": false,
"OfferToSaveLoginsDefault": false,
"OverrideFirstRunPage": "",
"OverridePostUpdatePage": "",
"PasswordManagerEnabled": false,
"Permissions": {
"Camera": {
"BlockNewRequests": true
},
"Location": {
"BlockNewRequests": true
},
"Microphone": {
"BlockNewRequests": true
},
"Notifications": {
"BlockNewRequests": true
}
},
"Preferences": {
"browser.tabs.warnOnClose": false,
"browser.urlbar.suggest.bookmark": false,
"browser.urlbar.suggest.history": false,
"browser.urlbar.suggest.openpage": false,
"datareporting.policy.dataSubmissionPolicyBypassNotification": true,
"dom.disable_window_flip": true,
"dom.disable_window_move_resize": true,
"dom.event.contextmenu.enabled": true,
"extensions.getAddons.showPane": false,
"places.history.enabled": false,
"privacy.file_unique_origin": true,
"ui.key.menuAccessKeyFocuses": false,
"browser.tabs.allowTabDetach": false
},
"PromptForDownloadLocation": false,
"SanitizeOnShutdown": {
"Cache": true,
"Cookies": true,
"Downloads": true,
"FormData": true,
"History": true,
"OfflineApps": true,
"Sessions": true,
"SiteSettings": true
}
}
}
================================================
FILE: apps/firefox/profiles.ini
================================================
[General]
StartWithLastProfile=1
[Profile0]
Name=default
IsRelative=1
Path=profile.default
Default=1
================================================
FILE: apps/firefox/supervisord.conf
================================================
[program:firefox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/firefox --no-remote -P default --display=%(ENV_DISPLAY)s -setDefaultBrowser -width 1280 -height 720
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/firefox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/firefox/supervisord.nvidia.conf
================================================
[program:firefox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/bin/entrypoint.sh /usr/bin/firefox
--no-remote
-P default
--display=%(ENV_DISPLAY)s
-setDefaultBrowser
-width 1280
-height 720
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/firefox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/google-chrome/Dockerfile
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
ARG SRC_URL="https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
#
# install google chrome
RUN set -eux; apt-get update; \
wget -O /tmp/google-chrome.deb "${SRC_URL}"; \
apt-get install -y --no-install-recommends openbox /tmp/google-chrome.deb; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.conf /etc/neko/supervisord/google-chrome.conf
COPY --chown=neko preferences.json /home/neko/.config/google-chrome/Default/Preferences
COPY policies.json /etc/opt/chrome/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/google-chrome/Dockerfile.nvidia
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest
FROM $BASE_IMAGE
# latest working version with EGL: 111.0.5563.146, revert when resolved
# 112.0.5615.49 fails: https://github.com/VirtualGL/virtualgl/issues/229
# google does not provide a direct link to the deb file anymore
# ARG SRC_URL="https://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_111.0.5563.146-1_amd64.deb"
ARG SRC_URL="https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"
#
# install google chrome
RUN set -eux; apt-get update; \
wget -O /tmp/google-chrome.deb "${SRC_URL}"; \
apt-get install -y --no-install-recommends openbox /tmp/google-chrome.deb; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.nvidia.conf /etc/neko/supervisord/google-chrome.conf
COPY --chown=neko preferences.json /home/neko/.config/google-chrome/Default/Preferences
COPY policies.json /etc/opt/chrome/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/google-chrome/openbox.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Default openbox config but all window decorations are moved
thereby making it harder to accidentally close the virtual browser -->
<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>
<applications>
<!-- Match all windows and remove their decorations (obxprop | grep "^_OB_APP") -->
<application class="Google-chrome*" name="google-chrome*" role="browser">
<decor>no</decor>
<maximized>true</maximized>
<focus>yes</focus>
<layer>normal</layer>
</application>
</applications>
<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>Clearlooks</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>8</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>8</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>1</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>
<!-- Take a screenshot of the current window with scrot when Alt+Print are pressed -->
<keybind key="A-Print">
<action name="Execute"><command>scrot -s</command></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 -->
<keybind key="W-e">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Konqueror</name>
</startupnotify>
<command>kfmclient openProfile filemanagement</command>
</action>
</keybind>
<!-- Launch scrot when Print is pressed -->
<keybind key="Print">
<action name="Execute"><command>scrot</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/) -->
<!-- system menu files on Debian systems -->
<!--file>/var/lib/openbox/debian-menu.xml</file-->
<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>
================================================
FILE: apps/google-chrome/policies.json
================================================
{
"AutofillAddressEnabled": false,
"AutofillCreditCardEnabled": false,
"BrowserSignin": 0,
"DefaultNotificationsSetting": 2,
"DeveloperToolsAvailability": 2,
"EditBookmarksEnabled": false,
"FullscreenAllowed": true,
"IncognitoModeAvailability": 1,
"SyncDisabled": true,
"AutoplayAllowed": true,
"BrowserAddPersonEnabled": false,
"BrowserGuestModeEnabled": false,
"DefaultPopupsSetting": 2,
"DownloadRestrictions": 3,
"VideoCaptureAllowed": true,
"AllowFileSelectionDialogs": false,
"PromptForDownloadLocation": false,
"BookmarkBarEnabled": false,
"PasswordManagerEnabled": false,
"URLAllowlist": [
"file:///home/neko/Downloads"
],
"URLBlocklist": [
"file://*",
"chrome://policy"
],
"ExtensionInstallForcelist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm;https://clients2.google.com/service/update2/crx",
"mnjggcdmjocbbbhaepdhchncahnbgone;https://clients2.google.com/service/update2/crx"
],
"ExtensionInstallAllowlist": [
"cjpalhdlnbpafiamejdnhcphjbkeiagm",
"mnjggcdmjocbbbhaepdhchncahnbgone"
],
"ExtensionInstallBlocklist": [
"*"
]
}
================================================
FILE: apps/google-chrome/preferences.json
================================================
{
"homepage": "http://www.google.com",
"homepage_is_newtabpage": false,
"first_run_tabs": [
"https://www.google.com/_/chrome/newtab?ie=UTF-8"
],
"custom_links": {
"initialized": true,
"list": [
{
"title": "YouTube",
"url": "https://www.youtube.com/"
},
{
"title": "Netflix",
"url": "https://netflix.com"
},
{
"title": "Hulu",
"url": "https://www.hulu.com/"
},
{
"title": "9Anime",
"url": "https://9anime.to/"
},
{
"title": "Crunchy Roll",
"url": "https://www.crunchyroll.com/"
},
{
"title": "Funimation",
"url": "https://www.funimation.com/"
},
{
"title": "Disney+",
"url": "https://www.disneyplus.com/"
},
{
"title": "HBO Now",
"url": "https://play.hbonow.com/"
},
{
"title": "Amazon Video",
"url": "https://www.amazon.com/Amazon-Video/b?node=2858778011"
},
{
"title": "VRV",
"url": "https://vrv.co/"
},
{
"title": "Twitch",
"url": "https://www.twitch.tv/"
},
{
"title": "Mixer",
"url": "https://mixer.com/"
}
]
},
"browser": {
"custom_chrome_frame": false,
"show_home_button": true,
"window_placement": {
"maximized": true
}
},
"bookmark_bar": {
"show_on_all_tabs": false
},
"sync_promo": {
"show_on_first_run_allowed": false
},
"distribution": {
"import_bookmarks_from_file": "bookmarks.html",
"import_bookmarks": true,
"import_history": true,
"import_home_page": true,
"import_search_engine": true,
"ping_delay": 60,
"do_not_create_desktop_shortcut": true,
"do_not_create_quick_launch_shortcut": true,
"do_not_create_taskbar_shortcut": true,
"do_not_launch_chrome": true,
"do_not_register_for_update_launch": true,
"make_chrome_default": true,
"make_chrome_default_for_user": true,
"system_level": false,
"verbose_logging": false
},
"profile": {
"avatar_index": 19,
"default_content_setting_values": {
"clipboard": 2,
"cookies": 4,
"geolocation": 2,
"media_stream_camera": 2,
"media_stream_mic": 2,
"midi_sysex": 2,
"payment_handler": 2,
"usb_guard": 2
},
"name": "neko",
"using_default_avatar": false,
"using_default_name": false,
"using_gaia_avatar": false
},
"signin": {
"allowed": false
}
}
================================================
FILE: apps/google-chrome/supervisord.conf
================================================
[program:google-chrome]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/google-chrome
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/google-chrome
--no-first-run
--start-maximized
--bwsi
--force-dark-mode
--disable-file-system
--disable-gpu
--disable-software-rasterizer
--disable-dev-shm-usage
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/google-chrome.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/google-chrome/supervisord.nvidia.conf
================================================
[program:google-chrome]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/bin/entrypoint.sh /usr/bin/google-chrome
--window-position=0,0
--display=%(ENV_DISPLAY)s
--user-data-dir=/home/neko/.config/chromium
--no-first-run
--start-maximized
--bwsi
--force-dark-mode
--disable-file-system
--enable-features=Vulkan,UseSkiaRenderer,VaapiVideoEncoder,VaapiVideoDecoder,CanvasOopRasterization
--ignore-gpu-blocklist
--disable-seccomp-filter-sandbox
--use-angle=vulkan
--disable-software-rasterizer
--disable-dev-shm-usage
--disable-vulkan-surface
--enable-unsafe-webgpu
stopsignal=INT
autorestart=true
priority=800
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/google-chrome.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:openbox]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/openbox --config-file /etc/neko/openbox.xml
autorestart=true
priority=300
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/openbox.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/kde/Dockerfile
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
#
# install kde
RUN set -eux; apt-get update; \
apt-get install -y --no-install-recommends kde-full kwin-x11 sudo; \
#
# add user to sudoers
usermod -aG sudo neko; \
echo "neko:neko" | chpasswd; \
echo "%sudo ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers; \
# clean up
apt remove xserver-xorg-legacy -y; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# disable autolock
RUN kwriteconfig5 --file /home/neko/.config/kscreenlockerrc --group Daemon --key Autolock false; \
chown neko:neko /home/neko/.config/kscreenlockerrc
#
# copy configuation files
COPY supervisord.conf /etc/neko/supervisord/kde.conf
================================================
FILE: apps/kde/supervisord.conf
================================================
[program:kde]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/startplasma-x11
stopsignal=INT
autorestart=true
priority=500
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/kde.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
[program:kwin]
environment=HOME="/home/%(ENV_USER)s",USER="%(ENV_USER)s",DISPLAY="%(ENV_DISPLAY)s"
command=/usr/bin/kwin_x11
stopsignal=INT
autorestart=true
priority=500
user=%(ENV_USER)s
stdout_logfile=/var/log/neko/kwin.log
stdout_logfile_maxbytes=100MB
stdout_logfile_backups=10
redirect_stderr=true
================================================
FILE: apps/microsoft-edge/Dockerfile
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
ARG API_URL="https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/"
#
# install microsoft edge
RUN set -eux; apt-get update; \
#
# fetch latest release
SRC_URL="${API_URL}$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"]*\).*/\1/p' | sort --version-sort | tail -1)"; \
wget -O /tmp/microsoft-edge.deb "${SRC_URL}"; \
apt-get install -y --no-install-recommends openbox /tmp/microsoft-edge.deb; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.conf /etc/neko/supervisord/microsoft-edge.conf
COPY --chown=neko preferences.json /home/neko/.config/microsoft-edge/Default/Preferences
COPY policies.json /etc/opt/edge/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/microsoft-edge/Dockerfile.nvidia
================================================
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
ARG API_URL="https://packages.microsoft.com/repos/edge/pool/main/m/microsoft-edge-stable/"
#
# install microsoft edge
RUN set -eux; apt-get update; \
#
# fetch latest release
SRC_URL="${API_URL}$(wget -O - "${API_URL}" 2>/dev/null | sed -n 's/.*href="\([^"]*\).*/\1/p' | sort --version-sort | tail -1)"; \
wget -O /tmp/microsoft-edge.deb "${SRC_URL}"; \
apt-get install -y --no-install-recommends openbox /tmp/microsoft-edge.deb; \
#
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
#
# copy configuation files
COPY supervisord.nvidia.conf /etc/neko/supervisord/microsoft-edge.conf
COPY --chown=neko preferences.json /home/neko/.config/microsoft-edge/Default/Preferences
COPY policies.json /etc/opt/edge/policies/managed/policies.json
COPY openbox.xml /etc/neko/openbox.xml
================================================
FILE: apps/microsoft-edge/openbox.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!-- Default openbox config but all window decorations are moved
thereby making it harder to accidentally close the virtual browser -->
<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>
<applications>
<!-- Match all windows and remove their decorations (obxprop | grep "^_OB_APP") -->
<application class="Microsoft-edge*" name="microsoft-edge*" role="browser">
<decor>no</decor>
<maximized>true</maximized>
<focus>yes</focus>
<layer>normal</layer>
</application>
</applications>
<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>Clearlooks</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>8</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>8</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>1</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>
<!-- Take a screenshot of the current window with scrot when Alt+Print are pressed -->
<keybind key="A-Print">
<action name="Execute"><command>scrot -s</command></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 -->
<keybind key="W-e">
<action name="Execute">
<startupnotify>
<enabled>true</enabled>
<name>Konqueror</name>
</startupnotify>
<command>kfmclient openProfile filemanagement</command>
</action>
</keybind>
<!-- Launch scrot when Print is pressed -->
<keybind key="Print">
<
gitextract_7wv1b94k/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── client_build.yml
│ ├── client_test.yml
│ ├── dockerhub.yml
│ ├── ghcr.yml
│ ├── ghcr_intel.yml
│ ├── ghcr_nvidia.yml
│ ├── image_app.yml
│ ├── image_base.yml
│ ├── server_test.yml
│ ├── webpage_build.yml
│ ├── webpage_deploy.yml
│ └── webpage_test.yml
├── .gitignore
├── .vscode/
│ ├── launch.json
│ └── settings.json
├── Dockerfile.tmpl
├── LICENSE
├── README.md
├── SECURITY.md
├── apps/
│ ├── brave/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── chromium/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ ├── supervisord.nvidia.conf
│ │ └── widevinecdm.sh
│ ├── firefox/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── autoconfig.js
│ │ ├── neko.js
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── profiles.ini
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── google-chrome/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── kde/
│ │ ├── Dockerfile
│ │ └── supervisord.conf
│ ├── microsoft-edge/
│ │ ├── Dockerfile
│ │ ├── Dockerfile.nvidia
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── supervisord.nvidia.conf
│ ├── opera/
│ │ ├── Dockerfile
│ │ ├── fix-ffmpeg-widevine.sh
│ │ ├── openbox.xml
│ │ └── supervisord.conf
│ ├── remmina/
│ │ ├── Dockerfile
│ │ ├── rdp.remmina
│ │ ├── remmina.pref
│ │ ├── run-remmina.sh
│ │ ├── spice.remmina
│ │ ├── supervisord.conf
│ │ └── vnc.remmina
│ ├── tor-browser/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ └── supervisord.conf
│ ├── ungoogled-chromium/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ ├── supervisord.conf
│ │ └── widevinecdm.sh
│ ├── vivaldi/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── preferences.json
│ │ └── supervisord.conf
│ ├── vlc/
│ │ ├── Dockerfile
│ │ ├── openbox.xml
│ │ └── supervisord.conf
│ ├── waterfox/
│ │ ├── Dockerfile
│ │ ├── autoconfig.js
│ │ ├── neko.js
│ │ ├── openbox.xml
│ │ ├── policies.json
│ │ ├── profiles.ini
│ │ └── supervisord.conf
│ └── xfce/
│ ├── Dockerfile
│ └── supervisord.conf
├── build
├── client/
│ ├── .babelrc
│ ├── .browserslistrc
│ ├── .editorconfig
│ ├── .eslintrc
│ ├── .prettierrc
│ ├── .vscode/
│ │ └── settings.json
│ ├── Dockerfile
│ ├── dev/
│ │ ├── build
│ │ ├── exec
│ │ ├── npm
│ │ └── serve
│ ├── package.json
│ ├── public/
│ │ ├── browserconfig.xml
│ │ ├── emoji.json
│ │ ├── index.html
│ │ ├── keyboard_layouts.json
│ │ └── site.webmanifest
│ ├── src/
│ │ ├── app.vue
│ │ ├── assets/
│ │ │ └── styles/
│ │ │ ├── _reset.scss
│ │ │ ├── _variables.scss
│ │ │ ├── main.scss
│ │ │ └── vendor/
│ │ │ ├── _emoji.scss
│ │ │ ├── _emote.scss
│ │ │ ├── _font-awesome.scss
│ │ │ ├── _font-whitney.scss
│ │ │ ├── _github.scss
│ │ │ ├── _swal.scss
│ │ │ └── _tooltip.scss
│ │ ├── components/
│ │ │ ├── about.vue
│ │ │ ├── avatar.vue
│ │ │ ├── chat.vue
│ │ │ ├── clipboard.vue
│ │ │ ├── connect.vue
│ │ │ ├── context.vue
│ │ │ ├── controls.vue
│ │ │ ├── emoji.vue
│ │ │ ├── emote.vue
│ │ │ ├── emotes.vue
│ │ │ ├── files.vue
│ │ │ ├── header.vue
│ │ │ ├── markdown.ts
│ │ │ ├── members.vue
│ │ │ ├── menu.vue
│ │ │ ├── resolution.vue
│ │ │ ├── settings.vue
│ │ │ ├── side.vue
│ │ │ ├── unsupported.vue
│ │ │ └── video.vue
│ │ ├── lib.ts
│ │ ├── locale/
│ │ │ ├── de-de.ts
│ │ │ ├── en-us.ts
│ │ │ ├── es-sp.ts
│ │ │ ├── fi-fi.ts
│ │ │ ├── fr-fr.ts
│ │ │ ├── id-id.ts
│ │ │ ├── index.ts
│ │ │ ├── ja-jp.ts
│ │ │ ├── ko-kr.ts
│ │ │ ├── nb-no.ts
│ │ │ ├── pl-pl.ts
│ │ │ ├── ru-ru.ts
│ │ │ ├── sk-sk.ts
│ │ │ ├── sv-se.ts
│ │ │ ├── zh-cn.ts
│ │ │ └── zh-tw.ts
│ │ ├── main.ts
│ │ ├── neko/
│ │ │ ├── base.ts
│ │ │ ├── data.ts
│ │ │ ├── events.ts
│ │ │ ├── index.ts
│ │ │ ├── messages.ts
│ │ │ └── types.ts
│ │ ├── plugins/
│ │ │ ├── anime.ts
│ │ │ ├── axios.ts
│ │ │ ├── i18n.ts
│ │ │ ├── log.ts
│ │ │ ├── neko.ts
│ │ │ └── swal.ts
│ │ ├── store/
│ │ │ ├── chat.ts
│ │ │ ├── client.ts
│ │ │ ├── emoji.ts
│ │ │ ├── files.ts
│ │ │ ├── index.ts
│ │ │ ├── remote.ts
│ │ │ ├── settings.ts
│ │ │ ├── user.ts
│ │ │ └── video.ts
│ │ ├── types/
│ │ │ ├── eventemitter3.d.ts
│ │ │ ├── navigator.keyboard.d.ts
│ │ │ ├── shims-scss.d.ts
│ │ │ ├── shims-tsx.d.ts
│ │ │ └── shims-vue.d.ts
│ │ └── utils/
│ │ ├── guacamole-keyboard.js
│ │ ├── guacamole-keyboard.ts
│ │ ├── index.ts
│ │ └── localstorage.ts
│ ├── tools/
│ │ ├── emoji.ts
│ │ ├── emoji_custom.ts
│ │ └── tsconfig.json
│ ├── tsconfig.json
│ └── vue.config.js
├── config.yml
├── docker-compose.yaml
├── neko.code-workspace
├── runtime/
│ ├── .Xresources
│ ├── Dockerfile
│ ├── Dockerfile.bookworm
│ ├── Dockerfile.intel
│ ├── Dockerfile.intel.bookworm
│ ├── Dockerfile.nvidia
│ ├── Dockerfile.nvidia.bookworm
│ ├── dbus
│ ├── default.pa
│ ├── fontconfig/
│ │ └── 75-emoji.conf
│ ├── fonts/
│ │ └── .gitkeep
│ ├── icon-theme/
│ │ └── .gitkeep
│ ├── intel/
│ │ ├── add-render-group.sh
│ │ └── supervisord.rendergroup.conf
│ ├── nvidia/
│ │ └── entrypoint.sh
│ ├── supervisord.conf
│ ├── supervisord.dbus.conf
│ └── xorg.conf
├── server/
│ ├── .gitignore
│ ├── Dockerfile
│ ├── Dockerfile.bookworm
│ ├── build
│ ├── cmd/
│ │ ├── neko/
│ │ │ └── main.go
│ │ ├── plugins.go
│ │ ├── root.go
│ │ └── serve.go
│ ├── dev/
│ │ ├── build
│ │ ├── exec
│ │ ├── fmt
│ │ ├── go
│ │ ├── lint
│ │ ├── rebuild
│ │ ├── rebuild.input
│ │ ├── runtime/
│ │ │ ├── Dockerfile
│ │ │ ├── config.nvidia.yml
│ │ │ ├── config.yml
│ │ │ └── supervisord.conf
│ │ └── start
│ ├── go.mod
│ ├── go.sum
│ ├── internal/
│ │ ├── api/
│ │ │ ├── members/
│ │ │ │ ├── bluk.go
│ │ │ │ ├── controler.go
│ │ │ │ └── handler.go
│ │ │ ├── room/
│ │ │ │ ├── broadcast.go
│ │ │ │ ├── clipboard.go
│ │ │ │ ├── control.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── keyboard.go
│ │ │ │ ├── screen.go
│ │ │ │ ├── settings.go
│ │ │ │ └── upload.go
│ │ │ ├── router.go
│ │ │ ├── session.go
│ │ │ └── sessions/
│ │ │ ├── controller.go
│ │ │ └── handler.go
│ │ ├── capture/
│ │ │ ├── broadcast.go
│ │ │ ├── manager.go
│ │ │ ├── screencast.go
│ │ │ ├── streamselector.go
│ │ │ ├── streamsink.go
│ │ │ └── streamsrc.go
│ │ ├── config/
│ │ │ ├── capture.go
│ │ │ ├── capture_pipeline.go
│ │ │ ├── config.go
│ │ │ ├── desktop.go
│ │ │ ├── member.go
│ │ │ ├── plugins.go
│ │ │ ├── root.go
│ │ │ ├── server.go
│ │ │ ├── session.go
│ │ │ └── webrtc.go
│ │ ├── desktop/
│ │ │ ├── clipboard.go
│ │ │ ├── drop.go
│ │ │ ├── filechooserdialog.go
│ │ │ ├── manager.go
│ │ │ ├── xevent.go
│ │ │ ├── xinput.go
│ │ │ └── xorg.go
│ │ ├── http/
│ │ │ ├── batch.go
│ │ │ ├── debug.go
│ │ │ ├── legacy/
│ │ │ │ ├── event/
│ │ │ │ │ └── events.go
│ │ │ │ ├── handler.go
│ │ │ │ ├── message/
│ │ │ │ │ └── messages.go
│ │ │ │ ├── session.go
│ │ │ │ ├── types/
│ │ │ │ │ └── types.go
│ │ │ │ ├── wstobackend.go
│ │ │ │ └── wstoclient.go
│ │ │ ├── logger.go
│ │ │ ├── manager.go
│ │ │ └── router.go
│ │ ├── member/
│ │ │ ├── file/
│ │ │ │ ├── provider.go
│ │ │ │ ├── provider_test.go
│ │ │ │ └── types.go
│ │ │ ├── manager.go
│ │ │ ├── multiuser/
│ │ │ │ ├── provider.go
│ │ │ │ └── types.go
│ │ │ ├── noauth/
│ │ │ │ └── provider.go
│ │ │ └── object/
│ │ │ ├── provider.go
│ │ │ └── types.go
│ │ ├── plugins/
│ │ │ ├── chat/
│ │ │ │ ├── config.go
│ │ │ │ ├── manager.go
│ │ │ │ ├── plugin.go
│ │ │ │ └── types.go
│ │ │ ├── dependency.go
│ │ │ ├── dependency_test.go
│ │ │ ├── filetransfer/
│ │ │ │ ├── config.go
│ │ │ │ ├── manager.go
│ │ │ │ ├── plugin.go
│ │ │ │ ├── types.go
│ │ │ │ └── utils.go
│ │ │ └── manager.go
│ │ ├── session/
│ │ │ ├── auth.go
│ │ │ ├── manager.go
│ │ │ ├── serialize.go
│ │ │ └── session.go
│ │ ├── webrtc/
│ │ │ ├── cursor/
│ │ │ │ ├── image.go
│ │ │ │ └── position.go
│ │ │ ├── handler.go
│ │ │ ├── legacyhandler.go
│ │ │ ├── manager.go
│ │ │ ├── metrics.go
│ │ │ ├── payload/
│ │ │ │ ├── receive.go
│ │ │ │ ├── send.go
│ │ │ │ └── types.go
│ │ │ ├── peer.go
│ │ │ ├── pionlog/
│ │ │ │ ├── factory.go
│ │ │ │ ├── logger.go
│ │ │ │ └── nullog.go
│ │ │ └── track.go
│ │ └── websocket/
│ │ ├── filechooserdialog.go
│ │ ├── handler/
│ │ │ ├── clipboard.go
│ │ │ ├── control.go
│ │ │ ├── handler.go
│ │ │ ├── keyboard.go
│ │ │ ├── screen.go
│ │ │ ├── send.go
│ │ │ ├── session.go
│ │ │ ├── signal.go
│ │ │ └── system.go
│ │ ├── manager.go
│ │ └── peer.go
│ ├── neko.go
│ ├── openapi.yaml
│ ├── pkg/
│ │ ├── auth/
│ │ │ ├── auth.go
│ │ │ └── auth_test.go
│ │ ├── drop/
│ │ │ ├── drop.c
│ │ │ ├── drop.go
│ │ │ └── drop.h
│ │ ├── gst/
│ │ │ ├── gst.c
│ │ │ ├── gst.go
│ │ │ └── gst.h
│ │ ├── types/
│ │ │ ├── api.go
│ │ │ ├── capture.go
│ │ │ ├── codec/
│ │ │ │ └── codecs.go
│ │ │ ├── desktop.go
│ │ │ ├── event/
│ │ │ │ └── events.go
│ │ │ ├── http.go
│ │ │ ├── member.go
│ │ │ ├── message/
│ │ │ │ └── messages.go
│ │ │ ├── plugins.go
│ │ │ ├── session.go
│ │ │ ├── webrtc.go
│ │ │ └── websocket.go
│ │ ├── utils/
│ │ │ ├── array.go
│ │ │ ├── color.go
│ │ │ ├── deocde.go
│ │ │ ├── http.go
│ │ │ ├── image.go
│ │ │ ├── request.go
│ │ │ ├── trenddetector.go
│ │ │ ├── uid.go
│ │ │ └── zip.go
│ │ ├── xevent/
│ │ │ ├── xevent.c
│ │ │ ├── xevent.go
│ │ │ └── xevent.h
│ │ ├── xinput/
│ │ │ ├── dummy.go
│ │ │ ├── types.go
│ │ │ └── xinput.go
│ │ └── xorg/
│ │ ├── keysymdef.go
│ │ ├── keysymdef.sh
│ │ ├── xorg.c
│ │ ├── xorg.go
│ │ └── xorg.h
│ └── plugins/
│ └── .gitkeep
├── tsconfig.json
├── utils/
│ ├── docker/
│ │ ├── go.mod
│ │ └── main.go
│ └── xorg-deps/
│ ├── Dockerfile
│ ├── xf86-input-neko/
│ │ ├── .gitignore
│ │ ├── 80-neko.conf
│ │ ├── COPYING
│ │ ├── Dockerfile
│ │ ├── Makefile.am
│ │ ├── README.md
│ │ ├── autogen-clean.sh
│ │ ├── autogen.sh
│ │ ├── configure.ac
│ │ ├── m4/
│ │ │ └── .gitkeep
│ │ ├── release.sh
│ │ ├── src/
│ │ │ ├── Makefile.am
│ │ │ └── neko.c
│ │ └── xorg-neko.pc.in
│ └── xf86-video-dummy/
│ ├── 01_v0.3.8_xdummy-randr.patch
│ ├── README.md
│ └── v0.3.8/
│ ├── COPYING
│ ├── ChangeLog
│ ├── Makefile.am
│ ├── Makefile.in
│ ├── README
│ ├── aclocal.m4
│ ├── compile
│ ├── config.guess
│ ├── config.h.in
│ ├── config.sub
│ ├── configure
│ ├── configure.ac
│ ├── depcomp
│ ├── install-sh
│ ├── ltmain.sh
│ ├── missing
│ └── src/
│ ├── Makefile.am
│ ├── Makefile.in
│ ├── compat-api.h
│ ├── dummy.h
│ ├── dummy_cursor.c
│ ├── dummy_dga.c
│ └── dummy_driver.c
└── webpage/
├── .gitignore
├── README.md
├── docs/
│ ├── api/
│ │ ├── README.mdx
│ │ ├── batch.api.mdx
│ │ ├── broadcast-start.api.mdx
│ │ ├── broadcast-status.api.mdx
│ │ ├── broadcast-stop.api.mdx
│ │ ├── clipboard-get-image.api.mdx
│ │ ├── clipboard-get-text.api.mdx
│ │ ├── clipboard-set-text.api.mdx
│ │ ├── control-give.api.mdx
│ │ ├── control-release.api.mdx
│ │ ├── control-request.api.mdx
│ │ ├── control-reset.api.mdx
│ │ ├── control-status.api.mdx
│ │ ├── control-take.api.mdx
│ │ ├── current-session.tag.mdx
│ │ ├── general.tag.mdx
│ │ ├── healthcheck.api.mdx
│ │ ├── keyboard-map-get.api.mdx
│ │ ├── keyboard-map-set.api.mdx
│ │ ├── keyboard-modifiers-get.api.mdx
│ │ ├── keyboard-modifiers-set.api.mdx
│ │ ├── login.api.mdx
│ │ ├── logout.api.mdx
│ │ ├── members-bulk-delete.api.mdx
│ │ ├── members-bulk-update.api.mdx
│ │ ├── members-create.api.mdx
│ │ ├── members-get-profile.api.mdx
│ │ ├── members-list.api.mdx
│ │ ├── members-remove.api.mdx
│ │ ├── members-update-password.api.mdx
│ │ ├── members-update-profile.api.mdx
│ │ ├── members.tag.mdx
│ │ ├── metrics.api.mdx
│ │ ├── profile.api.mdx
│ │ ├── room-broadcast.tag.mdx
│ │ ├── room-clipboard.tag.mdx
│ │ ├── room-control.tag.mdx
│ │ ├── room-keyboard.tag.mdx
│ │ ├── room-screen.tag.mdx
│ │ ├── room-settings.tag.mdx
│ │ ├── room-upload.tag.mdx
│ │ ├── schemas/
│ │ │ └── memberprofile.schema.mdx
│ │ ├── screen-cast-image.api.mdx
│ │ ├── screen-configuration-change.api.mdx
│ │ ├── screen-configuration.api.mdx
│ │ ├── screen-configurations-list.api.mdx
│ │ ├── screen-shot-image.api.mdx
│ │ ├── session-disconnect.api.mdx
│ │ ├── session-get.api.mdx
│ │ ├── session-remove.api.mdx
│ │ ├── sessions-get.api.mdx
│ │ ├── sessions.tag.mdx
│ │ ├── settings-get.api.mdx
│ │ ├── settings-set.api.mdx
│ │ ├── sidebar.ts
│ │ ├── stats.api.mdx
│ │ ├── upload-dialog-close.api.mdx
│ │ ├── upload-dialog.api.mdx
│ │ ├── upload-drop.api.mdx
│ │ └── whoami.api.mdx
│ ├── configuration/
│ │ ├── README.md
│ │ ├── authentication.md
│ │ ├── capture.md
│ │ ├── desktop.md
│ │ ├── help.json
│ │ ├── help.txt
│ │ ├── plugins.md
│ │ └── webrtc.md
│ ├── customization/
│ │ ├── README.md
│ │ ├── browsers.json
│ │ ├── browsers.md
│ │ ├── browsers.tsx
│ │ ├── networking.md
│ │ ├── projects.md
│ │ └── ui.md
│ ├── developer-guide/
│ │ ├── README.md
│ │ ├── build.md
│ │ └── repository-structure.md
│ ├── faq.md
│ ├── hardware-acceleration/
│ │ ├── amd-gpu-support.md
│ │ ├── gpu-acceleration-overview.md
│ │ ├── intel-qsv.md
│ │ ├── nvidia-gpu-support.md
│ │ └── raspberry-pi.md
│ ├── installation/
│ │ ├── README.md
│ │ ├── docker-images.md
│ │ └── examples.md
│ ├── introduction.md
│ ├── migration-from-v2/
│ │ ├── README.md
│ │ ├── help.json
│ │ └── help.txt
│ ├── quick-start.md
│ ├── release-notes.md
│ ├── reverse-proxy-setup.md
│ ├── roadmap.md
│ └── troubleshooting.md
├── docusaurus.config.ts
├── package.json
├── scripts/
│ ├── gen-api-docs.sh
│ └── gen-config.sh
├── sidebars.ts
├── src/
│ ├── components/
│ │ ├── Anchor.tsx
│ │ ├── AppIcon.tsx
│ │ ├── Configuration/
│ │ │ ├── generate.js
│ │ │ └── index.tsx
│ │ ├── HomepageFeatures/
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ ├── HomepageShowcase/
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ └── HomepageUseCases/
│ │ ├── index.tsx
│ │ └── styles.module.css
│ ├── css/
│ │ └── custom.css
│ └── pages/
│ ├── contact.md
│ ├── contributing.md
│ ├── index.module.css
│ ├── index.tsx
│ └── non-goals.md
├── static/
│ ├── .nojekyll
│ ├── .well-known/
│ │ └── security.txt
│ └── CNAME
├── tsconfig.json
├── versioned_docs/
│ └── version-v2/
│ ├── README.md
│ ├── configuration.md
│ ├── examples.md
│ ├── faq.md
│ ├── quick-start.md
│ ├── reverse-proxy.md
│ └── troubleshooting.md
├── versioned_sidebars/
│ └── version-v2-sidebars.json
└── versions.json
Showing preview only (308K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3695 symbols across 189 files)
FILE: client/src/components/markdown.ts
type Rule (line 7) | type Rule = SingleNodeParserRule & HtmlOutputRule
type MarkdownRules (line 9) | interface MarkdownRules extends Rules<HtmlOutputRule> {
type HTMLAttributes (line 34) | interface HTMLAttributes {
type MarkdownState (line 38) | interface MarkdownState extends State {}
function htmlTag (line 40) | function htmlTag(
method parse (line 85) | parse(capture, parse, state) {
method html (line 92) | html(node, output, state) {
method match (line 98) | match(source, state, prevSource) {
method parse (line 103) | parse(capture, parse, state) {
method parse (line 127) | parse(capture) {
method html (line 138) | html(node, output, state) {
method parse (line 149) | parse(capture) {
method html (line 160) | html(node, output, state) {
method parse (line 172) | parse(capture) {
method html (line 183) | html(node, output, state) {
method html (line 190) | html(node, output, state) {
method parse (line 205) | parse(capture) {
method html (line 210) | html(node, output, state) {
method parse (line 226) | parse(capture) {
method html (line 232) | html(node, output, state) {
method parse (line 239) | parse(capture, parse, state) {
method html (line 244) | html(node, output, state) {
method render (line 260) | render(h: any) {
FILE: client/src/lib.ts
method $accessor (line 38) | $accessor() {
method $client (line 41) | $client() {
method install (line 48) | install(Vue) {
function extend (line 55) | function extend(component: any) {
FILE: client/src/main.ts
method created (line 31) | created() {
FILE: client/src/neko/base.ts
type BaseEvents (line 14) | interface BaseEvents {
method id (line 35) | get id() {
method supported (line 39) | get supported() {
method socketOpen (line 43) | get socketOpen() {
method peerConnected (line 47) | get peerConnected() {
method connected (line 51) | get connected() {
method connect (line 55) | public connect(url: string, password: string, displayname: string) {
method disconnect (line 83) | protected disconnect() {
method microphoneActive (line 141) | get microphoneActive() {
method enableMicrophone (line 145) | public async enableMicrophone(): Promise<void> {
method disableMicrophone (line 168) | public disableMicrophone(): void {
method sendData (line 189) | public sendData(event: string, data: any) {
method sendMessage (line 240) | public sendMessage(event: WebSocketEvents, payload?: WebSocketPayloads) {
method createPeer (line 249) | public async createPeer(lite: boolean, servers: RTCIceServer[]) {
method setRemoteOffer (line 351) | public async setRemoteOffer(sdp: string) {
method setRemoteAnswer (line 384) | public async setRemoteAnswer(sdp: string) {
method onMessage (line 393) | private async onMessage(e: MessageEvent) {
method onData (line 438) | private onData(e: MessageEvent) {
method onTrack (line 442) | private onTrack(event: RTCTrackEvent) {
method onError (line 452) | private onError(event: Event) {
method onConnected (line 456) | private onConnected() {
method onTimeout (line 471) | private onTimeout() {
method onDisconnected (line 480) | protected onDisconnected(reason?: Error) {
method [EVENT.MESSAGE] (line 486) | protected [EVENT.MESSAGE](event: string, payload: any) {
FILE: client/src/neko/data.ts
constant OPCODE (line 1) | const OPCODE = {
FILE: client/src/neko/events.ts
constant EVENT (line 1) | const EVENT = {
type Events (line 71) | type Events = typeof EVENT
type WebSocketEvents (line 73) | type WebSocketEvents =
type ControlEvents (line 85) | type ControlEvents =
type SystemEvents (line 93) | type SystemEvents = typeof EVENT.SYSTEM.DISCONNECT
type ClientEvents (line 94) | type ClientEvents = typeof EVENT.CLIENT.HEARTBEAT
type MemberEvents (line 95) | type MemberEvents = typeof EVENT.MEMBER.LIST | typeof EVENT.MEMBER.CONNE...
type SignalEvents (line 97) | type SignalEvents =
type ChatEvents (line 103) | type ChatEvents = typeof EVENT.CHAT.MESSAGE | typeof EVENT.CHAT.EMOTE
type FileTransferEvents (line 105) | type FileTransferEvents = typeof EVENT.FILETRANSFER.LIST | typeof EVENT....
type ScreenEvents (line 107) | type ScreenEvents = typeof EVENT.SCREEN.CONFIGURATIONS | typeof EVENT.SC...
type BroadcastEvents (line 109) | type BroadcastEvents =
type AdminEvents (line 114) | type AdminEvents =
FILE: client/src/neko/index.ts
type NekoEvents (line 28) | interface NekoEvents extends BaseEvents {}
class NekoClient (line 30) | class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
method init (line 35) | init(vue: Vue) {
method initWithURL (line 44) | initWithURL(vue: Vue, url: string) {
method cleanup (line 52) | private cleanup() {
method login (line 60) | login(password: string, displayname: string) {
method logout (line 64) | logout() {
method member (line 596) | protected member(id: string): Member | undefined {
method [EVENT.RECONNECTING] (line 77) | protected [EVENT.RECONNECTING]() {
method [EVENT.CONNECTING] (line 87) | protected [EVENT.CONNECTING]() {
method [EVENT.CONNECTED] (line 91) | protected [EVENT.CONNECTED]() {
method [EVENT.DISCONNECTED] (line 109) | protected [EVENT.DISCONNECTED](reason?: Error) {
method [EVENT.TRACK] (line 122) | protected [EVENT.TRACK](event: RTCTrackEvent) {
method [EVENT.DATA] (line 132) | protected [EVENT.DATA]() {}
method [EVENT.SYSTEM.INIT] (line 137) | protected [EVENT.SYSTEM.INIT]({ implicit_hosting, locks, file_transfer, ...
method [EVENT.SYSTEM.DISCONNECT] (line 155) | protected [EVENT.SYSTEM.DISCONNECT]({ message }: SystemMessagePayload) {
method [EVENT.SYSTEM.ERROR] (line 171) | protected [EVENT.SYSTEM.ERROR]({ title, message }: SystemMessagePayload) {
method [EVENT.MEMBER.LIST] (line 183) | protected [EVENT.MEMBER.LIST]({ members }: MemberListPayload) {
method [EVENT.MEMBER.CONNECTED] (line 193) | protected [EVENT.MEMBER.CONNECTED](member: MemberPayload) {
method [EVENT.MEMBER.DISCONNECTED] (line 206) | protected [EVENT.MEMBER.DISCONNECTED]({ id }: MemberDisconnectPayload) {
method [EVENT.CONTROL.LOCKED] (line 225) | protected [EVENT.CONTROL.LOCKED]({ id }: ControlPayload) {
method [EVENT.CONTROL.RELEASE] (line 254) | protected [EVENT.CONTROL.RELEASE]({ id }: ControlPayload) {
method [EVENT.CONTROL.REQUEST] (line 281) | protected [EVENT.CONTROL.REQUEST]({ id }: ControlPayload) {
method [EVENT.CONTROL.REQUESTING] (line 297) | protected [EVENT.CONTROL.REQUESTING]({ id }: ControlPayload) {
method [EVENT.CONTROL.GIVE] (line 312) | protected [EVENT.CONTROL.GIVE]({ id, target }: ControlTargetPayload) {
method [EVENT.CONTROL.CLIPBOARD] (line 331) | protected [EVENT.CONTROL.CLIPBOARD]({ text }: ControlClipboardPayload) {
method [EVENT.CHAT.MESSAGE] (line 338) | protected [EVENT.CHAT.MESSAGE]({ id, content }: ChatPayload) {
method [EVENT.CHAT.EMOTE] (line 352) | protected [EVENT.CHAT.EMOTE]({ id, emote }: EmotePayload) {
method [EVENT.FILETRANSFER.LIST] (line 364) | protected [EVENT.FILETRANSFER.LIST]({ cwd, files }: FileTransferListPayl...
method [EVENT.SCREEN.CONFIGURATIONS] (line 372) | protected [EVENT.SCREEN.CONFIGURATIONS]({ configurations }: ScreenConfig...
method [EVENT.SCREEN.RESOLUTION] (line 376) | protected [EVENT.SCREEN.RESOLUTION]({ id, width, height, rate }: ScreenR...
method [EVENT.BROADCAST.STATUS] (line 403) | protected [EVENT.BROADCAST.STATUS](payload: BroadcastStatusPayload) {
method [EVENT.ADMIN.BAN] (line 410) | protected [EVENT.ADMIN.BAN]({ id, target }: AdminTargetPayload) {
method [EVENT.ADMIN.KICK] (line 430) | protected [EVENT.ADMIN.KICK]({ id, target }: AdminTargetPayload) {
method [EVENT.ADMIN.MUTE] (line 450) | protected [EVENT.ADMIN.MUTE]({ id, target }: AdminTargetPayload) {
method [EVENT.ADMIN.UNMUTE] (line 472) | protected [EVENT.ADMIN.UNMUTE]({ id, target }: AdminTargetPayload) {
method [EVENT.ADMIN.LOCK] (line 494) | protected [EVENT.ADMIN.LOCK]({ id, resource }: AdminLockMessage) {
method [EVENT.ADMIN.UNLOCK] (line 505) | protected [EVENT.ADMIN.UNLOCK]({ id, resource }: AdminLockMessage) {
method [EVENT.ADMIN.CONTROL] (line 516) | protected [EVENT.ADMIN.CONTROL]({ id, target }: AdminTargetPayload) {
method [EVENT.ADMIN.RELEASE] (line 545) | protected [EVENT.ADMIN.RELEASE]({ id, target }: AdminTargetPayload) {
method [EVENT.ADMIN.GIVE] (line 572) | protected [EVENT.ADMIN.GIVE]({ id, target }: AdminTargetPayload) {
FILE: client/src/neko/messages.ts
type WebSocketMessages (line 15) | type WebSocketMessages =
type WebSocketPayloads (line 29) | type WebSocketPayloads =
type WebSocketMessage (line 49) | interface WebSocketMessage {
type SystemInit (line 57) | interface SystemInit extends WebSocketMessage, SystemInitPayload {
type SystemInitPayload (line 60) | interface SystemInitPayload {
type SystemMessage (line 69) | interface SystemMessage extends WebSocketMessage, SystemMessagePayload {
type SystemMessagePayload (line 72) | interface SystemMessagePayload {
type SignalProvideMessage (line 81) | interface SignalProvideMessage extends WebSocketMessage, SignalProvidePa...
type SignalProvidePayload (line 84) | interface SignalProvidePayload {
type SignalOfferMessage (line 92) | interface SignalOfferMessage extends WebSocketMessage, SignalOfferPayload {
type SignalOfferPayload (line 95) | interface SignalOfferPayload {
type SignalAnswerMessage (line 100) | interface SignalAnswerMessage extends WebSocketMessage, SignalAnswerPayl...
type SignalAnswerPayload (line 103) | interface SignalAnswerPayload {
type SignalCandidateMessage (line 109) | interface SignalCandidateMessage extends WebSocketMessage, SignalCandida...
type SignalCandidatePayload (line 112) | interface SignalCandidatePayload {
type MemberListMessage (line 120) | interface MemberListMessage extends WebSocketMessage, MemberListPayload {
type MemberListPayload (line 123) | interface MemberListPayload {
type MemberConnectMessage (line 128) | interface MemberConnectMessage extends WebSocketMessage, MemberPayload {
type MemberPayload (line 131) | type MemberPayload = Member
type MemberDisconnectMessage (line 134) | interface MemberDisconnectMessage extends WebSocketMessage, MemberPayload {
type MemberDisconnectPayload (line 137) | interface MemberDisconnectPayload {
type ControlMessage (line 145) | interface ControlMessage extends WebSocketMessage, ControlPayload {
type ControlPayload (line 148) | interface ControlPayload {
type ControlTargetPayload (line 152) | interface ControlTargetPayload {
type ControlClipboardPayload (line 157) | interface ControlClipboardPayload {
type ControlKeyboardPayload (line 161) | interface ControlKeyboardPayload {
type ChatMessage (line 172) | interface ChatMessage extends WebSocketMessage, ChatPayload {
type ChatSendPayload (line 176) | interface ChatSendPayload {
type ChatPayload (line 179) | interface ChatPayload {
type ChatEmoteMessage (line 185) | interface ChatEmoteMessage extends WebSocketMessage, EmotePayload {
type EmotePayload (line 189) | interface EmotePayload {
type EmojiSendPayload (line 194) | interface EmojiSendPayload {
type FileTransferListMessage (line 201) | interface FileTransferListMessage extends WebSocketMessage, FileTransfer...
type FileTransferListPayload (line 205) | interface FileTransferListPayload {
type ScreenResolutionMessage (line 213) | interface ScreenResolutionMessage extends WebSocketMessage, ScreenResolu...
type ScreenResolutionPayload (line 217) | interface ScreenResolutionPayload extends ScreenResolution {
type ScreenConfigurationsMessage (line 221) | interface ScreenConfigurationsMessage extends WebSocketMessage, ScreenCo...
type ScreenConfigurationsPayload (line 225) | interface ScreenConfigurationsPayload {
type BroadcastCreatePayload (line 232) | interface BroadcastCreatePayload {
type BroadcastStatusPayload (line 236) | interface BroadcastStatusPayload {
type AdminMessage (line 244) | interface AdminMessage extends WebSocketMessage, AdminPayload {
type AdminPayload (line 248) | interface AdminPayload {
type AdminTargetMessage (line 252) | interface AdminTargetMessage extends WebSocketMessage, AdminTargetPayload {
type AdminTargetPayload (line 256) | interface AdminTargetPayload {
type AdminLockMessage (line 261) | interface AdminLockMessage extends WebSocketMessage, AdminLockPayload {
type AdminLockResource (line 266) | type AdminLockResource = 'login' | 'control' | 'file_transfer'
type AdminLockPayload (line 268) | interface AdminLockPayload {
FILE: client/src/neko/types.ts
type Member (line 1) | interface Member {
type ScreenConfigurations (line 10) | interface ScreenConfigurations {
type ScreenConfiguration (line 14) | interface ScreenConfiguration {
type ScreenResolution (line 20) | interface ScreenResolution {
type FileListItem (line 26) | interface FileListItem {
type FileTransfer (line 32) | interface FileTransfer {
FILE: client/src/plugins/anime.ts
type FunctionBasedParameter (line 4) | type FunctionBasedParameter = (element: HTMLElement, index: number, leng...
type AnimeTarget (line 5) | type AnimeTarget = string | object | HTMLElement | SVGElement | NodeList...
type AnimeFunc (line 6) | type AnimeFunc = (params: AnimeParams) => AnimeInstance
type Anime (line 8) | interface Anime {
type Vue (line 33) | interface Vue {
method install (line 39) | install(Vue) {
FILE: client/src/plugins/axios.ts
type Window (line 7) | interface Window {
type Vue (line 13) | interface Vue {
method install (line 19) | install(Vue) {
FILE: client/src/plugins/i18n.ts
function detectBrowserLanguage (line 10) | function detectBrowserLanguage(): string {
FILE: client/src/plugins/log.ts
type Logger (line 3) | interface Logger {
type Window (line 13) | interface Window {
type Vue (line 19) | interface Vue {
method install (line 25) | install(Vue) {
FILE: client/src/plugins/neko.ts
type Window (line 7) | interface Window {
type Vue (line 13) | interface Vue {
method install (line 19) | install(Vue) {
FILE: client/src/plugins/swal.ts
type VueSwalInstance (line 6) | type VueSwalInstance = typeof Swal.fire
type Vue (line 9) | interface Vue {
type VueConstructor (line 13) | interface VueConstructor {
type VueSweetalert2Options (line 18) | interface VueSweetalert2Options extends SweetAlertOptions {
class VueSweetalert2 (line 22) | class VueSweetalert2 {
method install (line 23) | static install(vue: Vue | any, options?: VueSweetalert2Options): void {
FILE: client/src/store/chat.ts
type Emote (line 8) | interface Emote {
type Emotes (line 12) | interface Emotes {
type Message (line 16) | interface Message {
method addMessage (line 34) | addMessage(state, message: Message) {
method addEmote (line 42) | addEmote(state, { id, emote }: { id: string; emote: Emote }) {
method delEmote (line 49) | delEmote(state, id: string) {
method reset (line 57) | reset(state) {
method newEmote (line 67) | newEmote(store, emote: Emote) {
method newMessage (line 76) | newMessage(store, message: Message) {
method sendMessage (line 83) | sendMessage(store, content: string) {
method sendEmote (line 90) | sendEmote(store, emote: string) {
FILE: client/src/store/client.ts
method setTab (line 16) | setTab(state, tab: string) {
method setAbout (line 20) | setAbout(state, page: string) {
method toggleAbout (line 23) | toggleAbout(state) {
method toggleSide (line 26) | toggleSide(state) {
method setSide (line 30) | setSide(state, side: boolean) {
FILE: client/src/store/emoji.ts
type Group (line 7) | interface Group {
type Keywords (line 13) | interface Keywords {
type Emojis (line 17) | interface Emojis {
method setRecent (line 38) | setRecent(state, emoji: string) {
method addGroup (line 47) | addGroup(state, group: Group) {
method setKeywords (line 50) | setKeywords(state, keywords: Keywords) {
method setList (line 53) | setList(state, list: string[]) {
method initialise (line 61) | async initialise() {
FILE: client/src/store/files.ts
method _setCwd (line 17) | _setCwd(state, cwd: string) {
method _setFileList (line 21) | _setFileList(state, files: FileListItem[]) {
method _addTransfer (line 25) | _addTransfer(state, transfer: FileTransfer) {
method _removeTransfer (line 29) | _removeTransfer(state, transfer: FileTransfer) {
method setCwd (line 37) | setCwd(store, cwd: string) {
method setFileList (line 41) | setFileList(store, files: FileListItem[]) {
method addTransfer (line 45) | addTransfer(store, transfer: FileTransfer) {
method removeTransfer (line 52) | removeTransfer(store, transfer: FileTransfer) {
method cancelAllTransfers (line 56) | cancelAllTransfers() {
method refresh (line 65) | refresh() {
FILE: client/src/store/index.ts
method setActive (line 27) | setActive(state) {
method setLogin (line 31) | setLogin(state, { displayname, password }: { displayname: string; passwo...
method setLocked (line 36) | setLocked(state, resource: string) {
method setUnlocked (line 40) | setUnlocked(state, resource: string) {
method setConnnecting (line 44) | setConnnecting(state) {
method setConnected (line 49) | setConnected(state, connected: boolean) {
method initialise (line 66) | initialise() {
method lock (line 71) | lock(_, resource: AdminLockResource) {
method unlock (line 79) | unlock(_, resource: AdminLockResource) {
method toggleLock (line 87) | toggleLock(_, resource: AdminLockResource) {
method login (line 95) | login(store, { displayname, password }: { displayname: string; password:...
method logout (line 100) | logout() {
type Vue (line 125) | interface Vue {
FILE: client/src/store/remote.ts
method setHost (line 36) | setHost(state, host: string | Member) {
method setClipboard (line 44) | setClipboard(state, clipboard: string) {
method setKeyboardModifierState (line 48) | setKeyboardModifierState(state, { capsLock, numLock, scrollLock }) {
method setLocked (line 52) | setLocked(state, locked: boolean) {
method setImplicitHosting (line 56) | setImplicitHosting(state, val: boolean) {
method setFileTransfer (line 60) | setFileTransfer(state, val: boolean) {
method reset (line 64) | reset(state) {
method sendClipboard (line 74) | sendClipboard({ getters }, clipboard: string) {
method toggle (line 82) | toggle({ getters }) {
method request (line 94) | request({ getters }) {
method release (line 102) | release({ getters }) {
method give (line 110) | give({ getters }, member: string | Member) {
method adminControl (line 126) | adminControl() {
method adminRelease (line 134) | adminRelease() {
method adminGive (line 142) | adminGive(store, member: string | Member) {
method changeKeyboard (line 158) | changeKeyboard({ getters }) {
method syncKeyboardModifierState (line 166) | syncKeyboardModifierState({ state }, { capsLock, numLock, scrollLock }) {
FILE: client/src/store/settings.ts
type KeyboardLayouts (line 8) | interface KeyboardLayouts {
method setScroll (line 31) | setScroll(state, scroll: number) {
method setInvert (line 36) | setInvert(state, value: boolean) {
method setAutoplay (line 41) | setAutoplay(state, value: boolean) {
method setIgnore (line 46) | setIgnore(state, value: boolean) {
method setSound (line 51) | setSound(state, value: boolean) {
method setKeyboardLayout (line 56) | setKeyboardLayout(state, value: string) {
method setKeyboardLayoutsList (line 61) | setKeyboardLayoutsList(state, value: KeyboardLayouts) {
method setBroadcastStatus (line 64) | setBroadcastStatus(state, { url, isActive }) {
method initialise (line 73) | async initialise() {
method broadcastStatus (line 82) | broadcastStatus(store, { url, isActive }) {
method broadcastCreate (line 85) | broadcastCreate(store, url: string) {
method broadcastDestroy (line 88) | broadcastDestroy() {
FILE: client/src/store/user.ts
type Members (line 10) | interface Members {
method setIgnored (line 26) | setIgnored(state, { id, ignored }: { id: string; ignored: boolean }) {
method setMuted (line 32) | setMuted(state, { id, muted }: { id: string; muted: boolean }) {
method setMembers (line 38) | setMembers(state, members: Member[]) {
method setMember (line 49) | setMember(state, id: string) {
method addMember (line 52) | addMember(state, member: Member) {
method delMember (line 62) | delMember(state, id: string) {
method reset (line 68) | reset(state) {
method ban (line 76) | ban({ state }, member: string | Member) {
method kick (line 92) | kick({ state }, member: string | Member) {
method mute (line 108) | mute({ state }, member: string | Member) {
method unmute (line 124) | unmute({ state }, member: string | Member) {
FILE: client/src/store/video.ts
method play (line 32) | play(state) {
method pause (line 38) | pause(state) {
method togglePlay (line 44) | togglePlay(state) {
method setMuted (line 50) | setMuted(state, muted: boolean) {
method toggleMute (line 55) | toggleMute(state) {
method setPlayable (line 60) | setPlayable(state, playable: boolean) {
method setResolution (line 67) | setResolution(state, { width, height, rate }: { width: number; height: n...
method setConfigurations (line 106) | setConfigurations(state, configurations: ScreenConfigurations) {
method setVolume (line 135) | setVolume(state, volume: number) {
method setStream (line 140) | setStream(state, index: number) {
method addTrack (line 144) | addTrack(state, [track, stream]: [MediaStreamTrack, MediaStream]) {
method delTrack (line 149) | delTrack(state, index: number) {
method reset (line 154) | reset(state) {
method screenConfiguations (line 172) | screenConfiguations() {
method screenGet (line 180) | screenGet() {
method screenSet (line 188) | screenSet(store, resolution: ScreenResolution) {
FILE: client/src/types/eventemitter3.d.ts
type Arguments (line 2) | type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] ex...
class TypedEventEmitter (line 4) | class TypedEventEmitter<Events> {
FILE: client/src/types/navigator.keyboard.d.ts
type Keyboard (line 5) | interface Keyboard {
type NavigatorKeyboard (line 10) | interface NavigatorKeyboard {
type Navigator (line 15) | interface Navigator extends NavigatorKeyboard {}
FILE: client/src/types/shims-tsx.d.ts
type Element (line 6) | interface Element extends VNode {}
type ElementClass (line 8) | interface ElementClass extends Vue {}
type IntrinsicElements (line 9) | interface IntrinsicElements {
FILE: client/src/utils/guacamole-keyboard.js
function keysym_from_key_identifier (line 711) | function keysym_from_key_identifier(identifier, location, shifted) {
function isControlCharacter (line 745) | function isControlCharacter(codepoint) {
function keysym_from_charcode (line 749) | function keysym_from_charcode(codepoint) {
function keysym_from_keycode (line 766) | function keysym_from_keycode(keyCode, location) {
function interpret_events (line 1075) | function interpret_events() {
FILE: client/src/utils/guacamole-keyboard.ts
type GuacamoleKeyboardInterface (line 3) | interface GuacamoleKeyboardInterface {
FILE: client/src/utils/index.ts
function makeid (line 1) | function makeid(length: number) {
function lockKeyboard (line 11) | function lockKeyboard() {
function unlockKeyboard (line 17) | function unlockKeyboard() {
function elementRequestFullscreen (line 23) | function elementRequestFullscreen(el: HTMLElement) {
function isFullscreen (line 48) | function isFullscreen(): boolean {
function onFullscreenChange (line 60) | function onFullscreenChange(el: HTMLElement, fn: () => void) {
FILE: client/src/utils/localstorage.ts
function set (line 1) | function set<T extends string | number | boolean>(key: string, val: T) {
function get (line 15) | function get<T extends string | number | boolean>(key: string, def: T): T {
FILE: client/tools/emoji.ts
type EmojiDatasource (line 7) | interface EmojiDatasource {
constant SHEET_COLUMNS (line 46) | const SHEET_COLUMNS = 58
constant MULTIPLY (line 47) | const MULTIPLY = 100 / (SHEET_COLUMNS - 1)
FILE: server/cmd/neko/main.go
function main (line 13) | func main() {
FILE: server/cmd/plugins.go
function init (line 14) | func init() {
function pluginsCmd (line 25) | func pluginsCmd(cmd *cobra.Command, args []string) {
FILE: server/cmd/root.go
function Execute (line 22) | func Execute() error {
function init (line 41) | func init() {
FILE: server/cmd/serve.go
function init (line 24) | func init() {
type serve (line 42) | type serve struct
method Init (line 68) | func (c *serve) Init(cmd *cobra.Command) error {
method PreRun (line 116) | func (c *serve) PreRun(cmd *cobra.Command, args []string) {
method Start (line 138) | func (c *serve) Start(cmd *cobra.Command) {
method Shutdown (line 208) | func (c *serve) Shutdown() {
method Run (line 233) | func (c *serve) Run(cmd *cobra.Command, args []string) {
FILE: server/internal/api/members/bluk.go
type MemberBulkUpdatePayload (line 12) | type MemberBulkUpdatePayload struct
method membersBulkUpdate (line 17) | func (h *MembersHandler) membersBulkUpdate(w http.ResponseWriter, r *htt...
type MemberBulkDeletePayload (line 59) | type MemberBulkDeletePayload struct
method membersBulkDelete (line 63) | func (h *MembersHandler) membersBulkDelete(w http.ResponseWriter, r *htt...
FILE: server/internal/api/members/controler.go
type MemberDataPayload (line 12) | type MemberDataPayload struct
type MemberCreatePayload (line 17) | type MemberCreatePayload struct
type MemberPasswordPayload (line 23) | type MemberPasswordPayload struct
method membersList (line 27) | func (h *MembersHandler) membersList(w http.ResponseWriter, r *http.Requ...
method membersCreate (line 56) | func (h *MembersHandler) membersCreate(w http.ResponseWriter, r *http.Re...
method membersRead (line 99) | func (h *MembersHandler) membersRead(w http.ResponseWriter, r *http.Requ...
method membersUpdateProfile (line 106) | func (h *MembersHandler) membersUpdateProfile(w http.ResponseWriter, r *...
method membersUpdatePassword (line 121) | func (h *MembersHandler) membersUpdatePassword(w http.ResponseWriter, r ...
method membersDelete (line 136) | func (h *MembersHandler) membersDelete(w http.ResponseWriter, r *http.Re...
FILE: server/internal/api/members/handler.go
type key (line 15) | type key
constant keyMemberCtx (line 17) | keyMemberCtx key = iota
type MembersHandler (line 19) | type MembersHandler struct
method Route (line 33) | func (h *MembersHandler) Route(r types.Router) {
method RouteBulk (line 47) | func (h *MembersHandler) RouteBulk(r types.Router) {
method ExtractMember (line 67) | func (h *MembersHandler) ExtractMember(w http.ResponseWriter, r *http....
function New (line 23) | func New(
type MemberData (line 54) | type MemberData struct
function SetMember (line 59) | func SetMember(r *http.Request, session MemberData) context.Context {
function GetMember (line 63) | func GetMember(r *http.Request) MemberData {
FILE: server/internal/api/room/broadcast.go
type BroadcastStatusPayload (line 11) | type BroadcastStatusPayload struct
method broadcastStatus (line 16) | func (h *RoomHandler) broadcastStatus(w http.ResponseWriter, r *http.Req...
method broadcastStart (line 25) | func (h *RoomHandler) broadcastStart(w http.ResponseWriter, r *http.Requ...
method broadcastStop (line 54) | func (h *RoomHandler) broadcastStop(w http.ResponseWriter, r *http.Reque...
FILE: server/internal/api/room/clipboard.go
type ClipboardPayload (line 14) | type ClipboardPayload struct
method clipboardGetText (line 19) | func (h *RoomHandler) clipboardGetText(w http.ResponseWriter, r *http.Re...
method clipboardSetText (line 31) | func (h *RoomHandler) clipboardSetText(w http.ResponseWriter, r *http.Re...
method clipboardGetImage (line 49) | func (h *RoomHandler) clipboardGetImage(w http.ResponseWriter, r *http.R...
FILE: server/internal/api/room/control.go
type ControlStatusPayload (line 14) | type ControlStatusPayload struct
type ControlTargetPayload (line 19) | type ControlTargetPayload struct
method controlStatus (line 23) | func (h *RoomHandler) controlStatus(w http.ResponseWriter, r *http.Reque...
method controlRequest (line 37) | func (h *RoomHandler) controlRequest(w http.ResponseWriter, r *http.Requ...
method controlRelease (line 62) | func (h *RoomHandler) controlRelease(w http.ResponseWriter, r *http.Requ...
method controlTake (line 74) | func (h *RoomHandler) controlTake(w http.ResponseWriter, r *http.Request...
method controlGive (line 81) | func (h *RoomHandler) controlGive(w http.ResponseWriter, r *http.Request...
method controlReset (line 99) | func (h *RoomHandler) controlReset(w http.ResponseWriter, r *http.Reques...
FILE: server/internal/api/room/handler.go
type RoomHandler (line 14) | type RoomHandler struct
method Route (line 57) | func (h *RoomHandler) Route(r types.Router) {
method uploadMiddleware (line 119) | func (h *RoomHandler) uploadMiddleware(w http.ResponseWriter, r *http....
function New (line 22) | func New(
FILE: server/internal/api/room/keyboard.go
method keyboardMapSet (line 10) | func (h *RoomHandler) keyboardMapSet(w http.ResponseWriter, r *http.Requ...
method keyboardMapGet (line 24) | func (h *RoomHandler) keyboardMapGet(w http.ResponseWriter, r *http.Requ...
method keyboardModifiersSet (line 33) | func (h *RoomHandler) keyboardModifiersSet(w http.ResponseWriter, r *htt...
method keyboardModifiersGet (line 43) | func (h *RoomHandler) keyboardModifiersGet(w http.ResponseWriter, r *htt...
FILE: server/internal/api/room/screen.go
method screenConfiguration (line 14) | func (h *RoomHandler) screenConfiguration(w http.ResponseWriter, r *http...
method screenConfigurationChange (line 20) | func (h *RoomHandler) screenConfigurationChange(w http.ResponseWriter, r...
method screenConfigurationsList (line 47) | func (h *RoomHandler) screenConfigurationsList(w http.ResponseWriter, r ...
method screenShotGet (line 53) | func (h *RoomHandler) screenShotGet(w http.ResponseWriter, r *http.Reque...
method screenCastGet (line 72) | func (h *RoomHandler) screenCastGet(w http.ResponseWriter, r *http.Reque...
FILE: server/internal/api/room/settings.go
method settingsGet (line 13) | func (h *RoomHandler) settingsGet(w http.ResponseWriter, r *http.Request...
method settingsSet (line 18) | func (h *RoomHandler) settingsSet(w http.ResponseWriter, r *http.Request...
FILE: server/internal/api/room/upload.go
constant maxUploadSize (line 16) | maxUploadSize = 32 << 20
method uploadDrop (line 18) | func (h *RoomHandler) uploadDrop(w http.ResponseWriter, r *http.Request)...
method uploadDialogPost (line 93) | func (h *RoomHandler) uploadDialogPost(w http.ResponseWriter, r *http.Re...
method uploadDialogClose (line 160) | func (h *RoomHandler) uploadDialogClose(w http.ResponseWriter, r *http.R...
FILE: server/internal/api/router.go
type ApiManagerCtx (line 16) | type ApiManagerCtx struct
method Route (line 40) | func (api *ApiManagerCtx) Route(r types.Router) {
method Authenticate (line 68) | func (api *ApiManagerCtx) Authenticate(w http.ResponseWriter, r *http....
method AddRouter (line 85) | func (api *ApiManagerCtx) AddRouter(path string, router func(types.Rou...
function New (line 24) | func New(
FILE: server/internal/api/session.go
type SessionLoginPayload (line 12) | type SessionLoginPayload struct
type SessionDataPayload (line 17) | type SessionDataPayload struct
method Login (line 24) | func (api *ApiManagerCtx) Login(w http.ResponseWriter, r *http.Request) ...
method Logout (line 58) | func (api *ApiManagerCtx) Logout(w http.ResponseWriter, r *http.Request)...
method Whoami (line 77) | func (api *ApiManagerCtx) Whoami(w http.ResponseWriter, r *http.Request)...
method UpdateProfile (line 87) | func (api *ApiManagerCtx) UpdateProfile(w http.ResponseWriter, r *http.R...
method Stats (line 107) | func (api *ApiManagerCtx) Stats(w http.ResponseWriter, r *http.Request) ...
FILE: server/internal/api/sessions/controller.go
type SessionDataPayload (line 14) | type SessionDataPayload struct
method sessionsList (line 20) | func (h *SessionsHandler) sessionsList(w http.ResponseWriter, r *http.Re...
method sessionsRead (line 33) | func (h *SessionsHandler) sessionsRead(w http.ResponseWriter, r *http.Re...
method sessionsDelete (line 48) | func (h *SessionsHandler) sessionsDelete(w http.ResponseWriter, r *http....
method sessionsDisconnect (line 68) | func (h *SessionsHandler) sessionsDisconnect(w http.ResponseWriter, r *h...
FILE: server/internal/api/sessions/handler.go
type SessionsHandler (line 8) | type SessionsHandler struct
method Route (line 22) | func (h *SessionsHandler) Route(r types.Router) {
function New (line 12) | func New(
FILE: server/internal/capture/broadcast.go
type BroacastManagerCtx (line 15) | type BroacastManagerCtx struct
method shutdown (line 71) | func (manager *BroacastManagerCtx) shutdown() {
method Start (line 77) | func (manager *BroacastManagerCtx) Start(url string) error {
method Stop (line 92) | func (manager *BroacastManagerCtx) Stop() {
method Started (line 100) | func (manager *BroacastManagerCtx) Started() bool {
method Url (line 107) | func (manager *BroacastManagerCtx) Url() string {
method createPipeline (line 114) | func (manager *BroacastManagerCtx) createPipeline() error {
method destroyPipeline (line 144) | func (manager *BroacastManagerCtx) destroyPipeline() {
function broadcastNew (line 31) | func broadcastNew(pipelineFn func(url string) (string, error), defaultUr...
FILE: server/internal/capture/manager.go
type CaptureManagerCtx (line 17) | type CaptureManagerCtx struct
method Start (line 196) | func (manager *CaptureManagerCtx) Start() {
method Shutdown (line 237) | func (manager *CaptureManagerCtx) Shutdown() error {
method Broadcast (line 252) | func (manager *CaptureManagerCtx) Broadcast() types.BroadcastManager {
method Screencast (line 256) | func (manager *CaptureManagerCtx) Screencast() types.ScreencastManager {
method Audio (line 260) | func (manager *CaptureManagerCtx) Audio() types.StreamSinkManager {
method Video (line 264) | func (manager *CaptureManagerCtx) Video() types.StreamSelectorManager {
method Webcam (line 268) | func (manager *CaptureManagerCtx) Webcam() types.StreamSrcManager {
method Microphone (line 272) | func (manager *CaptureManagerCtx) Microphone() types.StreamSrcManager {
function New (line 33) | func New(desktop types.DesktopManager, config *config.Capture) *CaptureM...
FILE: server/internal/capture/screencast.go
constant screencastTimeout (line 19) | screencastTimeout = 5 * time.Second
type ScreencastManagerCtx (line 21) | type ScreencastManagerCtx struct
method shutdown (line 113) | func (manager *ScreencastManagerCtx) shutdown() {
method Enabled (line 122) | func (manager *ScreencastManagerCtx) Enabled() bool {
method Started (line 129) | func (manager *ScreencastManagerCtx) Started() bool {
method Image (line 136) | func (manager *ScreencastManagerCtx) Image() ([]byte, error) {
method start (line 154) | func (manager *ScreencastManagerCtx) start() error {
method stop (line 171) | func (manager *ScreencastManagerCtx) stop() {
method createPipeline (line 179) | func (manager *ScreencastManagerCtx) createPipeline() error {
method setImage (line 236) | func (manager *ScreencastManagerCtx) setImage(image types.Sample) {
method destroyPipeline (line 244) | func (manager *ScreencastManagerCtx) destroyPipeline() {
function screencastNew (line 44) | func screencastNew(enabled bool, pipelineStr string) *ScreencastManagerC...
FILE: server/internal/capture/streamselector.go
type StreamSelectorManagerCtx (line 14) | type StreamSelectorManagerCtx struct
method shutdown (line 35) | func (manager *StreamSelectorManagerCtx) shutdown() {
method destroyPipelines (line 41) | func (manager *StreamSelectorManagerCtx) destroyPipelines() {
method recreatePipelines (line 49) | func (manager *StreamSelectorManagerCtx) recreatePipelines() error {
method IDs (line 61) | func (manager *StreamSelectorManagerCtx) IDs() []string {
method Codec (line 65) | func (manager *StreamSelectorManagerCtx) Codec() codec.RTPCodec {
method GetStream (line 69) | func (manager *StreamSelectorManagerCtx) GetStream(selector types.Stre...
method nearestBitrate (line 161) | func (manager *StreamSelectorManagerCtx) nearestBitrate(bitrate uint64...
function streamSelectorNew (line 21) | func streamSelectorNew(codec codec.RTPCodec, streams map[string]types.St...
FILE: server/internal/capture/streamsink.go
type StreamSinkManagerCtx (line 22) | type StreamSinkManagerCtx struct
method shutdown (line 125) | func (manager *StreamSinkManagerCtx) shutdown() {
method ID (line 141) | func (manager *StreamSinkManagerCtx) ID() string {
method Bitrate (line 145) | func (manager *StreamSinkManagerCtx) Bitrate() uint64 {
method Codec (line 149) | func (manager *StreamSinkManagerCtx) Codec() codec.RTPCodec {
method start (line 153) | func (manager *StreamSinkManagerCtx) start() error {
method stop (line 166) | func (manager *StreamSinkManagerCtx) stop() {
method addListener (line 173) | func (manager *StreamSinkManagerCtx) addListener(listener types.Sample...
method removeListener (line 198) | func (manager *StreamSinkManagerCtx) removeListener(listener types.Sam...
method AddListener (line 210) | func (manager *StreamSinkManagerCtx) AddListener(listener types.Sample...
method RemoveListener (line 229) | func (manager *StreamSinkManagerCtx) RemoveListener(listener types.Sam...
method MoveListenerTo (line 248) | func (manager *StreamSinkManagerCtx) MoveListenerTo(listener types.Sam...
method ListenersCount (line 291) | func (manager *StreamSinkManagerCtx) ListenersCount() int {
method Started (line 298) | func (manager *StreamSinkManagerCtx) Started() bool {
method CreatePipeline (line 302) | func (manager *StreamSinkManagerCtx) CreatePipeline() error {
method saveSampleBitrate (line 352) | func (manager *StreamSinkManagerCtx) saveSampleBitrate(timestamp time....
method onSample (line 373) | func (manager *StreamSinkManagerCtx) onSample(sample types.Sample) {
method DestroyPipeline (line 397) | func (manager *StreamSinkManagerCtx) DestroyPipeline() {
function streamSinkNew (line 51) | func streamSinkNew(codec codec.RTPCodec, pipelineFn func() (string, erro...
FILE: server/internal/capture/streamsrc.go
type StreamSrcManagerCtx (line 17) | type StreamSrcManagerCtx struct
method shutdown (line 101) | func (manager *StreamSrcManagerCtx) shutdown() {
method Codec (line 107) | func (manager *StreamSrcManagerCtx) Codec() codec.RTPCodec {
method Start (line 114) | func (manager *StreamSrcManagerCtx) Start(codec codec.RTPCodec) error {
method Stop (line 161) | func (manager *StreamSrcManagerCtx) Stop() {
method Push (line 180) | func (manager *StreamSrcManagerCtx) Push(bytes []byte) {
method Started (line 192) | func (manager *StreamSrcManagerCtx) Started() bool {
function streamSrcNew (line 33) | func streamSrcNew(enabled bool, codecPipeline map[string]string, video_i...
FILE: server/internal/config/capture.go
type HwEnc (line 18) | type HwEnc
constant HwEncUnset (line 22) | HwEncUnset HwEnc = iota
constant HwEncNone (line 23) | HwEncNone
constant HwEncVAAPI (line 24) | HwEncVAAPI
constant HwEncNVENC (line 25) | HwEncNVENC
type Capture (line 28) | type Capture struct
method Init (line 60) | func (Capture) Init(cmd *cobra.Command) error {
method InitV2 (line 193) | func (Capture) InitV2(cmd *cobra.Command) error {
method Set (line 319) | func (s *Capture) Set() {
method SetV2 (line 439) | func (s *Capture) SetV2() {
FILE: server/internal/config/capture_pipeline.go
constant videoSrc (line 34) | videoSrc = "ximagesrc display-name=%s show-pointer=true use-damage=false...
constant audioSrc (line 35) | audioSrc = "pulsesrc device=%s ! audio/x-raw,channels=2 ! audioconvert ! "
function NewBroadcastPipeline (line 38) | func NewBroadcastPipeline(device string, display string, pipelineSrc str...
function NewVideoPipeline (line 62) | func NewVideoPipeline(rtpCodec codec.RTPCodec, display string, pipelineS...
function NewAudioPipeline (line 190) | func NewAudioPipeline(rtpCodec codec.RTPCodec, device string, pipelineSr...
FILE: server/internal/config/config.go
type Config (line 5) | type Config interface
FILE: server/internal/config/desktop.go
type Desktop (line 15) | type Desktop struct
method Init (line 28) | func (Desktop) Init(cmd *cobra.Command) error {
method InitV2 (line 67) | func (Desktop) InitV2(cmd *cobra.Command) error {
method Set (line 76) | func (s *Desktop) Set() {
method SetV2 (line 112) | func (s *Desktop) SetV2() {
FILE: server/internal/config/member.go
type Member (line 15) | type Member struct
method Init (line 24) | func (Member) Init(cmd *cobra.Command) error {
method InitV2 (line 71) | func (Member) InitV2(cmd *cobra.Command) error {
method Set (line 85) | func (s *Member) Set() {
method SetV2 (line 144) | func (s *Member) SetV2() {
FILE: server/internal/config/plugins.go
type Plugins (line 8) | type Plugins struct
method Init (line 14) | func (Plugins) Init(cmd *cobra.Command) error {
method Set (line 33) | func (s *Plugins) Set() {
FILE: server/internal/config/root.go
type Root (line 14) | type Root struct
method Init (line 25) | func (Root) Init(cmd *cobra.Command) error {
method InitV2 (line 73) | func (Root) InitV2(cmd *cobra.Command) error {
method Set (line 82) | func (s *Root) Set() {
method SetV2 (line 123) | func (s *Root) SetV2() {
FILE: server/internal/config/server.go
type Server (line 13) | type Server struct
method Init (line 25) | func (Server) Init(cmd *cobra.Command) error {
method InitV2 (line 74) | func (Server) InitV2(cmd *cobra.Command) error {
method Set (line 113) | func (s *Server) Set() {
method SetV2 (line 130) | func (s *Server) SetV2() {
method HasCors (line 180) | func (s *Server) HasCors() bool {
method AllowOrigin (line 184) | func (s *Server) AllowOrigin(origin string) bool {
FILE: server/internal/config/session.go
type SessionCookie (line 11) | type SessionCookie struct
type Session (line 21) | type Session struct
method Init (line 37) | func (Session) Init(cmd *cobra.Command) error {
method InitV2 (line 127) | func (Session) InitV2(cmd *cobra.Command) error {
method Set (line 151) | func (s *Session) Set() {
method SetV2 (line 173) | func (s *Session) SetV2() {
FILE: server/internal/config/webrtc.go
constant defStunSrv (line 18) | defStunSrv = "stun:stun.l.google.com:19302"
type WebRTCEstimator (line 20) | type WebRTCEstimator struct
type WebRTC (line 42) | type WebRTC struct
method Init (line 58) | func (WebRTC) Init(cmd *cobra.Command) error {
method InitV2 (line 170) | func (WebRTC) InitV2(cmd *cobra.Command) error {
method Set (line 214) | func (s *WebRTC) Set() {
method SetV2 (line 320) | func (s *WebRTC) SetV2() {
FILE: server/internal/desktop/clipboard.go
constant ClipboardTextPlainTarget (line 14) | ClipboardTextPlainTarget = "UTF8_STRING"
constant ClipboardTextHtmlTarget (line 15) | ClipboardTextHtmlTarget = "text/html"
method ClipboardGetText (line 18) | func (manager *DesktopManagerCtx) ClipboardGetText() (*types.ClipboardTe...
method ClipboardSetText (line 33) | func (manager *DesktopManagerCtx) ClipboardSetText(data types.ClipboardT...
method ClipboardGetBinary (line 45) | func (manager *DesktopManagerCtx) ClipboardGetBinary(mime string) ([]byt...
method replaceClipboardCommand (line 61) | func (manager *DesktopManagerCtx) replaceClipboardCommand(newCmd *exec.C...
method ClipboardSetBinary (line 78) | func (manager *DesktopManagerCtx) ClipboardSetBinary(mime string, data [...
method ClipboardGetTargets (line 132) | func (manager *DesktopManagerCtx) ClipboardGetTargets() ([]string, error) {
FILE: server/internal/desktop/drop.go
constant dropMoveRepeat (line 10) | dropMoveRepeat = 4
constant dropMoveDelay (line 13) | dropMoveDelay = 100 * time.Millisecond
method DropFiles (line 15) | func (manager *DesktopManagerCtx) DropFiles(x int, y int, files []string...
method IsUploadDropEnabled (line 66) | func (manager *DesktopManagerCtx) IsUploadDropEnabled() bool {
FILE: server/internal/desktop/filechooserdialog.go
constant fileChooserDialogName (line 11) | fileChooserDialogName = "Open File"
constant fileChooserDialogShortSleep (line 14) | fileChooserDialogShortSleep = "0.2"
constant fileChooserDialogLongSleep (line 17) | fileChooserDialogLongSleep = "0.4"
method HandleFileChooserDialog (line 19) | func (manager *DesktopManagerCtx) HandleFileChooserDialog(uri string) er...
method CloseFileChooserDialog (line 59) | func (manager *DesktopManagerCtx) CloseFileChooserDialog() {
method IsFileChooserDialogEnabled (line 87) | func (manager *DesktopManagerCtx) IsFileChooserDialogEnabled() bool {
method IsFileChooserDialogOpened (line 91) | func (manager *DesktopManagerCtx) IsFileChooserDialogOpened() bool {
FILE: server/internal/desktop/manager.go
type DesktopManagerCtx (line 22) | type DesktopManagerCtx struct
method Start (line 55) | func (manager *DesktopManagerCtx) Start() {
method OnBeforeScreenSizeChange (line 125) | func (manager *DesktopManagerCtx) OnBeforeScreenSizeChange(listener fu...
method OnAfterScreenSizeChange (line 131) | func (manager *DesktopManagerCtx) OnAfterScreenSizeChange(listener fun...
method Shutdown (line 137) | func (manager *DesktopManagerCtx) Shutdown() error {
function New (line 37) | func New(config *config.Desktop) *DesktopManagerCtx {
FILE: server/internal/desktop/xevent.go
method OnCursorChanged (line 7) | func (manager *DesktopManagerCtx) OnCursorChanged(listener func(serial u...
method OnClipboardUpdated (line 13) | func (manager *DesktopManagerCtx) OnClipboardUpdated(listener func()) {
method OnFileChooserDialogOpened (line 19) | func (manager *DesktopManagerCtx) OnFileChooserDialogOpened(listener fun...
method OnFileChooserDialogClosed (line 25) | func (manager *DesktopManagerCtx) OnFileChooserDialogClosed(listener fun...
method OnEventError (line 31) | func (manager *DesktopManagerCtx) OnEventError(listener func(error_code ...
FILE: server/internal/desktop/xinput.go
method inputRelToAbs (line 5) | func (manager *DesktopManagerCtx) inputRelToAbs(x, y int) (int, int) {
method HasTouchSupport (line 9) | func (manager *DesktopManagerCtx) HasTouchSupport() bool {
method TouchBegin (line 14) | func (manager *DesktopManagerCtx) TouchBegin(touchId uint32, x, y int, p...
method TouchUpdate (line 22) | func (manager *DesktopManagerCtx) TouchUpdate(touchId uint32, x, y int, ...
method TouchEnd (line 30) | func (manager *DesktopManagerCtx) TouchEnd(touchId uint32, x, y int, pre...
FILE: server/internal/desktop/xorg.go
method Move (line 13) | func (manager *DesktopManagerCtx) Move(x, y int) {
method GetCursorPosition (line 17) | func (manager *DesktopManagerCtx) GetCursorPosition() (int, int) {
method Scroll (line 21) | func (manager *DesktopManagerCtx) Scroll(deltaX, deltaY int, controlKey ...
method ButtonDown (line 25) | func (manager *DesktopManagerCtx) ButtonDown(code uint32) error {
method KeyDown (line 29) | func (manager *DesktopManagerCtx) KeyDown(code uint32) error {
method ButtonUp (line 33) | func (manager *DesktopManagerCtx) ButtonUp(code uint32) error {
method KeyUp (line 37) | func (manager *DesktopManagerCtx) KeyUp(code uint32) error {
method ButtonPress (line 41) | func (manager *DesktopManagerCtx) ButtonPress(code uint32) error {
method KeyPress (line 48) | func (manager *DesktopManagerCtx) KeyPress(codes ...uint32) error {
method ResetKeys (line 65) | func (manager *DesktopManagerCtx) ResetKeys() {
method ScreenConfigurations (line 69) | func (manager *DesktopManagerCtx) ScreenConfigurations() []types.ScreenS...
method SetScreenSize (line 88) | func (manager *DesktopManagerCtx) SetScreenSize(screenSize types.ScreenS...
method GetScreenSize (line 106) | func (manager *DesktopManagerCtx) GetScreenSize() types.ScreenSize {
method SetKeyboardMap (line 110) | func (manager *DesktopManagerCtx) SetKeyboardMap(kbd types.KeyboardMap) ...
method GetKeyboardMap (line 117) | func (manager *DesktopManagerCtx) GetKeyboardMap() (*types.KeyboardMap, ...
method SetKeyboardModifiers (line 142) | func (manager *DesktopManagerCtx) SetKeyboardModifiers(mod types.Keyboar...
method GetKeyboardModifiers (line 176) | func (manager *DesktopManagerCtx) GetKeyboardModifiers() types.KeyboardM...
method GetCursorImage (line 196) | func (manager *DesktopManagerCtx) GetCursorImage() *types.CursorImage {
method GetScreenshotImage (line 200) | func (manager *DesktopManagerCtx) GetScreenshotImage() *image.RGBA {
FILE: server/internal/http/batch.go
type BatchRequest (line 14) | type BatchRequest struct
type BatchResponse (line 20) | type BatchResponse struct
method Error (line 27) | func (b *BatchResponse) Error(httpErr *utils.HTTPError) (err error) {
type batchHandler (line 33) | type batchHandler struct
method Handle (line 39) | func (b *batchHandler) Handle(w http.ResponseWriter, r *http.Request) ...
type responseRecorder (line 99) | type responseRecorder struct
method Header (line 113) | func (w *responseRecorder) Header() http.Header {
method Write (line 117) | func (w *responseRecorder) Write(b []byte) (int, error) {
method WriteHeader (line 121) | func (w *responseRecorder) WriteHeader(code int) {
function newResponseRecorder (line 105) | func newResponseRecorder() *responseRecorder {
FILE: server/internal/http/debug.go
function pprofHandler (line 12) | func pprofHandler(r types.Router) {
FILE: server/internal/http/legacy/event/events.go
constant SYSTEM_INIT (line 4) | SYSTEM_INIT = "system/init"
constant SYSTEM_DISCONNECT (line 5) | SYSTEM_DISCONNECT = "system/disconnect"
constant SYSTEM_ERROR (line 6) | SYSTEM_ERROR = "system/error"
constant CLIENT_HEARTBEAT (line 10) | CLIENT_HEARTBEAT = "client/heartbeat"
constant SIGNAL_OFFER (line 14) | SIGNAL_OFFER = "signal/offer"
constant SIGNAL_ANSWER (line 15) | SIGNAL_ANSWER = "signal/answer"
constant SIGNAL_PROVIDE (line 16) | SIGNAL_PROVIDE = "signal/provide"
constant SIGNAL_CANDIDATE (line 17) | SIGNAL_CANDIDATE = "signal/candidate"
constant MEMBER_LIST (line 21) | MEMBER_LIST = "member/list"
constant MEMBER_CONNECTED (line 22) | MEMBER_CONNECTED = "member/connected"
constant MEMBER_DISCONNECTED (line 23) | MEMBER_DISCONNECTED = "member/disconnected"
constant CONTROL_LOCKED (line 27) | CONTROL_LOCKED = "control/locked"
constant CONTROL_RELEASE (line 28) | CONTROL_RELEASE = "control/release"
constant CONTROL_REQUEST (line 29) | CONTROL_REQUEST = "control/request"
constant CONTROL_REQUESTING (line 30) | CONTROL_REQUESTING = "control/requesting"
constant CONTROL_GIVE (line 31) | CONTROL_GIVE = "control/give"
constant CONTROL_CLIPBOARD (line 32) | CONTROL_CLIPBOARD = "control/clipboard"
constant CONTROL_KEYBOARD (line 33) | CONTROL_KEYBOARD = "control/keyboard"
constant CHAT_MESSAGE (line 37) | CHAT_MESSAGE = "chat/message"
constant CHAT_EMOTE (line 38) | CHAT_EMOTE = "chat/emote"
constant FILETRANSFER_LIST (line 42) | FILETRANSFER_LIST = "filetransfer/list"
constant FILETRANSFER_REFRESH (line 43) | FILETRANSFER_REFRESH = "filetransfer/refresh"
constant SCREEN_CONFIGURATIONS (line 47) | SCREEN_CONFIGURATIONS = "screen/configurations"
constant SCREEN_RESOLUTION (line 48) | SCREEN_RESOLUTION = "screen/resolution"
constant SCREEN_SET (line 49) | SCREEN_SET = "screen/set"
constant BROADCAST_STATUS (line 53) | BROADCAST_STATUS = "broadcast/status"
constant BROADCAST_CREATE (line 54) | BROADCAST_CREATE = "broadcast/create"
constant BROADCAST_DESTROY (line 55) | BROADCAST_DESTROY = "broadcast/destroy"
constant ADMIN_BAN (line 59) | ADMIN_BAN = "admin/ban"
constant ADMIN_KICK (line 60) | ADMIN_KICK = "admin/kick"
constant ADMIN_LOCK (line 61) | ADMIN_LOCK = "admin/lock"
constant ADMIN_MUTE (line 62) | ADMIN_MUTE = "admin/mute"
constant ADMIN_UNLOCK (line 63) | ADMIN_UNLOCK = "admin/unlock"
constant ADMIN_UNMUTE (line 64) | ADMIN_UNMUTE = "admin/unmute"
constant ADMIN_CONTROL (line 65) | ADMIN_CONTROL = "admin/control"
constant ADMIN_RELEASE (line 66) | ADMIN_RELEASE = "admin/release"
constant ADMIN_GIVE (line 67) | ADMIN_GIVE = "admin/give"
FILE: server/internal/http/legacy/handler.go
type LegacyHandler (line 42) | type LegacyHandler struct
method Route (line 67) | func (h *LegacyHandler) Route(r types.Router) {
method ban (line 397) | func (h *LegacyHandler) ban(sessionId string) error {
method isBanned (line 408) | func (h *LegacyHandler) isBanned(r *http.Request) bool {
function New (line 51) | func New(serverAddr, pathPrefix string) *LegacyHandler {
function getIp (line 414) | func getIp(r *http.Request) string {
FILE: server/internal/http/legacy/message/messages.go
type Message (line 9) | type Message struct
type SystemInit (line 13) | type SystemInit struct
type SystemMessage (line 21) | type SystemMessage struct
type SignalProvide (line 27) | type SignalProvide struct
type SignalOffer (line 35) | type SignalOffer struct
type SignalAnswer (line 40) | type SignalAnswer struct
type SignalCandidate (line 46) | type SignalCandidate struct
type MembersList (line 51) | type MembersList struct
type Member (line 56) | type Member struct
type MemberDisconnected (line 60) | type MemberDisconnected struct
type Clipboard (line 65) | type Clipboard struct
type Keyboard (line 70) | type Keyboard struct
type Control (line 78) | type Control struct
type ControlTarget (line 83) | type ControlTarget struct
type ChatReceive (line 89) | type ChatReceive struct
type ChatSend (line 94) | type ChatSend struct
type EmoteReceive (line 100) | type EmoteReceive struct
type EmoteSend (line 105) | type EmoteSend struct
type FileTransferList (line 111) | type FileTransferList struct
type Admin (line 117) | type Admin struct
type AdminTarget (line 122) | type AdminTarget struct
type AdminLock (line 128) | type AdminLock struct
type ScreenResolution (line 134) | type ScreenResolution struct
type ScreenConfigurations (line 142) | type ScreenConfigurations struct
type BroadcastStatus (line 147) | type BroadcastStatus struct
type BroadcastCreate (line 153) | type BroadcastCreate struct
FILE: server/internal/http/legacy/session.go
type memberStruct (line 27) | type memberStruct struct
type session (line 33) | type session struct
method req (line 76) | func (s *session) req(method, reqPath string, headers http.Header, req...
method apiReq (line 113) | func (s *session) apiReq(method, path string, request, response any) e...
method toClient (line 142) | func (s *session) toClient(payload any) error {
method toBackend (line 155) | func (s *session) toBackend(event string, payload any) error {
method create (line 175) | func (s *session) create(username, password string) error {
method destroy (line 200) | func (s *session) destroy() {
method newSession (line 59) | func (h *LegacyHandler) newSession(r *http.Request) *session {
FILE: server/internal/http/legacy/types/types.go
type Stats (line 5) | type Stats struct
type Member (line 21) | type Member struct
type FileListItem (line 28) | type FileListItem struct
type ScreenConfiguration (line 34) | type ScreenConfiguration struct
FILE: server/internal/http/legacy/wstobackend.go
method wsToBackend (line 21) | func (s *session) wsToBackend(msg []byte) error {
FILE: server/internal/http/legacy/wstoclient.go
function profileToMember (line 22) | func profileToMember(id string, profile types.MemberProfile) (*oldTypes....
function screenConfigurations (line 41) | func screenConfigurations(screenSizes []types.ScreenSize) map[int]oldTyp...
method settingsToLocks (line 76) | func (s *session) settingsToLocks(settings types.Settings) (map[string]s...
method sendControlHost (line 111) | func (s *session) sendControlHost(request message.ControlHost) error {
method wsToClient (line 163) | func (s *session) wsToClient(msg []byte) error {
FILE: server/internal/http/logger.go
type logFormatter (line 15) | type logFormatter struct
method NewLogEntry (line 19) | func (l *logFormatter) NewLogEntry(r *http.Request) middleware.LogEntry {
type logEntry (line 48) | type logEntry struct
method Panic (line 60) | func (e *logEntry) Panic(v any, stack []byte) {
method Error (line 67) | func (e *logEntry) Error(err error) {
method SetSession (line 71) | func (e *logEntry) SetSession(session types.Session) {
method Write (line 75) | func (e *logEntry) Write(status, bytes int, header http.Header, elapse...
type logPanic (line 55) | type logPanic struct
type nulllog (line 129) | type nulllog struct
method Panic (line 131) | func (e *nulllog) Panic(v any, stack []byte) {}
method Error (line 132) | func (e *nulllog) Error(err error) {}
method SetSession (line 133) | func (e *nulllog) SetSession(session types.Session) {}
method Write (line 134) | func (e *nulllog) Write(status, bytes int, header http.Header, elapsed...
FILE: server/internal/http/manager.go
type HttpManagerCtx (line 19) | type HttpManagerCtx struct
method Start (line 113) | func (manager *HttpManagerCtx) Start() {
method Shutdown (line 154) | func (manager *HttpManagerCtx) Shutdown() error {
function New (line 26) | func New(WebSocketManager types.WebSocketManager, ApiManager types.ApiMa...
FILE: server/internal/http/router.go
type RouterOption (line 16) | type RouterOption
function WithRequestID (line 18) | func WithRequestID() RouterOption {
function WithLogger (line 24) | func WithLogger(logger zerolog.Logger) RouterOption {
function WithRecoverer (line 30) | func WithRecoverer() RouterOption {
function WithCORS (line 36) | func WithCORS(allowOrigin func(origin string) bool) RouterOption {
function WithPathPrefix (line 51) | func WithPathPrefix(prefix string) RouterOption {
function WithRealIP (line 59) | func WithRealIP() RouterOption {
type router (line 65) | type router struct
method Group (line 77) | func (r *router) Group(fn func(types.Router)) {
method Route (line 83) | func (r *router) Route(pattern string, fn func(types.Router)) {
method Get (line 89) | func (r *router) Get(pattern string, fn types.RouterHandler) {
method Post (line 93) | func (r *router) Post(pattern string, fn types.RouterHandler) {
method Put (line 97) | func (r *router) Put(pattern string, fn types.RouterHandler) {
method Patch (line 101) | func (r *router) Patch(pattern string, fn types.RouterHandler) {
method Delete (line 105) | func (r *router) Delete(pattern string, fn types.RouterHandler) {
method With (line 109) | func (r *router) With(fn types.MiddlewareHandler) types.Router {
method Use (line 114) | func (r *router) Use(fn types.MiddlewareHandler) {
method ServeHTTP (line 118) | func (r *router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
function newRouter (line 69) | func newRouter(opts ...RouterOption) types.Router {
function errorHandler (line 122) | func errorHandler(err error, w http.ResponseWriter, r *http.Request) {
function routeHandler (line 131) | func routeHandler(fn types.RouterHandler) http.HandlerFunc {
function middlewareHandler (line 148) | func middlewareHandler(fn types.MiddlewareHandler) func(http.Handler) ht...
FILE: server/internal/member/file/provider.go
function New (line 13) | func New(config Config) types.MemberProvider {
type MemberProviderCtx (line 19) | type MemberProviderCtx struct
method hash (line 23) | func (provider *MemberProviderCtx) hash(password string) string {
method Connect (line 35) | func (provider *MemberProviderCtx) Connect() error {
method Disconnect (line 39) | func (provider *MemberProviderCtx) Disconnect() error {
method Authenticate (line 43) | func (provider *MemberProviderCtx) Authenticate(username string, passw...
method Insert (line 59) | func (provider *MemberProviderCtx) Insert(username string, password st...
method UpdateProfile (line 81) | func (provider *MemberProviderCtx) UpdateProfile(id string, profile ty...
method UpdatePassword (line 98) | func (provider *MemberProviderCtx) UpdatePassword(id string, password ...
method Select (line 115) | func (provider *MemberProviderCtx) Select(id string) (types.MemberProf...
method SelectAll (line 124) | func (provider *MemberProviderCtx) SelectAll(limit int, offset int) (m...
method Delete (line 144) | func (provider *MemberProviderCtx) Delete(id string) error {
method deserialize (line 160) | func (provider *MemberProviderCtx) deserialize() (map[string]MemberEnt...
method getEntry (line 183) | func (provider *MemberProviderCtx) getEntry(id string) (MemberEntry, e...
method serialize (line 197) | func (provider *MemberProviderCtx) serialize(data map[string]MemberEnt...
FILE: server/internal/member/file/provider_test.go
function TestMemberProviderCtx_hash (line 11) | func TestMemberProviderCtx_hash(t *testing.T) {
FILE: server/internal/member/file/types.go
type MemberEntry (line 7) | type MemberEntry struct
type Config (line 12) | type Config struct
FILE: server/internal/member/manager.go
function New (line 18) | func New(sessions types.SessionManager, config *config.Member) *MemberMa...
type MemberManagerCtx (line 41) | type MemberManagerCtx struct
method Connect (line 50) | func (manager *MemberManagerCtx) Connect() error {
method Disconnect (line 57) | func (manager *MemberManagerCtx) Disconnect() error {
method Authenticate (line 64) | func (manager *MemberManagerCtx) Authenticate(username string, passwor...
method Insert (line 71) | func (manager *MemberManagerCtx) Insert(username string, password stri...
method Select (line 78) | func (manager *MemberManagerCtx) Select(id string) (types.MemberProfil...
method SelectAll (line 91) | func (manager *MemberManagerCtx) SelectAll(limit int, offset int) (map...
method UpdateProfile (line 98) | func (manager *MemberManagerCtx) UpdateProfile(id string, profile type...
method UpdatePassword (line 111) | func (manager *MemberManagerCtx) UpdatePassword(id string, password st...
method Delete (line 118) | func (manager *MemberManagerCtx) Delete(id string) error {
method Login (line 135) | func (manager *MemberManagerCtx) Login(username string, password strin...
method Logout (line 163) | func (manager *MemberManagerCtx) Logout(id string) error {
FILE: server/internal/member/multiuser/provider.go
function New (line 11) | func New(config Config) types.MemberProvider {
type MemberProviderCtx (line 17) | type MemberProviderCtx struct
method Connect (line 21) | func (provider *MemberProviderCtx) Connect() error {
method Disconnect (line 25) | func (provider *MemberProviderCtx) Disconnect() error {
method Authenticate (line 29) | func (provider *MemberProviderCtx) Authenticate(username string, passw...
method Insert (line 60) | func (provider *MemberProviderCtx) Insert(username string, password st...
method UpdateProfile (line 64) | func (provider *MemberProviderCtx) UpdateProfile(id string, profile ty...
method UpdatePassword (line 68) | func (provider *MemberProviderCtx) UpdatePassword(id string, password ...
method Select (line 72) | func (provider *MemberProviderCtx) Select(id string) (types.MemberProf...
method SelectAll (line 76) | func (provider *MemberProviderCtx) SelectAll(limit int, offset int) (m...
method Delete (line 80) | func (provider *MemberProviderCtx) Delete(id string) error {
FILE: server/internal/member/multiuser/types.go
type Config (line 5) | type Config struct
FILE: server/internal/member/noauth/provider.go
function New (line 11) | func New() types.MemberProvider {
type MemberProviderCtx (line 27) | type MemberProviderCtx struct
method Connect (line 31) | func (provider *MemberProviderCtx) Connect() error {
method Disconnect (line 35) | func (provider *MemberProviderCtx) Disconnect() error {
method Authenticate (line 39) | func (provider *MemberProviderCtx) Authenticate(username string, passw...
method Insert (line 53) | func (provider *MemberProviderCtx) Insert(username string, password st...
method UpdateProfile (line 57) | func (provider *MemberProviderCtx) UpdateProfile(id string, profile ty...
method UpdatePassword (line 61) | func (provider *MemberProviderCtx) UpdatePassword(id string, password ...
method Select (line 65) | func (provider *MemberProviderCtx) Select(id string) (types.MemberProf...
method SelectAll (line 69) | func (provider *MemberProviderCtx) SelectAll(limit int, offset int) (m...
method Delete (line 73) | func (provider *MemberProviderCtx) Delete(id string) error {
FILE: server/internal/member/object/provider.go
function New (line 7) | func New(config Config) types.MemberProvider {
type MemberProviderCtx (line 14) | type MemberProviderCtx struct
method Connect (line 19) | func (provider *MemberProviderCtx) Connect() error {
method Disconnect (line 29) | func (provider *MemberProviderCtx) Disconnect() error {
method Authenticate (line 33) | func (provider *MemberProviderCtx) Authenticate(username string, passw...
method Insert (line 50) | func (provider *MemberProviderCtx) Insert(username string, password st...
method UpdateProfile (line 68) | func (provider *MemberProviderCtx) UpdateProfile(id string, profile ty...
method UpdatePassword (line 79) | func (provider *MemberProviderCtx) UpdatePassword(id string, password ...
method Select (line 91) | func (provider *MemberProviderCtx) Select(id string) (types.MemberProf...
method SelectAll (line 100) | func (provider *MemberProviderCtx) SelectAll(limit int, offset int) (m...
method Delete (line 115) | func (provider *MemberProviderCtx) Delete(id string) error {
FILE: server/internal/member/object/types.go
type memberEntry (line 7) | type memberEntry struct
method CheckPassword (line 12) | func (m *memberEntry) CheckPassword(password string) bool {
type User (line 16) | type User struct
type Config (line 22) | type Config struct
FILE: server/internal/plugins/chat/config.go
type Config (line 8) | type Config struct
method Init (line 12) | func (Config) Init(cmd *cobra.Command) error {
method Set (line 21) | func (s *Config) Set() {
FILE: server/internal/plugins/chat/manager.go
function NewManager (line 18) | func NewManager(
type Manager (line 31) | type Manager struct
method settingsForSession (line 42) | func (m *Manager) settingsForSession(session types.Session) (Settings,...
method sendMessage (line 68) | func (m *Manager) sendMessage(session types.Session, content Content) {
method Start (line 91) | func (m *Manager) Start() error {
method Shutdown (line 102) | func (m *Manager) Shutdown() error {
method Route (line 106) | func (m *Manager) Route(r types.Router) {
method WebSocketHandler (line 110) | func (m *Manager) WebSocketHandler(session types.Session, msg types.We...
method sendMessageHandler (line 138) | func (m *Manager) sendMessageHandler(w http.ResponseWriter, r *http.Re...
type Settings (line 37) | type Settings struct
FILE: server/internal/plugins/chat/plugin.go
type Plugin (line 7) | type Plugin struct
method Name (line 18) | func (p *Plugin) Name() string {
method Config (line 22) | func (p *Plugin) Config() types.PluginConfig {
method Start (line 26) | func (p *Plugin) Start(m types.PluginManagers) error {
method Shutdown (line 33) | func (p *Plugin) Shutdown() error {
function NewPlugin (line 12) | func NewPlugin() *Plugin {
FILE: server/internal/plugins/chat/types.go
constant PluginName (line 5) | PluginName = "chat"
constant CHAT_INIT (line 8) | CHAT_INIT = "chat/init"
constant CHAT_MESSAGE (line 9) | CHAT_MESSAGE = "chat/message"
type Init (line 12) | type Init struct
type Content (line 16) | type Content struct
type Message (line 20) | type Message struct
FILE: server/internal/plugins/dependency.go
type dependency (line 11) | type dependency struct
method findPlugin (line 18) | func (a *dependency) findPlugin(name string) (*dependency, bool) {
method startPlugin (line 37) | func (a *dependency) startPlugin(pm types.PluginManagers) error {
type dependiencies (line 59) | type dependiencies struct
method addPlugin (line 64) | func (d *dependiencies) addPlugin(plugin types.Plugin) error {
method findPlugin (line 103) | func (d *dependiencies) findPlugin(name string) (*dependency, bool) {
method start (line 113) | func (d *dependiencies) start(pm types.PluginManagers) error {
method forEach (line 122) | func (d *dependiencies) forEach(f func(*dependency) error) error {
method len (line 131) | func (d *dependiencies) len() int {
FILE: server/internal/plugins/dependency_test.go
function Test_deps_addPlugin (line 10) | func Test_deps_addPlugin(t *testing.T) {
type dummyPlugin (line 600) | type dummyPlugin struct
method Name (line 607) | func (d dummyPlugin) Name() string {
method DependsOn (line 611) | func (d dummyPlugin) DependsOn() []string {
method Config (line 615) | func (d dummyPlugin) Config() types.PluginConfig {
method Start (line 619) | func (d *dummyPlugin) Start(types.PluginManagers) error {
method Shutdown (line 628) | func (d dummyPlugin) Shutdown() error {
FILE: server/internal/plugins/filetransfer/config.go
type Config (line 11) | type Config struct
method Init (line 17) | func (Config) Init(cmd *cobra.Command) error {
method Set (line 48) | func (s *Config) Set() {
FILE: server/internal/plugins/filetransfer/manager.go
constant MULTIPART_FORM_MAX_MEMORY (line 23) | MULTIPART_FORM_MAX_MEMORY = 32 << 20
function NewManager (line 25) | func NewManager(
type Manager (line 39) | type Manager struct
method isEnabledForSession (line 48) | func (m *Manager) isEnabledForSession(session types.Session) (bool, er...
method refresh (line 69) | func (m *Manager) refresh() (error, bool) {
method broadcastUpdate (line 100) | func (m *Manager) broadcastUpdate() {
method sendUpdate (line 112) | func (m *Manager) sendUpdate(session types.Session) {
method Start (line 124) | func (m *Manager) Start() error {
method Shutdown (line 205) | func (m *Manager) Shutdown() error {
method Route (line 210) | func (m *Manager) Route(r types.Router) {
method WebSocketHandler (line 215) | func (m *Manager) WebSocketHandler(session types.Session, msg types.We...
method downloadFileHandler (line 237) | func (m *Manager) downloadFileHandler(w http.ResponseWriter, r *http.R...
method uploadFileHandler (line 271) | func (m *Manager) uploadFileHandler(w http.ResponseWriter, r *http.Req...
FILE: server/internal/plugins/filetransfer/plugin.go
type Plugin (line 7) | type Plugin struct
method Name (line 18) | func (p *Plugin) Name() string {
method Config (line 22) | func (p *Plugin) Config() types.PluginConfig {
method Start (line 26) | func (p *Plugin) Start(m types.PluginManagers) error {
method Shutdown (line 33) | func (p *Plugin) Shutdown() error {
function NewPlugin (line 12) | func NewPlugin() *Plugin {
FILE: server/internal/plugins/filetransfer/types.go
constant PluginName (line 3) | PluginName = "filetransfer"
type Settings (line 5) | type Settings struct
constant FILETRANSFER_UPDATE (line 10) | FILETRANSFER_UPDATE = "filetransfer/update"
type Message (line 13) | type Message struct
type ItemType (line 19) | type ItemType
constant ItemTypeFile (line 22) | ItemTypeFile ItemType = "file"
constant ItemTypeDir (line 23) | ItemTypeDir ItemType = "dir"
type Item (line 26) | type Item struct
FILE: server/internal/plugins/filetransfer/utils.go
function ListFiles (line 5) | func ListFiles(path string) ([]Item, error) {
FILE: server/internal/plugins/manager.go
type ManagerCtx (line 19) | type ManagerCtx struct
method loadDir (line 54) | func (manager *ManagerCtx) loadDir(dir string) error {
method load (line 77) | func (manager *ManagerCtx) load(path string) error {
method InitConfigs (line 100) | func (manager *ManagerCtx) InitConfigs(cmd *cobra.Command) {
method SetConfigs (line 109) | func (manager *ManagerCtx) SetConfigs() {
method Start (line 116) | func (manager *ManagerCtx) Start(
method Shutdown (line 137) | func (manager *ManagerCtx) Shutdown() error {
method LookupService (line 146) | func (manager *ManagerCtx) LookupService(pluginName string) (any, erro...
method Metadata (line 160) | func (manager *ManagerCtx) Metadata() []types.PluginMetadata {
function New (line 25) | func New(config *config.Plugins) *ManagerCtx {
FILE: server/internal/session/auth.go
method CookieSetToken (line 12) | func (manager *SessionManagerCtx) CookieSetToken(w http.ResponseWriter, ...
method CookieClearToken (line 30) | func (manager *SessionManagerCtx) CookieClearToken(w http.ResponseWriter...
method Authenticate (line 41) | func (manager *SessionManagerCtx) Authenticate(r *http.Request) (types.S...
method getToken (line 59) | func (manager *SessionManagerCtx) getToken(r *http.Request) (string, boo...
FILE: server/internal/session/manager.go
function New (line 18) | func New(config *config.Session) *SessionManagerCtx {
type SessionManagerCtx (line 65) | type SessionManagerCtx struct
method Create (line 91) | func (manager *SessionManagerCtx) Create(id string, profile types.Memb...
method Update (line 126) | func (manager *SessionManagerCtx) Update(id string, profile types.Memb...
method Delete (line 146) | func (manager *SessionManagerCtx) Delete(id string) error {
method Disconnect (line 172) | func (manager *SessionManagerCtx) Disconnect(id string) error {
method Get (line 192) | func (manager *SessionManagerCtx) Get(id string) (types.Session, bool) {
method GetByToken (line 200) | func (manager *SessionManagerCtx) GetByToken(token string) (types.Sess...
method List (line 217) | func (manager *SessionManagerCtx) List() []types.Session {
method Range (line 229) | func (manager *SessionManagerCtx) Range(f func(session types.Session) ...
method setHost (line 244) | func (manager *SessionManagerCtx) setHost(session, host types.Session) {
method GetHost (line 254) | func (manager *SessionManagerCtx) GetHost() (types.Session, bool) {
method isHost (line 263) | func (manager *SessionManagerCtx) isHost(host types.Session) bool {
method SetCursor (line 272) | func (manager *SessionManagerCtx) SetCursor(cursor types.Cursor, sessi...
method PopCursors (line 285) | func (manager *SessionManagerCtx) PopCursors() map[types.Session][]typ...
method Broadcast (line 299) | func (manager *SessionManagerCtx) Broadcast(event string, payload any,...
method AdminBroadcast (line 315) | func (manager *SessionManagerCtx) AdminBroadcast(event string, payload...
method InactiveCursorsBroadcast (line 331) | func (manager *SessionManagerCtx) InactiveCursorsBroadcast(event strin...
method OnCreated (line 351) | func (manager *SessionManagerCtx) OnCreated(listener func(session type...
method OnDeleted (line 357) | func (manager *SessionManagerCtx) OnDeleted(listener func(session type...
method OnConnected (line 363) | func (manager *SessionManagerCtx) OnConnected(listener func(session ty...
method OnDisconnected (line 369) | func (manager *SessionManagerCtx) OnDisconnected(listener func(session...
method OnProfileChanged (line 375) | func (manager *SessionManagerCtx) OnProfileChanged(listener func(sessi...
method OnStateChanged (line 381) | func (manager *SessionManagerCtx) OnStateChanged(listener func(session...
method OnHostChanged (line 387) | func (manager *SessionManagerCtx) OnHostChanged(listener func(session,...
method OnSettingsChanged (line 397) | func (manager *SessionManagerCtx) OnSettingsChanged(listener func(sess...
method UpdateSettingsFunc (line 407) | func (manager *SessionManagerCtx) UpdateSettingsFunc(session types.Ses...
method updateSettings (line 420) | func (manager *SessionManagerCtx) updateSettings(session types.Session...
method Settings (line 471) | func (manager *SessionManagerCtx) Settings() types.Settings {
method CookieEnabled (line 478) | func (manager *SessionManagerCtx) CookieEnabled() bool {
method Stats (line 486) | func (manager *SessionManagerCtx) Stats() types.Stats {
FILE: server/internal/session/serialize.go
method save (line 11) | func (manager *SessionManagerCtx) save() {
method load (line 42) | func (manager *SessionManagerCtx) load() {
FILE: server/internal/session/session.go
constant WS_DELAYED_DURATION (line 15) | WS_DELAYED_DURATION = 5 * time.Second
type SessionCtx (line 17) | type SessionCtx struct
method ID (line 36) | func (session *SessionCtx) ID() string {
method Profile (line 40) | func (session *SessionCtx) Profile() types.MemberProfile {
method profileChanged (line 44) | func (session *SessionCtx) profileChanged() {
method State (line 68) | func (session *SessionCtx) State() types.SessionState {
method IsHost (line 72) | func (session *SessionCtx) IsHost() bool {
method LegacyIsHost (line 77) | func (session *SessionCtx) LegacyIsHost() bool {
method SetAsHost (line 82) | func (session *SessionCtx) SetAsHost() {
method SetAsHostBy (line 86) | func (session *SessionCtx) SetAsHostBy(bySession types.Session) {
method ClearHost (line 90) | func (session *SessionCtx) ClearHost() {
method PrivateModeEnabled (line 94) | func (session *SessionCtx) PrivateModeEnabled() bool {
method SetCursor (line 98) | func (session *SessionCtx) SetCursor(cursor types.Cursor) {
method ConnectWebSocketPeer (line 110) | func (session *SessionCtx) ConnectWebSocketPeer(websocketPeer types.We...
method DisconnectWebSocketPeer (line 151) | func (session *SessionCtx) DisconnectWebSocketPeer(websocketPeer types...
method DestroyWebSocketPeer (line 217) | func (session *SessionCtx) DestroyWebSocketPeer(reason string) {
method Send (line 234) | func (session *SessionCtx) Send(event string, payload any) {
method SetWebRTCPeer (line 249) | func (session *SessionCtx) SetWebRTCPeer(webrtcPeer types.WebRTCPeer) {
method SetWebRTCConnected (line 265) | func (session *SessionCtx) SetWebRTCConnected(webrtcPeer types.WebRTCP...
method GetWebRTCPeer (line 307) | func (session *SessionCtx) GetWebRTCPeer() types.WebRTCPeer {
FILE: server/internal/webrtc/cursor/image.go
type ImageListener (line 13) | type ImageListener interface
type Image (line 17) | type Image interface
type imageEntry (line 25) | type imageEntry struct
type image (line 30) | type image struct
method Start (line 53) | func (manager *image) Start() {
method Shutdown (line 75) | func (manager *image) Shutdown() {
method getCached (line 85) | func (manager *image) getCached(serial uint64) (*imageEntry, error) {
method GetCurrent (line 121) | func (manager *image) GetCurrent() (cur *types.CursorImage, img []byte...
method AddListener (line 135) | func (manager *image) AddListener(listener ImageListener) {
method RemoveListener (line 145) | func (manager *image) RemoveListener(listener ImageListener) {
method fetchEntry (line 155) | func (manager *image) fetchEntry() (*imageEntry, error) {
function NewImage (line 43) | func NewImage(logger zerolog.Logger, desktop types.DesktopManager) *image {
FILE: server/internal/webrtc/cursor/position.go
type PositionListener (line 10) | type PositionListener interface
type Position (line 14) | type Position interface
type position (line 21) | type position struct
method Shutdown (line 35) | func (manager *position) Shutdown() {
method Set (line 45) | func (manager *position) Set(x, y int) {
method AddListener (line 56) | func (manager *position) AddListener(listener PositionListener) {
method RemoveListener (line 66) | func (manager *position) RemoveListener(listener PositionListener) {
function NewPosition (line 28) | func NewPosition(logger zerolog.Logger) *position {
FILE: server/internal/webrtc/handler.go
method handle (line 16) | func (manager *WebRTCManagerCtx) handle(
FILE: server/internal/webrtc/legacyhandler.go
constant OP_MOVE (line 14) | OP_MOVE = 0x01
constant OP_SCROLL (line 15) | OP_SCROLL = 0x02
constant OP_KEY_DOWN (line 16) | OP_KEY_DOWN = 0x03
constant OP_KEY_UP (line 17) | OP_KEY_UP = 0x04
constant OP_KEY_CLK (line 18) | OP_KEY_CLK = 0x05
type PayloadHeader (line 21) | type PayloadHeader struct
type PayloadMove (line 26) | type PayloadMove struct
type PayloadScroll (line 32) | type PayloadScroll struct
type PayloadKey (line 38) | type PayloadKey struct
method handleLegacy (line 43) | func (manager *WebRTCManagerCtx) handleLegacy(
FILE: server/internal/webrtc/manager.go
constant tcpReadChanBufferSize (line 35) | tcpReadChanBufferSize = 50
constant tcpWriteBufferSizeInBytes (line 38) | tcpWriteBufferSizeInBytes = 4 * 1024 * 1024
constant disconnectedTimeout (line 41) | disconnectedTimeout = 4 * time.Second
constant failedTimeout (line 44) | failedTimeout = 6 * time.Second
constant keepAliveInterval (line 47) | keepAliveInterval = 2 * time.Second
constant rtcpPLIInterval (line 50) | rtcpPLIInterval = 3 * time.Second
function New (line 53) | func New(desktop types.DesktopManager, capture types.CaptureManager, con...
type WebRTCManagerCtx (line 94) | type WebRTCManagerCtx struct
method Start (line 113) | func (manager *WebRTCManagerCtx) Start() {
method Shutdown (line 161) | func (manager *WebRTCManagerCtx) Shutdown() error {
method ICEServers (line 170) | func (manager *WebRTCManagerCtx) ICEServers() []types.ICEServer {
method newPeerConnection (line 174) | func (manager *WebRTCManagerCtx) newPeerConnection(logger zerolog.Logg...
method CreatePeer (line 271) | func (manager *WebRTCManagerCtx) CreatePeer(session types.Session) (*w...
method SetCursorPosition (line 597) | func (manager *WebRTCManagerCtx) SetCursorPosition(x, y int) {
FILE: server/internal/webrtc/metrics.go
constant connectionStatsInterval (line 17) | connectionStatsInterval = 5 * time.Second
type metricsManager (line 20) | type metricsManager struct
method getBySession (line 32) | func (m *metricsManager) getBySession(session types.Session) *metrics {
function newMetricsManager (line 26) | func newMetricsManager() *metricsManager {
type metrics (line 225) | type metrics struct
method reset (line 258) | func (met *metrics) reset() {
method NewConnection (line 274) | func (met *metrics) NewConnection() {
method NewICECandidate (line 278) | func (met *metrics) NewICECandidate(candidate webrtc.ICECandidateStats) {
method SetICECandidatesUsed (line 294) | func (met *metrics) SetICECandidatesUsed(candidates []webrtc.ICECandid...
method SetState (line 308) | func (met *metrics) SetState(state webrtc.PeerConnectionState) {
method SetVideoID (line 330) | func (met *metrics) SetVideoID(videoId string) {
method SetReceiverEstimatedMaximumBitrate (line 356) | func (met *metrics) SetReceiverEstimatedMaximumBitrate(bitrate float32) {
method SetReceiverEstimatedTargetBitrate (line 360) | func (met *metrics) SetReceiverEstimatedTargetBitrate(bitrate float64) {
method SetReceiverReport (line 364) | func (met *metrics) SetReceiverReport(report rtcp.ReceptionReport) {
method SetIceTransportStats (line 370) | func (met *metrics) SetIceTransportStats(data webrtc.TransportStats) {
method SetSctpTransportStats (line 375) | func (met *metrics) SetSctpTransportStats(data webrtc.TransportStats) {
method rtcpReceiver (line 384) | func (met *metrics) rtcpReceiver(rtcpCh chan []rtcp.Packet) {
method connectionStats (line 412) | func (met *metrics) connectionStats(connection *webrtc.PeerConnection) {
FILE: server/internal/webrtc/payload/receive.go
constant OP_MOVE (line 6) | OP_MOVE = 0x01
constant OP_SCROLL (line 7) | OP_SCROLL = 0x02
constant OP_KEY_DOWN (line 8) | OP_KEY_DOWN = 0x03
constant OP_KEY_UP (line 9) | OP_KEY_UP = 0x04
constant OP_BTN_DOWN (line 10) | OP_BTN_DOWN = 0x05
constant OP_BTN_UP (line 11) | OP_BTN_UP = 0x06
constant OP_PING (line 12) | OP_PING = 0x07
constant OP_TOUCH_BEGIN (line 14) | OP_TOUCH_BEGIN = 0x08
constant OP_TOUCH_UPDATE (line 15) | OP_TOUCH_UPDATE = 0x09
constant OP_TOUCH_END (line 16) | OP_TOUCH_END = 0x0a
type Move (line 19) | type Move struct
type Scroll_Old (line 25) | type Scroll_Old struct
type Scroll (line 30) | type Scroll struct
type Key (line 36) | type Key struct
type Ping (line 40) | type Ping struct
method ClientTs (line 46) | func (p Ping) ClientTs() uint64 {
type Touch (line 50) | type Touch struct
FILE: server/internal/webrtc/payload/send.go
constant OP_CURSOR_POSITION (line 6) | OP_CURSOR_POSITION = 0x01
constant OP_CURSOR_IMAGE (line 7) | OP_CURSOR_IMAGE = 0x02
constant OP_PONG (line 8) | OP_PONG = 0x03
type CursorPosition (line 11) | type CursorPosition struct
type CursorImage (line 16) | type CursorImage struct
type Pong (line 23) | type Pong struct
method ServerTs (line 31) | func (p Pong) ServerTs() uint64 {
FILE: server/internal/webrtc/payload/types.go
type Header (line 3) | type Header struct
FILE: server/internal/webrtc/peer.go
type WebRTCPeerCtx (line 21) | type WebRTCPeerCtx struct
method CreateOffer (line 51) | func (peer *WebRTCPeerCtx) CreateOffer(ICERestart bool) (*webrtc.Sessi...
method CreateAnswer (line 65) | func (peer *WebRTCPeerCtx) CreateAnswer() (*webrtc.SessionDescription,...
method setLocalDescription (line 77) | func (peer *WebRTCPeerCtx) setLocalDescription(description webrtc.Sess...
method SetRemoteDescription (line 96) | func (peer *WebRTCPeerCtx) SetRemoteDescription(desc webrtc.SessionDes...
method SetCandidate (line 103) | func (peer *WebRTCPeerCtx) SetCandidate(candidate webrtc.ICECandidateI...
method Destroy (line 111) | func (peer *WebRTCPeerCtx) Destroy() {
method estimatorReader (line 125) | func (peer *WebRTCPeerCtx) estimatorReader() {
method SetPaused (line 314) | func (peer *WebRTCPeerCtx) SetPaused(isPaused bool) error {
method Paused (line 327) | func (peer *WebRTCPeerCtx) Paused() bool {
method SetVideo (line 338) | func (peer *WebRTCPeerCtx) SetVideo(r types.PeerVideoRequest) error {
method Video (line 413) | func (peer *WebRTCPeerCtx) Video() types.PeerVideo {
method SetAudio (line 436) | func (peer *WebRTCPeerCtx) SetAudio(r types.PeerAudioRequest) error {
method Audio (line 467) | func (peer *WebRTCPeerCtx) Audio() types.PeerAudio {
method SendCursorPosition (line 480) | func (peer *WebRTCPeerCtx) SendCursorPosition(x, y int) error {
method SendCursorImage (line 512) | func (peer *WebRTCPeerCtx) SendCursorImage(cur *types.CursorImage, img...
FILE: server/internal/webrtc/pionlog/factory.go
function New (line 8) | func New(logger zerolog.Logger) Factory {
type Factory (line 14) | type Factory struct
method NewLogger (line 18) | func (l Factory) NewLogger(subsystem string) logging.LeveledLogger {
FILE: server/internal/webrtc/pionlog/logger.go
type logger (line 10) | type logger struct
method Trace (line 15) | func (l logger) Trace(msg string) {
method Tracef (line 19) | func (l logger) Tracef(format string, args ...any) {
method Debug (line 24) | func (l logger) Debug(msg string) {
method Debugf (line 28) | func (l logger) Debugf(format string, args ...any) {
method Info (line 33) | func (l logger) Info(msg string) {
method Infof (line 41) | func (l logger) Infof(format string, args ...any) {
method Warn (line 50) | func (l logger) Warn(msg string) {
method Warnf (line 54) | func (l logger) Warnf(format string, args ...any) {
method Error (line 59) | func (l logger) Error(msg string) {
method Errorf (line 63) | func (l logger) Errorf(format string, args ...any) {
FILE: server/internal/webrtc/pionlog/nullog.go
type nulllog (line 3) | type nulllog struct
method Trace (line 5) | func (l nulllog) Trace(msg string) {}
method Tracef (line 6) | func (l nulllog) Tracef(format string, args ...any) {}
method Debug (line 7) | func (l nulllog) Debug(msg string) {}
method Debugf (line 8) | func (l nulllog) Debugf(format string, args ...any) {}
method Info (line 9) | func (l nulllog) Info(msg string) {}
method Infof (line 10) | func (l nulllog) Infof(format string, args ...any) {}
method Warn (line 11) | func (l nulllog) Warn(msg string) {}
method Warnf (line 12) | func (l nulllog) Warnf(format string, args ...any) {}
method Error (line 13) | func (l nulllog) Error(msg string) {}
method Errorf (line 14) | func (l nulllog) Errorf(format string, args ...any) {}
FILE: server/internal/webrtc/track.go
type Track (line 17) | type Track struct
method Shutdown (line 66) | func (t *Track) Shutdown() {
method rtcpReader (line 71) | func (t *Track) rtcpReader(sender *webrtc.RTPSender) {
method sampleReader (line 92) | func (t *Track) sampleReader() {
method WriteSample (line 112) | func (t *Track) WriteSample(sample types.Sample) {
method SetStream (line 118) | func (t *Track) SetStream(stream types.StreamSinkManager) (bool, error) {
method RemoveStream (line 147) | func (t *Track) RemoveStream() {
method Stream (line 165) | func (t *Track) Stream() (types.StreamSinkManager, bool) {
method SetPaused (line 174) | func (t *Track) SetPaused(paused bool) {
method Paused (line 198) | func (t *Track) Paused() bool {
type trackOption (line 29) | type trackOption
function WithRtcpChan (line 31) | func WithRtcpChan(rtcp chan []rtcp.Packet) trackOption {
function NewTrack (line 37) | func NewTrack(logger zerolog.Logger, codec codec.RTPCodec, connection *w...
FILE: server/internal/websocket/filechooserdialog.go
method fileChooserDialogEvents (line 9) | func (manager *WebSocketManagerCtx) fileChooserDialogEvents() {
FILE: server/internal/websocket/handler/clipboard.go
method clipboardSet (line 10) | func (h *MessageHandlerCtx) clipboardSet(session types.Session, payload ...
FILE: server/internal/websocket/handler/control.go
method controlRelease (line 19) | func (h *MessageHandlerCtx) controlRelease(session types.Session) error {
method controlRequest (line 34) | func (h *MessageHandlerCtx) controlRequest(session types.Session) error {
method controlMove (line 72) | func (h *MessageHandlerCtx) controlMove(session types.Session, payload *...
method controlScroll (line 83) | func (h *MessageHandlerCtx) controlScroll(session types.Session, payload...
method controlButtonPress (line 98) | func (h *MessageHandlerCtx) controlButtonPress(session types.Session, pa...
method controlButtonDown (line 110) | func (h *MessageHandlerCtx) controlButtonDown(session types.Session, pay...
method controlButtonUp (line 122) | func (h *MessageHandlerCtx) controlButtonUp(session types.Session, paylo...
method controlKeyPress (line 134) | func (h *MessageHandlerCtx) controlKeyPress(session types.Session, paylo...
method controlKeyDown (line 146) | func (h *MessageHandlerCtx) controlKeyDown(session types.Session, payloa...
method controlKeyUp (line 158) | func (h *MessageHandlerCtx) controlKeyUp(session types.Session, payload ...
method controlTouchBegin (line 170) | func (h *MessageHandlerCtx) controlTouchBegin(session types.Session, pay...
method controlTouchUpdate (line 177) | func (h *MessageHandlerCtx) controlTouchUpdate(session types.Session, pa...
method controlTouchEnd (line 184) | func (h *MessageHandlerCtx) controlTouchEnd(session types.Session, paylo...
method controlCut (line 191) | func (h *MessageHandlerCtx) controlCut(session types.Session) error {
method controlCopy (line 199) | func (h *MessageHandlerCtx) controlCopy(session types.Session) error {
method controlPaste (line 207) | func (h *MessageHandlerCtx) controlPaste(session types.Session, payload ...
method controlSelectAll (line 222) | func (h *MessageHandlerCtx) controlSelectAll(session types.Session) error {
FILE: server/internal/websocket/handler/handler.go
function New (line 13) | func New(
type MessageHandlerCtx (line 28) | type MessageHandlerCtx struct
method Message (line 36) | func (h *MessageHandlerCtx) Message(session types.Session, data types....
FILE: server/internal/websocket/handler/keyboard.go
method keyboardMap (line 10) | func (h *MessageHandlerCtx) keyboardMap(session types.Session, payload *...
method keyboardModifiers (line 18) | func (h *MessageHandlerCtx) keyboardModifiers(session types.Session, pay...
FILE: server/internal/websocket/handler/screen.go
method screenSet (line 11) | func (h *MessageHandlerCtx) screenSet(session types.Session, payload *me...
FILE: server/internal/websocket/handler/send.go
method sendUnicast (line 11) | func (h *MessageHandlerCtx) sendUnicast(session types.Session, payload *...
method sendBroadcast (line 29) | func (h *MessageHandlerCtx) sendBroadcast(session types.Session, payload...
FILE: server/internal/websocket/handler/session.go
method SessionCreated (line 9) | func (h *MessageHandlerCtx) SessionCreated(session types.Session) error {
method SessionDeleted (line 21) | func (h *MessageHandlerCtx) SessionDeleted(session types.Session) error {
method SessionConnected (line 31) | func (h *MessageHandlerCtx) SessionConnected(session types.Session) error {
method SessionDisconnected (line 55) | func (h *MessageHandlerCtx) SessionDisconnected(session types.Session) e...
method SessionProfileChanged (line 86) | func (h *MessageHandlerCtx) SessionProfileChanged(session types.Session,...
method SessionStateChanged (line 97) | func (h *MessageHandlerCtx) SessionStateChanged(session types.Session) e...
FILE: server/internal/websocket/handler/signal.go
method signalRequest (line 13) | func (h *MessageHandlerCtx) signalRequest(session types.Session, payload...
method signalRestart (line 77) | func (h *MessageHandlerCtx) signalRestart(session types.Session) error {
method signalOffer (line 98) | func (h *MessageHandlerCtx) signalOffer(session types.Session, payload *...
method signalAnswer (line 126) | func (h *MessageHandlerCtx) signalAnswer(session types.Session, payload ...
method signalCandidate (line 138) | func (h *MessageHandlerCtx) signalCandidate(session types.Session, paylo...
method signalVideo (line 147) | func (h *MessageHandlerCtx) signalVideo(session types.Session, payload *...
method signalAudio (line 156) | func (h *MessageHandlerCtx) signalAudio(session types.Session, payload *...
FILE: server/internal/websocket/handler/system.go
method systemInit (line 12) | func (h *MessageHandlerCtx) systemInit(session types.Session) error {
method systemAdmin (line 53) | func (h *MessageHandlerCtx) systemAdmin(session types.Session) error {
method systemLogs (line 79) | func (h *MessageHandlerCtx) systemLogs(session types.Session, payload *m...
FILE: server/internal/websocket/manager.go
constant pingPeriod (line 22) | pingPeriod = 10 * time.Second
constant inactiveCursorsPeriod (line 25) | inactiveCursorsPeriod = 750 * time.Millisecond
constant maxPayloadLogLength (line 28) | maxPayloadLogLength = 10_000
function New (line 41) | func New(
type WebSocketManagerCtx (line 59) | type WebSocketManagerCtx struct
method Start (line 71) | func (manager *WebSocketManagerCtx) Start() {
method Shutdown (line 191) | func (manager *WebSocketManagerCtx) Shutdown() error {
method AddHandler (line 199) | func (manager *WebSocketManagerCtx) AddHandler(handler types.WebSocket...
method Upgrade (line 203) | func (manager *WebSocketManagerCtx) Upgrade(checkOrigin types.CheckOri...
method connect (line 222) | func (manager *WebSocketManagerCtx) connect(connection *websocket.Conn...
method handle (line 302) | func (manager *WebSocketManagerCtx) handle(connection *websocket.Conn,...
method startInactiveCursors (line 375) | func (manager *WebSocketManagerCtx) startInactiveCursors() {
method stopInactiveCursors (line 430) | func (manager *WebSocketManagerCtx) stopInactiveCursors() {
FILE: server/internal/websocket/peer.go
type WebSocketPeerCtx (line 17) | type WebSocketPeerCtx struct
method Send (line 30) | func (peer *WebSocketPeerCtx) Send(event string, payload any) {
method Ping (line 67) | func (peer *WebSocketPeerCtx) Ping() error {
method Destroy (line 81) | func (peer *WebSocketPeerCtx) Destroy(reason string) {
function newPeer (line 23) | func newPeer(logger zerolog.Logger, connection *websocket.Conn) *WebSock...
FILE: server/neko.go
constant Header (line 9) | Header = `&34
type version (line 39) | type version struct
method String (line 49) | func (i *version) String() string {
method Details (line 58) | func (i *version) Details() string {
FILE: server/pkg/auth/auth.go
type key (line 12) | type key
constant keySessionCtx (line 14) | keySessionCtx key = iota
function SetSession (line 16) | func SetSession(r *http.Request, session types.Session) context.Context {
function GetSession (line 20) | func GetSession(r *http.Request) (types.Session, bool) {
function AdminsOnly (line 25) | func AdminsOnly(w http.ResponseWriter, r *http.Request) (context.Context...
function HostsOnly (line 34) | func HostsOnly(w http.ResponseWriter, r *http.Request) (context.Context,...
function HostsOrAdminsOnly (line 43) | func HostsOrAdminsOnly(w http.ResponseWriter, r *http.Request) (context....
function CanWatchOnly (line 52) | func CanWatchOnly(w http.ResponseWriter, r *http.Request) (context.Conte...
function CanHostOnly (line 61) | func CanHostOnly(w http.ResponseWriter, r *http.Request) (context.Contex...
function CanAccessClipboardOnly (line 74) | func CanAccessClipboardOnly(w http.ResponseWriter, r *http.Request) (con...
function PluginsGenericOnly (line 83) | func PluginsGenericOnly[V comparable](key string, exp V) func(w http.Res...
FILE: server/pkg/auth/auth_test.go
function rWithSession (line 17) | func rWithSession(profile types.MemberProfile) (*http.Request, types.Ses...
function TestSessionCtx (line 26) | func TestSessionCtx(t *testing.T) {
function TestAdminsOnly (line 45) | func TestAdminsOnly(t *testing.T) {
function TestHostsOnly (line 86) | func TestHostsOnly(t *testing.T) {
function TestCanWatchOnly (line 141) | func TestCanWatchOnly(t *testing.T) {
function TestCanHostOnly (line 182) | func TestCanHostOnly(t *testing.T) {
function TestCanAccessClipboardOnly (line 242) | func TestCanAccessClipboardOnly(t *testing.T) {
function TestPluginsGenericOnly (line 283) | func TestPluginsGenericOnly(t *testing.T) {
FILE: server/pkg/drop/drop.c
function dragDataGet (line 5) | static void dragDataGet(
function dragEnd (line 26) | static void dragEnd(
function dragWindowOpen (line 37) | void dragWindowOpen(char **uris) {
function dragWindowClose (line 73) | void dragWindowClose() {
function dragUrisSetFile (line 82) | void dragUrisSetFile(char **uris, char *file, int n) {
function dragUrisFree (line 87) | void dragUrisFree(char **uris, int size) {
FILE: server/pkg/drop/drop.go
function init (line 19) | func init() {
function OpenWindow (line 23) | func OpenWindow(files []string) {
function CloseWindow (line 38) | func CloseWindow() {
function goDragCreate (line 43) | func goDragCreate(widget *C.GtkWidget, event *C.GdkEvent, user_data C.gp...
function goDragCursorEnter (line 48) | func goDragCursorEnter(widget *C.GtkWidget, event *C.GdkEvent, user_data...
function goDragButtonPress (line 53) | func goDragButtonPress(widget *C.GtkWidget, event *C.GdkEvent, user_data...
function goDragBegin (line 58) | func goDragBegin(widget *C.GtkWidget, context *C.GdkDragContext, user_da...
function goDragFinish (line 63) | func goDragFinish(succeeded C.gboolean) {
FILE: server/pkg/gst/gst.c
function gstreamer_pipeline_log (line 3) | static void gstreamer_pipeline_log(GstPipelineCtx *ctx, char* level, con...
function gboolean (line 12) | static gboolean gstreamer_bus_call(GstBus *bus, GstMessage *msg, gpointe...
function GstPipelineCtx (line 70) | GstPipelineCtx *gstreamer_pipeline_create(char *pipelineStr, int pipelin...
function GstFlowReturn (line 86) | static GstFlowReturn gstreamer_send_new_sample_handler(GstElement *objec...
function gstreamer_pipeline_attach_appsink (line 109) | void gstreamer_pipeline_attach_appsink(GstPipelineCtx *ctx, char *sinkNa...
function gstreamer_pipeline_attach_appsrc (line 115) | void gstreamer_pipeline_attach_appsrc(GstPipelineCtx *ctx, char *srcName) {
function gstreamer_pipeline_play (line 119) | void gstreamer_pipeline_play(GstPipelineCtx *ctx) {
function gstreamer_pipeline_pause (line 123) | void gstreamer_pipeline_pause(GstPipelineCtx *ctx) {
function gstreamer_pipeline_destory (line 127) | void gstreamer_pipeline_destory(GstPipelineCtx *ctx) {
function gstreamer_pipeline_push (line 152) | void gstreamer_pipeline_push(GstPipelineCtx *ctx, void *buffer, int buff...
function gboolean (line 160) | gboolean gstreamer_pipeline_set_prop_int(GstPipelineCtx *ctx, char *binN...
function gboolean (line 172) | gboolean gstreamer_pipeline_set_caps_framerate(GstPipelineCtx *ctx, cons...
function gboolean (line 189) | gboolean gstreamer_pipeline_set_caps_resolution(GstPipelineCtx *ctx, con...
function gboolean (line 207) | gboolean gstreamer_pipeline_emit_video_keyframe(GstPipelineCtx *ctx) {
FILE: server/pkg/gst/gst.go
function init (line 29) | func init() {
type Pipeline (line 34) | type Pipeline interface
type pipeline (line 53) | type pipeline struct
method Src (line 93) | func (p *pipeline) Src() string {
method Sample (line 97) | func (p *pipeline) Sample() chan types.Sample {
method AttachAppsink (line 101) | func (p *pipeline) AttachAppsink(sinkName string) {
method AttachAppsrc (line 108) | func (p *pipeline) AttachAppsrc(srcName string) {
method Play (line 115) | func (p *pipeline) Play() {
method Pause (line 119) | func (p *pipeline) Pause() {
method Destroy (line 123) | func (p *pipeline) Destroy() {
method Push (line 134) | func (p *pipeline) Push(buffer []byte) {
method SetPropInt (line 141) | func (p *pipeline) SetPropInt(binName string, prop string, value int) ...
method SetCapsFramerate (line 156) | func (p *pipeline) SetCapsFramerate(binName string, numerator, denomin...
method SetCapsResolution (line 169) | func (p *pipeline) SetCapsResolution(binName string, width, height int...
method EmitVideoKeyframe (line 182) | func (p *pipeline) EmitVideoKeyframe() bool {
function CreatePipeline (line 61) | func CreatePipeline(pipelineStr string) (Pipeline, error) {
function CheckPlugins (line 188) | func CheckPlugins(plugins []string) error {
function goHandlePipelineBuffer (line 203) | func goHandlePipelineBuffer(pipelineID C.int, buf C.gpointer, bufLen C.i...
function goPipelineLog (line 228) | func goPipelineLog(pipelineID C.int, levelUnsafe *C.char, msgUnsafe *C.c...
FILE: server/pkg/gst/gst.h
type GstPipelineCtx (line 19) | typedef struct GstPipelineCtx {
FILE: server/pkg/types/api.go
type ApiManager (line 3) | type ApiManager interface
FILE: server/pkg/types/capture.go
type Sample (line 20) | type Sample struct
type SampleListener (line 32) | type SampleListener interface
type BroadcastManager (line 36) | type BroadcastManager interface
type ScreencastManager (line 43) | type ScreencastManager interface
type StreamSelectorType (line 49) | type StreamSelectorType
method String (line 62) | func (s StreamSelectorType) String() string {
method UnmarshalText (line 77) | func (s *StreamSelectorType) UnmarshalText(text []byte) error {
method MarshalText (line 93) | func (s StreamSelectorType) MarshalText() ([]byte, error) {
constant StreamSelectorTypeExact (line 53) | StreamSelectorTypeExact StreamSelectorType = iota
constant StreamSelectorTypeNearest (line 55) | StreamSelectorTypeNearest
constant StreamSelectorTypeLower (line 57) | StreamSelectorTypeLower
constant StreamSelectorTypeHigher (line 59) | StreamSelectorTypeHigher
type StreamSelector (line 97) | type StreamSelector struct
type StreamSelectorManager (line 106) | type StreamSelectorManager interface
type StreamSinkManager (line 113) | type StreamSinkManager interface
type StreamSrcManager (line 129) | type StreamSrcManager interface
type CaptureManager (line 139) | type CaptureManager interface
type VideoConfig (line 152) | type VideoConfig struct
method GetPipeline (line 165) | func (config *VideoConfig) GetPipeline(screen ScreenSize) (string, err...
FILE: server/pkg/types/codec/codecs.go
function ParseRTC (line 21) | func ParseRTC(codec webrtc.RTPCodecParameters) (RTPCodec, bool) {
function ParseStr (line 26) | func ParseStr(codecName string) (codec RTPCodec, ok bool) {
type RTPCodec (line 53) | type RTPCodec struct
method Register (line 61) | func (codec *RTPCodec) Register(engine *webrtc.MediaEngine) error {
method IsVideo (line 68) | func (codec *RTPCodec) IsVideo() bool {
method IsAudio (line 72) | func (codec *RTPCodec) IsAudio() bool {
method String (line 76) | func (codec *RTPCodec) String() string {
function VP8 (line 80) | func VP8() RTPCodec {
function VP9 (line 99) | func VP9() RTPCodec {
function H264 (line 118) | func H264() RTPCodec {
function AV1 (line 140) | func AV1() RTPCodec {
function Opus (line 158) | func Opus() RTPCodec {
function G722 (line 176) | func G722() RTPCodec {
function PCMU (line 194) | func PCMU() RTPCodec {
function PCMA (line 212) | func PCMA() RTPCodec {
FILE: server/pkg/types/desktop.go
type CursorImage (line 8) | type CursorImage struct
type ScreenSize (line 17) | type ScreenSize struct
method String (line 23) | func (s ScreenSize) String() string {
type KeyboardModifiers (line 27) | type KeyboardModifiers struct
type KeyboardMap (line 38) | type KeyboardMap struct
type ClipboardText (line 43) | type ClipboardText struct
type DesktopManager (line 48) | type DesktopManager interface
FILE: server/pkg/types/event/events.go
constant SYSTEM_INIT (line 4) | SYSTEM_INIT = "system/init"
constant SYSTEM_ADMIN (line 5) | SYSTEM_ADMIN = "system/admin"
constant SYSTEM_SETTINGS (line 6) | SYSTEM_SETTINGS = "system/settings"
constant SYSTEM_LOGS (line 7) | SYSTEM_LOGS = "system/logs"
constant SYSTEM_DISCONNECT (line 8) | SYSTEM_DISCONNECT = "system/disconnect"
constant SYSTEM_HEARTBEAT (line 9) | SYSTEM_HEARTBEAT = "system/heartbeat"
constant CLIENT_HEARTBEAT (line 13) | CLIENT_HEARTBEAT = "client/heartbeat"
constant SIGNAL_REQUEST (line 17) | SIGNAL_REQUEST = "signal/request"
constant SIGNAL_RESTART (line 18) | SIGNAL_RESTART = "signal/restart"
constant SIGNAL_OFFER (line 19) | SIGNAL_OFFER = "signal/offer"
constant SIGNAL_ANSWER (line 20) | SIGNAL_ANSWER = "signal/answer"
constant SIGNAL_PROVIDE (line 21) | SIGNAL_PROVIDE = "signal/provide"
constant SIGNAL_CANDIDATE (line 22) | SIGNAL_CANDIDATE = "signal/candidate"
constant SIGNAL_VIDEO (line 23) | SIGNAL_VIDEO = "signal/video"
constant SIGNAL_AUDIO (line 24) | SIGNAL_AUDIO = "signal/audio"
constant SIGNAL_CLOSE (line 25) | SIGNAL_CLOSE = "signal/close"
constant SESSION_CREATED (line 29) | SESSION_CREATED = "session/created"
constant SESSION_DELETED (line 30) | SESSION_DELETED = "session/deleted"
constant SESSION_PROFILE (line 31) | SESSION_PROFILE = "session/profile"
constant SESSION_STATE (line 32) | SESSION_STATE = "session/state"
constant SESSION_CURSORS (line 33) | SESSION_CURSORS = "session/cursors"
constant CONTROL_HOST (line 37) | CONTROL_HOST = "control/host"
constant CONTROL_RELEASE (line 38) | CONTROL_RELEASE = "control/release"
constant CONTROL_REQUEST (line 39) | CONTROL_REQUEST = "control/request"
constant CONTROL_MOVE (line 41) | CONTROL_MOVE = "control/move"
constant CONTROL_SCROLL (line 42) | CONTROL_SCROLL = "control/scroll"
constant CONTROL_BUTTONPRESS (line 43) | CONTROL_BUTTONPRESS = "control/buttonpress"
constant CONTROL_BUTTONDOWN (line 44) | CONTROL_BUTTONDOWN = "control/buttondown"
constant CONTROL_BUTTONUP (line 45) | CONTROL_BUTTONUP = "control/buttonup"
constant CONTROL_KEYPRESS (line 47) | CONTROL_KEYPRESS = "control/keypress"
constant CONTROL_KEYDOWN (line 48) | CONTROL_KEYDOWN = "control/keydown"
constant CONTROL_KEYUP (line 49) | CONTROL_KEYUP = "control/keyup"
constant CONTROL_TOUCHBEGIN (line 51) | CONTROL_TOUCHBEGIN = "control/touchbegin"
constant CONTROL_TOUCHUPDATE (line 52) | CONTROL_TOUCHUPDATE = "control/touchupdate"
constant CONTROL_TOUCHEND (line 53) | CONTROL_TOUCHEND = "control/touchend"
constant CONTROL_CUT (line 55) | CONTROL_CUT = "control/cut"
constant CONTROL_COPY (line 56) | CONTROL_COPY = "control/copy"
constant CONTROL_PASTE (line 57) | CONTROL_PASTE = "control/paste"
constant CONTROL_SELECT_ALL (line 58) | CONTROL_SELECT_ALL = "control/select_all"
constant SCREEN_UPDATED (line 62) | SCREEN_UPDATED = "screen/updated"
constant SCREEN_SET (line 63) | SCREEN_SET = "screen/set"
constant CLIPBOARD_UPDATED (line 67) | CLIPBOARD_UPDATED = "clipboard/updated"
constant CLIPBOARD_SET (line 68) | CLIPBOARD_SET = "clipboard/set"
constant KEYBOARD_MODIFIERS (line 72) | KEYBOARD_MODIFIERS = "keyboard/modifiers"
constant KEYBOARD_MAP (line 73) | KEYBOARD_MAP = "keyboard/map"
constant BROADCAST_STATUS (line 77) | BROADCAST_STATUS = "broadcast/status"
constant SEND_UNICAST (line 81) | SEND_UNICAST = "send/unicast"
constant SEND_BROADCAST (line 82) | SEND_BROADCAST = "send/broadcast"
constant FILE_CHOOSER_DIALOG_OPENED (line 86) | FILE_CHOOSER_DIALOG_OPENED = "file_chooser_dialog/opened"
constant FILE_CHOOSER_DIALOG_CLOSED (line 87) | FILE_CHOOSER_DIALOG_CLOSED = "file_chooser_dialog/closed"
FILE: server/pkg/types/http.go
type RouterHandler (line 8) | type RouterHandler
type MiddlewareHandler (line 9) | type MiddlewareHandler
type Router (line 11) | type Router interface
type HttpManager (line 24) | type HttpManager interface
FILE: server/pkg/types/member.go
type MemberProfile (line 11) | type MemberProfile struct
type MemberProvider (line 29) | type MemberProvider interface
type MemberManager (line 43) | type MemberManager interface
FILE: server/pkg/types/message/messages.go
type SystemWebRTC (line 13) | type SystemWebRTC struct
type SystemInit (line 17) | type SystemInit struct
type SystemAdmin (line 28) | type SystemAdmin struct
type SystemLog (line 35) | type SystemLog struct
type SystemDisconnect (line 41) | type SystemDisconnect struct
type SystemSettingsUpdate (line 45) | type SystemSettingsUpdate struct
type SignalRequest (line 54) | type SignalRequest struct
type SignalProvide (line 61) | type SignalProvide struct
type SignalCandidate (line 69) | type SignalCandidate struct
type SignalDescription (line 73) | type SignalDescription struct
type SignalVideo (line 77) | type SignalVideo struct
type SignalAudio (line 81) | type SignalAudio struct
type SessionID (line 89) | type SessionID struct
type MemberProfile (line 93) | type MemberProfile struct
type SessionState (line 98) | type SessionState struct
type SessionData (line 103) | type SessionData struct
type SessionCursors (line 109) | type SessionCursors struct
type ControlHost (line 118) | type ControlHost struct
type ControlScroll (line 124) | type ControlScroll struct
type ControlPos (line 134) | type ControlPos struct
type ControlButton (line 139) | type ControlButton struct
type ControlKey (line 144) | type ControlKey struct
type ControlTouch (line 149) | type ControlTouch struct
type ScreenSize (line 159) | type ScreenSize struct
type ScreenSizeUpdate (line 163) | type ScreenSizeUpdate struct
type ClipboardData (line 172) | type ClipboardData struct
type KeyboardMap (line 180) | type KeyboardMap struct
type KeyboardModifiers (line 184) | type KeyboardModifiers struct
type BroadcastStatus (line 192) | type BroadcastStatus struct
type SendUnicast (line 201) | type SendUnicast struct
type SendBroadcast (line 208) | type SendBroadcast struct
FILE: server/pkg/types/plugins.go
type Plugin (line 17) | type Plugin interface
type DependablePlugin (line 24) | type DependablePlugin interface
type ExposablePlugin (line 29) | type ExposablePlugin interface
type PluginConfig (line 34) | type PluginConfig interface
type PluginMetadata (line 39) | type PluginMetadata struct
type PluginManagers (line 46) | type PluginManagers struct
method Validate (line 53) | func (p *PluginManagers) Validate() error {
type PluginSettings (line 73) | type PluginSettings
method Unmarshal (line 75) | func (p PluginSettings) Unmarshal(name string, def any) error {
FILE: server/pkg/types/session.go
type Cursor (line 17) | type Cursor struct
type SessionProfile (line 22) | type SessionProfile struct
type SessionState (line 28) | type SessionState struct
type Settings (line 42) | type Settings struct
type Stats (line 56) | type Stats struct
type Session (line 66) | type Session interface
type SessionManager (line 92) | type SessionManager interface
FILE: server/pkg/types/webrtc.go
type ICEServer (line 15) | type ICEServer struct
type PeerVideo (line 21) | type PeerVideo struct
type PeerVideoRequest (line 28) | type PeerVideoRequest struct
type PeerAudio (line 34) | type PeerAudio struct
type PeerAudioRequest (line 38) | type PeerAudioRequest struct
type WebRTCPeer (line 42) | type WebRTCPeer interface
type WebRTCManager (line 62) | type WebRTCManager interface
FILE: server/pkg/types/websocket.go
type WebSocketMessage (line 8) | type WebSocketMessage struct
type WebSocketHandler (line 13) | type WebSocketHandler
type CheckOrigin (line 15) | type CheckOrigin
type WebSocketPeer (line 17) | type WebSocketPeer interface
type WebSocketManager (line 23) | type WebSocketManager interface
FILE: server/pkg/utils/array.go
function ArrayIn (line 3) | func ArrayIn[T comparable](val T, array []T) (exists bool, index int) {
FILE: server/pkg/utils/color.go
constant char (line 9) | char = "&"
function Color (line 15) | func Color(str string) string {
function Colorf (line 32) | func Colorf(format string, a ...any) string {
FILE: server/pkg/utils/deocde.go
function Decode (line 10) | func Decode(input interface{}, output interface{}) error {
function Unmarshal (line 14) | func Unmarshal(in any, raw []byte, callback func() error) error {
function JsonStringAutoDecode (line 21) | func JsonStringAutoDecode(m any) func(rf reflect.Kind, rt reflect.Kind, ...
FILE: server/pkg/utils/http.go
function HttpJsonRequest (line 12) | func HttpJsonRequest(w http.ResponseWriter, r *http.Request, res any) er...
function HttpJsonResponse (line 26) | func HttpJsonResponse(w http.ResponseWriter, code int, res any) {
function HttpSuccess (line 35) | func HttpSuccess(w http.ResponseWriter, res ...any) error {
type HTTPError (line 46) | type HTTPError struct
method Error (line 54) | func (e *HTTPError) Error() string {
method Cause (line 61) | func (e *HTTPError) Cause() error {
method WithInternalErr (line 69) | func (e *HTTPError) WithInternalErr(err error) *HTTPError {
method WithInternalMsg (line 75) | func (e *HTTPError) WithInternalMsg(msg string) *HTTPError {
method WithInternalMsgf (line 81) | func (e *HTTPError) WithInternalMsgf(fmtStr string, args ...any) *HTTP...
method Msgf (line 87) | func (e *HTTPError) Msgf(fmtSt string, args ...any) *HTTPError {
method Msg (line 93) | func (e *HTTPError) Msg(str string) *HTTPError {
function HttpError (line 98) | func HttpError(code int, res ...string) *HTTPError {
function HttpBadRequest (line 111) | func HttpBadRequest(res ...string) *HTTPError {
function HttpUnauthorized (line 115) | func HttpUnauthorized(res ...string) *HTTPError {
function HttpForbidden (line 119) | func HttpForbidden(res ...string) *HTTPError {
function HttpNotFound (line 123) | func HttpNotFound(res ...string) *HTTPError {
function HttpUnprocessableEntity (line 127) | func HttpUnprocessableEntity(res ...string) *HTTPError {
function HttpInternalServerError (line 131) | func HttpInternalServerError(res ...string) *HTTPError {
FILE: server/pkg/utils/image.go
function CreatePNGImage (line 11) | func CreatePNGImage(img *image.RGBA) ([]byte, error) {
function CreateJPGImage (line 21) | func CreateJPGImage(img *image.RGBA, quality int) ([]byte, error) {
function CreatePNGImageURI (line 31) | func CreatePNGImageURI(img *image.RGBA) (string, error) {
FILE: server/pkg/utils/request.go
function HttpRequestGET (line 9) | func HttpRequestGET(url string) (string, error) {
FILE: server/pkg/utils/trenddetector.go
type TrendDirection (line 11) | type TrendDirection
method String (line 19) | func (t TrendDirection) String() string {
constant TrendDirectionNeutral (line 14) | TrendDirectionNeutral TrendDirection = iota
constant TrendDirectionUpward (line 15) | TrendDirectionUpward
constant TrendDirectionDownward (line 16) | TrendDirectionDownward
type TrendDetectorParams (line 34) | type TrendDetectorParams struct
type TrendDetector (line 40) | type TrendDetector struct
method Seed (line 60) | func (t *TrendDetector) Seed(value int64) {
method AddValue (line 68) | func (t *TrendDetector) AddValue(value int64) {
method GetLowest (line 90) | func (t *TrendDetector) GetLowest() int64 {
method GetHighest (line 94) | func (t *TrendDetector) GetHighest() int64 {
method GetValues (line 98) | func (t *TrendDetector) GetValues() []int64 {
method GetDirection (line 102) | func (t *TrendDetector) GetDirection() TrendDirection {
method ToString (line 106) | func (t *TrendDetector) ToString() string {
method updateDirection (line 114) | func (t *TrendDetector) updateDirection() {
function NewTrendDetector (line 52) | func NewTrendDetector(params TrendDetectorParams) *TrendDetector {
function kendallsTau (line 134) | func kendallsTau(values []int64) float64 {
FILE: server/pkg/utils/uid.go
constant defaultAlphabet (line 10) | defaultAlphabet = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO...
constant defaultSize (line 11) | defaultSize = 21
constant defaultMaskSize (line 12) | defaultMaskSize = 5
type Generator (line 16) | type Generator
function initMasks (line 21) | func initMasks(params ...int) []uint {
function getMask (line 36) | func getMask(alphabet string, masks []uint) int {
function GenerateUID (line 47) | func GenerateUID(alphabet string, size int) (string, error) {
function NewUID (line 81) | func NewUID(param ...int) (string, error) {
FILE: server/pkg/utils/zip.go
function Zip (line 11) | func Zip(source, zipPath string) error {
function Unzip (line 63) | func Unzip(zipPath, target string) error {
FILE: server/pkg/xevent/xevent.c
function XEventError (line 3) | static int XEventError(Display *display, XErrorEvent *event) {
function XSetupErrorHandler (line 17) | void XSetupErrorHandler() {
function XEventLoop (line 21) | void XEventLoop(char *name) {
function XWindowManagerStateEvent (line 145) | static void XWindowManagerStateEvent(Display *display, Window window, ul...
function XFileChooserHide (line 176) | void XFileChooserHide(Display *display, Window window) {
FILE: server/pkg/xevent/xevent.go
function init (line 22) | func init() {
function SetupErrorHandler (line 26) | func SetupErrorHandler() {
function EventLoop (line 30) | func EventLoop(display string) {
function goXEventCursorChanged (line 38) | func goXEventCursorChanged(event C.XFixesCursorNotifyEvent) {
function goXEventClipboardUpdated (line 43) | func goXEventClipboardUpdated() {
function goXEventConfigureNotify (line 48) | func goXEventConfigureNotify(display *C.Display, window C.Window, name *...
function goXEventUnmapNotify (line 68) | func goXEventUnmapNotify(window C.Window) {
function goXEventWMChangeState (line 78) | func goXEventWMChangeState(display *C.Display, window C.Window, window_s...
function goXEventError (line 89) | func goXEventError(event *C.XErrorEvent, message *C.char) {
function goXEventActive (line 94) | func goXEventActive() C.int {
FILE: server/pkg/xinput/dummy.go
type dummy (line 5) | type dummy struct
method Connect (line 11) | func (d *dummy) Connect() error {
method Close (line 15) | func (d *dummy) Close() error {
method Debounce (line 19) | func (d *dummy) Debounce(duration time.Duration) {}
method TouchBegin (line 21) | func (d *dummy) TouchBegin(touchId uint32, x, y int, pressure uint8) e...
method TouchUpdate (line 25) | func (d *dummy) TouchUpdate(touchId uint32, x, y int, pressure uint8) ...
method TouchEnd (line 29) | func (d *dummy) TouchEnd(touchId uint32, x, y int, pressure uint8) err...
function NewDummy (line 7) | func NewDummy() Driver {
FILE: server/pkg/xinput/types.go
constant AbsX (line 7) | AbsX = 0xffff
constant AbsY (line 8) | AbsY = 0xffff
constant XI_TouchBegin (line 12) | XI_TouchBegin = 18
constant XI_TouchUpdate (line 13) | XI_TouchUpdate = 19
constant XI_TouchEnd (line 14) | XI_TouchEnd = 20
type Message (line 17) | type Message struct
method Unpack (line 25) | func (msg *Message) Unpack(buffer []byte) {
method Pack (line 33) | func (msg *Message) Pack() []byte {
type Driver (line 52) | type Driver interface
FILE: server/pkg/xinput/xinput.go
type driver (line 11) | type driver struct
method Connect (line 27) | func (d *driver) Connect() error {
method Close (line 36) | func (d *driver) Close() error {
method Debounce (line 40) | func (d *driver) Debounce(duration time.Duration) {
method TouchBegin (line 61) | func (d *driver) TouchBegin(touchId uint32, x, y int, pressure uint8) ...
method TouchUpdate (line 82) | func (d *driver) TouchUpdate(touchId uint32, x, y int, pressure uint8)...
method TouchEnd (line 103) | func (d *driver) TouchEnd(touchId uint32, x, y int, pressure uint8) er...
function NewDriver (line 19) | func NewDriver(socket string) Driver {
FILE: server/pkg/xorg/keysymdef.go
constant XK_VoidSymbol (line 116) | XK_VoidSymbol = 0xffffff
constant XK_BackSpace (line 125) | XK_BackSpace = 0xff08
constant XK_Tab (line 126) | XK_Tab = 0xff09
constant XK_Linefeed (line 127) | XK_Linefeed = 0xff0a
constant XK_Clear (line 128) | XK_Clear = 0xff0b
constant XK_Return (line 129) | XK_Return = 0xff0d
constant XK_Pause (line 130) | XK_Pause = 0xff13
constant XK_Scroll_Lock (line 131) | XK_Scroll_Lock = 0xff14
constant XK_Sys_Req (line 132) | XK_Sys_Req = 0xff15
constant XK_Escape (line 133) | XK_Escape = 0xff1b
constant XK_Delete (line 134) | XK_Delete = 0xffff
constant XK_Multi_key (line 140) | XK_Multi_key = 0xff20
constant XK_Codeinput (line 141) | XK_Codeinput = 0xff37
constant XK_SingleCandidate (line 142) | XK_SingleCandidate = 0xff3c
constant XK_MultipleCandidate (line 143) | XK_MultipleCandidate = 0xff3d
constant XK_PreviousCandidate (line 144) | XK_PreviousCandidate = 0xff3e
constant XK_Kanji (line 148) | XK_Kanji = 0xff21
constant XK_Muhenkan (line 149) | XK_Muhenkan = 0xff22
constant XK_Henkan_Mode (line 150) | XK_Henkan_Mode = 0xff23
constant XK_Henkan (line 151) | XK_Henkan = 0xff23
constant XK_Romaji (line 152) | XK_Romaji = 0xff24
constant XK_Hiragana (line 153) | XK_Hiragana = 0xff25
constant XK_Katakana (line 154) | XK_Katakana = 0xff26
constant XK_Hiragana_Katakana (line 155) | XK_Hiragana_Katakana = 0xff27
constant XK_Zenkaku (line 156) | XK_Zenkaku = 0xff28
constant XK_Hankaku (line 157) | XK_Hankaku = 0xff29
constant XK_Zenkaku_Hankaku (line 158) | XK_Zenkaku_Hankaku = 0xff2a
constant XK_Touroku (line 159) | XK_Touroku = 0xff2b
constant XK_Massyo (line 160) | XK_Massyo = 0xff2c
constant XK_Kana_Lock (line 161) | XK_Kana_Lock = 0xff2d
constant XK_Kana_Shift (line 162) | XK_Kana_Shift = 0xff2e
constant XK_Eisu_Shift (line 163) | XK_Eisu_Shift = 0xff2f
constant XK_Eisu_toggle (line 164) | XK_Eisu_toggle = 0xff30
constant XK_Kanji_Bangou (line 165) | XK_Kanji_Bangou = 0xff37
constant XK_Zen_Koho (line 166) | XK_Zen_Koho = 0xff3d
constant XK_Mae_Koho (line 167) | XK_Mae_Koho = 0xff3e
constant XK_Home (line 173) | XK_Home = 0xff50
constant XK_Left (line 174) | XK_Left = 0xff51
constant XK_Up (line 175) | XK_Up = 0xff52
constant XK_Right (line 176) | XK_Right = 0xff53
constant XK_Down (line 177) | XK_Down = 0xff54
constant XK_Prior (line 178) | XK_Prior = 0xff55
constant XK_Page_Up (line 179) | XK_Page_Up = 0xff55
constant XK_Next (line 180) | XK_Next = 0xff56
constant XK_Page_Down (line 181) | XK_Page_Down = 0xff56
constant XK_End (line 182) | XK_End = 0xff57
constant XK_Begin (line 183) | XK_Begin = 0xff58
constant XK_Select (line 188) | XK_Select = 0xff60
constant XK_Print (line 189) | XK_Print = 0xff61
constant XK_Execute (line 190) | XK_Execute = 0xff62
constant XK_Insert (line 191) | XK_Insert = 0xff63
constant XK_Undo (line 192) | XK_Undo = 0xff65
constant XK_Redo (line 193) | XK_Redo = 0xff66
constant XK_Menu (line 194) | XK_Menu = 0xff67
constant XK_Find (line 195) | XK_Find = 0xff68
constant XK_Cancel (line 196) | XK_Cancel = 0xff69
constant XK_Help (line 197) | XK_Help = 0xff6a
constant XK_Break (line 198) | XK_Break = 0xff6b
constant XK_Mode_switch (line 199) | XK_Mode_switch = 0xff7e
constant XK_script_switch (line 200) | XK_script_switch = 0xff7e
constant XK_Num_Lock (line 201) | XK_Num_Lock = 0xff7f
constant XK_KP_Space (line 205) | XK_KP_Space = 0xff80
constant XK_KP_Tab (line 206) | XK_KP_Tab = 0xff89
constant XK_KP_Enter (line 207) | XK_KP_Enter = 0xff8d
constant XK_KP_F1 (line 208) | XK_KP_F1 = 0xff91
constant XK_KP_F2 (line 209) | XK_KP_F2 = 0xff92
constant XK_KP_F3 (line 210) | XK_KP_F3 = 0xff93
constant XK_KP_F4 (line 211) | XK_KP_F4 = 0xff94
constant XK_KP_Home (line 212) | XK_KP_Home = 0xff95
constant XK_KP_Left (line 213) | XK_KP_Left = 0xff96
constant XK_KP_Up (line 214) | XK_KP_Up = 0xff97
constant XK_KP_Right (line 215) | XK_KP_Right = 0xff98
constant XK_KP_Down (line 216) | XK_KP_Down = 0xff99
constant XK_KP_Prior (line 217) | XK_KP_Prior = 0xff9a
constant XK_KP_Page_Up (line 218) | XK_KP_Page_Up = 0xff9a
constant XK_KP_Next (line 219) | XK_KP_Next = 0xff9b
constant XK_KP_Page_Down (line 220) | XK_KP_Page_Down = 0xff9b
constant XK_KP_End (line 221) | XK_KP_End = 0xff9c
constant XK_KP_Begin (line 222) | XK_KP_Begin = 0xff9d
constant XK_KP_Insert (line 223) | XK_KP_Insert = 0xff9e
constant XK_KP_Delete (line 224) | XK_KP_Delete = 0xff9f
constant XK_KP_Equal (line 225) | XK_KP_Equal = 0xffbd
constant XK_KP_Multiply (line 226) | XK_KP_Multiply = 0xffaa
constant XK_KP_Add (line 227) | XK_KP_Add = 0xffab
constant XK_KP_Separator (line 228) | XK_KP_Separator = 0xffac
constant XK_KP_Subtract (line 229) | XK_KP_Subtract = 0xffad
constant XK_KP_Decimal (line 230) | XK_KP_Decimal = 0xffae
constant XK_KP_Divide (line 231) | XK_KP_Divide = 0xffaf
constant XK_KP_0 (line 233) | XK_KP_0 = 0xffb0
constant XK_KP_1 (line 234) | XK_KP_1 = 0xffb1
constant XK_KP_2 (line 235) | XK_KP_2 = 0xffb2
constant XK_KP_3 (line 236) | XK_KP_3 = 0xffb3
constant XK_KP_4 (line 237) | XK_KP_4 = 0xffb4
constant XK_KP_5 (line 238) | XK_KP_5 = 0xffb5
constant XK_KP_6 (line 239) | XK_KP_6 = 0xffb6
constant XK_KP_7 (line 240) | XK_KP_7 = 0xffb7
constant XK_KP_8 (line 241) | XK_KP_8 = 0xffb8
constant XK_KP_9 (line 242) | XK_KP_9 = 0xffb9
constant XK_F1 (line 253) | XK_F1 = 0xffbe
constant XK_F2 (line 254) | XK_F2 = 0xffbf
constant XK_F3 (line 255) | XK_F3 = 0xffc0
constant XK_F4 (line 256) | XK_F4 = 0xffc1
constant XK_F5 (line 257) | XK_F5 = 0xffc2
constant XK_F6 (line 258) | XK_F6 = 0xffc3
constant XK_F7 (line 259) | XK_F7 = 0xffc4
constant XK_F8 (line 260) | XK_F8 = 0xffc5
constant XK_F9 (line 261) | XK_F9 = 0xffc6
constant XK_F10 (line 262) | XK_F10 = 0xffc7
constant XK_F11 (line 263) | XK_F11 = 0xffc8
constant XK_L1 (line 264) | XK_L1 = 0xffc8
constant XK_F12 (line 265) | XK_F12 = 0xffc9
constant XK_L2 (line 266) | XK_L2 = 0xffc9
constant XK_F13 (line 267) | XK_F13 = 0xffca
constant XK_L3 (line 268) | XK_L3 = 0xffca
constant XK_F14 (line 269) | XK_F14 = 0xffcb
constant XK_L4 (line 270) | XK_L4 = 0xffcb
constant XK_F15 (line 271) | XK_F15 = 0xffcc
constant XK_L5 (line 272) | XK_L5 = 0xffcc
constant XK_F16 (line 273) | XK_F16 = 0xffcd
constant XK_L6 (line 274) | XK_L6 = 0xffcd
constant XK_F17 (line 275) | XK_F17 = 0xffce
constant XK_L7 (line 276) | XK_L7 = 0xffce
constant XK_F18 (line 277) | XK_F18 = 0xffcf
constant XK_L8 (line 278) | XK_L8 = 0xffcf
constant XK_F19 (line 279) | XK_F19 = 0xffd0
constant XK_L9 (line 280) | XK_L9 = 0xffd0
constant XK_F20 (line 281) | XK_F20 = 0xffd1
constant XK_L10 (line 282) | XK_L10 = 0xffd1
constant XK_F21 (line 283) | XK_F21 = 0xffd2
constant XK_R1 (line 284) | XK_R1 = 0xffd2
constant XK_F22 (line 285) | XK_F22 = 0xffd3
constant XK_R2 (line 286) | XK_R2 = 0xffd3
constant XK_F23 (line 287) | XK_F23 = 0xffd4
constant XK_R3 (line 288) | XK_R3 = 0xffd4
constant XK_F24 (line 289) | XK_F24 = 0xffd5
constant XK_R4 (line 290) | XK_R4 = 0xffd5
constant XK_F25 (line 291) | XK_F25 = 0xffd6
constant XK_R5 (line 292) | XK_R5 = 0xffd6
constant XK_F26 (line 293) | XK_F26 = 0xffd7
constant XK_R6 (line 294) | XK_R6 = 0xffd7
constant XK_F27 (line 295) | XK_F27 = 0xffd8
constant XK_R7 (line 296) | XK_R7 = 0xffd8
constant XK_F28 (line 297) | XK_F28 = 0xffd9
constant XK_R8 (line 298) | XK_R8 = 0xffd9
constant XK_F29 (line 299) | XK_F29 = 0xffda
constant XK_R9 (line 300) | XK_R9 = 0xffda
constant XK_F30 (line 301) | XK_F30 = 0xffdb
constant XK_R10 (line 302) | XK_R10 = 0xffdb
constant XK_F31 (line 303) | XK_F31 = 0xffdc
constant XK_R11 (line 304) | XK_R11 = 0xffdc
constant XK_F32 (line 305) | XK_F32 = 0xffdd
constant XK_R12 (line 306) | XK_R12 = 0xffdd
constant XK_F33 (line 307) | XK_F33 = 0xffde
constant XK_R13 (line 308) | XK_R13 = 0xffde
constant XK_F34 (line 309) | XK_F34 = 0xffdf
constant XK_R14 (line 310) | XK_R14 = 0xffdf
constant XK_F35 (line 311) | XK_F35 = 0xffe0
constant XK_R15 (line 312) | XK_R15 = 0xffe0
constant XK_Shift_L (line 316) | XK_Shift_L = 0xffe1
constant XK_Shift_R (line 317) | XK_Shift_R = 0xffe2
constant XK_Control_L (line 318) | XK_Control_L = 0xffe3
constant XK_Control_R (line 319) | XK_Control_R = 0xffe4
constant XK_Caps_Lock (line 320) | XK_Caps_Lock = 0xffe5
constant XK_Shift_Lock (line 321) | XK_Shift_Lock = 0xffe6
constant XK_Meta_L (line 323) | XK_Meta_L = 0xffe7
constant XK_Meta_R (line 324) | XK_Meta_R = 0xffe8
constant XK_Alt_L (line 325) | XK_Alt_L = 0xffe9
constant XK_Alt_R (line 326) | XK_Alt_R = 0xffea
constant XK_Super_L (line 327) | XK_Super_L = 0xffeb
constant XK_Super_R (line 328) | XK_Super_R = 0xffec
constant XK_Hyper_L (line 329) | XK_Hyper_L = 0xffed
constant XK_Hyper_R (line 330) | XK_Hyper_R = 0xffee
constant XK_ISO_Lock (line 340) | XK_ISO_Lock = 0xfe01
constant XK_ISO_Level2_Latch (line 341) | XK_ISO_Level2_Latch = 0xfe02
constant XK_ISO_Level3_Shift (line 342) | XK_ISO_Level3_Shift = 0xfe03
constant XK_ISO_Level3_Latch (line 343) | XK_ISO_Level3_Latch = 0xfe04
constant XK_ISO_Level3_Lock (line 344) | XK_ISO_Level3_Lock = 0xfe05
constant XK_ISO_Level5_Shift (line 345) | XK_ISO_Level5_Shift = 0xfe11
constant XK_ISO_Level5_Latch (line 346) | XK_ISO_Level5_Latch = 0xfe12
constant XK_ISO_Level5_Lock (line 347) | XK_ISO_Level5_Lock = 0xfe13
constant XK_ISO_Group_Shift (line 348) | XK_ISO_Group_Shift = 0xff7e
constant XK_ISO_Group_Latch (line 349) | XK_ISO_Group_Latch = 0xfe06
constant XK_ISO_Group_Lock (line 350) | XK_ISO_Group_Lock = 0xfe07
constant XK_ISO_Next_Group (line 351) | XK_ISO_Next_Group = 0xfe08
constant XK_ISO_Next_Group_Lock (line 352) | XK_ISO_Next_Group_Lock = 0xfe09
constant XK_ISO_Prev_Group (line 353) | XK_ISO_Prev_Group = 0xfe0a
constant XK_ISO_Prev_Group_Lock (line 354) | XK_ISO_Prev_Group_Lock = 0xfe0b
constant XK_ISO_First_Group (line 355) | XK_ISO_First_Group = 0xfe0c
constant XK_ISO_First_Group_Lock (line 356) | XK_ISO_First_Group_Lock = 0xfe0d
constant XK_ISO_Last_Group (line 357) | XK_ISO_Last_Group = 0xfe0e
constant XK_ISO_Last_Group_Lock (line 358) | XK_ISO_Last_Group_Lock = 0xfe0f
constant XK_ISO_Left_Tab (line 360) | XK_ISO_Left_Tab = 0xfe20
constant XK_ISO_Move_Line_Up (line 361) | XK_ISO_Move_Line_Up = 0xfe21
constant XK_ISO_Move_Line_Down (line 362) | XK_ISO_Move_Line_Down = 0xfe22
constant XK_ISO_Partial_Line_Up (line 363) | XK_ISO_Partial_Line_Up = 0xfe23
constant XK_ISO_Partial_Line_Down (line 364) | XK_ISO_Partial_Line_Down = 0xfe24
constant XK_ISO_Partial_Space_Left (line 365) | XK_ISO_Partial_Space_Left = 0xfe25
constant XK_ISO_Partial_Space_Right (line 366) | XK_ISO_Partial_Space_Right = 0xfe26
constant XK_ISO_Set_Margin_Left (line 367) | XK_ISO_Set_Margin_Left = 0xfe27
constant XK_ISO_Set_Margin_Right (line 368) | XK_ISO_Set_Margin_Right = 0xfe28
constant XK_ISO_Release_Margin_Left (line 369) | XK_ISO_Release_Margin_Left = 0xfe29
constant XK_ISO_Release_Margin_Right (line 370) | XK_ISO_Release_Margin_Right = 0xfe2a
constant XK_ISO_Release_Both_Margins (line 371) | XK_ISO_Release_Both_Margins = 0xfe2b
constant XK_ISO_Fast_Cursor_Left (line 372) | XK_ISO_Fast_Cursor_Left = 0xfe2c
constant XK_ISO_Fast_Cursor_Right (line 373) | XK_ISO_Fast_Cursor_Right = 0xfe2d
constant XK_ISO_Fast_Cursor_Up (line 374) | XK_ISO_Fast_Cursor_Up = 0xfe2e
constant XK_ISO_Fast_Cursor_Down (line 375) | XK_ISO_Fast_Cursor_Down = 0xfe2f
constant XK_ISO_Continuous_Underline (line 376) | XK_ISO_Continuous_Underline = 0xfe30
constant XK_ISO_Discontinuous_Underline (line 377) | XK_ISO_Discontinuous_Underline = 0xfe31
constant XK_ISO_Emphasize (line 378) | XK_ISO_Emphasize = 0xfe32
constant XK_ISO_Center_Object (line 379) | XK_ISO_Center_Object = 0xfe33
constant XK_ISO_Enter (line 380) | XK_ISO_Enter = 0xfe34
constant XK_dead_grave (line 382) | XK_dead_grave = 0xfe50
constant XK_dead_acute (line 383) | XK_dead_acute = 0xfe51
constant XK_dead_circumflex (line 384) | XK_dead_circumflex = 0xfe52
constant XK_dead_tilde (line 385) | XK_dead_tilde = 0xfe53
constant XK_dead_perispomeni (line 386) | XK_dead_perispomeni = 0xfe53
constant XK_dead_macron (line 387) | XK_dead_macron = 0xfe54
constant XK_dead_breve (line 388) | XK_dead_breve = 0xfe55
constant XK_dead_abovedot (line 389) | XK_dead_abovedot = 0xfe56
constant XK_dead_diaeresis (line 390) | XK_dead_diaeresis = 0xfe57
constant XK_dead_abovering (line 391) | XK_dead_abovering = 0xfe58
constant XK_dead_doubleacute (line 392) | XK_dead_doubleacute = 0xfe59
constant XK_dead_caron (line 393) | XK_dead_caron = 0xfe5a
constant XK_dead_cedilla (line 394) | XK_dead_cedilla = 0xfe5b
constant XK_dead_ogonek (line 395) | XK_dead_ogonek = 0xfe5c
constant XK_dead_iota (line 396) | XK_dead_iota = 0xfe5d
constant XK_dead_voiced_sound (line 397) | XK_dead_voiced_sound = 0xfe5e
constant XK_dead_semivoiced_sound (line 398) | XK_dead_semivoiced_sound = 0xfe5f
constant XK_dead_belowdot (line 399) | XK_dead_belowdot = 0xfe60
constant XK_dead_hook (line 400) | XK_dead_hook = 0xfe61
constant XK_dead_horn (line 401) | XK_dead_horn = 0xfe62
constant XK_dead_stroke (line 402) | XK_dead_stroke = 0xfe63
constant XK_dead_abovecomma (line 403) | XK_dead_abovecomma = 0xfe64
constant XK_dead_psili (line 404) | XK_dead_psili = 0xfe64
constant XK_dead_abovereversedcomma (line 405) | XK_dead_abovereversedcomma = 0xfe65
constant XK_dead_dasia (line 406) | XK_dead_dasia = 0xfe65
constant XK_dead_doublegrave (line 407) | XK_dead_doublegrave = 0xfe66
constant XK_dead_belowring (line 408) | XK_dead_belowring = 0xfe67
constant XK_dead_belowmacron (line 409) | XK_dead_belowmacron = 0xfe68
constant XK_dead_belowcircumflex (line 410) | XK_dead_belowcircumflex = 0xfe69
constant XK_dead_belowtilde (line 411) | XK_dead_belowtilde = 0xfe6a
constant XK_dead_belowbreve (line 412) | XK_dead_belowbreve = 0xfe6b
constant XK_dead_belowdiaeresis (line 413) | XK_dead_belowdiaeresis = 0xfe6c
constant XK_dead_invertedbreve (line 414) | XK_dead_invertedbreve = 0xfe6d
constant XK_dead_belowcomma (line 415) | XK_dead_belowcomma = 0xfe6e
constant XK_dead_currency (line 416) | XK_dead_currency = 0xfe6f
constant XK_dead_lowline (line 419) | XK_dead_lowline = 0xfe90
constant XK_dead_aboveverticalline (line 420) | XK_dead_aboveverticalline = 0xfe91
constant XK_dead_belowverticalline (line 421) | XK_dead_belowverticalline = 0xfe92
constant XK_dead_longsolidusoverlay (line 422) | XK_dead_longsolidusoverlay = 0xfe93
constant XK_dead_a (line 425) | XK_dead_a = 0xfe80
constant XK_dead_A (line 426) | XK_dead_A = 0xfe81
constant XK_dead_e (line 427) | XK_dead_e = 0xfe82
constant XK_dead_E (line 428) | XK_dead_E = 0xfe83
constant XK_dead_i (line 429) | XK_dead_i = 0xfe84
constant XK_dead_I (line 430) | XK_dead_I = 0xfe85
constant XK_dead_o (line 431) | XK_dead_o = 0xfe86
constant XK_dead_O (line 432) | XK_dead_O = 0xfe87
constant XK_dead_u (line 433) | XK_dead_u = 0xfe88
constant XK_dead_U (line 434) | XK_dead_U = 0xfe89
constant XK_dead_small_schwa (line 435) | XK_dead_small_schwa = 0xfe8a
constant XK_dead_capital_schwa (line 436) | XK_dead_capital_schwa = 0xfe8b
constant XK_dead_greek (line 438) | XK_dead_greek = 0xfe8c
constant XK_First_Virtual_Screen (line 440) | XK_First_Virtual_Screen = 0xfed0
constant XK_Prev_Virtual_Screen (line 441) | XK_Prev_Virtual_Screen = 0xfed1
constant XK_Next_Virtual_Screen (line 442) | XK_Next_Virtual_Screen = 0xfed2
constant XK_Last_Virtual_Screen (line 443) | XK_Last_Virtual_Screen = 0xfed4
constant XK_Terminate_Server (line 444) | XK_Terminate_Server = 0xfed5
constant XK_AccessX_Enable (line 446) | XK_AccessX_Enable = 0xfe70
constant XK_AccessX_Feedback_Enable (line 447) | XK_AccessX_Feedback_Enable = 0xfe71
constant XK_RepeatKeys_Enable (line 448) | XK_RepeatKeys_Enable = 0xfe72
constant XK_SlowKeys_Enable (line 449) | XK_SlowKeys_Enable = 0xfe73
constant XK_BounceKeys_Enable (line 450) | XK_BounceKeys_Enable = 0xfe74
constant XK_StickyKeys_Enable (line 451) | XK_StickyKeys_Enable = 0xfe75
constant XK_MouseKeys_Enable (line 452) | XK_MouseKeys_Enable = 0xfe76
constant XK_MouseKeys_Accel_Enable (line 453) | XK_MouseKeys_Accel_Enable = 0xfe77
constant XK_Overlay1_Enable (line 454) | XK_Overlay1_Enable = 0xfe78
constant XK_Overlay2_Enable (line 455) | XK_Overlay2_Enable = 0xfe79
constant XK_AudibleBell_Enable (line 456) | XK_AudibleBell_Enable = 0xfe7a
constant XK_Pointer_Left (line 458) | XK_Pointer_Left = 0xfee0
constant XK_Pointer_Right (line 459) | XK_Pointer_Right = 0xfee1
constant XK_Pointer_Up (line 460) | XK_Pointer_Up = 0xfee2
constant XK_Pointer_Down (line 461) | XK_Pointer_Down = 0xfee3
constant XK_Pointer_UpLeft (line 462) | XK_Pointer_UpLeft = 0xfee4
constant XK_Pointer_UpRight (line 463) | XK_Pointer_UpRight = 0xfee5
constant XK_Pointer_DownLeft (line 464) | XK_Pointer_DownLeft = 0xfee6
constant XK_Pointer_DownRight (line 465) | XK_Pointer_DownRight = 0xfee7
constant XK_Pointer_Button_Dflt (line 466) | XK_Pointer_Button_Dflt = 0xfee8
constant XK_Pointer_Button1 (line 467) | XK_Pointer_Button1 = 0xfee9
constant XK_Pointer_Button2 (line 468) | XK_Pointer_Button2 = 0xfeea
constant XK_Pointer_Button3 (line 469) | XK_Pointer_Button3 = 0xfeeb
constant XK_Pointer_Button4 (line 470) | XK_Pointer_Button4 = 0xfeec
constant XK_Pointer_Button5 (line 471) | XK_Pointer_Button5 = 0xfeed
constant XK_Pointer_DblClick_Dflt (line 472) | XK_Pointer_DblClick_Dflt = 0xfeee
constant XK_Pointer_DblClick1 (line 473) | XK_Pointer_DblClick1 = 0xfeef
constant XK_Pointer_DblClick2 (line 474) | XK_Pointer_DblClick2 = 0xfef0
constant XK_Pointer_DblClick3 (line 475) | XK_Pointer_DblClick3 = 0xfef1
constant XK_Pointer_DblClick4 (line 476) | XK_Pointer_DblClick4 = 0xfef2
constant XK_Pointer_DblClick5 (line 477) | XK_Pointer_DblClick5 = 0xfef3
constant XK_Pointer_Drag_Dflt (line 478) | XK_Pointer_Drag_Dflt = 0xfef4
constant XK_Pointer_Drag1 (line 479) | XK_Pointer_Drag1 = 0xfef5
constant XK_Pointer_Drag2 (line 480) | XK_Pointer_Drag2 = 0xfef6
constant XK_Pointer_Drag3 (line 481) | XK_Pointer_Drag3 = 0xfef7
constant XK_Pointer_Drag4 (line 482) | XK_Pointer_Drag4 = 0xfef8
constant XK_Pointer_Drag5 (line 483) | XK_Pointer_Drag5 = 0xfefd
constant XK_Pointer_EnableKeys (line 485) | XK_Pointer_EnableKeys = 0xfef9
constant XK_Pointer_Accelerate (line 486) | XK_Pointer_Accelerate = 0xfefa
constant XK_Pointer_DfltBtnNext (line 487) | XK_Pointer_DfltBtnNext = 0xfefb
constant XK_Pointer_DfltBtnPrev (line 488) | XK_Pointer_DfltBtnPrev = 0xfefc
constant XK_ch (line 492) | XK_ch = 0xfea0
constant XK_Ch (line 493) | XK_Ch = 0xfea1
constant XK_CH (line 494) | XK_CH = 0xfea2
constant XK_c_h (line 495) | XK_c_h = 0xfea3
constant XK_C_h (line 496) | XK_C_h = 0xfea4
constant XK_C_H (line 497) | XK_C_H = 0xfea5
constant XK_3270_Duplicate (line 507) | XK_3270_Duplicate = 0xfd01
constant XK_3270_FieldMark (line 508) | XK_3270_FieldMark = 0xfd02
constant XK_3270_Right2 (line 509) | XK_3270_Right2 = 0xfd03
constant XK_3270_Left2 (line 510) | XK_3270_Left2 = 0xfd04
constant XK_3270_BackTab (line 511) | XK_3270_BackTab = 0xfd05
constant XK_3270_EraseEOF (line 512) | XK_3270_EraseEOF = 0xfd06
constant XK_3270_EraseInput (line 513) | XK_3270_EraseInput = 0xfd07
constant XK_3270_Reset (line 514) | XK_3270_Reset = 0xfd08
constant XK_3270_Quit (line 515) | XK_3270_Quit = 0xfd09
constant XK_3270_PA1 (line 516) | XK_3270_PA1 = 0xfd0a
constant XK_3270_PA2 (line 517) | XK_3270_PA2 = 0xfd0b
constant XK_3270_PA3 (line 518) | XK_3270_PA3 = 0xfd0c
constant XK_3270_Test (line 519) | XK_3270_Test = 0xfd0d
constant XK_3270_Attn (line 520) | XK_3270_Attn = 0xfd0e
constant XK_3270_CursorBlink (line 521) | XK_3270_CursorBlink = 0xfd0f
constant XK_3270_AltCursor (line 522) | XK_3270_AltCursor = 0xfd10
constant XK_3270_KeyClick (line 523) | XK_3270_KeyClick = 0xfd11
constant XK_3270_Jump (line 524) | XK_3270_Jump = 0xfd12
constant XK_3270_Ident (line 525) | XK_3270_Ident = 0xfd13
constant XK_3270_Rule (line 526) | XK_3270_Rule = 0xfd14
constant XK_3270_Copy (line 527) | XK_3270_Copy = 0xfd15
constant XK_3270_Play (line 528) | XK_3270_Play = 0xfd16
constant XK_3270_Setup (line 529) | XK_3270_Setup = 0xfd17
constant XK_3270_Record (line 530) | XK_3270_Record = 0xfd18
constant XK_3270_ChangeScreen (line 531) | XK_3270_ChangeScreen = 0xfd19
constant XK_3270_DeleteWord (line 532) | XK_3270_DeleteWord = 0xfd1a
constant XK_3270_ExSelect (line 533) | XK_3270_ExSelect = 0xfd1b
constant XK_3270_CursorSelect (line 534) | XK_3270_CursorSelect = 0xfd1c
constant XK_3270_PrintScreen (line 535) | XK_3270_PrintScreen = 0xfd1d
constant XK_3270_Enter (line 536) | XK_3270_Enter = 0xfd1e
constant XK_space (line 545) | XK_space = 0x0020
constant XK_exclam (line 546) | XK_exclam = 0x0021
constant XK_quotedbl (line 547) | XK_quotedbl = 0x0022
constant XK_numbersign (line 548) | XK_numbersign = 0x0023
constant XK_dollar (line 549) | XK_dollar = 0x0024
constant XK_percent (line 550) | XK_percent = 0x0025
constant XK_ampersand (line 551) | XK_ampersand = 0x0026
constant XK_apostrophe (line 552) | XK_apostrophe = 0x0027
constant XK_quoteright (line 553) | XK_quoteright = 0x0027
constant XK_parenleft (line 554) | XK_parenleft = 0x0028
constant XK_parenright (line 555) | XK_parenright = 0x0029
constant XK_asterisk (line 556) | XK_asterisk = 0x002a
constant XK_plus (line 557) | XK_plus = 0x002b
constant XK_comma (line 558) | XK_comma = 0x002c
constant XK_minus (line 559) | XK_minus = 0x002d
constant XK_period (line 560) | XK_period = 0x002e
constant XK_slash (line 561) | XK_slash = 0x002f
constant XK_0 (line 562) | XK_0 = 0x0030
constant XK_1 (line 563) | XK_1 = 0x0031
constant XK_2 (line 564) | XK_2 = 0x0032
constant XK_3 (line 565) | XK_3 = 0x0033
constant XK_4 (line 566) | XK_4 = 0x0034
constant XK_5 (line 567) | XK_5 = 0x0035
constant XK_6 (line 568) | XK_6 = 0x0036
constant XK_7 (line 569) | XK_7 = 0x0037
constant XK_8 (line 570) | XK_8 = 0x0038
constant XK_9 (line 571) | XK_9 = 0x0039
constant XK_colon (line 572) | XK_colon = 0x003a
constant XK_semicolon (line 573) | XK_semicolon = 0x003b
constant XK_less (line 574) | XK_less = 0x003c
constant XK_equal (line 575) | XK_equal = 0x003d
constant XK_greater (line 576) | XK_greater = 0x003e
constant XK_question (line 577) | XK_question = 0x003f
constant XK_at (line 578) | XK_at = 0x0040
constant XK_A (line 579) | XK_A = 0x0041
constant XK_B (line 580) | XK_B = 0x0042
constant XK_C (line 581) | XK_C = 0x0043
constant XK_D (line 582) | XK_D = 0x0044
constant XK_E (line 583) | XK_E = 0x0045
constant XK_F (line 584) | XK_F = 0x0046
constant XK_G (line 585) | XK_G = 0x0047
constant XK_H (line 586) | XK_H = 0x0048
constant XK_I (line 587) | XK_I = 0x0049
constant XK_J (line 588) | XK_J = 0x004a
constant XK_K (line 589) | XK_K = 0x004b
constant XK_L (line 590) | XK_L = 0x004c
constant XK_M (line 591) | XK_M = 0x004d
constant XK_N (line 592) | XK_N = 0x004e
constant XK_O (line 593) | XK_O = 0x004f
constant XK_P (line 594) | XK_P = 0x0050
constant XK_Q (line 595) | XK_Q = 0x0051
constant XK_R (line 596) | XK_R = 0x0052
constant XK_S (line 597) | XK_S = 0x0053
constant XK_T (line 598) | XK_T = 0x0054
constant XK_U (line 599) | XK_U = 0x0055
constant XK_V (line 600) | XK_V = 0x0056
constant XK_W (line 601) | XK_W = 0x0057
constant XK_X (line 602) | XK_X = 0x0058
constant XK_Y (line 603) | XK_Y = 0x0059
constant XK_Z (line 604) | XK_Z = 0x005a
constant XK_bracketleft (line 605) | XK_bracketleft = 0x005b
constant XK_backslash (line 606) | XK_backslash = 0x005c
constant XK_bracketright (line 607) | XK_bracketright = 0x005d
constant XK_asciicircum (line 608) | XK_asciicircum = 0x005e
constant XK_underscore (line 609) | XK_underscore = 0x005f
constant XK_grave (line 610) | XK_grave = 0x0060
constant XK_quoteleft (line 611) | XK_quoteleft = 0x0060
constant XK_a (line 612) | XK_a = 0x0061
constant XK_b (line 613) | XK_b = 0x0062
constant XK_c (line 614) | XK_c = 0x0063
constant XK_d (line 615) | XK_d = 0x0064
constant XK_e (line 616) | XK_e = 0x0065
constant XK_f (line 617) | XK_f = 0x0066
constant XK_g (line 618) | XK_g = 0x0067
constant XK_h (line 619) | XK_h = 0x0068
constant XK_i (line 620) | XK_i = 0x0069
constant XK_j (line 621) | XK_j = 0x006a
constant XK_k (line 622) | XK_k = 0x006b
constant XK_l (line 623) | XK_l = 0x006c
constant XK_m (line 624) | XK_m = 0x006d
constant XK_n (line 625) | XK_n = 0x006e
constant XK_o (line 626) | XK_o = 0x006f
constant XK_p (line 627) | XK_p = 0x0070
constant XK_q (line 628) | XK_q = 0x0071
constant XK_r (line 629) | XK_r = 0x0072
constant XK_s (line 630) | XK_s = 0x0073
constant XK_t (line 631) | XK_t = 0x0074
constant XK_u (line 632) | XK_u = 0x0075
constant XK_v (line 633) | XK_v = 0x0076
constant XK_w (line 634) | XK_w = 0x0077
constant XK_x (line 635) | XK_x = 0x0078
constant XK_y (line 636) | XK_y = 0x0079
constant XK_z (line 637) | XK_z = 0x007a
constant XK_braceleft (line 638) | XK_braceleft = 0x007b
constant XK_bar (line 639) | XK_bar = 0x007c
constant XK_braceright (line 640) | XK_braceright = 0x007d
constant XK_asciitilde (line 641) | XK_asciitilde = 0x007e
constant XK_nobreakspace (line 643) | XK_nobreakspace = 0x00a0
constant XK_exclamdown (line 644) | XK_exclamdown = 0x00a1
constant XK_cent (line 645) | XK_cent = 0x00a2
constant XK_sterling (line 646) | XK_sterling = 0x00a3
constant XK_currency (line 647) | XK_currency = 0x00a4
constant XK_yen (line 648) | XK_yen = 0x00a5
constant XK_brokenbar (line 649) | XK_brokenbar = 0x00a6
constant XK_section (line 650) | XK_section = 0x00a7
constant XK_diaeresis (line 651) | XK_diaeresis = 0x00a8
constant XK_copyright (line 652) | XK_copyright = 0x00a9
constant XK_ordfeminine (line 653) | XK_ordfeminine = 0x00aa
constant XK_guillemotleft (line 654) | XK_guillemotleft = 0x00ab
constant XK_notsign (line 655) | XK_notsign = 0x00ac
constant XK_hyphen (line 656) | XK_hyphen = 0x00ad
constant XK_registered (line 657) | XK_registered = 0x00ae
constant XK_macron (line 658) | XK_macron = 0x00af
constant XK_degree (line 659) | XK_degree = 0x00b0
constant XK_plusminus (line 660) | XK_plusminus = 0x00b1
constant XK_twosuperior (line 661) | XK_twosuperior = 0x00b2
constant XK_threesuperior (line 662) | XK_threesuperior = 0x00b3
constant XK_acute (line 663) | XK_acute = 0x00b4
constant XK_mu (line 664) | XK_mu = 0x00b5
constant XK_paragraph (line 665) | XK_paragraph = 0x00b6
constant XK_periodcentered (line 666) | XK_periodcentered = 0x00b7
constant XK_cedilla (line 667) | XK_cedilla = 0x00b8
constant XK_onesuperior (line 668) | XK_onesuperior = 0x00b9
constant XK_masculine (line 669) | XK_masculine = 0x00ba
constant XK_guillemotright (line 670) | XK_guillemotright = 0x00bb
constant XK_onequarter (line 671) | XK_onequarter = 0x00bc
constant XK_onehalf (line 672) | XK_onehalf = 0x00bd
constant XK_threequarters (line 673) | XK_threequarters = 0x00be
constant XK_questiondown (line 674) | XK_questiondown = 0x00bf
constant XK_Agrave (line 675) | XK_Agrave = 0x00c0
constant XK_Aacute (line 676) | XK_Aacute = 0x00c1
constant XK_Acircumflex (line 677) | XK_Acircumflex = 0x00c2
constant XK_Atilde (line 678) | XK_Atilde = 0x00c3
constant XK_Adiaeresis (line 679) | XK_Adiaeresis = 0x00c4
constant XK_Aring (line 680) | XK_Aring = 0x00c5
constant XK_AE (line 681) | XK_AE = 0x00c6
constant XK_Ccedilla (line 682) | XK_Ccedilla = 0x00c7
constant XK_Egrave (line 683) | XK_Egrave = 0x00c8
constant XK_Eacute (line 684) | XK_Eacute = 0x00c9
constant XK_Ecircumflex (line 685) | XK_Ecircumflex = 0x00ca
constant XK_Ediaeresis (line 686) | XK_Ediaeresis = 0x00cb
constant XK_Igrave (line 687) | XK_Igrave = 0x00cc
constant XK_Iacute (line 688) | XK_Iacute = 0x00cd
constant XK_Icircumflex (line 689) | XK_Icircumflex = 0x00ce
constant XK_Idiaeresis (line 690) | XK_Idiaeresis = 0x00cf
constant XK_ETH (line 691) | XK_ETH = 0x00d0
constant XK_Eth (line 692) | XK_Eth = 0x00d0
constant XK_Ntilde (line 693) | XK_Ntilde = 0x00d1
constant XK_Ograve (line 694) | XK_Ograve = 0x00d2
constant XK_Oacute (line 695) | XK_Oacute = 0x00d3
constant XK_Ocircumflex (line 696) | XK_Ocircumflex = 0x00d4
constant XK_Otilde (line 697) | XK_Otilde = 0x00d5
constant XK_Odiaeresis (line 698) | XK_Odiaeresis = 0x00d6
constant XK_multiply (line 699) | XK_multiply = 0x00d7
constant XK_Oslash (line 700) | XK_Oslash = 0x00d8
constant XK_Ooblique (line 701) | XK_Ooblique = 0x00d8
constant XK_Ugrave (line 702) | XK_Ugrave = 0x00d9
constant XK_Uacute (line 703) | XK_Uacute = 0x00da
constant XK_Ucircumflex (line 704) | XK_Ucircumflex = 0x00db
constant XK_Udiaeresis (line 705) | XK_Udiaeresis = 0x00dc
constant XK_Yacute (line 706) | XK_Yacute = 0x00dd
constant XK_THORN (line 707) | XK_THORN = 0x00de
constant XK_Thorn (line 708) | XK_Thorn = 0x00de
constant XK_ssharp (line 709) | XK_ssharp = 0x00df
constant XK_agrave (line 710) | XK_agrave = 0x00e0
constant XK_aacute (line 711) | XK_aacute = 0x00e1
constant XK_acircumflex (line 712) | XK_acircumflex = 0x00e2
constant XK_atilde (line 713) | XK_atilde = 0x00e3
constant XK_adiaeresis (line 714) | XK_adiaeresis = 0x00e4
constant XK_aring (line 715) | XK_aring = 0x00e5
constant XK_ae (line 716) | XK_ae = 0x00e6
constant XK_ccedilla (line 717) | XK_ccedilla = 0x00e7
constant XK_egrave (line 718) | XK_egrave = 0x00e8
constant XK_eacute (line 719) | XK_eacute = 0x00e9
constant XK_ecircumflex (line 720) | XK_ecircumflex = 0x00ea
constant XK_ediaeresis (line 721) | XK_ediaeresis = 0x00eb
constant XK_igrave (line 722) | XK_igrave = 0x00ec
constant XK_iacute (line 723) | XK_iacute = 0x00ed
constant XK_icircumflex (line 724) | XK_icircumflex = 0x00ee
constant XK_idiaeresis (line 725) | XK_idiaeresis = 0x00ef
constant XK_eth (line 726) | XK_eth = 0x00f0
constant XK_ntilde (line 727) | XK_ntilde = 0x00f1
constant XK_ograve (line 728) | XK_ograve = 0x00f2
constant XK_oacute (line 729) | XK_oacute = 0x00f3
constant XK_ocircumflex (line 730) | XK_ocircumflex = 0x00f4
constant XK_otilde (line 731) | XK_otilde = 0x00f5
constant XK_odiaeresis (line 732) | XK_odiaeresis = 0x00f6
constant XK_division (line 733) | XK_division = 0x00f7
constant XK_oslash (line 734) | XK_oslash = 0x00f8
constant XK_ooblique (line 735) | XK_ooblique = 0x00f8
constant XK_ugrave (line 736) | XK_ugrave = 0x00f9
constant XK_uacute (line 737) | XK_uacute = 0x00fa
constant XK_ucircumflex (line 738) | XK_ucircumflex = 0x00fb
constant XK_udiaeresis (line 739) | XK_udiaeresis = 0x00fc
constant XK_yacute (line 740) | XK_yacute = 0x00fd
constant XK_thorn (line 741) | XK_thorn = 0x00fe
constant XK_ydiaeresis (line 742) | XK_ydiaeresis = 0x00ff
constant XK_Aogonek (line 751) | XK_Aogonek = 0x01a1
constant XK_breve (line 752) | XK_breve = 0x01a2
constant XK_Lstroke (line 753) | XK_Lstroke = 0x01a3
constant XK_Lcaron (line 754) | XK_Lcaron = 0x01a5
constant XK_Sacute (line 755) | XK_Sacute = 0x01a6
constant XK_Scaron (line 756) | XK_Scaron = 0x01a9
constant XK_Scedilla (line 757) | XK_Scedilla = 0x01aa
constant XK_Tcaron (line 758) | XK_Tcaron = 0x01ab
constant XK_Zacute (line 759) | XK_Zacute = 0x01ac
constant XK_Zcaron (line 760) | XK_Zcaron = 0x01ae
constant XK_Zabovedot (line 761) | XK_Zabovedot = 0x01af
constant XK_aogonek (line 762) | XK_aogonek = 0x01b1
constant XK_ogonek (line 763) | XK_ogonek = 0x01b2
constant XK_lstroke (line 764) | XK_lstroke = 0x01b3
constant XK_lcaron (line 765) | XK_lcaron = 0x01b5
constant XK_sacute (line 766) | XK_sacute = 0x01b6
constant XK_caron (line 767) | XK_caron = 0x01b7
constant XK_scaron (line 768) | XK_scaron = 0x01b9
constant XK_scedilla (line 769) | XK_scedilla = 0x01ba
constant XK_tcaron (line 770) | XK_tcaron = 0x01bb
constant XK_zacute (line 771) | XK_zacute = 0x01bc
constant XK_doubleacute (line 772) | XK_doubleacute = 0x01bd
constant XK_zcaron (line 773) | XK_zcaron = 0x01be
constant XK_zabovedot (line 774) | XK_zabovedot = 0x01bf
constant XK_Racute (line 775) | XK_Racute = 0x01c0
constant XK_Abreve (line 776) | XK_Abreve = 0x01c3
constant XK_Lacute (line 777) | XK_Lacute = 0x01c5
constant XK_Cacute (line 778) | XK_Cacute = 0x01c6
constant XK_Ccaron (line 779) | XK_Ccaron = 0x01c8
constant XK_Eogonek (line 780) | XK_Eogonek = 0x01ca
constant XK_Ecaron (line 781) | XK_Ecaron = 0x01cc
constant XK_Dcaron (line 782) | XK_Dcaron = 0x01cf
constant XK_Dstroke (line 783) | XK_Dstroke = 0x01d0
constant XK_Nacute (line 784) | XK_Nacute = 0x01d1
constant XK_Ncaron (line 785) | XK_Ncaron = 0x01d2
constant XK_Odoubleacute (line 786) | XK_Odoubleacute = 0x01d5
constant XK_Rcaron (line 787) | XK_Rcaron = 0x01d8
constant XK_Uring (line 788) | XK_Uring = 0x01d9
constant XK_Udoubleacute (line 789) | XK_Udoubleacute = 0x01db
constant XK_Tcedilla (line 790) | XK_Tcedilla = 0x01de
constant XK_racute (line 791) | XK_racute = 0x01e0
constant XK_abreve (line 792) | XK_abreve = 0x01e3
constant XK_lacute (line 793) | XK_lacute = 0x01e5
constant XK_cacute (line 794) | XK_cacute = 0x01e6
constant XK_ccaron (line 795) | XK_ccaron = 0x01e8
constant XK_eogonek (line 796) | XK_eogonek = 0x01ea
constant XK_ecaron (line 797) | XK_ecaron = 0x01ec
constant XK_dcaron (line 798) | XK_dcaron = 0x01ef
constant XK_dstroke (line 799) | XK_dstroke = 0x01f0
constant XK_nacute (line 800) | XK_nacute = 0x01f1
constant XK_ncaron (line 801) | XK_ncaron = 0x01f2
constant XK_odoubleacute (line 802) | XK_odoubleacute = 0x01f5
constant XK_rcaron (line 803) | XK_rcaron = 0x01f8
constant XK_uring (line 804) | XK_uring = 0x01f9
constant XK_udoubleacute (line 805) | XK_udoubleacute = 0x01fb
constant XK_tcedilla (line 806) | XK_tcedilla = 0x01fe
constant XK_abovedot (line 807) | XK_abovedot = 0x01ff
constant XK_Hstroke (line 816) | XK_Hstroke = 0x02a1
constant XK_Hcircumflex (line 817) | XK_Hcircumflex = 0x02a6
constant XK_Iabovedot (line 818) | XK_Iabovedot = 0x02a9
constant XK_Gbreve (line 819) | XK_Gbreve = 0x02ab
constant XK_Jcircumflex (line 820) | XK_Jcircumflex = 0x02ac
constant XK_hstroke (line 821) | XK_hstroke = 0x02b1
constant XK_hcircumflex (line 822) | XK_hcircumflex = 0x02b6
constant XK_idotless (line 823) | XK_idotless = 0x02b9
constant XK_gbreve (line 824) | XK_gbreve = 0x02bb
constant XK_jcircumflex (line 825) | XK_jcircumflex = 0x02bc
constant XK_Cabovedot (line 826) | XK_Cabovedot = 0x02c5
constant XK_Ccircumflex (line 827) | XK_Ccircumflex = 0x02c6
constant XK_Gabovedot (line 828) | XK_Gabovedot = 0x02d5
constant XK_Gcircumflex (line 829) | XK_Gcircumflex = 0x02d8
constant XK_Ubreve (line 830) | XK_Ubreve = 0x02dd
constant XK_Scircumflex (line 831) | XK_Scircumflex = 0x02de
constant XK_cabovedot (line 832) | XK_cabovedot = 0x02e5
constant XK_ccircumflex (line 833) | XK_ccircumflex = 0x02e6
constant XK_gabovedot (line 834) | XK_gabovedot = 0x02f5
constant XK_gcircumflex (line 835) | XK_gcircumflex = 0x02f8
constant XK_ubreve (line 836) | XK_ubreve = 0x02fd
constant XK_scircumflex (line 837) | XK_scircumflex = 0x02fe
constant XK_kra (line 847) | XK_kra = 0x03a2
constant XK_kappa (line 848) | XK_kappa = 0x03a2
constant XK_Rcedilla (line 849) | XK_Rcedilla = 0x03a3
constant XK_Itilde (line 850) | XK_Itilde = 0x03a5
constant XK_Lcedilla (line 851) | XK_Lcedilla = 0x03a6
constant XK_Emacron (line 852) | XK_Emacron = 0x03aa
constant XK_Gcedilla (line 853) | XK_Gcedilla = 0x03ab
constant XK_Tslash (line 854) | XK_Tslash = 0x03ac
constant XK_rcedilla (line 855) | XK_rcedilla = 0x03b3
constant XK_itilde (line 856) | XK_itilde = 0x03b5
constant XK_lcedilla (line 857) | XK_lcedilla = 0x03b6
constant XK_emacron (line 858) | XK_emacron = 0x03ba
constant XK_gcedilla (line 859) | XK_gcedilla = 0x03bb
constant XK_tslash (line 860) | XK_tslash = 0x03bc
constant XK_ENG (line 861) | XK_ENG = 0x03bd
constant XK_eng (line 862) | XK_eng = 0x03bf
constant XK_Amacron (line 863) | XK_Amacron = 0x03c0
constant XK_Iogonek (line 864) | XK_Iogonek = 0x03c7
constant XK_Eabovedot (line 865) | XK_Eabovedot = 0x03cc
constant XK_Imacron (line 866) | XK_Imacron = 0x03cf
constant XK_Ncedilla (line 867) | XK_Ncedilla = 0x03d1
constant XK_Omacron (line 868) | XK_Omacron = 0x03d2
constant XK_Kcedilla (line 869) | XK_Kcedilla = 0x03d3
constant XK_Uogonek (line 870) | XK_Uogonek = 0x03d9
constant XK_Utilde (line 871) | XK_Utilde = 0x03dd
constant XK_Umacron (line 872) | XK_Umacron = 0x03de
constant XK_amacron (line 873) | XK_amacron = 0x03e0
constant XK_iogonek (line 874) | XK_iogonek = 0x03e7
constant XK_eabovedot (line 875) | XK_eabovedot = 0x03ec
constant XK_imacron (line 876) | XK_imacron = 0x03ef
constant XK_ncedilla (line 877) | XK_ncedilla = 0x03f1
constant XK_omacron (line 878) | XK_omacron = 0x03f2
constant XK_kcedilla (line 879) | XK_kcedilla = 0x03f3
constant XK_uogonek (line 880) | XK_uogonek = 0x03f9
constant XK_utilde (line 881) | XK_utilde = 0x03fd
constant XK_umacron (line 882) | XK_umacron = 0x03fe
constant XK_Wcircumflex (line 889) | XK_Wcircumflex = 0x1000174
constant XK_wcircumflex (line 890) | XK_wcircumflex = 0x1000175
constant XK_Ycircumflex (line 891) | XK_Ycircumflex = 0x1000176
constant XK_ycircumflex (line 892) | XK_ycircumflex = 0x1000177
constant XK_Babovedot (line 893) | XK_Babovedot = 0x1001e02
constant XK_babovedot (line 894) | XK_babovedot = 0x1001e03
constant XK_Dabovedot (line 895) | XK_Dabovedot = 0x1001e0a
constant XK_dabovedot (line 896) | XK_dabovedot = 0x1001e0b
constant XK_Fabovedot (line 897) | XK_Fabovedot = 0x1001e1e
constant XK_fabovedot (line 898) | XK_fabovedot = 0x1001e1f
constant XK_Mabovedot (line 899) | XK_Mabovedot = 0x1001e40
constant XK_mabovedot (line 900) | XK_mabovedot = 0x1001e41
constant XK_Pabovedot (line 901) | XK_Pabovedot = 0x1001e56
constant XK_pabovedot (line 902) | XK_pabovedot = 0x1001e57
constant XK_Sabovedot (line 903) | XK_Sabovedot = 0x1001e60
constant XK_sabovedot (line 904) | XK_sabovedot = 0x1001e61
constant XK_Tabovedot (line 905) | XK_Tabovedot = 0x1001e6a
constant XK_tabovedot (line 906) | XK_tabovedot = 0x1001e6b
constant XK_Wgrave (line 907) | XK_Wgrave = 0x1001e80
constant XK_wgrave (line 908) | XK_wgrave = 0x1001e81
constant XK_Wacute (line 909) | XK_Wacute = 0x1001e82
constant XK_wacute (line 910) | XK_wacute = 0x1001e83
constant XK_Wdiaeresis (line 911) | XK_Wdiaeresis = 0x1001e84
constant XK_wdiaeresis (line 912) | XK_wdiaeresis = 0x1001e85
constant XK_Ygrave (line 913) | XK_Ygrave = 0x1001ef2
constant XK_ygrave (line 914) | XK_ygrave = 0x1001ef3
constant XK_OE (line 923) | XK_OE = 0x13bc
constant XK_oe (line 924) | XK_oe = 0x13bd
constant XK_Ydiaeresis (line 925) | XK_Ydiaeresis = 0x13be
constant XK_overline (line 934) | XK_overline = 0x047e
constant XK_kana_fullstop (line 935) | XK_kana_fullstop = 0x04a1
constant XK_kana_openingbracket (line 936) | XK_kana_openingbracket = 0x04a2
constant XK_kana_closingbracket (line 937) | XK_kana_closingbracket = 0x04a3
constant XK_kana_comma (line 938) | XK_kana_comma = 0x04a4
constant XK_kana_conjunctive (line 939) | XK_kana_conjunctive = 0x04a5
constant XK_kana_middledot (line 940) | XK_kana_middledot = 0x04a5
constant XK_kana_WO (line 941) | XK_kana_WO = 0x04a6
constant XK_kana_a (line 942) | XK_kana_a = 0x04a7
constant XK_kana_i (line 943) | XK_kana_i = 0x04a8
constant XK_kana_u (line 944) | XK_kana_u = 0x04a9
constant XK_kana_e (line 945) | XK_kana_e = 0x04aa
constant XK_kana_o (line 946) | XK_kana_o = 0x04ab
constant XK_kana_ya (line 947) | XK_kana_ya = 0x04ac
constant XK_kana_yu (line 948) | XK_kana_yu = 0x04ad
constant XK_kana_yo (line 949) | XK_kana_yo = 0x04ae
constant XK_kana_tsu (line 950) | XK_kana_tsu = 0x04af
constant XK_kana_tu (line 951) | XK_kana_tu = 0x04af
constant XK_prolongedsound (line 952) | XK_prolongedsound = 0x04b0
constant XK_kana_A (line 953) | XK_kana_A = 0x04b1
constant XK_kana_I (line 954) | XK_kana_I = 0x04b2
constant XK_kana_U (line 955) | XK_kana_U = 0x04b3
constant XK_kana_E (line 956) | XK_kana_E = 0x04b4
constant XK_kana_O (line 957) | XK_kana_O = 0x04b5
constant XK_kana_KA (line 958) | XK_kana_KA = 0x04b6
constant XK_kana_KI (line 959) | XK_kana_KI = 0x04b7
constant XK_kana_KU (line 960) | XK_kana_KU = 0x04b8
constant XK_kana_KE (line 961) | XK_kana_KE = 0x04b9
constant XK_kana_KO (line 962) | XK_kana_KO = 0x04ba
constant XK_kana_SA (line 963) | XK_kana_SA = 0x04bb
constant XK_kana_SHI (line 964) | XK_kana_SHI = 0x04bc
constant XK_kana_SU (line 965) | XK_kana_SU = 0x04bd
constant XK_kana_SE (line 966) | XK_kana_SE = 0x04be
constant XK_kana_SO (line 967) | XK_kana_SO = 0x04bf
constant XK_kana_TA (line 968) | XK_kana_TA = 0x04c0
constant XK_kana_CHI (line 969) | XK_kana_CHI = 0x04c1
constant XK_kana_TI (line 970) | XK_kana_TI = 0x04c1
constant XK_kana_TSU (line 971) | XK_kana_TSU = 0x04c2
constant XK_kana_TU (line 972) | XK_kana_TU = 0x04c2
constant XK_kana_TE (line 973) | XK_kana_TE = 0x04c3
constant XK_kana_TO (line 974) | XK_kana_TO = 0x04c4
constant XK_kana_NA (line 975) | XK_kana_NA = 0x04c5
constant XK_kana_NI (line 976) | XK_kana_NI = 0x04c6
constant XK_kana_NU (line 977) | XK_kana_NU = 0x04c7
constant XK_kana_NE (line 978) | XK_kana_NE = 0x04c8
constant XK_kana_NO (line 979) | XK_kana_NO = 0x04c9
constant XK_kana_HA (line 980) | XK_kana_HA = 0x04ca
constant XK_kana_HI (line 981) | XK_kana_HI = 0x04cb
constant XK_kana_FU (line 982) | XK_kana_FU = 0x04cc
constant XK_kana_HU (line 983) | XK_kana_HU = 0x04cc
constant XK_kana_HE (line 984) | XK_kana_HE = 0x04cd
constant XK_kana_HO (line 985) | XK_kana_HO = 0x04ce
constant XK_kana_MA (line 986) | XK_kana_MA = 0x04cf
constant XK_kana_MI (line 987) | XK_kana_MI = 0x04d0
constant XK_kana_MU (line 988) | XK_kana_MU = 0x04d1
constant XK_kana_ME (line 989) | XK_kana_ME = 0x04d2
constant XK_kana_MO (line 990) | XK_kana_MO = 0x04d3
constant XK_kana_YA (line 991) | XK_kana_YA = 0x04d4
constant XK_kana_YU (line 992) | XK_kana_YU = 0x04d5
constant XK_kana_YO (line 993) | XK_kana_YO = 0x04d6
constant XK_kana_RA (line 994) | XK_kana_RA = 0x04d7
constant XK_kana_RI (line 995) | XK_kana_RI = 0x04d8
constant XK_kana_RU (line 996) | XK_kana_RU = 0x04d9
constant XK_kana_RE (line 997) | XK_kana_RE = 0x04da
constant XK_kana_RO (line 998) | XK_kana_RO = 0x04db
constant XK_kana_WA (line 999) | XK_kana_WA = 0x04dc
constant XK_kana_N (line 1000) | XK_kana_N = 0x04dd
constant XK_voicedsound (line 1001) | XK_voicedsound = 0x04de
constant XK_semivoicedsound (line 1002) | XK_semivoicedsound = 0x04df
constant XK_kana_switch (line 1003) | XK_kana_switch = 0xff7e
constant XK_Farsi_0 (line 1012) | XK_Farsi_0 = 0x10006f0
constant XK_Farsi_1 (line 1013) | XK_Farsi_1 = 0x10006f1
constant XK_Farsi_2 (line 1014) | XK_Farsi_2 = 0x10006f2
constant XK_Farsi_3 (line 1015) | XK_Farsi_3 = 0x10006f3
constant XK_Farsi_4 (line 1016) | XK_Farsi_4 = 0x10006f4
constant XK_Farsi_5 (line 1017) | XK_Farsi_5 = 0x10006f5
constant XK_Farsi_6 (line 1018) | XK_Farsi_6 = 0x10006f6
constant XK_Farsi_7 (line 1019) | XK_Farsi_7 = 0x10006f7
constant XK_Farsi_8 (line 1020) | XK_Farsi_8 = 0x10006f8
constant XK_Farsi_9 (line 1021) | XK_Farsi_9 = 0x10006f9
constant XK_Arabic_percent (line 1022) | XK_Arabic_percent = 0x100066a
constant XK_Arabic_superscript_alef (line 1023) | XK_Arabic_superscript_alef = 0x1000670
constant XK_Arabic_tteh (line 1024) | XK_Arabic_tteh = 0x1000679
constant XK_Arabic_peh (line 1025) | XK_Arabic_peh = 0x100067e
constant XK_Arabic_tcheh (line 1026) | XK_Arabic_tcheh = 0x1000686
constant XK_Arabic_ddal (line 1027) | XK_Arabic_ddal = 0x1000688
constant XK_Arabic_rreh (line 1028) | XK_Arabic_rreh = 0x1000691
constant XK_Arabic_comma (line 1029) | XK_Arabic_comma = 0x05ac
constant XK_Arabic_fullstop (line 1030) | XK_Arabic_fullstop = 0x10006d4
constant XK_Arabic_0 (line 1031) | XK_Arabic_0 = 0x1000660
constant XK_Arabic_1 (line 1032) | XK_Arabic_1 = 0x1000661
constant XK_Arabic_2 (line 1033) | XK_Arabic_2 = 0x1000662
constant XK_Arabic_3 (line 1034) | XK_Arabic_3 = 0x1000663
constant XK_Arabic_4 (line 1035) | XK_Arabic_4 = 0x1000664
constant XK_Arabic_5 (line 1036) | XK_Arabic_5 = 0x1000665
constant XK_Arabic_6 (line 1037) | XK_Arabic_6 = 0x1000666
constant XK_Arabic_7 (line 1038) | XK_Arabic_7 = 0x1000667
constant XK_Arabic_8 (line 1039) | XK_Arabic_8 = 0x1000668
constant XK_Arabic_9 (line 1040) | XK_Arabic_9 = 0x1000669
constant XK_Arabic_semicolon (line 1041) | XK_Arabic_semicolon = 0x05bb
constant XK_Arabic_question_mark (line 1042) | XK_Arabic_question_mark = 0x05bf
constant XK_Arabic_hamza (line 1043) | XK_Arabic_hamza = 0x05c1
constant XK_Arabic_maddaonalef (line 1044) | XK_Arabic_maddaonalef = 0x05c2
constant XK_Arabic_hamzaonalef (line 1045) | XK_Arabic_hamzaonalef = 0x05c3
constant XK_Arabic_hamzaonwaw (line 1046) | XK_Arabic_hamzaonwaw = 0x05c4
constant XK_Arabic_hamzaunderalef (line 1047) | XK_Arabic_hamzaunderalef = 0x05c5
constant XK_Arabic_hamzaonyeh (line 1048) | XK_Arabic_hamzaonyeh = 0x05c6
constant XK_Arabic_alef (line 1049) | XK_Arabic_alef = 0x05c7
constant XK_Arabic_beh (line 1050) | XK_Arabic_beh = 0x05c8
constant XK_Arabic_tehmarbuta (line 1051) | XK_Arabic_tehmarbuta = 0x05c9
constant XK_Arabic_teh (line 1052) | XK_Arabic_teh = 0x05ca
constant XK_Arabic_theh (line 1053) | XK_Arabic_theh = 0x05cb
constant XK_Arabic_jeem (line 1054) | XK_Arabic_jeem = 0x05cc
constant XK_Arabic_hah (line 1055) | XK_Arabic_hah = 0x05cd
constant XK_Arabic_khah (line 1056) | XK_Arabic_khah = 0x05ce
constant XK_Arabic_dal (line 1057) | XK_Arabic_dal = 0x05cf
constant XK_Arabic_thal (line 1058) | XK_Arabic_thal = 0x05d0
constant XK_Arabic_ra (line 1059) | XK_Arabic_ra = 0x05d1
constant XK_Arabic_zain (line 1060) | XK_Arabic_zain = 0x05d2
constant XK_Arabic_seen (line 1061) | XK_Arabic_seen = 0x05d3
constant XK_Arabic_sheen (line 1062) | XK_Arabic_sheen = 0x05d4
constant XK_Arabic_sad (line 1063) | XK_Arabic_sad = 0x05d5
constant XK_Arabic_dad (line 1064) | XK_Arabic_dad = 0x05d6
constant XK_Arabic_tah (line 1065) | XK_Arabic_tah = 0x05d7
constant XK_Arabic_zah (line 1066) | XK_Arabic_zah = 0x05d8
constant XK_Arabic_ain (line 1067) | XK_Arabic_ain = 0x05d9
constant XK_Arabic_ghain (line 1068) | XK_Arabic_ghain = 0x05da
constant XK_Arabic_tatweel (line 1069) | XK_Arabic_tatweel = 0x05e0
constant XK_Arabic_feh (line 1070) | XK_Arabic_feh = 0x05e1
constant XK_Arabic_qaf (line 1071) | XK_Arabic_qaf = 0x05e2
constant XK_Arabic_kaf (line 1072) | XK_Arabic_kaf = 0x05e3
constant XK_Arabic_lam (line 1073) | XK_Arabic_lam = 0x05e4
constant XK_Arabic_meem (line 1074) | XK_Arabic_meem = 0x05e5
constant XK_Arabic_noon (line 1075) | XK_Arabic_noon = 0x05e6
constant XK_Arabic_ha (line 1076) | XK_Arabic_ha = 0x05e7
constant XK_Arabic_heh (line 1077) | XK_Arabic_heh = 0x05e7
constant XK_Arabic_waw (line 1078) | XK_Arabic_waw = 0x05e8
constant XK_Arabic_alefmaksura (line 1079) | XK_Arabic_alefmaksura = 0x05e9
constant XK_Arabic_yeh (line 1080) | XK_Arabic_yeh = 0x05ea
constant XK_Arabic_fathatan (line 1081) | XK_Arabic_fathatan = 0x05eb
constant XK_Arabic_dammatan (line 1082) | XK_Arabic_dammatan = 0x05ec
constant XK_Arabic_kasratan (line 1083) | XK_Arabic_kasratan = 0x05ed
constant XK_Arabic_fatha (line 1084) | XK_Arabic_fatha = 0x05ee
constant XK_Arabic_damma (line 1085) | XK_Arabic_damma = 0x05ef
constant XK_Arabic_kasra (line 1086) | XK_Arabic_kasra = 0x05f0
constant XK_Arabic_shadda (line 1087) | XK_Arabic_shadda = 0x05f1
constant XK_Arabic_sukun (line 1088) | XK_Arabic_sukun = 0x05f2
constant XK_Arabic_madda_above (line 1089) | XK_Arabic_madda_above = 0x1000653
constant XK_Arabic_hamza_above (line 1090) | XK_Arabic_hamza_above = 0x1000654
constant XK_Arabic_hamza_below (line 1091) | XK_Arabic_hamza_below = 0x1000655
constant XK_Arabic_jeh (line 1092) | XK_Arabic_jeh = 0x1000698
constant XK_Arabic_veh (line 1093) | XK_Arabic_veh = 0x10006a4
constant XK_Arabic_keheh (line 1094) | XK_Arabic_keheh = 0x10006a9
constant XK_Arabic_gaf (line 1095) | XK_Arabic_gaf = 0x10006af
constant XK_Arabic_noon_ghunna (line 1096) | XK_Arabic_noon_ghunna = 0x10006ba
constant XK_Arabic_heh_doachashmee (line 1097) | XK_Arabic_heh_doachashmee = 0x10006be
constant XK_Farsi_yeh (line 1098) | XK_Farsi_yeh = 0x10006cc
constant XK_Arabic_farsi_yeh (line 1099) | XK_Arabic_farsi_yeh = 0x10006cc
constant XK_Arabic_yeh_baree (line 1100) | XK_Arabic_yeh_baree = 0x10006d2
constant XK_Arabic_heh_goal (line 1101) | XK_Arabic_heh_goal = 0x10006c1
constant XK_Arabic_switch (line 1102) | XK_Arabic_switch = 0xff7e
constant XK_Cyrillic_GHE_bar (line 1110) | XK_Cyrillic_GHE_bar = 0x1000492
constant XK_Cyrillic_ghe_bar (line 1111) | XK_Cyrillic_ghe_bar = 0x1000493
constant XK_Cyrillic_ZHE_descender (line 1112) | XK_Cyrillic_ZHE_descender = 0x1000496
constant XK_Cyrillic_zhe_descender (line 1113) | XK_Cyrillic_zhe_descender = 0x1000497
constant XK_Cyrillic_KA_descender (line 1114) | XK_Cyrillic_KA_descender = 0x100049a
constant XK_Cyrillic_ka_descender (line 1115) | XK_Cyrillic_ka_descender = 0x100049b
constant XK_Cyrillic_KA_vertstroke (line 1116) | XK_Cyrillic_KA_vertstroke = 0x100049c
constant XK_Cyrillic_ka_vertstroke (line 1117) | XK_Cyrillic_ka_vertstroke = 0x100049d
constant XK_Cyrillic_EN_descender (line 1118) | XK_Cyrillic_EN_descender = 0x10004a2
constant XK_Cyrillic_en_descender (line 1119) | XK_Cyrillic_en_descender = 0x10004a3
constant XK_Cyrillic_U_straight (line 1120) | XK_Cyrillic_U_straight = 0x10004ae
constant XK_Cyrillic_u_straight (line 1121) | XK_Cyrillic_u_straight = 0x10004af
constant XK_Cyrillic_U_straight_bar (line 1122) | XK_Cyrillic_U_straight_bar = 0x10004b0
constant XK_Cyrillic_u_straight_bar (line 1123) | XK_Cyrillic_u_straight_bar = 0x10004b1
constant XK_Cyrillic_HA_descender (line 1124) | XK_Cyrillic_HA_descender = 0x10004b2
constant XK_Cyrillic_ha_descender (line 1125) | XK_Cyrillic_ha_descender = 0x10004b3
constant XK_Cyrillic_CHE_descender (line 1126) | XK_Cyrillic_CHE_descender = 0x10004b6
constant XK_Cyrillic_che_descender (line 1127) | XK_Cyrillic_che_descender = 0x10004b7
constant XK_Cyrillic_CHE_vertstroke (line 1128) | XK_Cyrillic_CHE_vertstroke = 0x10004b8
constant XK_Cyrillic_che_vertstroke (line 1129) | XK_Cyrillic_che_vertstroke = 0x10004b9
constant XK_Cyrillic_SHHA (line 1130) | XK_Cyrillic_SHHA = 0x10004ba
constant XK_Cyrillic_shha (line 1131) | XK_Cyrillic_shha = 0x10004bb
constant XK_Cyrillic_SCHWA (line 1133) | XK_Cyrillic_SCHWA = 0x10004d8
constant XK_Cyrillic_schwa (line 1134) | XK_Cyrillic_schwa = 0x10004d9
constant XK_Cyrillic_I_macron (line 1135) | XK_Cyrillic_I_macron = 0x10004e2
constant XK_Cyrillic_i_macron (line 1136) | XK_Cyrillic_i_macron = 0x10004e3
constant XK_Cyrillic_O_bar (line 1137) | XK_Cyrillic_O_bar = 0x10004e8
constant XK_Cyrillic_o_bar (line 1138) | XK_Cyrillic_o_bar = 0x10004e9
constant XK_Cyrillic_U_macron (line 1139) | XK_Cyrillic_U_macron = 0x10004ee
constant XK_Cyrillic_u_macron (line 1140) | XK_Cyrillic_u_macron = 0x10004ef
constant XK_Serbian_dje (line 1142) | XK_Serbian_dje = 0x06a1
constant XK_Macedonia_gje (line 1143) | XK_Macedonia_gje = 0x06a2
constant XK_Cyrillic_io (line 1144) | XK_Cyrillic_io = 0x06a3
constant XK_Ukrainian_ie (line 1145) | XK_Ukrainian_ie = 0x06a4
constant XK_Ukranian_je (line 1146) | XK_Ukranian_je = 0x06a4
constant XK_Macedonia_dse (line 1147) | XK_Macedonia_dse = 0x06a5
constant XK_Ukrainian_i (line 1148) | XK_Ukrainian_i = 0x06a6
constant XK_Ukranian_i (line 1149) | XK_Ukranian_i = 0x06a6
constant XK_Ukrainian_yi (line 1150) | XK_Ukrainian_yi = 0x06a7
constant XK_Ukranian_yi (line 1151) | XK_Ukranian_yi = 0x06a7
constant XK_Cyrillic_je (line 1152) | XK_Cyrillic_je = 0x06a8
constant XK_Serbian_je (line 1153) | XK_Serbian_je = 0x06a8
constant XK_Cyrillic_lje (line 1154) | XK_Cyrillic_lje = 0x06a9
constant XK_Serbian_lje (line 1155) | XK_Serbian_lje = 0x06a9
constant XK_Cyrillic_nje (line 1156) | XK_Cyrillic_nje = 0x06aa
constant XK_Serbian_nje (line 1157) | XK_Serbian_nje = 0x06aa
constant XK_Serbian_tshe (line 1158) | XK_Serbian_tshe = 0x06ab
constant XK_Macedonia_kje (line 1159) | XK_Macedonia_kje = 0x06ac
constant XK_Ukrainian_ghe_with_upturn (line 1160) | XK_Ukrainian_ghe_with_upturn = 0x06ad
constant XK_Byelorussian_shortu (line 1161) | XK_Byelorussian_shortu = 0x06ae
constant XK_Cyrillic_dzhe (line 1162) | XK_Cyrillic_dzhe = 0x06af
constant XK_Serbian_dze (line 1163) | XK_Serbian_dze = 0x06af
constant XK_numerosign (line 1164) | XK_numerosign = 0x06b0
constant XK_Serbian_DJE (line 1165) | XK_Serbian_DJE = 0x06b1
constant XK_Macedonia_GJE (line 1166) | XK_Macedonia_GJE = 0x06b2
constant XK_Cyrillic_IO (line 1167) | XK_Cyrillic_IO = 0x06b3
constant XK_Ukrainian_IE (line 1168) | XK_Ukrainian_IE = 0x06b4
constant XK_Ukranian_JE (line 1169) | XK_Ukranian_JE = 0x06b4
constant XK_Macedonia_DSE (line 1170) | XK_Macedonia_DSE = 0x06b5
constant XK_Ukrainian_I (line 1171) | XK_Ukrainian_I = 0x06b6
constant XK_Ukranian_I (line 1172) | XK_Ukranian_I = 0x06b6
constant XK_Ukrainian_YI (line 1173) | XK_Ukrainian_YI = 0x06b7
constant XK_Ukranian_YI (line 1174) | XK_Ukranian_YI = 0x06b7
constant XK_Cyrillic_JE (line 1175) | XK_Cyrillic_JE = 0x06b8
constant XK_Serbian_JE (line 1176) | XK_Serbian_JE = 0x06b8
constant XK_Cyrillic_LJE (line 1177) | XK_Cyrillic_LJE = 0x06b9
constant XK_Serbian_LJE (line 1178) | XK_Serbian_LJE = 0x06b9
constant XK_Cyrillic_NJE (line 1179) | XK_Cyrillic_NJE = 0x06ba
constant XK_Serbian_NJE (line 1180) | XK_Serbian_NJE = 0x06ba
constant XK_Serbian_TSHE (line 1181) | XK_Serbian_TSHE = 0x06bb
constant XK_Macedonia_KJE (line 1182) | XK_Macedonia_KJE = 0x06bc
constant XK_Ukrainian_GHE_WITH_UPTURN (line 1183) | XK_Ukrainian_GHE_WITH_UPTURN = 0x06bd
constant XK_Byelorussian_SHORTU (line 1184) | XK_Byelorussian_SHORTU = 0x06be
constant XK_Cyrillic_DZHE (line 1185) | XK_Cyrillic_DZHE = 0x06bf
constant XK_Serbian_DZE (line 1186) | XK_Serbian_DZE = 0x06bf
constant XK_Cyrillic_yu (line 1187) | XK_Cyrillic_yu = 0x06c0
constant XK_Cyrillic_a (line 1188) | XK_Cyrillic_a = 0x06c1
constant XK_Cyrillic_be (line 1189) | XK_Cyrillic_be = 0x06c2
constant XK_Cyrillic_tse (line 1190) | XK_Cyrillic_tse = 0x06c3
constant XK_Cyrillic_de (line 1191) | XK_Cyrillic_de = 0x06c4
constant XK_Cyrillic_ie (line 1192) | XK_Cyrillic_ie = 0x06c5
constant XK_Cyrillic_ef (line 1193) | XK_Cyrillic_ef = 0x06c6
constant XK_Cyrillic_ghe (line 1194) | XK_Cyrillic_ghe = 0x06c7
constant XK_Cyrillic_ha (line 1195) | XK_Cyrillic_ha = 0x06c8
constant XK_Cyrillic_i (line 1196) | XK_Cyrillic_i = 0x06c9
constant XK_Cyrillic_shorti (line 1197) | XK_Cyrillic_shorti = 0x06ca
constant XK_Cyrillic_ka (line 1198) | XK_Cyrillic_ka = 0x06cb
constant XK_Cyrillic_el (line 1199) | XK_Cyrillic_el = 0x06cc
constant XK_Cyrillic_em (line 1200) | XK_Cyrillic_em = 0x06cd
constant XK_Cyrillic_en (line 1201) | XK_Cyrillic_en = 0x06ce
constant XK_Cyrillic_o (line 1202) | XK_Cyrillic_o = 0x06cf
constant XK_Cyrillic_pe (line 1203) | XK_Cyrillic_pe = 0x06d0
constant XK_Cyrillic_ya (line 1204) | XK_Cyrillic_ya = 0x06d1
constant XK_Cyrillic_er (line 1205) | XK_Cyrillic_er = 0x06d2
constant XK_Cyrillic_es (line 1206) | XK_Cyrillic_es = 0x06d3
constant XK_Cyrillic_te (line 1207) | XK_Cyrillic_te = 0x06d4
constant XK_Cyrillic_u (line 1208) | XK_Cyrillic_u = 0x06d5
constant XK_Cyrillic_zhe (line 1209) | XK_Cyrillic_zhe = 0x06d6
constant XK_Cyrillic_ve (line 1210) | XK_Cyrillic_ve = 0x06d7
constant XK_Cyrillic_softsign (line 1211) | XK_Cyrillic_softsign = 0x06d8
constant XK_Cyrillic_yeru (line 1212) | XK_Cyrillic_yeru = 0x06d9
constant XK_Cyrillic_ze (line 1213) | XK_Cyrillic_ze = 0x06da
constant XK_Cyrillic_sha (line 1214) | XK_Cyrillic_sha = 0x06db
constant
Condensed preview — 563 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,533K chars).
[
{
"path": ".editorconfig",
"chars": 147,
"preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
},
{
"path": ".gitattributes",
"chars": 259,
"preview": "* text=auto\n*.css text\n*.js text\n*.ts text\n*.json text\n*.htm text\n*.html text\n*.env text\n*.xml text\n*.svg text\n*.txt tex"
},
{
"path": ".github/FUNDING.yml",
"chars": 18,
"preview": "github: [ m1k1o ]\n"
},
{
"path": ".github/workflows/client_build.yml",
"chars": 1121,
"preview": "name: Build Client\n\non:\n workflow_call:\n inputs:\n with-artifact:\n required: false\n type: boolean\n"
},
{
"path": ".github/workflows/client_test.yml",
"chars": 379,
"preview": "name: Test Client\n\non:\n pull_request:\n branches:\n - master\n paths:\n - client/**\n - .github/workflo"
},
{
"path": ".github/workflows/dockerhub.yml",
"chars": 3311,
"preview": "name: Build and Push to Docker Hub\n\non:\n push:\n branches:\n - master\n paths-ignore:\n - 'webpage/**'\n #\n"
},
{
"path": ".github/workflows/ghcr.yml",
"chars": 1688,
"preview": "name: Build and Push to GHCR\n\non:\n push:\n tags:\n - 'v*'\n\njobs:\n build-base:\n name: Base Image\n uses: ./."
},
{
"path": ".github/workflows/ghcr_intel.yml",
"chars": 1113,
"preview": "name: Build and Push to GHCR for Intel\n\non:\n push:\n tags:\n - 'v*'\n\njobs:\n build-base:\n name: Base Image\n "
},
{
"path": ".github/workflows/ghcr_nvidia.yml",
"chars": 1016,
"preview": "name: Build and Push to GHCR for Nvidia\n\non:\n push:\n tags:\n - 'v*'\n\njobs:\n build-base:\n name: Base Image\n "
},
{
"path": ".github/workflows/image_app.yml",
"chars": 2278,
"preview": "name: Build App Image\n\non:\n workflow_call:\n inputs:\n name:\n required: true\n type: string\n "
},
{
"path": ".github/workflows/image_base.yml",
"chars": 2476,
"preview": "name: Build Base Image\n\non:\n workflow_call:\n inputs:\n flavor:\n required: false\n type: string\n "
},
{
"path": ".github/workflows/server_test.yml",
"chars": 826,
"preview": "name: Test Server\n\non:\n pull_request:\n branches:\n - master\n paths:\n - server/**\n - .github/workflo"
},
{
"path": ".github/workflows/webpage_build.yml",
"chars": 1153,
"preview": "name: Build Webpage\n\non:\n workflow_call:\n inputs:\n with-artifact:\n required: false\n type: boolean"
},
{
"path": ".github/workflows/webpage_deploy.yml",
"chars": 1225,
"preview": "name: Build and Deploy Webpage to GitHub Pages\n\non:\n # Runs on pushes targeting the default branch\n push:\n branches"
},
{
"path": ".github/workflows/webpage_test.yml",
"chars": 386,
"preview": "name: Test Webpage\n\non:\n pull_request:\n branches:\n - master\n paths:\n - webpage/**\n - .github/workf"
},
{
"path": ".gitignore",
"chars": 517,
"preview": "# OS files\n.DS_Store\n.DS_Store?\n._*\n.Spotlight-V100\n.Trashes\nehthumbs.db\nThumbs.db\n\n# Log/Temp files\n.tmp/\ntmp/\n*.tmp\n.l"
},
{
"path": ".vscode/launch.json",
"chars": 793,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n"
},
{
"path": ".vscode/settings.json",
"chars": 257,
"preview": "{\n \"go.inferGopath\": false,\n \"go.autocompleteUnimportedPackages\": true,\n \"go.delveConfig\": {\n \"useApiV1\": false\n "
},
{
"path": "Dockerfile.tmpl",
"chars": 725,
"preview": "# This Dockerfile is pre-processed by the ./utils/docker script, it is not meant to be used directly.\n\nFROM ./server/ AS"
},
{
"path": "LICENSE",
"chars": 11466,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 12931,
"preview": "<div align=\"center\">\n <a href=\"https://github.com/m1k1o/neko\" title=\"Neko's Github repository.\">\n <img src=\"https://"
},
{
"path": "SECURITY.md",
"chars": 773,
"preview": "# Security Policy\n\n## Reporting a Vulnerability\n\nIf there are any vulnerabilities in **m1k1o/neko**, don't hesitate to _"
},
{
"path": "apps/brave/Dockerfile",
"chars": 1076,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nRUN set -eux; apt-get update; \\\n apt-get install -y -"
},
{
"path": "apps/brave/Dockerfile.nvidia",
"chars": 1047,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest\nFROM $BASE_IMAGE\n\nRUN set -eux; apt-get update; \\\n apt-get insta"
},
{
"path": "apps/brave/openbox.xml",
"chars": 24572,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/brave/policies.json",
"chars": 1131,
"preview": "{\n \"AutofillAddressEnabled\": false,\n \"AutofillCreditCardEnabled\": false,\n \"BrowserSignin\": 0,\n \"DefaultNotifications"
},
{
"path": "apps/brave/preferences.json",
"chars": 2557,
"preview": "{\n \"homepage\": \"http://www.google.com\",\n \"homepage_is_newtabpage\": false,\n \"first_run_tabs\": [\n \"https://www.googl"
},
{
"path": "apps/brave/supervisord.conf",
"chars": 899,
"preview": "[program:brave]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/bra"
},
{
"path": "apps/brave/supervisord.nvidia.conf",
"chars": 1137,
"preview": "[program:brave]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/bin/entrypo"
},
{
"path": "apps/chromium/Dockerfile",
"chars": 1167,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nCOPY ./widevinecdm.sh /widevine.sh\n\n#\n# install neko chr"
},
{
"path": "apps/chromium/Dockerfile.nvidia",
"chars": 1073,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest\nFROM $BASE_IMAGE\n\nCOPY ./widevinecdm.sh /widevine.sh\n\n#\n# install n"
},
{
"path": "apps/chromium/openbox.xml",
"chars": 24562,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/chromium/policies.json",
"chars": 1162,
"preview": "{\n \"AutofillAddressEnabled\": false,\n \"AutofillCreditCardEnabled\": false,\n \"BrowserSignin\": 0,\n \"DefaultNotifications"
},
{
"path": "apps/chromium/preferences.json",
"chars": 2557,
"preview": "{\n \"homepage\": \"http://www.google.com\",\n \"homepage_is_newtabpage\": false,\n \"first_run_tabs\": [\n \"https://www.googl"
},
{
"path": "apps/chromium/supervisord.conf",
"chars": 903,
"preview": "[program:chromium]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/"
},
{
"path": "apps/chromium/supervisord.nvidia.conf",
"chars": 1141,
"preview": "[program:chromium]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/bin/entr"
},
{
"path": "apps/chromium/widevinecdm.sh",
"chars": 1185,
"preview": "#!/usr/bin/env bash\nset -e\n\nTARGET_DIR=\"$(realpath \"$1\")\"\nif [ -z \"$TARGET_DIR\" ]; then\n echo \"Usage: $0 /path/to/ins"
},
{
"path": "apps/firefox/Dockerfile",
"chars": 2473,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n#\n# install firefox\nRUN set -eux; apt-get update; \\\n "
},
{
"path": "apps/firefox/Dockerfile.nvidia",
"chars": 1272,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest\nFROM $BASE_IMAGE\n\nARG SRC_URL=\"https://download.mozilla.org/?produc"
},
{
"path": "apps/firefox/autoconfig.js",
"chars": 88,
"preview": "pref(\"general.config.obscure_value\", 0);\npref(\"general.config.filename\", \"mozilla.cfg\");"
},
{
"path": "apps/firefox/neko.js",
"chars": 2054,
"preview": "// firefox config for neko\nlockPref(\"browser.tabs.closeWindowWithLastTab\", false);\nlockPref(\"app.update.auto\", false);\nl"
},
{
"path": "apps/firefox/openbox.xml",
"chars": 24560,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/firefox/policies.json",
"chars": 3790,
"preview": "{\n \"policies\": {\n \"BlockAboutAddons\": false,\n \"BlockAboutConfig\": true,\n \"BlockAboutProfiles\": true,\n \"Bloc"
},
{
"path": "apps/firefox/profiles.ini",
"chars": 102,
"preview": "[General]\nStartWithLastProfile=1\n\n[Profile0]\nName=default\nIsRelative=1\nPath=profile.default\nDefault=1\n"
},
{
"path": "apps/firefox/supervisord.conf",
"chars": 730,
"preview": "[program:firefox]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/f"
},
{
"path": "apps/firefox/supervisord.nvidia.conf",
"chars": 761,
"preview": "[program:firefox]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/bin/entry"
},
{
"path": "apps/google-chrome/Dockerfile",
"chars": 722,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nARG SRC_URL=\"https://dl.google.com/linux/direct/google-c"
},
{
"path": "apps/google-chrome/Dockerfile.nvidia",
"chars": 1081,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest\nFROM $BASE_IMAGE\n\n# latest working version with EGL: 111.0.5563.146"
},
{
"path": "apps/google-chrome/openbox.xml",
"chars": 24572,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/google-chrome/policies.json",
"chars": 1131,
"preview": "{\n \"AutofillAddressEnabled\": false,\n \"AutofillCreditCardEnabled\": false,\n \"BrowserSignin\": 0,\n \"DefaultNotifications"
},
{
"path": "apps/google-chrome/preferences.json",
"chars": 2557,
"preview": "{\n \"homepage\": \"http://www.google.com\",\n \"homepage_is_newtabpage\": false,\n \"first_run_tabs\": [\n \"https://www.googl"
},
{
"path": "apps/google-chrome/supervisord.conf",
"chars": 923,
"preview": "[program:google-chrome]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr"
},
{
"path": "apps/google-chrome/supervisord.nvidia.conf",
"chars": 1156,
"preview": "[program:google-chrome]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/bin"
},
{
"path": "apps/kde/Dockerfile",
"chars": 728,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n#\n# install kde\nRUN set -eux; apt-get update; \\\n apt-"
},
{
"path": "apps/kde/supervisord.conf",
"chars": 612,
"preview": "[program:kde]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/start"
},
{
"path": "apps/microsoft-edge/Dockerfile",
"chars": 896,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nARG API_URL=\"https://packages.microsoft.com/repos/edge/p"
},
{
"path": "apps/microsoft-edge/Dockerfile.nvidia",
"chars": 903,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nARG API_URL=\"https://packages.microsoft.com/repos/edge/p"
},
{
"path": "apps/microsoft-edge/openbox.xml",
"chars": 24574,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/microsoft-edge/policies.json",
"chars": 1129,
"preview": "{\n \"AutofillAddressEnabled\": false,\n \"AutofillCreditCardEnabled\": false,\n \"BrowserSignin\": 0,\n \"DefaultNotifications"
},
{
"path": "apps/microsoft-edge/preferences.json",
"chars": 2557,
"preview": "{\n \"homepage\": \"http://www.google.com\",\n \"homepage_is_newtabpage\": false,\n \"first_run_tabs\": [\n \"https://www.googl"
},
{
"path": "apps/microsoft-edge/supervisord.conf",
"chars": 927,
"preview": "[program:microsoft-edge]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/us"
},
{
"path": "apps/microsoft-edge/supervisord.nvidia.conf",
"chars": 1165,
"preview": "[program:microsoft-edge]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/bi"
},
{
"path": "apps/opera/Dockerfile",
"chars": 1354,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nARG API_URL=\"https://download5.operacdn.com/pub/opera/de"
},
{
"path": "apps/opera/fix-ffmpeg-widevine.sh",
"chars": 3983,
"preview": "#!/bin/bash\n# From https://github.com/Ld-Hagen/fix-opera-linux-ffmpeg-widevine.\n\n# Config section\nreadonly FIX_FFMPEG=tr"
},
{
"path": "apps/opera/openbox.xml",
"chars": 24553,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/opera/supervisord.conf",
"chars": 710,
"preview": "[program:opera]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/ope"
},
{
"path": "apps/remmina/Dockerfile",
"chars": 717,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n# install remmina\nRUN set -eux; apt-get update; \\\n ap"
},
{
"path": "apps/remmina/rdp.remmina",
"chars": 1323,
"preview": "[remmina]\npassword=\ngateway_username=\nnotes_text=\nvc=\npreferipv6=0\nssh_tunnel_loopback=0\nserialname=\nsound=local\nprinter"
},
{
"path": "apps/remmina/remmina.pref",
"chars": 2057,
"preview": "[remmina_pref]\nsecret=Jsh7BJPwHqLCKi2vdkMAImSgdBVZGF6s8VbUPY3Q9WA=\ndatadir_path=\nremmina_file_name=%G_%P_%N_%h\nscreensho"
},
{
"path": "apps/remmina/run-remmina.sh",
"chars": 1403,
"preview": "#!/bin/bash\n\nerr() {\n echo \"ERROR: $*\" >&2\n exit 1\n}\n\nprofile_dir=\"/home/neko/.local/share/remmina\"\nif [[ -n \"$REMMINA"
},
{
"path": "apps/remmina/spice.remmina",
"chars": 537,
"preview": "[remmina]\ndisablegstvideooverlay=0\ndisablepasswordstoring=0\nsharesmartcard=0\nvideocodec=0\nssh_tunnel_password=\npostcomma"
},
{
"path": "apps/remmina/supervisord.conf",
"chars": 316,
"preview": "\n[program:remmina]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/"
},
{
"path": "apps/remmina/vnc.remmina",
"chars": 760,
"preview": "[remmina]\nencodings=\nvideocodec=0\nname=temp eos\nssh_tunnel_server=\nssh_tunnel_privatekey=\npassword=\nquality=0\ndisablesmo"
},
{
"path": "apps/tor-browser/Dockerfile",
"chars": 944,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n#\n# install dependencies\nRUN set -eux; apt-get update; \\"
},
{
"path": "apps/tor-browser/openbox.xml",
"chars": 24542,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/tor-browser/supervisord.conf",
"chars": 852,
"preview": "[program:tor-browser]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/opt/t"
},
{
"path": "apps/ungoogled-chromium/Dockerfile",
"chars": 2605,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nARG API_URL=\"https://api.github.com/repos/macchrome/linc"
},
{
"path": "apps/ungoogled-chromium/openbox.xml",
"chars": 24567,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/ungoogled-chromium/policies.json",
"chars": 914,
"preview": "{\n \"AutofillAddressEnabled\": false,\n \"AutofillCreditCardEnabled\": false,\n \"BrowserSignin\": 0,\n \"DefaultNotifications"
},
{
"path": "apps/ungoogled-chromium/preferences.json",
"chars": 2535,
"preview": "{\n \"homepage\": \"https://duckduckgo.com/\",\n \"homepage_is_newtabpage\": false,\n \"first_run_tabs\": [\n \"https://duckduc"
},
{
"path": "apps/ungoogled-chromium/supervisord.conf",
"chars": 869,
"preview": "[program:ungoogled-chromium]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand"
},
{
"path": "apps/ungoogled-chromium/widevinecdm.sh",
"chars": 1185,
"preview": "#!/usr/bin/env bash\nset -e\n\nTARGET_DIR=\"$(realpath \"$1\")\"\nif [ -z \"$TARGET_DIR\" ]; then\n echo \"Usage: $0 /path/to/ins"
},
{
"path": "apps/vivaldi/Dockerfile",
"chars": 1701,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n#\n# install vivaldi\nSHELL [\"/bin/bash\", \"-c\"]\nRUN set -e"
},
{
"path": "apps/vivaldi/openbox.xml",
"chars": 24574,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/vivaldi/policies.json",
"chars": 1131,
"preview": "{\n \"AutofillAddressEnabled\": false,\n \"AutofillCreditCardEnabled\": false,\n \"BrowserSignin\": 0,\n \"DefaultNotifications"
},
{
"path": "apps/vivaldi/preferences.json",
"chars": 10607,
"preview": "{\n \"homepage\": \"http://www.google.com\",\n \"homepage_is_newtabpage\": false,\n \"first_run_tabs\": [\n \"https://www.googl"
},
{
"path": "apps/vivaldi/supervisord.conf",
"chars": 904,
"preview": "[program:vivaldi-stable]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/us"
},
{
"path": "apps/vlc/Dockerfile",
"chars": 431,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n#\n# install vlc\nRUN set -eux; apt-get update; \\\n apt-"
},
{
"path": "apps/vlc/openbox.xml",
"chars": 24551,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/vlc/supervisord.conf",
"chars": 694,
"preview": "[program:vlc]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/vlc -"
},
{
"path": "apps/waterfox/Dockerfile",
"chars": 1273,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\nARG SRC_URL=\"https://cdn1.waterfox.net/waterfox/releases"
},
{
"path": "apps/waterfox/autoconfig.js",
"chars": 88,
"preview": "pref(\"general.config.obscure_value\", 0);\npref(\"general.config.filename\", \"mozilla.cfg\");"
},
{
"path": "apps/waterfox/neko.js",
"chars": 2054,
"preview": "// firefox config for neko\nlockPref(\"browser.tabs.closeWindowWithLastTab\", false);\nlockPref(\"app.update.auto\", false);\nl"
},
{
"path": "apps/waterfox/openbox.xml",
"chars": 24561,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!-- Default openbox config but all window decorations are moved\n thereby makin"
},
{
"path": "apps/waterfox/policies.json",
"chars": 3745,
"preview": "{\n \"policies\": {\n \"BlockAboutAddons\": false,\n \"BlockAboutConfig\": true,\n \"BlockAboutProfiles\": true,\n \"Bloc"
},
{
"path": "apps/waterfox/profiles.ini",
"chars": 102,
"preview": "[General]\nStartWithLastProfile=1\n\n[Profile0]\nName=default\nIsRelative=1\nPath=profile.default\nDefault=1\n"
},
{
"path": "apps/waterfox/supervisord.conf",
"chars": 733,
"preview": "[program:waterfox]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/"
},
{
"path": "apps/xfce/Dockerfile",
"chars": 516,
"preview": "ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest\nFROM $BASE_IMAGE\n\n#\n# install xfce\nRUN set -eux; apt-get update; \\\n apt"
},
{
"path": "apps/xfce/supervisord.conf",
"chars": 305,
"preview": "[program:xfce]\nenvironment=HOME=\"/home/%(ENV_USER)s\",USER=\"%(ENV_USER)s\",DISPLAY=\"%(ENV_DISPLAY)s\"\ncommand=/usr/bin/star"
},
{
"path": "build",
"chars": 10254,
"preview": "#!/bin/bash\nset -e\ncd \"$(dirname \"$0\")\"\n\n#\n# This script builds the neko base image and all the applications\n#\n\n# disabl"
},
{
"path": "client/.babelrc",
"chars": 50,
"preview": "{\n \"presets\": [\"@vue/cli-plugin-babel/preset\"]\n}\n"
},
{
"path": "client/.browserslistrc",
"chars": 21,
"preview": "> 1%\nlast 2 versions\n"
},
{
"path": "client/.editorconfig",
"chars": 146,
"preview": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_"
},
{
"path": "client/.eslintrc",
"chars": 362,
"preview": "{\n \"root\": true,\n \"env\": {\n \"node\": true\n },\n \"extends\": [\"plugin:vue/essential\", \"@vue/prettier\", \"@vue/typescri"
},
{
"path": "client/.prettierrc",
"chars": 142,
"preview": "{\n \"semi\": false,\n \"trailingComma\": \"all\",\n \"singleQuote\": true,\n \"printWidth\": 120,\n \"tabWidth\": 2,\n \"vueIndentSc"
},
{
"path": "client/.vscode/settings.json",
"chars": 1007,
"preview": "{\n \"editor.tabSize\": 2,\n \"editor.insertSpaces\": true,\n \"editor.detectIndentation\": false,\n \"files.encoding\": \"utf8\","
},
{
"path": "client/Dockerfile",
"chars": 259,
"preview": "ARG BASE_IMAGE=node:18-bullseye-slim\nFROM $BASE_IMAGE AS client\n\nWORKDIR /src\n\n#\n# install dependencies\nCOPY package*.js"
},
{
"path": "client/dev/build",
"chars": 228,
"preview": "#!/bin/sh\ncd \"$(dirname \"$0\")\"\n\n# start component watch\ndocker run --rm -it \\\n --user \"$(id -u):$(id -g)\" \\\n --vol"
},
{
"path": "client/dev/exec",
"chars": 224,
"preview": "#!/bin/sh\ncd \"$(dirname \"$0\")\"\n\n# start component watch\ndocker run --rm -it \\\n --user \"$(id -u):$(id -g)\" \\\n --vol"
},
{
"path": "client/dev/npm",
"chars": 205,
"preview": "#!/bin/sh\ncd \"$(dirname \"$0\")\"\n\n# npm\ndocker run --rm -it \\\n --user \"$(id -u):$(id -g)\" \\\n --volume \"${PWD}/../:/a"
},
{
"path": "client/dev/serve",
"chars": 664,
"preview": "#!/bin/bash\ncd \"$(dirname \"$0\")\"\n\nif [ -z $VUE_APP_SERVER_PORT ]; then\n VUE_APP_SERVER_PORT=\"3000\"\nfi\n\necho \"Using VU"
},
{
"path": "client/package.json",
"chars": 2204,
"preview": "{\n \"name\": \"neko-client\",\n \"version\": \"2.5.0\",\n \"description\": \"Client for neko streaming server\",\n \"license\": \"Apac"
},
{
"path": "client/public/browserconfig.xml",
"chars": 246,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n <msapplication>\n <tile>\n <square150x150logo"
},
{
"path": "client/public/emoji.json",
"chars": 181497,
"preview": "{\"groups\":[{\"id\":\"neko\",\"name\":\"Neko\",\"list\":[\"neko\"]},{\"id\":\"emotion\",\"name\":\"Emotion\",\"list\":[\"japanese_ogre\",\"japanes"
},
{
"path": "client/public/index.html",
"chars": 1188,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE="
},
{
"path": "client/public/keyboard_layouts.json",
"chars": 1657,
"preview": "{\"af\":\"Afghani\",\"al\":\"Albanian\",\"et\":\"Amharic\",\"ma\":\"Arabic (Morocco)\",\"sy\":\"Arabic (Syria)\",\"am\":\"Armenian\",\"az\":\"Azerb"
},
{
"path": "client/public/site.webmanifest",
"chars": 436,
"preview": "{\n \"name\": \"n.eko\",\n \"short_name\": \"n.eko\",\n \"icons\": [\n {\n \"src\": \"/android-chrome-192x192.p"
},
{
"path": "client/src/app.vue",
"chars": 6404,
"preview": "<template>\n <div id=\"neko\" :class=\"[!videoOnly && side ? 'expanded' : '']\">\n <template v-if=\"!$client.supported\">\n "
},
{
"path": "client/src/assets/styles/_reset.scss",
"chars": 6695,
"preview": "html, body, div, span, applet, object, iframe,\nh1, h2, h3, h4, h5, h6, p, blockquote, pre,\na, abbr, acronym, address, bi"
},
{
"path": "client/src/assets/styles/_variables.scss",
"chars": 883,
"preview": "$text-family: Whitney, Helvetica Neue, Helvetica, Arial, sans-serif;;\n$text-size: 14px;\n$text-normal: #dcddde;\n$text-m"
},
{
"path": "client/src/assets/styles/main.scss",
"chars": 550,
"preview": "@charset \"utf-8\";\n\n// Import variables\n@import \"variables\";\n\n// Reset CSS\n@import \"reset\";\n\n// Import Vendor\n@import \"ve"
},
{
"path": "client/src/assets/styles/vendor/_emoji.scss",
"chars": 165573,
"preview": "\n.emoji {\n display: inline-block;\n background-size: 5800%;\n background-image: url('~emoji-datasource/img/twitter/shee"
},
{
"path": "client/src/assets/styles/vendor/_emote.scss",
"chars": 3247,
"preview": ".emote {\n width: 24px;\n height: 24px;\n background-size: contain;\n background-repeat: no-repeat;\n background-positio"
},
{
"path": "client/src/assets/styles/vendor/_font-awesome.scss",
"chars": 661,
"preview": "// Variables\n\n@use \"sass:math\";\n\n$fa-font-path: \"~@fortawesome/fontawesome-free/webfonts\";\n$fa-font-size-base: "
},
{
"path": "client/src/assets/styles/vendor/_font-whitney.scss",
"chars": 539,
"preview": "@font-face{\n font-family:Whitney;\n font-weight:300;\n src:url(\"fonts/whitney-300.woff\") format(\"woff\")\n}\n\n@font-face{\n"
},
{
"path": "client/src/assets/styles/vendor/_github.scss",
"chars": 17770,
"preview": "@font-face {\n font-family: octicons-link;\n src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAA"
},
{
"path": "client/src/assets/styles/vendor/_swal.scss",
"chars": 1943,
"preview": "@import '~sweetalert2/src/variables';\n\n$swal2-outline-color: transparent;\n\n// POPUP\n$swal2-padding: 1.25em;\n$swal2-borde"
},
{
"path": "client/src/assets/styles/vendor/_tooltip.scss",
"chars": 2350,
"preview": ".tooltip {\n display: block !important;\n z-index: 10000;\n\n .tooltip-inner {\n background: darken($background-floatin"
},
{
"path": "client/src/components/about.vue",
"chars": 3855,
"preview": "<template>\n <div class=\"about\" @click=\"toggle\">\n <div class=\"window\">\n <div class=\"loading\" v-if=\"loading\">\n "
},
{
"path": "client/src/components/avatar.vue",
"chars": 1299,
"preview": "<template>\n <!--\n <img :src=\"`https://ui-avatars.com/api/?name=${seed}&size=${size}`\" />\n -->\n <div\n class=\"a"
},
{
"path": "client/src/components/chat.vue",
"chars": 12779,
"preview": "<template>\n <div class=\"chat\">\n <ul class=\"chat-history\" ref=\"history\" @click=\"onClick\">\n <template v-for=\"(mes"
},
{
"path": "client/src/components/clipboard.vue",
"chars": 1629,
"preview": "<template>\n <div class=\"clipboard\" v-if=\"opened\" @click=\"$event.stopPropagation()\">\n <textarea ref=\"textarea\" v-mode"
},
{
"path": "client/src/components/connect.vue",
"chars": 5646,
"preview": "<template>\n <div class=\"connect\">\n <div class=\"window\">\n <div class=\"logo\" title=\"About n.eko\" @click.stop.prev"
},
{
"path": "client/src/components/context.vue",
"chars": 7242,
"preview": "<template>\n <vue-context class=\"context\" ref=\"context\">\n <template slot-scope=\"child\" v-if=\"child.data\">\n <li c"
},
{
"path": "client/src/components/controls.vue",
"chars": 9830,
"preview": "<template>\n <ul>\n <li v-if=\"!implicitHosting && (!controlLocked || hosting)\">\n <i\n :class=\"[\n !"
},
{
"path": "client/src/components/emoji.vue",
"chars": 9623,
"preview": "<template>\n <div class=\"neko-emoji\" v-on-clickaway=\"onClickAway\">\n <div class=\"search\">\n <div class=\"search-con"
},
{
"path": "client/src/components/emote.vue",
"chars": 2294,
"preview": "<template>\n <div ref=\"emote\" @click.stop.prevent=\"run\" class=\"emote-container\">\n <div :class=\"classes\" />\n <div :"
},
{
"path": "client/src/components/emotes.vue",
"chars": 3993,
"preview": "<template>\n <div class=\"emotes\" @mouseleave=\"stopSendingEmotes\" @mouseup=\"stopSendingEmotes\">\n <ul v-if=\"!muted\">\n "
},
{
"path": "client/src/components/files.vue",
"chars": 14299,
"preview": "<template>\n <div class=\"files\">\n <div class=\"files-cwd\">\n <p>{{ cwd }}</p>\n <i class=\"fas fa-rotate-right "
},
{
"path": "client/src/components/header.vue",
"chars": 5085,
"preview": "<template>\n <div class=\"header\">\n <a href=\"https://github.com/m1k1o/neko\" title=\"Github repository\" target=\"_blank\" "
},
{
"path": "client/src/components/markdown.ts",
"chars": 6120,
"preview": "import md, { SingleNodeParserRule, HtmlOutputRule, defaultRules, State, Rules } from 'simple-markdown'\nimport { Componen"
},
{
"path": "client/src/components/members.vue",
"chars": 4946,
"preview": "<template>\n <div class=\"members\">\n <div class=\"members-container\">\n <ul class=\"members-list\">\n <li v-if="
},
{
"path": "client/src/components/menu.vue",
"chars": 2300,
"preview": "<template>\n <ul>\n <li><i @click.stop.prevent=\"about\" class=\"fas fa-question-circle\" /></li>\n <li>\n <i\n "
},
{
"path": "client/src/components/resolution.vue",
"chars": 2923,
"preview": "<template>\n <vue-context class=\"context\" ref=\"context\">\n <template v-for=\"(conf, i) in configurations\">\n <li\n "
},
{
"path": "client/src/components/settings.vue",
"chars": 9620,
"preview": "<template>\n <div class=\"settings\">\n <ul>\n <li>\n <span>{{ $t('setting.scroll') }}</span>\n <label c"
},
{
"path": "client/src/components/side.vue",
"chars": 3175,
"preview": "<template>\n <aside class=\"neko-menu\">\n <div class=\"tabs-container\">\n <ul>\n <li :class=\"{ active: tab ==="
},
{
"path": "client/src/components/unsupported.vue",
"chars": 1427,
"preview": "<template>\n <div class=\"unsupported\">\n <div class=\"window\">\n <div class=\"logo\">\n <img src=\"@/assets/imag"
},
{
"path": "client/src/components/video.vue",
"chars": 23788,
"preview": "<template>\n <div ref=\"component\" class=\"video\">\n <div ref=\"player\" class=\"player\">\n <div ref=\"container\" class="
},
{
"path": "client/src/lib.ts",
"chars": 2283,
"preview": "import { accessor as neko } from './store'\nimport { PluginObject } from 'vue'\n\n// Plugins\nimport Logger from './plugins/"
},
{
"path": "client/src/locale/de-de.ts",
"chars": 4363,
"preview": "export const logout = 'Ausloggen'\nexport const unsupported = 'Dieser Webbrowser unterstützt kein Web-RTC.'\nexport const "
},
{
"path": "client/src/locale/en-us.ts",
"chars": 3968,
"preview": "export const logout = 'log out'\nexport const unsupported = 'this web-browser does not support WebRTC'\nexport const admin"
},
{
"path": "client/src/locale/es-sp.ts",
"chars": 4298,
"preview": "export const logout = 'salir'\nexport const unsupported = 'este navegador no soporta webrtc'\nexport const admin_loggedin "
},
{
"path": "client/src/locale/fi-fi.ts",
"chars": 4158,
"preview": "export const logout = 'kirjaudu ulos'\nexport const unsupported = 'Tämä nettiselain ei tue WebRTC:tä'\nexport const admin_"
},
{
"path": "client/src/locale/fr-fr.ts",
"chars": 4565,
"preview": "export const logout = 'Se déconnecter'\nexport const unsupported = 'ce navigateur ne prend pas en charge WebRTC'\nexport c"
},
{
"path": "client/src/locale/id-id.ts",
"chars": 4165,
"preview": "export const logout = 'keluar'\nexport const unsupported = 'peramban web ini tidak mendukung WebRTC'\nexport const admin_l"
},
{
"path": "client/src/locale/index.ts",
"chars": 569,
"preview": "import * as en from './en-us'\nimport * as es from './es-sp'\nimport * as sk from './sk-sk'\nimport * as sv from './sv-se'\n"
},
{
"path": "client/src/locale/ja-jp.ts",
"chars": 3432,
"preview": "export const logout = 'ログアウト'\nexport const unsupported = 'このウェブブラウザは WebRTC をサポートしていません'\nexport const admin_loggedin = '"
},
{
"path": "client/src/locale/ko-kr.ts",
"chars": 3292,
"preview": "export const logout = '로그아웃'\nexport const unsupported = '이 브라우저는 WebRTC 를 지원하지 않습니다'\nexport const admin_loggedin = '관리자로"
},
{
"path": "client/src/locale/nb-no.ts",
"chars": 4009,
"preview": "export const logout = 'logg ut'\nexport const unsupported = 'Denne nettleseren støtter ikke WebRTC'\nexport const admin_lo"
},
{
"path": "client/src/locale/pl-pl.ts",
"chars": 4170,
"preview": "export const logout = 'Wyloguj się'\nexport const unsupported = 'Ta przeglądarka nie obsługuje WebRTC'\nexport const admin"
},
{
"path": "client/src/locale/ru-ru.ts",
"chars": 4206,
"preview": "export const logout = 'выход'\nexport const unsupported = 'этот браузер не поддерживает WebRTC'\nexport const admin_logged"
},
{
"path": "client/src/locale/sk-sk.ts",
"chars": 4664,
"preview": "export const logout = 'odhlásiť sa'\nexport const unsupported = 'tento prehliadač nepodporuje webrtc'\nexport const admin_"
},
{
"path": "client/src/locale/sv-se.ts",
"chars": 4199,
"preview": "export const logout = 'logga ut'\nexport const unsupported = 'denna webbläsare har inte stöd för webrtc'\nexport const adm"
},
{
"path": "client/src/locale/zh-cn.ts",
"chars": 2771,
"preview": "export const logout = '登出'\nexport const unsupported = '你的浏览器不支持 WebRTC'\nexport const admin_loggedin = '您以管理员身份登录'\nexport"
},
{
"path": "client/src/locale/zh-tw.ts",
"chars": 2814,
"preview": "export const logout = '登出'\nexport const unsupported = '您的網頁瀏覽器不支援 WebRTC'\nexport const admin_loggedin = '您已經以管理員身份登入'\nex"
},
{
"path": "client/src/main.ts",
"chars": 710,
"preview": "import './assets/styles/main.scss'\n\nimport Vue from 'vue'\n\nimport Notifications from 'vue-notification'\nimport ToolTip f"
},
{
"path": "client/src/neko/base.ts",
"chars": 14098,
"preview": "import EventEmitter from 'eventemitter3'\nimport { OPCODE } from './data'\nimport { EVENT, WebSocketEvents } from './event"
},
{
"path": "client/src/neko/data.ts",
"chars": 99,
"preview": "export const OPCODE = {\n MOVE: 0x01,\n SCROLL: 0x02,\n KEY_DOWN: 0x03,\n KEY_UP: 0x04,\n} as const\n"
},
{
"path": "client/src/neko/events.ts",
"chars": 3145,
"preview": "export const EVENT = {\n // Internal Events\n RECONNECTING: 'RECONNECTING',\n CONNECTING: 'CONNECTING',\n CONNECTED: 'CO"
},
{
"path": "client/src/neko/index.ts",
"chars": 15522,
"preview": "import Vue from 'vue'\nimport EventEmitter from 'eventemitter3'\nimport { BaseClient, BaseEvents } from './base'\nimport { "
},
{
"path": "client/src/neko/messages.ts",
"chars": 5666,
"preview": "import {\n EVENT,\n WebSocketEvents,\n SystemEvents,\n ControlEvents,\n MemberEvents,\n SignalEvents,\n ChatEvents,\n Sc"
},
{
"path": "client/src/neko/types.ts",
"chars": 753,
"preview": "export interface Member {\n id: string\n displayname: string\n admin: boolean\n muted: boolean\n connected?: boolean\n i"
},
{
"path": "client/src/plugins/anime.ts",
"chars": 1515,
"preview": "import { PluginObject } from 'vue'\nimport anime, { StaggerOptions, AnimeTimelineInstance, AnimeParams, AnimeInstance } f"
},
{
"path": "client/src/plugins/axios.ts",
"chars": 409,
"preview": "import { PluginObject } from 'vue'\nimport axios, { AxiosStatic } from 'axios'\n\ndeclare global {\n const $http: AxiosStat"
},
{
"path": "client/src/plugins/i18n.ts",
"chars": 726,
"preview": "import Vue from 'vue'\nimport VueI18n from 'vue-i18n'\nimport { messages } from '~/locale'\nimport { get } from '~/utils/lo"
},
{
"path": "client/src/plugins/log.ts",
"chars": 943,
"preview": "import { PluginObject } from 'vue'\n\ninterface Logger {\n error(error: Error): void\n warn(...log: any[]): void\n info(.."
},
{
"path": "client/src/plugins/neko.ts",
"chars": 571,
"preview": "import { PluginObject } from 'vue'\nimport { NekoClient } from '~/neko'\n\ndeclare global {\n const $client: NekoClient\n\n "
},
{
"path": "client/src/plugins/swal.ts",
"chars": 1336,
"preview": "import Vue from 'vue'\n\nimport { SweetAlertOptions } from 'sweetalert2'\nimport Swal from 'sweetalert2/dist/sweetalert2.js"
},
{
"path": "client/src/store/chat.ts",
"chars": 1973,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { makeid } from '~/utils'\nimport { EVENT } from"
},
{
"path": "client/src/store/client.ts",
"chars": 822,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { get, set } from '~/utils/localstorage'\n\nexpor"
},
{
"path": "client/src/store/emoji.ts",
"chars": 1645,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { get, set } from '~/utils/localstorage'\nimport"
},
{
"path": "client/src/store/files.ts",
"chars": 1663,
"preview": "import { actionTree, getterTree, mutationTree } from 'typed-vuex'\nimport { FileListItem, FileTransfer } from '~/neko/typ"
},
{
"path": "client/src/store/index.ts",
"chars": 3171,
"preview": "import Vue from 'vue'\nimport Vuex from 'vuex'\nimport { useAccessor, mutationTree, getterTree, actionTree } from 'typed-v"
},
{
"path": "client/src/store/remote.ts",
"chars": 4156,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { Member } from '~/neko/types'\nimport { EVENT }"
},
{
"path": "client/src/store/settings.ts",
"chars": 2319,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { get, set } from '~/utils/localstorage'\nimport"
},
{
"path": "client/src/store/user.ts",
"chars": 3119,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { Member } from '~/neko/types'\nimport { EVENT }"
},
{
"path": "client/src/store/video.ts",
"chars": 4457,
"preview": "import { getterTree, mutationTree, actionTree } from 'typed-vuex'\nimport { get, set } from '~/utils/localstorage'\nimport"
},
{
"path": "client/src/types/eventemitter3.d.ts",
"chars": 1117,
"preview": "declare module 'eventemitter3' {\n type Arguments<T> = [T] extends [(...args: infer U) => any] ? U : [T] extends [void] "
},
{
"path": "client/src/types/navigator.keyboard.d.ts",
"chars": 374,
"preview": "// navigator.keyboard.d.ts\n\n// Type declarations for Keyboard API\n// https://developer.mozilla.org/en-US/docs/Web/API/Ke"
},
{
"path": "client/src/types/shims-scss.d.ts",
"chars": 27,
"preview": "declare module '*.scss' {}\n"
},
{
"path": "client/src/types/shims-tsx.d.ts",
"chars": 304,
"preview": "import Vue, { VNode } from 'vue'\n\ndeclare global {\n namespace JSX {\n // tslint:disable no-empty-interface\n interf"
},
{
"path": "client/src/types/shims-vue.d.ts",
"chars": 72,
"preview": "declare module '*.vue' {\n import Vue from 'vue'\n export default Vue\n}\n"
},
{
"path": "client/src/utils/guacamole-keyboard.js",
"chars": 49504,
"preview": "/* eslint-disable */\n\n/*\n * Licensed to the Apache Software Foundation (ASF) under one\n * or more contributor license ag"
},
{
"path": "client/src/utils/guacamole-keyboard.ts",
"chars": 2364,
"preview": "import GuacamoleKeyboard from './guacamole-keyboard.js'\n\nexport interface GuacamoleKeyboardInterface {\n /**\n * Fired "
},
{
"path": "client/src/utils/index.ts",
"chars": 2012,
"preview": "export function makeid(length: number) {\n let result = ''\n const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm"
},
{
"path": "client/src/utils/localstorage.ts",
"chars": 727,
"preview": "export function set<T extends string | number | boolean>(key: string, val: T) {\n switch (typeof val) {\n case 'number"
},
{
"path": "client/tools/emoji.ts",
"chars": 4869,
"preview": "import * as fs from 'fs'\nimport { custom } from './emoji_custom'\n\nconst datasource = require('emoji-datasource/emoji.jso"
},
{
"path": "client/tools/emoji_custom.ts",
"chars": 126,
"preview": "export const custom = [\n {\n name: 'neko',\n file: 'neko.png',\n keywords: ['neko', 'cat', 'cat butt', 'butt'],\n "
},
{
"path": "client/tools/tsconfig.json",
"chars": 178,
"preview": "{\n \"compilerOptions\": {\n\t\t\"target\": \"es2016\",\n\t\t\"module\": \"commonjs\",\n \"moduleResolution\": \"node\",\n \"types\": [\n "
},
{
"path": "client/tsconfig.json",
"chars": 743,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"esnext\",\n \"module\": \"esnext\",\n \"strict\": true,\n \"jsx\": \"preserve\",\n "
}
]
// ... and 363 more files (download for full content)
About this extraction
This page contains the full source code of the m1k1o/neko GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 563 files (4.0 MB), approximately 1.1M tokens, and a symbol index with 3695 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.