notification window
authorArkadiusz Szulakiewicz <a.szulakiewi@partner.samsung.com>
Tue, 7 Jun 2016 10:09:10 +0000 (12:09 +0200)
committerTomasz Iwanek <t.iwanek@samsung.com>
Fri, 10 Jun 2016 07:33:32 +0000 (09:33 +0200)
Introduces possiblity of creating notification level window type
for ui web application if application matches always_on_top category.

12 files changed:
packaging/crosswalk-tizen.spec
runtime/browser/native_window.cc
runtime/browser/native_window.h
runtime/browser/notification_window.cc [new file with mode: 0644]
runtime/browser/notification_window.h [new file with mode: 0644]
runtime/browser/preload_manager.cc
runtime/browser/preload_manager.h
runtime/browser/ui_runtime.cc
runtime/browser/ui_runtime.h
runtime/browser/web_application.cc
runtime/browser/web_application.h
runtime/runtime.gyp

index a961b37..cb4037e 100755 (executable)
@@ -27,6 +27,7 @@ BuildRequires: pkgconfig(capi-appfw-application)
 BuildRequires: pkgconfig(capi-appfw-app-manager)
 BuildRequires: pkgconfig(capi-appfw-package-manager)
 BuildRequires: pkgconfig(capi-system-system-settings)
+BuildRequires: pkgconfig(capi-ui-efl-util)
 BuildRequires: pkgconfig(chromium-efl)
 BuildRequires: pkgconfig(deviced)
 BuildRequires: pkgconfig(dlog)
index 97fb15b..c201a6a 100755 (executable)
@@ -30,8 +30,9 @@ namespace {
 
 
 NativeWindow::NativeWindow()
-    : initialized_(false),
-      window_(NULL),
+    : window_(NULL),
+      window_type_(Type::NORMAL),
+      initialized_(false),
       layout_(NULL),
       content_(NULL),
       rotation_(0),
@@ -39,6 +40,8 @@ NativeWindow::NativeWindow()
 }
 
 NativeWindow::~NativeWindow() {
+  if (window_)
+    evas_object_del(window_);
 }
 
 void NativeWindow::Initialize() {
index 8833b02..a2f396d 100755 (executable)
@@ -34,6 +34,10 @@ class NativeWindow {
     NATURAL = 4,
     ANY = 5
   };
+  enum class Type {
+    NORMAL = 0,
+    NOTIFICATION = 1
+  };
   typedef std::function<void(int)> RotationHandler;
   NativeWindow();
   virtual ~NativeWindow();
@@ -54,9 +58,12 @@ class NativeWindow {
   void InActive();
   void FullScreen(bool enable);
   ScreenOrientation natural_orientation() const { return natural_orientation_;}
+  Type type() const { return window_type_;}
 
  protected:
   virtual Evas_Object* CreateWindowInternal() = 0;
+  Evas_Object* window_;
+  Type window_type_;
 
  private:
   static void DidDeleteRequested(void* data, Evas_Object* obj,
@@ -65,7 +72,6 @@ class NativeWindow {
   void DidRotation(int degree);
 
   bool initialized_;
-  Evas_Object* window_;
   Evas_Object* layout_;
   Evas_Object* content_;
   int rotation_;
diff --git a/runtime/browser/notification_window.cc b/runtime/browser/notification_window.cc
new file mode 100644 (file)
index 0000000..ee70e53
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+#include <runtime/browser/notification_window.h>
+
+#include <Ecore_Wayland.h>
+#include <efl_util.h>
+
+namespace runtime {
+
+
+NotificationWindow::NotificationWindow() {
+  window_type_ = NativeWindow::Type::NOTIFICATION;
+}
+
+Evas_Object* NotificationWindow::CreateWindowInternal() {
+  elm_config_accel_preference_set("opengl");
+  Evas_Object* window = elm_win_add(NULL, "xwalk-window", ELM_WIN_NOTIFICATION);
+  efl_util_set_notification_window_level(window,
+                                         EFL_UTIL_NOTIFICATION_LEVEL_3);
+  SetAlwaysOnTop(window, true);
+  return window;
+}
+
+void NotificationWindow::SetAlwaysOnTop(Evas_Object* window, bool enable) {
+  if (enable)
+    elm_win_aux_hint_add(window, "wm.policy.win.above.lock", "1");
+  else
+    elm_win_aux_hint_add(window, "wm.policy.win.above.lock", "0");
+}
+
+
+}  // namespace runtime
diff --git a/runtime/browser/notification_window.h b/runtime/browser/notification_window.h
new file mode 100644 (file)
index 0000000..299b1b4
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef XWALK_RUNTIME_BROWSER_NOTIFICATION_WINDOW_H_
+#define XWALK_RUNTIME_BROWSER_NOTIFICATION_WINDOW_H_
+
+#include <runtime/browser/native_window.h>
+
+namespace runtime {
+
+class NotificationWindow : public NativeWindow {
+ public:
+  NotificationWindow();
+  virtual ~NotificationWindow() = default;
+
+  Evas_Object* CreateWindowInternal() override;
+
+ private:
+  static void SetAlwaysOnTop(Evas_Object* window, bool enable);
+};
+
+}  // namespace runtime
+
+#endif  // XWALK_RUNTIME_BROWSER_NOTIFICATION_WINDOW_H_
index 9363773..810c232 100755 (executable)
@@ -55,4 +55,8 @@ NativeWindow* PreloadManager::GetCachedNativeWindow() {
   return cached_window_ ? cached_window_.release() : nullptr;
 }
 
+void PreloadManager::ReleaseCachedNativeWindow() {
+  cached_window_.reset(nullptr);
+}
+
 }  //  namespace runtime
index a63b7ec..b20d5f2 100755 (executable)
@@ -29,6 +29,8 @@ class PreloadManager {
   static PreloadManager* GetInstance();
   void CreateCacheComponet();
   NativeWindow* GetCachedNativeWindow();
+  void ReleaseCachedNativeWindow();
+
  private:
   PreloadManager();
   std::unique_ptr<NativeWindow> cached_window_;
index f2f46c1..6784937 100755 (executable)
  *    limitations under the License.
  */
 
+#include "runtime/browser/runtime.h"
+
 #include <ewk_chromium.h>
+#include <Ecore.h>
+
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "common/application_data.h"
 #include "common/app_control.h"
 #include "common/profiler.h"
 #include "runtime/common/constants.h"
 #include "runtime/browser/native_app_window.h"
+#include "runtime/browser/notification_window.h"
 #include "runtime/browser/preload_manager.h"
-#include "runtime/browser/runtime.h"
 #include "runtime/browser/ui_runtime.h"
 
 namespace runtime {
 
 namespace {
 
-static NativeWindow* CreateNativeWindow() {
+const char kCategoryAlwaysOnTop[] = "http://tizen.org/category/always_on_top";
+
+static NativeWindow* CreateNativeWindow(NativeWindow::Type windowType) {
   SCOPE_PROFILE();
-  // TODO(wy80.choi) : consider other type of native window.
-  auto cached = PreloadManager::GetInstance()->GetCachedNativeWindow();
-  NativeWindow* window = cached != nullptr ? cached : new NativeAppWindow();
+
+  NativeWindow* window;
+
+  switch (windowType) {
+    case NativeWindow::Type::NORMAL: {
+      auto cached = PreloadManager::GetInstance()->GetCachedNativeWindow();
+      window = cached != nullptr ? cached : new NativeAppWindow();
+    }
+    break;
+    case NativeWindow::Type::NOTIFICATION: {
+      PreloadManager::GetInstance()->ReleaseCachedNativeWindow();
+      NotificationWindow* win = new NotificationWindow();
+      window = win;
+    }
+    break;
+  }
+
   window->Initialize();
   return window;
 }
 
+bool HasAlwaysTopCategory(
+    const std::vector<std::string>& category_info_list) {
+  for (const auto& category : category_info_list) {
+      if (strcmp(category.c_str(), kCategoryAlwaysOnTop) == 0)
+        return true;
+    }
+    return false;
+}
+
+bool AlwaysTopRequested(common::AppControl* appcontrol) {
+  return appcontrol->data("always_on_top") == "true";
+}
+
 }  // namespace
 
 UiRuntime::UiRuntime(common::ApplicationData* app_data)
-    : application_(NULL),
-      native_window_(NULL),
+    : native_window_(nullptr),
+      application_(nullptr),
+      context_(
+        ewk_context_new_with_injected_bundle_path(INJECTED_BUNDLE_PATH)),
       app_data_(app_data) {
 }
 
 UiRuntime::~UiRuntime() {
-  if (application_) {
-    delete application_;
-  }
-  if (native_window_) {
-    delete native_window_;
-  }
+  application_.reset();
+  native_window_.reset();
+  if (context_)
+      ewk_context_delete(context_);
+}
+
+void UiRuntime::ResetWebApplication(NativeWindow::Type windowType) {
+  STEP_PROFILE_START("Runtime ResetWebApplication");
+
+  LOGGER(DEBUG) << "runtime.cc ResetWebApplication() started";
+
+  application_.reset();
+  native_window_.reset();
+
+  native_window_.reset(CreateNativeWindow(windowType));
+  LOGGER(DEBUG) << "runtime.cc Created native window";
+  application_.reset(new WebApplication(native_window_.get(),
+                                        app_data_,
+                                        context_));
+  LOGGER(DEBUG) << "runtime.cc created web application";
+  application_->set_terminator([](){ ui_app_exit(); });
+
+  LOGGER(DEBUG) << "runtime.cc ResetWebApplication() finished";
+
+  STEP_PROFILE_END("Runtime ResetWebApplication");
 }
 
 bool UiRuntime::OnCreate() {
@@ -74,12 +129,7 @@ bool UiRuntime::OnCreate() {
   appdb->Set(kAppDBRuntimeSection, kAppDBRuntimeAppID, appid);
   appdb->Remove(kAppDBRuntimeSection, kAppDBRuntimeBundle);
 
-  // Init WebApplication
-  native_window_ = CreateNativeWindow();
-  STEP_PROFILE_START("WebApplication Create");
-  application_ = new WebApplication(native_window_, app_data_);
-  STEP_PROFILE_END("WebApplication Create");
-  application_->set_terminator([](){ ui_app_exit(); });
+  ResetWebApplication(NativeWindow::Type::NORMAL);
 
   setlocale(LC_ALL, "");
   bindtextdomain(kTextDomainRuntime, kTextLocalePath);
@@ -109,6 +159,30 @@ void UiRuntime::OnAppControl(app_control_h app_control) {
   common::AppDB* appdb = common::AppDB::GetInstance();
   appdb->Set(kAppDBRuntimeSection, kAppDBRuntimeBundle,
              appcontrol->encoded_bundle());
+
+  bool reset_webapp = false;
+  NativeWindow::Type type;
+  if (AlwaysTopRequested(appcontrol.get()) &&
+      HasAlwaysTopCategory(app_data_->category_info_list()->categories)) {
+    if (native_window_->type() != NativeWindow::Type::NOTIFICATION) {
+      type = NativeWindow::Type::NOTIFICATION;
+      reset_webapp = true;
+    }
+  } else {
+    if (native_window_->type() != NativeWindow::Type::NORMAL) {
+      type = NativeWindow::Type::NORMAL;
+      reset_webapp = true;
+    }
+  }
+
+  if (reset_webapp) {
+    ResetWebApplication(type);
+    // TODO(t.iwanek): there is still problem with rendering content if
+    // window is replaced ewk won't render page.
+    // This looks the same as for workaround removed in: PR #80
+    native_window_->Show();
+  }
+
   if (application_->launched()) {
     application_->AppControl(std::move(appcontrol));
   } else {
index 83ed31e..7aff1f7 100644 (file)
@@ -25,6 +25,8 @@
 #include "runtime/browser/native_window.h"
 #include "runtime/browser/web_application.h"
 
+class Ewk_Context;
+
 namespace runtime {
 
 class UiRuntime : public Runtime {
@@ -44,8 +46,11 @@ class UiRuntime : public Runtime {
   virtual void OnLowMemory();
 
  private:
-  WebApplication* application_;
-  NativeWindow* native_window_;
+  void ResetWebApplication(NativeWindow::Type windowType);
+
+  std::unique_ptr<NativeWindow> native_window_;
+  std::unique_ptr<WebApplication> application_;
+  Ewk_Context* context_;
   common::ApplicationData* app_data_;
 };
 
index af4580b..ca56f97 100644 (file)
@@ -215,42 +215,61 @@ static bool ProcessWellKnownScheme(const std::string& url) {
 }  // namespace
 
 WebApplication::WebApplication(
-    NativeWindow* window, common::ApplicationData* app_data)
+    NativeWindow* window,
+    common::ApplicationData* app_data)
     : launched_(false),
       debug_mode_(false),
       verbose_mode_(false),
       ewk_context_(
           ewk_context_new_with_injected_bundle_path(INJECTED_BUNDLE_PATH)),
+      has_ownership_of_ewk_context_(true),
       window_(window),
       appid_(app_data->app_id()),
       app_data_(app_data),
       locale_manager_(new common::LocaleManager()),
       terminator_(NULL) {
-  std::unique_ptr<char, decltype(std::free)*> path{app_get_data_path(),
-                                                   std::free};
-  app_data_path_ = path.get();
-  LOGGER(DEBUG) << "path is " << path.get();
-  splash_screen_.reset(new SplashScreen(
-      window_, app_data_->splash_screen_info(), app_data_->application_path()));
-  resource_manager_.reset(
-      new common::ResourceManager(app_data_, locale_manager_.get()));
-  resource_manager_->set_base_resource_path(app_data_->application_path());
   Initialize();
 }
 
-WebApplication::~WebApplication() {
-  if (ewk_context_) ewk_context_delete(ewk_context_);
+WebApplication::WebApplication(
+    NativeWindow* window,
+    common::ApplicationData* app_data,
+    Ewk_Context* context)
+    : launched_(false),
+      debug_mode_(false),
+      verbose_mode_(false),
+      ewk_context_(context),
+      has_ownership_of_ewk_context_(false),
+      window_(window),
+      appid_(app_data->app_id()),
+      app_data_(app_data),
+      locale_manager_(new common::LocaleManager()),
+      terminator_(NULL) {
+  Initialize();
+}
 
+WebApplication::~WebApplication() {
   window_->SetContent(NULL);
   auto it = view_stack_.begin();
   for (; it != view_stack_.end(); ++it) {
     delete *it;
   }
   view_stack_.clear();
+  if (ewk_context_ && has_ownership_of_ewk_context_)
+    ewk_context_delete(ewk_context_);
 }
 
 bool WebApplication::Initialize() {
   SCOPE_PROFILE();
+  std::unique_ptr<char, decltype(std::free)*> path{app_get_data_path(),
+                                                   std::free};
+  app_data_path_ = path.get();
+  LOGGER(DEBUG) << "path is " << path.get();
+  splash_screen_.reset(new SplashScreen(
+      window_, app_data_->splash_screen_info(), app_data_->application_path()));
+  resource_manager_.reset(
+      new common::ResourceManager(app_data_, locale_manager_.get()));
+  resource_manager_->set_base_resource_path(app_data_->application_path());
 
   auto extension_server = extensions::XWalkExtensionServer::GetInstance();
   extension_server->SetupIPC(ewk_context_);
index d0af1aa..4710425 100755 (executable)
@@ -41,6 +41,9 @@ class WebApplication : public WebView::EventListener {
  public:
   WebApplication(NativeWindow* window,
                  common::ApplicationData* app_data);
+  WebApplication(NativeWindow* window,
+                 common::ApplicationData* app_data,
+                 Ewk_Context* context);
   virtual ~WebApplication();
 
   void AppControl(std::unique_ptr<common::AppControl> appcontrol);
@@ -112,6 +115,7 @@ class WebApplication : public WebView::EventListener {
   bool debug_mode_;
   bool verbose_mode_;
   Ewk_Context* ewk_context_;
+  bool has_ownership_of_ewk_context_;
   NativeWindow* window_;
   std::string appid_;
   std::string app_data_path_;
index 7d1883e..b0b5bae 100755 (executable)
@@ -23,6 +23,8 @@
         'browser/native_window.cc',
         'browser/native_app_window.h',
         'browser/native_app_window.cc',
+        'browser/notification_window.h',
+        'browser/notification_window.cc',
         'browser/web_application.h',
         'browser/web_application.cc',
         'browser/web_view.h',
@@ -47,6 +49,7 @@
       'variables': {
         'packages': [
           'capi-appfw-application',
+          'capi-ui-efl-util',
           'chromium-efl',
           'ecore',
           'ecore-wayland',