1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Copyright 2016 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot* found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot*/
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef Window_DEFINED
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define Window_DEFINED
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "DisplayParams.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRect.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTouchGesture.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h"
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrContext;
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkCanvas;
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass SkSurface;
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotnamespace sk_app {
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass WindowContext;
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass Window {
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic:
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static Window* CreateNativeWindow(void* platformData);
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual ~Window() { this->detach(); }
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void setTitle(const char*) = 0;
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void show() = 0;
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // JSON-formatted UI state for Android. Do nothing by default
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void setUIState(const char*) {}
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Shedules an invalidation event for window if one is not currently pending.
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Make sure that either onPaint or markInvalReceived is called when the client window consumes
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // the the inval event. They unset fIsContentInvalided which allow future onInval.
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void inval();
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual bool scaleContentToFit() const { return false; }
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum BackendType {
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kNativeGL_BackendType,
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if SK_ANGLE && defined(SK_BUILD_FOR_WIN)
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kANGLE_BackendType,
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_VULKAN
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kVulkan_BackendType,
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kRaster_BackendType,
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLast_BackendType = kRaster_BackendType
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum {
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kBackendTypeCount = kLast_BackendType + 1
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual bool attach(BackendType) = 0;
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void detach();
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // input handling
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum class Key {
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kNONE,    //corresponds to android's UNKNOWN
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLeftSoftKey,
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kRightSoftKey,
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kHome,    //!< the home key - added to match android
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kBack,    //!< (CLR)
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kSend,    //!< the green (talk) key
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kEnd,     //!< the red key
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k0,
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k1,
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k2,
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k3,
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k4,
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k5,
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k6,
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k7,
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k8,
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        k9,
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kStar,    //!< the * key
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kHash,    //!< the # key
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kUp,
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kDown,
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLeft,
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kRight,
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // Keys needed by ImGui
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kTab,
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPageUp,
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPageDown,
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kDelete,
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kEscape,
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kShift,
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCtrl,
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kOption, // AKA Alt
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kA,
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kC,
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kV,
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kX,
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kY,
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kZ,
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kOK,      //!< the center key
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kVolUp,   //!< volume up    - match android
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kVolDown, //!< volume down  - same
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kPower,   //!< power button - same
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCamera,  //!< camera       - same
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kLast = kCamera
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    static const int kKeyCount = static_cast<int>(Key::kLast) + 1;
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum ModifierKeys {
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kShift_ModifierKey = 1 << 0,
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kControl_ModifierKey = 1 << 1,
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kOption_ModifierKey = 1 << 2,   // same as ALT
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kCommand_ModifierKey = 1 << 3,
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kFirstPress_ModifierKey = 1 << 4,
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    enum InputState {
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kDown_InputState,
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kUp_InputState,
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        kMove_InputState   // only valid for mouse
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    class Layer {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    public:
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        Layer() : fActive(true) {}
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual ~Layer() = default;
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool getActive() { return fActive; }
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        void setActive(bool active) { fActive = active; }
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        // return value of 'true' means 'I have handled this event'
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onBackendCreated() {}
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onAttach(Window* window) {}
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual bool onChar(SkUnichar c, uint32_t modifiers) { return false; }
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual bool onKey(Key key, InputState state, uint32_t modifiers) { return false; }
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual bool onMouse(int x, int y, InputState state, uint32_t modifiers) { return false; }
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual bool onMouseWheel(float delta, uint32_t modifiers) { return false; }
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual bool onTouch(intptr_t owner, InputState state, float x, float y) { return false; }
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onUIStateChanged(const SkString& stateName, const SkString& stateValue) {}
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onPrePaint() {}
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        virtual void onPaint(SkCanvas*) {}
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    private:
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        friend class Window;
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        bool fActive;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    };
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void pushLayer(Layer* layer) {
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        layer->onAttach(this);
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        fLayers.push(layer);
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onBackendCreated();
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onChar(SkUnichar c, uint32_t modifiers);
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onKey(Key key, InputState state, uint32_t modifiers);
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onMouse(int x, int y, InputState state, uint32_t modifiers);
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onMouseWheel(float delta, uint32_t modifiers);
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool onTouch(intptr_t owner, InputState state, float x, float y);  // multi-owner = multi-touch
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onUIStateChanged(const SkString& stateName, const SkString& stateValue);
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onPaint();
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void onResize(int width, int height);
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int width();
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int height();
175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual const DisplayParams& getRequestedDisplayParams() { return fRequestedDisplayParams; }
177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void setRequestedDisplayParams(const DisplayParams&, bool allowReattach = true);
178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Actual parameters in effect, obtained from the native window.
180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int sampleCount() const;
181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    int stencilBits() const;
182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Returns null if there is not a GPU backend or if the backend is not yet created.
184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    const GrContext* getGrContext() const;
185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected:
187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    Window();
188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkTDArray<Layer*>      fLayers;
190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    DisplayParams          fRequestedDisplayParams;
191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    WindowContext* fWindowContext = nullptr;
193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    virtual void onInval() = 0;
195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // Uncheck fIsContentInvalided to allow future inval/onInval.
197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void markInvalProcessed();
198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool fIsContentInvalidated = false;  // use this to avoid duplicate invalidate events
200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    void visitLayers(std::function<void(Layer*)> visitor);
202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    bool signalLayers(std::function<bool(Layer*)> visitor);
203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot};
204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}   // namespace sk_app
206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif
207