I’ve encountered a weird issue while working with EffectLayer Library (a visual effect library for Pebble smartwatch). In this particular watchface called Clean & Smart I used “invert” effect which inverts colors of the watchface should the user choose that option in settings. It was working fine when option changed when watchface was loaded/unload and behaved weirdly only in one particular scenario: when you would receive a notification (email, text etc.) and then dismiss it. Upon coming back from notification to watchface invert effect would only partially cover the watchface (as seen on the screenshot).

I don’t know exactly what was happening, but had a theory. EffectLayer uses Pebble’s framebuffer capabilities – which gives you direct memory access to screen. In this particular case “invert” effect would loop thru every byte of that memory inverting values, causing related pixels on screen to invert colors. Now, when you dismiss a notification it disappears with sliding animation effect. So when watchface reappears and EffectLayer begins to kick in – not entire screen is available for manipulation, hence only partial invert effect.

With this theory in mind I decided to utilize Pebble Pebble AppFocusService API. It provides events and handlers that allow you to detect various stages of your application losing and gaining focus.

First we need to subscribe to focus events, we can do this in init part of app code:

app_focus_service_subscribe_handlers((AppFocusHandlers){ .did_focus = app_focus_changed, .will_focus = app_focus_changing });

This snippet subscribes to 4 events: when application about to lose focus ( .will_focus with boolean false passed to the handler), about to gain focus ( .will_focus with boolean true passed to the handler), lost focus ( .did_focus with boolean false passed to the handler), got focus ( .did_focus with boolean true passed to the handler).

Now we need to add handlers. First we need to catch moment when notification is being dismissed and watchface is about to gain focus:

static void app_focus_changing(bool focusing) { if (focusing) { layer_set_hidden(window_layer, true); } }

What this does – if focusing event is detected – code hides root window layer. If we leave it at that – when notification is dismissed – original screen is restored, but it will remain static, it won’t reflect any events including time change. So we need to add this:

static void app_focus_changed(bool focused) { if (focused) { layer_set_hidden(window_layer, false); layer_mark_dirty(window_layer); } }

what this does – is when focus is finally restored – code restores root window layer visibility and refreshes it. And the result you can see in the screenshot – invert effect is covering entire screen.