Skip to content

Virtual Desktop & Window Management

Leanid Astrakou edited this page Jul 15, 2020 · 7 revisions

The Virtual Desktop is a web component of Zowe which is an implementation of MVDWindowManagement, the interface which is used to create a window manager.

The code for this software can be found in the zlux-app-manager repository repository.

The interface for building an alternative window manager is present in zlux-platform.

Window Management acts upon Windows, which are visualizations of an Instance of an App. Apps are Plugins of type "application", and therefore the Virtual Desktop operates around a collection of Plugins.

NOTE: Other objects and frameworks that can be utilized by Apps, but not related to Window Management, such as App-to-App communication, Logging, URI lookup, and Auth are not covered here.

NOTE: APIs here exist but are under development, and features may be reorganized if it simplifies and clarifies the API, as well as that features may be added if Apps can benefit from them.

Loading & Presenting Apps

Upon loading the Desktop, a GET call is made to /plugins?type=application This returns a JSON list of all Apps present on the server, which can be accessed by the user. Apps can be composed of dataservices, web content, or both. Apps that have web content will be presented in the Virtual Desktop UI.

The Virtual Desktop presents a taskbar at the bottom of the page, where it presents each App as an icon with a description. The icon used, and description presented are based off of the App's PluginDefinition's webContent attributes.

Plugin Management

Apps can gain insight into the environment they have been spawned in via the Plugin Manager. This should be used to check for if a Plugin is present before acting upon the existence of that Plugin. When the Virtual Desktop is running, the Plugin Manager can be accessed via ZoweZLUX.pluginManager

The following are functions you may use on the Plugin Manager

  • getPlugin(pluginID: string)
    • Accepts a string of a unique plugin ID, and returns the Plugin Definition Object (DesktopPluginDefinition) associated with it if found.

Application Management

Apps within a Window Manager are created and acted upon in part by an Application Manager. This can facilitate communication between Apps, but formal App-to-App communication should be performed by calls to the Dispatcher. The Application Manager is not normally accessible directly by Apps, instead used by the Window Manager.

The following are functions of an Application Manager

  • spawnApplication(plugin: DesktopPluginDefinition, launchMetadata: any): Promise<MVDHosting.InstanceId>;

    • Opens an App instance into the Window Manager, with or without context on what actions it should perform after creation.
  • killApplication(plugin:ZLUX.Plugin, appId:MVDHosting.InstanceId): void;

    • Removes an App instance from the Window Manager.
  • showApplicationWindow(plugin: DesktopPluginDefinitionImpl): void;

    • Makes an open App instance visible within the Window Manager.
  • isApplicationRunning(plugin: DesktopPluginDefinitionImpl): boolean;

    • Determines if any instances of the App are open in the Window Manager.

Windows & Viewports

When an App's icon is clicked on the taskbar, an instance of the App is started and presented within a Viewport which is encapsulated in a Window within the Desktop. Every instance of an App's web content within Zowe is given context and can listen on events about the Viewport and Window it exists within regardless of if the Window Manager implementation utilizes these constructs visually - it is possible to create a Window Manager which only displays 1 App at a time, or to have a drawer-and-panel UI rather than a true windowed UI.

When the Window is created, the App's web content is encapsulated dependant upon its framework type. The following are valid framework types at this time:

  • "angular2": The web content is written in Angular, and packaged with Webpack. App framework objects are given through @injectables and imports, as seen in zlux-app-manager
  • "iframe": The web content can be written using any framework, but is included via an iframe tag. Apps within an iframe can access framework objects through parent.ZoweZLUX and callbacks.
  • "react": The web content is written in React, Typescript, and packaged with Webpack. App framework objects are provided via the ReactMVDResources object

In the case of the Virtual Desktop, this framework-specific wrapping is handled by the Plugin Manager

Viewport Manager

Viewports encapulate an instance of an App's web content, but otherwise do not add to the UI - they do not present chrome as a Window does. Each instance of an App is associated with a viewport, and operations to act upon a particular App instance should be done by specifying a viewport for an App, to differentiate which instance is the target of an action. Actions performed against viewports should be done in via the Viewport Manager.

The following are functions of the Viewport Manager

  • createViewport(providers: ResolvedReflectiveProvider[]): MVDHosting.ViewportId;

    • Creates a viewport for embedding an App's webcontent into.
  • registerViewport(viewportId: MVDHosting.ViewportId, instanceId: MVDHosting.InstanceId): void;

    • Registers a previously created viewport to an App instance.
  • destroyViewport(viewportId: MVDHosting.ViewportId): void;

    • Removes a viewport from the Window Manager.
  • getApplicationInstanceId(viewportId: MVDHosting.ViewportId): MVDHosting.InstanceId | null;

    • Returns the ID of an App's instance from within a viewport within the Window Manager.

Injection Manager

When Angular Apps are made, they can utilize injectables to be informed of when an action happens. iframe Apps indirectly benefit from some of these hooks due to the wrapper acting upon them, but Angular Apps have direct access to these.

This section details injectables that Apps can utilize

Plugin Definition

@Inject(Angular2InjectionTokens.PLUGIN_DEFINITION) private pluginDefinition: ZLUX.ContainerPluginDefinition

Provides the Plugin Definition associated with this App - it can be used to gain some context about the App but also can be used by the App with other App framework objects to perform a contextual action.

Logger

@Inject(Angular2InjectionTokens.LOGGER) private logger: ZLUX.ComponentLogger

Provides a logger that is named after the App's Plugin Definition ID.

Launch Metadata

@Inject(Angular2InjectionTokens.LAUNCH_METADATA) private launchMetadata: any

If present, this variable requests the App instance to initialize with some context, rather than the default view.

Viewport Events

@Inject(Angular2InjectionTokens.VIEWPORT_EVENTS) private viewportEvents: Angular2PluginViewportEvents

Presents hooks that can be subscribed to for event listening. Events include:

  • resized: Subject<{width: number, height: number}>
    • Fires when the viewport's size has changed.

Window Events

@Inject(Angular2InjectionTokens.WINDOW_EVENTS) private windowEvents: Angular2PluginWindowEvents

Presents hooks that can be subscribed to for event listening. Events include:

  • maximized: Subject

    • Fires when the Window has been maximized.
  • minimized: Subject

    • Fires when the Window has been minimized.
  • restored: Subject

    • Fires when the Window has been restored from a minimized state.
  • moved: Subject<{top: number, left: number}>

    • Fires when the Window has been been moved.
  • resized: Subject<{width: number, height: number}>

    • Fires when the Window has been resized.
  • titleChanged: Subject

    • Fires when the Window's title has changed.

Window Actions

@Inject(Angular2InjectionTokens.WINDOW_ACTIONS) private windowActions: Angular2PluginWindowActions

An App can request actions to be performed on the Window via the following:

  • close(): void

    • Closes the Window of the App instance.
  • maximize(): void

    • Maximizes the Window of the App instance.
  • minimize(): void

    • Minimizes the Window of the App instance.
  • restore(): void

    • Restores the Window of the App instance from a minimized state.
  • setTitle(title: string):void

    • Sets the title of the Window.
  • setPosition(pos: {top: number, left: number, width: number, height: number}): void

    • Sets the position of the Window on the page, as well as the size of the window.
  • spawnContextMenu(xPos: number, yPos: number, items: ContextMenuItem[]): void

    • Opens a context menu on the App instance, which uses the <Link: Context Menu framework>
  • registerCloseHandler(handler: () => Promise): void

    • Registers a handler which will be called when the Window and App instance are closed.

Example: What if I wanted to use the Window Actions to begin my App in maximized mode upon start-up?

Angular

  1. Import Angular2InjectionTokens from 'pluginlib/inject-resources'
  2. Within the constructor of your App, in the arguments, do @Optional() @Inject(Angular2InjectionTokens.WINDOW_ACTIONS) private windowActions: Angular2PluginWindowActions
  3. Then inside the constructor, check that window actions exist and then execute the action if (this.windowActions) { this.windowActions.maximize(); }
  4. Depending on your App layout, certain UI elements may not have loaded so to wait for them to load, one may want to use something like Angular's NgOnInit directive.

React

  1. Similar to how we do things in Angular, except the Window Actions (& other Zowe resources) are located in the resources object. So if we were using a React.Component, we could have a constructor with constructor(props){ super(props); ... }

  2. Then accessing Window Actions would be as simple as this.props.resources.windowActions

IFrames

  1. Iframes are similar to Angular & React, but require a different import step. Instead to use Window Actions (& other Zowe resources), we have to import the Iframe adapter. The Iframe adapter is located in zlux-app-manager/bootstrap/web/iframe-adapter.js so something like a relative path in my JS code will suffice,

<script type="text/javascript" src="../../../org.zowe.zlux.bootstrap/web/iframe-adapter.js"></script>

  1. Then to use Window Actions would be as simple as await windowActions.minimize();

NOTE: The Iframe adapter is not yet feature-complete. If you are attempting to use an event supported by Angular or React, but not yet supported in Iframes, try to use the window.parent.ZoweZLUX object instead.