Haiku operating system: porting applications and creating packages

Published on December 28, 2018

Haiku operating system: porting applications and creating packages

    In the autumn of this year, after 6 years of development, the first beta version of the Haiku operating system R1 / beta1 was released . I have been following this interesting project for a long time, which is aimed at the reconstruction and subsequent development of the BeOS system that existed in 1994-2000 . Therefore, as soon as I saw news on the release of the beta version of Haiku on IT news sites, I immediately decided to see what was added to this long-awaited release. After installing the system in a VirtualBox virtual machine and a little familiarization with its main functionality, I thought that it would be nice to help the OpenSource community, which is developing this operating system today. I decided to start with what I have gained a little experience: with porting some game projects.


    Desktop Haiku operating system.

    Later I tried to modify some already existing applications and libraries. This is my small activity in various open source repositories that this article will be devoted to. In it, I will successively describe the problems I encountered and tell you about the methods for solving them. Most of the patches that were made in the course of this work, I tried to send upstream existing projects in order to provide support for Haiku and interest their developers in the existence of alternative operating systems.

    The Haiku operating system uses a hybrid core , which is an implementation of the micronuclear architecture with the ability to dynamically load the necessary modules. It is based on the fork of the NewOS kernel , which was developed by a former Be Inc. engineer . , By Travis Geiselbrecht. Today, this developer is working at Google on a kernel called Zircon for the new Google Fuchsia operating system , but that's another story. So, since the Haiku developers declare binary compatibility with BeOS, they are forced to maintain not two architectural branches that are familiar to everyone, but three: x86_64, x86 and x86_gcc2. The latest architecture is the compatibility load with the old compiler.Gcc2.95. Thanks to it, it is possible to launch applications written for the original BeOS operating system. Unfortunately, due to this compatibility load, Haiku developers cannot use the advanced features of the C ++ programming language in the system APIs. However, they prepare installation images only for two architectures: x86_64 and x86. The fact is that the Haiku distribution for x86 is a hybrid one: despite the fact that all system components are built under x86_gcc2 to provide binary compatibility, the user is given the opportunity to install or build any modern applications that were made with modern compilers and x86 architecture . The x86_64 Haiku distribution is fully 64-bit and does not have the ability to run 32-bit BeOS and Haiku applications. But, there is compatibility at the API level, so if you have the source code for the application under BeOS or Haiku x86, you can easily compile it under Haiku x86_64 and everything should work. An x86_64 operating system image is recommended for installation on real hardware, if you do not require support for any specific BeOS applications or 32-bit Haiku applications.

    It is worth saying that this operating system has partial support for the POSIX standard . This foundation makes it akin to UNIX-like systems and makes it easy to port their software. The main programming language is C ++, it is actively used, since Haiku's public APIs mainly pursue an object-oriented programming paradigm. However, no one forbids the use of the C programming language, only for most cases you will have to write the appropriate compatibility layer. The operating system software interface is grouped into separate system frameworks that are responsible for a particular opportunity, for example, the interface or network support. This is a bit like what is in macOS or in the frameworkQt . It is necessary to note that this operating system is single-user, although there are some progress towards providing a multi-user mode of work for Haiku developers.

    I can not share with the readers of this article, the positive experience of using the advanced window management system of applications, which is available in Haiku. In my opinion, it is one of the most convenient and of its kind is the hallmark of this OS.


    Advanced window management in the Haiku operating system: support for tiling and tabs.

    Windows can be fastened together in tabs, as is done in modern browsers, attach them to each other and conveniently change their size. Simple tiling , context transfer of some applications from one window to another, and replicants are supported . For more information about all the features of the local window system can be found in the official documentation , there are also described all the necessary shortcut keys.

    I will not write in this article a complete overview of all the features and capabilities of Haiku, since those who are interested in it will easily be able to independently find the necessary information on the Internet.

    Content:


    1. Packages and repositories in Haiku
    2. First steps: porting Adamant Armor Affection Adventure
    3. Completing the existing NXEngine port (Cave Story)
    4. Porting Gish games
    5. BeGameLauncher project that allows you to quickly create game launchers
    6. Xash3D porting: legendary Half-Life game and official additions
    7. Porting the two parts of the game Serious Sam: The First Encounter and The Second Encounter
    8. Porting the game Vangers
    9. Implementing dialogs in the SDL2 library for Haiku
    10. Porting my fork of the program Cool Reader
    11. Improvement of the program KeymapSwitcher
    12. Conclusion

    1. Packages and repositories in Haiku


    Compared to the original BeOS, Haiku has a significant innovation: the package management system, which includes various tools for getting and installing software from various sources. Such sources can be official Haiku and HaikuPorts repositories ., informal repositories and just separate and specially prepared HPKG packages. Such opportunities for installing and updating software have long been known in the world of Unix-like operating systems, but now all their power and convenience have successfully reached Haiku, which cannot but make ordinary users of this operating system happy. Thanks to the infrastructure manager built around the package manager, now any developer can easily port a new or modify an existing open source application, then add the results of his work to the ports repository of HaikuPorts software, after which they will be available to all Haiku users. As a result, the resulting ecosystem resembles that of macOS with their Homebrew , FreeBSD with their ports., Windows with MSYS2 or Arch Linux with its AUR 'om.

    A tool for building packages and porting software, called HaikuPorter , comes separately from the operating system and installs on a small manual located in the repository on GitHub. After installing this utility, the entire recipe tree is downloaded from the same GitHub and the developer works on it. The recipe is a regular Shell script with instructions on which HaikuPorter will build the required HPKG package. It is noteworthy that the tool itself is written in the Python programming language.2, closely interacts with the existing package management system, and for fixing changes in the software source code and generating a set of patches, inside it uses a standard tool - Git . Thanks to this stack of technologies, it is very easy and simple to make recipes for assembling HPKG packages and patch sets to software in the form of patchset files. In most cases, I had to use only three commands when working with HaikuPorter:

    alias hp="haikuporter -S -j4 --get-dependencies --no-source-packages"
    hp libsdl2
    hp libsdl2 -c
    hp libsdl2 -e
    

    The first command simply collects the selected package, the second command clears the build directory, and the third creates or updates the patch set according to your changes, which were recorded in the Git-repository of the working directory via commits.

    Thus, to publish a package to the HaikuPorts repository and make it available to all Haiku users, the developer must install the HaikuPorter, expand the recipe tree, locally build the HPKG package and test it, then make a commit in its fork of the recipe tree, then draw Pull requeston github. The published work must be considered by the Haiku developers, after which they decide to pour your changes into the repository or send them for revision. If changes are accepted, then the same HaikuPorter installed on the build server will remotely assemble the package and automatically publish it to the repository.

    A special HaikuDepot program was added to the beta version of R1 / beta1 of the Haiku operating system , which allows you to work with packages and repositories through a graphical user interface, rather than via console commands in the terminal.


    The HaikuDepot program running on the Haiku operating system.

    Thanks to this tool, inexperienced and novice Haiku users can conveniently manage their package base. It should be noted that this application is not just a GUI shell over the existing package manager, but also implements additional functionality. For example, authorized users can rate and write reviews for packages available for installation. In addition, HaikuDepot has a special Haiku Depot Web site that allows you to view changes to the package base on the Internet or download individual HPKG packages.

    << Skip to content

    2. First Steps: Porting the Adamant Armor Affection Adventure Game


    After I familiarized myself with the functionality of the operating system in the VirtualBox virtual machine, I decided to evaluate the work of the SDL2 library in it and port the Adamant Armor Affection Adventure game to Haiku , about which I wrote to the Android platform earlier. Building the program did not require any changes to the source code, I just installed all the necessary tools, libraries, their header files from the repository and did the following:

    cmake -DCMAKE_BUILD_TYPE=Release -DGLES=off -DANDROID=off -DCMAKE_C_FLAGS="-D__linux__" -DSDL2_INCLUDE_DIR=`finddir B_SYSTEM_HEADERS_DIRECTORY` -DSDL2_MIXER_INCLUDE_DIR=`finddir B_SYSTEM_HEADERS_DIRECTORY` ../aaaa/src/main/cpp
    cmake --build .
    

    Since Haiku has the POSIX, the defayny -D__linux__ or -D__unix__ solves many problems associated with the definition of a platform. However, it is worth noting that it is best to abandon their use and implement support for Haiku in the source code of the project, if there are similar problems with the assembly. Calling the system utility finddir with a specific argument allows you to get the correct path to the header files for different architectures.

    So, having executed the commands above, I compiled an executable file that started perfectly, and the game worked fine. I thought that it would be cool to prepare a self-sufficient HPKG package with the game and for this I went deep into the Internet in search of the information I needed. Then I didn’t know about any convenient tools for porting software, like HaikuPorter, which I wrote about in the section above, so for the realization of my goal I decided to cheat and disassemble any system package to see how it works inside and done by analogy.

    On the Internet, I found the desired information , then unpacked a random system package using the Expander archiver built into the local file manager , found the .PackageInfo file, edited it and, in accordance with the structure of your application, changed files. Then I just executed the commands to build the HPKG package and install it into the system:

    package create -C AAAA/ aaaa.pkg
    pkgman install aaaa.pkg
    

    Unfortunately, the launch of the game from the “Applications” menu was not successful. Having run the executable file in the terminal, I received an error saying that it was impossible to find the data files that were necessary for the launch and operation of the application. At the same time, if you go to the application package directory in the terminal, then everything started up normally. This gave me the idea that when you start the game from the menu you need to make a forced change to the application directory. This can be done either with a shell script or by changing the source of the game. I chose the second option and added something similar to this code:

    #ifdef __HAIKU__
        // To make it able to start from Deskbar
        chdir(dirname(argv[0]));
    #endif
    

    At the very beginning of the start function main () , which completely solved this problem and the package turned out to be workable. In the comments on the news about the release of the Haiku beta on Linux.org.ru, I dropped a link to my assembled package and asked someone to send me to some active communities of users of this operating system, then went to bed.


    The port of the game Adamant Armor Affection Adventure, running on the Haiku operating system.

    In the morning I wrote an e-mail to a person using the nickname 3dEyes . As it turned out later, Gerasim Troyeglazov , one of the active developers of Haiku and the author of the port of the Qt framework for this operating system, was hiding behind this name . He showed me the HaikuPorts repository and told me how to use the HaikuPorter utility. In addition, he wrote a recipe for building the Adamant Armor Affection Adventure HPKG package and added it to HaikuDepot.

    After analyzing all the changes made by this developer, I noticed that there were some flaws in my manually assembled package, for example, the settings were not saved because the mounted directories of the installed packages did not have the ability to write. This problem with writing settings or saving in its package was elegantly solved with the help of symlinks in a special recordable directory for saving user data. My package also did not have its own original icon.

    In addition, I learned that in Haiku there is no hardware acceleration of 3D graphics and the same OpenGL is drawn programmatically using CPU power. For heavy graphics applications this, of course, is no good, but for old games this is more than enough. I even decided to specifically check the game package and installed Haiku on my old laptop, that is, on real hardware. To my surprise, the Adamant Armor Affection Adventure picture rendered so fast that if I hadn’t been told about the lack of hardware acceleration, I wouldn’t have noticed that the rendering is done by my processor.

    Project Source Code: https://github.com/EXL/AdamantArmorAffectionAdventure

    I postponed the manual creation of HPKG packages until better times and completely switched to using the HaikuPorter tool and writing recipes. But sometimes there are situations when manual reassembly is required. For example, if HaikuPorter has set the “night” version of Haiku too high in the .PackageInfo file , the package should be tested on the release version of the operating system. It is worth noting that it was thanks to Gerasim’s responsiveness and experience that I was able to understand many of the intricacies of creating packages for the Haiku operating system and continued my work further.

    << Skip to content

    3. Completion of the existing port NXEngine (Cave Story)


    I was incredibly surprised to find in the HaikuPorts repository a recipe that referred to my fork of the NXEngine engine for the game Cave Story , which I had been analyzing for a long time on my blog. The recipe and patches were prepared by a developer named Zoltán Mizsei , who uses the nickname extrowerk and is the active maintainer of many packages for Haiku.

    Surface analysis, package installation and application launch revealed the same problems that I described in the previous section of this article: saving the game did not work, the settings were not saved either, and besides the package did not have the original icon. I decided to correct these shortcomings and started working on the patch, first integrating all the extrowerk's work. I wrote the original Makefile for the Haiku operating system and corrected the recording and saving of various user data.


    The port of the game Cave Story based on the NXEngine engine, launched in the Haiku operating system.

    Since the game assumed Russian and English versions with a different set of executable files and data files, I decided to make a general package that combines two versions at once and automatically selects the necessary one based on the system language chosen by the user. This was implemented by the simplest shell script:

    #!/bin/bash
    if [[ `locale -l` == ru* ]] ;
    then
        EXE="`finddir B_SYSTEM_APPS_DIRECTORY`/NXEngine/RUS/Cave Story"
    else
        EXE="`finddir B_SYSTEM_APPS_DIRECTORY`/NXEngine/ENG/Cave Story"
    fi
    "$EXE" $@
    

    This script is launched when the game item is selected in the “Applications” menu and determines the current system locale. In the event that the user chose Russian as the system language, the Russian version of the game will be launched, and in all other cases - the English version.

    But with the creation of the original icons for the application had to pretty tricky. The fact is that in the Haiku operating system, only vector icons of a special HVIF format are allowed , which are set as attributes of the Be File System file system . In the official documentation, there are two large manuals dedicated to creating your own icons for applications: the first manual describes the styling and design, and the second manualexplains in detail how to use the Icon-O-Matic system software for creating icons.

    Icon-O-Matic allows you to import simple SVG files and export the resulting icon to the necessary format for HaikuPorter, called HVIF RDef, which is the same HVIF, but converted to text. RDef files can contain not only images, but also additional information, for example, the version of the application and its description. Something these files resemble RES-files used in Windows. The following commands in the recipe compile RDef files and set the result to special attributes:

    rc nxengine-launcher.rdef
    resattr -o "$appsDir/NXEngine/Cave Story" nxengine-launcher.rsrc
    addResourcesToBinaries $sourceDir/build/nxengine-rus.rdef "$appsDir/NXEngine/RUS/Cave Story"
    

    In addition, the recipes define the addResourcesToBinaries function to automate this work. The problem with the Icon-O-Matic program is one, but very serious: those SVG files that are saved by the popular vector editor Inkscape, either do not open, or are imported without the support of some necessary features, for example, gradients. Therefore, an adventure quest with converting raster images into vectors through the use of various paid and free online and offline converters, and then opening the resulting SVG files in Icon-O-Matic, I failed miserably. Later, I solved the problem of opening SVG files and found a workaround, but I'll write about this below. In the meantime, I decided to use the standard features of Icon-O-Matic and draw an icon on my own. After half an hour of work on hard copying pixels, I got the following art:


    The standard program is Icon-O-Matic in the Haiku operating system.

    Yes, I used a vector editor to create an image in the Pixel Art genre. In my amateurish opinion, a person who is poorly versed in art, turned out quite well. I saved this icon in the right format, prepared all the changes, updated the recipe and sent everything to the HaikuPorts repository.

    Source code of the project: https://github.com/EXL/NXEngine

    I sent the resulting packages just in case to the fan site of the game Cave Story (Doukutsu Monogatari) , the administration of which added the Haiku operating system to the download section.

    << Skip to content

    4. Porting the Gish game


    The next project I decided to transfer to Haiku was Gish , which I previously transferred to Android. In the HaikuPorts repository there was a recipe for an unfinished free implementation of the game called Freegish , so I decided to add the original game there, but without the data files, since they, unlike the engine, are supplied separately and are not free at all.


    The port of the game Gish, launched in the Haiku operating system.

    I had no particular problems with porting this game. The executable file was assembled immediately after the execution of the following build commands:

    cmake gish/src/main/cpp/ \
        -DGLES=0 \
        -DANDROID=0 \
        -DSDL2_INCLUDE_DIR=`finddir B_SYSTEM_HEADERS_DIRECTORY` \
        -DCMAKE_C_FLAGS="`sdl2-config --cflags` -D__linux__" \
        -DCMAKE_BUILD_TYPE=Release
    cmake --build .
    

    Next, I implemented the ability to launch the game from the “Applications” menu and provided support for storing user data in a writable and dedicated directory:

    char* getHaikuSettingsPath()
    {
        char path[PATH_MAX];
        find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, path, sizeof(path));
        strcat(path, "/Gish/");
        return strdup(path);
    }
    

    The getHaikuSettingsPath () function using the find_directory () function from the Haiku API generates the full path to the directory I need.

    The source code of the project: https://github.com/EXL/Gish

    It remained to solve the following question: how should the user choose the directory with the original files of the Gish game? The problem could be solved using Shell-scripts and the alert system utility , but I decided to approach this problem more thoroughly and implement a convenient GUI launcher using the Haiku API and the Interface Kit framework .

    << Skip to content

    5. The project BeGameLauncher, which allows you to quickly create launchers for games


    My project BeGameLauncher was decided to write in C ++ the old standard of 1998, using native operating system tools for creating applications with a graphical user interface. Since the names of many programs for Haiku and BeOS begin with the re-fix “Be”, I also decided to choose such a name for the project. I decided to start with an introduction to the Interface Kit framework, which is part of the Haiku API. In addition to sufficiently detailed documentation on the official Haiku website, I found two simply excellent courses of lessons from DarkWyrm , which allow the novice developer to quickly understand how certain system classes work. The first course is called Learning to Program with Haikuand at the very beginning it touches the basics of the C ++ programming language, which will be very useful for novice programmers. The second course is called Programming With Haiku and is intended for those who are already familiar with C ++ and have a basic knowledge of this language. Both courses talk about the most diverse aspects of the Haiku API and therefore will be very helpful to anyone who wants to start building applications for this operating system.

    After reading this excellent material diagonally, I made a general impression of the Haiku API and began to consider my further actions. I already had some experience developing application applications using the Qt framework, which is also written in the C ++ programming language and uses the object-oriented paradigm of building programs. So, the Haiku API is very similar to it, except for the absence of a system of signals and slots, so I will often carry out some parallels and comparisons with Qt. In addition, it is worth noting the use of the principle of Event-driven programming , which is common in Haiku API , which allows various entities to interact with each other by transmitting events or messages. An analogue of the QEvent class here is the classBMessage , around which the system of interaction of objects is built. An instance of the BMessage class generally gets a unique number that allows you to identify the sender and its action in the general event filter.

    For my project, it was necessary to select the appropriate Haiku API classes that would allow to implement the conceived functionality. First, to launch an external application, it was necessary to find an analogue of the QProcess class or the POSIX execve () function , which, by the way, also works fine in the Haiku operating system, but I decided that using native tools would be preferable, but just case left the ability to run applications through the POSIX-function. BRoster classInterprocess communication is well suited for this purpose. It found the appropriate Launch () method , which allows you to set the path to the executable file and pass arguments to it. Since the launcher should be able to save some parameters, for example, a user-selected directory with game data files, I needed a class that does all this. In Qt, this class has the name QSettings , and in the Haiku API, as Gerasim suggested to me, there is a class BMessage already familiar to mewhich has a very useful feature. The thing is that information of this class can be easily serialized and, for example, saved to disk. This is very convenient and is often used to record any user data in programs, so I chose this class to save the settings in my project for the implementation of launchers. Unfortunately, the Haiku API did not find an analogue of the QDebug class , so the debug output I needed during the development process was simply sent to stderr using the fprintf () function from the standard C programming language:

    // .h
    #if __cplusplus >= 201103L
    #define BeDebug(...) fprintf(stderr, __VA_ARGS__)
    #else
    extern void BeDebug(const char *format, ...);
    #endif // __cplusplus == 201103L
    // .cpp
    #if __cplusplus < 201103L
    #include <cstdarg>
    void
    BeDebug(const char *format, ...)
    {
        va_list args;
        va_start(args, format);
        vfprintf(stderr, format, args);
        va_end(args);
    }
    #endif
    

    I wrapped this function in the BeDebug () entity , which is convenient for me , which, depending on the standard of the language chosen, is either a macro or also a function. This was done because C ++ 98 does not support macros with a variable number of arguments.

    Still in the Qt framework, there is a useful QMessageBox class through which you can create a modal dialog with any information that the user should pay attention to, for example, an error or a warning. The Haiku API has a BAlert class for this purpose ., the implementation of which is somewhat different from what is available in Qt. For example, an object of this class must be created on the heap, not on the stack, because after some user action, it must delete itself. As for the other classes of the graphical interface, here I had absolutely no difficulties and I found everything I needed without any problems.

    Now I should have thought of a simple project architecture. I decided to dwell on the creation of a static library in which there would be two classes designed to inherit from their own derived classes. The first and most important class, BeLauncherBase, is responsible for creating the main launcher window, transferring all user parameters and provides the ability to add your own GUI elements. The second class, BeAboutWindow , is simply responsible for opening the “About program ...” dialog with information that is displayed in a separate window. Thus, a programmer to create his own launcher, for example, to play Gish, needs to do two simple steps:

    class GishAboutWindow : public BeAboutWindow
    {
        ...
    };
    class GishLauncher : public BeLauncherBase
    {
        ...
    };
    int
    main(void)
    {
        BeApp *beApp = new BeApp(SIGNATURE);
        GishLauncher *gishLauncher = new GishLauncher(BeUtils::GetPathToHomeDir());
        beApp->SetMainWindow(gishLauncher);
        beApp->Run();
        delete beApp;
        beApp = NULL;
        return 0;
    }
    


    First, create a suitable starting function main () , and second, simply inherit from the two classes listed above and implement the necessary methods in them. After that, we compile the resulting C ++ file with a link to my static library and our launcher for the Gish game is ready.


    The "About the program ..." dialogue in the port launcher of the game Gish.

    Next, I thought about how to transfer parameters from my launcher to the engine itself or to the executable file of the game. I saw only two ways to solve this problem. The first way was to change the environment variables. In practice, the launcher, after clicking on the “Run” button, simply puts all the parameters into environment variables through calls to the setenv () function , and the game engine then reads these parameters using the getenv () function , which looks quite simple. The only problem that could arise here was in the class BRoster and its method of Launch (): I did not know whether the application launched using this class will inherit all the environment variables that were set in the launcher. After a small experiment, the inheritance of environment variables was confirmed and I fully implemented this method in my project. The second way to solve the problem was to set special command line parameters. In practice, the launcher simply added all the settings to the appropriate arguments and called up the executable file of the application with them. But the game engine already had to process them independently, which created some difficulties. For example, if the game did not assume the possibility of specifying the path to the game files through command line parameters, then it was necessary to modify the argument parser in the engine itself. Despite these problems, I implemented this way of interaction and as a result I received an excellent opportunity to combine everything together. This allowed me to create in some launchers a string specifying custom arguments.

    When everything was designed, I decided to choose an assembly system for my project. Only two options were considered: Makefile "on steroids" and CMake . In the first case, the developers of the Haiku operating system prepared a convenient makefile-engine package in which they collected all the necessary features that the developer would have encountered when they started writing an application on the Haiku API, for example, automatically generating translations and compiling application resources. But I'm not one of those who are looking for easy ways, so I chose CMake and transferred to it some developments from the makefile-engine package. As a result, the resulting monstrous assembly script can be viewed in the project repository, a link to which I will leave below.


    Screenshot port launcher game Gish for Haiku.

    I would like to write a few words about the localization of applications. In the Qt framework, there is a convenient tr () wrapper function , two helper utilities lrelease and lupdate , which are engaged in generating translation files. Included with the framework is available even a special program Qt Linguist with a convenient graphical user interface designed for translators. The Haiku API tools for localizing applications are less convenient and more archaic. It is proposed to wrap the lines to be translated into a special macro B_TRANSLATE () , and add the definition B_TRANSLATION_CONTEXT to the source filewhich separates one group of translatable strings from another. After that, you need to do a very strange thing: set the compiler's preprocessor with the -DB_COLLECTING_CATKEYS flag on absolutely all project source files, do some magic using the grep utility, and eventually get a huge size PRE file. The collectcatkeys utility , which already creates human-readable and easy-to-edit CATKEYS files, will work with this file . After localizing the strings, you need to use the linkcatkeys utility .which adds translations to the resources of the executable file. Thus, when you select a specific system language, the application displays the translated strings. Strange, but the Haiku API documentation about application localization contains very little information. However, on the official website I found an excellent article Localizing an application , which examined in detail many aspects of the translation of applications for this operating system. As I understand it, in the original BeOS there was no Locale Kit framework and it was added only in Haiku.

    My next step was to choose an environment for developing applications in the C ++ programming language. Due to the fact that the Qt framework has been ported to Haiku, IDEs such as Qt Creator and are available in the HaikuPorts repositoryKDevelop . In addition, there is a JVM port that allows you to use IDEs written in the Java programming language, such as NetBeans or IntelliJ IDEA . I chose the Qt Creator development environment, especially in its latest versions there is a qualitative analysis of the code using the LibClang parser , which works an order of magnitude more precisely and faster than the standard parser.


    The Qt Creator integrated development environment running on the Haiku operating system.

    In terms of the well-known and cross-platform IDE in Haiku, everything is fine. But what about exclusive solutions? I can not fail to mention a very interesting project, the author of which is DarkWyrm and which currently supports Adam Fowler , it is called Paladin . This program makes the advanced Pe text editor available in the distribution of the operating system practically into a real IDE.


    Paladin integrated development environment for Haiku, installed from the HaikuPorts repository.

    Using the tiling built into the Haiku window system, you can attach the Paladin window to the side of the Pe editor and add a terminal. Even in the HaikuPorts repository there is a convenient text editor Koder , which resembles the popular Notepad ++ program for Windows and is also based on the developments of the Scintilla project . I created a project PLD file for my application and now any developer who uses Paladin IDE can open my project in this program without any problems.

    When the Qt Creator development environment was set up and ready to go, I began to implement all the features I had planned. The first problem I encountered was related to the scaling of the controls when the size of the system font was changed. Initially, in BeOS, all the layout code for GUI elements was explicitly specified in coordinates. It was very inconvenient, verbose, and created a huge heap of problems, for example, with the same change in font size, the entire form of the application dispersed and became unusable. Fortunately, Haiku tried to solve this problem and added the Layout API , which is part of the Interface Kit framework.


    Through the use of Layout API, launchers respond correctly to changing the size of the system font in Haiku.

    This innovation completely solved my problem with positioning controls and I rewrote the application using the Layout API, which seriously reduced the code length in some places. On the official Haiku website, I found a series of interesting articles, Laying It All Out , which just explains the reasons why this program interface was created and examples of its use were shown.

    One more problem was identified by Gerasim, when he tried to use my library to create a launcher for the game, which he ported. The point was that I often turned to the source code of the Haiku operating system itself to implement various functionalities. In particular, I found an example of using the Launch () method on an object of the BRoster class there. The problem manifested itself in the fact that this example turned out to be incorrect and the game engine, which was ported by Gerasim, could not parse the arguments set by the launcher correctly. After a closer look at the Haiku source code, I managed to find out that the first argument, which must contain the full path to the executable file, in the case of the Launch () method, is not required to be specified explicitly, since it will be automatically set.

    // Error
    const char* args[] = { "/bin/open", fURL.String(), NULL };
    be_roster->Launch(&ref, 2, args);
    // Good
    const char* args[] = { fURL.String(), NULL };
    be_roster->Launch(&ref, 1, args);
    // See "src/kits/app/Roster.cpp", BRoster::ArgVector::Init() method:
    if (error == B_OK) {
        fArgs[0] = fAppPath.Path(); // <= Here
        if (argc > 0 && args != NULL) {
            for (int i = 0; i < argc; i++)
                fArgs[i + 1] = args[i];
            if (hasDocArg)
                fArgs[fArgc - 1] = fDocPath.Path();
        }
        // NULL terminate (e.g. required by load_image())
        fArgs[fArgc] = NULL;
    }
    

    The documentation for the Launch () method says nothing about the fact that the first argument is not required, probably that is why the developer wrote this code incorrectly. I corrected this error in my project and the problem of Gerasim was solved by itself. But what about this small error in the Haiku operating system itself? I decided to fix it. Fortunately, it turned out to be very easy to do! You need to log in with GitHub on the Haiku Code Review Gerrit resource , add your public SSH key, fork the Haiku source code, create a commit with the fix, and send the resulting patch to Code review to the privileged developers:

    git clone ssh://EXL@git.haiku-os.org/haiku --depth=1 -b master && cd haiku
    git commit
    git push origin master:refs/for/master
    

    If you need to update already sent patches, then before sending modified or new commits, we must add to the end of the commit message the ID that gave us the Haiku Code Review service. After the patch is submitted, the Haiku developers must confirm, reject, or send it for revision. In my case, the correction was made immediately and this minor bug is now eliminated everywhere. If you need to test your patches before sending to the repository, then you can try using the jam utility , which is a fork of the Perforce Jam assembly system and used to build the entire Haiku code base, to compile a separate application. The source code repository contains the file ReadMe.Compiling.mdwhich will help you deal with all the wisdom of compilation.

    While finalizing my project, I found the reason why Icon-O-Matic does not open SVG files created using the Inkscape vector editor. The thing is that Icon-O-Matic cannot handle the viewBox attribute , however, if you find a simple SVG file without this attribute, edit it with Inkscape and save it as a Plain SVG file , it will open in Icon-O -Matic. Therefore, I put into my repository such a specially prepared SVG file that can be edited and which will open in Icon-O-Matic without problems. Additionally, I added a small instruction to the ReadMe-file of the project on how to create icons for my launchers using Inkscape.

    I decided to check the code of my project with a variety of static analyzers, but they did not find any serious problems. But I later found one problem that they could not detect. The fact that the static method GetBitmap () class BTranslationUtils could return NULL:

    // Somewhere
    fBitmap = BTranslationUtils::GetBitmap(B_PNG_FORMAT, fIndex);
    void
    BeImageView::Draw(BRect rect)
    {
        // Fail
        const BRect bitmapRect = fBitmap->Bounds();
        ...
    }
    

    And in the Draw () method, I inadvertently forgot to check the field of the fBitmap class for validity. Therefore, the application was expected to fall if it did not find a specific picture, but according to the plan it was necessary to draw a red square instead. I told this story to the fact that static analyzers are far from a panacea and care when working with code in the C ++ programming language is required in any case.

    I upload the source code of the BeGameLauncher project and all my work in the repository on GitHub. I hope this program will be useful to someone and may become a kind of textbook as a simple application for Haiku:

    Project source code: https://github.com/EXL/BeGameLauncher

    A little advice for those who will use my launcher in their recipes for the HaikuPorts repository. If you want to hide the executable file of the game from the list of Haiku applications that read some programs, and leave only the launcher there, you can use the following trick:

    settype -t application/x-vnd.Be-elfexecutable $appsDir/Gish/engine/Gish
    rc $portDir/additional-files/gish.rdef -o gish.rsrc
    resattr -o $appsDir/Gish/engine/Gish gish.rsrc
    

    This will exclude the possibility of launching executable files without the parameters passed by the launcher from various programs like QuickLaunch , which are engaged in quick launch of applications. In this case, your original icon on the executable file will be saved.

    << Skip to content

    6. Porting Xash3D: the legendary game Half-Life and official additions


    The Xash3D project is a free implementation of the GoldSrc engine, which is used in the Half-Life game and in its official additions. Behind the development of Xash3D is the domestic programmer Uncle Misha , who still coordinates its development and improvement. A little later, other developers joined the project who forked FWGS Xash3D , with the support of a huge number of operating systems other than Windows. Today, the key programmers of the FWGS Xash3D project are mittorn and a1batross ( libpony ), the last person was an active participant in the once popular forum MotoFan.Ruwhich I still administer in my free time.

    I wondered: why not port this engine to Haiku, adding support for such an interesting operating system to the Xash3D project, and give Haiku users the opportunity to play the legendary Half-Life, a game of all times and peoples? The case remained for small - it was necessary to immediately begin work on porting and, if successful, publish the results of this work.

    Having spent several hours studying the structure of the project and those parts of the code that are responsible for supporting various platforms, I began to make changes to the Xash3D engine to make it possible to support the Haiku operating system. In the old fashioned way, I zafefilil the compiler -D__linux__and tried to compile the executable and a bunch of libraries. Surprisingly, things went pretty fast and by the evening, after forwarding the data files for the game, I managed to run Half-Life and take a train to the initial station in Black Mesa.


    The process of porting the Xash3D engine to Haiku in the Qt Creator integrated development environment.

    Due to the fact that the project uses the SDL2 cross-platform library, engine porting is greatly simplified, since you do not need to write any pieces of code that depend on the platform, for example: sound output, creating a window with OpenGL context, or handling input events. All this is already implemented in the library SDL2 and ready to use. A small problem arose with network support, because Haiku has a separate library that implements the network stack, respectively, it was required to link it to the engine.

    The project for creating launchers, about which I wrote a little higher, came in very handy for me. With the help of C ++ class inheritance, I seriously expanded its functionality and implemented the ability to select various game add-ons:


    Screenshot port launcher engine Xash3D for Haiku.

    The idea was the following: to determine three environment variables that would allow the flexibility to customize the game engine to launch a specific add-on. At the same time, it would be useful to let the user play with the various arguments of the executable file and leave the possibility of portable launching the engine when it is just in the directory with the required data files. So, the first environment variable XASH3D_BASEDIR is responsible for the directory with the game files that the user selects from the launcher. The second variable, XASH3D_GAME, is responsible for which addition the user chooses to launch in the launcher. And here is the third variable XASH3D_MIRRORDIR, useful only to advanced users. It allows you to mirror the Xash3D system directory to any recordable user space on the disk. Thus, a person who wants to release his add-on game on the Xash3D engine for Haiku needs to simply compile several dynamic libraries from the source code of his project for different architectures:

    • ./cl_dlls/libclient-haiku.so
    • ./dlls/libserver-haiku .so
    • ./cl_dlls/libclient-haiku64.so
    • ./dlls/libserver-haiku64.so

    And then put them in the appropriate directories of your add-on. For my Xash3D port, I decided to pre-compile libraries of popular add-ons to the Half-Life game, namely Blue Shift and Opposing Force, which will allow users to simply download their data files, select a directory and start the game without compiling any libraries.

    In the process of porting the Xash3D engine, I ran into some funny problems. It turns out that to determine the length of the help message for the arguments of the executable file, which is generated when the --help parameter is passed , the preset MAX_SYSPATH constant size , which is an alias of another MAX_PATH constant , the value of which is taken from the Haiku API , was used in the engine . So, for a long time I could not understand why this certificate is issued incomplete and is cut off in the most interesting place. At first I sinned that in some strange way to the standard error output stream stderrBuffering was connected and even tried to force it off. After some time, I remembered that I was surprised by the very small size of the MAX_PATH constant in the Haiku operating system. This constant assumes the size of the path is only 1024 bytes. My guess fully justified itself, as soon as I increased the size of the message to the standard 4096 bytes, the problem was resolved. The following conclusion should be drawn from this funny story: you should not use the MAX_PATH constant in character arrays that are not related to file paths.


    A collage of screenshots of the game Half-Life, as well as its official additions Blue Shift and Opposing Force, launched using the Xash3D engine in the Haiku operating system (preview, increase by reference ).

    Another problem was the crash when using the functionality of the engine itself to select the add-on game. It turned out that when XASH_INTERNAL_GAMELIBS was set up, the client library was loaded not once, but twice. Which led to a similar problem. As a1batross explained to me , this was done in order to be able to statically link the OpenVGUI library to the client library. In my Xash3D port on Haiku, this library is not used at all, so I just quit using defaultsXASH_INTERNAL_GAMELIBS and zeportil this bug engine developers.

    Next, I came across the impossibility of opening the WebPositive browser built into Haiku when I clicked on links inside a game running in Xash3D. At the same time, the problem was really strange, since the browser was opened from the terminal when the engine was started from the terminal, but when it was launched using the launcher, it refused to do so. Having a little studied the code, I found an execve () call there , which I tried to replace with system () , after which the browser began to open without any problems.

    The Xash3D engine actively uses calls of the SDL_ShowSimpleMessageBox () and SDL_ShowMessageBox () functions when errors occur., here only the current port of the SDL2 library for Haiku does not support the creation of these dialogues. In our version of the library, this functionality is simply missing. But I will tell about the correction of this problem below.


    Port Xash3D engine, published in the repository of Haiku Depot.

    It is also worth noting that before my transfer of the Xash3D engine to Haiku, Gerasim Troyeglazov captured the mouse cursor in SDL2; Before that, playing 3D games was almost impossible. A little later, he fixed a cunning bug, in which the movement of a player in space gradually slowed down, and the game began to slow down terribly. It turns out that the point was that by default the events of the mouse cursor were transmitted with all its history of movement on the screen. Accordingly, this story quickly expanded during the game and everything began to slow down. Disabling this feature in the SDL2 port on Haiku solved this problem and now you can play in Half-Life without any special problems. Although the lack of 3D acceleration on a weak gland makes itself felt. And if the game works decently in the window and does not slow down at all, then in full-screen mode the FPS is significantly reduced.

    Project source code: https://github.com/FWGS/xash3d

    I sent all the changes to the source code to the FWGS Xash3D project developers, who accepted them to the repository, and packages with this engine have long been available in HaikuPorts and in the Haiku program for any Haiku user .

    << Skip to content

    7. Porting the two parts of the game Serious Sam: The First Encounter and The Second Encounter


    Recently, developers from Croteam have posted the source code for the Serious Engine , which is used in the games of the Serious Sam series: The First Encounter and The Second Encounter . I decided to port it to the Haiku operating system, downloaded the source code and started working.


    Screenshot port launcher engine Serious Engine for Haiku.

    The assembly of the executable file after the changes made did not occur without any problems, but it was not so easy to start the game due to the fact that errors were raining in the SDL2 dialogs, the implementation of which is not available in the version of this library for Haiku. Therefore, we had to take the time-tested standard stream of stderr error output and slowly understand the problems that were mainly in the absence of the required game data files.


    Screenshot of the game Serious Sam: The Second Encounter, launched using the Serious Engine engine port for the Haiku operating system.

    Having decomposed the downloaded files into the required directories, I was able to launch the second part of this wonderful game without any problems and even ran a little through the beautiful jungle. Despite the lack of 3D acceleration, the processor pulls out the graphic charms of the game, if you run it in a window, and not in full-screen mode. This engine works, of course, where with a smaller FPS than the Xash3D engine, about which I wrote above, but the graphics here are more modern and better. After some manipulations, it was possible to launch the first part of the game, which requires a different executable file and a different set of dynamic libraries. Surprisingly, she earned a little faster, apparently the graphics in it are not so demanding. Having climbed the settings of the engine, I found a huge number of graphical parameters that can significantly reduce the load on the processor,


    Screenshot of Serious Sam: The First Encounter game launched using the Serious Engine engine port for the Haiku operating system.

    I decided to make one package for two parts of the game at once, switching between them will be done simply by selecting a directory with the appropriate set of data files. For example, if a user chooses a directory with Serious Sam: The First Encounter game files in the launcher, the corresponding executable file is launched and the corresponding set of dynamic libraries is loaded. And if he chooses the directory with the files of the game Serious Sam: The Second Encounter, then the launcher will respectively launch another executable file, which will load its own set of shared libraries.

    Unfortunately, there were no problems. Re-changing the resolution of the video mode in the game led to the fall of the entire engine. At the same time in my Linux distribution this departure was not. I spent a lot of time localizing the problem and fixing it. It turned out that the whole thing was that each time the resolution was changed, the SDL_Window window was destroyed and re-created ., while the OpenGL renderer could not switch in time and tried to draw something in the destroyed window. Such frills port library SDL2 on Haiku did not allow to rotate. All the simple attempts to solve this problem did not help and I had to seriously get into the logic and change the behavior so that the window did not collapse when the resolution was changed, but simply changed its parameters. This helped to remove the crash, but added an additional limitation: now, in order to activate full-screen mode, you need to restart the engine.

    Another problem was the lack of music in the game. At the same time on Linux, again, this problem did not manifest itself. Exploring the source code of the engine, I found that playing music depends on the library libvorbisfile, but the engine itself does not link to it, but uses the system function dlopen () to feed the stream of the OGG-audio file to this library. The problem was that the engine could not find this library on Haiku, since there was no symlink to the library file without the version designation.

    void CUnixDynamicLoader::DoOpen(const char *lib)
    {
        // Small HACK for Haiku OS (:
    #ifdef __HAIKU__
        static int vorbis_cnt = 3;
        char path[PATH_MAX];
        char libpath[PATH_MAX];
        find_directory(B_SYSTEM_LIB_DIRECTORY, -1, false, libpath, PATH_MAX);
        if (strstr(lib, "vorbis")) {
            snprintf(path, sizeof(path), "%s/libvorbisfile.so.%c", libpath, char(vorbis_cnt + '0'));
            vorbis_cnt++;
            lib = path;
        }
    #endif
        // fprintf(stderr, "dlopen => %s\n", lib);
        module = ::dlopen(lib, RTLD_LAZY | RTLD_GLOBAL);
        SetError();
    }
    

    The little trick that put the full path to the required library into the function turned out to be quite a working solution. And since the library in its absence is searched for by the engine several times, I left for the future the possibility of loading the next major version. I hope they do not break the API in it.

    The next problem I encountered was the impossibility of determining the processor frequency on the x86 architecture, although on x86_64 everything worked fine. When running on the x86 engine, I asked to set an environment variable named SERIOUS_MHZand set the appropriate frequency in it, which really surprised me. I tried to do it and the game really started, but for some reason it worked too slowly. Having climbed the source code of the game, I could not find the source of the problem for a long time and even wrote a piece of code that, using the Haiku API, gets the correct processor frequency and inserts it into the game engine, this is how it looked:

    #include <kernel/OS.h>
    #include <stdio.h>
    ...
    uint64 cpuFreq = 0;
    uint32 count = 0;
    get_cpu_topology_info(NULL, &count);
    if (count != 0) {
        cpu_topology_node_info *topology = new cpu_topology_node_info[count];
        get_cpu_topology_info(topology, &count);
        for (uint32 i = 0; i < count; ++i) {
            if(topology[i].type == B_TOPOLOGY_CORE) {
                cpuFreq = topology[i].data.core.default_frequency;
            }
        }
        delete[] topology;
    }
    fprintf(stderr, "%llu\n", cpuFreq);
    

    But it did not help. Then I checked the engine logs on x86_64 and saw that the CPU frequency there is generally defined at 1 MHz, but everything works fine. Continuing to explore the code further, I stumbled upon the denial of the __GNU_INLINE_X86_32__ define , which is automatically set when the application is built for x86 architecture, but not for x86_64. Below this define, the checkbox that told you to use SDL2 timers hid instead of getting the processor frequency using various magic like inline-assembler and rdtsc instructions or reading the / proc / cpuinfo file , so I made sure that this flag was activated and for x86, that solved my problem.

    The last defect was related to my carelessness. I missed in the build fileCMakeLists.txt installation of the -march = native flag , which literally speaks to the compiler: when generating blocks of machine code, use all the advanced and modern instructions that are available in the processor of your computer.

    if(NOT PANDORA AND NOT HAIKU)
        message("Warning: arch-native will be used!")
        add_compile_options(-march=native)
    endif()
    if(HAIKU)
        if(CMAKE_SIZEOF_VOID_P EQUAL 4) # 32-bit
            message("Warning: Will building 32-bit executable with MMX, SSE, SSE2 support.")
            add_compile_options(-mmmx -msse -msse2)
        else()                          # 64-bit
            message("Warning: Will building 64-bit executable.")
        endif()
    endif()
    

    Because of this, the packages in the repository gathered exclusively for the most powerful build-server and refused to run on the computers of ordinary mortal people, cursing the wrong instructions and opcodes. Disabling this flag and manually adding support for MMX, SSE and SSE2 instructions not only solved this problem, but also allowed compiling a huge pile of inline assembler in this project, which fell off after this flag was removed.

    To my great regret, the Croteam developers do not accept any patches in the engine repository, so I made a fork and put all my work there:

    Source code of the project: https://github.com/EXLMOTODEV/Serious-Engine

    Ready-to-install packages that allow you to start Serious Sam games are already available in the HaikuPorts repository. Just remember to download the game data files.

    << Skip to content

    8. Porting the game Vangers


    Frankly, until recently, I was completely unfamiliar with this game, which in the distant 90s made the domestic development studio KD Lab. But the participants of the conference in Telegram IM , which is devoted to a discussion of the Haiku operating system, asked me to port Wangers and gave me a link to the GitHub repository , which contained the sources of this game.


    Screenshot port launcher game Wangers for Haiku.

    Pulling the source code into Haiku, I tried to compile them and I did it without any special problems. Little had to tinker with the lack of some header files and the paths to the libraries FFmpeg , which are used by the engine of this game. I immediately began to prepare the source code for packaging, so I added the VANGERS_DATA environment variable and transferred the engine log to the user directory available for writing.


    The process of porting the Wangers game to Haiku in the Qt Creator integrated development environment.

    I launched the game itself and after a while appreciated the whole atmosphere that the guys from KD Lab managed to create. After some time, I began to blithely carry the Nimbus into the Incubator and the Phlegm into the Podish, after which I even managed to bring the Elika to the third. Having played enough, I began to prepare a launcher for this game based on my library, about which I wrote above.


    The port of the game Wangers running on the Haiku operating system.

    The first problem I encountered was that the game data files that could be officially obtained using the digital distribution services GOG.com and Steam did not want to work with the engine. I had to contact a person who uses the nickname stalkerg and who was engaged in porting Wangers to Linux. He told me which files need to be changed in order for everything to start and start working. I followed his recommendations and got what I needed.

    As in the case of the port NXEngine (Cave Story), about which I wrote above, the Russian and English versions differ from each other by different executable files, but the directory with the data files is common, the differences are only in the scripts. At the prompt stalkerg, I tried to compile the game engine with the option -DBINARY_SCRIPT = Off , which activated the dynamic compilation of these scripts during execution, if they are available in the game data files directory. All this allowed me to create a launcher, in which there is the possibility of switching the language. The idea is this: the game directory is preliminarily checked, and if there are no necessary scripts in it, then they are copied from the package internals, after which the executable file of the Russian or English version is launched.


    The port of the game Wangers, published in the repository of Haiku Depot.

    When porting Wangers, I used one interesting feature related to shared libraries, which I like in Haiku. The game engine depends on the dynamic library libclunk.so , which is responsible for generating real-time binaural sounds. And if in Linux, I have to break my fingers, substituting the path to this library into the LD_LIBRARY_PATH environment variable , so that what was in this variable has also been saved, then Haiku has done it comfortably, as in Windows. It is enough to put the shared library next to the executable file and it will be picked up, with the only difference that in the case of Haiku the library needs to be placed in the ./lib/ directoryThat, in my opinion, allows to save a lot of time and nerves. Therefore, I decided not to consider a static compilation of this library.

    Project source code: https://github.com/KranX/Vangers

    Wangers developers accepted my changes to their game engine, and ready-to-install packages are available for download from the HaikuPorts repository or the HaikuDepot program, despite the recent fix in the repository infrastructure that happened after update the Linux distribution of Fedora to the new version.

    << Skip to content

    9. Implementation of dialogs in the library SDL2 for Haiku


    When porting the Xash3D and Serious Engine engines, about which I wrote above, I stumbled across the local port of the SDL2 library at the complete lack of dialogue implementation. Dialogues are called by two functions SDL_ShowSimpleMessageBox () and SDL_ShowMessageBox () , which allow you to inform the user about any important information, such as an error. The implementation of these dialogs is available on many platforms and operating systems: Windows, macOS, iOS, X11 and Android, but for some reason is missing from Haiku. I decided to correct this omission and add this functionality to the SDL2 library port.

    In the Haiku API, or rather in the Interface Kit framework, there is an excellent BAlert class .which is great for implementing such dialogs. I decided to choose it as the base. The only thing that confused me was that I was not sure that more than three buttons could be placed in the dialog that BAlert constructs . I also remembered the memory management features in this class that I wrote about above: you can create its objects only on the heap, and you cannot create them on the stack, because after calling the Go () method and the subsequent user action, it deletes itself. Having conducted some experiments, I dispelled all my doubts, inherited from this class, and began to write an implementation.


    The implementation of the dialogs in the library SDL2 for the Haiku operating system.

    The first difficulty I encountered was that when using any object of the BAlert class or its heirs, it was necessary to create an instance of the BApplication system class , apparently, to register the application in app_server to be able to interact with it. I created an instance of this class, but when I called the BAlert dialog from another process or from the created window, I received another error related to the fact that the application could not have two objects of the BApplication class , fortunately I found a solution to this problem. The Haiku API has a global pointer to the current instance of the class.BApplication , which is called be_app , its counterpart in the Qt framework is a special qApp macro , also defining a pointer to the current application object. So, it is enough just to check the be_app pointer to NULL, and if the check is completed successfully, create the required object. Thus, all these problems were solved.

    It is worth noting that the SDL2 library is written in the C programming language, and the Haiku API is known to use the C ++ programming language. Because of this, some parts of the code should always be smeared with extern "C" binding agreements so that there are no problems with resolving characters during the linking process. Also, instead of newyou should use the new operator (std :: nothrow) to be able to check the allocated memory by NULL, instead of throwing an exception, which SDL2 does not, of course, support.

    Otherwise, there was nothing complicated. We write several functions that convert entities and SDL2 representations in such a way that they are compatible with the Haiku API and verify their correct operation. For various checks, I extended a small test.which I occasionally ran on different operating systems, analyzed the results and evaluated my work. In the end, I got so carried away that I even made customization support, such as setting different colors to the buttons and dialogue background. This is supported by the SDL2 library API, but initially I did not plan to implement such things.

    If the programmer decides to spit out a very, very long line into this dialog, then the BTextView class object that is used inside the BAlert class object needs to call the SetWordWrap () method with a true argument in order to hit the programmer on his hands and make the dialog fit on the screen. It would seem that nothing is simpler: we check the length of the string with the help of the functionstrlen () and do the right thing. The problem is that SDL2 works the same with UTF-8, which means that the strlen () function will return the number of bytes, not the number of characters. Haiku API comes to the rescue and the BString string class contains the CountChars () method , which allows you to find out the length of a string in characters, not in bytes:

    bool
    CheckLongLines(const char *aMessage)
    {
        int final = 0;
        // This UTF-8 friendly. P.S. G_MAX_STRING_LENGTH = 120
        BString message = aMessage;
        int32 length = message.CountChars();
        for (int i = 0, c = 0; i < length; ++i)
        {
            c++;
            if (*(message.CharAt(i)) == '\n')
            {
                c = 0;
            }
            if (c > final)
            {
                final = c;
            }
        }
        return (final > G_MAX_STRING_LENGTH);
    }
    

    This function checks the message text for lines longer than 120 characters and, if there are any, returns true. As for UTF-8, there was still such a moment that some of the Haiku system fonts lack support for Chinese characters. Therefore, for example, it is impossible to install any Chinese inscription in the window title. But the text in Russian is installed without problems.

    When preparing the package, I encountered an assembly error for the x86_gcc2 architecture, which is activated in the SDL2 library recipe. It turned out that the oldest GCC 2.95 compiler cannot guess that the commented code is equivalent to what is below:

    rgb_color
    ConvertColorType(const SDL_MessageBoxColor *aColor) const
    {
        // return { aColor->r, aColor->g, aColor->b, 255 };
        rgb_color color = { aColor->r, aColor->g, aColor->b, color.alpha = 255 };
        return color;
    }
    

    So I had to rewrite this fragment in the old style and still remove the initialization of some constants in the class directly in their declarations, the old compiler didn’t like it either.

    I sent patches for the implementation of the SDL2 dialogs to the HaikuPorts repository, so that now the Xash3D and Serious Engine engines can correctly provide the user with any information, for example, about errors. But I have not yet contacted the developers of SDL2, but it would be nice to transfer all patches from the HaikuPorts repository to the upstream library SDL2. Although the work on transferring our patches has become a bit more complicated due to the recent renaming of function prefixes from BE_ * to HAIKU_ * , but this is not such a serious problem.

    << Skip to content

    10. Porting my fork to the program Cool Reader


    I have been developing the Cool Reader program for a long time , which was written by Vadim Lopatin ( Buggins ), the corresponding article about this is available on my site. In the comments to this article, readers of my blog are constantly unsubscribing, who either want to see some new feature in their favorite e-book reader application, or want to correct errors and shortcomings in the already implemented functions of the program.


    My fork is a Cool Reader program running on the Haiku operating system.

    In the HaikuPorts repository, I found a recipe for building the original Cool Reader program, but due to some constant changes with SourceForge , this recipe was not working because the source code of the application was no longer available for download. Then I decided to move my fork to the HaikuPorts repository, as a new version of Cool Reader. I put all the patches of Gerasim on the code, corrected some of the shortcomings in the recipe, and based on it created a new package that is already available to all Haiku users. The source code for my Cool Reader fork can be found in this GitHub repository:

    Project Source Code: https://github.com/EXLMOTODEV/coolreader

    The only problem I encountered was the inaccuracy of transferring Gerasim's patches. In addition to defining __HAIKU__ , somewhere in the build system, the _LINUX define was also exposed and, since in most cases the last one in the listing of the source code was the first, the conditional compilation let me down. In accordance with the rules of the preprocessor priority, Haiku compiled exactly those pieces of code that were framed with _LINUX , although I needed something completely different. But even in spite of this, the program started and worked, only it saved its settings in the wrong place. I correctly prioritized, rebuilt the package and the problem was completely resolved.

    << Skip to content

    11. Improvement of the program KeymapSwitcher


    Recently, many popular operating systems have switched to the new keyboard shortcut Meta / Opt / Cmd / Win + Space to switch the keyboard layout. It seemed to me very convenient because now there is no need to change anything and adjust. You sit down at any computer running macOS, Windows or Linux with the GNOME 3 shell and this convenient combination of changing the input language just works everywhere. Even in the mobile operating system Android has its counterpart. In general, I completely switched to this keyboard combination a long time ago and got used to it very much.

    Much to my regret, the program KeymapSwitcher, which comes with Haiku, did not allow to set such a convenient keyboard shortcut for switching layouts, which is why I constantly felt uncomfortable working with text in this operating system. Therefore, I decided to modify this application a bit and started looking for its source code. It turned out that this program, although included in the Haiku distribution, is supplied separately from the source code of the operating system itself. In addition, the application is available in the HaikuPorts repository and is also updated through it. As I was informed, KeymapSwitcher was not included in Haiku, because it is planned to implement a special API for changing keyboard layouts and sometime the need for this program will completely disappear.


    The program KeymapSwitcher in the Haiku operating system with the popular key combination to switch the keyboard layout.

    Despite the fact that I was frightened by the complexity of the KeymapSwitcher code, I rather quickly found the right place thanks to the comments and introduced a small patch into the program code, which greatly facilitated my typing of any texts in Haiku. The only minor flaw I couldn’t overcome is that the Opt key needs to be released to switch the language. That is, clamp Optand the space switch between the selected languages ​​will not work. But it absolutely does not interfere with language switching during typing, so I sent the patch to the program repository and updated the application package in HaikuPorts, after which the new version of KeymapSwitcher became available for installation to all Haiku users.

    Project source code: https://github.com/HaikuArchives/KeymapSwitcher

    I hope I'm not the only user of this keyboard shortcut for switching keyboard layouts.

    << Skip to content

    12. Conclusion


    Studying the Haiku API, as well as resolving various exotic problems that arose as a result of porting new and refining existing applications for this operating system, brought me a tremendous amount of valuable experience and pleasure. I was able to promote the haiku support patches in the source code repository of some large projects and met new interesting people somehow connected with this wonderful operating system.


    Various applications running on the Haiku operating system.

    I sincerely hope that in the future all today's problems such as the lack of 3D hardware acceleration and popular browsers, as well as poor support for modern hardware, will be successfully resolved and Haiku will receive an influx of new developers and users who will appreciate its unique features and original design. . Fortunately, development is far from being in place and today hot topics about 3D acceleration and porting of the GTK + 3 library are raised on the local forum of this operating system , and the possibility of transferring the QtWebEngine component is discussed in the HaikuPorts repositories .. The GTK + 3 port can lead to the launch and operation of the popular Firefox and Chromium browsers, and QtWebEngine will allow using the Blink engine in modern browsers based on the Qt framework, such as Otter Browser or Falkon .

    Already, I can recommend this operating system to those who have old and weak laptops or netbooks, for example, instead of the Lubuntu distribution kit or Windows XP. You will be amazed at how fast and responsive it works. Yes, you will have to limit yourself a little to browsing some sites because of old browsers and a lot of glitches that are associated with them, but for most cases this restriction is not a significant issue on the old hardware.

    All my ports and improvements have already been published and are available for installation to all users of Haiku. All changes to the source code are available in the corresponding repositories under their original licenses. In this work, I used a huge amount of materials, the main ones I will highlight in the useful links below. Many thanks to the resources stackoverflow.com and google.com for the fact that they are.

    1. The official website of the Haiku operating system .
    2. The official forum operating system Haiku .
    3. Official documentation for Haiku users .
    4. Official Haiku developer documentation .
    5. Description of the features of the Haiku GUI .
    6. Recommendations for creating icons for Haiku applications .
    7. Description of the program Icon-O-Matic and tips on its use .
    8. Description of the format of vector icons HVIF .
    9. Official documentation for the Interface Kit framework .
    10. Official Locale Kit framework documentation .
    11. An article on localization of applications for Haiku .
    12. Official documentation on the software interface Layout API .
    13. A series of articles telling about the introduction of the Layout API interface to Haiku .
    14. GitHub-repository source code operating system Haiku .
    15. GitHub-repository of the HaikuPorts recipe tree.
    16. Internet version of the repository of ready-made HPKG packages of Haiku Depot Web .
    17. An interesting article “Haiku: Lamp geek-OS” on the INSTEAD developer blog, Peter Kosykh .
    18. Article "Haiku: immersion" in the blog of the developer INSTEAD, Peter Kosykh .
    19. The DarkWyrm Learning to Program with Haiku programming course .
    20. The course of programming lessons “Programming With Haiku” from DarkWyrm .
    21. The publication “Is there life on Haiku?” On Linux.org.ru, from me .
    22. Conference in Telegram IM, dedicated to the discussion of the operating system Haiku .

    Congratulations to all users of the resource habrHappy New Year and wish them happy Christmas! Good luck to you guys in the new year 2019!

    << Skip to content