Magic Remote
Introduction

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)
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:
- The highest z-index
- 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.