1 // Copyright 2023 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "wrt/src/browser/wrt_native_window_on_screen.h"
7 #include <Ecore_Evas.h>
10 #include "base/task/single_thread_task_runner.h"
11 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
12 #include "ui/views/view.h"
13 #include "ui/views/widget/native_widget_private.h"
14 #include "ui/views/widget/widget.h"
15 #include "ui/wm/core/focus_controller.h"
16 #include "wrt/src/browser/wrt_native_widget.h"
17 #include "wrt/src/browser/wrt_window_tree_host.h"
21 WRTNativeWindowOnScreen::WRTNativeWindowOnScreen() {
22 auto* evas_object = GetWindowTreeHost(nullptr)->GetEvasObject();
23 auto* ee = ecore_evas_ecore_evas_get(evas_object_evas_get(evas_object));
24 auto* wl2_window = ecore_evas_wayland2_window_get(ee);
25 ecore_wl2_window_conformant_set(wl2_window, EINA_TRUE);
27 auto* conformant_handler = ecore_event_handler_add(
28 ECORE_WL2_EVENT_CONFORMANT_CHANGE,
29 [](void* data, int, void*) -> Eina_Bool {
30 auto* window = static_cast<WRTNativeWindowOnScreen*>(data);
31 window->OnConformantChange();
32 return ECORE_CALLBACK_PASS_ON;
35 if (conformant_handler)
36 handlers_.push_back(conformant_handler);
38 auto* focus_in_handler = ecore_event_handler_add(
39 ECORE_WL2_EVENT_FOCUS_IN,
40 [](void* data, int, void*) -> Eina_Bool {
41 auto* onscreen_window = static_cast<WRTNativeWindowOnScreen*>(data);
42 onscreen_window->ActiveAuraWindow(true);
43 return ECORE_CALLBACK_PASS_ON;
47 handlers_.push_back(focus_in_handler);
49 auto* focus_out_handler = ecore_event_handler_add(
50 ECORE_WL2_EVENT_FOCUS_OUT,
51 [](void* data, int, void*) -> Eina_Bool {
52 auto* onscreen_window = static_cast<WRTNativeWindowOnScreen*>(data);
53 onscreen_window->ActiveAuraWindow(false);
54 return ECORE_CALLBACK_PASS_ON;
57 if (focus_out_handler)
58 handlers_.push_back(focus_out_handler);
61 Evas_Object* WRTNativeWindowOnScreen::GetWindowEvasObject() {
62 return host_->GetEvasObject();
65 Evas_Object* WRTNativeWindowOnScreen::GetTopWindow() {
66 return host_->GetEvasObject();
69 WRTWindowTreeHost* WRTNativeWindowOnScreen::GetWindowTreeHost(
70 WRTNativeWindow* native_window) {
72 host_.reset(WRTWindowTreeHost::Create());
76 void WRTNativeWindowOnScreen::ClearHandlers() {
77 for (auto* handler : handlers_)
78 ecore_event_handler_del(handler);
82 void WRTNativeWindowOnScreen::OnNativeWindowDestroyed(
83 WRTNativeWindow* native_window) {
84 if (!native_window->is_main_native_window())
87 auto* host = host_.release();
88 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
90 base::BindOnce([](WRTWindowTreeHost* host) { delete host; }, host));
93 void WRTNativeWindowOnScreen::InitRotation() {
94 auto* handler = ecore_event_handler_add(
95 ECORE_WL2_EVENT_WINDOW_ROTATE,
96 [](void*, int, void*) -> Eina_Bool {
97 WRTNativeWindow::RotationCallback();
98 return ECORE_CALLBACK_PASS_ON;
102 handlers_.push_back(handler);
105 int WRTNativeWindowOnScreen::SetRotationState(bool is_auto, int degree) {
106 auto* ee = WRTNativeWindow::GetPlatformCanvas();
107 int rotation_degree = 0;
109 LOG(INFO) << "Rotation : Auto";
110 ecore_evas_wm_rotation_preferred_rotation_set(ee, -1);
111 if (ecore_evas_wm_rotation_supported_get(ee)) {
112 const int rotations[4] = {0, 90, 180, 270};
113 ecore_evas_wm_rotation_available_rotations_set(ee, rotations, 4);
115 ecore_evas_wm_rotation_manual_rotation_done_set(ee, EINA_TRUE);
116 rotation_degree = ecore_evas_rotation_get(ee);
119 rotation_degree = degree % 360;
120 LOG(INFO) << "Rotation : Lock to " << rotation_degree;
121 ecore_evas_wm_rotation_preferred_rotation_set(ee, rotation_degree);
124 return rotation_degree;
127 void WRTNativeWindowOnScreen::SetContentView(WRTNativeWindow* native_window,
129 auto* client_view = native_window->widget()->client_view();
132 if (native_window->content_view())
133 client_view->RemoveChildView(native_window->content_view());
134 client_view->AddChildView(view);
135 view->SetSize(client_view->size());
138 void WRTNativeWindowOnScreen::Show(WRTNativeWindow* native_window) {
139 auto widget = native_window->widget();
140 widget->native_widget_private()->Show(ui::SHOW_STATE_NORMAL, gfx::Rect());
141 // explicitly focus the window
145 void WRTNativeWindowOnScreen::Hide() {
149 bool WRTNativeWindowOnScreen::IsFocused(WRTNativeWindow* native_window) {
150 return native_window->widget()->IsActive();
153 void WRTNativeWindowOnScreen::Focus(WRTNativeWindow* native_window,
155 auto widget = native_window->widget();
159 widget->Deactivate();
162 void WRTNativeWindowOnScreen::OnConformantChange() {
163 auto* native_window = WRTNativeWindow::GetActiveNativeWindow();
167 if (!native_window->ShouldHandleConformantChange()) {
168 LOG(INFO) << "use.conformant is floating, not handle conformant change!";
173 ecore_evas_wayland2_window_get(WRTNativeWindow::GetPlatformCanvas());
177 int x, y, width, height;
178 ecore_wl2_window_geometry_get(wl2_window, &x, &y, &width, &height);
179 gfx::Rect rect(x, y, width, height);
181 if (native_window->WillHandleConformantChange()) {
182 if (ecore_wl2_window_indicator_state_get(wl2_window) ==
183 ECORE_WL2_INDICATOR_STATE_ON) {
184 ecore_wl2_window_indicator_geometry_get(
185 wl2_window, &x, &y, &width, &height);
186 rect.Subtract(gfx::Rect(x, y, width, height));
188 if (ecore_wl2_window_keyboard_state_get(wl2_window) ==
189 ECORE_WL2_VIRTUAL_KEYBOARD_STATE_ON) {
190 ecore_wl2_window_keyboard_geometry_get(
191 wl2_window, &x, &y, &width, &height);
192 rect.Subtract(gfx::Rect(x, y, width, height));
194 if (ecore_wl2_window_clipboard_state_get(wl2_window) ==
195 ECORE_WL2_CLIPBOARD_STATE_ON) {
196 ecore_wl2_window_clipboard_geometry_get(
197 wl2_window, &x, &y, &width, &height);
198 rect.Subtract(gfx::Rect(x, y, width, height));
202 auto rotation = ecore_wl2_window_rotation_get(wl2_window);
203 if (rotation == 90 || rotation == 270)
206 auto current_rect = native_window->GetBounds();
207 if (rect != current_rect) {
208 LOG(INFO) << "Set bounds : (" << current_rect.ToString() << ") -> ("
209 << rect.ToString() << ")";
210 native_window->SetBounds(rect);
214 void WRTNativeWindowOnScreen::ActiveAuraWindow(bool active) {
215 auto* native_window = WRTNativeWindow::GetActiveNativeWindow();
219 auto* rwhva = native_window->GetRenderWidgetHostView();
220 WRTNativeWidget* widget =
221 (WRTNativeWidget*)native_window->widget()->native_widget();
223 widget->ActiveAuraWindow(active, rwhva->GetNativeView());
226 void WRTNativeWindowOnScreen::CheckAndResetWidgetClient(
227 WRTNativeWindow* native_window) {
231 auto* rwhva = native_window->GetRenderWidgetHostView();
232 WRTNativeWidget* widget =
233 (WRTNativeWidget*)native_window->widget()->native_widget();
235 widget->CheckAndResetWidgetClient();
238 void WRTNativeWindowOnScreen::RemoveWidgetClient(
239 WRTNativeWindow* native_window) {
243 auto* rwhva = native_window->GetRenderWidgetHostView();
244 WRTNativeWidget* widget =
245 (WRTNativeWidget*)native_window->widget()->native_widget();
247 widget->RemoveWidgetClient();