From 77092d94d457d35e11194e0b2ee2a2e9b90b38b9 Mon Sep 17 00:00:00 2001 From: Gwanglim Lee Date: Sun, 9 Feb 2014 09:46:51 +0900 Subject: [PATCH] ecore_evas: added window manager rotation to manage the rotation of windows by the WM. Summary: The window manager rotation allows the WM to controls the rotation of application windows. It is designed to support synchronized rotation for the multiple application windows at same time. Reviewers: raster, seoz, cedric, Hermet Reviewed By: raster CC: cedric Differential Revision: https://phab.enlightenment.org/D529 --- ChangeLog | 13 + src/lib/ecore_evas/Ecore_Evas.h | 81 ++++ src/lib/ecore_evas/ecore_evas.c | 152 +++++++ src/lib/ecore_evas/ecore_evas_buffer.c | 10 +- src/lib/ecore_evas/ecore_evas_ews.c | 10 +- src/lib/ecore_evas/ecore_evas_private.h | 20 + src/lib/ecore_x/Ecore_X.h | 13 + src/lib/ecore_x/Ecore_X_Atoms.h | 10 + src/lib/ecore_x/ecore_x_atoms_decl.h | 21 +- src/lib/ecore_x/xcb/ecore_xcb_e.c | 289 +++++++++++++ src/lib/ecore_x/xlib/ecore_x_e.c | 278 ++++++++++++ .../engines/cocoa/ecore_evas_cocoa.c | 10 +- .../ecore_evas/engines/drm/ecore_evas_drm.c | 10 +- .../ecore_evas/engines/extn/ecore_evas_extn.c | 14 +- .../ecore_evas/engines/fb/ecore_evas_fb.c | 10 +- .../engines/psl1ght/ecore_evas_psl1ght.c | 10 +- .../ecore_evas/engines/sdl/ecore_evas_sdl.c | 10 +- .../engines/wayland/ecore_evas_wayland_egl.c | 7 +- .../engines/wayland/ecore_evas_wayland_shm.c | 7 +- .../engines/win32/ecore_evas_win32.c | 10 +- .../ecore_evas/engines/x/ecore_evas_x.c | 396 +++++++++++++++--- 21 files changed, 1302 insertions(+), 79 deletions(-) diff --git a/ChangeLog b/ChangeLog index a772e501d2..6c1bd85175 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2014-02-09 Gwanglim Lee + + * Ecore_Evas: Added window manager rotation to manage the rotation of + windows by the WM. + - add ecore_evas_wm_rotation_supported_get + - add ecore_evas_wm_rotation_preferred_rotation_set + - add ecore_evas_wm_rotation_preferred_rotation_get + - add ecore_evas_wm_rotation_available_rotations_set + - add ecore_evas_wm_rotation_available_rotations_get + - add ecore_evas_wm_rotation_manual_rotation_done_set + - add ecore_evas_wm_rotation_manual_rotation_done_get + - add ecore_evas_wm_rotation_manual_rotation_done + 2013-12-02 Daniel Juyung Seo (SeoZ) * Check ecore_x_window_prop_card32_get() return value correctly in ecore_x_e. diff --git a/src/lib/ecore_evas/Ecore_Evas.h b/src/lib/ecore_evas/Ecore_Evas.h index 3625316549..2ef08e50f3 100644 --- a/src/lib/ecore_evas/Ecore_Evas.h +++ b/src/lib/ecore_evas/Ecore_Evas.h @@ -683,6 +683,87 @@ EAPI void ecore_evas_window_available_profiles_set(Ecore_Evas *ee, const * @since 1.8.0 */ EAPI Eina_Bool ecore_evas_window_available_profiles_get(Ecore_Evas *ee, char ***profiles, unsigned int *count); +/** + * @brief Query if the underlying windowing system supports the window manager rotation. + * + * @param ee The Ecore_Evas + * @return @c EINA_TRUE if the window manager rotation is supported, @c EINA_FALSE otherwise. + * + * @warning Support for this depends on the underlying windowing system. + * @since 1.9.0 + */ +EAPI Eina_Bool ecore_evas_wm_rotation_supported_get(const Ecore_Evas *ee); +/** + * @brief Set the preferred rotation hint. + * + * @param ee The Ecore_Evas to set + * @param rotation Value to set the preferred rotation hint + * + * @warning Support for this depends on the underlying windowing system. + * @since 1.9.0 + */ +EAPI void ecore_evas_wm_rotation_preferred_rotation_set(Ecore_Evas *ee, int rotation); +/** + * @brief Get the preferred rotation hint. + * + * @param ee The Ecore_Evas to get the preferred rotation hint from. + * @return The preferred rotation hint, -1 on failure. + * + * @warning Support for this depends on the underlying windowing system. + * @since 1.9.0 + */ +EAPI int ecore_evas_wm_rotation_preferred_rotation_get(const Ecore_Evas *ee); +/** + * @brief Set the array of available window rotations. + * + * @param ee The Ecore_Evas to set + * @param rotations The integer array of available window rotations + * @param count The number of members in rotations + * + * @warning Support for this depends on the underlying windowing system. + * @since 1.9.0 + */ +EAPI void ecore_evas_wm_rotation_available_rotations_set(Ecore_Evas *ee, const int *rotations, unsigned int count); +/** + * @brief Get the array of available window rotations. + * + * @param ee The Ecore_Evas to get available window rotations from. + * @param rotations Where to return the integer array of available window rotations + * @param count Where to return the number of members in rotations + * @return EINA_TRUE if available window rotations exist, EINA_FALSE otherwise + * + * @warning Support for this depends on the underlying windowing system. + * @since 1.9.0 + */ +EAPI Eina_Bool ecore_evas_wm_rotation_available_rotations_get(const Ecore_Evas *ee, int **rotations, unsigned int *count); +/** + * @brief Set manual rotation done mode of Ecore_Evas's window + * + * @param ee The Ecore_Evas + * @param set If true, the window manager will not rotate the Ecore_Evas's window until + * the rotation done event is received by ecore_evas_wm_rotation_manual_rotation_done. + * If false, the manual rotation mode is disabled. + * + * @since 1.9.0 + */ +EAPI void ecore_evas_wm_rotation_manual_rotation_done_set(Ecore_Evas *ee, Eina_Bool set); +/** + * @brief Get manual rotation done mode of Ecore_Evas's window + * + * @param ee The Ecore_Evas + * @return If true, the manual rotation done mode is enabled + * + * @since 1.9.0 + */ +EAPI Eina_Bool ecore_evas_wm_rotation_manual_rotation_done_get(const Ecore_Evas *ee); +/** + * @brief Set rotation finish manually + * + * @param ee The Ecore_Evas + * + * @since 1.9.0 + */ +EAPI void ecore_evas_wm_rotation_manual_rotation_done(Ecore_Evas *ee); /** * @brief Send message to parent ecore * diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c index 37be5f8a76..43e4b8691f 100644 --- a/src/lib/ecore_evas/ecore_evas.c +++ b/src/lib/ecore_evas/ecore_evas.c @@ -1946,6 +1946,153 @@ ecore_evas_window_available_profiles_get(Ecore_Evas *ee, char ***profiles, unsig return EINA_FALSE; } +EAPI Eina_Bool +ecore_evas_wm_rotation_supported_get(const Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_supported_get"); + return EINA_FALSE; + } + return ee->prop.wm_rot.supported; +} + +EAPI void +ecore_evas_wm_rotation_preferred_rotation_set(Ecore_Evas *ee, int rotation) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_preferred_rotation_set"); + return; + } + if (rotation != -1) + { + if (ee->prop.wm_rot.available_rots) + { + Eina_Bool found = EINA_FALSE; + unsigned int i; + for (i = 0; i < ee->prop.wm_rot.count; i++) + { + if (ee->prop.wm_rot.available_rots[i] == rotation) + { + found = EINA_TRUE; + break; + } + } + if (!found) return; + } + } + IFC(ee, fn_wm_rot_preferred_rotation_set) (ee, rotation); + IFE; +} + +EAPI int +ecore_evas_wm_rotation_preferred_rotation_get(const Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_preferred_rotation_get"); + return -1; + } + return ee->prop.wm_rot.preferred_rot; +} + +EAPI void +ecore_evas_wm_rotation_available_rotations_set(Ecore_Evas *ee, const int *rotations, unsigned int count) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_available_rotations_set"); + return; + } + IFC(ee, fn_wm_rot_available_rotations_set) (ee, rotations, count); + IFE; +} + +EAPI Eina_Bool +ecore_evas_wm_rotation_available_rotations_get(const Ecore_Evas *ee, int **rotations, unsigned int *count) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_available_rotations_get"); + return EINA_FALSE; + } + if ((!rotations) || (!count)) + return EINA_FALSE; + + if ((!ee->prop.wm_rot.available_rots) || (ee->prop.wm_rot.count == 0)) + return EINA_FALSE; + + *rotations = calloc(ee->prop.wm_rot.count, sizeof(int)); + if (!*rotations) return EINA_FALSE; + + memcpy(*rotations, ee->prop.wm_rot.available_rots, sizeof(int) * ee->prop.wm_rot.count); + *count = ee->prop.wm_rot.count; + + return EINA_TRUE; +} + +EAPI void +ecore_evas_wm_rotation_manual_rotation_done_set(Ecore_Evas *ee, Eina_Bool set) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_manual_rotation_done_set"); + return; + } + + if (!ee->prop.wm_rot.app_set) + { + return; + } + + IFC(ee, fn_wm_rot_manual_rotation_done_set) (ee, set); + IFE; +} + +EAPI Eina_Bool +ecore_evas_wm_rotation_manual_rotation_done_get(const Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_manual_rotation_done_get"); + return EINA_FALSE; + } + + if (!ee->prop.wm_rot.app_set) + { + return EINA_FALSE; + } + + return ee->prop.wm_rot.manual_mode.set; +} + +EAPI void +ecore_evas_wm_rotation_manual_rotation_done(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_wm_rotation_manual_rotation_done"); + return; + } + + if (!ee->prop.wm_rot.app_set) + { + return; + } + + IFC(ee, fn_wm_rot_manual_rotation_done) (ee); + IFE; +} + EAPI void ecore_evas_fullscreen_set(Ecore_Evas *ee, Eina_Bool on) { @@ -2703,6 +2850,11 @@ _ecore_evas_free(Ecore_Evas *ee) ee->prop.profile.name = NULL; _ecore_evas_window_available_profiles_free(ee); ee->prop.profile.available_list = NULL; + if (ee->prop.wm_rot.available_rots) free(ee->prop.wm_rot.available_rots); + ee->prop.wm_rot.available_rots = NULL; + if (ee->prop.wm_rot.manual_mode.timer) + ecore_timer_del(ee->prop.wm_rot.manual_mode.timer); + ee->prop.wm_rot.manual_mode.timer = NULL; if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object); ee->prop.cursor.object = NULL; if (ee->evas) evas_free(ee->evas); diff --git a/src/lib/ecore_evas/ecore_evas_buffer.c b/src/lib/ecore_evas/ecore_evas_buffer.c index 0b9e124ac5..5c4a739ba7 100644 --- a/src/lib/ecore_evas/ecore_evas_buffer.c +++ b/src/lib/ecore_evas/ecore_evas_buffer.c @@ -581,7 +581,15 @@ static Ecore_Evas_Engine_Func _ecore_buffer_engine_func = NULL, // screen_geometry_get NULL, // screen_dpi_get _ecore_evas_buffer_msg_parent_send, - _ecore_evas_buffer_msg_send + _ecore_evas_buffer_msg_send, + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; static void * diff --git a/src/lib/ecore_evas/ecore_evas_ews.c b/src/lib/ecore_evas/ecore_evas_ews.c index 9aa1dba319..84c9a0f495 100644 --- a/src/lib/ecore_evas/ecore_evas_ews.c +++ b/src/lib/ecore_evas/ecore_evas_ews.c @@ -698,7 +698,15 @@ static const Ecore_Evas_Engine_Func _ecore_ews_engine_func = _ecore_evas_ews_screen_geometry_get, NULL, // screen_dpi_get NULL, - NULL // msg_send + NULL, // msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; void diff --git a/src/lib/ecore_evas/ecore_evas_private.h b/src/lib/ecore_evas/ecore_evas_private.h index ca7a801a13..cc514d5d8e 100644 --- a/src/lib/ecore_evas/ecore_evas_private.h +++ b/src/lib/ecore_evas/ecore_evas_private.h @@ -115,6 +115,11 @@ struct _Ecore_Evas_Engine_Func /* 1.8 abstractions */ void (*fn_pointer_xy_get) (const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y); Eina_Bool (*fn_pointer_warp) (const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y); + + void (*fn_wm_rot_preferred_rotation_set) (Ecore_Evas *ee, int rot); + void (*fn_wm_rot_available_rotations_set) (Ecore_Evas *ee, const int *rots, unsigned int count); + void (*fn_wm_rot_manual_rotation_done_set) (Ecore_Evas *ee, Eina_Bool set); + void (*fn_wm_rot_manual_rotation_done) (Ecore_Evas *ee); }; struct _Ecore_Evas_Interface @@ -186,6 +191,21 @@ struct _Ecore_Evas int x, y; } hot; } cursor; + struct { + Eina_Bool supported; // indicate that the underlying window system supports window manager rotation protocol + Eina_Bool app_set; // indicate that the ee supports window manager rotation protocol + Eina_Bool win_resize; // indicate that the ee will be resized by the WM + int angle; // rotation value which is decided by the WM + int w, h; // window size to rotate + int preferred_rot; // preferred rotation hint + int *available_rots; // array of avaialable rotation values + unsigned int count; // number of elements of available_rots + struct { + Eina_Bool set; + Eina_Bool wait_for_done; + Ecore_Timer *timer; + } manual_mode; + } wm_rot; int layer; Ecore_Window window; unsigned char avoid_damage; diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h index 71b7a73859..0d042791d4 100644 --- a/src/lib/ecore_x/Ecore_X.h +++ b/src/lib/ecore_x/Ecore_X.h @@ -2677,6 +2677,19 @@ EAPI void ecore_x_e_illume_window_state_send(Ec EAPI void ecore_x_xkb_select_group(int group); /* @since 1.7 */ +EAPI void ecore_x_e_window_rotation_supported_set(Ecore_X_Window root, Eina_Bool enabled); /**< @since 1.9 */ +EAPI Eina_Bool ecore_x_e_window_rotation_supported_get(Ecore_X_Window root); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_app_set(Ecore_X_Window win, Eina_Bool set); /**< @since 1.9 */ +EAPI Eina_Bool ecore_x_e_window_rotation_app_get(Ecore_X_Window win); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_preferred_rotation_set(Ecore_X_Window win, int rot); /**< @since 1.9 */ +EAPI Eina_Bool ecore_x_e_window_rotation_preferred_rotation_get(Ecore_X_Window win, int *rot); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_available_rotations_set(Ecore_X_Window win, const int *rots, unsigned int count); /**< @since 1.9 */ +EAPI Eina_Bool ecore_x_e_window_rotation_available_rotations_get(Ecore_X_Window win, int **rots, unsigned int *count); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_change_prepare_send(Ecore_X_Window win, int rot, Eina_Bool resize, int w, int h); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_change_prepare_done_send(Ecore_X_Window root, Ecore_X_Window win, int rot); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_change_request_send(Ecore_X_Window win, int rot); /**< @since 1.9 */ +EAPI void ecore_x_e_window_rotation_change_done_send(Ecore_X_Window root, Ecore_X_Window win, int rot, int w, int h); /**< @since 1.9 */ + #ifdef __cplusplus } #endif // ifdef __cplusplus diff --git a/src/lib/ecore_x/Ecore_X_Atoms.h b/src/lib/ecore_x/Ecore_X_Atoms.h index 59061cf56b..6c028e6582 100644 --- a/src/lib/ecore_x/Ecore_X_Atoms.h +++ b/src/lib/ecore_x/Ecore_X_Atoms.h @@ -312,4 +312,14 @@ EAPI extern Ecore_X_Atom ECORE_X_ATOM_SDB_SERVER_DISCONNECT; /* for deiconify approve protcol */ EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_DEICONIFY_APPROVE; + +/* E window rotation extension */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE; #endif /* _ECORE_X_ATOMS_H */ diff --git a/src/lib/ecore_x/ecore_x_atoms_decl.h b/src/lib/ecore_x/ecore_x_atoms_decl.h index 80c555c93a..a1f7ecbb85 100644 --- a/src/lib/ecore_x/ecore_x_atoms_decl.h +++ b/src/lib/ecore_x/ecore_x_atoms_decl.h @@ -342,6 +342,16 @@ EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_DONE = 0; /* for deiconify approve protcol */ EAPI Ecore_X_Atom ECORE_X_ATOM_E_DEICONIFY_APPROVE = 0; +/* E window rotation extension */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE = 0; + typedef struct _Atom_Item Atom_Item; struct _Atom_Item @@ -641,6 +651,15 @@ const Atom_Item atom_items[] = { "_E_WINDOW_PROFILE_CHANGE_REQUEST", &ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_REQUEST }, { "_E_WINDOW_PROFILE_CHANGE_DONE", &ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_DONE }, - { "_E_DEICONIFY_APPROVE", &ECORE_X_ATOM_E_DEICONIFY_APPROVE } + { "_E_DEICONIFY_APPROVE", &ECORE_X_ATOM_E_DEICONIFY_APPROVE }, + + { "_E_WINDOW_ROTATION_SUPPORTED", &ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED }, + { "_E_WINDOW_ROTATION_APP_SUPPORTED", &ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED }, + { "_E_WINDOW_ROTATION_AVAILABLE_LIST", &ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST }, + { "_E_WINDOW_ROTATION_PREFERRED_ROTATION", &ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION }, + { "_E_WINDOW_ROTATION_CHANGE_PREPARE", &ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE }, + { "_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE", &ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE }, + { "_E_WINDOW_ROTATION_CHANGE_REQUEST", &ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST }, + { "_E_WINDOW_ROTATION_CHANGE_DONE", &ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE } }; diff --git a/src/lib/ecore_x/xcb/ecore_xcb_e.c b/src/lib/ecore_x/xcb/ecore_xcb_e.c index b85659ed84..4249bb90fe 100644 --- a/src/lib/ecore_x/xcb/ecore_xcb_e.c +++ b/src/lib/ecore_x/xcb/ecore_xcb_e.c @@ -1942,3 +1942,292 @@ ecore_x_e_illume_window_state_send(Ecore_X_Window win, _ecore_x_e_illume_window_state_atom_get(state), 0, 0, 0, 0); } + +EAPI void +ecore_x_e_window_rotation_supported_set(Ecore_X_Window root, + Eina_Bool enabled) +{ + Ecore_X_Window win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + if (enabled) + { + win = ecore_x_window_new(root, 1, 2, 3, 4); + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + ecore_x_window_prop_xid_set(root, ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + } + else + { + int ret; + + ret = + ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win, 1); + if ((ret == 1) && (win)) + { + ecore_x_window_prop_property_del( + root, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED); + ecore_x_window_free(win); + } + } +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_supported_get(Ecore_X_Window root) +{ + Ecore_X_Window win, win2; + int ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ret = + ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win, 1); + if ((ret == 1) && (win)) + { + ret = + ecore_x_window_prop_xid_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win2, 1); + if ((ret == 1) && (win2 == win)) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_app_set(Ecore_X_Window win, + Eina_Bool set) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (set) val = 1; + + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED, + &val, 1); +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_app_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_preferred_rotation_set(Ecore_X_Window win, + int rot) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (rot != -1) + { + val = (unsigned int)rot; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION, + &val, 1); + } + else + { + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION); + } +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_preferred_rotation_get(Ecore_X_Window win, + int *rot) +{ + unsigned int val = 0; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION, + &val, 1); + if (ret == 1) + { + if (rot) *rot = (int)val; + return EINA_TRUE; + } + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_available_rotations_set(Ecore_X_Window win, + const int *rots, + unsigned int count) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + + if ((rots) && (count > 0)) + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST, + (unsigned int *)rots, count); + else + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST); +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_available_rotations_get(Ecore_X_Window win, + int **rots, + unsigned int *count) +{ + unsigned char *data = NULL; + int num, i; + int *val = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!win) || (!rots) || (!count)) + return EINA_FALSE; + + *rots = NULL; + *count = 0; + + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST, + XA_CARDINAL, 32, &data, &num)) + return EINA_FALSE; + + *count = num; + + if ((num >= 1) && (data)) + { + val = calloc(num, sizeof(int)); + if (!val) + { + *counter = 0; + if (data) free(data); + return EINA_FALSE; + } + for (i = 0; i < num; i++) + val[i] = ((int *)data)[i]; + if (data) free(data); + *rots = val; + return EINA_TRUE; + } + if (data) free(data); + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_change_prepare_send(Ecore_X_Window win, + int rot, + Eina_Bool resize, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE, + ECORE_X_EVENT_MASK_NONE, + win, rot, resize, w, h); +} + +EAPI void +ecore_x_e_window_rotation_change_prepare_done_send(Ecore_X_Window root, + Ecore_X_Window win, + int rot) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE; + ev.data.data32[0] = win; + ev.data.data32[1] = rot; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +} + +EAPI void +ecore_x_e_window_rotation_change_request_send(Ecore_X_Window win, + int rot) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST, + ECORE_X_EVENT_MASK_NONE, + win, rot, 0, 0, 0); +} + +EAPI void +ecore_x_e_window_rotation_change_done_send(Ecore_X_Window root, + Ecore_X_Window win, + int rot, + int w, + int h) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE; + ev.data.data32[0] = win; + ev.data.data32[1] = rot; + ev.data.data32[2] = w; + ev.data.data32[3] = h; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +} diff --git a/src/lib/ecore_x/xlib/ecore_x_e.c b/src/lib/ecore_x/xlib/ecore_x_e.c index 42380c0c09..f11da7d121 100644 --- a/src/lib/ecore_x/xlib/ecore_x_e.c +++ b/src/lib/ecore_x/xlib/ecore_x_e.c @@ -2027,3 +2027,281 @@ ecore_x_e_illume_window_state_send(Ecore_X_Window win, _ecore_x_e_illume_window_state_atom_get(state), 0, 0, 0, 0); } + +EAPI void +ecore_x_e_window_rotation_supported_set(Ecore_X_Window root, + Eina_Bool enabled) +{ + Ecore_X_Window win; + + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (enabled) + { + win = ecore_x_window_new(root, 1, 2, 3, 4); + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + ecore_x_window_prop_xid_set(root, ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + } + else + { + int ret; + + ret = + ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win, 1); + if ((ret == 1) && (win)) + { + ecore_x_window_prop_property_del( + root, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED); + ecore_x_window_free(win); + } + } +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_supported_get(Ecore_X_Window root) +{ + Ecore_X_Window win, win2; + int ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + ret = + ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win, 1); + if ((ret == 1) && (win)) + { + ret = + ecore_x_window_prop_xid_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win2, 1); + if ((ret == 1) && (win2 == win)) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_app_set(Ecore_X_Window win, + Eina_Bool set) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (set) val = 1; + + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED, + &val, 1); +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_app_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_preferred_rotation_set(Ecore_X_Window win, + int rot) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (rot != -1) + { + val = (unsigned int)rot; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION, + &val, 1); + } + else + { + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION); + } +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_preferred_rotation_get(Ecore_X_Window win, + int *rot) +{ + unsigned int val = 0; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION, + &val, 1); + if (ret == 1) + { + if (rot) *rot = (int)val; + return EINA_TRUE; + } + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_available_rotations_set(Ecore_X_Window win, + const int *rots, + unsigned int count) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + + if ((rots) && (count > 0)) + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST, + (unsigned int *)rots, count); + else + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST); +} + +EAPI Eina_Bool +ecore_x_e_window_rotation_available_rotations_get(Ecore_X_Window win, + int **rots, + unsigned int *count) +{ + unsigned char *data = NULL; + int num, i; + int *val = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((!win) || (!rots) || (!count)) + return EINA_FALSE; + + *rots = NULL; + *count = 0; + + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST, + XA_CARDINAL, 32, &data, &num)) + return EINA_FALSE; + + *count = num; + + if ((num >= 1) && (data)) + { + val = calloc(num, sizeof(int)); + if (!val) + { + if (data) XFree(data); + return EINA_FALSE; + } + for (i = 0; i < num; i++) + val[i] = ((int *)data)[i]; + if (data) XFree(data); + *rots = val; + return EINA_TRUE; + } + if (data) XFree(data); + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_rotation_change_prepare_send(Ecore_X_Window win, + int rot, + Eina_Bool resize, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send + (win, ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE, + ECORE_X_EVENT_MASK_NONE, + win, rot, resize, w, h); +} + +EAPI void +ecore_x_e_window_rotation_change_prepare_done_send(Ecore_X_Window root, + Ecore_X_Window win, + int rot) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = rot; + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(_ecore_x_disp, root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_window_rotation_change_request_send(Ecore_X_Window win, + int rot) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send + (win, ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST, + ECORE_X_EVENT_MASK_NONE, + win, rot, 0, 0, 0); +} + +EAPI void +ecore_x_e_window_rotation_change_done_send(Ecore_X_Window root, + Ecore_X_Window win, + int rot, + int w, + int h) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = rot; + xev.xclient.data.l[2] = w; + xev.xclient.data.l[3] = h; + xev.xclient.data.l[4] = 0; + + XSendEvent(_ecore_x_disp, root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} diff --git a/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c b/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c index 4079c11791..d54737eb1a 100644 --- a/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c +++ b/src/modules/ecore_evas/engines/cocoa/ecore_evas_cocoa.c @@ -473,7 +473,15 @@ static Ecore_Evas_Engine_Func _ecore_cocoa_engine_func = NULL, NULL, // screen_dpi_get NULL, - NULL // msg_send + NULL, // msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; EAPI Ecore_Evas * diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c index be62c795f5..ec6afa691d 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -96,7 +96,15 @@ static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = NULL, //void (*fn_screen_geometry_get) (const Ecore_Evas *ee, int *x, int *y, int *w, int *h); NULL, //void (*fn_screen_dpi_get) (const Ecore_Evas *ee, int *xdpi, int *ydpi); NULL, //void (*fn_msg_parent_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); - NULL //void (*fn_msg_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); + NULL, //void (*fn_msg_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; EAPI Ecore_Evas * diff --git a/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c b/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c index 9e08555783..221a7de639 100644 --- a/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c +++ b/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c @@ -877,7 +877,12 @@ static const Ecore_Evas_Engine_Func _ecore_extn_plug_engine_func = /* 1.8 abstractions */ NULL, // pointer_xy_get - NULL // pointer_warp + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; static Eina_Bool @@ -1997,7 +2002,12 @@ static const Ecore_Evas_Engine_Func _ecore_extn_socket_engine_func = /* 1.8 abstractions */ NULL, // pointer_xy_get - NULL // pointer_warp + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; EAPI Ecore_Evas * diff --git a/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c b/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c index 3f075367e5..9d999e228c 100644 --- a/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c +++ b/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c @@ -564,7 +564,15 @@ static Ecore_Evas_Engine_Func _ecore_fb_engine_func = NULL, // screen_geometry_get NULL, // screen_dpi_get NULL, - NULL // msg_send + NULL, // msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; EAPI Ecore_Evas * diff --git a/src/modules/ecore_evas/engines/psl1ght/ecore_evas_psl1ght.c b/src/modules/ecore_evas/engines/psl1ght/ecore_evas_psl1ght.c index a0fe244bd7..bd09d14565 100644 --- a/src/modules/ecore_evas/engines/psl1ght/ecore_evas_psl1ght.c +++ b/src/modules/ecore_evas/engines/psl1ght/ecore_evas_psl1ght.c @@ -407,7 +407,15 @@ static Ecore_Evas_Engine_Func _ecore_psl1ght_engine_func = _ecore_evas_screen_geometry_get, // screen_geometry_get NULL, // screen_dpi_get NULL, - NULL //msg_send + NULL, //msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; EAPI Ecore_Evas * diff --git a/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c b/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c index f8f4827be7..ede7872317 100644 --- a/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c +++ b/src/modules/ecore_evas/engines/sdl/ecore_evas_sdl.c @@ -447,7 +447,15 @@ static Ecore_Evas_Engine_Func _ecore_sdl_engine_func = NULL, // screen_geometry_get NULL, // screen_dpi_get NULL, - NULL // msg_send + NULL, // msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; static Ecore_Evas* diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c index bb9213c9ca..eaaa16b9ca 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c @@ -79,7 +79,12 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func = NULL, // msg_send _ecore_evas_wl_common_pointer_xy_get, - NULL // pointer warp + NULL, // pointer warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; /* external variables */ diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c index cdafd6695c..c873acef78 100644 --- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c +++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_shm.c @@ -79,7 +79,12 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func = NULL, // func msg send _ecore_evas_wl_common_pointer_xy_get, - NULL // pointer_warp + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; /* external variables */ diff --git a/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c b/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c index 4f73a2ba80..bbcfae228b 100644 --- a/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c +++ b/src/modules/ecore_evas/engines/win32/ecore_evas_win32.c @@ -1133,7 +1133,15 @@ static Ecore_Evas_Engine_Func _ecore_win32_engine_func = NULL, // screen_geometry_get _ecore_evas_win32_screen_dpi_get, NULL, - NULL // msg_send + NULL, // msg_send + + NULL, // pointer_xy_get + NULL, // pointer_warp + + NULL, // wm_rot_preferred_rotation_set + NULL, // wm_rot_available_rotations_set + NULL, // wm_rot_manual_rotation_done_set + NULL // wm_rot_manual_rotation_done }; #endif /* BUILD_ECORE_EVAS_WIN32 */ diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c index 0aa50f02d2..2a33fc8265 100644 --- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c +++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c @@ -88,6 +88,14 @@ struct _Ecore_Evas_Engine_Data_X11 { unsigned char change : 1; // need to send change event to the WM unsigned char done : 1; // need to send change done event to the WM } profile; + struct { + unsigned char supported: 1; + unsigned char prepare : 1; + unsigned char request : 1; + unsigned char done : 1; + unsigned char configure_coming : 1; + Ecore_Job *manual_mode_job; + } wm_rot; Ecore_X_Window win_shaped_input; struct { @@ -107,6 +115,9 @@ static Ecore_Evas_Interface_Software_X11 *_ecore_evas_x_interface_software_x11_n #ifdef BUILD_ECORE_EVAS_OPENGL_X11 static Ecore_Evas_Interface_Gl_X11 *_ecore_evas_x_interface_gl_x11_new(void); #endif +static void _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize); +static Eina_Bool _ecore_evas_x_wm_rot_manual_rotation_done_timeout(void *data); +static void _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(Ecore_Evas *ee); static void _resize_shape_do(Ecore_Evas *); static void _shaped_do(Ecore_Evas *, int); @@ -243,6 +254,17 @@ _ecore_evas_x_sync_clear(Ecore_Evas *ee) edata->sync_counter = 0; } +static void +_ecore_evas_x_wm_rotation_protocol_set(Ecore_Evas *ee) +{ + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + + if (ecore_x_e_window_rotation_supported_get(edata->win_root)) + ee->prop.wm_rot.supported = 1; + else + ee->prop.wm_rot.supported = 0; +} + static void _ecore_evas_x_window_profile_protocol_set(Ecore_Evas *ee) { @@ -304,6 +326,21 @@ _ecore_evas_x_window_profile_set(Ecore_Evas *ee) } } +static void +_ecore_evas_x_wm_rot_manual_rotation_done_job(void *data) +{ + Ecore_Evas *ee = (Ecore_Evas *)data; + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + + edata->wm_rot.manual_mode_job = NULL; + ee->prop.wm_rot.manual_mode.wait_for_done = EINA_FALSE; + + ecore_x_e_window_rotation_change_done_send + (edata->win_root, ee->prop.window, ee->rotation, ee->w, ee->h); + + edata->wm_rot.done = 0; +} + # ifdef BUILD_ECORE_EVAS_OPENGL_X11 static Ecore_X_Window _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, int w, int h, Eina_Bool override, int argb, const int *opt) @@ -1034,6 +1071,63 @@ _ecore_evas_x_event_client_message(void *data EINA_UNUSED, int type EINA_UNUSED, e->win, 1, 0, 0, 0); } + else if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) + { + ee = ecore_event_window_match(e->data.l[0]); + if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */ + edata = ee->engine.data; + if (e->data.l[0] != (long)ee->prop.window) + return ECORE_CALLBACK_PASS_ON; + if (ee->prop.wm_rot.supported) + { + if (ee->prop.wm_rot.app_set) + { + ee->prop.wm_rot.angle = (int)e->data.l[1]; + ee->prop.wm_rot.win_resize = (int)e->data.l[2]; + ee->prop.wm_rot.w = (int)e->data.l[3]; + ee->prop.wm_rot.h = (int)e->data.l[4]; + if (ee->prop.wm_rot.win_resize) + edata->wm_rot.configure_coming = 1; + edata->wm_rot.prepare = 1; + edata->wm_rot.request = 0; + edata->wm_rot.done = 0; + } + } + } + else if (e->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) + { + ee = ecore_event_window_match(e->data.l[0]); + if (!ee) return ECORE_CALLBACK_PASS_ON; /* pass on event */ + edata = ee->engine.data; + if (e->data.l[0] != (long)ee->prop.window) + return ECORE_CALLBACK_PASS_ON; + if (ee->prop.wm_rot.supported) + { + if (ee->prop.wm_rot.app_set) + { + edata->wm_rot.prepare = 0; + edata->wm_rot.request = 1; + edata->wm_rot.done = 0; + if (ee->prop.wm_rot.win_resize) + { + if ((ee->w == ee->prop.wm_rot.w) && + (ee->h == ee->prop.wm_rot.h)) + { + edata->wm_rot.configure_coming = 0; + } + } + if (!edata->wm_rot.configure_coming) + { + if (ee->prop.wm_rot.manual_mode.set) + { + ee->prop.wm_rot.manual_mode.wait_for_done = EINA_TRUE; + _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(ee); + } + _ecore_evas_x_rotation_set(ee, ee->prop.wm_rot.angle, 1); + } + } + } + } return ECORE_CALLBACK_PASS_ON; } @@ -1403,6 +1497,35 @@ _ecore_evas_x_event_window_configure(void *data EINA_UNUSED, int type EINA_UNUSE ee->expecting_resize.h = 0; } if (ee->func.fn_resize) ee->func.fn_resize(ee); + + if (ee->prop.wm_rot.supported) + { + if (edata->wm_rot.prepare) + { + if ((ee->prop.wm_rot.w == e->w) && + (ee->prop.wm_rot.h == e->h)) + { + edata->wm_rot.configure_coming = 0; + } + } + else if (edata->wm_rot.request) + { + if ((edata->wm_rot.configure_coming) && + (ee->prop.wm_rot.w == e->w) && + (ee->prop.wm_rot.h == e->h)) + { + edata->wm_rot.configure_coming = 0; + if (ee->prop.wm_rot.manual_mode.set) + { + ee->prop.wm_rot.manual_mode.wait_for_done = EINA_TRUE; + _ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(ee); + } + _ecore_evas_x_rotation_set(ee, + ee->prop.wm_rot.angle, + EINA_TRUE); + } + } + } } return ECORE_CALLBACK_PASS_ON; } @@ -1714,6 +1837,11 @@ _ecore_evas_x_free(Ecore_Evas *ee) ecore_x_pixmap_free(edata->pixmap.back); if (edata->pixmap.front) ecore_x_pixmap_free(edata->pixmap.front); + if (edata->wm_rot.manual_mode_job) + { + ecore_job_del(edata->wm_rot.manual_mode_job); + edata->wm_rot.manual_mode_job = NULL; + } _ecore_evas_x_group_leader_unset(ee); if (edata->sync_counter) @@ -2060,38 +2188,41 @@ _ecore_evas_x_rotation_set_internal(Ecore_Evas *ee, int rotation, int resize, } } -#define _USE_WIN_ROT_EFFECT 1 - -#if _USE_WIN_ROT_EFFECT -static void _ecore_evas_x_flush_pre(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED); - -typedef struct _Ecore_Evas_X_Rotation_Effect Ecore_Evas_X_Rotation_Effect; -struct _Ecore_Evas_X_Rotation_Effect +static Eina_Bool +_ecore_evas_x_wm_rotation_check(Ecore_Evas *ee) { - Eina_Bool wait_for_comp_reply; -}; - -static Ecore_Evas_X_Rotation_Effect _rot_effect = -{ - EINA_FALSE -}; - -static void -_ecore_evas_x_rotation_effect_setup(void) -{ - _rot_effect.wait_for_comp_reply = EINA_TRUE; + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + if (ee->prop.wm_rot.supported) + { + if (ee->prop.wm_rot.app_set) + { + if (edata->wm_rot.request) + { + if (ee->prop.wm_rot.win_resize) + { + if (!((ee->w == ee->prop.wm_rot.w) && + (ee->h == ee->prop.wm_rot.h))) + { + return EINA_FALSE; + } + else + edata->wm_rot.configure_coming = 0; + } + } + } + } + return EINA_TRUE; } -#endif /* end of _USE_WIN_ROT_EFFECT */ static void _rotation_do(Ecore_Evas *ee, int rotation, int resize) { #ifdef BUILD_ECORE_EVAS_SOFTWARE_X11 -#if _USE_WIN_ROT_EFFECT - int angles[2]; - angles[0] = rotation; - angles[1] = ee->rotation; -#endif /* end of _USE_WIN_ROT_EFFECT */ + if (ee->prop.wm_rot.supported) + { + if (!_ecore_evas_x_wm_rotation_check(ee)) return; + if (!resize) resize = 1; + } Evas_Engine_Info_Software_X11 *einfo; Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; @@ -2100,25 +2231,23 @@ _rotation_do(Ecore_Evas *ee, int rotation, int resize) einfo->info.rotation = rotation; _ecore_evas_x_rotation_set_internal(ee, rotation, resize, (Evas_Engine_Info *)einfo); -# if _USE_WIN_ROT_EFFECT + if (ee->prop.wm_rot.supported) + { + if (ee->prop.wm_rot.app_set) + { + if (edata->wm_rot.request) + { + if (ee->func.fn_state_change) ee->func.fn_state_change(ee); + edata->wm_rot.request = 0; + edata->wm_rot.done = 1; + } + } + } + + int angles[2] = { rotation, rotation }; ecore_x_window_prop_property_set(ee->prop.window, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &angles, 2); - - if ((ee->visible) && - ((ecore_x_e_comp_sync_supported_get(edata->win_root)) && - (!ee->no_comp_sync) && (_ecore_evas_app_comp_sync)) && - (edata->sync_counter) && - (edata->sync_val > 0)) - { - _ecore_evas_x_rotation_effect_setup(); - _ecore_evas_x_flush_pre(ee, NULL, NULL); - } -# else - ecore_x_window_prop_property_set(ee->prop.window, - ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, - ECORE_X_ATOM_CARDINAL, 32, &rotation, 1); -# endif #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */ } @@ -2127,13 +2256,36 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize) { Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; - if (ee->rotation == rotation) return; + if (ee->rotation == rotation) + { + if (ee->prop.wm_rot.supported) + { + if (edata->wm_rot.request) + { + if (ee->prop.wm_rot.manual_mode.set) + { + ee->prop.wm_rot.manual_mode.wait_for_done = EINA_FALSE; + if (ee->prop.wm_rot.manual_mode.timer) + ecore_timer_del(ee->prop.wm_rot.manual_mode.timer); + ee->prop.wm_rot.manual_mode.timer = NULL; + } + /* send rotation done message to wm, even if window is already rotated. + * that's why wm must be wait for comming rotation done message + * after sending rotation request. + */ + ecore_x_e_window_rotation_change_done_send + (edata->win_root, ee->prop.window, ee->rotation, ee->w, ee->h); + edata->wm_rot.request = 0; + } + } + return; + } -#if _USE_WIN_ROT_EFFECT - int angles[2]; - angles[0] = rotation; - angles[1] = ee->rotation; -#endif /* end of _USE_WIN_ROT_EFFECT */ + if (ee->prop.wm_rot.supported) + { + if (!_ecore_evas_x_wm_rotation_check(ee)) return; + if (!resize) resize = 1; + } if (!strcmp(ee->driver, "opengl_x11")) { @@ -2145,15 +2297,23 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize) einfo->info.rotation = rotation; _ecore_evas_x_rotation_set_internal(ee, rotation, resize, (Evas_Engine_Info *)einfo); -# if _USE_WIN_ROT_EFFECT + if (ee->prop.wm_rot.supported) + { + if (ee->prop.wm_rot.app_set) + { + if (edata->wm_rot.request) + { + if (ee->func.fn_state_change) ee->func.fn_state_change(ee); + edata->wm_rot.request = 0; + edata->wm_rot.done = 1; + } + } + } + + int angles[2] = { rotation, rotation }; ecore_x_window_prop_property_set(ee->prop.window, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &angles, 2); -# else - ecore_x_window_prop_property_set(ee->prop.window, - ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, - ECORE_X_ATOM_CARDINAL, 32, &rotation, 1); -# endif #endif /* BUILD_ECORE_EVAS_OPENGL_X11 */ } else if (!strcmp(ee->driver, "software_x11")) @@ -2168,18 +2328,6 @@ _ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation, int resize) _rotation_do(ee, rotation, resize); return; } - -#if _USE_WIN_ROT_EFFECT - if ((ee->visible) && - ((ecore_x_e_comp_sync_supported_get(edata->win_root)) && - (!ee->no_comp_sync) && (_ecore_evas_app_comp_sync)) && - (edata->sync_counter) && - (edata->sync_val > 0)) - { - _ecore_evas_x_rotation_effect_setup(); - _ecore_evas_x_flush_pre(ee, NULL, NULL); - } -#endif /* end of _USE_WIN_ROT_EFFECT */ } static void @@ -2330,6 +2478,7 @@ _alpha_do(Ecore_Evas *ee, int alpha) ecore_x_window_defaults_set(ee->prop.window); _ecore_evas_x_protocols_set(ee); _ecore_evas_x_window_profile_protocol_set(ee); + _ecore_evas_x_wm_rotation_protocol_set(ee); _ecore_evas_x_sync_set(ee); _ecore_evas_x_size_pos_hints_update(ee); #endif /* BUILD_ECORE_EVAS_SOFTWARE_X11 */ @@ -2481,6 +2630,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha) ecore_x_window_defaults_set(ee->prop.window); _ecore_evas_x_protocols_set(ee); _ecore_evas_x_window_profile_protocol_set(ee); + _ecore_evas_x_wm_rotation_protocol_set(ee); _ecore_evas_x_sync_set(ee); _ecore_evas_x_size_pos_hints_update(ee); #endif /* BUILD_ECORE_EVAS_OPENGL_X11 */ @@ -3156,6 +3306,103 @@ _ecore_evas_x_pointer_warp(const Ecore_Evas *ee, Evas_Coord x, Evas_Coord y) return ecore_x_pointer_warp(ee->prop.window, x, y); } +static void +_ecore_evas_x_wm_rot_preferred_rotation_set(Ecore_Evas *ee, int rot) +{ + if (ee->prop.wm_rot.supported) + { + if (!ee->prop.wm_rot.app_set) + { + ecore_x_e_window_rotation_app_set(ee->prop.window, EINA_TRUE); + ee->prop.wm_rot.app_set = EINA_TRUE; + } + ecore_x_e_window_rotation_preferred_rotation_set(ee->prop.window, rot); + ee->prop.wm_rot.preferred_rot = rot; + } +} + +static void +_ecore_evas_x_wm_rot_available_rotations_set(Ecore_Evas *ee, const int *rots, unsigned int count) +{ + if (ee->prop.wm_rot.supported) + { + if (!ee->prop.wm_rot.app_set) + { + ecore_x_e_window_rotation_app_set(ee->prop.window, EINA_TRUE); + ee->prop.wm_rot.app_set = EINA_TRUE; + } + + if (ee->prop.wm_rot.available_rots) + { + free(ee->prop.wm_rot.available_rots); + ee->prop.wm_rot.available_rots = NULL; + } + + ee->prop.wm_rot.count = 0; + + if (count > 0) + { + ee->prop.wm_rot.available_rots = calloc(count, sizeof(int)); + if (!ee->prop.wm_rot.available_rots) return; + + memcpy(ee->prop.wm_rot.available_rots, rots, sizeof(int) * count); + } + + ee->prop.wm_rot.count = count; + + ecore_x_e_window_rotation_available_rotations_set(ee->prop.window, rots, count); + } +} + +static void +_ecore_evas_x_wm_rot_manual_rotation_done_set(Ecore_Evas *ee, Eina_Bool set) +{ + ee->prop.wm_rot.manual_mode.set = set; +} + +static void +_ecore_evas_x_wm_rot_manual_rotation_done(Ecore_Evas *ee) +{ + Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; + + if ((ee->prop.wm_rot.supported) && + (ee->prop.wm_rot.app_set) && + (ee->prop.wm_rot.manual_mode.set)) + { + if (ee->prop.wm_rot.manual_mode.wait_for_done) + { + if (ee->prop.wm_rot.manual_mode.timer) + ecore_timer_del(ee->prop.wm_rot.manual_mode.timer); + ee->prop.wm_rot.manual_mode.timer = NULL; + + if (edata->wm_rot.manual_mode_job) + ecore_job_del(edata->wm_rot.manual_mode_job); + edata->wm_rot.manual_mode_job = ecore_job_add + (_ecore_evas_x_wm_rot_manual_rotation_done_job, ee); + } + } +} + +static Eina_Bool +_ecore_evas_x_wm_rot_manual_rotation_done_timeout(void *data) +{ + Ecore_Evas *ee = data; + + ee->prop.wm_rot.manual_mode.timer = NULL; + _ecore_evas_x_wm_rot_manual_rotation_done(ee); + return ECORE_CALLBACK_CANCEL; +} + +static void +_ecore_evas_x_wm_rot_manual_rotation_done_timeout_update(Ecore_Evas *ee) +{ + if (ee->prop.wm_rot.manual_mode.timer) + ecore_timer_del(ee->prop.wm_rot.manual_mode.timer); + + ee->prop.wm_rot.manual_mode.timer = ecore_timer_add + (4.0f, _ecore_evas_x_wm_rot_manual_rotation_done_timeout, ee); +} + static Ecore_Evas_Engine_Func _ecore_x_engine_func = { _ecore_evas_x_free, @@ -3221,7 +3468,12 @@ static Ecore_Evas_Engine_Func _ecore_x_engine_func = NULL, //fn_msg_send _ecore_evas_x_pointer_xy_get, - _ecore_evas_x_pointer_warp + _ecore_evas_x_pointer_warp, + + _ecore_evas_x_wm_rot_preferred_rotation_set, + _ecore_evas_x_wm_rot_available_rotations_set, + _ecore_evas_x_wm_rot_manual_rotation_done_set, + _ecore_evas_x_wm_rot_manual_rotation_done }; /* @@ -3415,6 +3667,16 @@ _ecore_evas_x_flush_post(void *data, Evas *e EINA_UNUSED, void *event_info EINA_ } edata->profile.done = 0; } + if ((ee->prop.wm_rot.supported) && + (edata->wm_rot.done)) + { + if (!ee->prop.wm_rot.manual_mode.set) + { + ecore_x_e_window_rotation_change_done_send + (edata->win_root, ee->prop.window, ee->rotation, ee->w, ee->h); + edata->wm_rot.done = 0; + } + } } #endif @@ -3610,6 +3872,7 @@ ecore_evas_software_x11_new_internal(const char *disp_name, Ecore_X_Window paren ecore_x_window_defaults_set(ee->prop.window); _ecore_evas_x_protocols_set(ee); _ecore_evas_x_window_profile_protocol_set(ee); + _ecore_evas_x_wm_rotation_protocol_set(ee); _ecore_evas_x_sync_set(ee); ee->engine.func->fn_render = _ecore_evas_x_render; @@ -4057,6 +4320,7 @@ ecore_evas_gl_x11_options_new_internal(const char *disp_name, Ecore_X_Window par ecore_x_window_defaults_set(ee->prop.window); _ecore_evas_x_protocols_set(ee); _ecore_evas_x_window_profile_protocol_set(ee); + _ecore_evas_x_wm_rotation_protocol_set(ee); _ecore_evas_x_sync_set(ee); ee->engine.func->fn_render = _ecore_evas_x_render;