2 #include "e_randr_private.h"
4 #define POLLINTERVAL 128
6 // Set functions for the global e_randr_screen_info struct
7 static void _screen_primary_output_assign(E_Randr_Output_Info *removed);
9 // Init helper functions
10 static void _outputs_init(void);
11 static void _crtcs_init(void);
12 static Eina_Bool _structs_init(void);
14 // Retrieval helper functions
15 static Ecore_X_Randr_Mode_Info *_mode_geo_identical_find(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode);
17 // Event helper functions
18 static Eina_Bool _x_poll_cb(void *data __UNUSED__);
19 static Eina_Bool _crtc_change_event_cb(void *data, int type, void *e);
20 static Eina_Bool _output_change_event_cb(void *data, int type, void *e);
21 static Eina_Bool _output_property_change_event_cb(void *data, int type, void *e);
23 static Ecore_Poller *poller = NULL;
24 static Eina_List *_event_handlers = NULL;
25 static const char *_CONNECTION_STATES_STRINGS[] = {"CONNECTED", "DISCONNECTED", "UNKNOWN"};
26 static const char *_POLICIES_STRINGS[] = {"ABOVE", "RIGHT", "BELOW", "LEFT", "CLONE", "NONE"};
28 //"New" helper functions
30 * @return array of E_Randr_Screen_Info_12 elements, or in case not all could
31 * be created or parameter 'nrequested'==0, NULL
33 static E_Randr_Screen_Info_12 *
34 _screen_info_12_new(void)
36 E_Randr_Screen_Info_12 *randr_info_12 = NULL;
38 EINA_SAFETY_ON_TRUE_RETURN_VAL((e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2), NULL);
40 randr_info_12 = E_NEW(E_Randr_Screen_Info_12, 1);
42 randr_info_12->min_size.width = Ecore_X_Randr_Unset;
43 randr_info_12->min_size.height = Ecore_X_Randr_Unset;
44 randr_info_12->max_size.width = Ecore_X_Randr_Unset;
45 randr_info_12->max_size.height = Ecore_X_Randr_Unset;
46 randr_info_12->current_size.width = Ecore_X_Randr_Unset;
47 randr_info_12->current_size.height = Ecore_X_Randr_Unset;
48 randr_info_12->crtcs = NULL;
49 randr_info_12->outputs = NULL;
50 randr_info_12->modes = NULL;
51 randr_info_12->primary_output = NULL;
52 randr_info_12->alignment = ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE;
54 ecore_x_randr_screen_size_range_get(e_randr_screen_info.root,
55 &randr_info_12->min_size.width,
56 &randr_info_12->min_size.height,
57 &randr_info_12->max_size.width,
58 &randr_info_12->max_size.height);
59 ecore_x_randr_screen_current_size_get(e_randr_screen_info.root,
60 &randr_info_12->current_size.width,
61 &randr_info_12->current_size.height,
71 Ecore_X_Randr_Output *outputs;
72 E_Randr_Output_Info *output_info = NULL;
75 Ecore_X_Randr_Crtc *crtcs = NULL;
76 E_Randr_Crtc_Info *crtc_info = NULL;
79 Ecore_X_Randr_Mode_Info **modes = NULL;
82 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, EINA_FALSE);
84 outputs = ecore_x_randr_outputs_get(e_randr_screen_info.root, &noutputs);
85 if (noutputs == 0) return EINA_FALSE;
87 while (--noutputs >= 0)
89 output_info = _output_info_new(outputs[noutputs]);
91 e_randr_screen_info.rrvd_info.randr_info_12->outputs = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->outputs, output_info);
95 crtcs = ecore_x_randr_crtcs_get(e_randr_screen_info.root, &ncrtcs);
96 if (ncrtcs == 0) return EINA_FALSE;
100 crtc_info = _crtc_info_new(crtcs[ncrtcs]);
101 e_randr_screen_info.rrvd_info.randr_info_12->crtcs = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, crtc_info);
105 modes = ecore_x_randr_modes_info_get(e_randr_screen_info.root, &nmodes);
106 if (nmodes == 0) return EINA_FALSE;
108 while (--nmodes >= 0)
110 e_randr_screen_info.rrvd_info.randr_info_12->modes = eina_list_append(e_randr_screen_info.rrvd_info.randr_info_12->modes, modes[nmodes]);
120 //Set value / retrieval helper functions
125 E_Randr_Crtc_Info *crtc = NULL;
128 EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
130 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc)
131 _crtc_refs_set(crtc);
137 E_Randr_Output_Info *output = NULL;
140 EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
142 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output)
144 _output_refs_set(output);
145 if (output->connection_status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
147 _monitor_info_free(output->monitor);
148 output->monitor = _monitor_info_new(output);
154 _screen_primary_output_assign(E_Randr_Output_Info *removed)
157 E_Randr_Output_Info *primary_output = NULL, *output_info;
159 EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO_OUTPUTS);
161 if (e_randr_screen_info.rrvd_info.randr_info_12->primary_output && (removed != e_randr_screen_info.rrvd_info.randr_info_12->primary_output)) return;
162 if (!(primary_output = _12_screen_info_output_info_get(ecore_x_randr_primary_output_get(e_randr_screen_info.root))))
164 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
166 if (!output_info || (output_info->connection_status != ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) || !output_info->crtc || !output_info->crtc->current_mode) continue;
167 primary_output = output_info;
171 e_randr_screen_info.rrvd_info.randr_info_12->primary_output = primary_output;
174 //"Free" helper functions
177 * @param screen_info the screen info to be freed.
180 _12_screen_info_free(E_Randr_Screen_Info_12 *screen_info)
182 Ecore_X_Randr_Mode_Info *mode_info;
183 E_Randr_Crtc_Info *crtc_info;
184 E_Randr_Output_Info *output_info;
186 EINA_SAFETY_ON_NULL_RETURN(screen_info);
187 EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
189 EINA_LIST_FREE(screen_info->crtcs, crtc_info)
190 _crtc_info_free(crtc_info);
192 EINA_LIST_FREE(screen_info->outputs, output_info)
193 _output_info_free(output_info);
195 EINA_LIST_FREE(screen_info->modes, mode_info)
196 ecore_x_randr_mode_info_free(mode_info);
202 *********************************************
204 * Getter functions for e_randr_screen_info struct
206 * ********************************************
208 Ecore_X_Randr_Mode_Info *
209 _12_screen_info_mode_info_get(const Ecore_X_Randr_Mode mode)
212 Ecore_X_Randr_Mode_Info *mode_info;
214 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_MODE(mode), NULL);
216 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->modes, iter, mode_info)
218 if (mode_info && (mode_info->xid == mode)) return mode_info;
223 E_Randr_Output_Info *
224 _12_screen_info_output_info_get(const Ecore_X_Randr_Output output)
227 E_Randr_Output_Info *output_info;
229 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_OUTPUTS, NULL);
231 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
233 if (output_info && (output_info->xid == output)) return output_info;
239 _12_screen_info_crtc_info_get(const Ecore_X_Randr_Crtc crtc)
242 E_Randr_Crtc_Info *crtc_info;
244 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_CRTCS, NULL);
246 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->crtcs, iter, crtc_info)
248 if (crtc_info && (crtc_info->xid == crtc)) return crtc_info;
254 _12_screen_info_edid_is_available(const E_Randr_Edid_Hash *hash)
257 E_Randr_Output_Info *output_info;
259 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO_OUTPUTS, EINA_FALSE);
260 EINA_SAFETY_ON_NULL_RETURN_VAL(hash, EINA_FALSE);
262 EINA_LIST_FOREACH(e_randr_screen_info.rrvd_info.randr_info_12->outputs, iter, output_info)
264 if (!output_info || !output_info->monitor)
266 if (output_info->monitor->edid_hash.hash == hash->hash)
273 * returns a mode within a given list of modes that is gemetrically identical.
274 * If none is found, NULL is returned.
276 static Ecore_X_Randr_Mode_Info *
277 _mode_geo_identical_find(Eina_List *modes, Ecore_X_Randr_Mode_Info *mode)
280 Ecore_X_Randr_Mode_Info *mode_info;
282 EINA_LIST_FOREACH(modes, iter, mode_info)
284 if ((mode_info->width == mode->width) && (mode_info->height == mode->height))
290 /*****************************************************************
292 * Init. and Shutdown code
294 *****************************************************************
297 _12_screen_info_refresh(void)
299 EINA_SAFETY_ON_TRUE_RETURN_VAL((e_randr_screen_info.randr_version < ECORE_X_RANDR_1_2), EINA_FALSE);
301 if (e_randr_screen_info.rrvd_info.randr_info_12)
302 _12_screen_info_free(e_randr_screen_info.rrvd_info.randr_info_12);
303 if (!(e_randr_screen_info.rrvd_info.randr_info_12 = _screen_info_12_new()) ||
307 _screen_primary_output_assign(NULL);
312 /******************************************************************
316 ******************************************************************
320 _x_poll_cb(void *data __UNUSED__)
322 EINA_SAFETY_ON_NULL_RETURN_VAL(e_randr_screen_info.rrvd_info.randr_info_12, ECORE_CALLBACK_CANCEL);
324 ecore_x_randr_screen_primary_output_orientations_get(e_randr_screen_info.root);
326 return ECORE_CALLBACK_RENEW;
330 _12_event_listeners_add(void)
332 EINA_SAFETY_ON_TRUE_RETURN(E_RANDR_12_NO);
334 ecore_x_randr_events_select(e_randr_screen_info.root, EINA_TRUE);
335 _event_handlers = eina_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, _crtc_change_event_cb, NULL));
336 _event_handlers = eina_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, _output_change_event_cb, NULL));
337 _event_handlers = eina_list_append(_event_handlers, ecore_event_handler_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, _output_property_change_event_cb, NULL));
338 // WORKAROUND problem of X not sending events
339 poller = ecore_poller_add(ECORE_POLLER_CORE, POLLINTERVAL, _x_poll_cb, NULL);
342 /* Usually events are triggered in the following order.
343 * (Dis)connect Display Scenario:
344 * 1.) ECORE_X_EVENT_OUTPUT_CHANGE //Triggered, when a display is connected to an
346 * 2.) ECORE_X_EVENT_CRTC_CHANGE //Triggered when the CRTC mode is changed (eg.
347 * enabled by e.g. e_randr or xrandr)
348 * 3.) ECORE_X_EVENT_OUTPUT_CHANGE //Triggered for each output changed by the
349 * preceeding enabling.
351 * When the mode of a CRTC is changed only events 2 and 3 are triggered
355 _output_change_event_cb(void *data __UNUSED__, int type, void *ev)
357 Ecore_X_Event_Randr_Output_Change *oce = (Ecore_X_Event_Randr_Output_Change *)ev;
358 E_Randr_Output_Info *output_info = NULL;
359 E_Randr_Crtc_Info *crtc_info = NULL;
360 Eina_Bool policy_success = EINA_FALSE, con_state_changed = EINA_FALSE;
362 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, ECORE_CALLBACK_CANCEL);
363 EINA_SAFETY_ON_TRUE_RETURN_VAL((type != ECORE_X_EVENT_RANDR_OUTPUT_CHANGE), ECORE_CALLBACK_RENEW);
365 /* event information:
367 Ecore_X_Randr_Output output;
368 Ecore_X_Randr_Crtc crtc;
369 Ecore_X_Randr_Mode mode;
370 Ecore_X_Randr_Orientation orientation;
371 Ecore_X_Randr_Connection_Status connection;
372 Ecore_X_Render_Subpixel_Order subpixel_order;
375 EINA_SAFETY_ON_FALSE_RETURN_VAL((output_info = _12_screen_info_output_info_get(oce->output)), ECORE_CALLBACK_RENEW);
377 DBG("E_RANDR: Output event: \n"
378 "\t\t: relative to win: %d\n"
379 "\t\t: output (xid): %d\n"
380 "\t\t: used by crtc (xid): %d\n"
382 "\t\t: orientation: %d\n"
383 "\t\t: connection state: %s\n"
384 "\t\t: subpixel_order: %d",
390 _CONNECTION_STATES_STRINGS[oce->connection],
391 oce->subpixel_order);
393 crtc_info = _12_screen_info_crtc_info_get(oce->crtc);
395 //Reason: Missing events, when an output is moved from one CRTC to
397 if (output_info->crtc && (crtc_info != output_info->crtc))
398 output_info->crtc->outputs = eina_list_remove(output_info->crtc->outputs, output_info);
400 output_info->crtc = crtc_info;
402 //Update mode references in case a mode was added manually
403 if (output_info->monitor)
405 eina_list_free(output_info->monitor->modes);
406 output_info->monitor->modes = NULL;
407 eina_list_free(output_info->monitor->preferred_modes);
408 output_info->monitor->preferred_modes = NULL;
409 _monitor_modes_refs_set(output_info->monitor, output_info->xid);
410 //Also update common modes of the used CRTC
411 if (crtc_info && crtc_info->current_mode)
413 eina_list_free(crtc_info->outputs);
414 crtc_info->outputs = NULL;
415 eina_list_free(crtc_info->outputs_common_modes);
416 crtc_info->outputs_common_modes = NULL;
417 _crtc_outputs_refs_set(crtc_info);
421 con_state_changed = (Eina_Bool)(output_info->connection_status != oce->connection);
422 output_info->connection_status = oce->connection;
423 output_info->subpixel_order = oce->subpixel_order;
425 if (con_state_changed)
427 _monitor_info_free(output_info->monitor);
428 output_info->monitor = NULL;
430 if (oce->connection == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)
432 //New device connected!
433 output_info->monitor = _monitor_info_new(output_info);
434 INF("E_RANDR: Output %d was newly connected.", output_info->xid);
436 //only try to enable the monitor if there is no serialized setup
437 if (!_12_try_restore_configuration())
439 policy_success = e_randr_12_try_enable_output(output_info, output_info->policy, EINA_FALSE); //maybe give a success message?
440 INF("E_RANDR: Policy \"%s\" was enforced %ssuccesfully.", _POLICIES_STRINGS[output_info->policy - 1], (policy_success ? "" : "un"));
445 //connection_state is 'unknown' or 'disconnected': treat as disconnected!
446 if (output_info->crtc)
448 output_info->crtc->outputs = eina_list_remove(output_info->crtc->outputs, output_info);
449 //in case this output was the last one connected on a CRTC,
451 if (eina_list_count(output_info->crtc->outputs) == 0)
453 //in case it was the only output running on this CRTC, disable
455 ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, output_info->crtc->xid, NULL, Ecore_X_Randr_None, Ecore_X_Randr_None);
458 //retry to find a suiting serialized setup for the remaining
460 _12_try_restore_configuration();
464 return ECORE_CALLBACK_RENEW;
468 _crtc_change_event_cb(void *data __UNUSED__, int type, void *ev)
470 Ecore_X_Event_Randr_Crtc_Change *cce = (Ecore_X_Event_Randr_Crtc_Change *)ev;
471 E_Randr_Crtc_Info *crtc_info;
473 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, ECORE_CALLBACK_CANCEL);
474 EINA_SAFETY_ON_TRUE_RETURN_VAL((type != ECORE_X_EVENT_RANDR_CRTC_CHANGE), ECORE_CALLBACK_RENEW);
476 /* event information:
478 Ecore_X_Randr_Crtc crtc;
479 Ecore_X_Randr_Mode mode;
480 Ecore_X_Randr_Orientation orientation;
486 DBG("E_RANDR: CRTC event: \n"
487 "\t\t: relative to win: %d\n"
488 "\t\t: crtc (xid): %d\n"
489 "\t\t: mode (xid): %d\n"
490 "\t\t: orientation: %d\n"
504 crtc_info = _12_screen_info_crtc_info_get(cce->crtc);
505 EINA_SAFETY_ON_NULL_RETURN_VAL(crtc_info, ECORE_CALLBACK_RENEW);
507 crtc_info->current_mode = _12_screen_info_mode_info_get(cce->mode);
508 crtc_info->current_orientation = cce->orientation;
509 crtc_info->geometry.x = cce->geo.x;
510 crtc_info->geometry.y = cce->geo.y;
511 crtc_info->geometry.w = cce->geo.w;
512 crtc_info->geometry.h = cce->geo.h;
514 //update screensize if necessary
515 e_randr_screen_info.rrvd_info.randr_info_12->current_size.width = MAX((cce->geo.x + cce->geo.w), e_randr_screen_info.rrvd_info.randr_info_12->current_size.width);
516 e_randr_screen_info.rrvd_info.randr_info_12->current_size.height = MAX((cce->geo.y + cce->geo.h), e_randr_screen_info.rrvd_info.randr_info_12->current_size.height);
519 eina_list_free(crtc_info->outputs);
520 crtc_info->outputs = NULL;
521 eina_list_free(crtc_info->outputs_common_modes);
522 crtc_info->outputs_common_modes = NULL;
524 //if still enabled, update references to outputs
525 if (crtc_info->current_mode)
527 eina_list_free(crtc_info->outputs);
528 crtc_info->outputs = NULL;
529 eina_list_free(crtc_info->outputs_common_modes);
530 crtc_info->outputs_common_modes = NULL;
531 _crtc_outputs_refs_set(crtc_info);
535 ecore_x_randr_screen_reset(e_randr_screen_info.root);
537 return ECORE_CALLBACK_RENEW;
541 _output_property_change_event_cb(void *data __UNUSED__, int type, void *ev)
543 Ecore_X_Event_Randr_Output_Property_Notify *opce = (Ecore_X_Event_Randr_Output_Property_Notify *)ev;
545 EINA_SAFETY_ON_TRUE_RETURN_VAL(E_RANDR_12_NO, ECORE_CALLBACK_CANCEL);
546 EINA_SAFETY_ON_TRUE_RETURN_VAL((type != ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY), ECORE_CALLBACK_RENEW);
548 /* event information:
550 Ecore_X_Randr_Output output;
551 Ecore_X_Atom property;
553 Ecore_X_Randr_Property_Change state;
555 EINA_SAFETY_ON_FALSE_RETURN_VAL((_12_screen_info_output_info_get(opce->output)), ECORE_CALLBACK_RENEW);
557 return ECORE_CALLBACK_RENEW;
561 * Try to enable this output on an unoccupied CRTC. 'Force' in this context
562 * means, that if there are only occupied CRTCs, we disable another output to
563 * enable this one. If not forced we will - if we don't find an unoccupied CRTC
564 * - try to share the output of a CRTC with other outputs already using it
568 e_randr_12_try_enable_output(E_Randr_Output_Info *output_info, Ecore_X_Randr_Output_Policy policy, Eina_Bool force)
570 Eina_List *iter, *outputs_list = NULL, *common_modes = NULL;
571 E_Randr_Crtc_Info *crtc_info = NULL, *usable_crtc = NULL;
572 const E_Randr_Crtc_Info *crtc_rel = NULL;
573 E_Randr_Output_Info *primary_output;
574 Ecore_X_Randr_Output *outputs;
575 Ecore_X_Randr_Mode_Info *mode_info;
576 int dx = Ecore_X_Randr_None, dy = Ecore_X_Randr_None;
577 Eina_Bool ret = EINA_TRUE;
579 EINA_SAFETY_ON_NULL_RETURN_VAL(output_info, EINA_FALSE);
580 EINA_SAFETY_ON_TRUE_RETURN_VAL((output_info->crtc && output_info->crtc->current_mode), EINA_FALSE);
583 * Try to find a usable crtc for this output. Either unused or forced.
585 EINA_LIST_FOREACH(output_info->possible_crtcs, iter, crtc_info)
587 if (!crtc_info->current_mode || !crtc_info->outputs || force)
589 usable_crtc = crtc_info;
595 * apparently we don't have a CRTC to make use of the device
600 //get the CRTC we will refer to, dependend on policy
603 case ECORE_X_RANDR_OUTPUT_POLICY_NONE:
606 case ECORE_X_RANDR_OUTPUT_POLICY_ASK:
607 e_randr_12_ask_dialog_new(output_info);
608 return EINA_TRUE; //This is a bit incorrect (dialog feedback is async), but probably not worth a lock.
610 case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
612 * Order of approaches to enable a clone (of the primary output):
614 * 0. Get Primary output from Server
615 * 1. Try to add new Output to primary output's CRTC, using the mode used
616 * by the primary output
617 * 2. Try to enable clone in the same
618 * 2a. exact mode or a
619 * 2b. geometrically identical mode
620 * 3. Find a most high resolution mode in common to enable on primary output's CRTC and the new
624 //Assign new output, if necessary
625 _screen_primary_output_assign(output_info);
626 if ((primary_output = e_randr_screen_info.rrvd_info.randr_info_12->primary_output))
628 if (primary_output->crtc && primary_output->crtc->current_mode && eina_list_data_find(output_info->monitor->modes, primary_output->crtc->current_mode))
631 * mode currently used by primary output's CRTC is also supported by the new output
633 if (eina_list_data_find(primary_output->crtc->possible_outputs, output_info) && eina_list_data_find(output_info->monitor->modes, primary_output->crtc->current_mode))
636 * 1. Try to add new Output to primary output's CRTC, using the mode used
637 * by the primary output
638 * TODO: check with compatibility list in RandRR >= 1.3
641 * The new output is also usable by the primary output's
642 * CRTC. Try to enable this output together with the already
643 * enabled outputs on the CRTC in already used mode.
645 outputs_list = primary_output->crtc->outputs;
646 outputs_list = eina_list_append(outputs_list, output_info);
647 outputs = _outputs_to_array(outputs_list);
648 primary_output->crtc->outputs = NULL;
649 ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, primary_output->crtc->xid, outputs, eina_list_count(outputs_list), primary_output->crtc->current_mode->xid);
651 eina_list_free(outputs_list);
657 * 2. Try to enable clone in the same
663 ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, primary_output->crtc->current_mode->xid);
664 ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info.rrvd_info.randr_info_12->alignment);
671 * 2b. geometrically identical mode
673 if (primary_output->crtc && (mode_info = _mode_geo_identical_find(output_info->monitor->modes, primary_output->crtc->current_mode)))
675 ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid);
676 ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info.rrvd_info.randr_info_12->alignment);
680 * 3. Find the highest resolution mode common to enable on primary output's CRTC and the new one.
682 if (((outputs_list = eina_list_append(outputs_list, primary_output)) && (outputs_list = eina_list_append(outputs_list, output_info))))
684 if (primary_output->crtc)
686 common_modes = _outputs_common_modes_get(outputs_list, primary_output->crtc->current_mode);
687 if ((mode_info = eina_list_nth(common_modes, 0)))
689 eina_list_free(common_modes);
690 INF("Will try to set mode: %dx%d for primary and clone.", mode_info->width, mode_info->height);
691 ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, primary_output->crtc->xid, ((Ecore_X_Randr_Output *)Ecore_X_Randr_Unset), Ecore_X_Randr_Unset, mode_info->xid);
692 ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid);
693 ret &= ecore_x_randr_crtc_pos_relative_set(e_randr_screen_info.root, usable_crtc->xid, primary_output->crtc->xid, ECORE_X_RANDR_OUTPUT_POLICY_CLONE, e_randr_screen_info.rrvd_info.randr_info_12->alignment);
696 eina_list_free(outputs_list);
701 ERR("E_RANDR: Failed to clone, because of missing or disabled primary output!");
708 //enable and position according to used policies
709 if (!(mode_info = ((Ecore_X_Randr_Mode_Info *)eina_list_data_get(output_info->monitor->preferred_modes))))
711 ERR("E_RANDR: Could not enable output(%d), as it has no preferred modes (and there for none at all)!", output_info->xid);
716 //get the crtc we will place our's relative to. If it's NULL, this is the
717 //only output attached, work done.
718 if (!(crtc_rel = _crtc_according_to_policy_get(usable_crtc, policy)))
720 INF("E_RANDR: CRTC %d enabled. No other CRTC had to be moved.", usable_crtc->xid);
721 ret &= ecore_x_randr_crtc_mode_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, mode_info->xid);
725 //Calculate new CRTC's position according to policy
728 case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
729 usable_crtc->geometry.x = crtc_rel->geometry.x;
730 usable_crtc->geometry.y = 0;
733 case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
734 usable_crtc->geometry.x = (crtc_rel->geometry.x + crtc_rel->geometry.w);
735 usable_crtc->geometry.y = crtc_rel->geometry.y;
738 case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
739 usable_crtc->geometry.x = crtc_rel->geometry.x;
740 usable_crtc->geometry.y = (crtc_rel->geometry.y + crtc_rel->geometry.h);
743 case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
744 usable_crtc->geometry.y = crtc_rel->geometry.y;
745 usable_crtc->geometry.x = 0;
749 usable_crtc->geometry.y = 0;
750 usable_crtc->geometry.x = 0;
753 if ((ret &= ecore_x_randr_crtc_settings_set(e_randr_screen_info.root, usable_crtc->xid, &output_info->xid, 1, usable_crtc->geometry.x, usable_crtc->geometry.y, mode_info->xid, ECORE_X_RANDR_ORIENTATION_ROT_0)))
756 //Reason: the CRTC event, that'd bring the new info about the set
757 //mode is arriving too late here.
758 usable_crtc->current_mode = mode_info;
759 usable_crtc->geometry.w = mode_info->width;
760 usable_crtc->geometry.h = mode_info->height;
763 INF("E_RANDR: Moved CRTC %d has geometry (x,y,wxh): %d, %d, %dx%d.", usable_crtc->xid, usable_crtc->geometry.x, usable_crtc->geometry.y, usable_crtc->geometry.w, usable_crtc->geometry.h);
764 //following is policy dependend.
767 case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
768 dy = (crtc_rel->geometry.y - usable_crtc->geometry.h);
771 //virtual move (move other CRTCs as nessesary)
773 ret &= ecore_x_randr_move_all_crtcs_but(e_randr_screen_info.root,
778 INF("E_RANDR: Moving all CRTCs but %d, by %dx%d delta.", usable_crtc->xid, dx, dy);
782 case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
783 dx = (crtc_rel->geometry.x - usable_crtc->geometry.w);
786 //virtual move (move other CRTCs as nessesary)
788 ret &= ecore_x_randr_move_all_crtcs_but(e_randr_screen_info.root,
793 INF("E_RANDR: Moving all CRTCs but %d, by %dx%d delta.", usable_crtc->xid, dx, dy);
804 ecore_x_randr_screen_reset(e_randr_screen_info.root);
810 _12_event_listeners_remove(void)
812 Ecore_Event_Handler *_event_handler = NULL;
814 EINA_LIST_FREE(_event_handlers, _event_handler)
815 ecore_event_handler_del(_event_handler);
816 ecore_poller_del(poller);