Magic Remote

Introduction

Webos magic remote

One of the WebOS SmartTv specific capabilities is the LG Magic Remote. A pointer allowing to navigate in any app through point and click.

Supporting the magic remote for a third party application may be mandatory to be allowed to deploy on LG Store.

Since v7.2201, Dana for WebOS supports this specific device and feature.

Configuration

To configure and use the magic remote, be sure you have set up your WebOS configuration.

To enable Magic remote integration, simply set enablePointer property to true in your profile:

"base-webos": {
    "app": {
        "enablePointer": true
    }
}

Handling remote events

Goal of Dana is to forward Magic Remote events to your screens so your app can support and behave accordingly. Each app and screens must define how it should interact with it like any other input events (LEFT, RIGHT, OK, …).

Caution

Specific UX behaviours may be needed as most of TV Application are not natively designed to support a mouse pointer.

Like a classic mouse control, LG magic remote supports these four pointer events:

  • click
  • hover
  • unhover
  • scroll

Any screen is able to listen to one or all of these inputs:

import $Screen from "@Screen";
import $MouseEvent from "@MouseEvent";

export default $Screen.declare("AppScreen", {
    inputs: [
        $MouseEvent.click,
        $MouseEvent.hover,
        $MouseEvent.unhover,
        $MouseEvent.scroll
    ],

    methods: {
        onMouseClick: function (element) {},
        onMouseHover: function (element) {},
        onMouseUnhover: function (element) {},
        onMouseScroll: function ({event, element}) {},
    }
}

Every handler has one parameter called element referencing to the View that triggered the pointer event (see more info below).

Therefore, every screen can define its own behaviour according to the kind of event and the View underneath:

onMouseHover: function(element) {
    if(element.id === this.clockView.id) {      // check if the "element" matches your view's screen children
        element.focus();                        // "element" is a View so you can focus it directly (or use setState)
    } else if(element.parent.id === this.programList.id) {      // Or you can check if the element's parent is a known children
        this.programList.selectItem(element.index);             // "element" knows its index so you can select the good item
    }
},

onMouseClick: function(element) {
    if(element.data.isContent) {                 // you can check if your View data matches your needs
        this.route("fip", {data: element.data}); // open the program info page with some data as context
    }
},

onMouseScroll: function({event, element}) {
    if(event.deltaY > 0) {                       // scroll "event" param is a WheelEvent
        this._down();
    } else {
        this._up();
    }
}

Enable collision on specific item

You need to activate view collision on items that you want to trigger mouse events. Flag isInteractive will allow to enable above events to be triggered on some specific View.

export default $View.declare("MyView", {
    children: {
      img: {class: $ImagePrimitive},
      rect: {class: $RectanglePrimitive}
    },
    properties: {
      isInteractive: true
    }
});

Default value of isInteractive is false. Only use this flag on view which needs collision detection.

What element is returned by the events ?

Dana’s integration is based on Lightning SDK and browser collision mechanism analyze. As a result, element returned by remote events are linked to those implementation and can be different between CSS and Lightning.
By default, Dana always trigger events on the lowest possible View in the rendering tree that is “under” the cursor (taking position and size properties in consideration)

Pointer trigger

In this example, event will be triggered on ProgramListItemView#1

CSS

In case 2 (or more) elements overlap, Dana will trigger the mouse events on the element with:

  1. The highest z-index (using stacking context)

Lightning

In case 2 (or more) elements overlap, Dana will trigger the mouse events on the element with:

  1. The highest z-index (absolute z-index, not using stacking context)
  2. The highest element id (integer incremented for every new Element creation)

Technical limitations

Not on primitives

Pointer events will be triggered on View only, not on Primitive. This is a technical choice to make event handling easier.
Therefore, if needed to distinguish two visual elements, it is recommended to create two separate views.

Caution

Creating views instead of primitives may impact performances, then it is important to not be greedy.

Lightning specific limitations

Bad behaviour on renderToTexture

If any of your component declares an rtt property (to enable Lightning renderToTexture), there is an issue with pointer events handling and positions of lightning elements.

For more information, check this GitHub issue.

Bad behaviour on RecyclingList

There is a known issue in which pointer events are not fired after navigating in a RecyclingListView.

This is because the List container may be out of screen bounds and not considered to be active by Lightning anymore.

An issue is opened on our side, and we will inform you once it is solved.

Z-index is not contextual

As collision detection is not using stacking context, it will not be possible to collision with a child which has a parent View with a positive z-index. Parent view always be considering collision before its child.