Files
MosisService/docs/DESKTOP-DESIGNER.md
omigamedev bd8ce61897 fix Music app layout and document RmlUi encoding issue
- Fixed Music app layout using incremental edit approach
- Documented RmlUi file encoding issue in DESKTOP-DESIGNER.md
- Added workaround: copy from working file and edit incrementally
2026-01-20 19:27:15 +01:00

8.8 KiB

Desktop Designer

The desktop designer (designer/) provides rapid UI development with:

  • Hot-reload: Automatically reloads when RML/RCSS/Lua files change
  • Shell Mode: Persistent system UI (status bar, nav bar) with apps loading into container
  • UI Hierarchy Dumping: Exports element tree to JSON for inspection
  • Screenshot Capture: PNG export via F12 key
  • Logging: Detailed output for debugging navigation and events
  • Action Recording: Record mouse/keyboard interactions to JSON
  • Action Playback: Replay recorded interactions with timing

Key Files

File Purpose
designer/main.cpp Main entry point, GLFW window, event loop
designer/src/desktop_sandbox.cpp Per-app sandbox isolation
designer/src/app_discovery.cpp Scans directories for app manifests
designer/src/testing/ui_inspector.cpp UI hierarchy JSON export
designer/src/testing/visual_capture.cpp PNG screenshot capture
designer/src/testing/action_recorder.cpp Record user interactions
designer/src/testing/action_player.cpp Playback recorded actions

Command Line Options

General:
  --resolution WxH    Set window resolution (default: 540x960)
  --assets PATH       Set assets directory (default: derived from document)
  --log FILE          Write all log messages to file
  --hierarchy FILE    Continuously dump UI hierarchy to JSON

Simulator mode:
  --simulator         Run in simulator mode (uses shell by default)
  --no-shell          Disable shell (use direct document loading)
  --test-apps PATH    Path to test-apps directory (default: ./base-apps)

Test modes:
  --record FILE       Record user actions to JSON file
  --playback FILE     Playback actions from JSON file
  --screenshot FILE   Take screenshot and exit
  --dump-hierarchy FILE  Dump UI hierarchy to JSON and exit

Running the Designer

cd MosisService
./designer/build/Release/mosis-designer.exe --simulator --test-apps base-apps

This will:

  • Load the system shell with persistent status bar and navigation bar
  • Load home screen content into the shell's app container
  • Scan base-apps/ for apps with valid manifest.json
  • Enable app navigation with proper back button support

Simulator Mode without Shell

To test the old direct-document approach:

./designer/build/Release/mosis-designer.exe --simulator --test-apps base-apps --no-shell

Direct Document Mode

To load a specific RML document directly:

./designer/build/Release/mosis-designer.exe path/to/document.rml

Keyboard Controls

Key Function
F5 Reload document / Start-stop recording
F12 Toggle RmlUi debugger
ESC Back navigation
R Start/Stop recording (in interactive mode)

Shell Architecture

The shell (apps/shell/) provides a persistent system UI layer that prevents apps from taking over the full screen.

Shell Components

┌──────────────────────────────┐
│     Status Bar (36px)        │  ← Time, WiFi, Signal, Battery
├──────────────────────────────┤
│                              │
│     App Container            │  ← App content loads here
│     (flex: 1)                │
│                              │
├──────────────────────────────┤
│     Navigation Bar (56px)    │  ← Back, Home, Recents
└──────────────────────────────┘

Overlay Layers (z-index order):
- Dialog overlay (z: 600)      ← Modal dialogs
- Toast container (z: 500)     ← Toast notifications
- Notification panel (z: 400)  ← Pull-down notifications
- Loading overlay (z: 300)     ← App loading spinner

Shell Files

File Purpose
apps/shell/shell.rml Shell document with status bar, nav bar, overlays
apps/shell/shell.lua Navigation, toasts, dialogs, notifications

App Content Fragments

Apps in shell mode use content fragments (*_content.rml) instead of full documents:

<!-- camera_content.rml - No <rml>, <head>, or document structure -->
<style>
    .camera-content { ... }
</style>

<div class="camera-content">
    <!-- App UI here -->
</div>

Shell Lua API

Functions available to apps via shell:

-- Navigation
shellNavigateTo("settings")      -- Navigate to system app
shellLaunchApp(id, path, entry)  -- Launch external app
shellGoBack()                    -- Go to previous app
shellGoHome()                    -- Go to home (clear history)

-- UI Feedback
showToast("Message")             -- Show toast notification
showToast("Error!", "error")     -- Toast types: default, success, error, warning
showDialog("Title", "Message", onConfirm, onCancel)

-- Notifications
addNotification("Title", "Text", icon, app_id)
toggleNotifications()            -- Show/hide notification panel
clearNotifications()

Creating Content Fragments

  1. Create appname_content.rml (not a full document)
  2. Include styles via <style> tag
  3. Use shell functions for navigation (shellNavigateTo, showToast, etc.)
  4. Don't include status bar or nav bar (shell provides these)

Example:

<!-- settings_content.rml -->
<style>
    .settings-list { padding: 16px; }
    .settings-item { padding: 16px; cursor: pointer; }
</style>

<div class="settings-list">
    <div class="settings-item" onclick="showToast('WiFi settings')">
        WiFi
    </div>
    <div class="settings-item" onclick="showToast('Bluetooth settings')">
        Bluetooth
    </div>
</div>

Content Fragment Locations

App Content Fragment Path
Home apps/home/home_content.rml
Camera apps/camera/camera_content.rml
Dialer apps/dialer/dialer_content.rml
Messages apps/messages/messages_content.rml
Browser apps/browser/browser_content.rml
Settings apps/settings/settings_content.rml
Music apps/music/music_content.rml
Store apps/store/store_content.rml
Contacts apps/contacts/contacts_content.rml

Hot Reload

The designer watches for file changes in the assets directory:

  • RML files: Reloads document
  • RCSS files: Reloads stylesheets
  • Lua files: Reloads scripts
  • TGA/PNG files: Reloads textures

Press F5 to force reload.

UI Hierarchy Dump

Use --hierarchy to continuously dump the UI element tree:

./designer/build/Release/mosis-designer.exe --simulator --hierarchy ui_tree.json

The JSON contains element bounds, classes, IDs, and visibility - useful for automated testing.

Action Recording and Playback

See TESTING-FRAMEWORK.md for details on recording and playing back UI interactions.


Known Issues and Workarounds

RmlUi Layout Breaking Due to File Encoding

Problem: Content fragments created with certain file-writing methods may render with broken layouts - elements appear with 0 width, text wraps excessively, and flex layouts collapse.

Symptoms:

  • List items don't expand to full width
  • Text wraps to very narrow columns
  • Avatars/icons overlap with text
  • UI hierarchy shows "width": 0.0 for elements that should have proper width

Root Cause: RmlUi's parser is sensitive to certain invisible file formatting. While files may appear identical in text editors and have the same line endings (CRLF), subtle encoding differences can break layout parsing.

Diagnosis: Use --hierarchy FILE flag to dump UI element dimensions:

./designer/build/Release/mosis-designer.exe --simulator --playback tests/test_app.json --hierarchy hierarchy.json

Check the JSON for elements with "width": 0.0 that should have proper dimensions.

Workaround: Instead of creating content fragments from scratch, copy an existing working file and modify it:

# 1. Copy a known working file (e.g., messages_content.rml)
cp src/main/assets/apps/messages/messages_content.rml src/main/assets/apps/myapp/myapp_content.rml

# 2. Edit the file incrementally (use sed, text editor, or Edit tool)
# DO NOT rewrite the entire file - preserve the original byte structure

# 3. Test the layout
./designer/build/Release/mosis-designer.exe --simulator --playback tests/test_myapp.json --screenshot-after test.png

Working Reference Files:

  • apps/messages/messages_content.rml - Known good file format
  • apps/store/store_content.rml - Created by copying from messages
  • apps/settings/settings_content.rml - Created by copying from messages

Prevention: When creating new content fragments:

  1. Always start by copying an existing working content fragment
  2. Make incremental edits rather than full file rewrites
  3. Test layout after changes using --hierarchy flag