Magic Remote

Introduction

webos magic remote One of the WebOS SmartTv specific capabilities is the [LG Magic Remote](https://www.lg.com/ch_fr/televiseurs/lg-mr20ga). 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": {
    "vendors": [...]
    "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();
    }
}

What element is returned by the events ?

Dana’s integration is based on Lightning SDK mechanism and so element returned by remote events are linked to this implementation.
Lightning SDK (and so 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 case 2 (or more) elements overlap (in the example above: HomeScreen, ProgramListView and ProgramListItemView), Dana will trigger the mouse events on the element with:

  1. The highest z-index
  2. The highest element id (integer incremented for every new Element creation)

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

Technical limitations

Lightning support only

For now, the pointer is handled by Lightning renderer only. However, an adapter exists and a specific CSS implementation can be done. If needed, please contact the Dana team.

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.

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.