
Broadway - rendering GTK3 interface in a browser (HTML5)
Sometimes it is necessary to provide access to applications that it is not always possible to install locally, and it is not always necessary. Probably the best solution here would be a web interface in JS / PHP and others like them. But maybe there are other, easier ways in some cases? Especially if the application should remain portable, and even better not to do almost anything extra in the code to implement such functionality.
This opportunity is provided by Broadway - not a new one for a long time, but remaining in the shadow of the backend for GTK3, which allows bringing new features to the place where everything seemed to have been trodden for a long time.


About broadway told on a habr , already in 2011. However, little has changed since then in the lighting area of this option.
UPD, thanks awoland :
Initially, this is the technology and internal code name for release 6.3 X Window System 11 (X11R6.3):
“Broadway was the internal code name for The X Window System 11 Release 6.3 (X11R6.3) development effort. The X11R6.3 project was a ground-breaking initiative for enabling the use of X to create and access interactive applications on the World Wide Web. Any application linked to the Web using X11R6.3 can be located, accessed and executed with the same tools used for accessing static HTML documents today - web browsers. ”
The main idea is to write one single version of the code based on the usual and already familiar GTK3, which can simultaneously and almost without changes work as a classic graphical application, as well as render its interface using HTML5 and websockets in the browser. In versions 3.8+, it became possible to set a password for the connection and the ability to run many applications on one server.
Officially, Broadway was released with GTK3, but only starting with version 3.8 did this subsystem get rid of annoying errors. I use 3.10.7, because it changed the principle of use, fixed many errors and made the HTTP server as a separate application. Therefore, I will talk about 3.10, because all the same, everything will come to him.

Together with GTK3, an HTTP server integrated with GTK3 (broadway d ) is installed . At startup, it creates a socket, for example /run/user/1000/broadway1.socket, and waits for the GTK3 application to connect to this socket.
You can specify a different port (screen number), you can set a password for the connection (> = GTK 3.8).
Such a mode of operation does not pretend to replace the standard interfaces based on PHP / JS / Java and their ilk that have now become standard. But in this way, you can create a service, for example, in the form of a virtual machine, which will provide users with access to any computing services or utilities without wasting time developing a special interface, while ensuring high performance on the server side. For example, I used it to make a console for accessing XenServer virtual machines and now I am implementing remote access to the cameras of my telescope.
At the moment, as far as I know, not a single distribution that I have tried provides the GTK3 + broadway package in stable branches. Debian 7 has such a package in the experimental repository, but it seems that not everything is going smoothly with it.
In Debian based systems, you can add PPA assembled by a kind person (Nicolas Delvaux).
There is a backport made by him on the basis of 3.8.0.
Both options should be used with caution and understanding, because there is a real opportunity to thoroughly break the system. I use 3.10.7, here it is only from the source.
We assemble, as described in the LFS manual, without forgetting about checkinstall instead of make install if you have a package manager
Unfortunately, there is no important nuance described there - in addition to assembling and installing the GTK3 library itself, you must manually collect and copy broadwayd somewhere accessible via $ PATH, e.g. in / usr / sbin
If you run the application like this
then it will work in the background, like a web server, and we get access to the interface by going to the appropriate address and port in the browser. In this example, it will be localhost: 8080 (The port is calculated as port = 8080 + (display - 1) ). The web server is already shipped with GTK - broadwayd. In this case, there is not even a need for a working X server on the host. It is enough to have the necessary libraries. The application will be displayed in the browser in almost the same way as in standard mode. Compare:


The first thing that catches your eye - there is no window name, as well as the title of the page says "broadway 2.0". It is also impossible to manually resize the window by dragging.
Using
will lead to segfault. The next caveat is that everything that is done in the browser is done relative to the host machine. For example, selecting a file on the local browser machine and something to do with it on the application side will not work. Or a libnotify call will cause a popup to appear on the host, and not on the machine with the browser.
On the other hand, other advantages open up, such as simplified access to server resources, but you need to pay attention to security, for example, through gtk_file_chooser_set_local_only, gtk_file_chooser_set_filter and configure jail for a separate user and launch the web version for this user, otherwise the user will be at a glance, at least least directory structure.
Another problem is that you can get to the standard menu with the mouse in the browser in such an application, but not very well with your finger (if you go from a mobile device). In addition, the size and position of the window are not always the same everywhere - this will also need to be taken into account. And very unpleasant - GTK3 does not support single click . So I still could not select another directory, even turning off double tap (Android 4.2.2 / Firefox / Chrome). Logging into the same session at the same time from different machines / browsers will not work, as there is only one socket, the previous session will be automatically closed
Consider how you can take into account the possibility of using Broadway in the application.
We will use Glade as an interface constructor. I use two versions of the interface in one application: one for normal use and one for the browser, which tries to take into account the nuances of working in a browser and / or on a mobile device.
GTK allows loading the interface from the memory buffer, which is what we will use. In the Makefile, I add the conversion from the XML file in which the Glade interface is saved to the uint8_t array, which will load the application. This allows you to store everything in one single executable file.
Now we have an array with an interface in the header file. The main loop is standard.
I’ll answer in advance about return - going with std = c99
Next, we need to understand when to use this or that type of interface.
Here, it will help us that if Broadway is used, then the GDK screen is called “browser”
ifdef is needed here to work properly under Win32, if necessary.
In this function, we check the name of the GDK window, and if it is a browser, then at the same time we remove the design (frame) of the window. Now we will load the interface depending on whether the application is running through broadway or not
We launch the application. We find that the window layout settings do not work. Immediately after launch, the resolution of the GDK screen 1024 * 768 is a consideration later. In addition, you will have to center the window with your hands, since rarely the browser resolution matches the default value in broadway.
After we opened the application in the browser, we need to set the desired screen resolution (most often it will stretch to the full screen) and at the same time combine the upper left corner with the origin. This can be done, for example, like this.
Then the test application (VNC console) will look like this in Android / Firefox):

If earlier (before 3.8) the user should have turned off the application on their own, otherwise if you close the browser or log in from another place, all that was visible was a white background. Now broadway takes over the work with sockets and idle / disconnect. Now we need to deal with other little things

Fortunately, GTK3 is an open source, so you can go deeper and change something.
The default text, “broadway 2.0,” is unlikely to suit anyone, we will change that. The HTML5 server page consists of a template and a JS file. The page title is written in the standard HTML header:
During assembly, the page is converted by a perl script into a simple C array, which is stored in gtk + -3.10.7 / gdk / broadway / clienthtml.h - static const char client_html [].
Then everything is simple, gtk + -3.10.7 / gdk / broadway / broadway-server.c:
Change the operation algorithm a bit, we will use the header as a format for sprintf. Therefore, gtk + -3.10.7 / gdk / broadway / clienthtml.h will have to be slightly corrected - add screening of percent signs, for example, like this:
instead
And replace the title text
on specifier
Change the algorithm of the server itself:
One could use asprintf, but then one would have to upgrade the Makefile, which I did not want to do.
Rebuild broadwayd, set the global variable and start the server

You can change the default screen size, it may be relevant when used with mobile devices.
And change the name of the GDK screen, so you can, for example, create several specific versions of broadwayd and identify them in this way
Broadway is a really interesting GTK3 feature that allows you to quickly create interesting lightweight services for a certain range of tasks. But, unfortunately, practically not used. With this article, I wanted to draw the attention of a large number of people to broadway and maybe someone can solve their problem using simpler methods.
This opportunity is provided by Broadway - not a new one for a long time, but remaining in the shadow of the backend for GTK3, which allows bringing new features to the place where everything seemed to have been trodden for a long time.

What is GTK Broadway

About broadway told on a habr , already in 2011. However, little has changed since then in the lighting area of this option.
UPD, thanks awoland :
Initially, this is the technology and internal code name for release 6.3 X Window System 11 (X11R6.3):
“Broadway was the internal code name for The X Window System 11 Release 6.3 (X11R6.3) development effort. The X11R6.3 project was a ground-breaking initiative for enabling the use of X to create and access interactive applications on the World Wide Web. Any application linked to the Web using X11R6.3 can be located, accessed and executed with the same tools used for accessing static HTML documents today - web browsers. ”
The main idea is to write one single version of the code based on the usual and already familiar GTK3, which can simultaneously and almost without changes work as a classic graphical application, as well as render its interface using HTML5 and websockets in the browser. In versions 3.8+, it became possible to set a password for the connection and the ability to run many applications on one server.
What version of GTK3?
Officially, Broadway was released with GTK3, but only starting with version 3.8 did this subsystem get rid of annoying errors. I use 3.10.7, because it changed the principle of use, fixed many errors and made the HTTP server as a separate application. Therefore, I will talk about 3.10, because all the same, everything will come to him.
Principle of operation

Together with GTK3, an HTTP server integrated with GTK3 (broadway d ) is installed . At startup, it creates a socket, for example /run/user/1000/broadway1.socket, and waits for the GTK3 application to connect to this socket.
You can specify a different port (screen number), you can set a password for the connection (> = GTK 3.8).
Why is it necessary
Such a mode of operation does not pretend to replace the standard interfaces based on PHP / JS / Java and their ilk that have now become standard. But in this way, you can create a service, for example, in the form of a virtual machine, which will provide users with access to any computing services or utilities without wasting time developing a special interface, while ensuring high performance on the server side. For example, I used it to make a console for accessing XenServer virtual machines and now I am implementing remote access to the cameras of my telescope.
Getting Broadway
At the moment, as far as I know, not a single distribution that I have tried provides the GTK3 + broadway package in stable branches. Debian 7 has such a package in the experimental repository, but it seems that not everything is going smoothly with it.
In Debian based systems, you can add PPA assembled by a kind person (Nicolas Delvaux).
There is a backport made by him on the basis of 3.8.0.
Both options should be used with caution and understanding, because there is a real opportunity to thoroughly break the system. I use 3.10.7, here it is only from the source.
Brief Assembly Instructions
We assemble, as described in the LFS manual, without forgetting about checkinstall instead of make install if you have a package manager
Unfortunately, there is no important nuance described there - in addition to assembling and installing the GTK3 library itself, you must manually collect and copy broadwayd somewhere accessible via $ PATH, e.g. in / usr / sbin
cd gtk+-3.10.7/gdk/broadway
make clean
make
cp broadwayd /usr/sbin
Launch
If you run the application like this
GDK_BACKEND=broadway BROADWAY_DISPLAY=:0 ./gtk_app
, then it will work in the background, like a web server, and we get access to the interface by going to the appropriate address and port in the browser. In this example, it will be localhost: 8080 (The port is calculated as port = 8080 + (display - 1) ). The web server is already shipped with GTK - broadwayd. In this case, there is not even a need for a working X server on the host. It is enough to have the necessary libraries. The application will be displayed in the browser in almost the same way as in standard mode. Compare:


The main nuances of use
The first thing that catches your eye - there is no window name, as well as the title of the page says "broadway 2.0". It is also impossible to manually resize the window by dragging.
Using
gtk_status_icon_set_visible(GTK_STATUS_ICON(tray_icon), TRUE);
will lead to segfault. The next caveat is that everything that is done in the browser is done relative to the host machine. For example, selecting a file on the local browser machine and something to do with it on the application side will not work. Or a libnotify call will cause a popup to appear on the host, and not on the machine with the browser.
On the other hand, other advantages open up, such as simplified access to server resources, but you need to pay attention to security, for example, through gtk_file_chooser_set_local_only, gtk_file_chooser_set_filter and configure jail for a separate user and launch the web version for this user, otherwise the user will be at a glance, at least least directory structure.
Another problem is that you can get to the standard menu with the mouse in the browser in such an application, but not very well with your finger (if you go from a mobile device). In addition, the size and position of the window are not always the same everywhere - this will also need to be taken into account. And very unpleasant - GTK3 does not support single click . So I still could not select another directory, even turning off double tap (Android 4.2.2 / Firefox / Chrome). Logging into the same session at the same time from different machines / browsers will not work, as there is only one socket, the previous session will be automatically closed
Practice
Consider how you can take into account the possibility of using Broadway in the application.
We will use Glade as an interface constructor. I use two versions of the interface in one application: one for normal use and one for the browser, which tries to take into account the nuances of working in a browser and / or on a mobile device.
GTK allows loading the interface from the memory buffer, which is what we will use. In the Makefile, I add the conversion from the XML file in which the Glade interface is saved to the uint8_t array, which will load the application. This allows you to store everything in one single executable file.
all:
xxd -i desktop.glade ../src/desktop.h;
xxd -i web.glade ../src/web.h;
make -C ../src
clean:
make -C ../src clean
Now we have an array with an interface in the header file. The main loop is standard.
int main(int argc, char *argv[])
{
gtk_init(&argc, &argv);
GtkWidget *main_window = glade_init( );
gtk_widget_show(main_window);
gtk_main( );
}
I’ll answer in advance about return - going with std = c99
Next, we need to understand when to use this or that type of interface.
Here, it will help us that if Broadway is used, then the GDK screen is called “browser”
#ifdef __WIN32
G_MODULE_EXPORT
#endif
gboolean is_run_in_a_browser (void)
{
GdkScreen *current_screen = gdk_screen_get_default();
char *screen_name= gdk_screen_make_display_name(current_screen);
gboolean is_browser = !strcmp(screen_name,"browser");
free(screen_name);
return is_browser;
}
ifdef is needed here to work properly under Win32, if necessary.
In this function, we check the name of the GDK window, and if it is a browser, then at the same time we remove the design (frame) of the window. Now we will load the interface depending on whether the application is running through broadway or not
#ifdef __WIN32
G_MODULE_EXPORT
#endif
GtkWidget *glade_init(void)
{
GtkBuilder *builder = gtk_builder_new( );
GError *error = NULL;
gboolean web_run = is_run_in_a_browser();
gtk_builder_add_from_string(builder, web_run ? (char *)web_glade : (char *)desktop_glade, -1, &error);
if (!error)
{
printf("Couldn't load builder buffer: %s", error->message);
g_error_free(error);
return NULL;
}
gtk_builder_connect_signals(builder, NULL );
GtkWidget *main_window = GTK_WIDGET (gtk_builder_get_object (builder, "mainwin"));
g_object_unref(builder);
return ( main_window );
}
We launch the application. We find that the window layout settings do not work. Immediately after launch, the resolution of the GDK screen 1024 * 768 is a consideration later. In addition, you will have to center the window with your hands, since rarely the browser resolution matches the default value in broadway.
After we opened the application in the browser, we need to set the desired screen resolution (most often it will stretch to the full screen) and at the same time combine the upper left corner with the origin. This can be done, for example, like this.
gtk_window_move(GTK_WINDOW(main_window),0,0);
GdkScreen *current_screen = gdk_screen_get_default();
int32_t w = gdk_screen_get_width(current_screen);
int32_t h = gdk_screen_get_height(current_screen);
gtk_window_resize(GTK_WINDOW(main_window),w, h);
Then the test application (VNC console) will look like this in Android / Firefox):

If earlier (before 3.8) the user should have turned off the application on their own, otherwise if you close the browser or log in from another place, all that was visible was a white background. Now broadway takes over the work with sockets and idle / disconnect. Now we need to deal with other little things
A bit of customization broadwayd

Fortunately, GTK3 is an open source, so you can go deeper and change something.
Let's start with the window title.
The default text, “broadway 2.0,” is unlikely to suit anyone, we will change that. The HTML5 server page consists of a template and a JS file. The page title is written in the standard HTML header:
broadway 2.0
During assembly, the page is converted by a perl script into a simple C array, which is stored in gtk + -3.10.7 / gdk / broadway / clienthtml.h - static const char client_html [].
Then everything is simple, gtk + -3.10.7 / gdk / broadway / broadway-server.c:
static void
got_request (HttpRequest *request)
...............
if (strcmp (escaped, "/client.html") == 0 || strcmp (escaped, "/") == 0)
send_data (request, "text/html", client_html, G_N_ELEMENTS(client_html) - 1);
Change the operation algorithm a bit, we will use the header as a format for sprintf. Therefore, gtk + -3.10.7 / gdk / broadway / clienthtml.h will have to be slightly corrected - add screening of percent signs, for example, like this:
background-image: -moz-linear-gradient(#D1D2D2 0%%, #BABBBC 65%%, #D4D4D5 100%%);\n"
instead
background-image: -moz-linear-gradient(#D1D2D2 0%, #BABBBC 65%, #D4D4D5 100%);\n"
And replace the title text
broadway 2.0
on specifier
%s
Change the algorithm of the server itself:
char *http_title = getenv("GTK_HTTP_TITLE");
if (NULL == http_title)
{
http_title = "Default";
}
size_t total_html_size = sizeof client_html + strlen(http_title) + 1;
char *_client_html = malloc (total_html_size);
snprintf(_client_html, total_html_size, client_html, http_title);
if (strcmp (escaped, "/client.html") == 0 || strcmp (escaped, "/") == 0)
send_data (request, "text/html", _client_html, strlen(_client_html) - 1);
...........
g_free (_client_html);
One could use asprintf, but then one would have to upgrade the Makefile, which I did not want to do.
Rebuild broadwayd, set the global variable and start the server
export GTK_HTTP_TITLE="PAGE TITLE"

You can change the default screen size, it may be relevant when used with mobile devices.
static void
gdk_broadway_screen_init (GdkBroadwayScreen *screen)
{
screen->width = 1024;
screen->height = 768;
}
And change the name of the GDK screen, so you can, for example, create several specific versions of broadwayd and identify them in this way
static gchar *
gdk_broadway_screen_make_display_name (GdkScreen *screen)
{
return g_strdup ("browser");
}
static gchar *
gdk_broadway_screen_get_monitor_plug_name (GdkScreen *screen,
gint monitor_num)
{
return g_strdup ("browser");
}
Conclusion
Broadway is a really interesting GTK3 feature that allows you to quickly create interesting lightweight services for a certain range of tasks. But, unfortunately, practically not used. With this article, I wanted to draw the attention of a large number of people to broadway and maybe someone can solve their problem using simpler methods.