Launch WebviewWindow
Learn about Wails WebviewWindow, its configurations, and how Wails manages this window using Go and runtime APIs. In this chapter, we will set up layout for our calculator app to serve as the foundation for visualizing our app and future enhancements.
What is Webview:
I won’t delve into too much detail, as most frontend developers are already familiar with the concept of Browsers. In essence, a Webview is an embedded website rendering engine provided by the operating system, complete with its own JavaScript runtime. It’s not a full-fledged Browser.
For a deeper understanding, you can refer to Wikipedia
Webview Renderers and Runtimes:
Linux:
- Webkit2GTK: A Linux-specific port of WebKit for embedding Webviews in applications.
- JS Runtime: JSC
MacOS:
Windows:
Read more about Webviews in Communication in Webviews chapter
Structure of main.go
The process of launching a Wails application can be broken down into several phases:
Creating a new Application
- This creates an
app
instance where you can attach multiple windows or menus. - Attaching
Services
- These act as an API interface for the frontend to interact with the backend.
- Everything else when creating the
app
instance can be left as is.
app := application.New(application.Options{
Name: "learn-wails",
Description: "A demo Calculator App",
Services: []application.Service{
// ... List of all the Services
},
// Leave the following as is,unless you know what you are doing.
Assets: application.AssetOptions{
Handler: application.AssetFileServerFS(assets),
},
Mac: application.MacOptions{
ApplicationShouldTerminateAfterLastWindowClosed: true,
},
})
Optional Event Handlers:
- Attach event handlers to the
app
instance if needed.
Custom App Menus (Optional):
- Create and attach a custom list of menus to the app instance.
- Example of adding custom menus
Creating a Webview Window:
- Initialize and load the main HTML page in a new window.
app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
Title: "Window 1",
Mac: application.MacWindow{
InvisibleTitleBarHeight: 50,
Backdrop: application.MacBackdropTranslucent,
TitleBar: application.MacTitleBarHiddenInset,
},
BackgroundColour: application.NewRGBA(0, 0, 0, 0),
BackgroundType: application.BackgroundTypeTransparent,
Linux: application.LinuxWindow{
WindowIsTranslucent: true,
},
URL: "/",
MinWidth: 800,
MinHeight: 600,
JS: "console.log('preload script', document.querySelector('body'))",
// BackgroundColour: application.NewRGB(27, 38, 54),
// AlwaysOnTop: true,
// Frameless: true,
})
// window.SetMinSize(1280, 720)
// window.SetMaxSize(2560, 1440)
Launching the Application:
The application is launched using the app.Run()
API. However, the visibility of the app window can be controlled programmatically using the window.Show()
and window.Hide()
APIs.
window.Show()
: Displays the app window.window.Hide()
: Hides the app window.
These APIs allow for flexible manipulation of the window’s visibility state based on your application’s logic or user interactions.
This chapter will focus on creating a Webview window. Other phases/APIs may be discussed in subsequent chapters.
Webview Window
A Webview Window in Wails is essentially a Go struct
with custom properties, event emitters/listeners, and APIs for window management.
The WebviewWindowOptions
struct is particularly important, as it defines the window’s appearance and behavior. Let’s review some of its key properties:
Key Properties of WebviewWindowOptions
AlwaysOnTop
bool
- Keeps the window above all other windows, useful for features like Quake-style terminal windows.
URL
string
- Specifies the URL or local HTML file to load. While remote hosting (via HTTP) is possible, local-first desktop apps are generally preferred. Remote capabilities can be added incrementally if needed.
Frameless
bool
- Removes the window frame and border. This is useful for curved window designs, but cross-platform support for this feature is currently limited.
- Note that frameless windows do not support native resizing.
MinWidth
, MinHeight
, MaxWidth
, MaxHeight
int
- Prevents resizing below specified dimensions.
- Using
window.SetMinSize
orSetMaxSize
feels more intuitive to me, since a user can forget to set one of these options and get confused, but the Setter APIs always require user to set both the options to restrict the window size.
Remember
wails
will set min width/height of the app only when bothMinWidth
&MinHeight
options are set, i.e.!= 0
The same is true forMaxWidth
andMaxHeight
as well.
StartState
application.WindowState
- Determines the initial state of the window (e.g., minimized, maximized).
BackgroundColour
application.RGBA
- Sets the background color of the window. For consistent cross-platform behavior, avoid using alpha transparency.
- We can anyway override this color using CSS on
html
orbody
elements.
JS
string
- Think of it as Electron’s
preload
scripts. - JavaScript string passed to this property is loaded before the DOM is loaded (i.e before
DOMContentLoaded
event).
InitialPosition
application.WindowStartPosition
- Specifies the starting position of the window (e.g., centered or specific coordinates using
X
andY
values).
Zoom
(float64
)
- Adjusts the window zoom level, useful for supporting high-resolution displays like 4K screens.
EnableDragAndDrop
(bool
)
- Enables drag-and-drop functionality for file uploads or processing.
ShouldClose
(func(window *WebviewWindow) bool
)
- A callback function to determine whether the application should close immediately or perform additional actions first.
Platform Specific Options:
Mac
application.MacWindowWindows
application.WindowsWindowLinux
application.LinuxWindow
- All the above options are platform specific and useful for modifying per platform window styles.
Dev options for Webview Window Options:
The following properties are particularly useful during development (and are always set to false
in production builds):
OpenInspectorOnStartup
bool: Automatically opens the developer tools when set totrue
.DevToolsEnabled
bool: Should be disabled in production builds for security. By default it is.
For more details, refer to the Wails v3 documentation or explore the source code directly.
Frontend
<script lang="ts">
const log = (x: string) => () => {
console.log(x);
}
const buttonListenerMap = {
"fib": [log("fib"), 'a'],
"√x": [log("square root") , 'b'],
"^2": [log("sqaure"), 'c'],
"/": [log("divide"), 'd'],
"AC": [log("Reset"), 'e'],
"7": [log("Number 7"), 'f'],
"8": [log("Number 8"), 'g'],
"9": [log("Number 9"), 'h'],
"×": [log("Multiply"), 'i'],
"C": [log("Clear"), 'j'],
"4": [log("Number 4"), 'k'],
"5": [log("Number 5"), 'l'],
"6": [log("Number 6"), 'm'],
"-": [log("Subtract"), 'n'],
"exp": [log("Expression"), 'o'],
"1": [log("Number 1"), 'p'],
"2": [log("Number 2"), 'q'],
"3": [log("Number 3"), 'r'],
"+": [log("Addition"), 's'],
"𝑥": [log("Variable `𝑥`"), 't'],
"0": [log("Number 0"), 'u'],
".": [log("Decimal"), 'v'],
"=": [log("Result"), 'w'],
"𝑦": [log("Variable `𝑦`"), 'x'],
} as Record<string, [() => void, string]>
</script>
<div class="grid">
{#each Object.entries(buttonListenerMap) as [k, v] (k)}
<button onclick={v[0]} style:--area={v[1]}>{k}</button>
{/each}
</div>
<style>
.grid {
display: grid;
grid-template-areas:
"a b c d e"
"f g h i j"
"k l m n o"
"p q r s t"
"u v w s x"
;
gap: 0.5rem;
height: 100%;
}
button {
font-size: 1.25rem;
grid-area: var(--area);
font-weight: bold;
}
</style>
The above screenshot is taken on a Ubuntu Desktop, and has issues with curved border on my local system.
At this stage, our goal is simply to set up a basic UI, without any functionality or logic. Those aspects will be addressed in the next chapter.
To create the layout, I have utilized CSS Grid, along with buttons and a textarea.
Refer to this Commit on the repo to check the details on the changes.