skeezix
Internal Development
Minimenu doesn't really need a plugin architecture, but it both could be handy (depending what/if-any plugins get built) and is fun to work on, so I'm making this proposal. If I/we go ahead with it, it will have almost no impact on current usage -- it will not slow anything down or change anything, but will make available some new options to scripters and developers. A user could enable the plugin system, and explore plugin options if they wish .. but by default, plugins would be disabled. (And hence no startup time cost, no new secuerity concerns, etc.)
Pardon my typing.
Scope:
- this is not a hard and fast spec; this is just some ideas noted down to illustrate where I'm going. If everyone seems happy with it, then I/we can proceed and during the coding nail down the hard spec that plugin developers would use. So this is for illustration and discussion.
- this specification is not comprehensive -- I'll illustrate a number of API functions below, but it is certainly not all of the planned API, and certainly much more API would become available over time as we anticipate more requirements or make more available to plugins. Again, I'm always a fan of designing small first, and designing expandability in, and going baby steps.
- this specification is for a specific set of plugin extensions, not a comprehensive plugin system; ie: under this spec, plugins could create tabs or add some basic effects (audio, display) and whatnot, but not entirely replace the whole rendering engine for example. It is better to start with specific achievable goals and get that tested and out, and then bite off larger and larger pieces. Going for the big enchilada day one means it'd never happen. But this does not mean I've not considered it!
- in designing this (where 'designing' is too big a word; these are things just rolling around in my head on occasin for a few weeks) I'm picturing a few basic plugin ideas; one sample plugin might be a weather app, where it opens up a single tab and then shows a picture of the sun for a sunny day. Another plugin sample could be a file explorer that opens up one or more tabs based ont he number of SD cards it finds (say), capturing user input to move a selection around, etc. Another plugin sample would be one that makes a wooshing noise when tabs change, but doesn't have a UI of its own. Another plugin sample coudl be somethign that renders a datestamp on the normal UI, and has a configuration panel sasking wehat date format to show in.
- in the future, plugin options that may be useful are such ideas as.. plugin 'application sources'; right now minimenu scans for pnd-files, but we coudl extend the plugin system so a plugin could offer a new pool of applications (say, regular unix executables found on various devices.) I decided not to present that in this specification, because its actually a complex topic -- consider if two plugins want to both scan for some file type and offer it up; then we need mm to offer a 'which plugin to run the selected app?' type function; and what if one plugin wants to be a file browser, does it need to talk to a app-source plugin to negotiate something? I'm specifically avoiding inter-plugin-communications and other heady topics right now
- in the future, we may have inter-plugin communication if needed; that is certainly not discussed now
Security:
- by default, plugins will be disabled
- by default, plugins will only be able to effect their own tabs; if a plugin wishes to be able to render on top of something else, it will have to ask for permission to do so, which could be a configurable user thing. (ie: a weather plugin coudl open a weather tab, and draw it, but it cannot draw over some other plugins tab.) Some operationks are global -- a plugin can request any tab to 'move to front', so that a plugin could somehow cycle tabs based on some event, say, but I don't consider bringing tabs to front a destructive operation. Obviously it is abusable, if a plugin randomly switches tabs every half second. (If abuse becomes commonplace, tight secueity coudl be implemented without changing the API .. limit the number of operations per time or something, but let us not tie developers hands together in the spec; let us see how it goes and offer a reasonable 'catch mistakes' form of security.)
- rather than build (for now) an API for a plugin to ask for permission for various activities, let us just make assumptions -- a plugin can do whatever it wants to its tab(s), and not much of anythign to anything else.
- a plugin is a standalone application, so can really do anything it wants; this is a security concern, when running any foreign application and so out of scope. But remember -- a plugin could play audio, capture keystrokes, or take over the framebuffer on its own. In general, it will take effort for plugins to be so badly behaved.. a naively written little plugin will use the API and crash itself or whatever, without really bothering the user; but a malicious plugin can go nuts!
- resources; when a plugin requests loading a graphic or audio or whatever, the searchpath mm will use is _implied_; ie: it is the plugins path, plus the system path, notwhere else. The plugin is not going to be pully artwork willy nill across the device and making a mess, unless it goes out of its way to do so. (Possibly we may relax this, or make a API function so the plugin can attempt to extend the searchpath for loading resources, but we'll see.)
- plugins will have a specific searchpath; akin to other searchpaths in libpnd, I figure we'll search something like: /etc/pandora/mmenu/plugins:/media/*/pandora/mmenu/plugins -- something like that; ie: a user could deposit plugins onto SD or NAND (and some coudl be shipped with firmware if desired). Plugin searchpath would be defined in minimenu conf file, so could be editted by clueful users (not average joes.)
- plugins will have to be enabled/disabled on a per-plugin basis; ie: user enables plugins _at all_, and then the plugin conf panel would list all known plugins (default set to 'not run'),and flip them to 'run' if they wish. (ie: similar to the tab yes/no and app yes/no conf panels already present.) Maybe this is annoying, but seems safe -- user drops new plugin onto SD, and it won't magicly just run until they enable it.
Stability:
- plugins will be standalone applications that communicate with the host (minimenu presumably); if they crash, minimenu will not be impacted.
- ex: If a plugin opens tab(s), and then crashes, minimenu can detect the crash and close those tabs implicitly or notify the user or whatever; it will not bring the system down. (Which is important, since mm coudl be someones launch desktop; if mm is made crashing, and thus making the device hard to boot, this is BAD. Recoverable, but bad!)
- minimenu reserves the right to not run plugins at all; ie: if mmenu crashes, comes up, crashes again, we may build in logic to flip skin back to default and turn off plugin mode, automatically, so that when it comes up again, it has a higher chance of not crashing.
Architecture:
-in general, many plugin systems use shared libraries for the plug; the host scans its searchpath and finds plugins and links them live, and then the plugins API is called back and forth. This makes coding easy, but means if the plugin crashes, everything crashes.
- instead, I'm going for the approach where a plugin is a separate application, communicating via pipes with the host. ie: plugin stdin is from minimenu, and plugin stdout goes to minimenu. All dialog is via this -- if minimenu has 10 plugins, it has a pile of pipes open. (or sockets, but pipes make it much more convenient .. you end up with perl, python, shell scripts, all the way to C or whatever, being able to make plugins. Very handy!) IF the pipe breaks (due to plugin crash), mm just gets a 'pipe broken' error and drops the plugin and tabs, piece of cake.
- communciation across the pipes will be a lightweight form, essentially a slimmed JSON. Every language can parse JSON, and some 'just do it' (ie: python). IT is easy and fast to parse, without being 'heavy' like XML usually is. The specification for functions is below/.
- synchronous; for this spec, the host or plugin can make one call, and shoudl not do anything until a response (or timeout) is hit. Currently there is not to be batching of instructions, though perhaps in the future we may permnit this (especially for rendering?). For now, make one API call, then wait.
- It is expected that plugins will have an intermediate wrapper do the work. ie: If you're writing a plugin in python that really just wants to be a MVP (model view) thing, with the python fetching weather data and then having minimenu do the rendering etc, then you don't really want every python plugin writng its own api. I fully expect we (and the public) will make up wrappers that we can hopefully all share. Consider:
python plugin <-> python wrapper (pyMMPlugin or something) <-> minimenu
C plugin <-> C library ( libmmplugin.so or whatever) <-> minimenu
- I debated a few different philosophies; be it plugin is doing its own rendering and handing rendered data over to minimenu for display, versus minimenu doing all the work with a heavier API, so the plugind tend to be more simplistic, etc. After some debate, I've decided to opt on the 'expected use case' -- a plugin will probably be a simple 'model' and have mm do the heavy lifting (loading assets, rendering, playback, etc.) ie: It is doubtful many plugins will be writing fiull games or heavy animations, but instead offering things like file browsers. Do correct me if my assumption seems incorrect. By moving the heavy lifting to mm, it makes heavy graphical plugins hard to make, but makes simple plugins easy to make. Example -- a weather app ro file browser is rendering once, or perhaps redrawing after key events, so is not heavy rendering, so mm doing the work is fine. For a game with 50fps or something, using proxy-rendering in mm would suck.
- In the future, we could extend the protocol; if we need better graphic APIs in the interface, or the ability for a plugin to do its own rendering and hand the ready to use artwork to mm (over shared mem say), or even have host supply cvoords to the plugin and the plugin just render to the box specified using its own rendering code, then we could build that in. We'll just have to see where it goes. Yes, I know, by mentioning it here, I pretty much require someone to make the send plugin ever to be a Pacman or Space Invaders game, and thus break the whole plugin concept day one. I'm ready, bring it.
-- for a video player say, you'd want mm telling the playback tool where to draw;p its just not possible with this spec to receive high speed wholesale screens and show them; for that, we'd extend the spec
- We're talking about an event and call model; host (minimenu) will post events to the plugin, and the plugin can make calls to the mm hosting API. There can be some give and take where the plugin negotiates features with the host, so that we can default some behaviours off and let the plugin ask for them (which is another way of saying, we can extend the protocol over time, and the plugins can ask for features to see if present or set things up, and thus know if they're being run on too old a minimenu version or whatever.) (I'd liek to avoid versioning issues, but such is life.)
- the plugin code will presumably be a layer in minimenu; possibly other applications could be a plugin host using the same code. (ie: as a debug harness for one, or perhaps just to re-use plugins. A new host could ignore rendering calls or honor them, could be neat, or useless? But keeps the mmenu code neat.) ie:
minimenu <-> mm plugin host code <-> plugin(s) so the end pipeline looks like:
minimenu <-> mm plugin host <-> pipe <-> plugin wrapper/lib <-> plugin
- one idea I've had with the layered host-code, is that a plugin interface could in theory be made for xfce or other environs .. a mini-minimenu; the idea being that perhaps a useful mm plugin is made, that someone might want it on xfce as a widget or something. But yes, plugin/accessories/panels APIs are a dime a dozen .. shoudl we be making another one, or doing this at all in mmenu? hmmrdf
- most common needs shoudl be covered by the spec, but uncommon (by expectation) APIs may need ot be done by plugin. ie: We're not going to have mm pass lid open/close to plugins, or have timer functions. A plugin is welcome to cruise through the pandora API for lid open/close, or to open its own timers. A plugin _is_ a standalone app after all, so it can do a lot of its own screwing around. But since most plugins will not (likely?) be games, we don't need ot offer high granularity timers to plugins.. they can do it on their own. But for catchign button UI, a lot of plugins will want to do that, so we make an API for it.
- note that mm will maintain tab state; if tab is fronted (and rendered by plugin) and then backed, and then fronted again, mm will ensure the tab content is still showing (and not blank.) The plugin thus could decide to render on first fronting, and not again,m if it doesn't need to.)
Protocol:
- I will leave the actual JSON protocol out of this; it is not critical for specification, but in essence, something like ..
{ func: NAME, args: { arg1: value, arg 2: value } }
with response being aninteger, a string, a hash of values, whatever, as defined below.
TBD as coded, really.
Setup:
- host mmenu, when plugins are active etc etc, will iterate the searchpaths and pull up a list of plugins. For each found, and for those the user has enabled (see Security above), mmenu will then pass a startup event to the plugin.
- host, on close, will pass an event to the plugins so they can do cleanup
Events:
- Startup event (mmenu has loaded the plugin and hooked up the in/out pipes): eStart ( plugID ) -> ACK response only, responding with plugin name. It is not defined if mmenu will be running all plugin startups concurrently or in queue .. plugins should not care, and leave it to host to decide
- Shutdown event (mmenu needs to close, only happens on controlled exit and not crash): eShutdown ( plugID ) -> ACK response only. -- this in general shouldn't do anything, since not many will be start/stopping their desktop environment. Instead, I would suggest plugins do their work during the Startup event, and then save state during config changes or during interaction, for now.
- Tab change event -- by default, plugins do not receive this, but as noted below a plugin could request it. eTabChange ( tabID from, tabID to ); if this is registered, the event order relative to tab-activated/deactivated is not defined, so pick one or the other to operate on.
- Tab activated -- when a plugins own tab(s) become the active ('on front of stack'), they get this notification. If a plugin has 2 tabs in a row, it could well see 'tab deactive'tab active' in a row, as one loses focus and the next gets it. The order of events it not defined, so play smart. eTabFocus ( tabID ) -> expects ACK
- Tab deactivated -- when a tab loses focus. eTabUnfocus ( tabID )
- Key Down -- when a 'button' is pressed; by default no notification for this, to save on bandwidth, but plugin can ask for it. Technically, plugins could just open up /dev/event and do their own IO for keys, and may have to for lid type events etc, but to keep interface clean for 'most plugins'., we're offering button interface here. Buttins include face-buttons or keyboards, but not touchscreen, USB joysticks, etc.
Security: Plugins to receive input events for their tab when focussed;
eKeyDown ( key )
eKeyUp ( key )
- Pen Down -- similar to buttons, but for touchscreen; again, by default this will not happen unless requested, and the request documents the scope .. ie: only when plugins tabs are fronted, or for other tabs or the root-window or what
ePenDown ( x, y, pressure )
ePenUp ( x, y, pressure )
Plugin samples -
- the 'weather plugin' for instance would handle Startup event and request to open a tab; then it would poll some weather server to get info, and request loading some resources in mmenu, and finally, on eventFocus-thing, render the tab.
- for a plugin that makes swooshy noises on tab change, it needn't open its own tab, and instead just request and monitor tabchange events, and play fart noises as it sees fit.
- for a plugin that shows a battery indicator or date-stamp, it could just request permission to render on the root window (outside of its own tab, and may not have a tab at all), and then on tab change (or perhaps on its own timer event) request rendering.
Pardon my typing.
Scope:
- this is not a hard and fast spec; this is just some ideas noted down to illustrate where I'm going. If everyone seems happy with it, then I/we can proceed and during the coding nail down the hard spec that plugin developers would use. So this is for illustration and discussion.
- this specification is not comprehensive -- I'll illustrate a number of API functions below, but it is certainly not all of the planned API, and certainly much more API would become available over time as we anticipate more requirements or make more available to plugins. Again, I'm always a fan of designing small first, and designing expandability in, and going baby steps.
- this specification is for a specific set of plugin extensions, not a comprehensive plugin system; ie: under this spec, plugins could create tabs or add some basic effects (audio, display) and whatnot, but not entirely replace the whole rendering engine for example. It is better to start with specific achievable goals and get that tested and out, and then bite off larger and larger pieces. Going for the big enchilada day one means it'd never happen. But this does not mean I've not considered it!
- in designing this (where 'designing' is too big a word; these are things just rolling around in my head on occasin for a few weeks) I'm picturing a few basic plugin ideas; one sample plugin might be a weather app, where it opens up a single tab and then shows a picture of the sun for a sunny day. Another plugin sample could be a file explorer that opens up one or more tabs based ont he number of SD cards it finds (say), capturing user input to move a selection around, etc. Another plugin sample would be one that makes a wooshing noise when tabs change, but doesn't have a UI of its own. Another plugin sample coudl be somethign that renders a datestamp on the normal UI, and has a configuration panel sasking wehat date format to show in.
- in the future, plugin options that may be useful are such ideas as.. plugin 'application sources'; right now minimenu scans for pnd-files, but we coudl extend the plugin system so a plugin could offer a new pool of applications (say, regular unix executables found on various devices.) I decided not to present that in this specification, because its actually a complex topic -- consider if two plugins want to both scan for some file type and offer it up; then we need mm to offer a 'which plugin to run the selected app?' type function; and what if one plugin wants to be a file browser, does it need to talk to a app-source plugin to negotiate something? I'm specifically avoiding inter-plugin-communications and other heady topics right now
- in the future, we may have inter-plugin communication if needed; that is certainly not discussed now
Security:
- by default, plugins will be disabled
- by default, plugins will only be able to effect their own tabs; if a plugin wishes to be able to render on top of something else, it will have to ask for permission to do so, which could be a configurable user thing. (ie: a weather plugin coudl open a weather tab, and draw it, but it cannot draw over some other plugins tab.) Some operationks are global -- a plugin can request any tab to 'move to front', so that a plugin could somehow cycle tabs based on some event, say, but I don't consider bringing tabs to front a destructive operation. Obviously it is abusable, if a plugin randomly switches tabs every half second. (If abuse becomes commonplace, tight secueity coudl be implemented without changing the API .. limit the number of operations per time or something, but let us not tie developers hands together in the spec; let us see how it goes and offer a reasonable 'catch mistakes' form of security.)
- rather than build (for now) an API for a plugin to ask for permission for various activities, let us just make assumptions -- a plugin can do whatever it wants to its tab(s), and not much of anythign to anything else.
- a plugin is a standalone application, so can really do anything it wants; this is a security concern, when running any foreign application and so out of scope. But remember -- a plugin could play audio, capture keystrokes, or take over the framebuffer on its own. In general, it will take effort for plugins to be so badly behaved.. a naively written little plugin will use the API and crash itself or whatever, without really bothering the user; but a malicious plugin can go nuts!
- resources; when a plugin requests loading a graphic or audio or whatever, the searchpath mm will use is _implied_; ie: it is the plugins path, plus the system path, notwhere else. The plugin is not going to be pully artwork willy nill across the device and making a mess, unless it goes out of its way to do so. (Possibly we may relax this, or make a API function so the plugin can attempt to extend the searchpath for loading resources, but we'll see.)
- plugins will have a specific searchpath; akin to other searchpaths in libpnd, I figure we'll search something like: /etc/pandora/mmenu/plugins:/media/*/pandora/mmenu/plugins -- something like that; ie: a user could deposit plugins onto SD or NAND (and some coudl be shipped with firmware if desired). Plugin searchpath would be defined in minimenu conf file, so could be editted by clueful users (not average joes.)
- plugins will have to be enabled/disabled on a per-plugin basis; ie: user enables plugins _at all_, and then the plugin conf panel would list all known plugins (default set to 'not run'),and flip them to 'run' if they wish. (ie: similar to the tab yes/no and app yes/no conf panels already present.) Maybe this is annoying, but seems safe -- user drops new plugin onto SD, and it won't magicly just run until they enable it.
Stability:
- plugins will be standalone applications that communicate with the host (minimenu presumably); if they crash, minimenu will not be impacted.
- ex: If a plugin opens tab(s), and then crashes, minimenu can detect the crash and close those tabs implicitly or notify the user or whatever; it will not bring the system down. (Which is important, since mm coudl be someones launch desktop; if mm is made crashing, and thus making the device hard to boot, this is BAD. Recoverable, but bad!)
- minimenu reserves the right to not run plugins at all; ie: if mmenu crashes, comes up, crashes again, we may build in logic to flip skin back to default and turn off plugin mode, automatically, so that when it comes up again, it has a higher chance of not crashing.
Architecture:
-in general, many plugin systems use shared libraries for the plug; the host scans its searchpath and finds plugins and links them live, and then the plugins API is called back and forth. This makes coding easy, but means if the plugin crashes, everything crashes.
- instead, I'm going for the approach where a plugin is a separate application, communicating via pipes with the host. ie: plugin stdin is from minimenu, and plugin stdout goes to minimenu. All dialog is via this -- if minimenu has 10 plugins, it has a pile of pipes open. (or sockets, but pipes make it much more convenient .. you end up with perl, python, shell scripts, all the way to C or whatever, being able to make plugins. Very handy!) IF the pipe breaks (due to plugin crash), mm just gets a 'pipe broken' error and drops the plugin and tabs, piece of cake.
- communciation across the pipes will be a lightweight form, essentially a slimmed JSON. Every language can parse JSON, and some 'just do it' (ie: python). IT is easy and fast to parse, without being 'heavy' like XML usually is. The specification for functions is below/.
- synchronous; for this spec, the host or plugin can make one call, and shoudl not do anything until a response (or timeout) is hit. Currently there is not to be batching of instructions, though perhaps in the future we may permnit this (especially for rendering?). For now, make one API call, then wait.
- It is expected that plugins will have an intermediate wrapper do the work. ie: If you're writing a plugin in python that really just wants to be a MVP (model view) thing, with the python fetching weather data and then having minimenu do the rendering etc, then you don't really want every python plugin writng its own api. I fully expect we (and the public) will make up wrappers that we can hopefully all share. Consider:
python plugin <-> python wrapper (pyMMPlugin or something) <-> minimenu
C plugin <-> C library ( libmmplugin.so or whatever) <-> minimenu
- I debated a few different philosophies; be it plugin is doing its own rendering and handing rendered data over to minimenu for display, versus minimenu doing all the work with a heavier API, so the plugind tend to be more simplistic, etc. After some debate, I've decided to opt on the 'expected use case' -- a plugin will probably be a simple 'model' and have mm do the heavy lifting (loading assets, rendering, playback, etc.) ie: It is doubtful many plugins will be writing fiull games or heavy animations, but instead offering things like file browsers. Do correct me if my assumption seems incorrect. By moving the heavy lifting to mm, it makes heavy graphical plugins hard to make, but makes simple plugins easy to make. Example -- a weather app ro file browser is rendering once, or perhaps redrawing after key events, so is not heavy rendering, so mm doing the work is fine. For a game with 50fps or something, using proxy-rendering in mm would suck.
- In the future, we could extend the protocol; if we need better graphic APIs in the interface, or the ability for a plugin to do its own rendering and hand the ready to use artwork to mm (over shared mem say), or even have host supply cvoords to the plugin and the plugin just render to the box specified using its own rendering code, then we could build that in. We'll just have to see where it goes. Yes, I know, by mentioning it here, I pretty much require someone to make the send plugin ever to be a Pacman or Space Invaders game, and thus break the whole plugin concept day one. I'm ready, bring it.
-- for a video player say, you'd want mm telling the playback tool where to draw;p its just not possible with this spec to receive high speed wholesale screens and show them; for that, we'd extend the spec
- We're talking about an event and call model; host (minimenu) will post events to the plugin, and the plugin can make calls to the mm hosting API. There can be some give and take where the plugin negotiates features with the host, so that we can default some behaviours off and let the plugin ask for them (which is another way of saying, we can extend the protocol over time, and the plugins can ask for features to see if present or set things up, and thus know if they're being run on too old a minimenu version or whatever.) (I'd liek to avoid versioning issues, but such is life.)
- the plugin code will presumably be a layer in minimenu; possibly other applications could be a plugin host using the same code. (ie: as a debug harness for one, or perhaps just to re-use plugins. A new host could ignore rendering calls or honor them, could be neat, or useless? But keeps the mmenu code neat.) ie:
minimenu <-> mm plugin host code <-> plugin(s) so the end pipeline looks like:
minimenu <-> mm plugin host <-> pipe <-> plugin wrapper/lib <-> plugin
- one idea I've had with the layered host-code, is that a plugin interface could in theory be made for xfce or other environs .. a mini-minimenu; the idea being that perhaps a useful mm plugin is made, that someone might want it on xfce as a widget or something. But yes, plugin/accessories/panels APIs are a dime a dozen .. shoudl we be making another one, or doing this at all in mmenu? hmmrdf
- most common needs shoudl be covered by the spec, but uncommon (by expectation) APIs may need ot be done by plugin. ie: We're not going to have mm pass lid open/close to plugins, or have timer functions. A plugin is welcome to cruise through the pandora API for lid open/close, or to open its own timers. A plugin _is_ a standalone app after all, so it can do a lot of its own screwing around. But since most plugins will not (likely?) be games, we don't need ot offer high granularity timers to plugins.. they can do it on their own. But for catchign button UI, a lot of plugins will want to do that, so we make an API for it.
- note that mm will maintain tab state; if tab is fronted (and rendered by plugin) and then backed, and then fronted again, mm will ensure the tab content is still showing (and not blank.) The plugin thus could decide to render on first fronting, and not again,m if it doesn't need to.)
Protocol:
- I will leave the actual JSON protocol out of this; it is not critical for specification, but in essence, something like ..
{ func: NAME, args: { arg1: value, arg 2: value } }
with response being aninteger, a string, a hash of values, whatever, as defined below.
TBD as coded, really.
Setup:
- host mmenu, when plugins are active etc etc, will iterate the searchpaths and pull up a list of plugins. For each found, and for those the user has enabled (see Security above), mmenu will then pass a startup event to the plugin.
- host, on close, will pass an event to the plugins so they can do cleanup
Events:
- Startup event (mmenu has loaded the plugin and hooked up the in/out pipes): eStart ( plugID ) -> ACK response only, responding with plugin name. It is not defined if mmenu will be running all plugin startups concurrently or in queue .. plugins should not care, and leave it to host to decide
- Shutdown event (mmenu needs to close, only happens on controlled exit and not crash): eShutdown ( plugID ) -> ACK response only. -- this in general shouldn't do anything, since not many will be start/stopping their desktop environment. Instead, I would suggest plugins do their work during the Startup event, and then save state during config changes or during interaction, for now.
- Tab change event -- by default, plugins do not receive this, but as noted below a plugin could request it. eTabChange ( tabID from, tabID to ); if this is registered, the event order relative to tab-activated/deactivated is not defined, so pick one or the other to operate on.
- Tab activated -- when a plugins own tab(s) become the active ('on front of stack'), they get this notification. If a plugin has 2 tabs in a row, it could well see 'tab deactive'tab active' in a row, as one loses focus and the next gets it. The order of events it not defined, so play smart. eTabFocus ( tabID ) -> expects ACK
- Tab deactivated -- when a tab loses focus. eTabUnfocus ( tabID )
- Key Down -- when a 'button' is pressed; by default no notification for this, to save on bandwidth, but plugin can ask for it. Technically, plugins could just open up /dev/event and do their own IO for keys, and may have to for lid type events etc, but to keep interface clean for 'most plugins'., we're offering button interface here. Buttins include face-buttons or keyboards, but not touchscreen, USB joysticks, etc.
Security: Plugins to receive input events for their tab when focussed;
eKeyDown ( key )
eKeyUp ( key )
- Pen Down -- similar to buttons, but for touchscreen; again, by default this will not happen unless requested, and the request documents the scope .. ie: only when plugins tabs are fronted, or for other tabs or the root-window or what
ePenDown ( x, y, pressure )
ePenUp ( x, y, pressure )
Plugin samples -
- the 'weather plugin' for instance would handle Startup event and request to open a tab; then it would poll some weather server to get info, and request loading some resources in mmenu, and finally, on eventFocus-thing, render the tab.
- for a plugin that makes swooshy noises on tab change, it needn't open its own tab, and instead just request and monitor tabchange events, and play fart noises as it sees fit.
- for a plugin that shows a battery indicator or date-stamp, it could just request permission to render on the root window (outside of its own tab, and may not have a tab at all), and then on tab change (or perhaps on its own timer event) request rendering.