Snap SDK
The essential layout capabilities of Here™ Core platforms allow end users and developers to compose sophisticated collections of multiple web apps in a single window. This key capability means that users can run apps side by side, even if those apps are produced by different teams or different vendors, without the need to toggle between windows to get tasks done.
With Snap SDK, Here™ extends its layout capabilities to snapping windows together, allowing them to be grouped to behave like a single window. One of the most powerful aspects of Snap SDK is that this ability to create window groups is not restricted to Here Core windows. With Snap SDK it is possible to group almost any window on the desktop. For example, it’s possible to group:
- Excel with a pricing app running in an Here Core window
- All of your Here platform windows or standalone Here Core windows
- A custom in-house developed application written in .NET with new features delivered as web content running in a Here Core window
- A whole collection of native applications, even if none of them are Here Core windows
Developers choose which applications’ windows should participate in snapping. They can either programmatically attach windows or let the user do it themselves, in which case the Snap SDK’s intuitive grouping overlays guide them to help them take control of their entire desktop. Grouped windows can be moved, minimized, restored, and switched to as a single unit, making it easier than ever for users to manage their desktop. All user actions with grouping or ungrouping are also available as events, allowing developers to save and restore state as needed.
Snap SDK is designed from the ground up to be performant, intuitive and robust. Snap SDK does not conflict with Windows® Snap layout in Windows® 10 and 11, and integrates intuitively with the Windows® Taskbar and window switching through alt/win-tab hotkeys. The technology powering Snap SDK under the hood is written in the Rust programming language to maximize security and performance. However, this is completely abstracted from developers through our ergonomic and fully typed JavaScript package available in the npm registry.
Download the Snap SDK client
The Snap SDK client library is an npm package that provides JavaScript/TypeScript Snap SDK APIs. As a developer, you must have npm installed in order to use it. To download and install the Snap SDK package, issue the following command in your Here Core project directory:
npm install @openfin/snap-sdk@SNAP_SDK_VERSION
Replace "SNAP_SDK_VERSION
" with the version number of Here™ Snap SDK you want to use.
Include the Snap SDK service
Snap SDK is a two-part system consisting of the client, described above, and the service, which is a standalone executable file (OpenFinSnap.exe
) that operates on the local computer.
A compatible version of the Snap SDK service is automatically fetched by the client library (1.1+), or it can be specified and downloaded by creating an appAssets
entry in the platform manifest.
📘 Note
Specifying a version is required only if you do not want to use the default version, or if you deploy to environments where access to cdn.openfin.co is not available.
This entry instructs your platform to download a specific version of the Snap SDK service if it does not already exist on your computer:
"appAssets": [
{
"src": "https://cdn.openfin.co/release/snap/SNAP_SDK_VERSION/snap.zip",
"alias": "openfin-snap",
"version": "SNAP_SDK_VERSION",
"target": "OpenFinSnap.exe",
"mandatory": true
}
]
Replace both occurrences of "SNAP_SDK_VERSION
" with the version number of Here™ Snap SDK service you want to use.
The Snap SDK client libraries are flexible enough to allow you to deploy the Snap SDK service through any other mechanism that works for your users. For example, you may wish to deploy the executable to your desktops using Microsoft SCCM rather than having it dynamically downloaded by Here Core. In this case, when using the client to start the server, you can specify the executable’s path on the local system.
Add Snap SDK code to your Here Core app or platform
Import the client library in your platform provider file:
let snapServer: Snap.SnapServer | undefined;
...
// Set the Here Snap SDK server ID to the platform UUID.
snapServer = new Snap.SnapServer(fin.me.identity.uuid);
Start Snap SDK Server
Start the SnapServer object with the following code:
// Download and start Here Snap SDK.
await snapServer.start()
This method starts the Snap SDK service as a hidden application.
OpenFinSnap.exe
appears in the Windows Task Manager.
Register Here Core platform windows with Snap SDK
Snap SDK doesn't manage every window on the system by default. It manages only those windows that are registered with Snap SDK.
To register your Here Core platform windows with Snap SDK, there are two ways to do it:
Method one: Start a new window and explicitly register it with Snap SDK by using the registerWindow function:
// Get a Here Core window to register with Snap SDK.
// In this example, we use the platform provider window.
const win = fin.Window.getCurrentSync();
const nativeId = await win.getNativeId();
// Register the platform window with Here Snap SDK.
await snapServer.registerWindow(fin.me.identity.uuid, nativeId);
Method two: Automatically register any newly created platform windows with Snap SDK by using the enableAutoWindowRegistration function. This automatically performs the tasks in Method one for each new platform window.
await snapServer.enableAutoWindowRegistration();
Listen to window events for snapped windows
Snap SDK injects code into each window to inspect and make available several WIN32 window messages as events in your platform. These events are made available from Here Core windows as well as from native application windows.
The events are:
Event | Description |
---|---|
client-registered / client-unregistered | Inform when a new window has been registered or unregistered with Snap SDK. |
clients-attached / client-detached | Inform when windows have been snapped together or unsnapped from the window group. |
client-activated / client-deactivated | Inform when a window has been activated or deactivated. |
move-size-completed | Inform when a window and its attached windows were moved or were resized. |
groups-changed | Inform when any window groups have been modified. |
An example of a client-activated
event handler:
snapServer.addEventListener("client-activated", (event: Snap.ClientActivatedEvent) => {
console.log(`Client Activated: ${JSON.stringify(event)}`);
});
Attach and detach windows from window groups with Snap SDK
To attach a window to a window group using the UI, you click and drag a window to a window group. To detach a window from a window group, you shift-click and drag a window away from a window group.
To programmatically attach a window to a window group, use the attachWindows function:
// Attach myWindowId to the specified window group.
await snapServer.attachWindows(fin.me.identity.uuid, myWindowId, "right", 0);
To programmatically detach a window from a window group, use the detachFromGroup function:
await snapServer.detachFromGroup(myWindowId);
Snapshots with Snap SDK
Here Core snapshots can be stored in the platform manifest. Snap SDK adds decorations (Snap SDK-specific JSON properties) to the platform manifest to describe Snap SDK managed windows and their relationship to a window group. This adds extra steps to creating and applying snapshots.
To create a Snap SDK snapshot, first call the base or prototype getSnapshot function, then call decorateSnapshot to add the Snap SDK decorations to the snapshot.
To apply a snapshot, first call the prepareToApplySnapshot function to inform the platform that it will soon apply a Snap SDK decorated snapshot. Next, apply the snapshot in the usual way. Finally, apply the Snap SDK decorations to the snapshot.
// Set up Here Core snapshot integration
fin.Platform.init({
overrideCallback: async (PlatformProvider, ...overrideArgs) => {
try {
class WithSnap extends PlatformProvider {
async getSnapshot(...args: [undefined, OpenFin.ClientIdentity]): Promise<OpenFin.Snapshot> {
// Create the platform snapshot.
const snapshot = await super.getSnapshot(...args);
// Add the Snap SDK properties to the platform snapshot.
const snapSnapshot = await snapServer.decorateSnapshot(snapshot);
return snapSnapshot;
}
async applySnapshot(...args: [OpenFin.ApplySnapshotPayload, OpenFin.ClientIdentity]): Promise<void> {
// Prepare Snap SDK to return a snapshot.
await snapServer.prepareToApplySnapshot();
// Apply the main snapshot.
await super.applySnapshot(...args);
// Apply the Snap SDK decorations to the snapshot.
await snapServer.applySnapshot(args[0].snapshot);
}
}
return new WithSnap(...overrideArgs);
} catch (error) {
return new PlatformProvider();
}
},
});
Native windows in Snap SDK
Native application support allows applications, like Excel, to join and participate in a window group. Native applications can be added to groups and then be moved, minimized, restored and switched to as a single group.
For a native application to participate with Snap SDK, Snap SDK must launch the application. This is accomplished by using the launch function and its parameter, LaunchOptions.
The LaunchOptions object contains four properties: The path
to the executable file, a unique string clientId
, a string array of command line args
, and an optional strategy
to identify the native application's main window.
Here is a simple example of a launch function to launch Windows 10 Notepad and open mydocument.txt
:
// Launch Windows 10 Notepad managed by Snap SDK.
const launchResult = await snapServer?.launch({
'C:\\Windows\\System32\\notepad.exe', // Path to Notepad.
'notepad-#1', // Unique client ID string.
['c:\\mydocs\mydocument.txt'] // Array of string arguments to be passed.
});
One of the challenges of integrating native applications with Snap SDK is that Here Core platforms have the concept of a main window, and native applications on Windows do not have that concept. So, Snap SDK must find the main application window on its own.
To accomplish this, various strategy types can be used. Starting in Snap SDK version 0.1.0, there are three strategies: waitForWindowOfName
, waitForWindowOfClass
, and delay
.
The waitForWindowOfName
strategy waits until the process opens a window with a window title that matches a regular expression rule. If the strategy doesn't find a matching window within the specified timeout period, the process fails.
The waitForWindowOfClass
strategy waits for a window whose underlying WIN32 Window Class that matches a regular expression rule. If the strategy doesn't find a matching window within the specified timeout period, the process fails.
The delay
strategy will delay for the specified time period, then grab the first window available.
More strategies are expected in future releases of Here™ Snap SDK.
This is an example of using the waitForWindowOfName strategy
to identify the main window of a custom process:
const launchResult = await snapServer?.launch({
'my_custom_process.exe', // Path to custom process.
'my-random-process-#1', // Unique client ID string.
[], // Empty array to indicate a strategy will be used.
{
type: 'waitForWindowOfName', // Strategy to use to identify the "main window."
timeoutMs: 15000, // Timeout in milliseconds.
matchRegex: '^My Process Title', // Regular expression to match title of "main window."
}
});
Native window limitations
While it is possible to save snapshot details containing snapped windows, applying a snapshot will not automatically launch the windows that are participating in that snapshot. It is currently the responsibility of the Platform Developer to launch any of the native applications that will be used within any given snapshot.
Some applications that consist of windows across multiple processes are not currently compatible with Snap SDK