QAndroidOffscreenView.h 15 KB
 Sergey Galin committed Jan 13, 2014 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /* Offscreen Android Views library for Qt Author: Sergey A. Galin Distrbuted under The BSD License Copyright (c) 2014, DoubleGIS, LLC. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice,  Sergey Galin committed Oct 04, 2016 16  this list of conditions and the following disclaimer.  Sergey Galin committed Jan 13, 2014 17  * Redistributions in binary form must reproduce the above copyright notice,  Sergey Galin committed Oct 04, 2016 18 19  this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.  Sergey Galin committed Jan 13, 2014 20  * Neither the name of the DoubleGIS, LLC nor the names of its contributors  Sergey Galin committed Oct 04, 2016 21 22  may be used to endorse or promote products derived from this software without specific prior written permission.  Sergey Galin committed Jan 13, 2014 23 24 25 26 27 28 29 30 31 32 33 34 35 36  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */  Sergey Galin committed Jan 10, 2014 37 #pragma once  Sergey Galin committed Feb 16, 2015 38 39 40 41 42 #include #include #include #include #include  Vyacheslav Koscheev committed Nov 12, 2018 43 #include  Рябченко Иван Константинович committed Mar 12, 2014 44 #include "QAndroidJniImagePair.h"  Sergey Galin committed Jan 10, 2014 45 #include "QOpenGLTextureHolder.h"  Sergey Galin committed Feb 18, 2014 46 #include "QApplicationActivityObserver.h"  Sergey Galin committed Feb 18, 2014 47   Sergey Galin committed Jan 10, 2014 48 /*!  Sergey Galin committed Jan 29, 2014 49  * A general wrapper for Android offscreen views.f  Sergey Galin committed Jan 10, 2014 50 51 52  * It can be used to create a QWidget / QGLWidget / QGraphicsWidget / QML component * which displays Android view. */  Sergey Galin committed Jan 10, 2014 53 54 55 56 57 class QAndroidOffscreenView: public QObject { Q_OBJECT Q_PROPERTY(QSize size READ size WRITE resize) Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor)  Sergey Galin committed Jan 23, 2014 58  Q_PROPERTY(bool visible READ visible WRITE setVisible)  Sergey Galin committed Jan 30, 2014 59  Q_PROPERTY(bool enabled READ enabled WRITE setEnabled)  Sergey Galin committed Jan 16, 2014 60 protected:  Sergey Galin committed Jan 14, 2014 61  /*!  Sergey Galin committed Jan 24, 2014 62 63 64 65  * \param classname - name of Java class of the View wrapper. * \param objectname - set for QObject and also passed to Java side, to identify the object in logs and etc. * \param defsize - initial size of the view. * \param parent - passed to QObject constructor.  Sergey Galin committed Feb 20, 2014 66 67 68  * \note The function invokes createView() through Qt::QueuedConnection so descenant constructor still * has time to register View-specific native functions and do some other initialization before * the construction of the View will start.  Sergey Galin committed Jan 14, 2014 69  */  Sergey Galin committed Feb 20, 2014 70  QAndroidOffscreenView(const QString & classname, const QString & objectname, const QSize & defsize, QObject * parent = 0);  Sergey Galin committed Jan 20, 2014 71   Sergey Galin committed Feb 20, 2014 72 73 protected slots: void createView();  Sergey Galin committed Jan 16, 2014 74 75  public:  Sergey Galin committed Jan 10, 2014 76 77  virtual ~QAndroidOffscreenView();  Sergey Galin committed Jan 21, 2014 78  static const QString & getDefaultJavaClassPath();  Sergey Galin committed Jan 30, 2014 79  static void preloadJavaClasses();  Sergey Galin committed Feb 10, 2014 80 81 82 83 84  // // Functions to check for available configuration //  Sergey Galin committed Feb 10, 2014 85  static bool openGlTextureSupportedOnJavaSide();  Sergey Galin committed Feb 10, 2014 86  static bool nonAttachingModeSupported();  Sergey Galin committed Jan 21, 2014 87   88 89 90  const QString & viewObjectName() const { return view_object_name_; } const QString & viewClassName() const { return view_class_name_; }  Sergey Galin committed Jan 10, 2014 91  /*!  Sergey Galin committed Jan 24, 2014 92 93  * Initialize OpenGL rendering surface. This function should be called within active * proper GL context as it will want to create an OpenGL texture.  Sergey Galin committed Feb 06, 2014 94 95 96 97  * When View is initialized using this function it may be rendered on screen only using * paintGL(). Call to getBitmapBuffer() may return 0. * If GL mode is not supported on Android side this function will call initializeBitmap() * instead of creating GL texture surface; paintGL() can still be used to draw the View.  Sergey Galin committed Jan 24, 2014 98  * It is safe to call this function multiple times. All subsequent calls are ignored.  Sergey Galin committed Jan 10, 2014 99 100 101  */ virtual void initializeGL();  Sergey Galin committed Feb 05, 2014 102  /*!  Sergey Galin committed Feb 06, 2014 103 104 105 106 107  * Initialize non-OpenGL (Bitmap-based) rendering surface. The View can be rendered on screen * either using paintGL() or by getting QImage via getBitmapBuffer() and drawing it using * some other method, e.g. QPainter::drawImage(). * This function should be used when Qt is working in unaccelerated UI mode. * It is safe to call this function multiple times. All subsequent calls are ignored.  Sergey Galin committed Feb 05, 2014 108 109 110  */ virtual void initializeBitmap();  Sergey Galin committed Jan 10, 2014 111 112 113  /*! * Returns true if initializeGL() has been called. */  Sergey Galin committed Feb 06, 2014 114  virtual bool isIntialized() const { return tex_.isAllocated() || bitmap_a_.isAllocated(); }  Sergey Galin committed Jan 10, 2014 115 116 117 118 119 120 121 122  /*! * Delete associated Android View and its rendering infrastructure. The texture continues * to exist and can be painted, but updates, resizes and so on will not work anymore. */ virtual void deleteAndroidView(); /*!  Sergey Galin committed Feb 06, 2014 123 124 125 126 127  * Draw GL texture or Bitmap (depending on the rendering surface on the Java side) using OpenGL. * targetRect is the output rectangle in OpenGL terms. If View image is not ready, the rectangle * is filled with fillColor. * Note: to draw the View when Qt is working in unaccelerated mode, intialize it * via initializeBitmap() and use QImage returned by getBitmapBuffer().  Sergey Galin committed Jan 10, 2014 128  */  Sergey Galin committed Jan 21, 2014 129  virtual void paintGL(int l, int b, int w, int h, bool reverse_y);  Sergey Galin committed Jan 10, 2014 130   Sergey Galin committed Jul 09, 2014 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146  /*! * Makes sure that the GL texture holder contains actual image, if possible. * This function should only be called if \ref getGLTextureHolder() is used to access * the texure directly. It is not needed to call it when using paintGL(). * Note: in Bitmap+GL mode this function may cause re-allocation of GL texture. */ bool updateGLTextureInHolder(); /*! * Access \ref QOpenGLTextureHolder for reading texture id or other properties * for direct painting without using \ref paintGL(). * \ref updateGLTextureInHolder() should be called to make sure that the texture * contains actual image. */ const QOpenGLTextureHolder & getGLTextureHolder() const { return tex_; }  Sergey Galin committed Feb 05, 2014 147 148 149  /*! * Used in Bitmap mode. Instead of paintGL(), get current bitmap buffer * using getBitmapBuffer() and paint it by yourself.  Sergey Galin committed Feb 06, 2014 150  * The image buffer is guaranteed to be unmodified until the next call to getBitmapBuffer().  Sergey Galin committed Feb 20, 2014 151  * \note This function is not guaranteed to return expected image when  Sergey Galin committed Feb 10, 2014 152 153  * initialized through initializeGL(). For example, returned image may be padded to * have power-of-two size.  Sergey Galin committed Feb 20, 2014 154 155 156  * \param out_texture_updated: the bool value is set to true/false to indicate * that the image has been actually changed since the last call to getBitmapBuffer(). * This can be used, for example, to avoid reloading the bitmap into GL texture.  Sergey Galin committed Feb 05, 2014 157  */  Sergey Galin committed Feb 07, 2014 158  const QImage * getBitmapBuffer(bool * out_texture_updated = 0);  Sergey Galin committed Feb 05, 2014 159   Sergey Galin committed Feb 06, 2014 160  //! Check if Android View already exists.  Sergey Galin committed Jan 10, 2014 161 162  bool isCreated() const;  Sergey Galin committed Feb 20, 2014 163  //! Check if Android View has already painted something.  Sergey Galin committed Jan 10, 2014 164 165 166  virtual bool hasValidImage() const; QSize size() const { return size_; }  Sergey Galin committed Feb 10, 2014 167  virtual void resize(const QSize & newsize);  Sergey Galin committed Jan 10, 2014 168 169 170  QColor fillColor() const { return fill_color_; } virtual void setFillColor(const QColor & color);  Sergey Galin committed Jan 23, 2014 171 172  /*! * Does the view thinks it's visible? When view is invisible, the texture may  Sergey Galin committed Jan 28, 2014 173  * contain an empty or outdated image. Also it stops all animations and etc.  Sergey Galin committed Jan 23, 2014 174 175 176 177 178  */ bool visible() const { return is_visible_; } /*! * Set visibility flag. It informs the view if it's visible or not.  Sergey Galin committed Jan 28, 2014 179  * By default, view is invisible.  Sergey Galin committed Jan 23, 2014 180 181 182 183 184 185 186 187 188 189 190 191 192 193  * When view is invisible, it may save resources by not doing any timer-based work, * for example. For simple widgets, it is not necessary to set them invisible * because it is enough to hide the control displaying the texture. For Wev Views * with active contents (e.g. JavaScript with timers, GIF images) it is important * to stop them when content updates are not visible to users to save CPU power * and battery. * Warning: unlike for widgets, visibility also should be explicitly set to false * when application goes to background. Cases when offscreen view should be marked * hidden are different depending on use-cases, graphical systems and QPA plugins * so proper reacting to application activation/deactivation cannot be handled * on this level. */ void setVisible(bool visible);  Sergey Galin committed Jan 30, 2014 194 195 196 197  bool enabled() const { return is_enabled_; } void setEnabled(bool enabled);  Sergey Galin committed Jan 28, 2014 198 199 200 201 202  /*! * Control attaching View to the main activity View. * It is typically called one time after constructing QAndroidOffscreenView. * Unattached views will not receive keyboard events when focused and * can't use SIP and popup menus.  Sergey Galin committed Feb 10, 2014 203  * Non-attached mode is not supported on API < 11 (\see nonAttachingModeSupported()).  Sergey Galin committed Jan 28, 2014 204 205 206  */ void setAttachingMode(bool attaching);  Sergey Galin committed Jul 20, 2016 207  void reattachView();  Sergey Galin committed Feb 18, 2014 208   Sergey Galin committed Feb 04, 2014 209  /* !  Sergey Galin committed Jan 28, 2014 210 211 212 213  * Returns true if View is currently focused. Please note that this View takes and * and releases focus in another thread so this function may e.g. return false if * called immediately after setFocused(true). */  Sergey Galin committed Feb 04, 2014 214  //bool isFocused() const;  Sergey Galin committed Jan 28, 2014 215 216 217 218 219 220 221  /*! * Set or remove focusing from the View. This should be called to keep Qt focus * in sync with Android focus. */ void setFocused(bool focused = true);  Sergey Galin committed Jan 28, 2014 222 223 224 225 226 227 228 229 230  /*! * Inform Android about real screen coordinates of the View. * This is important only if the View works with SIP (e.g.: EditText, interactive WebView) * because input method may want to display selection markers and need to know the * real position of the view. For non-interactive views calling this function is * not necessary. */ void setPosition(int left, int top);  Sergey Galin committed Feb 19, 2014 231 232 233  //! Make sure software keyboard is hidden for this control. void hideKeyboard();  Sergey Galin committed Jul 22, 2014 234  //! Make sure software keyboard is shown for this control.  Рябченко Иван Константинович committed May 28, 2014 235 236  void showKeyboard();  Sergey Galin committed Feb 19, 2014 237 238 239 240 241 242 243 244 245 246 247 248  /*! * Set/cleaer the flag to hide software keyboard when focus is lost. * By default, the mode is enabled and keyboard slides away when focus goes from the View. * If it is disabled, SIP won't hide when user changes focus to any pure Qt control * because main Qt window always accepts text input. * Disable the mode if you want user to be able to switch between various form * fields without hiding and re-opening keyboard. In this case, you have to call * hideKeyboard() from your C++/Qt code to make sure the keyboard is hidden when focus * goes to something which doesn't need it. */ void setHideKeyboardOnFocusLoss(bool hide);  Рябченко Иван Константинович committed May 28, 2014 249 250 251 252 253 254  /*! * Set/cleaer the flag to show software keyboard on focused. * By default, the mode is disabled. */ void setShowKeyboardOnFocusIn(bool show);  Sergey Galin committed Jan 10, 2014 255 256 257 258 259 260 261 262  // // Handling of user input events // static const int ANDROID_MOTIONEVENT_ACTION_DOWN = 0, ANDROID_MOTIONEVENT_ACTION_UP = 1, ANDROID_MOTIONEVENT_ACTION_MOVE = 2;  Sergey Galin committed Jan 10, 2014 263 264 265 266 267  /*! * Single-touch / mouse support. * Typically, this function is called from Qt mouse event handlers. * \param android_action can be ANDROID_MOTIONEVENT_ACTION_DOWN, ANDROID_MOTIONEVENT_ACTION_UP, * ANDROID_MOTIONEVENT_ACTION_MOVE.  Sergey Galin committed Jan 30, 2014 268 269 270 271 272 273  * \param timestamp_uptime_mills - this should be set either as a System.uptimeMillis() of the * time when the event has been initially generated or 0. Unfortunately, stock Qt currently * doesn't pass the right timestamp in mouse events. So we can pass 0 here and the Java side * will enable a workaround of getting the current timestamp. It will cause errors in determination * of the movement speed because the initial Andoid UI event queue and the Qt UI queue run at * uneven speed. So movement animations will not work good (e.g. WebView scrolling).  Sergey Galin committed Jan 10, 2014 274  */  Sergey Galin committed Jan 30, 2014 275  void mouse(int android_action, int x, int y, long long timestamp_uptime_millis = 0);  Sergey Galin committed Jan 10, 2014 276   Рябченко Иван Константинович committed Mar 21, 2014 277 278 279 280 281 282  //! Return the scrolled left position of this view. int getScrollX(); //! Return the scrolled top position of this view. int getScrollY();  283 284 285  void setScrollX(int x); void setScrollY(int y);  Рябченко Иван Константинович committed Jul 03, 2014 286 287 288 289 290 291  //! Return the width measurement information for this view as computed by the most recent call to measure(int, int). int getMeasuredWidth(); //! Return the height measurement information for this view as computed by the most recent call to measure(int, int). int getMeasuredHeight();  Sergey Galin committed Jan 30, 2014 292  //! \todo Add multi-touch support!  Sergey Galin committed Jan 10, 2014 293   Sergey Galin committed Jun 22, 2015 294 295  void setSoftInputModeResize(); void setSoftInputModeAdjustPan();  Sergey Galin committed Oct 04, 2016 296  void setSoftInputModeAdjustNothing(); // API 11+  Sergey Galin committed Jun 22, 2015 297   Sergey Galin committed Sep 29, 2016 298 299 300  //! Test function for lib developers, don't use it void testFunction();  Sergey Galin committed Feb 06, 2014 301 302 303 304 305 306 307 308 309 public slots: /*! * Free Android view and OpenGL resources. The object will be unusable after that. */ virtual void deinitialize(); //! Tell Android View to repaint. virtual void invalidate();  Sergey Galin committed Jul 31, 2014 310 311 312  //! Catch application activity status changes from the app activity observer. virtual void applicationActivityStatusChanged();  Sergey Galin committed Mar 17, 2014 313  //! Update Android View visibility from visibility of the Qt View and activity of Qt application.  Sergey Galin committed Feb 18, 2014 314 315  virtual void updateAndroidViewVisibility();  Sergey Galin committed Mar 17, 2014 316 317 318 319 320 321 322 323 324  /*! * Request currently visible rectangle of the view. * The result will be sent via visibleRectReceived() signal. * This function returns size of rectangle not covered by software keyboard * and may be used to scroll contents to have a text edit located in * the visible part of the screen. */ void requestVisibleRect();  Sergey Galin committed Jun 22, 2015 325   Sergey Galin committed Jan 10, 2014 326 327 328 329 330 331 signals: /*! * Emitted when texture has finished updating on Java side and the new image * can be displayed in our Qt app UI (via paintGL()). */ void updated();  Sergey Galin committed Mar 17, 2014 332 333 334 335  /*! * Emitted when view has been actually created. */  Sergey Galin committed Jan 24, 2014 336  void viewCreated();  Sergey Galin committed Jan 10, 2014 337   Sergey Galin committed Mar 17, 2014 338 339 340 341 342  /*! * Emitted when visible screen rect requested via requestVisibleRect() is receieved. */ void visibleRectReceived(int width, int height);  Sergey Galin committed Jan 10, 2014 343 344 private slots: void javaUpdate();  Sergey Galin committed Jan 24, 2014 345  void javaViewCreated();  Sergey Galin committed Mar 17, 2014 346  void javaVisibleRectReceived(int left, int top, int right, int bottom);  Sergey Galin committed Jan 10, 2014 347   Sergey Galin committed Feb 07, 2014 348 349 350 private: const QImage * getPreviousBitmapBuffer(bool convert_from_android_format);  Sergey Galin committed Jan 10, 2014 351 protected:  Sergey Galin committed Feb 07, 2014 352  const QImage * getBitmapBuffer(bool * out_texture_updated, bool convert_from_android_format);  Sergey Galin committed Feb 05, 2014 353  bool updateGlTexture();  Sergey Galin committed Feb 06, 2014 354  bool updateBitmapToGlTexture();  Sergey Galin committed Jan 29, 2014 355  QJniObject * offscreenView() { return offscreen_view_.data(); }  Sergey Galin committed Feb 14, 2014 356  const QJniObject * offscreenView() const { return offscreen_view_.data(); }  Sergey Galin committed Jan 29, 2014 357  QJniObject * getView();  Sergey Galin committed Jan 10, 2014 358   Sergey Galin committed Jan 13, 2014 359 private:  Sergey Galin committed Jan 10, 2014 360 361  QString view_class_name_; QString view_object_name_;  Sergey Galin committed Feb 05, 2014 362   363  //! Keeps OpenGL texture when painting goes on in GL.  Sergey Galin committed Jan 10, 2014 364  QOpenGLTextureHolder tex_;  Sergey Galin committed Feb 05, 2014 365   366  //! Intermediate buffer used in Bitmap mode to convert Android's BGR to RGB.  Sergey Galin committed Feb 05, 2014 367  QImage android_to_qt_buffer_;  Sergey Galin committed Feb 07, 2014 368  int last_qt_buffer_;  369 370  //! Double buffer for Bitmap mode.  Sergey Galin committed Feb 05, 2014 371  QAndroidJniImagePair bitmap_a_, bitmap_b_;  Sergey Galin committed Feb 05, 2014 372   373 374 375  //! Used to lock bitmap_a_/bitmap_b_ access. QMutex bitmaps_mutex_;  Sergey Galin committed Jan 29, 2014 376  QScopedPointer offscreen_view_;  Sergey Galin committed Jan 10, 2014 377 378  QSize size_; QColor fill_color_;  379 380  volatile bool need_update_texture_; volatile bool view_painted_;  Sergey Galin committed Jan 10, 2014 381  bool texture_received_;  Sergey Galin committed Jan 16, 2014 382  bool view_creation_requested_;  Sergey Galin committed Jan 23, 2014 383  bool is_visible_;  Sergey Galin committed Jan 30, 2014 384  bool is_enabled_;  385  volatile mutable bool view_created_; //!< Cache for isCreated()  Sergey Galin committed Jan 30, 2014 386  int last_texture_width_, last_texture_height_;  Sergey Galin committed Jan 10, 2014 387 388 389 private: Q_DISABLE_COPY(QAndroidOffscreenView) friend void JNICALL Java_OffscreenView_nativeUpdate(JNIEnv * env, jobject jo, jlong param);  390  friend void JNICALL Java_OffscreenView_nativeViewCreated(JNIEnv *, jobject, jlong param);  Sergey Galin committed Mar 17, 2014 391  friend void JNICALL Java_OffscreenView_onVisibleRect(JNIEnv *, jobject, jlong param, int left, int top, int right, int bottom);  Sergey Galin committed Jan 10, 2014 392 393 };  Sergey Galin committed Feb 14, 2014 394 395 396 int QColorToAndroidColor(const QColor & color);