diff --git a/src/bin/e_randr.c b/src/bin/e_randr.c deleted file mode 100644 index 257e87163..000000000 --- a/src/bin/e_randr.c +++ /dev/null @@ -1,1419 +0,0 @@ -#include "e.h" - -/* TODO: Handle orientation in stored config */ -/* TODO: Ignore xrandr events triggered by changes in acpi cb */ -/* TODO: Clone mode */ -/* TODO: Lid at (x, y) == (0, 0) always */ -/* TODO: Implement left-of, right-of, above and below placement relative for outputs */ - -/* local function prototypes */ -static Eina_Bool _e_randr_config_load(void); -static void _e_randr_config_new(void); -static void _e_randr_config_free(void); -static void _e_randr_free(void); -static Eina_Bool _e_randr_config_cb_timer(void *data); -static void _e_randr_load(void); -static void _e_randr_apply(void); -static void _e_randr_output_mode_update(E_Randr_Output *cfg); -static E_Config_Randr_Output *_e_randr_config_output_new(void); -static E_Config_Randr_Output *_e_randr_config_output_find(E_Randr_Output *output); -static E_Randr_Crtc *_e_randr_crtc_find(Ecore_X_Randr_Crtc xid); -static E_Randr_Output *_e_randr_output_find(Ecore_X_Randr_Output xid); -static void _e_randr_output_crtc_find(E_Randr_Output *output); - -static void _e_randr_config_mode_geometry(Ecore_X_Randr_Orientation orient, Eina_Rectangle *rect); -static void _e_randr_config_primary_update(void); - -static Eina_Bool _e_randr_event_cb_screen_change(void *data, int type, void *event); -static Eina_Bool _e_randr_event_cb_crtc_change(void *data, int type, void *event); -static Eina_Bool _e_randr_event_cb_output_change(void *data, int type, void *event); - -static void _e_randr_acpi_handler_add(void *data); -static int _e_randr_is_lid(E_Randr_Output *cfg); -static void _e_randr_crtc_from_outputs_set(E_Randr_Crtc *crtc); -static Eina_Bool _e_randr_lid_update(void); -static Eina_Bool _e_randr_output_mode_valid(Ecore_X_Randr_Mode mode, Ecore_X_Randr_Mode *modes, int nmodes); -static void _e_randr_output_active_set(E_Randr_Output *output, Eina_Bool connected); -//static int _e_randr_config_output_cmp(const void *a, const void *b); -static char *_e_randr_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output output); - -/* local variables */ -static Eina_List *_randr_event_handlers = NULL; -static E_Config_DD *_e_randr_edd = NULL; -static E_Config_DD *_e_randr_output_edd = NULL; - -static int _e_randr_lid_is_closed = 0; - -/* external variables */ -EAPI E_Config_Randr *e_randr_cfg = NULL; -EAPI E_Randr *e_randr = NULL; - -/* private internal functions */ -EINTERN Eina_Bool -e_randr_init(void) -{ - /* check if randr is available */ - if (!ecore_x_randr_query()) return EINA_FALSE; - - /* get initial lid status */ - _e_randr_lid_is_closed = (e_acpi_lid_status_get() == E_ACPI_LID_CLOSED); - - /* try to load config */ - if (!_e_randr_config_load()) - { - /* NB: We should probably print an error here */ - return EINA_FALSE; - } - - /* tell randr that we are interested in receiving events - * - * NB: Requires RandR >= 1.2 */ - if (ecore_x_randr_version_get() >= E_RANDR_VERSION_1_2) - { - Ecore_X_Window root = 0; - - if ((root = ecore_x_window_root_first_get())) - ecore_x_randr_events_select(root, EINA_TRUE); - - /* setup randr event listeners */ - E_LIST_HANDLER_APPEND(_randr_event_handlers, - ECORE_X_EVENT_SCREEN_CHANGE, - _e_randr_event_cb_screen_change, NULL); - E_LIST_HANDLER_APPEND(_randr_event_handlers, - ECORE_X_EVENT_RANDR_CRTC_CHANGE, - _e_randr_event_cb_crtc_change, NULL); - E_LIST_HANDLER_APPEND(_randr_event_handlers, - ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, - _e_randr_event_cb_output_change, NULL); - } - - /* delay setting up acpi handler, as acpi is init'ed after randr */ - ecore_job_add(_e_randr_acpi_handler_add, NULL); - - return EINA_TRUE; -} - -EINTERN int -e_randr_shutdown(void) -{ - /* check if randr is available */ - if (!ecore_x_randr_query()) return 1; - - if (ecore_x_randr_version_get() >= E_RANDR_VERSION_1_2) - { - Ecore_X_Window root = 0; - - /* tell randr that we are not interested in receiving events anymore */ - if ((root = ecore_x_window_root_first_get())) - ecore_x_randr_events_select(root, EINA_FALSE); - } - - /* remove event listeners */ - E_FREE_LIST(_randr_event_handlers, ecore_event_handler_del); - - /* free config */ - _e_randr_free(); - _e_randr_config_free(); - - /* free edd */ - E_CONFIG_DD_FREE(_e_randr_output_edd); - E_CONFIG_DD_FREE(_e_randr_edd); - - return 1; -} - -/* public API functions */ -EAPI Eina_Bool -e_randr_config_save(void) -{ - /* save the new config */ - return e_config_domain_save("e_randr", _e_randr_edd, e_randr_cfg); -} - -EAPI void -e_randr_config_apply(void) -{ - Eina_List *l; - E_Randr_Output *output; - - /* Update output mode */ - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - printf("RR: apply out %p... [%s]\n", output, output->name); - if ((output->cfg) && (!output->cfg->connect)) - { - printf("RR: output disabled\n"); - _e_randr_output_active_set(output, EINA_FALSE); - } - else if ((output->cfg) && (output->status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)) - { - if (output->cfg) - { - printf("RR: output enabled [%i %i %ix%i | %2.3f orient %i]\n", - output->cfg->geo.x, output->cfg->geo.y, - output->cfg->geo.w, output->cfg->geo.h, - output->cfg->refresh_rate, output->cfg->orient); - printf("RR: update mode\n"); - _e_randr_output_mode_update(output); - printf("RR: active set...\n"); - _e_randr_output_active_set(output, EINA_TRUE); - printf("RR: active set done\n"); - } - else - printf("RR: no cfg\n"); - } - else - { - printf("RR: ???\n"); - } - } - printf("RR: ... lid update\n"); - /* update lid status */ - _e_randr_lid_update(); - - printf("RR: randr apply...\n"); - /* apply randr settings */ - _e_randr_apply(); - - printf("RR: update primary...\n"); - /* update primary output */ - _e_randr_config_primary_update(); -} - -EAPI double -e_randr_mode_refresh_rate_get(Ecore_X_Randr_Mode_Info *mode) -{ - double rate = 0.0; - - if (mode) - { - if ((mode->hTotal) && (mode->vTotal)) - rate = ((double)mode->dotClock / - ((double)mode->hTotal * (double)mode->vTotal)); - rate = round(rate); - } - - return rate; -} - -/* local functions */ -static Eina_Bool -_e_randr_config_load(void) -{ - Eina_Bool do_restore = EINA_TRUE; - - /* define edd for output config */ - _e_randr_output_edd = - E_CONFIG_DD_NEW("E_Config_Randr_Output", E_Config_Randr_Output); -#undef T -#undef D -#define T E_Config_Randr_Output -#define D _e_randr_output_edd - E_CONFIG_VAL(D, T, name, STR); - E_CONFIG_VAL(D, T, edid, STR); - E_CONFIG_VAL(D, T, orient, UINT); - E_CONFIG_VAL(D, T, geo.x, INT); - E_CONFIG_VAL(D, T, geo.y, INT); - E_CONFIG_VAL(D, T, geo.w, INT); - E_CONFIG_VAL(D, T, geo.h, INT); - E_CONFIG_VAL(D, T, refresh_rate, DOUBLE); - E_CONFIG_VAL(D, T, connect, UCHAR); - - /* define edd for randr config */ - _e_randr_edd = E_CONFIG_DD_NEW("E_Config_Randr", E_Config_Randr); -#undef T -#undef D -#define T E_Config_Randr -#define D _e_randr_edd - E_CONFIG_VAL(D, T, version, INT); - E_CONFIG_LIST(D, T, outputs, _e_randr_output_edd); - E_CONFIG_VAL(D, T, restore, UCHAR); - E_CONFIG_VAL(D, T, config_timestamp, ULL); - // TODO: primary must be name + edid - E_CONFIG_VAL(D, T, primary, UINT); - - /* try to load the randr config */ - if ((e_randr_cfg = e_config_domain_load("e_randr", _e_randr_edd))) - { - /* check randr config version */ - if (e_randr_cfg->version < (E_RANDR_CONFIG_FILE_EPOCH * 1000000)) - { - /* config is too old */ - do_restore = EINA_FALSE; - _e_randr_config_free(); - ecore_timer_add(1.0, _e_randr_config_cb_timer, - _("Settings data needed upgrading. Your old settings have
" - "been wiped and a new set of defaults initialized. This
" - "will happen regularly during development, so don't report a
" - "bug. This simply means Enlightenment needs new settings
" - "data by default for usable functionality that your old
" - "settings simply lack. This new set of defaults will fix
" - "that by adding it in. You can re-configure things now to your
" - "liking. Sorry for the hiccup in your settings.
")); - } - else if (e_randr_cfg->version > E_RANDR_CONFIG_FILE_VERSION) - { - /* config is too new */ - do_restore = EINA_FALSE; - _e_randr_config_free(); - ecore_timer_add(1.0, _e_randr_config_cb_timer, - _("Your settings are NEWER than Enlightenment. This is very
" - "strange. This should not happen unless you downgraded
" - "Enlightenment or copied the settings from a place where
" - "a newer version of Enlightenment was running. This is bad and
" - "as a precaution your settings have been now restored to
" - "defaults. Sorry for the inconvenience.
")); - } - } - - /* if config was too old or too new, then reload a fresh one */ - if (!e_randr_cfg) - { - _e_randr_config_new(); - do_restore = EINA_FALSE; - } - else - { -#define CONFIG_VERSION_CHECK(VERSION) \ - if (e_randr_cfg->version - (E_RANDR_CONFIG_FILE_EPOCH * 1000000) < (VERSION)) - CONFIG_VERSION_CHECK(4) - { - E_Config_Randr_Output *output; - Eina_List *l; - - /* Set refresh_rate to 60 */ - EINA_LIST_FOREACH(e_randr_cfg->outputs, l, output) - if (dblequal(output->refresh_rate, 0.0)) output->refresh_rate = 60.0; - } - } - - if (!e_randr_cfg) return EINA_FALSE; - - _e_randr_load(); - e_randr_config_save(); - - if ((do_restore) && (e_randr_cfg->restore)) - { - _e_randr_apply(); - } - - return EINA_TRUE; -} - -static void -_e_randr_config_new(void) -{ - Ecore_X_Window root = 0; - - /* create new randr cfg */ - if (!(e_randr_cfg = E_NEW(E_Config_Randr, 1))) - return; - - /* grab the root window once */ - root = ecore_x_window_root_first_get(); - - /* set version */ - e_randr_cfg->version = E_RANDR_CONFIG_FILE_VERSION; - - /* by default, restore config */ - e_randr_cfg->restore = EINA_TRUE; - - /* remember current primary */ - e_randr_cfg->primary = ecore_x_randr_primary_output_get(root); - - /* update recorded config timestamp */ - e_randr_cfg->config_timestamp = ecore_x_randr_config_timestamp_get(root); -} - -static void -_e_randr_config_free(void) -{ - E_Config_Randr_Output *output = NULL; - - /* safety check */ - if (!e_randr_cfg) return; - - /* loop the config outputs and free them */ - EINA_LIST_FREE(e_randr_cfg->outputs, output) - { - E_FREE(output); - } - - /* free the config */ - E_FREE(e_randr_cfg); -} - -static void -_e_randr_free(void) -{ - E_Randr_Crtc *crtc = NULL; - E_Randr_Output *output = NULL; - - /* safety check */ - if (!e_randr) return; - - /* loop the crtcs and free them */ - EINA_LIST_FREE(e_randr->crtcs, crtc) - { - free(crtc); - } - - /* loop the outputs and free them */ - EINA_LIST_FREE(e_randr->outputs, output) - { - free(output->name); - free(output->edid); - free(output); - } - - /* free the config */ - E_FREE(e_randr); -} - -static Eina_Bool -_e_randr_config_cb_timer(void *data) -{ - e_util_dialog_show(_("Randr Settings Upgraded"), "%s", (char *)data); - return EINA_FALSE; -} - -static char * -_e_randr_output_edid_string_get(Ecore_X_Window root, Ecore_X_Randr_Output output) -{ - unsigned char *edid = NULL; - unsigned long edid_len = 0; - char *edid_str = NULL; - - edid = ecore_x_randr_output_edid_get(root, output, &edid_len); - if (edid) - { - unsigned int k, kk; - - edid_str = malloc((edid_len * 2) + 1); - if (edid_str) - { - const char *hexch = "0123456789abcdef"; - - for (kk = 0, k = 0; k < edid_len; k++) - { - edid_str[kk ] = hexch[(edid[k] >> 4) & 0xf]; - edid_str[kk + 1] = hexch[ edid[k] & 0xf]; - kk += 2; - } - edid_str[kk] = 0; - } - free(edid); - } - return edid_str; -} - -/* function to map X's settings with E's settings */ -static void -_e_randr_load(void) -{ - Ecore_X_Window root = 0; - Ecore_X_Randr_Output *outputs = NULL; - int noutputs = 0; - Ecore_X_Randr_Crtc *crtcs = NULL; - int ncrtcs = 0, i = 0; - - e_randr = E_NEW(E_Randr, 1); - if (!e_randr) return; - - /* grab the root window once */ - root = ecore_x_window_root_first_get(); - - /* try to get the list of crtcs from x */ - if ((crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs))) - { - /* loop the crtcs */ - for (i = 0; i < ncrtcs; i++) - { - E_Randr_Crtc *crtc; - Ecore_X_Randr_Crtc_Info *cinfo; - - crtc = E_NEW(E_Randr_Crtc, 1); - if (!crtc) continue; - e_randr->crtcs = eina_list_append(e_randr->crtcs, crtc); - crtc->xid = crtcs[i]; - - /* get crtc info from X */ - if ((cinfo = ecore_x_randr_crtc_info_get(root, crtc->xid))) - { - crtc->geo.x = cinfo->x; - crtc->geo.y = cinfo->y; - crtc->geo.w = cinfo->width; - crtc->geo.h = cinfo->height; - crtc->mode = cinfo->mode; - crtc->orient = cinfo->rotation; - - ecore_x_randr_crtc_info_free(cinfo); - } - printf("RR: crtc found %x | %i %i %ix%i - %x . %i\n", - crtc->xid, - crtc->geo.x, crtc->geo.y, crtc->geo.w, crtc->geo.h, - crtc->mode, crtc->orient); - } - - free(crtcs); - } - printf("RR: ====================\n"); - /* try to get the list of outputs from x */ - if ((outputs = ecore_x_randr_outputs_get(root, &noutputs))) - { - int j = 0; - - for (j = 0; j < noutputs; j++) - { - E_Randr_Output *output = NULL; - Eina_Bool unknown = EINA_FALSE; - - output = E_NEW(E_Randr_Output, 1); - if (!output) continue; - - e_randr->outputs = eina_list_append(e_randr->outputs, output); - output->xid = outputs[j]; - output->name = _e_randr_output_name_get(root, output->xid); - output->is_lid = _e_randr_is_lid(output); - output->edid = _e_randr_output_edid_string_get(root, outputs[j]); - output->status = ecore_x_randr_output_connection_status_get(root, output->xid); - output->cfg = _e_randr_config_output_find(output); - if (!output->cfg) - { - output->cfg = _e_randr_config_output_new(); - if (output->name) output->cfg->name = strdup(output->name); - if (output->edid) output->cfg->edid = strdup(output->edid); - unknown = EINA_TRUE; - } - printf("RR: output %x %s %i %p\n", output->xid, output->name, output->status, output->cfg); - - /* find a crtc if we want this output connected */ - if (output->cfg->connect && - (output->status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)) - { - _e_randr_output_active_set(output, EINA_TRUE); - - if (output->crtc) - { - printf("RR: ouput on crtc = %p\n", output->crtc); - /* get orientation from crtc if not set */ - if (!output->cfg->orient) - output->cfg->orient = output->crtc->orient; - /* find mode for output */ - _e_randr_output_mode_update(output); - /* set position from crtc if unknown */ - if (unknown) - { - output->cfg->geo.x = output->crtc->geo.x; - output->cfg->geo.y = output->crtc->geo.y; - } - } - } - } - - free(outputs); - } - - /* update lid status */ - _e_randr_lid_update(); - - /* update primary output */ - _e_randr_config_primary_update(); - - /* update recorded config timestamp */ - e_randr_cfg->config_timestamp = ecore_x_randr_config_timestamp_get(root); - - /* save the config */ - e_randr_config_save(); -} - -static void -_e_randr_apply(void) -{ - E_Randr_Crtc *crtc; - Eina_List *l; - Ecore_X_Window root = 0; - int nw = 0, nh = 0; - int minw = 0, minh = 0; - int maxw = 0, maxh = 0; - int nx = INT_MAX, ny = INT_MAX; - - /* don't try to restore if we have fake screens */ - if (e_xinerama_fake_screens_exist()) return; - - /* grab the X server so that we can apply settings without triggering - * any randr event updates until we are done */ - ecore_x_grab(); - - /* get the root window */ - root = ecore_x_window_root_first_get(); - - /* get the min and max screen size */ - ecore_x_randr_screen_size_range_get(root, &minw, &minh, &maxw, &maxh); - printf("RRR0: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh); - nx = maxw; - ny = maxh; - nw = nh = 0; - EINA_LIST_FOREACH(e_randr->crtcs, l, crtc) - { - int x = 0, y = 0, w = 0, h = 0; - Ecore_X_Randr_Orientation orient = ECORE_X_RANDR_ORIENTATION_ROT_0; - Eina_Rectangle rect; - - printf("RRR0: crtc: %x %i %i %ix%i rot: %i mode: %i\n", crtc->xid, crtc->geo.x, crtc->geo.y, crtc->geo.w, crtc->geo.h, crtc->orient, crtc->mode); - if (!crtc->outputs) continue; - _e_randr_crtc_from_outputs_set(crtc); - if (crtc->mode == 0) continue; - x = crtc->geo.x; - y = crtc->geo.y; - orient = crtc->orient; - rect = crtc->geo; - _e_randr_config_mode_geometry(orient, &rect); - w = rect.w; - h = rect.h; - if (((x + w) > maxw) || ((y + h) > maxh)) continue; - if ((x + w) > nw) nw = x + w; - if ((y + h) > nh) nh = y + h; - if (x < nx) nx = x; - if (y < ny) ny = y; - } - /* Adjust size according to origo */ - nw -= nx; - nh -= ny; - /* apply the new screen size */ - printf("RRR1: current screen size: %ix%i\n", nw, nh); - ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1); - - nx = ny = nw = nh = 0; - /* loop our lists of crtcs */ - EINA_LIST_FOREACH(e_randr->crtcs, l, crtc) - { - E_Randr_Output *output; - Eina_List *ll; - int x = 0, y = 0, w = 0, h = 0; - Ecore_X_Randr_Mode mode = 0; - Ecore_X_Randr_Orientation orient = ECORE_X_RANDR_ORIENTATION_ROT_0; - Eina_Rectangle rect; - int count = 0; - Ecore_X_Randr_Output *coutputs; - - printf("RRR2: crtc: %x %i %i %ix%i rot: %i mode: %i\n", crtc->xid, crtc->geo.x, crtc->geo.y, crtc->geo.w, crtc->geo.h, crtc->orient, crtc->mode); - if (!crtc->outputs) - { - printf("RRR2: no outputs - off\n"); - ecore_x_randr_crtc_settings_set(root, crtc->xid, NULL, 0, 0, 0, 0, - ECORE_X_RANDR_ORIENTATION_ROT_0); - continue; - } - /* set config from connected outputs */ - _e_randr_crtc_from_outputs_set(crtc); - - x = crtc->geo.x; - y = crtc->geo.y; - mode = crtc->mode; - orient = crtc->orient; - - /* at this point, we should have geometry, mode and orientation. - * we can now proceed to calculate crtc size */ - rect = crtc->geo; - _e_randr_config_mode_geometry(orient, &rect); - w = rect.w; - h = rect.h; - - /* if the crtc does not fit, disable it */ - if (((x + w) > maxw) || ((y + h) > maxh) || (mode == 0)) - { - printf("RRR2: crtc dose not fit - off\n"); - ecore_x_randr_crtc_settings_set(root, crtc->xid, NULL, 0, 0, 0, 0, - ECORE_X_RANDR_ORIENTATION_ROT_0); - continue; - } - - /* find outputs to enable on crtc */ - coutputs = calloc(eina_list_count(crtc->outputs), sizeof(Ecore_X_Randr_Output)); - if (!coutputs) - { - printf("RRR2: cannot alloc coutputs\n"); - continue; - } - EINA_LIST_FOREACH(crtc->outputs, ll, output) - { - /* TODO: If this condition isn't true, the output should not be in crtc->outputs. - * crtc->outputs should only contain valid outputs */ - if ((output->cfg) && (output->crtc == crtc) && (output->mode) && - (output->status == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED)) - { - int i; - Eina_Bool ok; - - ok = EINA_TRUE; - /* TODO: This is wrong, one output shouldn't be twice in crtc list */ - for (i = 0; i < count; i++) - { - if (coutputs[i] == output->xid) - { - ok = EINA_FALSE; - printf("RRR: Error, same output twice on crtc."); - printf(" output: '%s' lid: %i active: %i status: %i\n", output->name, output->is_lid, output->active, output->status); - break; - } - } - if (ok) - { - printf("RRR2: add output %s\n", output->name); - coutputs[count] = output->xid; - count++; - } - } - } - - printf("RRR2: set mode %x | %i %i %ix%i | %x | %i\n", - crtc->xid, - crtc->geo.x, crtc->geo.y, crtc->geo.w, crtc->geo.h, - crtc->mode, crtc->orient); - /* apply our stored crtc settings */ - if (count > 0) - ecore_x_randr_crtc_settings_set(root, crtc->xid, coutputs, - count, crtc->geo.x, crtc->geo.y, - crtc->mode, crtc->orient); - else - { - printf("RRR2: no coutputs - off\n"); - ecore_x_randr_crtc_settings_set(root, crtc->xid, NULL, 0, 0, 0, 0, - ECORE_X_RANDR_ORIENTATION_ROT_0); - } - - /* cleanup */ - free(coutputs); - } - /* this moves screen to (0, 0) */ - ecore_x_randr_screen_reset(root); - /* release the server grab */ - ecore_x_ungrab(); -} - -static Eina_Bool -_e_randr_event_cb_screen_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_X_Event_Screen_Change *ev; - Eina_Bool changed = EINA_FALSE; - Ecore_X_Randr_Output primary = 0; - - ev = event; - - /* check if this event's root window is Our root window */ - if (ev->root != e_manager_current_get()->root) - return ECORE_CALLBACK_RENEW; - - primary = ecore_x_randr_primary_output_get(ev->root); - - if (e_randr_cfg->primary != primary) - { - e_randr_cfg->primary = primary; - changed = EINA_TRUE; - } - - if (e_randr_cfg->config_timestamp != ev->config_time) - { - e_randr_cfg->config_timestamp = ev->config_time; - changed = EINA_TRUE; - } - - if (changed) e_randr_config_save(); - - return ECORE_CALLBACK_RENEW; -} - -static Eina_Bool -_e_randr_event_cb_crtc_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_X_Event_Randr_Crtc_Change *ev; - E_Randr_Crtc *crtc; - - ev = event; - crtc = _e_randr_crtc_find(ev->crtc); - - if (!crtc) - { - crtc = E_NEW(E_Randr_Crtc, 1); - if (crtc) - { - e_randr->crtcs = eina_list_append(e_randr->crtcs, crtc); - crtc->xid = ev->crtc; - - crtc->geo = ev->geo; - crtc->mode = ev->mode; - crtc->orient = ev->orientation; - } - } - else - { - /* check (and update if needed) our crtc config */ - if ((ev->mode != crtc->mode) || - (ev->orientation != crtc->orient) || - (ev->geo.x != crtc->geo.x) || (ev->geo.y != crtc->geo.y) || - (ev->geo.w != crtc->geo.w) || (ev->geo.h != crtc->geo.h)) - { - crtc->mode = ev->mode; - crtc->orient = ev->orientation; - crtc->geo = ev->geo; - } - } - - return ECORE_CALLBACK_RENEW; -} - -static Eina_Bool -_e_randr_event_cb_output_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - Ecore_X_Event_Randr_Output_Change *ev; - E_Randr_Output *output; - Eina_Bool changed = EINA_FALSE; - - ev = event; - - /* check if this event's root window is Our root window */ - if (ev->win != e_manager_current_get()->root) - return ECORE_CALLBACK_RENEW; - - /* loop our crtcs and try to find this output */ - output = _e_randr_output_find(ev->output); - if (!output) - { - Ecore_X_Window root; - - root = ecore_x_window_root_first_get(); - - output = E_NEW(E_Randr_Output, 1); - if (!output) goto error; - e_randr->outputs = eina_list_append(e_randr->outputs, output); - output->xid = ev->output; - output->name = _e_randr_output_name_get(root, output->xid); - output->is_lid = _e_randr_is_lid(output); - output->edid = _e_randr_output_edid_string_get(root, ev->output); - changed = EINA_TRUE; - output->cfg = _e_randr_config_output_find(output); - if (!output->cfg) - { - output->cfg = _e_randr_config_output_new(); - if (output->name) output->cfg->name = strdup(output->name); - if (output->edid) output->cfg->edid = strdup(output->edid); - } - } - output->status = ev->connection; - - /* we know this output */ - if (output->is_lid && _e_randr_lid_is_closed) - { - /* ignore event from disconnected lid */ - } - else if (ev->connection == ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) - { - Eina_Bool unknown = EINA_FALSE; - - if ((!output->crtc) || (output->crtc->xid == 0)) unknown = EINA_TRUE; - - /* connected */ - if ((ev->crtc != 0) && ((!unknown) && (output->crtc->xid != ev->crtc))) - { - /* remove from old crtc */ - _e_randr_output_active_set(output, EINA_FALSE); - } - if ((!output->active) && (output->cfg->connect)) - { - _e_randr_output_active_set(output, EINA_TRUE); - - if (output->crtc) - { - /* connect to crtc */ - /* get orientation from crtc if not set */ - if (!output->cfg->orient) - output->cfg->orient = output->crtc->orient; - /* validate output mode */ - _e_randr_output_mode_update(output); - /* if unknown position at far right */ - if (unknown) - { - E_Randr_Output *other; - Eina_List *l; - - EINA_LIST_FOREACH(e_randr->outputs, l, other) - { - if ((other == output) || (!output->active)) continue; - if ((other->cfg->geo.x + other->cfg->geo.w) > output->cfg->geo.x) - output->cfg->geo.x = other->cfg->geo.x + other->cfg->geo.w; - } - } - } - changed = EINA_TRUE; - } - } - else if (ev->connection == ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED) - { - /* disconnected */ - if (output->active) - { - _e_randr_output_active_set(output, EINA_FALSE); - changed = EINA_TRUE; - } - } - - /* save the config if anything changed or we added a new one */ - if (changed) - { - _e_randr_lid_update(); - _e_randr_config_primary_update(); - _e_randr_apply(); - - e_randr_config_save(); - } - - return ECORE_CALLBACK_RENEW; -error: - free(output); - return ECORE_CALLBACK_RENEW; -} - -static Eina_Bool -_e_randr_event_cb_acpi(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) -{ - E_Event_Acpi *ev; - - ev = event; - - if (ev->type == E_ACPI_TYPE_LID) - { - Eina_Bool changed; - - _e_randr_lid_is_closed = (ev->status == E_ACPI_LID_CLOSED); - changed = _e_randr_lid_update(); - if (changed) - { - /* force new evaluation of primary */ - e_randr_cfg->primary = 0; - _e_randr_config_primary_update(); - _e_randr_apply(); - } - } - return ECORE_CALLBACK_RENEW; -} - -static void -_e_randr_output_mode_update(E_Randr_Output *output) -{ - Ecore_X_Window root = 0; - Ecore_X_Randr_Mode *modes = NULL; - int nmodes = 0, pref = 0; - Ecore_X_Randr_Mode_Info **mode_infos = NULL; - int nmode_infos = 0; - int i = 0; - - /* grab the root window */ - root = ecore_x_window_root_first_get(); - - printf("RR: ... 1 - %s\n", output->name); - /* get mode infos */ - mode_infos = ecore_x_randr_modes_info_get(root, &nmode_infos); - if (nmode_infos == 0) goto error; - printf("RR: ... 2\n"); - /* get the list of modes for this output */ - modes = ecore_x_randr_output_modes_get(root, output->xid, &nmodes, &pref); - if (nmodes == 0) goto error; - printf("RR: ... 3\n"); - - /* try to find the matching mode */ - output->mode = 0; - if ((output->cfg->geo.w != 0) && (output->cfg->geo.h != 0)) - { - printf("RR: ... 4\n"); - for (i = 0; i < nmode_infos; i++) - { - double rate = 0.0; - - rate = e_randr_mode_refresh_rate_get(mode_infos[i]); - printf("RR: ... 4.1 ... %i %1.3f cfg=%p modes=%p nmodes=%i\n", i, rate, output->cfg, modes, nmodes); - if ((mode_infos[i]->width == (unsigned int)output->cfg->geo.w) && - (mode_infos[i]->height == (unsigned int)output->cfg->geo.h) && - (dblequal(rate, output->cfg->refresh_rate)) && - (_e_randr_output_mode_valid(mode_infos[i]->xid, modes, nmodes))) - { - printf("RR: ... 4.2 - match %ix%i @ %2.3f\n", output->cfg->geo.w, output->cfg->geo.h, rate); - output->mode = mode_infos[i]->xid; - break; - } - printf("RR: ... 4.3\n"); - } - } - printf("RR: ... 5\n"); - - /* see if we can use the mode of the crtc */ - if ((!output->mode) && (output->crtc)) - { - E_Randr_Crtc *crtc; - - crtc = _e_randr_crtc_find(ecore_x_randr_output_crtc_get(root, output->xid)); - printf("RR: ... 6\n"); - if (crtc && crtc->mode) - { - printf("RR: ... 6.1\n"); - if (_e_randr_output_mode_valid(crtc->mode, modes, nmodes)) - output->mode = crtc->mode; - /* TODO: See if we have a mode of the same size with another mode id */ - } - } - printf("RR: ... 7\n"); - - /* set preferred mode */ - if (!output->mode) - { - printf("RR: ... 8\n"); - if (pref > 0) output->mode = modes[pref - 1]; - else output->mode = modes[0]; - } - - /* set width and height from mode */ - for (i = 0; i < nmode_infos; i++) - { - printf("RR: ... 9\n"); - if (mode_infos[i]->xid == output->mode) - { - output->cfg->geo.w = mode_infos[i]->width; - output->cfg->geo.h = mode_infos[i]->height; - output->cfg->refresh_rate = e_randr_mode_refresh_rate_get(mode_infos[i]); - printf("RR: ... 9.1 %ix%i @ %2.3f\n", output->cfg->geo.w, output->cfg->geo.h, output->cfg->refresh_rate); - break; - } - } - printf("RR: ... 10\n"); - - if (modes) free(modes); - if (mode_infos) - { - for (i = 0; i < nmode_infos; i++) free(mode_infos[i]); - free(mode_infos); - } - return; -error: - if (modes) free(modes); - if (mode_infos) - { - for (i = 0; i < nmode_infos; i++) - free(mode_infos[i]); - free(mode_infos); - } - output->cfg->geo.x = output->cfg->geo.y = output->cfg->geo.w = output->cfg->geo.h = 0; - output->cfg->refresh_rate = 0.0; - output->mode = 0; - return; -} - -static E_Config_Randr_Output * -_e_randr_config_output_new(void) -{ - E_Config_Randr_Output *cfg = NULL; - - if ((cfg = E_NEW(E_Config_Randr_Output, 1))) - { - /* all new outputs should connect automatically */ - /* TODO: config option */ - cfg->connect = EINA_TRUE; - - /* append this output config to randr config */ - e_randr_cfg->outputs = - eina_list_append(e_randr_cfg->outputs, cfg); - } - - return cfg; -} - -static E_Config_Randr_Output * -_e_randr_config_output_find(E_Randr_Output *output) -{ - Eina_List *l; - E_Config_Randr_Output *output_cfg; - char b1[4096], b2[4096]; - - /* TODO: We should not match outputs with unknown name and edid */ - snprintf(b1, sizeof(b1), "%s.%s", - output->name ? output->name : "???", - output->edid ? output->edid : "???"); - EINA_LIST_FOREACH(e_randr_cfg->outputs, l, output_cfg) - { - snprintf(b2, sizeof(b2), "%s.%s", - output_cfg->name ? output_cfg->name : "???", - output_cfg->edid ? output_cfg->edid : "???"); - if (!strcmp(b1, b2)) return output_cfg; - } - - return NULL; -} - -static E_Randr_Crtc * -_e_randr_crtc_find(Ecore_X_Randr_Crtc xid) -{ - Eina_List *l; - E_Randr_Crtc *crtc; - - EINA_LIST_FOREACH(e_randr->crtcs, l, crtc) - { - if (crtc->xid == xid) - return crtc; - } - - return NULL; -} - -static E_Randr_Output * -_e_randr_output_find(Ecore_X_Randr_Output xid) -{ - Eina_List *l; - E_Randr_Output *output; - - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - if (output->xid == xid) - return output; - } - - return NULL; -} - -static void -_e_randr_output_crtc_find(E_Randr_Output *output) -{ - Ecore_X_Window root = 0; - E_Randr_Crtc *crtc = NULL; - Ecore_X_Randr_Crtc *possible = NULL; - Ecore_X_Randr_Mode *modes = NULL; - Eina_List *l; - int num = 0, i = 0; - int nmodes, pref; - - /* grab the root window */ - root = ecore_x_window_root_first_get(); - - /* check if last is available */ - if ((crtc = _e_randr_crtc_find(ecore_x_randr_output_crtc_get(root, output->xid)))) - { - if (!crtc->outputs) - goto done; - } - - /* get a list of possible crtcs for this output */ - possible = ecore_x_randr_output_possible_crtcs_get(root, output->xid, &num); - if (num == 0) goto error; - - /* loop the possible crtcs */ - for (i = 0; i < num; i++) - { - if ((crtc = _e_randr_crtc_find(possible[i]))) - { - if (!crtc->outputs) - goto done; - } - } - - /* get the list of modes for this output */ - modes = ecore_x_randr_output_modes_get(root, output->xid, &nmodes, &pref); - if (nmodes == 0) - goto error; - - /* can we clone this output */ - for (i = 0; i < num; i++) - { - if ((crtc = _e_randr_crtc_find(possible[i]))) - { - /* check if mode is valid for this output */ - if (_e_randr_output_mode_valid(crtc->mode, modes, nmodes)) - goto done; - } - } - - /* last resort, just loop crtcs to find available */ - EINA_LIST_FOREACH(e_randr->crtcs, l, crtc) - { - if (!crtc->outputs) goto done; - crtc = NULL; - } - -error: - free(possible); - free(modes); - - output->crtc = NULL; - return; - -done: - free(possible); - free(modes); - - output->crtc = crtc; -} - -static void -_e_randr_config_mode_geometry(Ecore_X_Randr_Orientation orient, Eina_Rectangle *rect) -{ - int mw = 0, mh = 0; - - /* based on orientation, calculate mode sizes */ - switch (orient) - { - case ECORE_X_RANDR_ORIENTATION_ROT_0: - case ECORE_X_RANDR_ORIENTATION_ROT_180: - mw = rect->w; - mh = rect->h; - break; - case ECORE_X_RANDR_ORIENTATION_ROT_90: - case ECORE_X_RANDR_ORIENTATION_ROT_270: - mw = rect->h; - mh = rect->w; - break; - default: - break; - } - - rect->x = 0; - rect->y = 0; - rect->w = mw; - rect->h = mh; -} - -static void -_e_randr_config_primary_update(void) -{ - Ecore_X_Window root = 0; - Eina_List *l; - E_Randr_Output *output; - Ecore_X_Randr_Output primary = 0; - - /* check if we agree with system setup */ - root = ecore_x_window_root_first_get(); - primary = ecore_x_randr_primary_output_get(root); - /* see if our selected primary exists and is connected */ - output = _e_randr_output_find(e_randr_cfg->primary); - if ((!output) || (!output->active)) - e_randr_cfg->primary = 0; - - /* check if system primary is the same as ours */ - if ((primary > 0) && (primary == e_randr_cfg->primary)) return; - - if ((e_randr_cfg->primary > 0) && - output && output->active) - { - /* prefer our primary */ - ecore_x_randr_primary_output_set(root, e_randr_cfg->primary); - } - else - { - /* find lid */ - e_randr_cfg->primary = 0; - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - if (output->is_lid) - { - if (output->active) - e_randr_cfg->primary = output->xid; - break; - } - } - if (!e_randr_cfg->primary) - { - /* TODO: prefer top-left active monitor */ - /* no lid, use first existing */ - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - if (output->active) - { - e_randr_cfg->primary = output->xid; - break; - } - } - } - /* set primary */ - ecore_x_randr_primary_output_set(root, e_randr_cfg->primary); - } -} - -static void -_e_randr_acpi_handler_add(void *data EINA_UNUSED) -{ - E_LIST_HANDLER_APPEND(_randr_event_handlers, - E_EVENT_ACPI, - _e_randr_event_cb_acpi, NULL); -} - -static int -_e_randr_is_lid(E_Randr_Output *cfg) -{ - /* TODO: ecore_x_randr_output_connector_type_get */ - int ret = 0; - - if (!cfg->name) return 0; - if (strstr(cfg->name, "LVDS")) ret = 1; - else if (strstr(cfg->name, "lvds")) ret = 1; - else if (strstr(cfg->name, "Lvds")) ret = 1; - else if (strstr(cfg->name, "LCD")) ret = 1; - else if (strstr(cfg->name, "eDP")) ret = 1; - else if (strstr(cfg->name, "edp")) ret = 1; - else if (strstr(cfg->name, "EDP")) ret = 1; - return ret; -} - -static void -_e_randr_crtc_from_outputs_set(E_Randr_Crtc *crtc) -{ - E_Randr_Output *output; - Eina_List *l; - - EINA_LIST_FOREACH(crtc->outputs, l, output) - { - if (!output->active) continue; - /* TODO: If status != connected, active should not be set */ - if (output->status != ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED) - { - printf("RRR: Error, unconnected output which is active."); - printf(" output: '%s' lid: %i active: %i status: %i\n", - output->name, output->is_lid, output->active, output->status); - continue; - } - printf("RRR: output: '%s' lid: %i active: %i status: %i\n", output->name, output->is_lid, output->active, output->status); - /* TODO: Match all connected outputs, not only the first */ - crtc->mode = output->mode; - crtc->orient = output->cfg->orient; - crtc->geo = output->cfg->geo; - break; - } -} - -static Eina_Bool -_e_randr_lid_update(void) -{ - E_Randr_Output *output; - Eina_List *l; - Eina_Bool changed = EINA_FALSE; - int active_nonlid = 0; - - changed = EINA_FALSE; - /* Find all non-lids */ - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - if (output->is_lid) continue; - if (!output->active) continue; - active_nonlid++; - } - if (_e_randr_lid_is_closed && (active_nonlid > 0)) - { - /* Disable lids if closed and we have other monitors */ - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - Eina_Bool active; - - if (!output->is_lid) continue; - active = output->active; - _e_randr_output_active_set(output, EINA_FALSE); - if (active != output->active) changed = EINA_TRUE; - } - } - else - { - /* Enable lids */ - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - Eina_Bool active; - - if (!output->is_lid) continue; - if (output->cfg && output->cfg->connect) - { - active = output->active; - _e_randr_output_active_set(output, EINA_TRUE); - if (active != output->active) changed = EINA_TRUE; - } - } - } - - return changed; -} - -static Eina_Bool -_e_randr_output_mode_valid(Ecore_X_Randr_Mode mode, Ecore_X_Randr_Mode *modes, int nmodes) -{ - Eina_Bool valid = EINA_FALSE; - int i; - - for (i = 0; i < nmodes; i++) - { - if (modes[i] == mode) - { - valid = EINA_TRUE; - break; - } - } - return valid; -} - -static void -_e_randr_output_active_set(E_Randr_Output *output, Eina_Bool active) -{ - E_Randr_Crtc *crtc; - Eina_List *l; - - printf("RR: _e_randr_output_active_set... [%s] %i %i\n", output->name, output->active, active); - output->active = EINA_FALSE; - - /* Remove output from all crtcs */ - /* TODO: In theory the output should be only on one crtc, but to be sure... - * And we always do this be sure we have a good crtc */ - EINA_LIST_FOREACH(e_randr->crtcs, l, crtc) - { - crtc->outputs = - eina_list_remove(crtc->outputs, output); - } - output->crtc = NULL; - - if (active) - { - /* Find a crtc for the output */ - _e_randr_output_crtc_find(output); - if (output->crtc) - { - printf("RR: ... found crtc %i\n", active); - output->crtc->outputs = - eina_list_append(output->crtc->outputs, output); - output->active = EINA_TRUE; - } - } - printf("RR: _e_randr_output_active_set... done - %p\n", output->crtc); - - /* Track all active outputs */ - e_randr->active = 0; - EINA_LIST_FOREACH(e_randr->outputs, l, output) - { - if (output->active) e_randr->active++; - } -} - -static char * -_e_randr_output_name_get(Ecore_X_Window root, Ecore_X_Randr_Output output) -{ - char *name; - - name = ecore_x_randr_output_name_get(root, output, NULL); - if (!name) - { - - unsigned char *edid = NULL; - unsigned long edid_length = 0; - - /* get the edid for this output */ - if ((edid = - ecore_x_randr_output_edid_get(root, output, &edid_length))) - { - /* get output name */ - name = ecore_x_randr_edid_display_name_get(edid, edid_length); - - /* free any memory allocated from ecore_x_randr */ - free(edid); - } - } - return name; -} diff --git a/src/bin/e_randr.h b/src/bin/e_randr.h deleted file mode 100644 index 654a7e482..000000000 --- a/src/bin/e_randr.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifdef E_TYPEDEFS - -typedef struct _E_Config_Randr_Output E_Config_Randr_Output; -typedef struct _E_Config_Randr E_Config_Randr; - -typedef struct _E_Randr_Output E_Randr_Output; -typedef struct _E_Randr_Crtc E_Randr_Crtc; -typedef struct _E_Randr E_Randr; - -#else -# ifndef E_RANDR_H -# define E_RANDR_H - -#define E_RANDR_VERSION_1_1 ((1 << 16) | 1) -#define E_RANDR_VERSION_1_2 ((1 << 16) | 2) -#define E_RANDR_VERSION_1_3 ((1 << 16) | 3) -#define E_RANDR_VERSION_1_4 ((1 << 16) | 4) - -#define E_RANDR_CONFIG_FILE_EPOCH 5 -#define E_RANDR_CONFIG_FILE_GENERATION 1 -#define E_RANDR_CONFIG_FILE_VERSION \ - ((E_RANDR_CONFIG_FILE_EPOCH * 1000000) + E_RANDR_CONFIG_FILE_GENERATION) - -struct _E_Config_Randr_Output -{ - const char *name; - const char *edid; - - unsigned int orient; // value of the ecore_x_randr_orientation - Eina_Rectangle geo; // geometry - double refresh_rate; // calculated refresh rate - Eina_Bool connect; // does the user want this output connected -}; - -struct _E_Config_Randr -{ - int version; // INTERNAL CONFIG VERSION - - Eina_List *outputs; - - unsigned char restore; - unsigned long config_timestamp; - unsigned int primary; -}; - -struct _E_Randr_Output -{ - unsigned int xid; // ecore_x_randr output id (xid) - unsigned int mode; // ecore_x_randr mode id (xid) - char *name; // name of output - char *edid; // edid as a hex string - Eina_Bool is_lid; // is this a laptop panel - Eina_Bool active; // if this output is active - Ecore_X_Randr_Connection_Status status; - - E_Config_Randr_Output *cfg; - E_Randr_Crtc *crtc; -}; - -struct _E_Randr_Crtc -{ - unsigned int xid; // ecore_x_randr output id (xid) - - Eina_Rectangle geo; // geometry - unsigned int orient; // value of the ecore_x_randr_orientation - unsigned int mode; // ecore_x_randr mode id (xid) - Eina_List *outputs; // list of outputs for this crtc -}; - -struct _E_Randr -{ - int active; // number of active outputs - Eina_List *crtcs; // list of crtcs - Eina_List *outputs; // list of outputs -}; - -EINTERN Eina_Bool e_randr_init(void); -EINTERN int e_randr_shutdown(void); - -EAPI Eina_Bool e_randr_config_save(void); -EAPI void e_randr_config_apply(void); -EAPI double e_randr_mode_refresh_rate_get(Ecore_X_Randr_Mode_Info *mode); - -extern EAPI E_Config_Randr *e_randr_cfg; -extern EAPI E_Randr *e_randr; - -# endif -#endif diff --git a/src/bin/e_widget.c b/src/bin/e_widget.c index 8d94ff850..4b72f9d2e 100644 --- a/src/bin/e_widget.c +++ b/src/bin/e_widget.c @@ -130,18 +130,13 @@ e_widget_data_get(Evas_Object *obj) EAPI void e_widget_size_min_set(Evas_Object *obj, Evas_Coord minw, Evas_Coord minh) { - API_ENTRY return; - if (minw >= 0) sd->minw = minw; - if (minh >= 0) sd->minh = minh; evas_object_size_hint_min_set(obj, minw, minh); } EAPI void e_widget_size_min_get(Evas_Object *obj, Evas_Coord *minw, Evas_Coord *minh) { - API_ENTRY return; - if (minw) *minw = sd->minw; - if (minh) *minh = sd->minh; + evas_object_size_hint_min_get(obj, minw, minh); } static void @@ -508,8 +503,9 @@ e_widget_pointer_get(Evas_Object *obj) EAPI void e_widget_size_min_resize(Evas_Object *obj) { - API_ENTRY return; - evas_object_resize(obj, sd->minw, sd->minh); + Evas_Coord minw, minh; + evas_object_size_hint_min_get(obj, &minw, &minh); + evas_object_resize(obj, minw, minh); } /* local subsystem functions */