mirror of
https://github.com/google/pebble
synced 2026-10-16 16:24:12 +02:00
Import of the watch repository from Pebble
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "applib/graphics/gtypes.h"
|
||||
#include "applib/ui/animation.h"
|
||||
|
||||
//! @addtogroup UI
|
||||
//! @{
|
||||
//! @addtogroup UnobstructedArea
|
||||
//!
|
||||
//! \brief Events about when the app's unobstructed area changes for visually adapting
|
||||
//!
|
||||
//! Unobstructed Area enables a watchface to adapt to overlays partially obstructing it. Timeline
|
||||
//! Peek is the only overlay, and it partially obstructs the bottom of watchfaces, displaying the
|
||||
//! immediately upcoming or newly began event. Unobstructed Area is for use only with watchfaces.
|
||||
//! There will be no Unobstructed Area events emitted for apps that are not watchfaces. Timeline
|
||||
//! Peek is also limited to rectangular platforms, thus using Unobstructed Area on Chalk will also
|
||||
//! result in no events.
|
||||
//!
|
||||
//! Watchfaces are encouraged to respect Unobstructed Area in order to dynamically resize within
|
||||
//! the remaining screen area that isn't obstructed by an overlay. Unobstructed Area provides
|
||||
//! handlers for when the screen area will begin and end changing as well as progress for every
|
||||
//! frame of the animation, allowing one to animate the watchface to resize while the overlay
|
||||
//! animates into or out of the screen. Additionally, at any point, a watchface can query the
|
||||
//! Unobstructed Area using \ref layer_get_unobstructed_bounds even if there was not event or if it
|
||||
//! didn't subscribe to them.
|
||||
//!
|
||||
//! The simplest usage of Unobstructed Area is to change rendering of your watchface to render
|
||||
//! within the unobstructed bounds obtained by \ref layer_get_unobstructed_bounds. This is
|
||||
//! accomplished by modifying your layer update procedure that you setup a layer with using
|
||||
//! \ref layer_set_update_proc to use \ref layer_get_unobstructed_bounds instead of
|
||||
//! \ref layer_get_bounds or \ref layer_get_frame and adjusting all the rendering logic within it
|
||||
//! to handle resizing bounds. The app will redraw automatically whenever the Unobstructed
|
||||
//! Area changes, even if you did not subscribe to the events.
|
||||
//!
|
||||
//! Subscribing to `will_change`, `change`, and `did_change` events with
|
||||
//! \ref app_unobstructed_area_service_subscribe will allow you to obtain the final unobstructed
|
||||
//! area as soon as the animation begins and the current animation progress for each frame as they
|
||||
//! occur should you need that information to resize your watchface.
|
||||
//!
|
||||
//! When designing your watchface resizing logic or animation, take into consideration the way
|
||||
//! Timeline Peek animates. Timeline Peek appears from the bottom with an animation that moves
|
||||
//! slightly at first and snaps across with a bounce back. Because there is a bounce back in the
|
||||
//! animation, there will be momentary frames where the unobstructed area is slightly smaller than
|
||||
//! when Timeline Peek is visible but not animating.
|
||||
//!
|
||||
//! If you intend to hide or show layers on the screen depending on the unobstructed area, there
|
||||
//! are two ways to do this. For anything inside a layer update procedure the simple solution would
|
||||
//! be sufficient. That is, in your update procedure, you can to determine whether something is to
|
||||
//! be rendered or not based on the remaining height available to you determined from
|
||||
//! \ref layer_get_unobstructed_bounds.
|
||||
//!
|
||||
//! The other method for deciding whether to show or hide layers is to subscribe to events using
|
||||
//! \ref app_unobstructed_area_service_subscribe. Note that hiding or showing elements in your
|
||||
//! `will_change` can be too early due to the nature of the Timeline Peek animation where it moves
|
||||
//! slowly in the first few frames. After judging the animation visually, you may instead show or
|
||||
//! hide your layers based on both the final unobstructed area obtained from `will_change` in
|
||||
//! combination with the progress obtained from `change`, or check the current height available to
|
||||
//! you by calling \ref layer_get_unobstructed_bounds in your `change` handler to update your
|
||||
//! state.
|
||||
//!
|
||||
//! For more advance usages such as functionally defined animations whose animation frames are a
|
||||
//! function of animation progress, you will want to subscribe to `will_change`, `change`, and
|
||||
//! optionally `did_change` events if you need to clean up resources or layers created in your
|
||||
//! `will_change` handler. For example, in your `will_change` handler, you may use
|
||||
//! \ref layer_get_unobstructed_bounds to get the current unobstructed area, and combine it with
|
||||
//! the final unobstructed area passed into `will_change` to set up a \ref PropertyAnimation. A
|
||||
//! separate example would be to save the animation progress passed to your `change` handler for
|
||||
//! use in your own custom easing curve in your layer update procedure.
|
||||
|
||||
//! Handler that will be called just before the unobstructed area will begin changing
|
||||
//! @param final_unobstructed_screen_area The final unobstructed screen area after
|
||||
//! the unobstructed area has finished changing.
|
||||
//! @param context A user-provided context.
|
||||
typedef void (*UnobstructedAreaWillChangeHandler)(GRect final_unobstructed_screen_area,
|
||||
void *context);
|
||||
|
||||
//! Handler that will be called every time the unobstructed area changes
|
||||
//! @param progress The progress of the animation changing the unobstructed area.
|
||||
//! @param context A user-provided context.
|
||||
typedef void (*UnobstructedAreaChangeHandler)(AnimationProgress progress, void *context);
|
||||
|
||||
//! Handler that will be called after the unobstructed area has finished changing
|
||||
//! @param context A user-provided context.
|
||||
typedef void (*UnobstructedAreaDidChangeHandler)(void *context);
|
||||
|
||||
typedef struct UnobstructedAreaHandlers {
|
||||
//! Handler that will be called just before the unobstructed area will begin changing.
|
||||
UnobstructedAreaWillChangeHandler will_change;
|
||||
//! Handler that will be called every time the unobstructed area changes.
|
||||
UnobstructedAreaChangeHandler change;
|
||||
//! Handler that will be called after the unobstructed area has finished changing.
|
||||
UnobstructedAreaDidChangeHandler did_change;
|
||||
} UnobstructedAreaHandlers;
|
||||
|
||||
//! @internal
|
||||
//! Puts a will change event notifying of the start of an obstruction animation.
|
||||
//! @param current_y The beginning obstruction y which is saved in the UnobstructedAreaState
|
||||
//! @param final_y The final obstruction y which is converted to the unobstructed area and passed
|
||||
//! to the `will_change` handler
|
||||
void unobstructed_area_service_will_change(int16_t current_y, int16_t final_y);
|
||||
|
||||
//! @internal
|
||||
//! Puts a change event notifying a frame change of an obstruction animation.
|
||||
//! If the app was newly started, this will also put a will change event.
|
||||
//! @param current_y The current obstruction y to be saved in UnobstructedAreaState for this frame
|
||||
//! @param final_y The final obstruction y which is converted to the unobstructed area and may be
|
||||
//! passed to the `will_change` handler if the app did not yet receive a will change event due to
|
||||
//! being started mid-animation.
|
||||
void unobstructed_area_service_change(int16_t current_y, int16_t final_y,
|
||||
AnimationProgress progress);
|
||||
//! @internal
|
||||
//! Puts a did change event notifying that the obstruction animation is complete.
|
||||
//! @param final_y The final obstruction y which is converted to the unobstructed area and may be
|
||||
//! passed to the `will_change` handler if the app did not yet receive a will change event due to
|
||||
//! being started mid-animation.
|
||||
void unobstructed_area_service_did_change(int16_t final_y);
|
||||
|
||||
//! Subscribe to be notified when the app's unobstructed area changes. When an unobstructed area
|
||||
//! begins changing, the `will_change` handler will be called, and every `will_change` call is
|
||||
//! always paired with a `did_change` call that occurs when it is done changing given that
|
||||
//! the `will_change` and `did_change` handlers are set. When subscribing while the unobstructed
|
||||
//! area is changing, the `will_change` handler will be called after subscription in the next event
|
||||
//! loop.
|
||||
//! @param handlers The handlers that should be called when the unobstructed area changes.
|
||||
//! @param context A user-provided context that will be passed to the callback handlers.
|
||||
//! @see layer_get_unobstructed_bounds
|
||||
void app_unobstructed_area_service_subscribe(UnobstructedAreaHandlers handlers, void *context);
|
||||
|
||||
//! Unsubscribe from notifications about changes to the app's unobstructed area.
|
||||
void app_unobstructed_area_service_unsubscribe(void);
|
||||
|
||||
//! @} // end addtogroup UnobstructedArea
|
||||
//! @} // end addtogroup UI
|
||||
Reference in New Issue
Block a user