Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Custom titlebar and menu (Windows only)

Brian Clifton edited this page Jan 5, 2017 · 3 revisions

The Electron/Muon layer for macOS offers a great option for the BrowserWindow object which puts functional "traffic light" (close, minimize, fullscreen) buttons in the top left of the window. However, this option is not available for Windows or Linux.

Linux is tricky because of the variety of window managers available. What should the minimize/maximize/close buttons look like? Because of this problem, no action has been taken. You can read more details about the issue here.

The custom titlebar for Windows was implemented back in September 2016 and this wiki page will go over functionality that was introduced.

Project goal

The overall goal is to make the titlebar on Windows slim and sleek... taking up very little pixel space. Before this change was implemented, a full titlebar was shown. It does show the title and offers the caption buttons, but most of the space is wasted. look at the wasted space on the titlebar

How was it implemented (and why?)

The first approach taken was to be Win32 friendly. A demo project was created in which the goal was to put a real Win32 menu on the same line as real working caption buttons. Here's a screenshot of the demo program, which (although ugly) shows that this is possible. rough implementation of menu on the same line as caption buttons

There are lots of problems with this pure Win32 approach:

  • The window has to be created as WS_POPUP, which is not supposed to have a menu
  • The caption buttons will ONLY draw if you include the WS_CAPTION style (which includes the whole titlebar).
  • The rendering of the caption buttons can be done manually... but matching Windows 10 styles is not well documented / difficult

For these reasons, we chose to take a different approach.

  • Create the window in Electron/Muon as "frameless" (initialized with frame: false)
  • Caption buttons would be manually rendered / re-implemented in React
    • Windows 7 will render similar to Google Chrome on Windows 7 (except using Gray colors)
    • Windows 8 and above will render in the Windows 10 style
  • Menu will be manually rendered and re-implemented in React

The implementation

To get a good overview, the best place to look is in js/components/main.js.

The customTitlebar property is called in render(). If enabled, it will optionally add titlebar components to the main window.

There are two components you can check out:

The menubar is hidden by default and can be toggled with ALT. The detection of ALT happens in a key listener in main.js (see method registerCustomTitlebarHandlers()). Once the menu is displayed, it registers additional listeners for arrowkey navigation.

The caption buttons have two different states

  • rendered when menu is shown
  • rendered when menu is hidden

The transition between these two states isn't the smoothest. However, we put a lot of time and thought into where the buttons are in each state, which you can read more about here.

Interesting notes:

  • Unlike before (Electron menus did not support this on Windows), the menus are now fully navigable by keyboard.
  • the win7 style will be applied at a top level if you're on Windows 7. Alternatively, win10 will be applied. You can use the Electron dev tools (shift+F8) to manually edit this style if you'd like to see the appearance for Windows 7 or vice-versa

Features available on all OSes

While the majority of the functionality is only usable on Windows, some of it benefited macOS and Linux.

accelerator keys shown in context menu

mac - accelerator text in context menu windows - accelerator text in context menu

ability to automate testing using webdriver

Webdriver tests on Windows are currently not working. However, with a small amount of work, the menus used on Windows can be shown for macOS and Linux. Where this comes in handy is for testing. Because the menu itself is HTML and can be interacted with, menu automation is possible.

For example, you could automate pushing ALT to show the menu, wait until the context menu with the selector you'd like is shown, then you can navigate the menu using keyboard or click. Once an action is taken, you can use webdriver to ensure your expected result actually did happen.