The problem that e17 couldn't move/resize window when the window fetch the rotation...
[platform/core/uifw/e17.git] / src / bin / e_randr_12_output.c
1 #include "e_randr_private.h"
2 #include "e_randr.h"
3
4 E_Randr_Monitor_Info           *_monitor_info_new(E_Randr_Output_Info *output_info);
5 static int                      _modes_size_sort_cb(const void *d1, const void *d2);
6
7 void
8 _monitor_modes_refs_set(E_Randr_Monitor_Info *mi, Ecore_X_Randr_Output o)
9 {
10    Ecore_X_Randr_Mode *modes = NULL;
11    Ecore_X_Randr_Mode_Info *mode_info = NULL;
12    int nmodes = 0, npreferred = 0;
13
14    EINA_SAFETY_ON_NULL_RETURN(mi);
15    EINA_SAFETY_ON_TRUE_RETURN(o == Ecore_X_Randr_None);
16
17    // Add (preferred) modes
18    modes = ecore_x_randr_output_modes_get(e_randr_screen_info.root, o, &nmodes, &npreferred);
19    while (--nmodes >= 0)
20      {
21         if (!modes[nmodes]) continue;
22         if (!(mode_info = _12_screen_info_mode_info_get(modes[nmodes])))
23           {
24              //Mode unknown to the global structure, so add it
25              mode_info = ecore_x_randr_mode_info_get(e_randr_screen_info.root, modes[nmodes]);
26              e_randr_screen_info.rrvd_info.randr_info_12->modes = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->modes, mode_info);
27           }
28         mi->modes = eina_list_prepend(mi->modes, mode_info);
29         if (nmodes <= npreferred)
30           mi->preferred_modes = eina_list_prepend(mi->preferred_modes, mode_info);
31      }
32    free(modes);
33 }
34
35 /**
36  * @brief Allocates a new E_Randr_Monitor_Info struct and initializes it with
37  * default values.
38  * @return E_Randr_Monitor_Info element, or if it could not be
39  * created, NULL
40  */
41 E_Randr_Monitor_Info *
42 _monitor_info_new(E_Randr_Output_Info *oi)
43 {
44    E_Randr_Monitor_Info *mi = NULL;
45
46    EINA_SAFETY_ON_NULL_RETURN_VAL(oi, NULL);
47
48    mi = E_NEW(E_Randr_Monitor_Info, 1);
49
50    // Set some default values
51    mi->modes = NULL;
52    mi->preferred_modes = NULL;
53    mi->size_mm.width = Ecore_X_Randr_Unset;
54    mi->size_mm.height = Ecore_X_Randr_Unset;
55    mi->edid = NULL;
56    mi->edid_length = 0;
57    mi->edid_hash.hash = 0;
58    mi->max_backlight = Ecore_X_Randr_Unset;
59    mi->backlight_level = 0.0;
60
61    _monitor_modes_refs_set(mi, oi->xid);
62
63    ecore_x_randr_output_size_mm_get(e_randr_screen_info.root, oi->xid, &mi->size_mm.width, &mi->size_mm.height);
64    mi->edid = ecore_x_randr_output_edid_get(e_randr_screen_info.root, oi->xid, &mi->edid_length);
65    if (mi->edid_length > 0)
66      mi->edid_hash.hash = eina_hash_superfast((char *)mi->edid, mi->edid_length);
67
68    return mi;
69 }
70
71 /**
72  * @brief Frees E_Randr_Monitor_Info structure
73  */
74 void
75 _monitor_info_free(E_Randr_Monitor_Info *monitor_info)
76 {
77    if (!monitor_info)
78      return;
79
80    eina_list_free(monitor_info->modes);
81    eina_list_free(monitor_info->preferred_modes);
82    free(monitor_info->edid);
83    free(monitor_info);
84 }
85
86 /**
87  * @brief allocates a struct and fills it with default values.
88  * @param output the output the display is queried for. If Ecore_X_Randr_None is
89  * given, a struct with only the xid will be set
90  * @return E_Randr_Output_Info element
91  */
92 E_Randr_Output_Info *
93 _output_info_new(Ecore_X_Randr_Output output)
94 {
95    E_Randr_Output_Info *output_info = NULL;
96    char *str;
97
98    EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, NULL);
99
100    output_info = E_NEW(E_Randr_Output_Info, 1);
101
102    output_info->xid = output;
103
104    //Use default values
105    output_info->crtc = NULL;
106    output_info->wired_clones = NULL;
107    output_info->possible_crtcs = NULL;
108    output_info->signalformats = Ecore_X_Randr_Unset;
109    output_info->signalformat = Ecore_X_Randr_Unset;
110    output_info->connector_number = 0;
111    output_info->monitor = NULL;
112    output_info->connector_type = Ecore_X_Randr_Unset;
113    output_info->policy = ECORE_X_RANDR_OUTPUT_POLICY_NONE;
114    output_info->compatibility_list = NULL;
115    output_info->subpixel_order = Ecore_X_Randr_Unset;
116
117    str = ecore_x_randr_output_name_get(e_randr_screen_info.root, output_info->xid, &output_info->name_length);
118    output_info->name = eina_stringshare_add(str);
119    free(str);
120    output_info->connection_status = ecore_x_randr_output_connection_status_get(e_randr_screen_info.root, output_info->xid);
121
122    return output_info;
123 }
124
125 void
126 _output_info_free(E_Randr_Output_Info *output_info)
127 {
128    EINA_SAFETY_ON_NULL_RETURN(output_info);
129
130     eina_list_free(output_info->wired_clones);
131     eina_list_free(output_info->possible_crtcs);
132     eina_list_free(output_info->compatibility_list);
133     eina_stringshare_del(output_info->name);
134     _monitor_info_free(output_info->monitor);
135     output_info->monitor = NULL;
136     free(output_info);
137 }
138
139 void
140 _output_refs_set(E_Randr_Output_Info *output_info)
141 {
142    Ecore_X_Randr_Crtc crtc, *crtcs = NULL;
143    E_Randr_Crtc_Info *crtc_info;
144    int ncrtcs = 0;
145
146    EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
147    EINA_SAFETY_ON_NULL_RETURN(output_info);
148
149    eina_list_free(output_info->possible_crtcs);
150
151    //Add possible crtcs
152    crtcs = ecore_x_randr_output_possible_crtcs_get(e_randr_screen_info.root, output_info->xid, &ncrtcs);
153    while (--ncrtcs >= 0)
154      {
155         if (!(crtc_info = _12_screen_info_crtc_info_get(crtcs[ncrtcs])))
156           continue;
157         output_info->possible_crtcs = eina_list_append(output_info->possible_crtcs, crtc_info);
158      }
159    free(crtcs);
160
161    crtc = ecore_x_randr_output_crtc_get(e_randr_screen_info.root, output_info->xid);
162    output_info->crtc = _12_screen_info_crtc_info_get(crtc);
163
164    if (output_info->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
165      output_info->monitor = _monitor_info_new(output_info);
166    else
167      output_info->monitor = NULL;
168 }
169
170 Ecore_X_Randr_Output *
171 _outputs_to_array(Eina_List *outputs_info)
172 {
173    Ecore_X_Randr_Output *ret = NULL;
174    E_Randr_Output_Info *output_info;
175    Eina_List *output_iter;
176    int i = 0;
177
178    if (!outputs_info || !(ret = malloc(sizeof(Ecore_X_Randr_Output) * eina_list_count(outputs_info)))) return NULL;
179    EINA_LIST_FOREACH(outputs_info, output_iter, output_info)
180       /* output_info == NULL should _not_ be possible! */
181       ret[i++] = output_info ? output_info->xid : Ecore_X_Randr_None;
182    return ret;
183 }
184
185 /*
186  * returns a list of modes common ammongst the given outputs,
187  * optionally limited by max_size_mode. If none are found, NULL is returned.
188  */
189 Eina_List
190 *_outputs_common_modes_get(Eina_List *outputs, Ecore_X_Randr_Mode_Info *max_size_mode)
191 {
192    Eina_List *common_modes = NULL, *mode_iter, *output_iter, *mode_next, *output_next;
193    E_Randr_Output_Info *output_info;
194    Ecore_X_Randr_Mode_Info *mode_info;
195
196    EINA_SAFETY_ON_NULL_RETURN_VAL(outputs, NULL);
197    EINA_SAFETY_ON_NULL_RETURN_VAL(e_randr_screen_info.rrvd_info.randr_info_12->modes, NULL);
198
199    //create a list of all common modes
200    common_modes = eina_list_clone(e_randr_screen_info.rrvd_info.randr_info_12->modes);
201    common_modes = eina_list_sort(common_modes, 0, _modes_size_sort_cb);
202
203    EINA_LIST_FOREACH_SAFE(common_modes, mode_iter, mode_next, mode_info)
204      {
205         EINA_LIST_FOREACH_SAFE(outputs, output_iter, output_next, output_info)
206           {
207              if (!output_info || !output_info->monitor)
208                continue;
209              if (!eina_list_data_find(output_info->monitor->modes, mode_info))
210                common_modes = eina_list_remove(common_modes, mode_info);
211           }
212      }
213
214    if (max_size_mode)
215      {
216         //remove all modes that are larger than max_size_mode
217         EINA_LIST_FOREACH_SAFE(common_modes, mode_iter, mode_next, mode_info)
218           {
219              if (_modes_size_sort_cb((void *)max_size_mode, (void *)mode_info) < 0)
220                common_modes = eina_list_remove(common_modes, mode_info);
221           }
222      }
223
224    //sort modes desc. by their sizes
225    common_modes = eina_list_reverse(common_modes);
226
227    return common_modes;
228 }
229
230 static int
231 _modes_size_sort_cb(const void *d1, const void *d2)
232 {
233    Ecore_X_Randr_Mode_Info *mode1 = ((Ecore_X_Randr_Mode_Info *)d1), *mode2 = ((Ecore_X_Randr_Mode_Info *)d2);
234
235    if (!d1) return 1;
236    if (!d2) return -1;
237
238    return (mode1->width * mode1->height) - (mode2->width * mode2->height);
239 }