Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Write an article/section for desktop environment developers on how to handle application bundles #103

Open
probonopd opened this issue Aug 7, 2024 · 1 comment

Comments

@probonopd
Copy link
Member

probonopd commented Aug 7, 2024

TODO: Write an article/section for desktop environment developers on how to handle application bundles.

The plethora of currently available "desktop integration" "solutions" are crude workarounds for the fact that most desktop environments do not handle application bundles like .app, .AppDir, and .AppImage natively:

  1. Ask the user whether to set the executable bit when ELF binaries are opened by the user which are lacking this bit
  2. Show the application icon embedded in the bundle
  3. Handle .app and .AppDir opaque (like files rather than folders)
  4. If applications exit with an error code within a few seconds after being launched, show the error in the GUI
  5. etc.

Since i have written file managers (e.g., https://github.com/probonopd/Filer) which do this properly, maybe I should write a description of how to support such application bundles, in the hope that developers of KDE, XFCE, Cosmic, etc. might take interest.

Thanks to @ivan-hc for triggering this idea in a discussion.

@probonopd
Copy link
Member Author

probonopd commented Aug 7, 2024

Version 0.1

Native Support for Application Bundles in Desktop Environments

As desktop environments continue to evolve, it's essential to provide a seamless user experience for applications packaged in various application bundle formats, such as .app, .AppDir, and .AppImage. Currently, many desktop environments are lacking features to handle these bundles, resulting in a subpar user experience. In this article, we'll outline the necessary steps to natively support application bundles, providing a better experience for users and developers alike.

Native support for application bundles is essential for providing a seamless user experience in desktop environments. By implementing the features outlined here, desktop environment developers can improve the usability and functionality of their platforms. We hope that this guide will inspire developers of KDE, XFCE, Cosmic, and other desktop environments to take interest in supporting application bundles natively.

Understanding Application Bundles

Application bundles are self-contained packages that include an application's executable, libraries, and resources. They provide a convenient way to distribute and run applications without requiring complex installation procedures. The most common bundle formats are:

  • .app (used on macOS and by GNUstep on Linux and other OSes)
  • .AppDir (used on Linux and other OSes)
  • .AppImage (used on Linux and other OSes)

Application bundles and packages are two different ways to distribute and manage applications on a computer system. While both provide a way to deliver software to users, they differ significantly in their approach and implications.

Traditional packages (as used on many Linux distributions) are typically installed on the system. They are often installed in a specific location, such as /usr/bin , and are managed by the package manager. Once installed, packages are typically not moved or relocated, as this can break dependencies and cause system instability.

In contrast, application bundles are directories or files that include all the necessary files and resources for an application to run. They are essentially a collection of files and folders that are packaged together to form a single, portable unit. Unlike packages, application bundles do not require installation and can be moved freely around the file system. Users can simply download an application bundle, move it to their desired location, and run it without the need for any additional setup or installation process.

This difference in approach has significant implications for desktop environments, as they can no longer rely on icons or desktop files being placed in specific directories by the installer. Instead, desktop environments must be able to discover and manage applications dynamically, regardless of their location on the system.
This requires a more flexible and adaptive approach to application management.

Requirements

To provide native support for application bundles, desktop environments should implement the following features:

1. Executable Bit Handling

When a user attempts to open an ELF binary without the executable bit set, prompt them to set the bit. This ensures that the application can be executed correctly.

2. Icon Display

Extract and display the application icon embedded in the bundle. This provides a visual representation of the application, making it easier for users to identify and launch the app in the file manager.

3. Opaque Bundle Handling

Treat .app and .AppDir bundles as opaque files, rather than folders.

4. Error Handling

If an application exits with an error code within a few seconds after launch, display the error message in the GUI. This provides users with valuable feedback and helps them troubleshoot issues.

5. Bundle-Specific Launching

Implement bundle-specific launching mechanisms to ensure that applications are launched correctly. For example, .AppDir bundles require the AppRun file to be executed, while .AppImage files just need to be executed.

6. Advanced topics

The above should already give a reasonably good user experience. However, it can be further improved by also implementing:

  • Desktop menus and launchers
  • File associations (scan the file system for available applications, update their file association databases accordingly)
  • Drag-and-drop support
  • Update mechanisms

(Section to be detailed)

Implementation guidelines

1. Executable Bit Handling

When a user attempts to open an ELF binary without the executable bit set, the system should prompt them to set the bit via a GUI dialog box.

The GUI dialog box should include a message indicating that the file is an executable binary, and should ask the user if they trust the application and want to execute the application. If the user confirms, the system requests administrative privileges if necessary for changing the permissions, and sets the executable bit (chmod +x). After setting the executable bit, the system retries the original attempt to open the ELF binary. If the bit is now set correctly, the application should execute correctly.

Best practice implementation: TBD (TODO: Add screenshot)

2. Icon Display

When displaying application bundles, they should not use the folder icon. Instead, they should load the application icon from the following locations:

  • .app: Contents/Resources/Icon.icns or Contents/Resources/Icon.png inside the directory
  • .AppDir: .DirIcon inside the directory. Should be png (preferred), but might not hurt to also check for other usable formats such as ico, icns, jpg, svg(z), etc.
  • .AppImage: .DirIcon inside the disk image file. Should be png (preferred), but might not hurt to also check for other usable formats such as ico, icns, jpg, svg(z), etc. To access files inside the disk image file, zisofs compressed ISO images at an offset and squashfs images at an offset must be read, e.g., using appropriate libraries. (It is said that 7z can do this; to be verified.) The offset at which the filesystem image begins is equal to the length of the ELF binary prepended to it, and will differ between AppImages. See the AppImageSpec on details of the file format. To determine the offset to the filesystem image, calculate the size of the ELF on disk. https://github.com/probonopd/elfsize and https://github.com/probonopd/libelfsize contain C code to do this. When extracting files from the squashfs filesystem image, symlinks need to be followed. See https://github.com/linuxmint/xapp-thumbnailers/blob/master/files/usr/bin/xapp-appimage-thumbnailer for an example using Python and unsquashfs to extract the icon from a type-2 (squashfs) AppImage.

The icons should not be copied to some location outside of the application bundle such as /usr/share/icons or ~/.local/share/icons, but only be used for display in the window. If a caching mechanism is desired, then there must also be a cleanup mechanism (e.g., similar to the cleanup mechanism for XDG thumbnailers).

If no application icon is found at these locations, then a fallback default application icon (e.g., the same one shown for generic ELF files) should be used.

This applies to the file manager but also to file open/save dialogs, etc.

3. Opaque Bundle Handling

When a directory with the .app or .AppDir suffix is double-clicked in the file manager, then it should be checked whether it contains a launchable executable (see the section on application launching) and if it does, trying to open the directory should not open it as a folder, but should launch the executable instead.

A context menu item should be there to open the directory as a folder, e.g., called "Show Contents".

4. Error Handling

Most desktop environments just disregard application output to stderr when launched outside of a terminal. To provide a better user experience, desktop environments should implement a mechanism to capture and display error messages from launched applications and display them in the GUI. This can be achieved through the following steps:

  1. Launch Helper: Create a launch helper component that is responsible for launching applications and capturing their output and errors. This component can be a separate process, a library, or even a part of the desktop environment's core functionality. It does not need to be a daemon, and can be created and destroyed as needed.
  2. Virtual Terminal Device: When launching an application, create a virtual terminal device to capture the output and errors of the application. This allows the launch helper to interact with the application as if it were a real terminal. The virtual terminal device can be created using platform-specific APIs.
  3. Output Redirection: Redirect the output of the application (including errors) to the virtual terminal device. This allows the launch helper to capture the output and errors of the application. Platform-specific APIs can be used to redirect the output, such as dup2() on Unix-like systems or SetStdHandle() on Windows.
  4. Error Detection and Parsing: Monitor the output of the application for errors. When an error occurs, detect it and parse the output to identify well-known error types, such as:
    • Missing dependency libraries
    • Permission errors
    • File not found errors
    • etc.
      By parsing the output, the launch helper can display well-formatted error messages that provide more context and are easier to understand.
  5. GUI Error Message: Display the error message in a GUI dialog box, which is a native window of the desktop environment. This allows the user to see the error message and take action accordingly. The GUI error message dialog box can be created using platform-specific APIs, such as QMessageBox on Qt or gtk_message_dialog_new() on Gtk,

Best practice implementation: Haiku (TODO: Add screenshot)

5. Bundle-Specific Launching

(Section to be written)

6. Advanced topics

(Section to be written)

Aspects missing in XDG Specifications

(Section to be written)

Contact

Feel free to ping me @probonopd if you have something I could give feedback on or could test. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant