From: Mun, Gwan-gyeong Date: Thu, 15 Jan 2015 13:10:15 +0000 (+0900) Subject: Add First step of Zone_Window_Rotation X-Git-Tag: accepted/tizen/common/20150119.084600~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F38%2F33838%2F1;p=platform%2Fcore%2Fuifw%2Fe-mod-tizen-wm-policy.git Add First step of Zone_Window_Rotation Change-Id: I257724e56db7d9ef736ea6ff5827efa7bb773530 --- diff --git a/AUTHORS b/AUTHORS index e69de29..6ae7099 100644 --- a/AUTHORS +++ b/AUTHORS @@ -0,0 +1,3 @@ +Gwangyeong Mun +Gwanglim Lee +MinJeong Kim diff --git a/COPYING.Flora b/COPYING.Flora new file mode 100644 index 0000000..09214d2 --- /dev/null +++ b/COPYING.Flora @@ -0,0 +1,215 @@ +Copyright notice for Flora-licensed files: + +The following files are copyrighted by Samsung Electronics Co., Ltd +and licensed under Flora License, Version 1.1 +- src/e_mod_main.c +- src/e_mod_rotation.c + +Copyright (C) 2013 Samsung Electronics Co., Ltd All rights reserved. + +Flora License + +Version 1.1, April, 2013 + +http://floralicense.org/license/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, +and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by +the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and +all other entities that control, are controlled by, or are +under common control with that entity. For the purposes of +this definition, "control" means (i) the power, direct or indirect, +to cause the direction or management of such entity, +whether by contract or otherwise, or (ii) ownership of fifty percent (50%) +or more of the outstanding shares, or (iii) beneficial ownership of +such entity. + +"You" (or "Your") shall mean an individual or Legal Entity +exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, +including but not limited to software source code, documentation source, +and configuration files. + +"Object" form shall mean any form resulting from mechanical +transformation or translation of a Source form, including but +not limited to compiled object code, generated documentation, +and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice +that is included in or attached to the work (an example is provided +in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial +revisions, annotations, elaborations, or other modifications represent, +as a whole, an original work of authorship. For the purposes of this License, +Derivative Works shall not include works that remain separable from, +or merely link (or bind by name) to the interfaces of, the Work and +Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original +version of the Work and any modifications or additions to that Work or +Derivative Works thereof, that is intentionally submitted to Licensor +for inclusion in the Work by the copyright owner or by an individual or +Legal Entity authorized to submit on behalf of the copyright owner. +For the purposes of this definition, "submitted" means any form of +electronic, verbal, or written communication sent to the Licensor or +its representatives, including but not limited to communication on +electronic mailing lists, source code control systems, and issue +tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding +communication that is conspicuously marked or otherwise designated +in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity +on behalf of whom a Contribution has been received by Licensor and +subsequently incorporated within the Work. + +"Tizen Certified Platform" shall mean a software platform that complies +with the standards set forth in the Tizen Compliance Specification +and passes the Tizen Compliance Tests as defined from time to time +by the Tizen Technical Steering Group and certified by the Tizen +Association or its designated agent. + +2. Grant of Copyright License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the +Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of +this License, each Contributor hereby grants to You a perpetual, +worldwide, non-exclusive, no-charge, royalty-free, irrevocable +(except as stated in this section) patent license to make, have made, +use, offer to sell, sell, import, and otherwise transfer the Work +solely as incorporated into a Tizen Certified Platform, where such +license applies only to those patent claims licensable by such +Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work solely +as incorporated into a Tizen Certified Platform to which such +Contribution(s) was submitted. If You institute patent litigation +against any entity (including a cross-claim or counterclaim +in a lawsuit) alleging that the Work or a Contribution incorporated +within the Work constitutes direct or contributory patent infringement, +then any patent licenses granted to You under this License for that +Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the +Work or Derivative Works thereof pursuant to the copyright license +above, in any medium, with or without modifications, and in Source or +Object form, provided that You meet the following conditions: + + 1. You must give any other recipients of the Work or Derivative Works + a copy of this License; and + 2. You must cause any modified files to carry prominent notices stating + that You changed the files; and + 3. You must retain, in the Source form of any Derivative Works that + You distribute, all copyright, patent, trademark, and attribution + notices from the Source form of the Work, excluding those notices + that do not pertain to any part of the Derivative Works; and + 4. If the Work includes a "NOTICE" text file as part of its distribution, + then any Derivative Works that You distribute must include a readable + copy of the attribution notices contained within such NOTICE file, + excluding those notices that do not pertain to any part of + the Derivative Works, in at least one of the following places: + within a NOTICE text file distributed as part of the Derivative Works; + within the Source form or documentation, if provided along with the + Derivative Works; or, within a display generated by the Derivative Works, + if and wherever such third-party notices normally appear. + The contents of the NOTICE file are for informational purposes only + and do not modify the License. You may add Your own attribution notices + within Derivative Works that You distribute, alongside or as an addendum + to the NOTICE text from the Work, provided that such additional attribution + notices cannot be construed as modifying the License. You may add Your own + copyright statement to Your modifications and may provide additional or + different license terms and conditions for use, reproduction, or + distribution of Your modifications, or for any such Derivative Works + as a whole, provided Your use, reproduction, and distribution of + the Work otherwise complies with the conditions stated in this License + and your own copyright statement or terms and conditions do not conflict + the conditions stated in the License including section 3. + +5. Submission of Contributions. Unless You explicitly state otherwise, +any Contribution intentionally submitted for inclusion in the Work +by You to the Licensor shall be under the terms and conditions of +this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify +the terms of any separate license agreement you may have executed +with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade +names, trademarks, service marks, or product names of the Licensor, +except as required for reasonable and customary use in describing the +origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or +agreed to in writing, Licensor provides the Work (and each +Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +implied, including, without limitation, any warranties or conditions +of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +PARTICULAR PURPOSE. You are solely responsible for determining the +appropriateness of using or redistributing the Work and assume any +risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, +whether in tort (including negligence), contract, or otherwise, +unless required by applicable law (such as deliberate and grossly +negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, +incidental, or consequential damages of any character arising as a +result of this License or out of the use or inability to use the +Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all +other commercial damages or losses), even if such Contributor +has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing +the Work or Derivative Works thereof, You may choose to offer, +and charge a fee for, acceptance of support, warranty, indemnity, +or other liability obligations and/or rights consistent with this +License. However, in accepting such obligations, You may act only +on Your own behalf and on Your sole responsibility, not on behalf +of any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason +of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Flora License to your work + +To apply the Flora License to your work, attach the following +boilerplate notice, with the fields enclosed by brackets "[]" +replaced with your own identifying information. (Don't include +the brackets!) The text should be enclosed in the appropriate +comment syntax for the file format. We also recommend that a +file or class name and description of purpose be included on the +same "printed page" as the copyright notice for easier +identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Flora License, Version 1.1 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://floralicense.org/license/ + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..f8cb23a --- /dev/null +++ b/NOTICE @@ -0,0 +1,6 @@ +Except as noted, this software is licensed under BSD license. +Please, see the COPYING file for BSD License terms and conditions. + +Several source codes may have its original copyright owner and/or +be licensed under other than BSD License, say, Flora License, Version 1.1 +Please, see the COPYING.Flora for Flora License, Version 1.1 terms and conditions. diff --git a/packaging/e-mod-tizen-wm-policy.spec b/packaging/e-mod-tizen-wm-policy.spec index 0d3a02a..4af42d7 100644 --- a/packaging/e-mod-tizen-wm-policy.spec +++ b/packaging/e-mod-tizen-wm-policy.spec @@ -3,7 +3,7 @@ Name: e-mod-tizen-wm-policy Summary: The Enlightenment WM Policy Module for Tizen Version: 0.1.0 Release: 1 -Group: System/GUI/Other +Group: Graphics & UI Framework/Other License: BSD-2-Clause Source0: %{name}-%{version}.tar.bz2 BuildRequires: pkgconfig(x11) @@ -27,6 +27,7 @@ make %{?_smp_mflags} # for license notification mkdir -p %{buildroot}/usr/share/license cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/usr/share/license/%{name} +cp -a %{_builddir}/%{buildsubdir}/COPYING.Flora %{buildroot}/usr/share/license/%{name}.Flora # install %make_install @@ -35,5 +36,6 @@ cp -a %{_builddir}/%{buildsubdir}/COPYING %{buildroot}/usr/share/license/%{name} %defattr(-,root,root,-) %{_libdir}/enlightenment/modules/e-mod-tizen-wm-policy /usr/share/license/%{name} +/usr/share/license/%{name}.Flora %define _unpackaged_files_terminate_build 0 diff --git a/src/Makefile.am b/src/Makefile.am index 3bd9e4f..0c2d1be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,10 @@ module_la_SOURCES = e_mod_config.c \ e_mod_softkey.c \ e_mod_visivility.c \ e_mod_atoms.c \ - e_mod_atoms.h + e_mod_atoms.h \ + e_mod_rotation.c \ + e_mod_rotation.h \ + e_mod_utils.h module_la_LIBADD = module_la_CFLAGS = @ENLIGHTENMENT_CFLAGS@ module_la_LDFLAGS = -module -avoid-version @ENLIGHTENMENT_LIBS@ diff --git a/src/e_mod_atoms.c b/src/e_mod_atoms.c index 71407f0..a6e0803 100644 --- a/src/e_mod_atoms.c +++ b/src/e_mod_atoms.c @@ -1,17 +1,31 @@ #include "e_mod_atoms.h" +#include "e_mod_utils.h" Ecore_X_Atom E_MOD_POL_ATOM_WINDOW_OPAQUE = 0; +static const char *atom_names[] = { + "_E_ILLUME_WINDOW_REGION_OPAQUE" +}; + Eina_Bool e_mod_pol_atoms_init(void) { - Eina_Bool ret = EINA_FALSE; - E_MOD_POL_ATOM_WINDOW_OPAQUE = ecore_x_atom_get ("_E_ILLUME_WINDOW_REGION_OPAQUE"); + Ecore_X_Atom *atoms = NULL; + int n = 0, i = 0; + Eina_Bool res = EINA_FALSE; + + n = (sizeof(atom_names) / sizeof(char *)); + + atoms = E_NEW(Ecore_X_Atom, n); + E_CHECK_GOTO(atoms, cleanup); + + ecore_x_atoms_get(atom_names, n, atoms); + + E_MOD_POL_ATOM_WINDOW_OPAQUE = atoms[i++]; - if (!E_MOD_POL_ATOM_WINDOW_OPAQUE) - fprintf (stderr, "[e-mod-tizen-wm-policy] Critical Error!!! Cannot create _E_ILLUME_WINDOW_REGION_OPAQUE Atom.\n"); - else - ret = EINA_TRUE; + res = EINA_TRUE; - return ret; +cleanup: + if (atoms) E_FREE(atoms); + return res; } diff --git a/src/e_mod_config.c b/src/e_mod_config.c index 07231e8..751be29 100644 --- a/src/e_mod_config.c +++ b/src/e_mod_config.c @@ -363,7 +363,7 @@ e_mod_pol_conf_desk_get_by_nums(Config *conf, unsigned int comp_num, unsigned in } E_Config_Dialog * -e_int_config_pol_mobile(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED) +e_int_config_pol_mobile(E_Comp *c EINA_UNUSED, const char *params EINA_UNUSED) { E_Config_Dialog *cfd; E_Config_Dialog_View *v; diff --git a/src/e_mod_main.c b/src/e_mod_main.c index 33f58fc..924992e 100644 --- a/src/e_mod_main.c +++ b/src/e_mod_main.c @@ -1,5 +1,25 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * This file is a modified version of BSD licensed file and + * licensed under the Flora License, Version 1.1 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Please, see the COPYING file for the original copyright owner and + * license. + */ #include "e_mod_main.h" #include "e_mod_atoms.h" +#include "e_mod_rotation.h" EAPI E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Policy-Mobile" }; @@ -9,6 +29,8 @@ Eina_Hash *hash_pol_clients = NULL; static Eina_List *handlers = NULL; static Eina_List *hooks = NULL; +static Eina_List *intercept_hooks = NULL; +static Ecore_Idle_Enterer *_idle_enterer = NULL; static Pol_Client *_pol_client_add(E_Client *ec); static void _pol_client_del(Pol_Client *pc); @@ -18,6 +40,15 @@ static void _pol_client_launcher_set(Pol_Client *pc); static void _pol_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec); static void _pol_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec); +static void _pol_hook_new_client(void *d EINA_UNUSED, E_Client *ec); +static void _pol_hook_new_client_post(void *d EINA_UNUSED, E_Client *ec); +static void _pol_hook_client_del(void *d EINA_UNUSED, E_Client *ec); +static void _pol_hook_eval_end(void *d EINA_UNUSED, E_Client *ec); +static void _pol_hook_eval_fetch(void *d EINA_UNUSED, E_Client *ec); + +static Eina_Bool _pol_intercept_hook_show_helper(void *d EINA_UNUSED, E_Client *ec); +static Eina_Bool _pol_intercept_hook_hide(void *d EINA_UNUSED, E_Client *ec); + static void _pol_cb_desk_data_free(void *data); static void _pol_cb_client_data_free(void *data); static Eina_Bool _pol_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); @@ -27,7 +58,15 @@ static Eina_Bool _pol_cb_zone_desk_count_set(void *data EINA_UNUSED, int type static Eina_Bool _pol_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); static Eina_Bool _pol_cb_client_remove(void *data EINA_UNUSED, int type, void *event); static Eina_Bool _pol_cb_client_add(void *data EINA_UNUSED, int type, void *event); -static Eina_Bool _pol_cb_window_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event); +static Eina_Bool _pol_cb_window_property(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Property *ev); + +static Eina_Bool _pol_cb_window_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure *ev); +static Eina_Bool _pol_cb_window_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Client_Message *ev); +static Eina_Bool _pol_cb_zone_rotation_change_begin(void *data EINA_UNUSED, int ev_type EINA_UNUSED, E_Event_Zone_Rotation_Change_Begin *ev); + +static Eina_Bool _pol_cb_idle_enterer(void *data EINA_UNUSED); + +static void _pol_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED); static void _pol_client_launcher_set(Pol_Client *pc) @@ -100,8 +139,6 @@ _pol_client_add(E_Client *ec) _pol_client_update(pc); - printf("[e-mod-tizen-wm-policy] pol_client_add()\n"); - return pc; } @@ -261,6 +298,54 @@ _pol_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec) } static void +_pol_hook_new_client(void *d EINA_UNUSED, E_Client *ec) +{ + e_mod_pol_rot_hook_new_client(ec); +} + +static void +_pol_hook_new_client_post(void *d EINA_UNUSED, E_Client *ec) +{ + if (ec->frame) + { + evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _pol_cb_evas_show, ec); + } + return; +} + + +static void +_pol_hook_client_del(void *d EINA_UNUSED, E_Client *ec) +{ + e_mod_pol_rot_hook_client_del(ec); + e_mod_pol_rot_hook_client_free(ec); +} + +static void +_pol_hook_eval_end(void *d EINA_UNUSED, E_Client *ec) +{ + e_mod_pol_rot_hook_eval_end(ec); +} + +static void +_pol_hook_eval_fetch(void *d EINA_UNUSED, E_Client *ec) +{ + e_mod_pol_rot_hook_eval_fetch(ec); +} + +static Eina_Bool +_pol_intercept_hook_show_helper(void *d EINA_UNUSED, E_Client *ec) +{ + return e_mod_pol_rot_intercept_hook_show_helper(ec); +} + +static Eina_Bool +_pol_intercept_hook_hide(void *d EINA_UNUSED, E_Client *ec) +{ + return e_mod_pol_rot_intercept_hook_hide(ec); +} + +static void _pol_cb_desk_data_free(void *data) { free(data); @@ -443,20 +528,69 @@ _pol_cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) } static Eina_Bool -_pol_cb_window_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) +_pol_cb_window_property(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Property *ev) { - Ecore_X_Event_Window_Property *ev; - ev = event; - if (ev->atom == E_MOD_POL_ATOM_WINDOW_OPAQUE) { - E_Client *ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, ev->win); - e_mod_pol_client_window_opaque_prop_change(ec); + e_mod_pol_visibility_cb_window_property(ev); + } + else if ((ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST)) + { + + e_mod_pol_rot_cb_window_property(ev); } return ECORE_CALLBACK_PASS_ON; } +static Eina_Bool +_pol_cb_window_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure *ev) +{ + e_mod_pol_rot_cb_window_configure(ev); + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_pol_cb_zone_rotation_change_begin(void *data EINA_UNUSED, int ev_type EINA_UNUSED, E_Event_Zone_Rotation_Change_Begin *ev) +{ + if ((!ev) || (!ev->zone)) return ECORE_CALLBACK_PASS_ON; + + e_mod_pol_rot_cb_zone_rotation_change_begin(ev); + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_pol_cb_window_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Client_Message *ev) +{ + e_mod_pol_rot_cb_window_message(ev); + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_pol_cb_idle_enterer(void *data EINA_UNUSED) +{ + e_mod_pol_rot_cb_idle_enterer(); + + return ECORE_CALLBACK_RENEW; +} + +static void +_pol_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + E_Client *ec = data; + e_mod_pol_rot_cb_evas_show(ec); + return; +} + void e_mod_pol_desk_add(E_Desk *desk) { @@ -569,6 +703,17 @@ e_mod_pol_client_launcher_get(E_Zone *zone) } \ while (0) +#undef E_COMP_OBJECT_INTERCEPT_HOOK_APPEND +#define E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(l, t, cb, d) \ + do \ + { \ + E_Comp_Object_Intercept_Hook *_h; \ + _h = e_comp_object_intercept_hook_add(t, cb, d); \ + assert(_h); \ + l = eina_list_append(l, _h); \ + } \ + while (0) + EAPI void * e_modapi_init(E_Module *m) { @@ -628,19 +773,53 @@ e_modapi_init(E_Module *m) // e_policy_zone_home_add_request(zone); } - E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD, _pol_cb_zone_add, NULL); - E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DEL, _pol_cb_zone_del, NULL); - E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_MOVE_RESIZE, _pol_cb_zone_move_resize, NULL); - E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET, _pol_cb_zone_desk_count_set, NULL); - E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_SHOW, _pol_cb_desk_show, NULL); - E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, _pol_cb_client_remove, NULL); - E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ADD, _pol_cb_client_add, NULL); - E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_PROPERTY, _pol_cb_window_property, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD, + _pol_cb_zone_add, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DEL, + _pol_cb_zone_del, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_MOVE_RESIZE, + _pol_cb_zone_move_resize, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET, + _pol_cb_zone_desk_count_set, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_SHOW, + _pol_cb_desk_show, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, + _pol_cb_client_remove, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ADD, + _pol_cb_client_add, NULL); + E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_PROPERTY, + _pol_cb_window_property, NULL); + E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_CONFIGURE, + _pol_cb_window_configure, NULL); + E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_CLIENT_MESSAGE, + _pol_cb_window_message, NULL); + E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, + _pol_cb_zone_rotation_change_begin, NULL); E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_EVAL_POST_FETCH, _pol_hook_client_eval_post_fetch, NULL); E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_DESK_SET, _pol_hook_client_desk_set, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_NEW_CLIENT, + _pol_hook_new_client, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_NEW_CLIENT_POST, + _pol_hook_new_client_post, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_DEL, + _pol_hook_client_del, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_EVAL_END, + _pol_hook_eval_end, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_EVAL_FETCH, + _pol_hook_eval_fetch, NULL); + + E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(intercept_hooks, + E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, + _pol_intercept_hook_show_helper, NULL); + E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(intercept_hooks, + E_COMP_OBJECT_INTERCEPT_HOOK_HIDE, + _pol_intercept_hook_hide, NULL); + + _idle_enterer = ecore_idle_enterer_add(_pol_cb_idle_enterer, NULL); + // change to ecore_idle_enterer_before_add()? return mod; } @@ -657,6 +836,14 @@ e_modapi_shutdown(E_Module *m) e_mod_pol_softkey_del(softkey); E_FREE_LIST(hooks, e_client_hook_del); E_FREE_LIST(handlers, ecore_event_handler_del); + E_FREE_LIST(intercept_hooks, e_comp_object_intercept_hook_del); + + if (_idle_enterer) + { + ecore_idle_enterer_del(_idle_enterer); + _idle_enterer = NULL; + } + E_FREE_FUNC(hash_pol_desks, eina_hash_free); E_FREE_FUNC(hash_pol_clients, eina_hash_free); diff --git a/src/e_mod_main.h b/src/e_mod_main.h index 7cd9279..f9ddba9 100644 --- a/src/e_mod_main.h +++ b/src/e_mod_main.h @@ -101,7 +101,7 @@ extern Eina_Hash *hash_pol_clients; EINTERN void e_mod_pol_conf_init(Mod *mod); EINTERN void e_mod_pol_conf_shutdown(Mod *mod); EINTERN Config_Desk *e_mod_pol_conf_desk_get_by_nums(Config *conf, unsigned int comp_num, unsigned int zone_num, int x, int y); -EINTERN E_Config_Dialog *e_int_config_pol_mobile(Evas_Object *parent, const char *params EINA_UNUSED); +EINTERN E_Config_Dialog *e_int_config_pol_mobile(E_Comp *c EINA_UNUSED, const char *params EINA_UNUSED); EINTERN void e_mod_pol_desk_add(E_Desk *desk); EINTERN void e_mod_pol_desk_del(Pol_Desk *pd); EINTERN Pol_Client *e_mod_pol_client_launcher_get(E_Zone *zone); @@ -119,6 +119,6 @@ EINTERN void e_mod_pol_zone_visibility_calc(E_Zone *zone); EINTERN void e_mod_pol_visibility_calc(void); EINTERN void e_mod_pol_client_visibility_del(E_Client *ec); EINTERN void e_mod_pol_client_window_opaque_set(E_Client *ec); -EINTERN void e_mod_pol_client_window_opaque_prop_change(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_visibility_cb_window_property(Ecore_X_Event_Window_Property *ev); #endif diff --git a/src/e_mod_rotation.c b/src/e_mod_rotation.c new file mode 100644 index 0000000..860342a --- /dev/null +++ b/src/e_mod_rotation.c @@ -0,0 +1,2171 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * This file is a modified version of BSD licensed file and + * licensed under the Flora License, Version 1.1 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://floralicense.org/license/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Please, see the COPYING file for the original copyright owner and + * license. + */ +#include "e_mod_rotation.h" +#include "e_mod_atoms.h" +#include "e_mod_utils.h" + +typedef struct _E_Client_Rotation E_Client_Rotation; + +struct _E_Client_Rotation +{ + Eina_List *list; + Eina_List *async_list; + + Eina_Bool wait_prepare_done; + Ecore_Timer *prepare_timer; + Ecore_Timer *done_timer; + + Ecore_X_Window vkbd_ctrl_win; + E_Client *vkbd; + E_Client *vkbd_prediction; + E_Client *vkbd_parent; + + /* vkbd show/hide preprare */ + Eina_Bool vkbd_show_prepare_done; + Ecore_Timer *vkbd_show_prepare_timer; + Ecore_Timer *vkbd_show_timer; + + Eina_Bool vkbd_hide_prepare_done; + Ecore_Timer *vkbd_hide_prepare_timer; + Ecore_Timer *vkbd_hide_timer; + + Eina_Bool screen_lock; + Eina_Bool fetch; + Eina_List *msgs; + + struct { + Eina_Bool state; + E_Zone *zone; + } cancel; +}; + +/* local subsystem variables */ +static E_Client_Rotation rot = +{ + NULL, + NULL, + EINA_FALSE, + NULL, + NULL, + 0, + NULL, + NULL, + NULL, + EINA_FALSE, + NULL, + NULL, + EINA_FALSE, + NULL, + NULL, + EINA_FALSE, + EINA_FALSE, + NULL, + { + EINA_FALSE, + NULL, + } +}; + +/* local subsystem e_client_rotation related functions */ +static Eina_Bool _e_client_rotation_change_prepare_timeout(void *data); +static void _e_client_rotation_list_send(void); +static void _e_client_rotation_change_message_send(E_Client *ec); +static Eina_Bool _e_client_rotation_change_done_timeout(void *data); +static void _e_client_rotation_change_done(void); +static Eina_Bool _e_client_rotation_geom_get(E_Client *ec, + E_Zone *zone, + int ang, + int *x, + int *y, + int *w, + int *h, + Eina_Bool *move); +static void _e_client_rotation_list_remove(E_Client *ec); +static Eina_Bool _e_client_rotation_prepare_send(E_Client *ec, int rotation); +static Eina_Bool _e_client_rotation_zone_set(E_Zone *zone); +static int _e_client_rotation_curr_next_get(const E_Client *ec); +static Eina_Bool _e_client_rotation_is_dependent_parent(const E_Client *ec); +static Eina_Bool _e_client_is_vkbd(E_Client *ec); +static Eina_Bool _e_client_vkbd_show_prepare_timeout(void *data); +static Eina_Bool _e_client_vkbd_hide_prepare_timeout(void *data); +static void _e_client_vkbd_show(E_Client *ec); +static void _e_client_vkbd_hide(E_Client *ec, Eina_Bool clean); +static void _e_client_event_client_rotation_change_begin_free(void *data, + void *ev); +static void _e_client_event_client_rotation_change_end_free(void *data, + void *ev); +static void _e_client_event_client_rotation_change_begin_send(E_Client *ec); + +/* local subsystem e_zone_rotation related functions */ +static void _e_zone_rotation_set_internal(E_Zone *zone, int rotation); +static void _e_zone_event_rotation_change_begin_free(void *data, + void *ev); +static void _e_zone_event_rotation_change_cancel_free(void *data, + void *ev); +static void _e_zone_event_rotation_change_end_free(void *data, + void *ev); +/* e_client_roation functions */ +static Eina_Bool e_client_rotation_is_progress(const E_Client *ec); +static Eina_Bool e_client_rotation_is_available(const E_Client *ec, int ang); +static Eina_List *e_client_rotation_available_list_get(const E_Client *ec); +static int e_client_rotation_curr_angle_get(const E_Client *ec); +static int e_client_rotation_next_angle_get(const E_Client *ec); +static int e_client_rotation_prev_angle_get(const E_Client *ec); +static int e_client_rotation_recommend_angle_get(const E_Client *ec); +static Eina_Bool e_client_rotation_set(E_Client *ec, int rotation); +static void e_client_rotation_change_request(E_Client *ec, int rotation); + +/* e_zone_roation functions */ +static void e_zone_rotation_set(E_Zone *zone, int rot); +static void e_zone_rotation_sub_set(E_Zone *zone, int rotation); +static int e_zone_rotation_get(E_Zone *zone); +static Eina_Bool e_zone_rotation_block_set(E_Zone *zone, const char *name_hint, Eina_Bool set); +static void e_zone_rotation_update_done(E_Zone *zone); +static void e_zone_rotation_update_cancel(E_Zone *zone); + +/* local subsystem e_client_rotation related functions */ +static Eina_Bool +_e_client_vkbd_state_check(E_Client *ec, + Eina_Bool show) +{ + Eina_Bool res = EINA_TRUE; + if ((rot.vkbd) && (rot.vkbd == ec)) + { + if (show) + { + if ((rot.vkbd_hide_prepare_done) || + (rot.vkbd_hide_prepare_timer)) + res = EINA_FALSE; + } + else + { + if ((rot.vkbd_show_prepare_done) || + (rot.vkbd_show_prepare_timer)) + res = EINA_FALSE; + } + } + return res; +} + +static Eina_Bool +_e_client_vkbd_show_timeout(void *data) +{ + E_Client *ec = data; + if ((ec) && ((E_OBJECT(ec)->type) == (E_CLIENT_TYPE))) + { + if (_e_client_vkbd_state_check(ec, EINA_TRUE)) + { + if (rot.vkbd_ctrl_win) + { + ecore_x_e_virtual_keyboard_state_set + (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON); + } + } + } + + rot.vkbd_show_prepare_done = EINA_FALSE; + + if (rot.vkbd_show_prepare_timer) + ecore_timer_del(rot.vkbd_show_prepare_timer); + rot.vkbd_show_prepare_timer = NULL; + + if (rot.vkbd_show_timer) + ecore_timer_del(rot.vkbd_show_timer); + rot.vkbd_show_timer = NULL; + + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_e_client_vkbd_hide_timeout(void *data) +{ + E_Client *ec = data; + int unref_count = 0; + + rot.vkbd_hide_timer = NULL; + unref_count++; + + if (rot.vkbd_hide_prepare_timer) + { + ecore_timer_del(rot.vkbd_hide_prepare_timer); + unref_count++; + } + rot.vkbd_hide_prepare_timer = NULL; + + if (_e_client_vkbd_state_check(ec, EINA_FALSE)) + { + if (rot.vkbd_ctrl_win) + { + ecore_x_e_virtual_keyboard_state_set + (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF); + } + } + + rot.vkbd_hide_prepare_done = EINA_FALSE; + + while (unref_count) + { + e_object_unref(E_OBJECT(ec)); + unref_count--; + } + + return ECORE_CALLBACK_CANCEL; +} + +static void +_e_client_vkbd_show(E_Client *ec) +{ + rot.vkbd_show_prepare_done = EINA_TRUE; + if (rot.vkbd_show_prepare_timer) + ecore_timer_del(rot.vkbd_show_prepare_timer); + rot.vkbd_show_prepare_timer = NULL; + if (rot.vkbd_show_timer) + ecore_timer_del(rot.vkbd_show_timer); + rot.vkbd_show_timer = NULL; + if ((ec) && (!e_object_is_del(E_OBJECT(ec)))) + { + evas_object_show(ec->frame);// e_client_show(ec) + rot.vkbd_show_timer = ecore_timer_add(1.0f, _e_client_vkbd_show_timeout, ec); + } +} + +static void +_e_client_vkbd_hide(E_Client *ec, Eina_Bool clean) +{ + int unref_count = 0; + + rot.vkbd_hide_prepare_done = EINA_TRUE; + + if (clean) + { + if (rot.vkbd_hide_prepare_timer) + { + ecore_timer_del(rot.vkbd_hide_prepare_timer); + unref_count++; + } + rot.vkbd_hide_prepare_timer = NULL; + + if (rot.vkbd_hide_timer) + { + ecore_timer_del(rot.vkbd_hide_timer); + unref_count++; + } + rot.vkbd_hide_timer = NULL; + + if ((ec) && ((E_OBJECT(ec)->type) == (E_CLIENT_TYPE))) + { + evas_object_hide(ec->frame); // e_client_hide(ec) + + e_object_ref(E_OBJECT(ec)); + if (!e_object_is_del(E_OBJECT(ec))) + { + e_object_del(E_OBJECT(ec)); // is it right? e_object_unref(E_OBJECT(ec));?? + } + rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_client_vkbd_hide_timeout, ec); + } + } + else + { + if ((ec) && ((E_OBJECT(ec)->type) == (E_CLIENT_TYPE))) + { + evas_object_hide(ec->frame);// e_client_hide(ec); + } + } + + while (unref_count) + { + e_object_unref(E_OBJECT(ec)); + unref_count--; + } +} + +static Eina_Bool +_e_client_vkbd_show_prepare_timeout(void *data) +{ + E_Client *ec = data; + if ((ec) && (!e_object_is_del(E_OBJECT(ec)))) + { + _e_client_vkbd_show(ec); + } + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_e_client_vkbd_hide_prepare_timeout(void *data) +{ + E_Client *ec = data; + int unref_count = 0; + + rot.vkbd_hide_prepare_timer = NULL; + unref_count++; + + if (rot.vkbd_hide_timer) + { + ecore_timer_del(rot.vkbd_hide_timer); + unref_count++; + } + rot.vkbd_hide_timer = NULL; + + _e_client_vkbd_hide(ec, EINA_TRUE); + + while (unref_count) + { + e_object_unref(E_OBJECT(ec)); + unref_count--; + } + + return ECORE_CALLBACK_CANCEL; +} + +#define SIZE_EQUAL_TO_ZONE(a, z) \ + ((((a)->w) == ((z)->w)) && \ + (((a)->h) == ((z)->h))) + +static int +_e_client_rotation_curr_next_get(const E_Client *ec) +{ + if (!ec) return -1; + + return ((ec->e.state.rot.ang.next == -1) ? + ec->e.state.rot.ang.curr : ec->e.state.rot.ang.next); +} + +static int +_prev_angle_get(Ecore_X_Window win) +{ + int ret, count = 0, ang = -1; + unsigned char* data = NULL; + + ret = ecore_x_window_prop_property_get + (win, ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, + ECORE_X_ATOM_CARDINAL, 32, &data, &count); + + if ((ret) && (data) && (count)) + ang = ((int *)data)[0]; + if (data) free(data); + return ang; +} + +/* check whether virtual keyboard is visible on the zone */ +static Eina_Bool +_e_client_is_vkbd(E_Client *ec) +{ + if ((rot.vkbd_ctrl_win) && + (rot.vkbd == ec) && + (!e_object_is_del(E_OBJECT(rot.vkbd))) && + (rot.vkbd->zone == ec->zone) && + (E_INTERSECTS(ec->zone->x, ec->zone->y, + ec->zone->w, ec->zone->h, + rot.vkbd->x, rot.vkbd->y, + rot.vkbd->w, rot.vkbd->h))) + { + return EINA_TRUE; + } + return EINA_FALSE; +} + +static Eina_Bool +_e_client_rotation_is_dependent_parent(const E_Client *ec) +{ + if (!ec) return EINA_FALSE; + if ((!ec->parent) || (!evas_object_visible_get(ec->parent->frame))) return EINA_FALSE; + if (ec->netwm.type == E_WINDOW_TYPE_NORMAL) return EINA_FALSE; + if ((!ec->e.state.rot.support) && + (!ec->e.state.rot.app_set)) return EINA_FALSE; + + return EINA_TRUE; +} + +static Eina_Bool +_e_client_rotation_zone_set(E_Zone *zone) +{ + E_Comp *comp; + Eina_List *cl; + E_Client *ec = NULL; + Eina_Bool res = EINA_FALSE; + Eina_Bool ret = EINA_FALSE; + + /* step 1. make the list needs to be rotated. */ + EINA_LIST_FOREACH(e_comp_list(), cl, comp) + { + E_Zone *ez; + Eina_List *zl; + + EINA_LIST_FOREACH(comp->zones, zl, ez) + { + Eina_List *l; + + if (ez != zone) continue; + + EINA_LIST_REVERSE_FOREACH(zone->comp->clients, l, ec) + { + if(ec->zone != zone) continue; + + // if this window has parent and window type isn't "ECORE_X_WINDOW_TYPE_NORMAL", + // it will be rotated when parent do rotate itself. + // so skip here. + if ((ec->parent) && + (ec->netwm.type != E_WINDOW_TYPE_NORMAL)) continue; + + // default type is "E_CLIENT_ROTATION_TYPE_NORMAL", + // but it can be changed to "E_CLIENT_ROTATION_TYPE_DEPENDENT" by illume according to its policy. + // if it's not normal type window, will be rotated by illume. + // so skip here. + if (ec->e.state.rot.type != E_CLIENT_ROTATION_TYPE_NORMAL) continue; + + if ((!evas_object_visible_get(ec->frame)) || + (!E_INTERSECTS(ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h, + ec->x, ec->y, ec->w, ec->h))) continue; + + res = e_client_rotation_set(ec, zone->rot.curr); + if (!res) + { + ; + } + else ret = EINA_TRUE; + } + } + } + + return ret; +} + +static void +_e_client_rotation_change_message_send(E_Client *ec) +{ + int rotation; + Eina_Bool resize = EINA_FALSE; + + if (!ec) return; + + rotation = ec->e.state.rot.ang.next; + if (rotation == -1) return; + if (ec->e.state.rot.wait_for_done) return; + + resize = _e_client_rotation_prepare_send(ec, rotation); + + // new protocol + if ((resize) && (!ec->e.state.rot.geom_hint)) + { + e_client_rotation_change_request(ec, rotation); + } + // original protocol + else + { + ec->e.state.rot.pending_change_request = resize; + + if (!resize) + { + e_client_rotation_change_request(ec, rotation); + } + } +} + +static void +_e_client_rotation_list_send(void) +{ + Eina_List *l; + E_Client *ec; + + if (!rot.list) return; + if (eina_list_count(rot.list) <= 0) return; + + EINA_LIST_FOREACH(rot.list, l, ec) + { + if (ec->e.state.rot.pending_change_request) continue; + if (ec->e.state.rot.wait_for_done) continue; + + _e_client_rotation_change_message_send(ec); + } +} + +static Eina_Bool +_e_client_rotation_change_prepare_timeout(void *data) +{ + E_Zone *zone = data; + + if ((zone) && (rot.wait_prepare_done)) + { + if (rot.list) + { + _e_client_rotation_list_send(); + if (rot.prepare_timer) + ecore_timer_del(rot.prepare_timer); + rot.prepare_timer = NULL; + rot.wait_prepare_done = EINA_FALSE; + } + } + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_e_client_rotation_change_done_timeout(void *data __UNUSED__) +{ + _e_client_rotation_change_done(); + return ECORE_CALLBACK_CANCEL; +} + +static void +_e_client_rotation_list_remove(E_Client *ec) +{ + E_Event_Client_Rotation_Change_End *ev = NULL; + Eina_Bool found = EINA_FALSE; + + if (eina_list_data_find(rot.list, ec) == ec) + { + found = EINA_TRUE; + rot.list = eina_list_remove(rot.list, ec); + } + + if (ec->e.state.rot.wait_for_done) + { + ec->e.state.rot.wait_for_done = 0; + + /* if we make the e_client event in the _e_client_free function, + * then we may meet a crash problem, only work this at least e_client_hide. + */ + if (!e_object_is_del(E_OBJECT(ec))) + { + ev = E_NEW(E_Event_Client_Rotation_Change_End, 1); + if (ev) + { + ev->ec = ec; + e_object_ref(E_OBJECT(ec)); + ecore_event_add(E_EVENT_CLIENT_ROTATION_CHANGE_END, + ev, + _e_client_event_client_rotation_change_end_free, + NULL); + } + } + + if ((found) && + (eina_list_count(rot.list) == 0)) + { + _e_client_rotation_change_done(); + } + } + ec->e.state.rot.ang.next = -1; + ec->changes.rotation = 0; +} + +static void +_e_client_rotation_change_done(void) +{ + E_Manager *m = NULL; + E_Client *ec; + + if (rot.prepare_timer) ecore_timer_del(rot.prepare_timer); + rot.prepare_timer = NULL; + + rot.wait_prepare_done = EINA_FALSE; + + if (rot.done_timer) ecore_timer_del(rot.done_timer); + rot.done_timer = NULL; + + EINA_LIST_FREE(rot.list, ec) + { + if (ec->e.state.rot.pending_show) + { + ec->e.state.rot.pending_show = 0; + evas_object_show(ec->frame); // e_client_show(ec); + } + ec->e.state.rot.ang.next = -1; + ec->e.state.rot.wait_for_done = 0; + } + + EINA_LIST_FREE(rot.async_list, ec) + { + _e_client_rotation_change_message_send(ec); + } + + rot.list = NULL; + rot.async_list = NULL; + + m = e_manager_current_get(); + if (rot.screen_lock) + { + // do call comp_x's screen unlock + rot.screen_lock = EINA_FALSE; + } + e_zone_rotation_update_done(e_util_zone_current_get(m)); +} + +static Eina_Bool +_e_client_rotation_prepare_send(E_Client *ec, int rotation) +{ + E_Zone *zone = ec->zone; + int x, y, w, h; + Eina_Bool move = EINA_FALSE; + Eina_Bool hint = EINA_FALSE; + Eina_Bool resize = EINA_FALSE; + + x = ec->x; + y = ec->y; + w = ec->w; + h = ec->h; + + if (SIZE_EQUAL_TO_ZONE(ec, zone)) goto end; + + hint = _e_client_rotation_geom_get(ec, ec->zone, rotation, + &x, &y, &w, &h, &move); + + if ((!hint) || (ec->w != w) || (ec->h != h)) resize = EINA_TRUE; + +end: + + ecore_x_e_window_rotation_change_prepare_send + (e_client_util_win_get(ec), rotation, resize, w, h); + + if (((move) && ((ec->x !=x) || (ec->y !=y))) || + ((resize) && ((ec->w != w) || (ec->h != h)))) + { +#if 0 + // need call: _e_comp_x_client_move_resize_send(); ? + _e_client_move_resize_internal(ec, x, y, w, h, EINA_TRUE, move); +#endif + e_client_util_move_resize_without_frame(ec, x, y, w, h); //check: this function work correct or not. + } + + return resize; +} + +static Eina_Bool +_e_client_rotation_geom_get(E_Client *ec, + E_Zone *zone, + int ang, + int *x, + int *y, + int *w, + int *h, + Eina_Bool *move) +{ + Eina_Bool res = EINA_FALSE; + int _x = ec->x; + int _y = ec->y; + int _w = ec->w; + int _h = ec->h; + + if (x) *x = ec->x; + if (y) *y = ec->y; + if (w) *w = ec->w; + if (h) *h = ec->h; + if (move) *move = EINA_TRUE; + + if (ec->e.state.rot.geom_hint) + { + switch (ang) + { + case 0: + _w = ec->e.state.rot.geom[0].w; + _h = ec->e.state.rot.geom[0].h; + if (_w == 0) _w = ec->w; + if (_h == 0) _h = ec->h; + _x = 0; _y = zone->h - _h; + break; + case 90: + _w = ec->e.state.rot.geom[1].w; + _h = ec->e.state.rot.geom[1].h; + if (_w == 0) _w = ec->w; + if (_h == 0) _h = ec->h; + _x = zone->w - _w; _y = 0; + break; + case 180: + _w = ec->e.state.rot.geom[2].w; + _h = ec->e.state.rot.geom[2].h; + if (_w == 0) _w = ec->w; + if (_h == 0) _h = ec->h; + _x = 0; _y = 0; + break; + case 270: + _w = ec->e.state.rot.geom[3].w; + _h = ec->e.state.rot.geom[3].h; + if (_w == 0) _w = ec->w; + if (_h == 0) _h = ec->h; + _x = 0; _y = 0; + break; + } + + if (x) *x = _x; + if (y) *y = _y; + if (w) *w = _w; + if (h) *h = _h; + + if (!((rot.vkbd) && (rot.vkbd == ec))) + { + if (x) *x = ec->x; + if (y) *y = ec->y; + if (move) *move = EINA_FALSE; + } + + res = EINA_TRUE; + } + + if (res) + { + _x = 0; _y = 0; _w = 0; _h = 0; + if (x) _x = *x; + if (y) _y = *y; + if (w) _w = *w; + if (h) _h = *h; + } + + return res; +} + +static void +_e_client_event_client_rotation_change_begin_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Client_Rotation_Change_Begin *e; + e = ev; + e_object_unref(E_OBJECT(e->ec)); + E_FREE(e); +} + +static void +_e_client_event_client_rotation_change_end_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Client_Rotation_Change_End *e; + e = ev; + e_object_unref(E_OBJECT(e->ec)); + E_FREE(e); +} + +static void +_e_client_event_client_rotation_change_begin_send(E_Client *ec) +{ + E_Event_Client_Rotation_Change_Begin *ev = NULL; + ev = E_NEW(E_Event_Client_Rotation_Change_End, 1); + if (ev) + { + ev->ec = ec; + e_object_ref(E_OBJECT(ec)); + ecore_event_add(E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN, + ev, + _e_client_event_client_rotation_change_begin_free, + NULL); + } +} + +/* local subsystem e_zone_rotation related functions */ +static void +_e_zone_rotation_set_internal(E_Zone *zone, int rot) +{ + E_Event_Zone_Rotation_Change_Begin *ev; + + E_OBJECT_CHECK(zone); + E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); + + if ((zone->rot.wait_for_done) || + (zone->rot.block_count > 0)) + { + zone->rot.next = rot; + zone->rot.pending = EINA_TRUE; + return; + } + + if (zone->rot.curr == rot) return; + + zone->rot.prev = zone->rot.curr; + zone->rot.curr = rot; + zone->rot.wait_for_done = EINA_TRUE; + + ev = E_NEW(E_Event_Zone_Rotation_Change_Begin, 1); + if (ev) + { + ev->zone = zone; + e_object_ref(E_OBJECT(ev->zone)); + ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, + ev, _e_zone_event_rotation_change_begin_free, NULL); + } +} + +static void +_e_zone_event_rotation_change_begin_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Zone_Rotation_Change_Begin *e = ev; + e_object_unref(E_OBJECT(e->zone)); + E_FREE(e); +} + +static void +_e_zone_event_rotation_change_cancel_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Zone_Rotation_Change_Cancel *e = ev; + e_object_unref(E_OBJECT(e->zone)); + E_FREE(e); +} + +static void +_e_zone_event_rotation_change_end_free(void *data __UNUSED__, + void *ev) +{ + E_Event_Zone_Rotation_Change_End *e = ev; + e_object_unref(E_OBJECT(e->zone)); + E_FREE(e); +} + +/* e_client_roation functions */ +static void +e_client_rotation_change_request(E_Client *ec, int rotation) +{ + if (!ec) return; + if (rotation < 0) return; + + // if this window is in withdrawn state, change the state to NORMAL. + // that's because the window in withdrawn state can't render its canvas. + // eventually, this window will not send the message of rotation done, + // even if e request to rotation this window. + e_hints_window_visible_set(ec); + + ecore_x_e_window_rotation_change_request_send(e_client_util_win_get(ec), rotation); + +#if 0 + if (ec->e.state.deiconify_approve.pending) + _e_client_deiconify_approve_send_pending_end(ec); +#endif + ec->e.state.rot.wait_for_done = 1; + + if ((!rot.async_list) || + (!eina_list_data_find(rot.async_list, ec))) + { + if (rot.done_timer) + ecore_timer_del(rot.done_timer); + rot.done_timer = ecore_timer_add(4.0f, + _e_client_rotation_change_done_timeout, + NULL); + } +} + +/** + * @describe + * Get current rotoation state. + * @param ec e_client + * @return EINA_FALSE the state that does not rotating. + * EINA_TRUE the state that rotating. + */ +static Eina_Bool +e_client_rotation_is_progress(const E_Client *ec) +{ + if (!ec) return EINA_FALSE; + + if (ec->e.state.rot.ang.next == -1) + return EINA_FALSE; + else + return EINA_TRUE; +} + +/** + * @describe + * Check if this e_client is rotatable to given angle. + * @param ec e_client + * @param ang test angle. + * @return EINA_FALSE can't be rotated. + * EINA_TRUE can be rotated. + */ +static Eina_Bool +e_client_rotation_is_available(const E_Client *ec, int ang) +{ + if (!ec) return EINA_FALSE; + + if (ang < 0) goto fail; + if ((!ec->e.state.rot.support) && (!ec->e.state.rot.app_set)) goto fail; + if (e_object_is_del(E_OBJECT(ec))) goto fail; + + if (ec->e.state.rot.preferred_rot == -1) + { + unsigned int i; + + if (ec->e.state.rot.app_set) + { + if (ec->e.state.rot.available_rots && + ec->e.state.rot.count) + { + Eina_Bool found = EINA_FALSE; + for (i = 0; i < ec->e.state.rot.count; i++) + { + if (ec->e.state.rot.available_rots[i] == ang) + { + found = EINA_TRUE; + } + } + if (found) goto success; + } + } + else + { + goto success; + } + } + else if (ec->e.state.rot.preferred_rot == ang) goto success; + +fail: + return EINA_FALSE; +success: + return EINA_TRUE; +} + +/** + * @describe + * Get the list of available rotation of e_client. + * @param ec e_client + * @return Eina_List* the list consist of integer value of available rotation angle. + * @caution the caller is responsible for freeing the list after use. + */ +static Eina_List* +e_client_rotation_available_list_get(const E_Client *ec) +{ + Eina_List *list = NULL; + int *element; + unsigned int i; + + E_OBJECT_CHECK_RETURN(ec, EINA_FALSE); + E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE); + + if ((!ec->e.state.rot.support) && (!ec->e.state.rot.app_set)) return list; + + if (ec->e.state.rot.preferred_rot != -1) + { + element = (int *)malloc(1 * sizeof(int)); + *element = ec->e.state.rot.preferred_rot; + list = eina_list_append(list, element); + } + else if (ec->e.state.rot.count > 0) + { + if (ec->e.state.rot.available_rots) + { + for (i = 0; i < ec->e.state.rot.count; i++) + { + element = (int *)malloc(1 * sizeof(int)); + *element = ec->e.state.rot.available_rots[i]; + list = eina_list_append(list, element); + } + } + } + + return list; +} + +/** + * @describe + * Get current rotation angle. + * @param ec e_client + * @return int current angle + */ +static int +e_client_rotation_curr_angle_get(const E_Client *ec) +{ + E_OBJECT_CHECK_RETURN(ec, -1); + E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, -1); + + return ec->e.state.rot.ang.curr; +} + +/** + * @describe + * Get being replaced rotation angle. + * @param ec e_client + * @return int be replaced angle. + */ +static int +e_client_rotation_next_angle_get(const E_Client *ec) +{ + E_OBJECT_CHECK_RETURN(ec, -1); + E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, -1); + + return ec->e.state.rot.ang.next; +} + +/** + * @describe + * Get previous angle get + * @param ec e_client + * @return int previous angle. + */ +static int +e_client_rotation_prev_angle_get(const E_Client *ec) +{ + E_OBJECT_CHECK_RETURN(ec, -1); + E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, -1); + + return ec->e.state.rot.ang.prev; +} + +/** + * @describe + * Get the angle that this e_client should be rotated. + * @param ec e_client + * @return Eina_Bool -1: There is no need to be rotated. + * != -1: The angle that this e_client should be rotated. + */ +static int +e_client_rotation_recommend_angle_get(const E_Client *ec) +{ + E_Zone *zone = NULL; + int ret_ang = -1; + + E_OBJECT_CHECK_RETURN(ec, ret_ang); + E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, ret_ang); + + zone = ec->zone; + + if (ec->e.state.rot.type == E_CLIENT_ROTATION_TYPE_DEPENDENT) goto end; + if ((!ec->e.state.rot.app_set) && (!ec->e.state.rot.support)) goto end; + + if (ec->e.state.rot.preferred_rot != -1) + { + ret_ang = ec->e.state.rot.preferred_rot; + } + else if ((ec->e.state.rot.available_rots) && + (ec->e.state.rot.count)) + { + unsigned int i; + int current_ang = _e_client_rotation_curr_next_get(ec); + Eina_Bool found = EINA_FALSE; + Eina_Bool found_curr_ang = EINA_FALSE; + + if (_e_client_rotation_is_dependent_parent(ec)) + { + ret_ang = _e_client_rotation_curr_next_get(ec->parent); + } + else + { + ret_ang = e_zone_rotation_get(zone); + } + + for (i = 0; i < ec->e.state.rot.count; i++) + { + if (ec->e.state.rot.available_rots[i] == ret_ang) + { + found = EINA_TRUE; + break; + } + if (ec->e.state.rot.available_rots[i] == current_ang) + found_curr_ang = EINA_TRUE; + } + + if (!found) + { + if (found_curr_ang) + ret_ang = current_ang; + else + ret_ang = ec->e.state.rot.available_rots[0]; + } + } + else + ; + +end: + return ret_ang; +} + +/** + * @describe + * Set the rotation of the e_client given angle. + * @param ec e_client + * *param rotation angle + * @return EINA_TRUE rotation starts or is already in progress. + * EINA_FALSE fail + */ +static Eina_Bool +e_client_rotation_set(E_Client *ec, int rotation) +{ + Eina_List *list, *l; + E_Client *child; + int curr_rot; + + if (!ec) return EINA_FALSE; + + if (rotation < 0) return EINA_FALSE; + if (!e_client_rotation_is_available(ec, rotation)) return EINA_FALSE; + + // in case same with current angle. + curr_rot = e_client_rotation_curr_angle_get(ec); + if (curr_rot == rotation) + { + if (e_client_rotation_is_progress(ec)) + { + // cancel the changes in case only doesn't send request. + if ((!ec->e.state.rot.pending_change_request) && + (!ec->e.state.rot.wait_for_done)) + { + _e_client_rotation_list_remove(ec); + if (ec->e.state.rot.pending_show) + { + ec->e.state.rot.pending_show = 0; + if (!e_object_is_del(E_OBJECT(ec))) + evas_object_show(ec->frame); // e_client_show(ec); + } +#if 0 //force rendering? + if (ec->e.state.deiconify_approve.pending) + _e_client_deiconify_approve_send_pending_end(ec); +#endif + + return EINA_FALSE; + } + else + ; + } + else + return EINA_FALSE; + } + + // in case same with next angle. + curr_rot = e_client_rotation_next_angle_get(ec); + if (curr_rot == rotation) + { + // if there is reserve angle, remove it. + if (ec->e.state.rot.ang.reserve != -1) + { + ec->e.state.rot.ang.reserve = -1; + } + goto finish; + } + + /* if this e_client is rotating now, + * it will be rotated to this angle after rotation done. + */ + if ((ec->e.state.rot.pending_change_request) || + (ec->e.state.rot.wait_for_done)) + { + ec->e.state.rot.ang.reserve = rotation; + goto finish; + } + + /* search rotatable window in this window's child */ + list = eina_list_clone(ec->transients); + EINA_LIST_FOREACH(list, l, child) + { + // the window which type is "ECORE_X_WINDOW_TYPE_NORMAL" will be rotated itself. + // it shouldn't be rotated by rotation state of parent window. + if (child->netwm.type == E_WINDOW_TYPE_NORMAL) continue; + if (e_client_rotation_set(child, rotation)) + { + ; + } + else + { + ; + } + } + eina_list_free(list); + + /* if there is vkbd window, send message to prepare rotation */ + if (_e_client_is_vkbd(ec)) + { + if (rot.prepare_timer) + ecore_timer_del(rot.prepare_timer); + rot.prepare_timer = NULL; + + ecore_x_e_window_rotation_change_prepare_send(rot.vkbd_ctrl_win, + rotation, + EINA_FALSE, 1, 1); + rot.prepare_timer = ecore_timer_add(4.0f, + _e_client_rotation_change_prepare_timeout, + NULL); + + rot.wait_prepare_done = EINA_TRUE; + } + + _e_client_event_client_rotation_change_begin_send(ec); + + ec->e.state.rot.pending_change_request = 0; + ec->e.state.rot.ang.next = rotation; + ec->changes.rotation = 1; + EC_CHANGED(ec); + +finish: + /* Now the WM has a rotatable window thus we unset variables about zone rotation cancel */ + if (rot.cancel.state) + { + rot.cancel.state = EINA_FALSE; + rot.cancel.zone = NULL; + } + return EINA_TRUE; +} + +/* e_zone_rotation related functions */ +static void +e_zone_rotation_set(E_Zone *zone, + int rot) +{ + E_OBJECT_CHECK(zone); + E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); + + if (rot == -1) + { + zone->rot.unknown_state = EINA_TRUE; + return; + } + else + zone->rot.unknown_state = EINA_FALSE; + + _e_zone_rotation_set_internal(zone, rot); +} + +static void +e_zone_rotation_sub_set(E_Zone *zone, int rotation) +{ + E_OBJECT_CHECK(zone); + E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); + + zone->rot.sub = rotation; + + if ((zone->rot.unknown_state) && + (zone->rot.curr != rotation)) + _e_zone_rotation_set_internal(zone, rotation); +} + +static int +e_zone_rotation_get(E_Zone *zone) +{ + E_OBJECT_CHECK_RETURN(zone, -1); + E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, -1); + if (!zone->rot.unknown_state) return zone->rot.curr; + else return zone->rot.sub; +} + +static Eina_Bool +e_zone_rotation_block_set(E_Zone *zone, const char *name_hint, Eina_Bool set) +{ + E_Event_Zone_Rotation_Change_Begin *ev; + + E_OBJECT_CHECK_RETURN(zone, EINA_FALSE); + E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, EINA_FALSE); + + if (set) zone->rot.block_count++; + else zone->rot.block_count--; + + if (zone->rot.block_count <= 0) + { + zone->rot.block_count = 0; + + if (zone->rot.pending) + { + zone->rot.prev = zone->rot.curr; + zone->rot.curr = zone->rot.next; + zone->rot.wait_for_done = EINA_TRUE; + zone->rot.pending = EINA_FALSE; + + ev = E_NEW(E_Event_Zone_Rotation_Change_Begin, 1); + if (ev) + { + ev->zone = zone; + e_object_ref(E_OBJECT(ev->zone)); + ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, + ev, _e_zone_event_rotation_change_begin_free, NULL); + } + } + } + + return EINA_TRUE; +} + +static void +e_zone_rotation_update_done(E_Zone *zone) +{ + E_Event_Zone_Rotation_Change_End *ev; + + E_OBJECT_CHECK(zone); + E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); + + ev = E_NEW(E_Event_Zone_Rotation_Change_End, 1); + if (ev) + { + ev->zone = zone; + e_object_ref(E_OBJECT(ev->zone)); + ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_END, + ev, _e_zone_event_rotation_change_end_free, NULL); + } + + zone->rot.wait_for_done = EINA_FALSE; + if ((zone->rot.pending) && + (zone->rot.block_count == 0)) + { + zone->rot.prev = zone->rot.curr; + zone->rot.curr = zone->rot.next; + zone->rot.wait_for_done = EINA_TRUE; + zone->rot.pending = EINA_FALSE; + + E_Event_Zone_Rotation_Change_Begin *ev2; + ev2 = E_NEW(E_Event_Zone_Rotation_Change_Begin, 1); + if (ev2) + { + ev2->zone = zone; + e_object_ref(E_OBJECT(ev2->zone)); + ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, + ev2, _e_zone_event_rotation_change_begin_free, NULL); + } + } +} + +static void +e_zone_rotation_update_cancel(E_Zone *zone) +{ + E_Event_Zone_Rotation_Change_Cancel *ev; + + E_OBJECT_CHECK(zone); + E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE); + + zone->rot.wait_for_done = EINA_FALSE; + if (zone->rot.pending) + { + zone->rot.prev = zone->rot.curr; + zone->rot.curr = zone->rot.next; + zone->rot.pending = EINA_FALSE; + } + + ev = E_NEW(E_Event_Zone_Rotation_Change_Cancel, 1); + if (ev) + { + ev->zone = zone; + e_object_ref(E_OBJECT(ev->zone)); + ecore_event_add(E_EVENT_ZONE_ROTATION_CHANGE_CANCEL, + ev, _e_zone_event_rotation_change_cancel_free, NULL); + } +} + +/* externally accessible functions */ +EINTERN Eina_Bool +e_mod_pol_rot_hook_client_free(E_Client *ec) +{ + Eina_Bool rm_vkbd_parent = EINA_FALSE; + + ec->e.fetch.rot.app_set = 0; + ec->e.state.rot.preferred_rot = -1; + + if (ec->e.state.rot.available_rots) + E_FREE(ec->e.state.rot.available_rots); + + _e_client_rotation_list_remove(ec); + if ((rot.vkbd) && (rot.vkbd == ec)) + { + rot.vkbd = NULL; + if (rot.vkbd_ctrl_win) + { + ecore_x_e_virtual_keyboard_state_set + (rot.vkbd_ctrl_win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF); + } + + rot.vkbd_hide_prepare_done = EINA_FALSE; + if (rot.vkbd_hide_prepare_timer) + ecore_timer_del(rot.vkbd_hide_prepare_timer); + rot.vkbd_hide_prepare_timer = NULL; + if (rot.vkbd_hide_timer) + ecore_timer_del(rot.vkbd_hide_timer); + rot.vkbd_hide_timer = NULL; + + rot.vkbd_show_prepare_done = EINA_FALSE; + if (rot.vkbd_show_prepare_timer) + ecore_timer_del(rot.vkbd_show_prepare_timer); + rot.vkbd_show_prepare_timer = NULL; + if (rot.vkbd_show_timer) + ecore_timer_del(rot.vkbd_show_timer); + rot.vkbd_show_timer = NULL; + if ((rot.vkbd_parent) && (!rot.vkbd_prediction)) + rm_vkbd_parent = EINA_TRUE; + } + else if ((rot.vkbd_prediction) && + (rot.vkbd_prediction == ec)) + { + rot.vkbd_prediction = NULL; + if ((rot.vkbd_parent) && (!rot.vkbd)) + rm_vkbd_parent = EINA_TRUE; + } + else if ((rot.vkbd_parent) && + (rot.vkbd_parent == ec)) + rm_vkbd_parent = EINA_TRUE; + + if (rm_vkbd_parent) + { + rot.vkbd_parent = NULL; + } + + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_hook_client_del(E_Client *ec) +{ + _e_client_rotation_list_remove(ec); + if (rot.async_list) rot.async_list = eina_list_remove(rot.async_list, ec); + + return EINA_TRUE; +} + +EINTERN void +e_mod_pol_rot_cb_evas_show(E_Client *ec) +{ + if (!ec->hidden) + { + if (rot.vkbd == ec) + _e_client_vkbd_show_timeout(ec); + } + + if (!ec->iconic) + { + if ((ec->e.state.rot.support) || (ec->e.state.rot.app_set)) + { + if (ec->e.state.rot.ang.next == -1) + { + int rotation = e_client_rotation_recommend_angle_get(ec); + if (rotation != -1) e_client_rotation_set(ec, rotation); + } + } + } +} + +EINTERN Eina_Bool +e_mod_pol_rot_hook_eval_end(E_Client *ec) +{ + if (ec->changes.rotation) + { + E_Zone *zone = ec->zone; + + if (ec->moving) e_client_act_move_end(ec, NULL); + + if ((!zone->rot.block_count) && + ((!evas_object_visible_get(ec->frame)) || + (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h)))) + { + // async list add + rot.async_list = eina_list_append(rot.async_list, ec); + } + else + { + // sync list add + rot.list = eina_list_append(rot.list, ec); + if (!rot.wait_prepare_done) + _e_client_rotation_change_message_send(ec); + } + rot.fetch = EINA_TRUE; + ec->changes.rotation = 0; + } + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_cb_idle_enterer(void) +{ + if (rot.cancel.state) + { + /* there is no border which supports window manager rotation */ + e_zone_rotation_update_cancel(rot.cancel.zone); + rot.cancel.state = EINA_FALSE; + rot.cancel.zone = NULL; + } + + if (rot.fetch) + { + Ecore_X_Event_Client_Message *msg = NULL; + Ecore_X_Atom t = 0; + EINA_LIST_FREE(rot.msgs, msg) + { + t = msg->message_type; + if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE) + { + if ((rot.vkbd_ctrl_win) && + ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) && + (rot.vkbd)) + { + if (rot.vkbd_show_prepare_timer) + _e_client_vkbd_show(rot.vkbd); + else + ; + } + } + else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) + { + if ((rot.vkbd_ctrl_win) && + ((Ecore_X_Window)msg->data.l[0] == rot.vkbd_ctrl_win) && + (rot.vkbd)) + { + if (rot.vkbd_hide_prepare_timer) + { + _e_client_vkbd_hide(rot.vkbd, EINA_TRUE); + } + else + ; + } + } + else if (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW) + { + rot.vkbd_ctrl_win = msg->data.l[0]; + } + else if (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE) + { + if ((rot.vkbd_ctrl_win) && + (rot.vkbd_ctrl_win == (Ecore_X_Window)msg->data.l[0])) + { + E_Zone *zone = e_util_zone_current_get(e_manager_current_get()); + if ((zone) && (rot.wait_prepare_done)) + { + if (rot.list) + _e_client_rotation_list_send(); + else + _e_client_rotation_change_done(); + + if (rot.prepare_timer) + ecore_timer_del(rot.prepare_timer); + rot.prepare_timer = NULL; + rot.wait_prepare_done = EINA_FALSE; + } + } + } + E_FREE(msg); + } + // if there is windows over 2 that has to be rotated or is existed window needs resizing, + // lock the screen. + // but, DO NOT lock the screen when rotation block state + if (eina_list_count(rot.list) > 1) + { + Eina_List *l; + E_Client *ec; + Eina_Bool rot_block = EINA_FALSE; + + EINA_LIST_FOREACH(rot.list, l, ec) + { + if (!ec->zone) continue; + if (ec->zone->rot.block_count) + { + rot_block = EINA_TRUE; + } + } + if ((!rot.screen_lock) && (!rot_block)) + { + //Do implement screen lock api on e_comp. + //do call comp_x's screen lock + rot.screen_lock = EINA_TRUE; + } + } + else if (eina_list_count(rot.list) == 0) + { + E_Client *ec; + Eina_List *zlist = NULL; + Eina_List *l = NULL; + E_Zone *zone = NULL; + + if (rot.async_list) + { + EINA_LIST_FREE(rot.async_list, ec) + { + if (!eina_list_data_find(zlist, ec->zone)) + zlist = eina_list_append(zlist, ec->zone); + _e_client_rotation_change_message_send(ec); + } + + EINA_LIST_FOREACH(zlist, l, zone) + e_zone_rotation_update_cancel(zone); + if (zlist) + eina_list_free(zlist); + } + } + + rot.msgs = NULL; + rot.fetch = EINA_FALSE; + } + + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_hook_new_client(E_Client *ec) +{ + Ecore_X_Window win = e_client_util_win_get(ec); + int at_num = 0, i; + Ecore_X_Atom *atoms; + + ec->e.state.rot.preferred_rot = -1; + ec->e.state.rot.type = E_CLIENT_ROTATION_TYPE_NORMAL; + ec->e.state.rot.ang.next = -1; + ec->e.state.rot.ang.reserve = -1; + ec->e.state.rot.pending_show = 0; + ec->e.state.rot.ang.curr = 0; + ec->e.state.rot.ang.prev = 0; + + atoms = ecore_x_window_prop_list(win, &at_num); + if (atoms) + { + for (i = 0; i < at_num; i++) + { + /* loop to check for wm rotation */ + if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED) + { + ec->e.fetch.rot.support = 1; + } + else if ((atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) || + (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) || + (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) || + (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY)) + { + ec->e.fetch.rot.geom_hint = 1; + } + else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED) + { + ec->e.fetch.rot.app_set = 1; + } + else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION) + { + ec->e.fetch.rot.preferred_rot = 1; + } + else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST) + { + ec->e.fetch.rot.available_rots = 1; + } + } + free(atoms); + } + + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_cb_zone_rotation_change_begin(E_Event_Zone_Rotation_Change_Begin *ev) +{ + if ((!ev) || (!ev->zone)) return EINA_FALSE; + + if (!_e_client_rotation_zone_set(ev->zone)) + { + /* The WM will decide to cancel zone rotation at idle time. + * Because, the policy module can make list of rotation windows + */ + rot.cancel.state = EINA_TRUE; + rot.cancel.zone = ev->zone; + } + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_intercept_hook_hide(E_Client *ec) +{ + if ((rot.vkbd_ctrl_win) && (rot.vkbd) && + (ec == rot.vkbd) && + (!rot.vkbd_hide_prepare_done) && + (!ec->iconic)) + { + Eina_Bool need_prepare = EINA_TRUE; + if (ec->parent) + { + if (e_object_is_del(E_OBJECT(ec->parent))) + need_prepare = EINA_FALSE; + } + else + need_prepare = EINA_FALSE; + + /* If E wait for VKBD_ON_PREPARE_DONE, + * E doesn't need to wait for that no more, + * VKBD will be destroyed soon. */ + if (rot.vkbd_show_prepare_timer) + { + ecore_timer_del(rot.vkbd_show_prepare_timer); + rot.vkbd_show_prepare_timer = NULL; + } + + if (need_prepare) + { + e_object_ref(E_OBJECT(ec)); + + ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win); + + if (rot.vkbd_hide_prepare_timer) + { + ecore_timer_del(rot.vkbd_hide_prepare_timer); + e_object_unref(E_OBJECT(rot.vkbd)); + } + rot.vkbd_hide_prepare_timer = NULL; + + if (rot.vkbd_hide_timer) + { + ecore_timer_del(rot.vkbd_hide_timer); + e_object_unref(E_OBJECT(rot.vkbd)); + } + rot.vkbd_hide_timer = NULL; + + rot.vkbd_hide_prepare_timer = ecore_timer_add(1.5f, + _e_client_vkbd_hide_prepare_timeout, + ec); + return EINA_FALSE; + } + else + { + e_object_ref(E_OBJECT(ec)); + + /* In order to clear conformant area properly, WM should send keyboard off prepare request event */ + ecore_x_e_virtual_keyboard_off_prepare_request_send(rot.vkbd_ctrl_win); + + /* cleanup code from _e_client_vkbd_hide() */ + rot.vkbd_hide_prepare_done = EINA_TRUE; + + if (rot.vkbd_hide_prepare_timer) + { + ecore_timer_del(rot.vkbd_hide_prepare_timer); + e_object_unref(E_OBJECT(rot.vkbd)); + } + rot.vkbd_hide_prepare_timer = NULL; + + if (rot.vkbd_hide_timer) + { + ecore_timer_del(rot.vkbd_hide_timer); + e_object_unref(E_OBJECT(rot.vkbd)); + } + rot.vkbd_hide_timer = NULL; + + rot.vkbd_hide_timer = ecore_timer_add(0.03f, _e_client_vkbd_hide_timeout, ec); + } + } + /* if vkbd's parent has to be hidden, + * vkbd and prediction widnow will be hidden with its parent. + */ + else if (ec == rot.vkbd_parent) + { + if ((rot.vkbd) && evas_object_visible_get(rot.vkbd->frame)) + { + _e_client_vkbd_hide(rot.vkbd, EINA_FALSE); + ecore_x_window_hide(e_client_util_win_get(rot.vkbd)); + } + if ((rot.vkbd_prediction) && evas_object_visible_get(rot.vkbd_prediction->frame)) + { + evas_object_hide(rot.vkbd_prediction->frame); // e_client_hide(rot.vkbd_prediction); + ecore_x_window_hide(e_client_util_win_get(rot.vkbd_prediction));// is it really needed? + } + } + // clear pending_show, because this window is hidden now. + ec->e.state.rot.pending_show = 0; + + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_intercept_hook_show_helper(E_Client *ec) +{ + // newly created window that has to be rotated will be shown after rotation done. + // so, skip at this time. it will be called again after GETTING ROT_DONE. + if (ec->e.state.rot.ang.next != -1) + { + ec->e.state.rot.pending_show = 1; + return EINA_FALSE; + } + + if ((rot.vkbd_ctrl_win) && (rot.vkbd) && + (ec == rot.vkbd) && + (!rot.vkbd_show_prepare_done)) + { + ecore_x_e_virtual_keyboard_on_prepare_request_send(rot.vkbd_ctrl_win); + + if (rot.vkbd_show_prepare_timer) + ecore_timer_del(rot.vkbd_show_prepare_timer); + rot.vkbd_show_prepare_timer = ecore_timer_add(1.5f, + _e_client_vkbd_show_prepare_timeout, + ec); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_cb_window_configure(Ecore_X_Event_Window_Configure *ev) +{ + E_Client *ec; + + ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, ev->win); + if (!ec) return EINA_FALSE; + + if ((ec->e.state.rot.pending_change_request) && + (ec->e.state.rot.geom_hint)) + { + if ((ev->w == ec->w) && (ev->h == ec->h)) + { + ec->e.state.rot.pending_change_request = 0; + if (!ec->e.state.rot.wait_for_done) + e_client_rotation_change_request(ec, ec->e.state.rot.ang.next); + } + } + + return EINA_TRUE; +} + +EINTERN Eina_Bool +e_mod_pol_rot_cb_window_property(Ecore_X_Event_Window_Property *ev) +{ + E_Client *ec; + + ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, ev->win); + + if (!ec) return ECORE_CALLBACK_RENEW; + + if (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED) + { + ec->e.fetch.rot.support = 1; + EC_CHANGED(ec); + } + else if ((ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_0_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_90_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_180_GEOMETRY) || + (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_270_GEOMETRY)) + { + ec->e.fetch.rot.geom_hint = 1; + EC_CHANGED(ec); + } + else if (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_APP_SUPPORTED) + { + ec->e.fetch.rot.app_set = 1; + EC_CHANGED(ec); + } + else if (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_PREFERRED_ROTATION) + { + ec->e.fetch.rot.preferred_rot = 1; + EC_CHANGED(ec); } + else if (ev->atom == ECORE_X_ATOM_E_WINDOW_ROTATION_AVAILABLE_LIST) + { + ec->e.fetch.rot.available_rots = 1; + EC_CHANGED(ec); + } + + return ECORE_CALLBACK_RENEW; +} + +EINTERN Eina_Bool +e_mod_pol_rot_cb_window_message(Ecore_X_Event_Client_Message *ev) +{ + E_Client *ec; + + ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, ev->win); + + if (!ec) + { + Ecore_X_Event_Client_Message *msg = NULL; + Ecore_X_Atom t = ev->message_type; + if ((t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_DONE) || + (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_DONE) || + (t == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_CONTROL_WINDOW) || + (t == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE_DONE)) + { + msg = E_NEW(Ecore_X_Event_Client_Message, 1); + if (!msg) return ECORE_CALLBACK_PASS_ON; + + msg->win = ev->win; + msg->message_type = ev->message_type; + msg->data.l[0] = ev->data.l[0]; + msg->data.l[1] = ev->data.l[1]; + msg->data.l[2] = ev->data.l[2]; + msg->data.l[3] = ev->data.l[3]; + msg->data.l[4] = ev->data.l[4]; + + rot.msgs = eina_list_append(rot.msgs, msg); + rot.fetch = EINA_TRUE; + } + return ECORE_CALLBACK_PASS_ON; + } + + if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_DONE) + { + ec->e.state.rot.ang.prev = ec->e.state.rot.ang.curr; + ec->e.state.rot.ang.curr = (int)ev->data.l[1]; + + if ((int)ev->data.l[1] == ec->e.state.rot.ang.next) + { + ec->e.state.rot.ang.next = -1; + + _e_client_rotation_list_remove(ec); + + if (ec->e.state.rot.ang.reserve != -1) + { + e_client_rotation_set(ec, ec->e.state.rot.ang.reserve); + ec->e.state.rot.ang.reserve = -1; + } + else if (ec->e.state.rot.pending_show) + { + ec->e.state.rot.pending_show = 0; + evas_object_show(ec->frame); //e_client_show(ec); + } + } + else + { + int angle = e_client_rotation_recommend_angle_get(ec); + if (angle != -1) e_client_rotation_set(ec, angle); + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +EINTERN Eina_Bool +e_mod_pol_rot_hook_eval_fetch(E_Client *ec) +{ +#if 0 + //TODO: add vkbd fetch_transient_for flag + /* workaround: since transient_for is fetched by illume in hook, + * added below flag to know this state in this eval time + */ + Eina_Bool fetch_transient_for = EINA_FALSE; + + if (ec->icccm.fetch.transient_for) + { + if (((rot.vkbd) && (rot.vkbd == ec)) || + ((rot.vkbd_prediction) && (rot.vkbd_prediction == ec))) + { + ec->e.fetch.rot.need_rotation = EINA_TRUE; + } + + fetch_transient_for = EINA_TRUE; + } +#endif + //TODO: Add fetch flag for VKBD + if ((ec->icccm.name) && (ec->icccm.class)) + { + if ((!strcmp(ec->icccm.name, "Virtual Keyboard")) && + (!strcmp(ec->icccm.class, "ISF")) && + (ec->vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD)) + { + ec->vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_KEYPAD; + rot.vkbd = ec; + } + else if ((!strcmp(ec->icccm.name, "Prediction Window")) && + (!strcmp(ec->icccm.class, "ISF")) && + (ec->vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION)) + { + ec->vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_PREDICTION; + rot.vkbd_prediction = ec; + } + else if ((!strcmp(ec->icccm.name, "Key Magnifier")) && + (!strcmp(ec->icccm.class, "ISF")) && + (ec->vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER)) + { + ec->vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_MAGNIFIER; + } + else if ((!strcmp(ec->icccm.name, "ISF Popup")) && + (!strcmp(ec->icccm.class, "ISF")) && + (ec->vkbd.win_type != E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP)) + { + ec->vkbd.win_type = E_VIRTUAL_KEYBOARD_WINDOW_TYPE_POPUP; + } + } + + if(ec->e.fetch.rot.support) + { + int ret = 0; + unsigned int support = 0; + + ret = ecore_x_window_prop_card32_get + (e_client_util_win_get(ec), + ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED, + &support, 1); + + ec->e.state.rot.support = 0; + if ((ret == 1) && (support == 1)) + { + int ang = -1; + + ang = _prev_angle_get(e_client_util_win_get(ec)); + if (ang != -1) + { + ec->e.state.rot.ang.curr = ang; + } + ec->e.state.rot.support = 1; + } + + if (ec->e.state.rot.support) + ec->e.fetch.rot.need_rotation = EINA_TRUE; + + ec->e.fetch.rot.support = 0; + } + if (ec->e.fetch.rot.geom_hint) + { + Eina_Rectangle r[4]; + int i, x, y, w, h; + ec->e.state.rot.geom_hint = 0; + for (i = 0; i < 4; i++) + { + r[i].x = ec->e.state.rot.geom[i].x; + r[i].y = ec->e.state.rot.geom[i].y; + r[i].w = ec->e.state.rot.geom[i].w; + r[i].h = ec->e.state.rot.geom[i].h; + + ec->e.state.rot.geom[i].x = 0; + ec->e.state.rot.geom[i].y = 0; + ec->e.state.rot.geom[i].w = 0; + ec->e.state.rot.geom[i].h = 0; + } + + for (i = 0; i < 4; i++) + { + x = 0; y = 0; w = 0; h = 0; + if (ecore_x_e_window_rotation_geometry_get(e_client_util_win_get(ec), i*90, &x, &y, &w, &h)) + { + ec->e.state.rot.geom_hint = 1; + ec->e.state.rot.geom[i].x = x; + ec->e.state.rot.geom[i].y = y; + ec->e.state.rot.geom[i].w = w; + ec->e.state.rot.geom[i].h = h; + + if (!((r[i].x == x) && (r[i].y == y) && + (r[i].w == w) && (r[i].h == h))) + { + ec->e.fetch.rot.need_rotation = EINA_TRUE; + } + } + } + ec->e.fetch.rot.geom_hint = 0; + } + if (ec->e.fetch.rot.app_set) + { + unsigned char _prev_app_set = ec->e.state.rot.app_set; + ec->e.state.rot.app_set = ecore_x_e_window_rotation_app_get(e_client_util_win_get(ec)); + + if (_prev_app_set != ec->e.state.rot.app_set) + { + if (ec->e.state.rot.app_set) + { + int ang = -1; + + ang = _prev_angle_get(e_client_util_win_get(ec)); + + if (ang != -1) + { + ec->e.state.rot.ang.curr = ang; + } + } + ec->e.fetch.rot.need_rotation = EINA_TRUE; + } + + ec->e.fetch.rot.app_set = 0; + } + if (ec->e.fetch.rot.preferred_rot) + { + int r = 0, _prev_preferred_rot; + _prev_preferred_rot = ec->e.state.rot.preferred_rot; + ec->e.state.rot.preferred_rot = -1; + if (ecore_x_e_window_rotation_preferred_rotation_get(e_client_util_win_get(ec), &r)) + { + ec->e.state.rot.preferred_rot = r; + } + else + { + ; + } + + if (_prev_preferred_rot != ec->e.state.rot.preferred_rot) + ec->e.fetch.rot.need_rotation = EINA_TRUE; + + ec->e.fetch.rot.preferred_rot = 0; + } + if (ec->e.fetch.rot.available_rots) + { + Eina_Bool res, diff = EINA_FALSE; + int *rots = NULL; + unsigned int count = 0, i = 0; + int _prev_rots[4] = { -1, }; + + if (ec->e.state.rot.available_rots) + { + memcpy(_prev_rots, + ec->e.state.rot.available_rots, + (sizeof(int) * ec->e.state.rot.count)); + + E_FREE(ec->e.state.rot.available_rots); + } + + ec->e.state.rot.count = 0; + + res = ecore_x_e_window_rotation_available_rotations_get(e_client_util_win_get(ec), + &rots, &count); + if ((res) && (count > 0) && (rots)) + { + ec->e.state.rot.available_rots = rots; + ec->e.state.rot.count = count; + + for (i = 0; i < count; i++) + { + if ((!diff) && (_prev_rots[i] != rots[i])) + { + diff = EINA_TRUE; + } + } + } + else + { + diff = EINA_TRUE; + } + + if (diff) ec->e.fetch.rot.need_rotation = EINA_TRUE; + + ec->e.fetch.rot.available_rots = 0; + } +#if 0 + if (fetch_transient_for) + { + Eina_Bool need_fetch = EINA_FALSE; + + if (rot.vkbd) + { + if (rot.vkbd == bd) need_fetch = EINA_TRUE; + } + else if ((rot.vkbd_prediction) && (rot.vkbd_prediction == bd)) + need_fetch = EINA_TRUE; + + if (need_fetch) + { + if (bd->parent != rot.vkbd_parent) + { + ; + } + } + } +#endif + if ((ec->e.fetch.rot.need_rotation) && + (ec->e.state.rot.type == E_CLIENT_ROTATION_TYPE_NORMAL)) + { + Eina_Bool hint = EINA_FALSE; + int ang = 0; + int x, y, w, h; + Eina_Bool move; + + ang = e_client_rotation_recommend_angle_get(ec); + e_client_rotation_set(ec, ang); + + if (ec->e.state.rot.ang.next == -1) + { + ang = ec->e.state.rot.ang.curr; + //Fix geometry change case. + hint = _e_client_rotation_geom_get(ec, ec->zone, ang, &x, &y, &w, &h, &move); + if (hint) + { +#if 0 + /// need to change api to _e_comp_x_client_move_resize_send(); + _e_client_move_resize_internal(bd, x, y, w, h, EINA_TRUE, move);//? +#endif + e_client_util_move_resize_without_frame(ec, x, y, w, h); //check: this function work correct or not. + } + } + else + { + EC_CHANGED(ec); + } + } + if (ec->e.fetch.rot.need_rotation) + ec->e.fetch.rot.need_rotation = EINA_FALSE; + + return EINA_TRUE; +} + diff --git a/src/e_mod_rotation.h b/src/e_mod_rotation.h new file mode 100644 index 0000000..71e461c --- /dev/null +++ b/src/e_mod_rotation.h @@ -0,0 +1,19 @@ +#ifndef E_MOD_ROTATION_H +#define E_MOD_ROTATION_H +#include + +EINTERN Eina_Bool e_mod_pol_rot_hook_client_free(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_rot_hook_client_del(E_Client *ec); +EINTERN void e_mod_pol_rot_cb_evas_show(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_rot_hook_eval_end(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_rot_cb_idle_enterer(void); +EINTERN Eina_Bool e_mod_pol_rot_hook_new_client(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_rot_cb_zone_rotation_change_begin(E_Event_Zone_Rotation_Change_Begin *ev); +EINTERN Eina_Bool e_mod_pol_rot_intercept_hook_show_helper(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_rot_intercept_hook_hide(E_Client *ec); +EINTERN Eina_Bool e_mod_pol_rot_cb_window_configure(Ecore_X_Event_Window_Configure *ev); +EINTERN Eina_Bool e_mod_pol_rot_cb_window_property(Ecore_X_Event_Window_Property *ev); +EINTERN Eina_Bool e_mod_pol_rot_cb_window_message(Ecore_X_Event_Client_Message *ev); +EINTERN Eina_Bool e_mod_pol_rot_hook_eval_fetch(E_Client *ec); + +#endif diff --git a/src/e_mod_utils.h b/src/e_mod_utils.h new file mode 100644 index 0000000..b7ea683 --- /dev/null +++ b/src/e_mod_utils.h @@ -0,0 +1,8 @@ +#ifndef E_MOD_UTILS_H +#define E_MOD_UTILS_H + +#define E_CHECK(x) do {if (!(x)) return; } while(0) +#define E_CHECK_RETURN(x, r) do {if (!(x)) return (r);} while(0) +#define E_CHECK_GOTO(x, l) do {if (!(x)) goto l; } while(0) + +#endif diff --git a/src/e_mod_visivility.c b/src/e_mod_visivility.c index 5ca5548..4940932 100644 --- a/src/e_mod_visivility.c +++ b/src/e_mod_visivility.c @@ -181,7 +181,6 @@ e_mod_pol_zone_visibility_calc(E_Zone *zone) E_Client *ec; Eina_Tiler *t; Eina_Rectangle r; - Eina_Iterator *itr; const int edge = 1; const int OBSCURED = 1; const int UNOBSCURED = 0; @@ -323,17 +322,21 @@ e_mod_pol_client_window_opaque_set(E_Client *ec) _win_opaque_add(ec, opaque); } -void -e_mod_pol_client_window_opaque_prop_change(E_Client *ec) +Eina_Bool +e_mod_pol_visibility_cb_window_property(Ecore_X_Event_Window_Property *ev) { Ecore_X_Window win; int opaque = 0; Pol_Win_Opaque *pwo; + E_Client *ec; - if (!ec) return; + if (!ev) return EINA_FALSE; + + ec = e_pixmap_find_client(E_PIXMAP_TYPE_X, ev->win); + if (!ec) return EINA_FALSE; pwo = _win_opaque_find(ec); - win = e_client_util_win_get(ec); + win = ev->win; if (_win_opaque_prop_get(win, &opaque)) { @@ -346,4 +349,6 @@ e_mod_pol_client_window_opaque_prop_change(E_Client *ec) } e_mod_pol_visibility_calc(); + + return EINA_TRUE; }