Porting Brackets to a new platform

by Dimitar Trendafilov November. 08, 12 0 Comment

is a code editor for HTML, CSS and JavaScript that is built in HTML, CSS and JavaScript. That makes it a fully featured desktop application written using Web technologies. Brackets embeds a browser to show and run the entire editor and extends it with additional functionality used by JavaScript. There are more and more applications using this kind of mixed platform – HTML/JavaScript becomes first class User Interface (UI) (and not only) for Window 8 applications, other tools from Adobe such as Edge AnimateIcenium – a new cloud IDE, recently announced by TelerikSencha Animator also is an HTML5 application, running inside QT WebKit. Even the UI of most browsers is written in HTML.
This approach has several advantages:

  • fully cross-platform UI – as long as the browser is running on a platform, the UI is going to be running on that platform too
  • full UI customization using CSS lots of available application frameworks MVC, MVVM – Backbone.js, knockout.js, you name it
  • lots of UI libraries – Kendo UI, jQuery UI, mochaui
  • easy development of the UI using Chrome Dev Tools, Firebug, etc.
  • Live reload of the UI, without restarting the whole application!
  • native access to filesystem and everything without sandboxing
  • use existing native APIs
  • native performance where necessary
  • only single browser to support – this is a huge relief for the HTML/JavaScript developers

Given the advantages, I am sure that more and more mixed native and HTML applications are going to appear.

Brackets Architecture

Brackets consists of two applications running together – an HTML/JavaScript application and a native C++ shell that runs the HTML application. The native shell consists of two processes – one running the HTML application inside a browser, and one running the heavy native part like filesystem operations and number crunching. The communication between the two processes is asynchronous, using JavaScript callbacks and request / response for the native code.

  • The shell extends the standard HTML DOM with the following functions:
  • Open file or directory using the OS dialog
  • Read file
  • Write file
  • Create directory
  • Rename file or directory
  • Get file last modification time
  • List directory contents
  • Open and close browser for Live Preview
  • Open extensions directory in OS file browser
  • Open developer tools for brackets itself
  • Get the system default language
  • Time since the application start
  • Get the application support directory

Brackets Shell implements the asynchronous communication between the HTML render process and the browser in a very simplistic way: JavaScript executes a function appshell.fs.readdir(path, callback), the render process stores the callback in a mapping from a request id to callback and calls the native process with the name of the function. When the native process is ready it sends back any result of the call together with the request id. The HTML process finds the callback by the request id and executes it with any result.

Porting Brackets to a new platform

This architecture is the same as for any good GUI application – the UI never executes any expensive functions and is always responsive and all data manipulation is in a separate thread.

Running Brackets in Coherent UI

Making Brackets run inside Coherent UI is really easy. We start by creating a view that loads www/index.html relatively to the executable. To support Coherent UI we have to include some JavaScript files in the index.html of Brackets

These scripts are Coherent UI dependencies, Coherent UI itself and the abstraction layer between all JavaScript code of Brackets and Coherent UI. Then we have to register our native callbacks for the asynchronous calls:

Brackets native functions always return an error code as first argument to the JavaScript callback. This mechanism can be implemented in Coherent UI, but then the callbacks always have to do two things – handle the correct result and handle the error, which is kind of annoying. engine.Call might take two callbacks – one for the successful result and one for error. Therefore we have to wrap the normal callback in an object with separate handlers for success and error.
gist: javascript callback wrapper
All that is left now is to wrap the callbacks and use engine.Call instead of native function.

and to write the native function

Handling synchronous calls

Brackets has and some synchronous methods that return to JavaScript immediately. These methods are:

  • Get the application support directory
  • Get the system default language
  • Time since the application start

Coherent UI does not support providing synchronous JavaScript functions by design, so we will have to work around that.

The application support directory remains constant through a single run of Brackets, so we can set it once and for all during application initialization:

Getting the system default language might be implemented in the same way. The last method left is time since the application start and is used only in Show Performance Data menu. This method might be implemented entirely in JavaScript, assuming Brackets is not going to be reloaded during the performance test run.

Porting Bracket to Linux

Since Coherent UI already runs on Linux and we have implemented most of the native functions using the cross-platform boost::filesystem library, all we have to do to get is showing an open file dialog, creating and closing a chrome instance opening an URL and folder in the default OS HTML browser and file manager.

We use the GtkFileChooserDialog and the xdg-open tool. Unfortunately, the Live Preview doesn’t work under Linux. Live Preview in Brackets creates a new Google Chrome instance with enabled remote debugger, attaches to the debugger using XmlHttpRequest and WebSockets and controls the instance via the debugger. What happens on Linux is that one of the XmlHttpRequests fails with “DOM Exception” and the debugger is unable to attach to the instance.

Another Linux related issue is that I couldn’t find a way to close a Google Chrome  tab on Linux gracefully, so when the developer tools are closed you get the “Ow, Snap” page. In a future version we will stop usingGoogle Chrome for Live Preview and for showing the developer tools, which will fix this problem.

Here is a short video of Brackets running on Linux:

Get a prebuild package or get

 Coherent UI>/div> and start hacking!
Follow Dimitar on Twitter: @DimitarNT
Social Shares

Related Articles

Leave a Comment