Fix race-condition when window is resized or rotated.
[platform/core/uifw/dali-adaptor.git] / dali / internal / window-system / ubuntu-x11 / window-base-ecore-x.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/window-system/ubuntu-x11/window-base-ecore-x.h>
20
21 // INTERNAL HEADERS
22 #include <dali/internal/window-system/common/window-impl.h>
23 #include <dali/internal/window-system/common/window-render-surface.h>
24 #include <dali/internal/window-system/common/window-system.h>
25 #include <dali/internal/window-system/ubuntu-x11/ecore-x-types.h>
26
27 // EXTERNAL_HEADERS
28 #include <dali/integration-api/debug.h>
29 #include <dali/internal/input/ubuntu-x11/dali-ecore-input.h>
30 #include <dali/public-api/events/mouse-button.h>
31 #include <dali/public-api/object/any.h>
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37 namespace Adaptor
38 {
39 namespace
40 {
41 const std::string            DEFAULT_DEVICE_NAME     = "";
42 const Device::Class::Type    DEFAULT_DEVICE_CLASS    = Device::Class::NONE;
43 const Device::Subclass::Type DEFAULT_DEVICE_SUBCLASS = Device::Subclass::NONE;
44
45 const unsigned int PRIMARY_TOUCH_BUTTON_ID(1);
46
47 #if defined(DEBUG_ENABLED)
48 Debug::Filter* gWindowBaseLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_WINDOW_BASE");
49 #endif
50
51 /////////////////////////////////////////////////////////////////////////////////////////////////
52 // Window Callbacks
53 /////////////////////////////////////////////////////////////////////////////////////////////////
54
55 static Eina_Bool EcoreEventWindowPropertyChanged(void* data, int type, void* event)
56 {
57   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
58   if(windowBase)
59   {
60     return windowBase->OnWindowPropertyChanged(data, type, event);
61   }
62
63   return ECORE_CALLBACK_PASS_ON;
64 }
65
66 /**
67  * Called when the window receives a delete request
68  */
69 static Eina_Bool EcoreEventWindowDeleteRequest(void* data, int type, void* event)
70 {
71   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
72   if(windowBase)
73   {
74     windowBase->OnDeleteRequest();
75   }
76   return ECORE_CALLBACK_DONE;
77 }
78
79 /**
80  * Called when the window gains focus.
81  */
82 static Eina_Bool EcoreEventWindowFocusIn(void* data, int type, void* event)
83 {
84   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
85   if(windowBase)
86   {
87     windowBase->OnFocusIn(data, type, event);
88   }
89   return ECORE_CALLBACK_PASS_ON;
90 }
91
92 /**
93  * Called when the window loses focus.
94  */
95 static Eina_Bool EcoreEventWindowFocusOut(void* data, int type, void* event)
96 {
97   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
98   if(windowBase)
99   {
100     windowBase->OnFocusOut(data, type, event);
101   }
102   return ECORE_CALLBACK_PASS_ON;
103 }
104
105 /**
106  * Called when the window is damaged.
107  */
108 static Eina_Bool EcoreEventWindowDamaged(void* data, int type, void* event)
109 {
110   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
111   if(windowBase)
112   {
113     windowBase->OnWindowDamaged(data, type, event);
114   }
115
116   return ECORE_CALLBACK_PASS_ON;
117 }
118
119 /////////////////////////////////////////////////////////////////////////////////////////////////
120 // Selection Callbacks
121 /////////////////////////////////////////////////////////////////////////////////////////////////
122
123 /**
124  * Called when the source window notifies us the content in clipboard is selected.
125  */
126 static Eina_Bool EcoreEventSelectionClear(void* data, int type, void* event)
127 {
128   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
129   if(windowBase)
130   {
131     windowBase->OnSelectionClear(data, type, event);
132   }
133   return ECORE_CALLBACK_PASS_ON;
134 }
135
136 /**
137  * Called when the source window sends us about the selected content.
138  * For example, when dragged items are dragged INTO our window or when items are selected in the clipboard.
139  */
140 static Eina_Bool EcoreEventSelectionNotify(void* data, int type, void* event)
141 {
142   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
143   if(windowBase)
144   {
145     windowBase->OnSelectionNotify(data, type, event);
146   }
147   return ECORE_CALLBACK_PASS_ON;
148 }
149
150 /////////////////////////////////////////////////////////////////////////////////////////////////
151 // Touch Callbacks
152 /////////////////////////////////////////////////////////////////////////////////////////////////
153
154 /**
155  * Called when a touch down is received.
156  */
157 static Eina_Bool EcoreEventMouseButtonDown(void* data, int type, void* event)
158 {
159   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
160   if(windowBase)
161   {
162     windowBase->OnMouseButtonDown(data, type, event);
163   }
164   return ECORE_CALLBACK_PASS_ON;
165 }
166
167 /**
168  * Called when a touch up is received.
169  */
170 static Eina_Bool EcoreEventMouseButtonUp(void* data, int type, void* event)
171 {
172   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
173   if(windowBase)
174   {
175     windowBase->OnMouseButtonUp(data, type, event);
176   }
177   return ECORE_CALLBACK_PASS_ON;
178 }
179
180 /**
181  * Called when a touch motion is received.
182  */
183 static Eina_Bool EcoreEventMouseButtonMove(void* data, int type, void* event)
184 {
185   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
186   if(windowBase)
187   {
188     windowBase->OnMouseButtonMove(data, type, event);
189   }
190   return ECORE_CALLBACK_PASS_ON;
191 }
192
193 /////////////////////////////////////////////////////////////////////////////////////////////////
194 // Wheel Callbacks
195 /////////////////////////////////////////////////////////////////////////////////////////////////
196
197 /**
198  * Called when a mouse wheel is received.
199  */
200 static Eina_Bool EcoreEventMouseWheel(void* data, int type, void* event)
201 {
202   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
203   if(windowBase)
204   {
205     windowBase->OnMouseWheel(data, type, event);
206   }
207   return ECORE_CALLBACK_PASS_ON;
208 }
209
210 /////////////////////////////////////////////////////////////////////////////////////////////////
211 // Key Callbacks
212 /////////////////////////////////////////////////////////////////////////////////////////////////
213
214 /**
215  * Called when a key down is received.
216  */
217 static Eina_Bool EcoreEventKeyDown(void* data, int type, void* event)
218 {
219   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
220   if(windowBase)
221   {
222     windowBase->OnKeyDown(data, type, event);
223   }
224   return ECORE_CALLBACK_PASS_ON;
225 }
226
227 /**
228  * Called when a key up is received.
229  */
230 static Eina_Bool EcoreEventKeyUp(void* data, int type, void* event)
231 {
232   WindowBaseEcoreX* windowBase = static_cast<WindowBaseEcoreX*>(data);
233   if(windowBase)
234   {
235     windowBase->OnKeyUp(data, type, event);
236   }
237   return ECORE_CALLBACK_PASS_ON;
238 }
239
240 } // unnamed namespace
241
242 WindowBaseEcoreX::WindowBaseEcoreX(Dali::PositionSize positionSize, Any surface, bool isTransparent)
243 : mEcoreEventHandler(),
244   mEcoreWindow(0),
245   mOwnSurface(false),
246   mIsTransparent(false), // Should only be set to true once we actually create a transparent window regardless of what isTransparent is.
247   mRotationAppSet(false),
248   mWindowRotationAngle(0)
249 {
250   Initialize(positionSize, surface, isTransparent);
251 }
252
253 WindowBaseEcoreX::~WindowBaseEcoreX()
254 {
255   for(Dali::Vector<Ecore_Event_Handler*>::Iterator iter = mEcoreEventHandler.Begin(), endIter = mEcoreEventHandler.End(); iter != endIter; ++iter)
256   {
257     ecore_event_handler_del(*iter);
258   }
259   mEcoreEventHandler.Clear();
260
261   if(mOwnSurface)
262   {
263     ecore_x_window_free(mEcoreWindow);
264
265     WindowSystem::Shutdown();
266   }
267 }
268
269 void WindowBaseEcoreX::Initialize(PositionSize positionSize, Any surface, bool isTransparent)
270 {
271   // see if there is a surface in Any surface
272   unsigned int surfaceId = GetSurfaceId(surface);
273
274   // if the surface is empty, create a new one.
275   if(surfaceId == 0)
276   {
277     WindowSystem::Initialize();
278
279     // we own the surface about to created
280     mOwnSurface = true;
281     CreateWindow(positionSize, isTransparent);
282   }
283   else
284   {
285     // XLib should already be initialized so no point in calling XInitThreads
286     mEcoreWindow = static_cast<Ecore_X_Window>(surfaceId);
287   }
288
289   // set up etc properties to match with ecore-evas
290   char* id = NULL;
291   if((id = getenv("DESKTOP_STARTUP_ID")))
292   {
293     ecore_x_netwm_startup_id_set(mEcoreWindow, id);
294   }
295
296   ecore_x_icccm_hints_set(mEcoreWindow,
297                           1,                                // accepts_focus
298                           ECORE_X_WINDOW_STATE_HINT_NORMAL, // initial_state
299                           0,                                // icon_pixmap
300                           0,                                // icon_mask
301                           0,                                // icon_window
302                           0,                                // window_group
303                           0);                               // is_urgent
304
305   // we SHOULD guarantee the x11 window was created in x server.
306   ecore_x_sync();
307
308   ecore_x_input_multi_select(mEcoreWindow);
309
310   // This ensures that we catch the window close (or delete) request
311   ecore_x_icccm_protocol_set(mEcoreWindow, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, EINA_TRUE);
312
313   // Enable Drag & Drop
314   ecore_x_dnd_aware_set(mEcoreWindow, EINA_TRUE);
315
316   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY, EcoreEventWindowPropertyChanged, this));
317   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, EcoreEventWindowDeleteRequest, this));
318
319   // Register window focus events
320   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, EcoreEventWindowFocusIn, this));
321   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, EcoreEventWindowFocusOut, this));
322
323   // Register Window damage events
324   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, EcoreEventWindowDamaged, this));
325
326   // Register Touch events
327   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, EcoreEventMouseButtonDown, this));
328   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, EcoreEventMouseButtonUp, this));
329   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, EcoreEventMouseButtonMove, this));
330   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_MOUSE_OUT, EcoreEventMouseButtonUp, this)); // process mouse out event like up event
331
332   // Register Mouse wheel events
333   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_MOUSE_WHEEL, EcoreEventMouseWheel, this));
334
335   // Register Key events
336   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, EcoreEventKeyDown, this));
337   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_EVENT_KEY_UP, EcoreEventKeyUp, this));
338
339   // Register Selection event
340   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, EcoreEventSelectionClear, this));
341   mEcoreEventHandler.PushBack(ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, EcoreEventSelectionNotify, this));
342 }
343
344 Eina_Bool WindowBaseEcoreX::OnWindowPropertyChanged(void* data, int type, void* event)
345 {
346   Ecore_X_Event_Window_Property* propertyChangedEvent = static_cast<Ecore_X_Event_Window_Property*>(event);
347   Eina_Bool                      handled(ECORE_CALLBACK_PASS_ON);
348
349   if(propertyChangedEvent->win == mEcoreWindow)
350   {
351     Ecore_X_Window_State_Hint state(ecore_x_icccm_state_get(propertyChangedEvent->win));
352
353     switch(state)
354     {
355       case ECORE_X_WINDOW_STATE_HINT_WITHDRAWN:
356       {
357         // Window was hidden.
358         mIconifyChangedSignal.Emit(true);
359         handled = ECORE_CALLBACK_DONE;
360         break;
361       }
362       case ECORE_X_WINDOW_STATE_HINT_ICONIC:
363       {
364         // Window was iconified (minimised).
365         mIconifyChangedSignal.Emit(true);
366         handled = ECORE_CALLBACK_DONE;
367         break;
368       }
369       case ECORE_X_WINDOW_STATE_HINT_NORMAL:
370       {
371         // Window was shown.
372         mIconifyChangedSignal.Emit(false);
373         handled = ECORE_CALLBACK_DONE;
374         break;
375       }
376       default:
377       {
378         // Ignore
379         break;
380       }
381     }
382   }
383
384   return handled;
385 }
386
387 void WindowBaseEcoreX::OnDeleteRequest()
388 {
389   mDeleteRequestSignal.Emit();
390 }
391
392 void WindowBaseEcoreX::OnFocusIn(void* data, int type, void* event)
393 {
394   Ecore_X_Event_Window_Focus_In* focusInEvent = static_cast<Ecore_X_Event_Window_Focus_In*>(event);
395
396   if(focusInEvent->win == mEcoreWindow)
397   {
398     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::General, "Window EcoreEventWindowFocusIn\n");
399
400     mFocusChangedSignal.Emit(true);
401   }
402 }
403
404 void WindowBaseEcoreX::OnFocusOut(void* data, int type, void* event)
405 {
406   Ecore_X_Event_Window_Focus_Out* focusOutEvent = static_cast<Ecore_X_Event_Window_Focus_Out*>(event);
407
408   // If the window loses focus then hide the keyboard.
409   if(focusOutEvent->win == mEcoreWindow)
410   {
411     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::General, "Window EcoreEventWindowFocusOut\n");
412
413     mFocusChangedSignal.Emit(false);
414   }
415 }
416
417 void WindowBaseEcoreX::OnWindowDamaged(void* data, int type, void* event)
418 {
419   Ecore_X_Event_Window_Damage* windowDamagedEvent = static_cast<Ecore_X_Event_Window_Damage*>(event);
420
421   if(windowDamagedEvent->win == mEcoreWindow)
422   {
423     DamageArea area;
424     area.x      = windowDamagedEvent->x;
425     area.y      = windowDamagedEvent->y;
426     area.width  = windowDamagedEvent->w;
427     area.height = windowDamagedEvent->h;
428
429     mWindowDamagedSignal.Emit(area);
430   }
431 }
432
433 void WindowBaseEcoreX::OnMouseButtonDown(void* data, int type, void* event)
434 {
435   Ecore_Event_Mouse_Button* touchEvent = static_cast<Ecore_Event_Mouse_Button*>(event);
436
437   if(touchEvent->window == mEcoreWindow)
438   {
439     PointState::Type state(PointState::DOWN);
440
441     Integration::Point point;
442     point.SetDeviceId(touchEvent->multi.device);
443     point.SetState(state);
444     point.SetScreenPosition(Vector2(touchEvent->x, touchEvent->y));
445     point.SetRadius(touchEvent->multi.radius, Vector2(touchEvent->multi.radius_x, touchEvent->multi.radius_y));
446     point.SetPressure(touchEvent->multi.pressure);
447     point.SetAngle(Degree(touchEvent->multi.angle));
448     if(touchEvent->buttons)
449     {
450       point.SetMouseButton(static_cast<MouseButton::Type>(touchEvent->buttons));
451     }
452
453     mTouchEventSignal.Emit(point, touchEvent->timestamp);
454   }
455 }
456
457 void WindowBaseEcoreX::OnMouseButtonUp(void* data, int type, void* event)
458 {
459   Ecore_Event_Mouse_Button* touchEvent = static_cast<Ecore_Event_Mouse_Button*>(event);
460
461   if(touchEvent->window == mEcoreWindow)
462   {
463     Integration::Point point;
464     point.SetDeviceId(touchEvent->multi.device);
465     point.SetState(PointState::UP);
466     point.SetScreenPosition(Vector2(touchEvent->x, touchEvent->y));
467     point.SetRadius(touchEvent->multi.radius, Vector2(touchEvent->multi.radius_x, touchEvent->multi.radius_y));
468     point.SetPressure(touchEvent->multi.pressure);
469     point.SetAngle(Degree(static_cast<float>(touchEvent->multi.angle)));
470     if(touchEvent->buttons)
471     {
472       point.SetMouseButton(static_cast<MouseButton::Type>(touchEvent->buttons));
473     }
474
475     mTouchEventSignal.Emit(point, touchEvent->timestamp);
476   }
477 }
478
479 void WindowBaseEcoreX::OnMouseButtonMove(void* data, int type, void* event)
480 {
481   Ecore_Event_Mouse_Move* touchEvent = static_cast<Ecore_Event_Mouse_Move*>(event);
482
483   if(touchEvent->window == mEcoreWindow)
484   {
485     Integration::Point point;
486     point.SetDeviceId(touchEvent->multi.device);
487     point.SetState(PointState::MOTION);
488     point.SetScreenPosition(Vector2(static_cast<float>(touchEvent->x), static_cast<float>(touchEvent->y)));
489     point.SetRadius(static_cast<float>(touchEvent->multi.radius), Vector2(static_cast<float>(touchEvent->multi.radius_x), static_cast<float>(touchEvent->multi.radius_y)));
490     point.SetPressure(static_cast<float>(touchEvent->multi.pressure));
491     point.SetAngle(Degree(static_cast<float>(touchEvent->multi.angle)));
492
493     mTouchEventSignal.Emit(point, touchEvent->timestamp);
494   }
495 }
496
497 void WindowBaseEcoreX::OnMouseWheel(void* data, int type, void* event)
498 {
499   Ecore_Event_Mouse_Wheel* mouseWheelEvent = static_cast<Ecore_Event_Mouse_Wheel*>(event);
500
501   if(mouseWheelEvent->window == mEcoreWindow)
502   {
503     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::General, "WindowBaseEcoreX::OnMouseWheel: direction: %d, modifiers: %d, x: %d, y: %d, z: %d\n", mouseWheelEvent->direction, mouseWheelEvent->modifiers, mouseWheelEvent->x, mouseWheelEvent->y, mouseWheelEvent->z);
504
505     Integration::WheelEvent wheelEvent(Integration::WheelEvent::MOUSE_WHEEL, mouseWheelEvent->direction, mouseWheelEvent->modifiers, Vector2(static_cast<float>(mouseWheelEvent->x), static_cast<float>(mouseWheelEvent->y)), mouseWheelEvent->z, mouseWheelEvent->timestamp);
506
507     mWheelEventSignal.Emit(wheelEvent);
508   }
509 }
510
511 void WindowBaseEcoreX::OnKeyDown(void* data, int type, void* event)
512 {
513   Ecore_Event_Key* keyEvent = static_cast<Ecore_Event_Key*>(event);
514
515   if(keyEvent->window == mEcoreWindow)
516   {
517     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::General, "WindowBaseEcoreX::OnKeyDown\n");
518
519     std::string keyName(keyEvent->keyname);
520     std::string logicalKey("");
521     std::string keyString("");
522     std::string compose("");
523
524     // Ensure key compose string is not NULL as keys like SHIFT or arrow have a null string.
525     if(keyEvent->compose)
526     {
527       compose = keyEvent->compose;
528     }
529
530     // Ensure key symbol is not NULL as keys like SHIFT have a null string.
531     if(keyEvent->key)
532     {
533       logicalKey = keyEvent->key;
534     }
535
536     int           keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
537     int           modifier(keyEvent->modifiers);
538     unsigned long time = keyEvent->timestamp;
539
540     // Ensure key event string is not NULL as keys like SHIFT have a null string.
541     if(keyEvent->string)
542     {
543       keyString = keyEvent->string;
544     }
545
546     Integration::KeyEvent keyEvent(keyName, logicalKey, keyString, keyCode, modifier, time, Integration::KeyEvent::DOWN, compose, DEFAULT_DEVICE_NAME, DEFAULT_DEVICE_CLASS, DEFAULT_DEVICE_SUBCLASS);
547
548     mKeyEventSignal.Emit(keyEvent);
549   }
550 }
551
552 void WindowBaseEcoreX::OnKeyUp(void* data, int type, void* event)
553 {
554   Ecore_Event_Key* keyEvent = static_cast<Ecore_Event_Key*>(event);
555
556   if(keyEvent->window == mEcoreWindow)
557   {
558     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::General, " WindowBaseEcoreX::OnKeyUp\n");
559
560     std::string keyName(keyEvent->keyname);
561     std::string logicalKey("");
562     std::string keyString("");
563     std::string compose("");
564
565     // Ensure key compose string is not NULL as keys like SHIFT or arrow have a null string.
566     if(keyEvent->compose)
567     {
568       compose = keyEvent->compose;
569     }
570     // Ensure key symbol is not NULL as keys like SHIFT have a null string.
571     if(keyEvent->key)
572     {
573       logicalKey = keyEvent->key;
574     }
575
576     int           keyCode = ecore_x_keysym_keycode_get(keyEvent->keyname);
577     int           modifier(keyEvent->modifiers);
578     unsigned long time(keyEvent->timestamp);
579
580     // Ensure key event string is not NULL as keys like SHIFT have a null string.
581     if(keyEvent->string)
582     {
583       keyString = keyEvent->string;
584     }
585
586     Integration::KeyEvent keyEvent(keyName, logicalKey, keyString, keyCode, modifier, time, Integration::KeyEvent::UP, compose, DEFAULT_DEVICE_NAME, DEFAULT_DEVICE_CLASS, DEFAULT_DEVICE_SUBCLASS);
587
588     mKeyEventSignal.Emit(keyEvent);
589   }
590 }
591
592 void WindowBaseEcoreX::OnSelectionClear(void* data, int type, void* event)
593 {
594   Ecore_X_Event_Selection_Clear* selectionClearEvent = static_cast<Ecore_X_Event_Selection_Clear*>(event);
595
596   if(selectionClearEvent->win == mEcoreWindow)
597   {
598     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Concise, " WindowBaseEcoreX::OnSelectionClear\n");
599
600     if(selectionClearEvent->selection == ECORE_X_SELECTION_SECONDARY)
601     {
602       // Request to get the content from Ecore.
603       ecore_x_selection_secondary_request(selectionClearEvent->win, ECORE_X_SELECTION_TARGET_TEXT);
604     }
605   }
606 }
607
608 void WindowBaseEcoreX::OnSelectionNotify(void* data, int type, void* event)
609 {
610   Ecore_X_Event_Selection_Notify* selectionNotifyEvent = static_cast<Ecore_X_Event_Selection_Notify*>(event);
611
612   if(selectionNotifyEvent->win == mEcoreWindow)
613   {
614     DALI_LOG_INFO(gWindowBaseLogFilter, Debug::Concise, " WindowBaseEcoreX::OnSelectionNotify\n");
615
616     Ecore_X_Selection_Data* selectionData = static_cast<Ecore_X_Selection_Data*>(selectionNotifyEvent->data);
617     if(selectionData->data)
618     {
619       if(selectionNotifyEvent->selection == ECORE_X_SELECTION_SECONDARY)
620       {
621         mSelectionDataReceivedSignal.Emit(event);
622       }
623     }
624   }
625 }
626
627 Any WindowBaseEcoreX::GetNativeWindow()
628 {
629   return mEcoreWindow;
630 }
631
632 int WindowBaseEcoreX::GetNativeWindowId()
633 {
634   return mEcoreWindow;
635 }
636
637 std::string WindowBaseEcoreX::GetNativeWindowResourceId()
638 {
639   return std::string();
640 }
641
642 EGLNativeWindowType WindowBaseEcoreX::CreateEglWindow(int width, int height)
643 {
644   // need to create X handle as in 64bit system ECore handle is 32 bit whereas EGLnative and XWindow are 64 bit
645   XWindow window(mEcoreWindow);
646   return reinterpret_cast<EGLNativeWindowType>(window);
647 }
648
649 void WindowBaseEcoreX::DestroyEglWindow()
650 {
651 }
652
653 void WindowBaseEcoreX::SetEglWindowRotation(int angle)
654 {
655 }
656
657 void WindowBaseEcoreX::SetEglWindowBufferTransform(int angle)
658 {
659 }
660
661 void WindowBaseEcoreX::SetEglWindowTransform(int angle)
662 {
663 }
664
665 void WindowBaseEcoreX::ResizeEglWindow(PositionSize positionSize)
666 {
667 }
668
669 bool WindowBaseEcoreX::IsEglWindowRotationSupported()
670 {
671   return false;
672 }
673
674 void WindowBaseEcoreX::Move(PositionSize positionSize)
675 {
676   ecore_x_window_move(mEcoreWindow, positionSize.x, positionSize.y);
677 }
678
679 void WindowBaseEcoreX::Resize(PositionSize positionSize)
680 {
681   ecore_x_window_resize(mEcoreWindow, positionSize.width, positionSize.height);
682 }
683
684 void WindowBaseEcoreX::MoveResize(PositionSize positionSize)
685 {
686   ecore_x_window_move_resize(mEcoreWindow, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
687 }
688
689 void WindowBaseEcoreX::SetClass(const std::string& name, const std::string& className)
690 {
691   ecore_x_icccm_title_set(mEcoreWindow, name.c_str());
692   ecore_x_netwm_name_set(mEcoreWindow, name.c_str());
693   ecore_x_icccm_name_class_set(mEcoreWindow, name.c_str(), className.c_str());
694 }
695
696 void WindowBaseEcoreX::Raise()
697 {
698   ecore_x_window_raise(mEcoreWindow);
699 }
700
701 void WindowBaseEcoreX::Lower()
702 {
703   ecore_x_window_lower(mEcoreWindow);
704 }
705
706 void WindowBaseEcoreX::Activate()
707 {
708   ecore_x_netwm_client_active_request(ecore_x_window_root_get(mEcoreWindow), mEcoreWindow, 1 /* request type, 1:application, 2:pager */, 0);
709 }
710
711 void WindowBaseEcoreX::Maximize(bool maximize)
712 {
713 }
714
715 bool WindowBaseEcoreX::IsMaximized() const
716 {
717   return false;
718 }
719
720 void WindowBaseEcoreX::SetMaximumSize(Dali::Window::WindowSize size)
721 {
722 }
723
724 void WindowBaseEcoreX::Minimize(bool minimize)
725 {
726 }
727
728 bool WindowBaseEcoreX::IsMinimized() const
729 {
730   return false;
731 }
732
733 void WindowBaseEcoreX::SetMimimumSize(Dali::Window::WindowSize size)
734 {
735 }
736
737 void WindowBaseEcoreX::SetAvailableAnlges(const std::vector<int>& angles)
738 {
739 }
740
741 void WindowBaseEcoreX::SetPreferredAngle(int angle)
742 {
743 }
744
745 void WindowBaseEcoreX::SetAcceptFocus(bool accept)
746 {
747 }
748
749 void WindowBaseEcoreX::Show()
750 {
751   ecore_x_window_show(mEcoreWindow);
752 }
753
754 void WindowBaseEcoreX::Hide()
755 {
756   ecore_x_window_hide(mEcoreWindow);
757 }
758
759 unsigned int WindowBaseEcoreX::GetSupportedAuxiliaryHintCount() const
760 {
761   return 0;
762 }
763
764 std::string WindowBaseEcoreX::GetSupportedAuxiliaryHint(unsigned int index) const
765 {
766   return std::string();
767 }
768
769 unsigned int WindowBaseEcoreX::AddAuxiliaryHint(const std::string& hint, const std::string& value)
770 {
771   return 0;
772 }
773
774 bool WindowBaseEcoreX::RemoveAuxiliaryHint(unsigned int id)
775 {
776   return false;
777 }
778
779 bool WindowBaseEcoreX::SetAuxiliaryHintValue(unsigned int id, const std::string& value)
780 {
781   return false;
782 }
783
784 std::string WindowBaseEcoreX::GetAuxiliaryHintValue(unsigned int id) const
785 {
786   return std::string();
787 }
788
789 unsigned int WindowBaseEcoreX::GetAuxiliaryHintId(const std::string& hint) const
790 {
791   return 0;
792 }
793
794 void WindowBaseEcoreX::SetInputRegion(const Rect<int>& inputRegion)
795 {
796 }
797
798 void WindowBaseEcoreX::SetType(Dali::WindowType type)
799 {
800 }
801
802 Dali::WindowType WindowBaseEcoreX::GetType() const
803 {
804   return Dali::WindowType::NORMAL;
805 }
806
807 Dali::WindowOperationResult WindowBaseEcoreX::SetNotificationLevel(Dali::WindowNotificationLevel level)
808 {
809   return Dali::WindowOperationResult::NOT_SUPPORTED;
810 }
811
812 Dali::WindowNotificationLevel WindowBaseEcoreX::GetNotificationLevel() const
813 {
814   return Dali::WindowNotificationLevel::NONE;
815 }
816
817 void WindowBaseEcoreX::SetOpaqueState(bool opaque)
818 {
819 }
820
821 Dali::WindowOperationResult WindowBaseEcoreX::SetScreenOffMode(WindowScreenOffMode screenOffMode)
822 {
823   return Dali::WindowOperationResult::NOT_SUPPORTED;
824 }
825
826 WindowScreenOffMode WindowBaseEcoreX::GetScreenOffMode() const
827 {
828   return WindowScreenOffMode::TIMEOUT;
829 }
830
831 Dali::WindowOperationResult WindowBaseEcoreX::SetBrightness(int brightness)
832 {
833   return Dali::WindowOperationResult::NOT_SUPPORTED;
834 }
835
836 int WindowBaseEcoreX::GetBrightness() const
837 {
838   return 0;
839 }
840
841 bool WindowBaseEcoreX::GrabKey(Dali::KEY key, KeyGrab::KeyGrabMode grabMode)
842 {
843   return false;
844 }
845
846 bool WindowBaseEcoreX::UngrabKey(Dali::KEY key)
847 {
848   return false;
849 }
850
851 bool WindowBaseEcoreX::GrabKeyList(const Dali::Vector<Dali::KEY>& key, const Dali::Vector<KeyGrab::KeyGrabMode>& grabMode, Dali::Vector<bool>& result)
852 {
853   return false;
854 }
855
856 bool WindowBaseEcoreX::UngrabKeyList(const Dali::Vector<Dali::KEY>& key, Dali::Vector<bool>& result)
857 {
858   return false;
859 }
860
861 void WindowBaseEcoreX::GetDpi(unsigned int& dpiHorizontal, unsigned int& dpiVertical)
862 {
863   // 1 inch = 25.4 millimeters
864   // ecore does not account for differing DPI in the x and y axes, so only get for x is available
865
866   dpiHorizontal = ecore_x_dpi_get();
867   dpiVertical   = ecore_x_dpi_get();
868 }
869
870 int WindowBaseEcoreX::GetWindowRotationAngle() const
871 {
872   return 0;
873 }
874
875 int WindowBaseEcoreX::GetScreenRotationAngle()
876 {
877   return 0;
878 }
879
880 void WindowBaseEcoreX::SetWindowRotationAngle(int degree)
881 {
882   mWindowRotationAngle = degree;
883 }
884
885 void WindowBaseEcoreX::WindowRotationCompleted(int degree, int width, int height)
886 {
887 }
888
889 void WindowBaseEcoreX::SetTransparency(bool transparent)
890 {
891 }
892
893 unsigned int WindowBaseEcoreX::GetSurfaceId(Any surface) const
894 {
895   unsigned int surfaceId = 0;
896
897   if(surface.Empty() == false)
898   {
899     // check we have a valid type
900     DALI_ASSERT_ALWAYS(((surface.GetType() == typeid(XWindow)) || (surface.GetType() == typeid(Ecore_X_Window))) && "Surface type is invalid");
901
902     if(surface.GetType() == typeid(Ecore_X_Window))
903     {
904       surfaceId = AnyCast<Ecore_X_Window>(surface);
905     }
906     else
907     {
908       surfaceId = static_cast<unsigned int>(AnyCast<XWindow>(surface));
909     }
910   }
911   return surfaceId;
912 }
913
914 void WindowBaseEcoreX::CreateWindow(PositionSize positionSize, bool isTransparent)
915 {
916   if(isTransparent)
917   {
918     // create 32 bit window
919     mEcoreWindow   = ecore_x_window_argb_new(0, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
920     mIsTransparent = true;
921   }
922   else
923   {
924     // create 24 bit window
925     mEcoreWindow = ecore_x_window_new(0, positionSize.x, positionSize.y, positionSize.width, positionSize.height);
926   }
927
928   if(mEcoreWindow == 0)
929   {
930     DALI_ASSERT_ALWAYS(0 && "Failed to create X window");
931   }
932 }
933
934 void WindowBaseEcoreX::SetParent(WindowBase* parentWinBase, bool belowParent)
935 {
936   Ecore_X_Window ecoreParent = 0;
937   if(parentWinBase)
938   {
939     WindowBaseEcoreX* winBaseEcoreX = static_cast<WindowBaseEcoreX*>(parentWinBase);
940     ecoreParent                     = winBaseEcoreX->mEcoreWindow;
941     ecore_x_icccm_transient_for_set(mEcoreWindow, ecoreParent);
942   }
943   else
944   {
945     ecoreParent = 0;
946     ecore_x_icccm_transient_for_unset(mEcoreWindow);
947   }
948 }
949
950 int WindowBaseEcoreX::CreateFrameRenderedSyncFence()
951 {
952   return -1;
953 }
954
955 int WindowBaseEcoreX::CreateFramePresentedSyncFence()
956 {
957   return -1;
958 }
959
960 void WindowBaseEcoreX::SetPositionSizeWithAngle(PositionSize positionSize, int angle)
961 {
962 }
963
964 void WindowBaseEcoreX::InitializeIme()
965 {
966 }
967
968 void WindowBaseEcoreX::ImeWindowReadyToRender()
969 {
970 }
971
972 void WindowBaseEcoreX::RequestMoveToServer()
973 {
974 }
975
976 void WindowBaseEcoreX::RequestResizeToServer(WindowResizeDirection direction)
977 {
978 }
979
980 void WindowBaseEcoreX::EnableFloatingMode(bool enable)
981 {
982 }
983
984 bool WindowBaseEcoreX::IsFloatingModeEnabled() const
985 {
986   return false;
987 }
988
989 void WindowBaseEcoreX::IncludeInputRegion(const Rect<int>& inputRegion)
990 {
991 }
992
993 void WindowBaseEcoreX::ExcludeInputRegion(const Rect<int>& inputRegion)
994 {
995 }
996
997 } // namespace Adaptor
998
999 } // namespace Internal
1000
1001 } // namespace Dali