Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "localdesktop"
version = "3.2.2"
version = "3.3.0"
edition = "2021"
build = "build.rs"
default-run = "build_apk"
Expand Down
4 changes: 2 additions & 2 deletions gh-pages/docs/user/1-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ The hardest part is installing `yay` or `paru`. You have to follow the `README.m

## I don't have a physical keyboard.

An on-screen keyboard slides up when you tap a text field, and hides again when you tap elsewhere. For apps where it doesn't appear on its own, open _"Applications"_ > _"Accessories"_ > _"On-screen keyboard"_ to show or hide it. A physical keyboard is still more comfortable for long sessions.
Your phone's own keyboard comes up when you tap a text field, and the desktop fits above it. Swipe back to put it away. To use Squeekboard, the desktop's own on-screen keyboard, instead, turn off **Use the Android keyboard** in [Local Desktop settings](/docs/user/configurations). For apps where it doesn't come up on its own, open _"Applications"_ > _"Accessories"_ > _"On-screen keyboard"_. A physical keyboard is still more comfortable for long sessions.

![On-screen keyboard](/img/squeekboard.webp#boxed)
![The Android keyboard typing into the desktop](/img/android-keyboard.webp#boxed)

## Text is too small

Expand Down
17 changes: 2 additions & 15 deletions gh-pages/docs/user/2-creating-a-non-root-user.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,6 @@ sudo ls /root # Make sure it does not output something like: "teddy is not in th

## [Important] Tell Local Desktop

You must tell Local Desktop who to log in as, or it will log in as root. To (create and) edit the config file:
You must tell Local Desktop who to log in as, or it will log in as root. In Android, open **App info** for Local Desktop > **Additional settings in the app**, and set **User** to `teddy` _(the username you created [previously](#create-your-user))_. Then tap **Restart Local Desktop**.

```
nano /etc/localdesktop/localdesktop.toml
```

Add the following content:

```toml title="/etc/localdesktop/localdesktop.toml"
[user]
username = "teddy"
```

_(Replace `teddy` with the username you created [previously](#create-your-user))_

The changes will take effect the next time you launch Local Desktop. If something goes wrong, you can always delete this config file and restart as root.
If something goes wrong, set **User** back to `root` there. See [Settings](/docs/user/configurations).
47 changes: 26 additions & 21 deletions gh-pages/docs/user/3-custom-de.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,14 @@ title: Using other Desktop Environments
This is an advanced topic. Proceed with your own risk.
:::

## The `[command]` configs
## The 3 commands

Local Desktop uses 3 commands to set up your desktop environment:

```toml title="/etc/localdesktop/localdesktop.toml"
[command]
check="pacman -Q noto-fonts && pacman -Q xfce4-session && pacman -Q xfce4-panel && pacman -Q xfce4-settings && pacman -Q xfce4-terminal && pacman -Q thunar && pacman -Q xfdesktop && pacman -Q xfconf && pacman -Q labwc && pacman -Q wlr-randr && pacman -Q xorg-xwayland && pacman -Q xdg-desktop-portal && pacman -Q xdg-desktop-portal-gtk && pacman -Q squeekboard"
install="stdbuf -oL pacman -Syu --needed --noconfirm --noprogressbar noto-fonts xfce4 labwc wlr-randr xorg-xwayland xdg-desktop-portal xdg-desktop-portal-gtk squeekboard"
launch="XDG_RUNTIME_DIR=/tmp WAYLAND_DISPLAY=wayland-0 XDG_SESSION_TYPE=wayland XDG_CURRENT_DESKTOP=XFCE /usr/local/bin/startxfce4-localdesktop 2>&1"
```
Local Desktop uses 3 commands to set up your desktop environment: **Check**, **Install** and **Launch**. Change them in [Local Desktop settings](/docs/user/configurations), under **Additional settings in the app** in Android's App info for Local Desktop, which shows the current ones.

You can change these 3 commands to install and launch your custom desktop environment. Please share your successful setups with us and we can put them here to help others.

:::success Tips
The `try_check`, `try_install`, `try_launch` configs are very handy to try different config values **without breaking anything**. Check out the [Configurations](/docs/user/configurations#special-try_-configs) documentation for more details about `try_*`.
The settings open from Android even when the desktop doesn't start, so a command that doesn't work is easy to undo: change it back, or tap **Restore defaults**.
:::

### check
Expand Down Expand Up @@ -65,14 +58,28 @@ For a legacy **X11 session via Xwayland**, start Xwayland first and point the de

### KDE Plasma

```toml title="/etc/localdesktop/localdesktop.toml"
[command]
try_check = "pacman -Qg plasma"
try_install = "stdbuf -oL pacman -Syu plasma --noconfirm --noprogressbar"
# X11 session via Xwayland
try_launch = "XDG_RUNTIME_DIR=/tmp Xwayland -hidpi :1 2>&1 & while [ ! -e /tmp/.X11-unix/X1 ]; do sleep 0.1; done; XDG_SESSION_TYPE=x11 DISPLAY=:1 dbus-launch startplasma-x11 2>&1"
# Wayland session
try_launch = "XDG_RUNTIME_DIR=/tmp WAYLAND_DISPLAY=wayland-0 /usr/lib/plasma-dbus-run-session-if-needed startplasma-wayland 2>&1"
**Check:**

```bash
pacman -Qg plasma
```

**Install:**

```bash
stdbuf -oL pacman -Syu plasma --noconfirm --noprogressbar
```

**Launch**, a Wayland session:

```bash
XDG_RUNTIME_DIR=/tmp WAYLAND_DISPLAY=wayland-0 /usr/lib/plasma-dbus-run-session-if-needed startplasma-wayland 2>&1
```

Or an X11 session via Xwayland:

```bash
XDG_RUNTIME_DIR=/tmp Xwayland -hidpi :1 2>&1 & while [ ! -e /tmp/.X11-unix/X1 ]; do sleep 0.1; done; XDG_SESSION_TYPE=x11 DISPLAY=:1 dbus-launch startplasma-x11 2>&1
```

![KDE Plasma on Local Desktop](/img/kde.webp)
Expand All @@ -85,6 +92,4 @@ Feedback:

### Others

```toml title="/etc/localdesktop/localdesktop.toml"
Feel free to contribute your configs by using the "Edit this page" link below
```
Feel free to contribute your commands by using the "Edit this page" link below.
59 changes: 17 additions & 42 deletions gh-pages/docs/user/4-configurations.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,28 @@
---
title: Configurations
title: Settings
---

## Config file
## Open the settings

On launch, Local Desktop reads the config file located at:
Local Desktop's settings are in Android, so you can change them even when the desktop doesn't start:

```
/etc/localdesktop/localdesktop.toml
```
1. Touch and hold the Local Desktop icon, then tap **App info**. Or open Android's **Settings** > **Apps** > **Local Desktop**.
2. Tap **Additional settings in the app** (on some phones, a gear icon).

If the content of the config file is invalid (for example, invalid TOML format), it will be **replaced** with the default config. You can still view its original content in:
<img src="/img/settings-step-1.webp" width="32%" alt="Touch and hold the Local Desktop icon, then tap App info" /> <img src="/img/settings-step-2.webp" width="32%" alt="Tap Additional settings in the app" /> <img src="/img/settings.webp" width="32%" alt="Local Desktop settings" />

```
/etc/localdesktop/localdesktop.bak
```
Changes apply the next time Local Desktop starts. **Restart Local Desktop** at the bottom applies them right away.

Some important notes:
- Although TOML does support multi-line strings, Local Desktop requires each config to fit in a **single line**. You can use `\n` for multi-line config values if needed.
- We use **all lowercase** for config **keys**. For config **values**, the content is **case-sensitive**.
## What you can change

## Config schema
| Setting | What it does | Default |
|---|---|---|
| **Use the Android keyboard** | Your phone's keyboard comes up when a text field takes focus, and the desktop fits above it. Turn it off to use Squeekboard, the desktop's own on-screen keyboard. With an external display, the Android keyboard always types. | On |
| **User** | The Linux user the desktop runs as. Create the user first, see [Creating a non-root user](/docs/user/creating-a-non-root-user). | `root` |
| **Check** | A command that succeeds when the desktop environment is installed. | Checks for Xfce |
| **Install** | Installs the desktop environment when **Check** fails. | Installs Xfce |
| **Launch** | Starts the desktop environment. | Starts Xfce |

We might draw a table or have a mechanism to generate the config schema automatically here. But for now, please check the code for the schema: [localdesktop/src/core/config.rs#L28-L87](https://github.com/localdesktop/localdesktop.github.io/blob/main/src/core/config.rs#L28-L87).
See [Using other Desktop Environments](/docs/user/custom-de) for other **Check**, **Install** and **Launch** commands.

## Special `try_*` configs

Some configs are so important that a misconfiguration can leave you stuck on a black screen. So we support a special `try_*` variant of each config. These configs have **higher priority**, but only get applied **once**.

For example, you just have to clone a config and prefix it with `try_`:

```toml
[user]
username="root"
try_username="teddy"
```

The next time Local Desktop starts, it will log in as `teddy` instead of `root`. But then the `try_` configs will be commented out like this:

```toml
[user]
username="root"
# try_username="teddy"
```

So if the config didn't work, and you got stuck on a black screen, you can just restart Local Desktop, and things will go back to normal. Then you can uncomment the config and try with another value. If the config does work, you just have to remove the `try_` prefix to persist the config.

Some important notes:
- This rule applies to **all** configs.
- It is not required for the `try_` config to be inside the same group as the normal config. But it is strongly recommended to do so, and to put the `try_` variant right under its normal variant.
- If a normal config appears multiple times, the **first** entry is applied. If a `try_` config appears multiple times, the **last** entry is applied. This behavior is not guaranteed, and is subject to change. But in general, it is **invalid** to have duplicate config keys inside a TOML file.
- `try_x` and `x` are not duplicate keys. `try_x` always has higher priority than `x`.
If a setting leaves you with a black screen, change it back here, or tap **Restore defaults**.
7 changes: 3 additions & 4 deletions gh-pages/docs/user/7-gpu-acceleration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ On a supported device this prints a renderer like `zink Vulkan 1.4(Turnip Adreno

## Turn it off

If an app misbehaves with the GPU, prefix your [`launch` command](/docs/user/custom-de#launch) with `LOCALDESKTOP_GPU=0`:
If an app misbehaves with the GPU, put `LOCALDESKTOP_GPU=0 ` in front of the **Launch** command in [Local Desktop settings](/docs/user/configurations), for example:

```toml title="/etc/localdesktop/localdesktop.toml"
[command]
try_launch="LOCALDESKTOP_GPU=0 XDG_RUNTIME_DIR=/tmp WAYLAND_DISPLAY=wayland-0 XDG_SESSION_TYPE=wayland XDG_CURRENT_DESKTOP=XFCE /usr/local/bin/startxfce4-localdesktop 2>&1"
```bash
LOCALDESKTOP_GPU=0 XDG_RUNTIME_DIR=/tmp WAYLAND_DISPLAY=wayland-0 XDG_SESSION_TYPE=wayland XDG_CURRENT_DESKTOP=XFCE /usr/local/bin/startxfce4-localdesktop 2>&1
```

To turn it off for a single app, start it with the distro's Mesa instead:
Expand Down
2 changes: 1 addition & 1 deletion gh-pages/docs/user/8-external-display.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The bear in the top left corner of the trackpad shows which way is up.
## Buttons

- **Rotate** turns the phone's screen a quarter clockwise, trackpad and Android keyboard included, for when you lay the phone sideways while auto-rotate keeps it upright.
- **Keyboard** opens the Android keyboard on the phone and types into the desktop. It also opens by itself when a text field on the desktop takes focus, instead of the desktop's own touch keyboard.
- **Keyboard** opens the Android keyboard on the phone and types into the desktop. It also opens by itself when a text field on the desktop takes focus.

![The Android keyboard typing into the desktop](/img/external-display-keyboard.png#boxed)

Expand Down
Binary file added gh-pages/static/img/android-keyboard.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gh-pages/static/img/settings-step-1.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gh-pages/static/img/settings-step-2.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gh-pages/static/img/settings.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed gh-pages/static/img/squeekboard.webp
Binary file not shown.
15 changes: 15 additions & 0 deletions manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ android:
label: "Local Desktop"
extract_native_libs: true # Required for proot invocations
use_cleartext_traffic: true # Required for connecting to ws://127.0.0.1, see assets/setup-progress.html
activities:
# The desktop: android.app.NativeActivity, filled in by the build.
- {}
# "Local Desktop settings" in App info. Its own process, so it still opens while the
# desktop is stuck, and can restart it.
- name: io.github.localdesktop.SettingsActivity
label: "Local Desktop settings"
process: ":settings"
theme: "@android:style/Theme.DeviceDefault.Settings"
exported: true
intent_filters:
- actions:
- android.intent.action.APPLICATION_PREFERENCES
categories:
- android.intent.category.DEFAULT
services:
- name: io.github.localdesktop.KeyboardAccessibilityService
permission: android.permission.BIND_ACCESSIBILITY_SERVICE
Expand Down
4 changes: 4 additions & 0 deletions patches/xbuild/apk/src/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ pub struct Activity {
pub intent_filters: Vec<IntentFilter>,
#[serde(rename(serialize = "android:colorMode"))]
pub color_mode: Option<String>,
#[serde(rename(serialize = "android:process"))]
pub process: Option<String>,
#[serde(rename(serialize = "android:theme"))]
pub theme: Option<String>,
}

/// Android [service element](https://developer.android.com/guide/topics/manifest/service-element).
Expand Down
4 changes: 3 additions & 1 deletion src/android/accessibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ pub enum AppUserEvent {
ExternalDisplayChanged,
/// A mouse (or touch) on the external monitor moved, clicked or scrolled.
ExternalPointer,
/// A text field on the desktop took focus while the phone is a trackpad.
/// A text field on the desktop took focus.
KeyboardRequested,
/// The Android keyboard on the phone's screen came up, changed height or went away.
KeyboardInset,
}

#[derive(Clone, Copy, Debug)]
Expand Down
11 changes: 8 additions & 3 deletions src/android/app/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ use crate::android::{
pipewire_standalone_aaudio,
wayland::{
bind, centralize, centralize_injected_keyboard, dispatch_clients, handle, idle,
on_external_pointer, on_vsync, paint_trackpad, start_frame_loop,
on_external_pointer, on_vsync, paint_trackpad, set_keyboard_inset, start_frame_loop,
write_guest_output_state, CentralizedEvent, State, WaylandBackend,
},
webview::ErrorVariant,
},
external_display,
proot::launch::launch,
utils::{
application_context::get_application_context,
ndk::{self, run_in_jvm},
webview::show_webview_popup,
},
Expand Down Expand Up @@ -85,7 +86,8 @@ fn configure_output(backend: &mut WaylandBackend) {
);

let guest_scale = guest_scale_factor.round().max(1.0) as i32;
let touch_keyboard = winit.external_surface().is_none();
let touch_keyboard = winit.external_surface().is_none()
&& !get_application_context().local_config.android_keyboard;
write_guest_output_state(window_size.w, window_size.h, guest_scale, touch_keyboard);

for surface in backend.compositor.state.xdg_shell_state.toplevel_surfaces() {
Expand Down Expand Up @@ -229,13 +231,16 @@ impl ApplicationHandler<AppUserEvent> for PolarBearApp {
}
}
AppUserEvent::KeyboardRequested => {
if backend.is_trackpad() && backend.window_visible() {
if backend.window_visible() {
run_in_jvm(
external_display::show_keyboard,
self.frontend.android_app.clone(),
);
}
}
AppUserEvent::KeyboardInset => {
set_keyboard_inset(backend, external_display::keyboard_inset());
}
}
}

Expand Down
Loading
Loading