/* * Copyright (C) 2021 The Android Open Source Project * * 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 #include #include #include #include #include namespace android::inputdispatcher { // Keeps track of the focused window per display. The class listens to updates from input dispatcher // and provides focus changes. // // Focus Policy // Window focusabilty - A window token can be focused if there is at least one window handle that // is visible with the same token and all window handles with the same token are focusable. // See FocusResolver::isTokenFocusable // // Focus request - Request will be granted if the window is focusable. If it's not // focusable, then the request is persisted and granted when it becomes focusable. The currently // focused window will lose focus and any pending keys will be added to a queue so it can be sent // to the window when it gets focus. // // Condition focus request - Request with a focus token specified. Request will be granted if the // window is focusable and the focus token is the currently focused. Otherwise, the request is // dropped. Conditional focus requests are not persisted. The window will lose focus and go back // to the focus token if it becomes not focusable. // // Window handle updates - Focus is lost when the currently focused window becomes not focusable. // If the previous focus request is focusable, then we will try to grant that window focus. class FocusResolver { public: // Returns the focused window token on the specified display. sp getFocusedWindowToken(int32_t displayId) const; struct FocusChanges { sp oldFocus; sp newFocus; int32_t displayId; std::string reason; }; std::optional setInputWindows( int32_t displayId, const std::vector>& windows); std::optional setFocusedWindow( const FocusRequest& request, const std::vector>& windows); // Display has been removed from the system, clean up old references. void displayRemoved(int32_t displayId); // exposed for debugging bool hasFocusedWindowTokens() const { return !mFocusedWindowTokenByDisplay.empty(); } std::string dumpFocusedWindows() const; std::string dump() const; private: enum class Focusability { OK, NO_WINDOW, NOT_FOCUSABLE, NOT_VISIBLE, }; // Checks if the window token can be focused on a display. The token can be focused if there is // at least one window handle that is visible with the same token and all window handles with // the same token are focusable. // // In the case of mirroring, two windows may share the same window token and their visibility // might be different. Example, the mirrored window can cover the window its mirroring. However, // we expect the focusability of the windows to match since its hard to reason why one window // can receive focus events and the other cannot when both are backed by the same input channel. // static Focusability isTokenFocusable(const sp& token, const std::vector>& windows); // Focus tracking for keys, trackball, etc. A window token can be associated with one or // more InputWindowHandles. If a window is mirrored, the window and its mirror will share // the same token. Focus is tracked by the token per display and the events are dispatched // to the channel associated by this token. typedef std::pair> NamedToken; std::unordered_map mFocusedWindowTokenByDisplay; // This map will store the focus request per display. When the input window handles are updated, // the current request will be checked to see if it can be processed at that time. std::unordered_map mFocusRequestByDisplay; // Last reason for not granting a focus request. This is used to add more debug information // in the event logs. std::unordered_map mLastFocusResultByDisplay; std::optional updateFocusedWindow( int32_t displayId, const std::string& reason, const sp& token, const std::string& tokenName = ""); std::optional getFocusRequest(int32_t displayId); }; } // namespace android::inputdispatcher