typedef Ecore_X_ID Ecore_X_Randr_Crtc;
typedef Ecore_X_ID Ecore_X_Randr_Mode;
typedef unsigned short Ecore_X_Randr_Size_ID;
+typedef int Ecore_X_Randr_Screen;
typedef Ecore_X_ID Ecore_X_Device;
ECORE_X_WINDOW_STACK_OPPOSITE = 4
} Ecore_X_Window_Stack_Mode;
-typedef enum _Ecore_X_Randr_Rotation {
- ECORE_X_RANDR_ROT_0 = (1 << 0),
- ECORE_X_RANDR_ROT_90 = (1 << 1),
- ECORE_X_RANDR_ROT_180 = (1 << 2),
- ECORE_X_RANDR_ROT_270 = (1 << 3),
- ECORE_X_RANDR_FLIP_X = (1 << 4),
- ECORE_X_RANDR_FLIP_Y = (1 << 5)
-} Ecore_X_Randr_Rotation;
-
-typedef enum _Ecore_X_Randr_Connection {
- ECORE_X_RANDR_CONNECTED = 0,
- ECORE_X_RANDR_DISCONNECTED = 1,
- ECORE_X_RANDR_UNKNOWN_CONNECTION = 2
-} Ecore_X_Randr_Connection;
+typedef enum _Ecore_X_Randr_Orientation {
+ ECORE_X_RANDR_ORIENTATION_ROT_0 = (1 << 0),
+ ECORE_X_RANDR_ORIENTATION_ROT_90 = (1 << 1),
+ ECORE_X_RANDR_ORIENTATION_ROT_180 = (1 << 2),
+ ECORE_X_RANDR_ORIENTATION_ROT_270 = (1 << 3),
+ ECORE_X_RANDR_ORIENTATION_FLIP_X = (1 << 4),
+ ECORE_X_RANDR_ORIENTATION_FLIP_Y = (1 << 5)
+} Ecore_X_Randr_Orientation;
+
+typedef enum _Ecore_X_Randr_Connection_Status {
+ ECORE_X_RANDR_CONNECTION_STATUS_CONNECTED = 0,
+ ECORE_X_RANDR_CONNECTION_STATUS_DISCONNECTED = 1,
+ ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN = 2
+} Ecore_X_Randr_Connection_Status;
+
+typedef enum _Ecore_X_Randr_Output_Policy {
+ ECORE_X_RANDR_OUTPUT_POLICY_ABOVE = 1,
+ ECORE_X_RANDR_OUTPUT_POLICY_RIGHT = 2,
+ ECORE_X_RANDR_OUTPUT_POLICY_BELOW = 3,
+ ECORE_X_RANDR_OUTPUT_POLICY_LEFT = 4,
+ ECORE_X_RANDR_OUTPUT_POLICY_CLONE = 5
+} Ecore_X_Randr_Output_Policy;
+
+typedef enum _Ecore_X_Randr_Relative_Alignment {
+ ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE = 0,
+ ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL = 1,
+ ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR = 2
+} Ecore_X_Randr_Relative_Alignment;
typedef enum _Ecore_X_Render_Subpixel_Order {
ECORE_X_RENDER_SUBPIXEL_ORDER_UNKNOWN = 0,
typedef struct _Ecore_X_Event_Generic Ecore_X_Event_Generic;
+typedef struct _Ecore_X_Randr_Screen_Size Ecore_X_Randr_Screen_Size;
+typedef struct _Ecore_X_Randr_Screen_Size_MM Ecore_X_Randr_Screen_Size_MM;
+
struct _Ecore_X_Event_Mouse_In
{
int modifiers;
Ecore_X_Sync_Alarm alarm;
};
+struct _Ecore_X_Randr_Screen_Size
+{
+ int width, height;
+};
+
+struct _Ecore_X_Randr_Screen_Size_MM
+{
+ int width, height, width_mm, height_mm;
+};
+
struct _Ecore_X_Event_Screen_Change
{
Ecore_X_Window win;
Ecore_X_Window root;
- int width;
- int height;
+ Ecore_X_Randr_Screen_Size_MM size; /* in pixel and millimeters */
Ecore_X_Time time;
Ecore_X_Time config_time;
- int mm_width; /* in millimeters */
- int mm_height; /* in millimeters */
- Ecore_X_Randr_Rotation rotation;
+ Ecore_X_Randr_Orientation orientation;
Ecore_X_Render_Subpixel_Order subpixel_order;
Ecore_X_Randr_Size_ID size_id;
};
struct _Ecore_X_Event_Randr_Crtc_Change
{
- Ecore_X_Window win;
- Ecore_X_Randr_Crtc crtc;
- Ecore_X_Randr_Mode mode;
- Ecore_X_Randr_Rotation rotation;
- int x;
- int y;
- int width;
- int height;
+ Ecore_X_Window win;
+ Ecore_X_Randr_Crtc crtc;
+ Ecore_X_Randr_Mode mode;
+ Ecore_X_Randr_Orientation orientation;
+ Eina_Rectangle geo;
};
struct _Ecore_X_Event_Randr_Output_Change
{
- Ecore_X_Window win;
- Ecore_X_Randr_Output output;
- Ecore_X_Randr_Crtc crtc;
- Ecore_X_Randr_Mode mode;
- Ecore_X_Randr_Rotation rotation;
- Ecore_X_Randr_Connection connection;
- Ecore_X_Render_Subpixel_Order subpixel_order;
+ Ecore_X_Window win;
+ Ecore_X_Randr_Output output;
+ Ecore_X_Randr_Crtc crtc;
+ Ecore_X_Randr_Mode mode;
+ Ecore_X_Randr_Orientation orientation;
+ Ecore_X_Randr_Connection_Status connection;
+ Ecore_X_Render_Subpixel_Order subpixel_order;
};
struct _Ecore_X_Event_Randr_Output_Property_Notify
Ecore_X_Rectangle *rect);
/* ecore_x_randr.c */
-typedef struct _Ecore_X_Screen_Size Ecore_X_Screen_Size;
-struct _Ecore_X_Screen_Size
-{
- int width, height;
-};
-typedef struct _Ecore_X_Screen_Refresh_Rate Ecore_X_Screen_Refresh_Rate;
-struct _Ecore_X_Screen_Refresh_Rate
-{
- int rate;
-};
+/* The usage of 'Ecore_X_Randr_None' or 'Ecore_X_Randr_Unset'
+ * depends on the context. In most cases 'Ecore_X_Randr_Unset'
+ * can be used, but in some cases -1 is a special value to
+ * functions, thus 'Ecore_X_Randr_None' (=0) musst be used.
+ */
-EAPI int ecore_x_randr_query(void);
-EAPI int ecore_x_randr_events_select(
- Ecore_X_Window win,
- int on);
-EAPI void ecore_x_randr_get_screen_info_prefetch(
- Ecore_X_Window window);
-EAPI void ecore_x_randr_get_screen_info_fetch(void);
-EAPI Ecore_X_Randr_Rotation ecore_x_randr_screen_rotations_get(
+typedef short Ecore_X_Randr_Refresh_Rate;
+typedef int Ecore_X_Randr_Crtc_Gamma;
+typedef int Ecore_X_Randr_Signal_Format;
+typedef int Ecore_X_Randr_Signal_Property;
+typedef int Ecore_X_Randr_Connector_Type;
+
+typedef struct _Ecore_X_Randr_Mode_Info
+{
+ Ecore_X_ID xid;
+ unsigned int width;
+ unsigned int height;
+ unsigned long dotClock;
+ unsigned int hSyncStart;
+ unsigned int hSyncEnd;
+ unsigned int hTotal;
+ unsigned int hSkew;
+ unsigned int vSyncStart;
+ unsigned int vSyncEnd;
+ unsigned int vTotal;
+ char *name;
+ unsigned int nameLength;
+ unsigned long modeFlags;
+} Ecore_X_Randr_Mode_Info;
+
+EAPI int ecore_x_randr_version_get(
+ void);
+EAPI const Eina_Bool ecore_x_randr_query(void);
+
+/* ecore_x_randr_11.c */
+EAPI Ecore_X_Randr_Orientation
+ ecore_x_randr_screen_primary_output_orientations_get(
Ecore_X_Window root);
-EAPI Ecore_X_Randr_Rotation ecore_x_randr_screen_rotation_get(
+EAPI Ecore_X_Randr_Orientation
+ ecore_x_randr_screen_primary_output_orientation_get(
Ecore_X_Window root);
-EAPI void ecore_x_randr_screen_rotation_set(
- Ecore_X_Window root,
- Ecore_X_Randr_Rotation rot);
-EAPI Ecore_X_Screen_Size * ecore_x_randr_screen_sizes_get(
+EAPI Eina_Bool
+ ecore_x_randr_screen_primary_output_orientation_set(
Ecore_X_Window root,
- int *num);
-EAPI Ecore_X_Screen_Size ecore_x_randr_current_screen_size_get(
- Ecore_X_Window root);
-EAPI int ecore_x_randr_screen_size_set(
- Ecore_X_Window root,
- Ecore_X_Screen_Size size);
-
-EAPI Ecore_X_Screen_Refresh_Rate * ecore_x_randr_screen_refresh_rates_get(
+ Ecore_X_Randr_Orientation
+ orientation);
+EAPI Ecore_X_Randr_Screen_Size_MM *
+ ecore_x_randr_screen_primary_output_sizes_get(
Ecore_X_Window root,
- int size_id,
- int *num);
-EAPI Ecore_X_Screen_Refresh_Rate ecore_x_randr_current_screen_refresh_rate_get(
+ int *num);
+EAPI void
+ ecore_x_randr_screen_primary_output_current_size_get(
+ Ecore_X_Window root,
+ int *w,
+ int *h,
+ int *w_mm,
+ int *h_mm,
+ int *size_index);
+EAPI Eina_Bool
+ecore_x_randr_screen_primary_output_size_set(Ecore_X_Window root,
+ int size_index);
+EAPI Ecore_X_Randr_Refresh_Rate
+ecore_x_randr_screen_primary_output_current_refresh_rate_get(
Ecore_X_Window root);
+EAPI Ecore_X_Randr_Refresh_Rate *
+ecore_x_randr_screen_primary_output_refresh_rates_get(Ecore_X_Window root,
+ int size_index,
+ int *num);
+EAPI Eina_Bool
+ecore_x_randr_screen_primary_output_refresh_rate_set(
+ Ecore_X_Window root,
+ int size_index,
+ Ecore_X_Randr_Refresh_Rate
+ rate);
+
+/* ecore_x_randr_12.c */
+EAPI void
+ecore_x_randr_events_select(Ecore_X_Window win,
+ Eina_Bool on);
-EAPI int ecore_x_randr_screen_refresh_rate_set(
- Ecore_X_Window root,
- Ecore_X_Screen_Size size,
- Ecore_X_Screen_Refresh_Rate rate);
+EAPI void
+ecore_x_randr_screen_current_size_get(Ecore_X_Window root,
+ int *w,
+ int *h,
+ int *w_mm,
+ int *h_mm);
+EAPI void
+ ecore_x_randr_screen_size_range_get(Ecore_X_Window root,
+ int *wmin,
+ int *hmin,
+ int *wmax,
+ int *hmax);
+EAPI void ecore_x_randr_screen_reset(
+ Ecore_X_Window root);
+EAPI Eina_Bool
+ ecore_x_randr_screen_current_size_set(Ecore_X_Window root,
+ int w,
+ int h,
+ int w_mm,
+ int h_mm);
+EAPI Ecore_X_Randr_Mode_Info **
+ ecore_x_randr_modes_info_get(Ecore_X_Window root,
+ int *num);
+EAPI Ecore_X_Randr_Mode_Info *
+ ecore_x_randr_mode_info_get(Ecore_X_Window root,
+ Ecore_X_Randr_Mode mode);
+EAPI void
+ ecore_x_randr_mode_info_free(
+ Ecore_X_Randr_Mode_Info *mode_info);
+EAPI Ecore_X_Randr_Crtc * ecore_x_randr_crtcs_get(
+ Ecore_X_Window root,
+ int *num);
+EAPI Ecore_X_Randr_Output *ecore_x_randr_outputs_get(
+ Ecore_X_Window root,
+ int *num);
+EAPI Ecore_X_Randr_Output *
+ ecore_x_randr_current_output_get(
+ Ecore_X_Window window,
+ int *num);
+EAPI Ecore_X_Randr_Crtc *
+ ecore_x_randr_current_crtc_get(Ecore_X_Window window,
+ int *num);
+EAPI Ecore_X_Randr_Output *
+ ecore_x_randr_crtc_outputs_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *num);
+EAPI Ecore_X_Randr_Output *
+ ecore_x_randr_crtc_possible_outputs_get(
+ Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *num);
+EAPI void
+ ecore_x_randr_crtc_geometry_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *x,
+ int *y,
+ int *w,
+ int *h);
+EAPI void
+ecore_x_randr_crtc_pos_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *x,
+ int *y);
+EAPI Eina_Bool
+ecore_x_randr_crtc_pos_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int x,
+ int y);
+EAPI Ecore_X_Randr_Mode
+ecore_x_randr_crtc_mode_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc);
+EAPI Eina_Bool
+ecore_x_randr_crtc_mode_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Output *outputs,
+ int noutputs,
+ Ecore_X_Randr_Mode mode);
+EAPI void
+ecore_x_randr_crtc_size_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *w,
+ int *h);
+EAPI Ecore_X_Randr_Refresh_Rate
+ecore_x_randr_crtc_refresh_rate_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Mode mode);
+EAPI Ecore_X_Randr_Orientation
+ecore_x_randr_crtc_orientations_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc);
+EAPI Ecore_X_Randr_Orientation
+ecore_x_randr_crtc_orientation_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc);
+EAPI Eina_Bool
+ecore_x_randr_crtc_orientation_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ const Ecore_X_Randr_Orientation orientation);
+EAPI Eina_Bool
+ecore_x_randr_crtc_clone_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc original,
+ Ecore_X_Randr_Crtc clone);
+EAPI Eina_Bool
+ecore_x_randr_crtc_settings_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Output *outputs,
+ int noutputs,
+ int x,
+ int y,
+ Ecore_X_Randr_Mode mode,
+ Ecore_X_Randr_Orientation orientation);
+EAPI Eina_Bool
+ecore_x_randr_crtc_pos_relative_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc_r1,
+ Ecore_X_Randr_Crtc crtc_r2,
+ Ecore_X_Randr_Output_Policy policy,
+ Ecore_X_Randr_Relative_Alignment alignment);
+EAPI Ecore_X_Randr_Mode *
+ ecore_x_randr_output_modes_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *num,
+ int *npreferred);
+EAPI Ecore_X_Randr_Output * ecore_x_randr_output_clones_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num);
+EAPI Ecore_X_Randr_Crtc * ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num);
+EAPI Ecore_X_Randr_Crtc
+ ecore_x_randr_output_crtc_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI char *
+ ecore_x_randr_output_name_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *len);
+EAPI int
+ ecore_x_randr_crtc_gamma_ramp_size_get(
+ Ecore_X_Randr_Crtc crtc);
+EAPI Ecore_X_Randr_Crtc_Gamma **
+ ecore_x_randr_crtc_gamma_ramps_get(Ecore_X_Randr_Crtc crtc);
+EAPI Eina_Bool
+ ecore_x_randr_crtc_gamma_ramps_set(Ecore_X_Randr_Crtc crtc,
+ const Ecore_X_Randr_Crtc_Gamma *red,
+ const Ecore_X_Randr_Crtc_Gamma *green,
+ const Ecore_X_Randr_Crtc_Gamma *blue);
+EAPI Eina_Bool
+ ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root,
+ const Ecore_X_Randr_Crtc *not_moved,
+ int nnot_moved,
+ int dx,
+ int dy);
+EAPI Eina_Bool ecore_x_randr_move_crtcs(
+ Ecore_X_Window root,
+ const Ecore_X_Randr_Crtc *crtcs,
+ int ncrtc,
+ int dx,
+ int dy);
+EAPI void
+ecore_x_randr_mode_size_get(Ecore_X_Window root,
+ Ecore_X_Randr_Mode mode,
+ int *w,
+ int *h);
+EAPI Ecore_X_Randr_Connection_Status
+ecore_x_randr_output_connection_status_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI void
+ecore_x_randr_output_size_mm_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *w,
+ int *h);
+EAPI Eina_Bool
+ecore_x_randr_output_crtc_set(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ const Ecore_X_Randr_Crtc crtc);
+
+/* ecore_x_randr_13.c */
+EAPI void
+ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root, double level);
+EAPI double
+ecore_x_randr_output_backlight_level_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI Eina_Bool
+ecore_x_randr_output_backlight_level_set(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ double level);
+EAPI Ecore_X_Randr_Output
+ecore_x_randr_primary_output_get(Ecore_X_Window root);
+EAPI void
+ecore_x_randr_primary_output_set(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI Ecore_X_Render_Subpixel_Order
+ecore_x_randr_output_subpixel_order_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI unsigned char *
+ecore_x_randr_output_edid_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ unsigned long *length);
+EAPI Ecore_X_Randr_Output *
+ecore_x_randr_output_wired_clones_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *num);
+EAPI Ecore_X_Randr_Output **
+ecore_x_randr_output_compatibility_list_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *num);
+EAPI Ecore_X_Randr_Signal_Format *
+ecore_x_randr_output_signal_formats_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *num);
+EAPI Eina_Bool
+ecore_x_randr_output_signal_format_set(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ Ecore_X_Randr_Signal_Format *signal);
+EAPI Ecore_X_Randr_Signal_Property *
+ecore_x_randr_output_signal_properties_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *num);
+EAPI int
+ecore_x_randr_output_connector_number_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI Ecore_X_Randr_Connector_Type
+ecore_x_randr_output_connector_type_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output);
+EAPI Eina_Rectangle *
+ecore_x_randr_crtc_panning_area_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *x,
+ int *y,
+ int *w,
+ int *h);
+EAPI Eina_Bool
+ecore_x_randr_crtc_panning_area_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int x,
+ const int y,
+ const int w,
+ const int h);
+EAPI Eina_Rectangle *
+ecore_x_randr_crtc_tracking_area_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *x,
+ int *y,
+ int *w,
+ int *h);
+EAPI Eina_Bool
+ecore_x_randr_crtc_tracking_area_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int x,
+ const int y,
+ const int w,
+ const int h);
+EAPI Eina_Rectangle *
+ecore_x_randr_crtc_border_area_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc);
+EAPI Eina_Bool
+ecore_x_randr_crtc_border_area_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int left,
+ const int top,
+ const int right,
+ const int bottom);
/* XRender Support (horrendously incomplete) */
typedef Ecore_X_ID Ecore_X_Picture;
# include <config.h>
#endif /* ifdef HAVE_CONFIG_H */
-#include <stdlib.h>
-
#include "ecore_x_private.h"
+#include "ecore_x_inline.x"
-static int _randr_available = 0;
+static Eina_Bool _randr_available = EINA_FALSE;
#ifdef ECORE_XRANDR
-static int _randr_major, _randr_minor, _randr_version;
+static int _randr_major, _randr_minor;
+int _randr_version;
+#define RANDR_1_1 ((1 << 16) | 1)
#define RANDR_1_2 ((1 << 16) | 2)
#define RANDR_1_3 ((1 << 16) | 3)
+
+#define RANDR_VALIDATE_ROOT(screen, \
+ root) ((screen = \
+ XRRRootToScreen(_ecore_x_disp, \
+ root)) != -1)
+
+#define Ecore_X_Randr_Unset -1
+
+XRRScreenResources * (*_ecore_x_randr_get_screen_resources)(Display * dpy,
+ Window window);
+
#endif /* ifdef ECORE_XRANDR */
void
_randr_minor = 3;
_randr_version = 0;
+ _ecore_x_disp = _ecore_x_disp;
+ _ecore_x_randr_get_screen_resources = NULL;
if (XRRQueryVersion(_ecore_x_disp, &_randr_major, &_randr_minor))
- {
- _randr_version = (_randr_major << 16) | _randr_minor;
- _randr_available = 1;
- }
+ {
+ _randr_version = (_randr_major << 16) | _randr_minor;
+ if (_randr_version >= RANDR_1_3)
+ _ecore_x_randr_get_screen_resources = XRRGetScreenResourcesCurrent;
+ else if (_randr_version == RANDR_1_2)
+ _ecore_x_randr_get_screen_resources = XRRGetScreenResources;
+
+ _randr_available = EINA_TRUE;
+ }
else
- _randr_available = 0;
-
-#else /* ifdef ECORE_XRANDR */
- _randr_available = 0;
-#endif /* ifdef ECORE_XRANDR */
-} /* _ecore_x_randr_init */
-
-EAPI int
+ _randr_available = EINA_FALSE;
+
+#else
+ _randr_available = EINA_FALSE;
+#endif
+}
+
+/*
+ * @brief query whether randr is available or not
+ * @return EINA_TRUE, if extension is available, else EINA_FALSE
+ */
+EAPI const Eina_Bool
ecore_x_randr_query(void)
{
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
return _randr_available;
-} /* ecore_x_randr_query */
+}
+/*
+ * @return version of the RandRR extension supported by the server or,
+ * in case RandRR extension is not available, Ecore_X_Randr_Unset (=-1).
+ * bit version information: 31 MAJOR 16 | 15 MINOR 0
+ */
EAPI int
-ecore_x_randr_events_select(Ecore_X_Window win, int on)
+ecore_x_randr_version_get(void)
{
#ifdef ECORE_XRANDR
- int mask;
-
LOGFN(__FILE__, __LINE__, __FUNCTION__);
- if (!on)
- mask = 0;
+ if (_randr_available)
+ {
+ return _randr_version;
+ }
else
- {
- mask = RRScreenChangeNotifyMask;
- if (_randr_version >= RANDR_1_2)
- mask |= (RRCrtcChangeNotifyMask |
- RROutputChangeNotifyMask |
- RROutputPropertyNotifyMask);
- }
+ {
+ return Ecore_X_Randr_Unset;
+ }
- XRRSelectInput(_ecore_x_disp, win, mask);
+#endif
+}
- return 1;
-#else /* ifdef ECORE_XRANDR */
- return 0;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_events_select */
-
-EAPI Ecore_X_Randr_Rotation
-ecore_x_randr_screen_rotations_get(Ecore_X_Window root)
+inline Eina_Bool
+_ecore_x_randr_root_validate(Ecore_X_Window root)
{
#ifdef ECORE_XRANDR
- Rotation rot, crot;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- rot = XRRRotations(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp,
- root), &crot);
- return rot;
-#else /* ifdef ECORE_XRANDR */
- return 0;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_rotations_get */
-
-EAPI Ecore_X_Randr_Rotation
-ecore_x_randr_screen_rotation_get(Ecore_X_Window root)
-{
-#ifdef ECORE_XRANDR
- Rotation crot = 0;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- XRRRotations(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &crot);
- return crot;
-#else /* ifdef ECORE_XRANDR */
- return 0;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_rotation_get */
-
-EAPI void
-ecore_x_randr_screen_rotation_set(Ecore_X_Window root,
- Ecore_X_Randr_Rotation rot)
-{
-#ifdef ECORE_XRANDR
- XRRScreenConfiguration *xrrcfg;
- SizeID sizeid;
- Rotation crot;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- xrrcfg = XRRGetScreenInfo(_ecore_x_disp, root);
- if (!xrrcfg)
- return;
-
- sizeid = XRRConfigCurrentConfiguration(xrrcfg, &crot);
- XRRSetScreenConfig(_ecore_x_disp, xrrcfg, root, sizeid, rot, CurrentTime);
- XRRFreeScreenConfigInfo(xrrcfg);
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_rotation_set */
-
-EAPI Ecore_X_Screen_Size *
-ecore_x_randr_screen_sizes_get(Ecore_X_Window root, int *num)
-{
-#ifdef ECORE_XRANDR
- Ecore_X_Screen_Size *ret;
- XRRScreenSize *sizes;
- int i, n;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- if (num)
- *num = 0;
-
- /* we don't have to free sizes, no idea why not */
- sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
- ret = calloc(n, sizeof(Ecore_X_Screen_Size));
- if (!ret)
- return NULL;
-
- if (num)
- *num = n;
-
- for (i = 0; i < n; i++)
- {
- ret[i].width = sizes[i].width;
- ret[i].height = sizes[i].height;
- }
- return ret;
-#else /* ifdef ECORE_XRANDR */
- if (num)
- *num = 0;
-
- return NULL;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_sizes_get */
-
-EAPI Ecore_X_Screen_Size
-ecore_x_randr_current_screen_size_get(Ecore_X_Window root)
-{
- Ecore_X_Screen_Size ret = { -1, -1 };
-#ifdef ECORE_XRANDR
- XRRScreenSize *sizes;
- XRRScreenConfiguration *sc;
- SizeID size_index;
- Rotation rotation;
- int n;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- sc = XRRGetScreenInfo(_ecore_x_disp, root);
- if (!sc)
- {
- ERR("Couldn't get screen information for %d", root);
- return ret;
- }
-
- size_index = XRRConfigCurrentConfiguration(sc, &rotation);
-
- sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
- if (size_index < n)
- {
- ret.width = sizes[size_index].width;
- ret.height = sizes[size_index].height;
- }
-
- XRRFreeScreenConfigInfo(sc);
-#endif /* ifdef ECORE_XRANDR */
- return ret;
-} /* ecore_x_randr_current_screen_size_get */
-
-EAPI int
-ecore_x_randr_screen_size_set(Ecore_X_Window root, Ecore_X_Screen_Size size)
-{
-#ifdef ECORE_XRANDR
- XRRScreenConfiguration *sc;
- XRRScreenSize *sizes;
- int i, n, size_index = -1;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
- for (i = 0; i < n; i++)
- {
- if ((sizes[i].width == size.width) && (sizes[i].height == size.height))
- {
- size_index = i;
- break;
- }
- }
- if (size_index == -1)
- return 0;
-
- sc = XRRGetScreenInfo(_ecore_x_disp, root);
- if (XRRSetScreenConfig(_ecore_x_disp, sc,
- root, size_index,
- RR_Rotate_0, CurrentTime))
- {
- ERR("Can't set new screen size!");
- XRRFreeScreenConfigInfo(sc);
- return 0;
- }
-
- XRRFreeScreenConfigInfo(sc);
- return 1;
-#else /* ifdef ECORE_XRANDR */
- return 0;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_size_set */
-
-EAPI Ecore_X_Screen_Refresh_Rate
-ecore_x_randr_current_screen_refresh_rate_get(Ecore_X_Window root)
-{
- Ecore_X_Screen_Refresh_Rate ret = { -1 };
-#ifdef ECORE_XRANDR
- XRRScreenConfiguration *sc;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- sc = XRRGetScreenInfo(_ecore_x_disp, root);
- if (!sc)
- {
- ERR("Couldn't get screen information for %d", root);
- return ret;
- }
-
- ret.rate = XRRConfigCurrentRate(sc);
- XRRFreeScreenConfigInfo(sc);
-#endif /* ifdef ECORE_XRANDR */
- return ret;
-} /* ecore_x_randr_current_screen_refresh_rate_get */
-
-EAPI Ecore_X_Screen_Refresh_Rate *
-ecore_x_randr_screen_refresh_rates_get(Ecore_X_Window root,
- int size_id,
- int *num)
-{
-#ifdef ECORE_XRANDR
- Ecore_X_Screen_Refresh_Rate *ret = NULL;
- XRRScreenConfiguration *sc;
- short *rates;
- int i, n;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- if (num)
- *num = 0;
-
- sc = XRRGetScreenInfo(_ecore_x_disp, root);
- if (!sc)
- {
- ERR("Couldn't get screen information for %d", root);
- return ret;
- }
-
- rates = XRRRates(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp,
- root), size_id, &n);
- ret = calloc(n, sizeof(Ecore_X_Screen_Refresh_Rate));
- if (!ret)
- {
- XRRFreeScreenConfigInfo(sc);
- return NULL;
- }
-
- if (num)
- *num = n;
-
- for (i = 0; i < n; i++)
- {
- ret[i].rate = rates[i];
- }
- XRRFreeScreenConfigInfo(sc);
- return ret;
-#else /* ifdef ECORE_XRANDR */
- if (num)
- *num = 0;
-
- return NULL;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_refresh_rates_get */
-
-EAPI int
-ecore_x_randr_screen_refresh_rate_set(Ecore_X_Window root,
- Ecore_X_Screen_Size size,
- Ecore_X_Screen_Refresh_Rate rate)
-{
-#ifdef ECORE_XRANDR
- XRRScreenConfiguration *sc;
- XRRScreenSize *sizes;
- int i, n, size_index = -1;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
- sizes = XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, root), &n);
- for (i = 0; i < n; i++)
- {
- if ((sizes[i].width == size.width) && (sizes[i].height == size.height))
- {
- size_index = i;
- break;
- }
- }
- if (size_index == -1)
- return 0;
-
- sc = XRRGetScreenInfo(_ecore_x_disp, root);
- if (XRRSetScreenConfigAndRate(_ecore_x_disp, sc,
- root, size_index,
- RR_Rotate_0, rate.rate, CurrentTime))
- {
- ERR("Can't set new screen size and refresh rate!");
- XRRFreeScreenConfigInfo(sc);
- return 0;
- }
-
- XRRFreeScreenConfigInfo(sc);
- return 1;
-#else /* ifdef ECORE_XRANDR */
- return 1;
-#endif /* ifdef ECORE_XRANDR */
-} /* ecore_x_randr_screen_refresh_rate_set */
+ Ecore_X_Randr_Screen scr = -1;
+ if (root && RANDR_VALIDATE_ROOT(scr, root))
+ return EINA_TRUE;
+ else
+ return EINA_FALSE;
+#else
+ return EINA_FALSE;
+#endif
+}
--- /dev/null
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "ecore_x_private.h"
+#include "ecore_x_inline.x"
+
+#define Ecore_X_Randr_None 0
+#define Ecore_X_Randr_Unset -1
+
+#ifdef ECORE_XRANDR
+
+#define RANDR_1_2 ((1 << 16) | 2)
+
+#define RANDR_VALIDATE_ROOT(screen, \
+ root) ((screen = \
+ XRRRootToScreen(_ecore_x_disp, \
+ root)) != -1)
+#define RANDR_CHECK_1_2_RET(ret) if(_randr_version < RANDR_1_2) return ret
+
+#define RANDR_PROPERTY_EDID "EDID"
+#define RANDR_PROPERTY_BACKLIGHT "Backlight"
+#define RANDR_PROPERTY_SIGNAL_FORMAT "SignalFormat"
+#define RANDR_PROPERTY_SIGNAL_PROPERTIES "SignalProperties"
+#define RANDR_PROPERTY_CONNECTOR_TYPE "ConnectorType"
+#define RANDR_PROPERTY_CONNECTOR_NUMBER "ConnectorNumber"
+#define RANDR_PROPERTY_COMPATIBILITY_LIST "CompatibilityList"
+#define RANDR_PROPERTY_CLONE_LIST "CloneList"
+
+extern XRRScreenResources * (*_ecore_x_randr_get_screen_resources)(Display *
+ dpy,
+ Window
+ window);
+extern int _randr_version;
+#endif
+
+/**
+ * @Brief enable event selection. This enables basic interaction with
+ * output/crtc events and requires RRandR >= 1.2.
+ * @param win select this window's properties for RandRR events
+ * @param on enable/disable selecting
+ */
+EAPI void
+ecore_x_randr_events_select(Ecore_X_Window win, Eina_Bool on)
+{
+#ifdef ECORE_XRANDR
+ int mask;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+ if (!on)
+ mask = 0;
+ else
+ {
+ mask = RRScreenChangeNotifyMask;
+ if (_randr_version >= RANDR_1_2)
+ mask |= (RRCrtcChangeNotifyMask |
+ RROutputChangeNotifyMask |
+ RROutputPropertyNotifyMask);
+ }
+
+ XRRSelectInput(_ecore_x_disp, win, mask);
+#endif
+}
+
+/**
+ * @brief validates a CRTC for a given root window's screen.
+ * @param root the window which's default display will be queried
+ * @param crtc the CRTC to be validated.
+ * @return in case it is found EINA_TRUE will be returned. Else EINA_FALSE is returned.
+ */
+static inline Eina_Bool
+_ecore_x_randr_crtc_validate(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ XRRScreenResources *res = NULL;
+ int i;
+ Eina_Bool ret = EINA_FALSE;
+
+ if ((crtc == Ecore_X_Randr_None) || (crtc == Ecore_X_Randr_Unset))
+ return ret;
+
+ if (_ecore_x_randr_root_validate(root) && crtc &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ for (i = 0; i < res->ncrtc; i++)
+ {
+ if (res->crtcs[i] == crtc)
+ {
+ ret = EINA_TRUE;
+ break;
+ }
+ }
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+inline Eina_Bool
+_ecore_x_randr_output_validate(Ecore_X_Window root, Ecore_X_Randr_Output output)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ Eina_Bool ret = EINA_FALSE;
+ XRRScreenResources *res = NULL;
+ int i;
+
+ if (_ecore_x_randr_root_validate(root) && output &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ for (i = 0; i < res->noutput; i++)
+ {
+ if (res->outputs[i] == output)
+ {
+ ret = EINA_TRUE;
+ break;
+ }
+ }
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+static inline Eina_Bool
+_ecore_x_randr_mode_validate(Ecore_X_Window root, Ecore_X_Randr_Mode mode)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ Eina_Bool ret = EINA_FALSE;
+ XRRScreenResources *res = NULL;
+ int i;
+
+ if (_ecore_x_randr_root_validate(root) && mode &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ for (i = 0; i < res->nmode; i++)
+ {
+ if (res->modes[i].id == mode)
+ {
+ ret = EINA_TRUE;
+ break;
+ }
+ }
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/*
+ * @param w width of screen in px
+ * @param h height of screen in px
+ */
+EAPI void
+ecore_x_randr_screen_current_size_get(Ecore_X_Window root,
+ int *w,
+ int *h,
+ int *w_mm,
+ int *h_mm)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ Ecore_X_Randr_Screen scr;
+
+ if (!RANDR_VALIDATE_ROOT(scr, root))
+ return;
+
+ if (w)
+ *w = DisplayWidth(_ecore_x_disp, scr);
+
+ if (h)
+ *h = DisplayHeight(_ecore_x_disp, scr);
+
+ if (w_mm)
+ *w_mm = DisplayWidthMM(_ecore_x_disp, scr);
+
+ if (h_mm)
+ *h_mm = DisplayHeightMM(_ecore_x_disp, scr);
+
+#endif
+}
+
+/*
+ * @param root window which's screen will be queried
+ * @param wmin minimum width the screen can be set to
+ * @param hmin minimum height the screen can be set to
+ * @param wmax maximum width the screen can be set to
+ * @param hmax maximum height the screen can be set to
+ */
+EAPI void
+ecore_x_randr_screen_size_range_get(Ecore_X_Window root,
+ int *wmin,
+ int *hmin,
+ int *wmax,
+ int *hmax)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ int twmin, thmin, twmax, thmax;
+ if (XRRGetScreenSizeRange (_ecore_x_disp, root, &twmin, &thmin, &twmax,
+ &thmax))
+ {
+ if (wmin)
+ *wmin = twmin;
+
+ if (hmin)
+ *hmin = thmin;
+
+ if (wmax)
+ *wmax = twmax;
+
+ if (hmax)
+ *hmax = thmax;
+ }
+
+#endif
+}
+
+/*
+ * @param root window which's screen's size should be set. If invalid (e.g. NULL) no action is taken.
+ * @param w width in px the screen should be set to. If out of valid boundaries, current value is assumed.
+ * @param h height in px the screen should be set to. If out of valid boundaries, current value is assumed.
+ * @param w_mm width in mm the screen should be set to. If 0, current aspect is assumed.
+ * @param h_mm height in mm the screen should be set to. If 0, current aspect is assumed.
+ * @return EINA_TRUE if request was successfully sent or screen is already in
+ * requested size, EINA_FALSE if parameters are invalid
+ */
+EAPI Eina_Bool
+ecore_x_randr_screen_current_size_set(Ecore_X_Window root,
+ int w,
+ int h,
+ int w_mm,
+ int h_mm)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ Ecore_X_Randr_Screen scr;
+ int w_c, h_c, w_mm_c, h_mm_c, twmin, thmin, twmax, thmax;
+
+ if (!RANDR_VALIDATE_ROOT(scr, root))
+ return EINA_FALSE;
+
+ ecore_x_randr_screen_current_size_get(root, &w_c, &h_c, &w_mm_c, &h_mm_c);
+ if ((w == w_c) && (h == h_c) && (w_mm_c == w_mm) && (h_mm_c == h_mm))
+ return EINA_TRUE;
+
+ ecore_x_randr_screen_size_range_get(root, &twmin, &thmin, &twmax, &thmax);
+
+ if (((w != Ecore_X_Randr_None) &&
+ ((w < twmin) ||
+ (w > twmax))) ||
+ ((h != Ecore_X_Randr_None) && ((h < thmin) || (h > thmax))))
+ return EINA_FALSE;
+
+ if (w <= 0)
+ w = DisplayWidth(_ecore_x_disp, scr);
+
+ if (h <= 0)
+ h = DisplayHeight(_ecore_x_disp, scr);
+
+ if(w_mm <= 0)
+ w_mm =
+ (int)(((double)(DisplayWidthMM(_ecore_x_disp,
+ scr) /
+ (double)DisplayWidth(_ecore_x_disp,
+ scr))) * (double)w);
+
+ if(h_mm <= 0)
+ h_mm =
+ (int)(((double)(DisplayHeightMM(_ecore_x_disp,
+ scr) /
+ (double)DisplayHeight(_ecore_x_disp,
+ scr))) * (double)h);
+
+ XRRSetScreenSize (_ecore_x_disp, root, w, h, w_mm, h_mm);
+ return EINA_TRUE;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/*
+ * @brief get detailed information for all modes related to a root window's screen
+ * @param root window which's screen's ressources are queried
+ * @param num number of modes returned
+ * @return modes' information
+ */
+EAPI Ecore_X_Randr_Mode_Info **
+ecore_x_randr_modes_info_get(Ecore_X_Window root, int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Mode_Info **ret = NULL;
+ int i;
+
+ if (_ecore_x_randr_root_validate(root) &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ if ((ret =
+ (Ecore_X_Randr_Mode_Info **)malloc(sizeof(
+ Ecore_X_Randr_Mode_Info *)
+ *
+ res->nmode)))
+ {
+ for (i = 0; i < res->nmode; i++)
+ {
+ if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
+ {
+ ret[i]->xid = res->modes[i].id;
+ ret[i]->width = res->modes[i].width;
+ ret[i]->height = res->modes[i].height;
+ ret[i]->dotClock = res->modes[i].dotClock;
+ ret[i]->hSyncStart = res->modes[i].hSyncStart;
+ ret[i]->hSyncEnd = res->modes[i].hSyncEnd;
+ ret[i]->hTotal = res->modes[i].hTotal;
+ ret[i]->hSkew = res->modes[i].hSkew;
+ ret[i]->vSyncStart = res->modes[i].vSyncStart;
+ ret[i]->vSyncEnd = res->modes[i].vSyncEnd;
+ ret[i]->vTotal = res->modes[i].vTotal;
+ if ((ret[i]->name = (malloc(res->modes[i].nameLength))))
+ strncpy(ret[i]->name, res->modes[i].name,
+ res->modes[i].nameLength);
+ else
+ ret[i]->name = NULL;
+
+ ret[i]->nameLength = res->modes[i].nameLength;
+ ret[i]->modeFlags = res->modes[i].modeFlags;
+ }
+ else
+ {
+ while(i > 0)
+ free(ret[--i]);
+ free(ret);
+ ret = NULL;
+ break;
+ }
+ }
+ }
+
+ if (ret && num)
+ *num = res->nmode;
+
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * @brief get detailed information for a given mode id
+ * @param root window which's screen's ressources are queried
+ * @param mode the XID which identifies the mode of interest
+ * @return mode's detailed information
+ */
+EAPI Ecore_X_Randr_Mode_Info *
+ecore_x_randr_mode_info_get(Ecore_X_Window root, Ecore_X_Randr_Mode mode)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Mode_Info *ret = NULL;
+ int i;
+
+ if (_ecore_x_randr_root_validate(root) &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ for (i = 0; i < res->nmode; i++)
+ {
+ if ((res->modes[i].id == mode) &&
+ (ret = malloc(sizeof(Ecore_X_Randr_Mode_Info))))
+ {
+ ret->xid = res->modes[i].id;
+ ret->width = res->modes[i].width;
+ ret->height = res->modes[i].height;
+ ret->dotClock = res->modes[i].dotClock;
+ ret->hSyncStart = res->modes[i].hSyncStart;
+ ret->hSyncEnd = res->modes[i].hSyncEnd;
+ ret->hTotal = res->modes[i].hTotal;
+ ret->hSkew = res->modes[i].hSkew;
+ ret->vSyncStart = res->modes[i].vSyncStart;
+ ret->vSyncEnd = res->modes[i].vSyncEnd;
+ ret->vTotal = res->modes[i].vTotal;
+ if (!(ret->name =
+ strndup(res->modes[i].name, res->modes[i].nameLength)))
+ {
+ ret->name = NULL;
+ ret->nameLength = 0;
+ }
+ else
+ ret->nameLength = res->modes[i].nameLength;
+
+ ret->modeFlags = res->modes[i].modeFlags;
+ break;
+ }
+ }
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * @brief free detailed mode information. The pointer handed in will be set to
+ * NULL after freeing the memory.
+ * @param mode_info the mode information that should be freed
+ */
+EAPI void
+ecore_x_randr_mode_info_free(Ecore_X_Randr_Mode_Info *mode_info)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ if (!mode_info)
+ return;
+
+ if (mode_info->name)
+ free(mode_info->name);
+
+ free(mode_info);
+ mode_info = NULL;
+#endif
+}
+
+/*
+ * @brief get all known CRTCs related to a root window's screen
+ * @param root window which's screen's ressources are queried
+ * @param num number of CRTCs returned
+ * @return CRTC IDs
+ */
+EAPI Ecore_X_Randr_Crtc *
+ecore_x_randr_crtcs_get(Ecore_X_Window root, int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Crtc *ret = NULL;
+
+ if (num && root &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ if ((ret = malloc(sizeof(Ecore_X_Randr_Crtc) * res->ncrtc)))
+ {
+ memcpy(ret, res->crtcs, (sizeof(Ecore_X_Randr_Crtc) * res->ncrtc));
+ *num = res->ncrtc;
+ }
+
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+EAPI Ecore_X_Randr_Output *
+ecore_x_randr_outputs_get(Ecore_X_Window root, int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Output *ret = NULL;
+
+ if (num && root &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * res->noutput)))
+ {
+ memcpy(ret, res->outputs,
+ (sizeof(Ecore_X_Randr_Output) * res->noutput));
+ if (num)
+ *num = res->noutput;
+ }
+
+ if (res)
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+//Per Crtc
+/*
+ * @brief get a CRTC's outputs.
+ * @param root the root window which's screen will be queried
+ * @param num number of outputs referenced by given CRTC
+ */
+EAPI Ecore_X_Randr_Output *
+ecore_x_randr_crtc_outputs_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Output *ret = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res =
+ _ecore_x_randr_get_screen_resources (_ecore_x_disp,
+ root)) &&
+ (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * crtc_info->noutput)))
+ {
+ memcpy(ret, crtc_info->outputs,
+ (sizeof(Ecore_X_Randr_Output) * crtc_info->noutput));
+ if (num)
+ *num = res->ncrtc;
+ }
+
+ if (crtc_info)
+ XRRFreeCrtcInfo(crtc_info);
+
+ if (res)
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+/*
+ * @brief get a CRTC's possible outputs.
+ * @param root the root window which's screen will be queried
+ * @param num number of possible outputs referenced by given CRTC
+ */
+EAPI Ecore_X_Randr_Output *
+ecore_x_randr_crtc_possible_outputs_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Output *ret = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ if((crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ if ((ret =
+ malloc(sizeof(Ecore_X_Randr_Output) * crtc_info->npossible)))
+ {
+ memcpy(ret, crtc_info->possible,
+ (sizeof(Ecore_X_Randr_Output) * crtc_info->npossible));
+ if (num)
+ *num = res->ncrtc;
+ }
+
+ XRRFreeCrtcInfo(crtc_info);
+ }
+
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+EAPI void
+ecore_x_randr_crtc_geometry_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *x,
+ int *y,
+ int *w,
+ int *h)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ XRRScreenResources *res = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res =
+ _ecore_x_randr_get_screen_resources (_ecore_x_disp,
+ root)) &&
+ (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ if (x)
+ *x = crtc_info->x;
+
+ if (y)
+ *y = crtc_info->y;
+
+ if (w)
+ *w = crtc_info->width;
+
+ if (h)
+ *h = crtc_info->height;
+
+ XRRFreeCrtcInfo(crtc_info);
+ XRRFreeScreenResources(res);
+ }
+
+#endif
+}
+
+/*
+ * @Brief sets the position of given CRTC within root window's screen
+ * @param root the window's screen to be queried
+ * @param crtc the CRTC which's position within the mentioned screen is to be altered
+ * @param x position on the x-axis (0 == left) of the screen. if x < 0 current value will be kept.
+ * @param y position on the y-ayis (0 == top) of the screen. if y < 0, current value will be kept.
+ * @return EINA_TRUE if position could be successfully be altered.
+ */
+EAPI Eina_Bool
+ecore_x_randr_crtc_pos_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int x,
+ int y)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+ int w_c, h_c, w_new = 0, h_new = 0;
+ Eina_Rectangle crtc_geo;
+
+ ecore_x_randr_crtc_geometry_get(root,
+ crtc,
+ &crtc_geo.x,
+ &crtc_geo.y,
+ &crtc_geo.w,
+ &crtc_geo.h);
+ ecore_x_randr_screen_current_size_get(root, &w_c, &h_c, NULL, NULL);
+ if (x < 0)
+ x = crtc_geo.x;
+
+ if (y < 0)
+ y = crtc_geo.y;
+
+ if ((x + crtc_geo.w) > w_c)
+ w_new = x + crtc_geo.w;
+
+ if ((y + crtc_geo.h) > h_c)
+ h_new = y + crtc_geo.h;
+
+ if ((w_new != 0) || (h_new != 0))
+ if (!ecore_x_randr_screen_current_size_set(root, w_new, h_new, 0, 0))
+ return EINA_FALSE;
+
+ return ecore_x_randr_crtc_settings_set(root,
+ crtc,
+ NULL,
+ Ecore_X_Randr_Unset,
+ x,
+ y,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset);
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/**
+ * @Brief Get the current set mode of a given CRTC
+ * @param root the window's screen to be queried
+ * @param crtc the CRTC which's should be queried
+ * @return currently set mode or - in case parameters are invalid -
+ * Ecore_X_Randr_Unset
+ */
+EAPI Ecore_X_Randr_Mode
+ecore_x_randr_crtc_mode_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(Ecore_X_Randr_Unset);
+ XRRScreenResources *res = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+ Ecore_X_Randr_Mode ret = Ecore_X_Randr_Unset;
+ if (_ecore_x_randr_root_validate(root) &&
+ _ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res =
+ _ecore_x_randr_get_screen_resources(_ecore_x_disp,
+ root)) &&
+ (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ ret = crtc_info->mode;
+ XRRFreeCrtcInfo(crtc_info);
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return Ecore_X_Randr_Unset;
+#endif
+}
+
+/**
+ * @Brief sets a mode for a CRTC and the outputs attached to it
+ * @param root the window's screen to be queried
+ * @param crtc the CRTC which shall be set
+ * @param outputs array of outputs which have to be compatible with the mode. If
+ * NULL CRTC will be disabled.
+ * @param noutputs number of outputs in array to be used. Use
+ * Ecore_X_Randr_Unset (or -1) to use currently used outputs.
+ * @para mode XID of the mode to be set. If set to 0 the CRTC will be disabled.
+ * If set to -1 the call will fail.
+ * @return EINA_TRUE if mode setting was successfull. Else EINA_FALSE
+ */
+EAPI Eina_Bool
+ecore_x_randr_crtc_mode_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Output *outputs,
+ int noutputs,
+ Ecore_X_Randr_Mode mode)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ if (mode == Ecore_X_Randr_Unset)
+ return EINA_FALSE;
+
+ return ecore_x_randr_crtc_settings_set(root,
+ crtc,
+ outputs,
+ noutputs,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset,
+ mode,
+ Ecore_X_Randr_Unset);
+#else
+ return EINA_FALSE;
+#endif
+}
+
+EAPI void
+ecore_x_randr_crtc_size_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *w,
+ int *h)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ ecore_x_randr_crtc_geometry_get(root, crtc, NULL, NULL, w, h);
+#endif
+}
+
+EAPI Ecore_X_Randr_Refresh_Rate
+ecore_x_randr_crtc_refresh_rate_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Mode mode)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(0.0);
+ XRRScreenResources *res = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+ Ecore_X_Randr_Refresh_Rate ret = 0.0;
+ int i;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ for (i = 0; i < res->nmode; i++)
+ if (res->modes[i].id == mode)
+ {
+ if (res->modes[i].hTotal && res->modes[i].vTotal)
+ ret = ((double)res->modes[i].dotClock /
+ ((double)res->modes[i].hTotal *
+ (double)res->modes[i].vTotal));
+
+ break;
+ }
+
+ }
+
+ if (crtc_info)
+ XRRFreeCrtcInfo(crtc_info);
+
+ if (res)
+ XRRFreeScreenResources(res);
+
+ return ret;
+#else
+ return 0.0;
+#endif
+}
+
+EAPI Ecore_X_Randr_Orientation
+ecore_x_randr_crtc_orientations_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
+ XRRCrtcInfo *crtc_info = NULL;
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res =
+ _ecore_x_randr_get_screen_resources (_ecore_x_disp,
+ root)) &&
+ (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ ret = crtc_info->rotations;
+ if (crtc_info)
+ XRRFreeCrtcInfo(crtc_info);
+
+ if (res)
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return Ecore_X_Randr_None;
+#endif
+}
+
+EAPI Ecore_X_Randr_Orientation
+ecore_x_randr_crtc_orientation_get(Ecore_X_Window root, Ecore_X_Randr_Crtc crtc)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
+ XRRCrtcInfo *crtc_info = NULL;
+ XRRScreenResources *res = NULL;
+ Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res =
+ _ecore_x_randr_get_screen_resources (_ecore_x_disp,
+ root)) &&
+ (crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ ret = crtc_info->rotation;
+ if (crtc_info)
+ XRRFreeCrtcInfo(crtc_info);
+
+ if (res)
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return Ecore_X_Randr_None;
+#endif
+}
+
+EAPI Eina_Bool
+ecore_x_randr_crtc_orientation_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Orientation orientation)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+ Eina_Bool ret = EINA_FALSE;
+
+ if (orientation != Ecore_X_Randr_None)
+ {
+ ret = ecore_x_randr_crtc_settings_set(root,
+ crtc,
+ NULL,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset,
+ orientation);
+ }
+
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+EAPI void
+ecore_x_randr_crtc_pos_get(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ int *x,
+ int *y)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+
+ ecore_x_randr_crtc_geometry_get(root, crtc, x, y, NULL, NULL);
+#endif
+}
+
+EAPI Eina_Bool
+ecore_x_randr_crtc_clone_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc original,
+ Ecore_X_Randr_Crtc clone)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ XRRScreenResources *res = NULL;
+ XRRCrtcInfo *clone_crtc_info = NULL;
+ Ecore_X_Randr_Mode original_mode = Ecore_X_Randr_None;
+ Ecore_X_Randr_Orientation original_orientation = Ecore_X_Randr_None;
+ Eina_Bool ret = EINA_FALSE;
+ int x, y;
+
+ if (_ecore_x_randr_root_validate(root) &&
+ _ecore_x_randr_crtc_validate(root,
+ original) &&
+ _ecore_x_randr_crtc_validate(root,
+ clone) &&
+ (res =
+ _ecore_x_randr_get_screen_resources (_ecore_x_disp,
+ root)) &&
+ (clone_crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, clone)))
+ {
+ ecore_x_randr_crtc_geometry_get(root, original, &x, &y, NULL, NULL);
+ original_mode = ecore_x_randr_crtc_mode_get(root, original);
+ original_orientation = ecore_x_randr_crtc_orientation_get(root,
+ original);
+ ret = ecore_x_randr_crtc_settings_set(root,
+ clone,
+ NULL,
+ Ecore_X_Randr_Unset,
+ x,
+ y,
+ original_mode,
+ original_orientation);
+ XRRFreeCrtcInfo(clone_crtc_info);
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/**
+ * @brief sets the demanded parameters for a given CRTC. Note that the CRTC is
+ * auto enabled in it's preferred mode, when it was disabled before.
+ * @param root the root window which's default display will be queried
+ * @param crtc the CRTC which's configuration should be altered
+ * @param outputs an array of outputs, that should display this CRTC's content.
+ * @param noutputs number of outputs in the array of outputs.
+ * If set to Ecore_X_Randr_Unset, current outputs and number of outputs will be used.
+ * If set to Ecore_X_Randr_None, CRTC will be disabled
+ * @param x new x coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current x
+ * corrdinate will be assumed.
+ * @param y new y coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current y
+ * corrdinate will be assumed.
+ * @param mode the new mode to be set. If Ecore_X_Randr_None is passed, the
+ * CRTC will be disabled. If Ecore_X_Randr_Unset is passed, the current mode is assumed.
+ * @param orientation the new orientation to be set. If Ecore_X_Randr_Unset is used,
+ * the current mode is assumed.
+ * @return EINA_TRUE if the configuration alteration was successful, else
+ * EINA_FALSE
+ */
+EAPI Eina_Bool
+ecore_x_randr_crtc_settings_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc,
+ Ecore_X_Randr_Output *outputs,
+ int noutputs,
+ int x,
+ int y,
+ Ecore_X_Randr_Mode mode,
+ Ecore_X_Randr_Orientation orientation)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+ XRRScreenResources *res = NULL;
+ XRRCrtcInfo *crtc_info = NULL;
+ Eina_Bool ret = EINA_FALSE;
+
+ if (_ecore_x_randr_crtc_validate(root,
+ crtc) &&
+ (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ {
+ if ((crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, crtc)))
+ {
+ if ((mode == Ecore_X_Randr_None) ||
+ (noutputs == Ecore_X_Randr_None))
+ {
+ outputs = NULL;
+ noutputs = 0;
+ }
+ else if (noutputs == Ecore_X_Randr_Unset)
+ {
+ outputs = (Ecore_X_Randr_Output *)crtc_info->outputs;
+ noutputs = crtc_info->noutput;
+ }
+
+ if (mode == Ecore_X_Randr_Unset)
+ mode = crtc_info->mode;
+
+ if (x < 0)
+ x = crtc_info->x;
+
+ if (y < 0)
+ y = crtc_info->y;
+
+ if (orientation == Ecore_X_Randr_Unset)
+ orientation = crtc_info->rotation;
+
+ if (!XRRSetCrtcConfig(_ecore_x_disp, res, crtc, CurrentTime,
+ x, y, mode, orientation, (RROutput *)outputs,
+ noutputs))
+ ret = EINA_TRUE;
+
+ XRRFreeCrtcInfo(crtc_info);
+ }
+
+ XRRFreeScreenResources(res);
+ }
+
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/**
+ * @brief sets a CRTC relative to another one.
+ * @crtc_r1 the CRTC to be positioned.
+ * @crtc_r2 the CRTC the position should be relative to
+ * @position the relation between the crtcs
+ * @aligment in case CRTCs size differ, aligns CRTC1 accordingly at CRTC2's
+ * borders
+ * @return EINA_TRUE if crtc could be successfully positioned. EINA_FALSE if
+ * repositioning failed or if position of new crtc would be out of given screen's min/max bounds.
+ */
+EAPI Eina_Bool
+ecore_x_randr_crtc_pos_relative_set(Ecore_X_Window root,
+ Ecore_X_Randr_Crtc crtc_r1,
+ Ecore_X_Randr_Crtc crtc_r2,
+ Ecore_X_Randr_Output_Policy policy,
+ Ecore_X_Randr_Relative_Alignment alignment)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+
+ Eina_Rectangle r1_geo, r2_geo;
+ int w_max, h_max, cw, ch, x_n = Ecore_X_Randr_Unset, y_n =
+ Ecore_X_Randr_Unset;
+ /*
+ int r1_noutputs, r2_noutputs, r1_nmodes, i, j, outputs_mode_found, mode_w, mode_h;
+ Ecore_X_Randr_Output *r1_outputs, *r2_outputs, *r2_r1_outputs;
+ Ecore_X_Randr_Mode *r1_modes, r2_mode, r1_mode;
+ Eina_Bool ret;
+ */
+
+ if ((ecore_x_randr_crtc_mode_get(root, crtc_r1) == Ecore_X_Randr_None)
+ || (ecore_x_randr_crtc_mode_get(root, crtc_r2) == Ecore_X_Randr_None))
+ return EINA_FALSE;
+
+ if (!_ecore_x_randr_crtc_validate(root,
+ crtc_r1) ||
+ (!(crtc_r1 != crtc_r2) &&
+ !_ecore_x_randr_crtc_validate(root, crtc_r2)))
+ return EINA_FALSE;
+
+ ecore_x_randr_crtc_geometry_get(root,
+ crtc_r1,
+ &r1_geo.x,
+ &r1_geo.y,
+ &r1_geo.w,
+ &r1_geo.h);
+ ecore_x_randr_crtc_geometry_get(root,
+ crtc_r2,
+ &r2_geo.x,
+ &r2_geo.y,
+ &r2_geo.w,
+ &r2_geo.h);
+ ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
+ ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
+
+ switch (policy)
+ {
+ case ECORE_X_RANDR_OUTPUT_POLICY_RIGHT:
+ //set r1 right of r2
+ x_n = r2_geo.x + r2_geo.w;
+
+ switch (alignment)
+ {
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
+ y_n = Ecore_X_Randr_Unset;
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
+ y_n =
+ ((int)(((double)r2_geo.h /
+ 2.0) + (double)r2_geo.y - ((double)r1_geo.h / 2.0)));
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
+ y_n = ((int)((double)ch / 2.0) - ((double)r1_geo.h / 2.0));
+ break;
+ }
+ break;
+
+ case ECORE_X_RANDR_OUTPUT_POLICY_LEFT:
+ //set r1 left of r2
+ x_n = r2_geo.x - r1_geo.w;
+
+ switch (alignment)
+ {
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
+ y_n = Ecore_X_Randr_Unset;
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
+ y_n =
+ ((int)(((double)r2_geo.h /
+ 2.0) + r2_geo.y - ((double)r1_geo.h / 2.0)));
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
+ y_n = ((int)(((double)ch / 2.0) - ((double)r1_geo.h / 2.0)));
+ break;
+ }
+ break;
+
+ case ECORE_X_RANDR_OUTPUT_POLICY_BELOW:
+ //set r1 below r2
+ y_n = r2_geo.y + r2_geo.h;
+
+ switch (alignment)
+ {
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
+ x_n = Ecore_X_Randr_Unset;
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
+ x_n =
+ ((int)((((double)r2_geo.x +
+ (double)r2_geo.w) / 2.0) - ((double)r1_geo.w / 2.0)));
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
+ x_n = ((int)((double)cw / 2.0));
+ break;
+ }
+ break;
+
+ case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE:
+ y_n = r2_geo.y - r1_geo.h;
+
+ //set r1 above r2
+ switch (alignment)
+ {
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE:
+ x_n = Ecore_X_Randr_Unset;
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL:
+ x_n =
+ ((int)((((double)r2_geo.x +
+ (double)r2_geo.w) / 2.0) - ((double)r1_geo.w / 2.0)));
+ break;
+
+ case ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR:
+ x_n = ((int)((double)cw / 2.0));
+ break;
+ }
+ break;
+
+ case ECORE_X_RANDR_OUTPUT_POLICY_CLONE:
+ return ecore_x_randr_crtc_pos_set(root, crtc_r1, r2_geo.x, r2_geo.y);
+
+ /* entire cloning (including modesetting)
+ //all outputs of crtc1 capable of crtc2's current mode?
+ r2_mode = ecore_x_randr_crtc_mode_get(root, crtc_r2);
+ if (!(r1_outputs =
+ ecore_x_randr_crtc_outputs_get(root, crtc_r1,
+ &r1_noutputs)) ||
+ (r1_noutputs == 0))
+ return EINA_FALSE;
+
+ for (i = 0, outputs_mode_found = 0; i < r1_noutputs; i++)
+ {
+ if (!(r1_modes =
+ ecore_x_randr_output_modes_get(root, r1_outputs[i],
+ &r1_nmodes, NULL)))
+ {
+ free(r1_outputs);
+ return EINA_FALSE;
+ }
+
+ for (j = 0; j < r1_nmodes; j++)
+ {
+ ecore_x_randr_mode_size_get(root,
+ r1_modes[j],
+ &mode_w,
+ &mode_h);
+ if ((mode_w == r2_geo.w) && (mode_h == r2_geo.h))
+ {
+ r1_mode = r1_modes[j];
+ ++outputs_mode_found;
+ free(r1_modes);
+ r1_modes = NULL;
+ break;
+ }
+ }
+ if (r1_modes)
+ free(r1_modes);
+
+ if (outputs_mode_found <= i)
+ {
+ //an output doesn't support the set mode, cancel!
+ free(r1_outputs);
+ return EINA_FALSE;
+ }
+ }
+ free (r1_outputs);
+ //CRTC 1's outputs support a mode of same geometry as CRTC 2.
+ ret =
+ (ecore_x_randr_crtc_mode_set(root, crtc_r1, Ecore_X_Randr_None,
+ Ecore_X_Randr_None,
+ r1_mode) &&
+ ecore_x_randr_crtc_pos_set(root, crtc_r1, r2_geo.x, r2_geo.y));
+ return ret;
+ */
+
+ /* entire cloning on same CRTC
+ //all outputs of crtc1 capable of crtc2's current mode?
+ r2_mode = ecore_x_randr_crtc_mode_get(root, crtc_r2);
+ if (!(r1_outputs =
+ ecore_x_randr_crtc_outputs_get(root, crtc_r1,
+ &r1_noutputs)) ||
+ (r1_noutputs == 0))
+ return EINA_FALSE;
+
+ for (i = 0, outputs_mode_found = 0; i < r1_noutputs; i++)
+ {
+ if (!(r1_modes =
+ ecore_x_randr_output_modes_get(root, r1_outputs[i],
+ &r1_nmodes, NULL)))
+ {
+ free(r1_outputs);
+ return EINA_FALSE;
+ }
+
+ for (j = 0; j < r1_nmodes; j++)
+ {
+ if (r1_modes[j] == r2_mode)
+ {
+ ++outputs_mode_found;
+ free(r1_modes);
+ r1_modes = NULL;
+ break;
+ }
+ }
+ if (r1_modes)
+ free(r1_modes);
+
+ if (outputs_mode_found <= i)
+ {
+ //an output doesn't support the set mode, cancel!
+ free(r1_outputs);
+ return EINA_FALSE;
+ }
+ }
+ //check whether crtc r2 can use all outputs of r1.
+ if (!(r2_outputs =
+ ecore_x_randr_crtc_possible_outputs_get(root, crtc_r2,
+ &r2_noutputs)) ||
+ (r2_noutputs == 0))
+ {
+ free(r1_outputs);
+ return EINA_FALSE;
+ }
+
+ for (i = 0; i < r1_noutputs; i++)
+ {
+ for (j = 0; j < r2_noutputs; )
+ {
+ if (r1_outputs[i] == r2_outputs[j])
+ break;
+
+ j++;
+ }
+ if (j == r2_noutputs)
+ {
+ //didn't find the output!
+ free (r1_outputs);
+ free (r2_outputs);
+ return EINA_FALSE;
+ }
+ }
+
+ //apparently crtc2 supports all outputs of r1
+ //TODO: check with the compatible list of outputs (property in RR1.3)
+ r2_r1_outputs =
+ malloc(sizeof(Ecore_X_Randr_Output) * (r1_noutputs + r2_noutputs));
+ for (i = 0; i < r1_noutputs; i++)
+ {
+ r2_r1_outputs[i] = r1_outputs[i];
+ }
+ free(r1_outputs);
+ for (; i < r2_noutputs; i++)
+ {
+ r2_r1_outputs[i] = r2_outputs[i];
+ }
+ free(r2_outputs);
+ ret =
+ ecore_x_randr_crtc_mode_set(root, crtc_r2, r2_r1_outputs,
+ (r1_noutputs + r1_noutputs), r2_mode);
+ free (r2_r1_outputs);
+ return ret;
+ */
+ }
+ if ((x_n == r1_geo.x) && (y_n == r1_geo.x))
+ return EINA_TRUE;
+
+ //out of possible bounds?
+ if (((y_n + r1_geo.h) > h_max) || ((x_n + r1_geo.w) > w_max))
+ return EINA_FALSE;
+
+ return ecore_x_randr_crtc_pos_set(root, crtc_r1, x_n, y_n);
+#else
+ return EINA_FALSE;
+#endif
+}
+
+
+EAPI Ecore_X_Randr_Mode *
+ecore_x_randr_output_modes_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *num,
+ int *npreferred)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+ Ecore_X_Randr_Mode *modes = NULL;
+
+ if ((output != Ecore_X_Randr_None)
+ && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
+ && (output_info =
+ XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
+ {
+ if ((modes = malloc(sizeof(Ecore_X_Randr_Mode) * output_info->nmode)))
+ {
+ memcpy(modes, output_info->modes,
+ (sizeof(Ecore_X_Randr_Mode) * output_info->nmode));
+ if (num)
+ *num = output_info->nmode;
+
+ if (npreferred)
+ *npreferred = output_info->npreferred;
+ }
+ }
+
+ if (output_info)
+ XRRFreeOutputInfo(output_info);
+
+ if (res)
+ XRRFreeScreenResources(res);
+
+ return modes;
+#else
+ return NULL;
+#endif
+}
+
+EAPI Ecore_X_Randr_Crtc *
+ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+ Ecore_X_Randr_Crtc *crtcs = NULL;
+
+ if ((output != Ecore_X_Randr_None))
+ {
+ if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ {
+ if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
+ {
+ if ((crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc)))
+ {
+ memcpy(crtcs, output_info->crtcs, (sizeof(Ecore_X_Randr_Crtc) * output_info->ncrtc));
+ if (num) *num = output_info->ncrtc;
+ }
+ XRRFreeOutputInfo(output_info);
+ }
+ XRRFreeScreenResources(res);
+ }
+ }
+ return crtcs;
+#else
+ return Ecore_X_Randr_None;
+#endif
+}
+
+/**
+ * @brief gets the the outputs which might be used simultenously on the same
+ * CRTC.
+ * @root window that this information should be queried for.
+ * @output the output which's clones we concern
+ * @num number of possible clones
+ */
+EAPI Ecore_X_Randr_Output *
+ecore_x_randr_output_clones_get(Ecore_X_Window root, Ecore_X_Randr_Output output, int *num)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+ Ecore_X_Randr_Output *outputs = NULL;
+
+ if ((output != Ecore_X_Randr_None))
+ {
+ if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ {
+ if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
+ {
+ if ((outputs = malloc(sizeof(Ecore_X_Randr_Output) * output_info->nclone)))
+ {
+ memcpy(outputs, output_info->clones, (sizeof(Ecore_X_Randr_Output) * output_info->nclone));
+ if (num) *num = output_info->nclone;
+ }
+ XRRFreeOutputInfo(output_info);
+ }
+ XRRFreeScreenResources(res);
+ }
+ }
+ return outputs;
+#else
+ return Ecore_X_Randr_None;
+#endif
+}
+
+EAPI Ecore_X_Randr_Crtc
+ecore_x_randr_output_crtc_get(Ecore_X_Window root, Ecore_X_Randr_Output output)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(Ecore_X_Randr_None);
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+ Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None;
+
+ if ((output != Ecore_X_Randr_None))
+ {
+ if ((res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ {
+ if ((output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
+ {
+ ret = output_info->crtc;
+ XRRFreeOutputInfo(output_info);
+ }
+ XRRFreeScreenResources(res);
+ }
+ }
+
+ return ret;
+#else
+ return Ecore_X_Randr_None;
+#endif
+}
+
+/**
+ * @brief gets the given output's name as reported by X
+ * @param root the window which's screen will be queried
+ * @len length of returned c-string.
+ * @return name of the output as reported by X
+ */
+ EAPI char *
+ecore_x_randr_output_name_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *len)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+ char *ret = NULL;
+
+ if ((output != Ecore_X_Randr_None)
+ && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
+ && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
+ {
+ /*
+ * Actually the bewow command is correct, but due to a bug in libXrandr
+ * it doesn't work. Therefor we stick with strlen().
+ * Replace the line below with the following once
+ * libXrandr >= git revision '25d793ab4ec111658e541c94eba4893a81d6a3b7'.
+ * is shipped and standard.
+ *
+ * *len = output_info->nameLen;
+ *
+ */
+ if ((ret = strdup(output_info->name)) && len)
+ *len = strlen(ret);
+
+ XRRFreeOutputInfo(output_info);
+ }
+
+ if (res)
+ XRRFreeScreenResources(res);
+
+ return ret;
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * @brief gets the width and hight of a given mode
+ * @param mode the mode which's size is to be looked up
+ * @w width of given mode in px
+ * @h height of given mode in px
+ */
+ EAPI void
+ecore_x_randr_mode_size_get(Ecore_X_Window root,
+ Ecore_X_Randr_Mode mode,
+ int *w,
+ int *h)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ XRRScreenResources *res = NULL;
+ int i;
+
+ if ((mode != Ecore_X_Randr_None)
+ && (w || h)
+ && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ {
+ for (i = 0; i < res->nmode; i++)
+ {
+ if (res->modes[i].id == mode)
+ {
+ if (w)
+ *w = res->modes[i].width;
+
+ if (h)
+ *h = res->modes[i].height;
+
+ break;
+ }
+ }
+ }
+
+ if (res)
+ XRRFreeScreenResources(res);
+
+#endif
+}
+
+/**
+ * @Brief gets the EDID information of an attached output if available.
+ * Note that this information is not to be compared using ordinary string
+ * comparison functions, since it includes 0-bytes.
+ * @param root window this information should be queried from
+ * @output the XID of the output
+ * @length length of the byte-array. If NULL, request will fail.
+ */
+EAPI unsigned char *
+ecore_x_randr_output_edid_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ unsigned long *length)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(NULL);
+ Atom name = XInternAtom (_ecore_x_disp, RANDR_PROPERTY_EDID, False);
+ unsigned char *prop_data, *ret = NULL;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ Atom actual_type;
+
+ if (!length || !_ecore_x_randr_output_validate(root, output))
+ return NULL;
+
+ if(XRRGetOutputProperty (_ecore_x_disp, output, name,
+ 0, 100, False, False,
+ AnyPropertyType,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop_data) == Success)
+ {
+ if (actual_type == XA_INTEGER && actual_format == 8)
+ {
+ if ((ret = malloc(nitems * sizeof(unsigned char))))
+ {
+ if(length &&
+ (memcpy(ret, prop_data, (nitems * sizeof(unsigned char)))))
+ *length = nitems;
+
+ return ret;
+ }
+ }
+ }
+
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+EAPI Ecore_X_Randr_Connection_Status
+ecore_x_randr_output_connection_status_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN);
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+ Ecore_X_Randr_Connection_Status ret =
+ ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
+
+ if ((output != Ecore_X_Randr_None)
+ && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))
+ && (output_info = XRRGetOutputInfo(_ecore_x_disp, res, output)))
+ {
+ ret = output_info->connection;
+ }
+
+ if (output_info)
+ XRRFreeOutputInfo(output_info);
+
+ if (res)
+ XRRFreeScreenResources(res);
+
+ return ret;
+#else
+ return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN;
+#endif
+}
+
+EAPI void
+ecore_x_randr_output_size_mm_get(Ecore_X_Window root,
+ Ecore_X_Randr_Output output,
+ int *w_mm,
+ int *h_mm)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET();
+ XRRScreenResources *res = NULL;
+ XRROutputInfo *output_info = NULL;
+
+ if ((output != Ecore_X_Randr_None)
+ && (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ {
+ if ((output_info =
+ XRRGetOutputInfo(_ecore_x_disp, res, (RROutput)output)))
+ {
+ if (w_mm)
+ *w_mm = output_info->mm_width;
+
+ if (h_mm)
+ *h_mm = output_info->mm_height;
+
+ XRRFreeOutputInfo(output_info);
+ }
+
+ XRRFreeScreenResources(res);
+ }
+
+#endif
+}
+
+EAPI Eina_Bool
+ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root,
+ const Ecore_X_Randr_Crtc *not_moved,
+ int nnot_moved,
+ int dx,
+ int dy)
+{
+#ifdef ECORE_XRANDR
+ Ecore_X_Randr_Crtc *crtcs_to_be_moved = NULL;
+ XRRScreenResources *res = NULL;
+ int i, j, k, n;
+ Eina_Bool ret;
+
+
+ if ((nnot_moved <= 0) || (not_moved == NULL)
+ || !_ecore_x_randr_root_validate(root)
+ || !(res =
+ _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ return EINA_FALSE;
+
+ n = (res->ncrtc - nnot_moved);
+ if ((crtcs_to_be_moved = malloc(sizeof(Ecore_X_Randr_Crtc) * n)))
+ {
+ for (i = 0, k = 0; (i < res->ncrtc) && (k < n); i++)
+ {
+ for (j = 0; j < nnot_moved; j++)
+ {
+ if (res->crtcs[i] == not_moved[j])
+ break;
+ }
+ if (j == nnot_moved)
+ //crtcs[i] is not in the 'not to move'-list
+ crtcs_to_be_moved[k++] = res->crtcs[i];
+ }
+ }
+
+ XRRFreeScreenResources(res);
+ ret = ecore_x_randr_move_crtcs(root, crtcs_to_be_moved, n, dx, dy);
+ free(crtcs_to_be_moved);
+ return ret;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/*
+ * @Brief move given CRTCs belonging to the given root window's screen dx/dy pixels relative to their current position. The screen size will be automatically adjusted if neccessary and possible.
+ * @param root window which's screen's resources are used
+ * @param crtcs list of CRTCs to be moved
+ * @param ncrtc number of CRTCs in array
+ * @param dx amount of pixels the CRTCs should be moved in x direction
+ * @param dy amount of pixels the CRTCs should be moved in y direction
+ * @return EINA_TRUE if all crtcs could be moved successfully.
+ */
+EAPI Eina_Bool
+ecore_x_randr_move_crtcs(Ecore_X_Window root,
+ const Ecore_X_Randr_Crtc *crtcs,
+ int ncrtc,
+ int dx,
+ int dy)
+{
+#ifdef ECORE_XRANDR
+ RANDR_CHECK_1_2_RET(EINA_FALSE);
+ XRRScreenResources *res = NULL;
+ XRRCrtcInfo *crtc_info[ncrtc];
+ Eina_Bool ret = EINA_TRUE;
+ int i, cw, ch, w_max, h_max, nw, nh;
+
+ if (_ecore_x_randr_root_validate(root)
+ && (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root)))
+ {
+ ecore_x_randr_screen_size_range_get(root, NULL, NULL, &w_max, &h_max);
+ ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL);
+ nw = cw;
+ nh = ch;
+
+ for (i = 0;
+ (i < ncrtc) &&
+ (crtc_info[i] = XRRGetCrtcInfo(_ecore_x_disp, res, crtcs[i]));
+ i++)
+ {
+ if (((crtc_info[i]->x + dx) < 0) ||
+ ((crtc_info[i]->x + crtc_info[i]->width + dx) > w_max)
+ || ((crtc_info[i]->y + dy) < 0) ||
+ ((crtc_info[i]->y + crtc_info[i]->height + dy) > h_max)
+ )
+ goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
+
+ nw = MAX((crtc_info[i]->x + crtc_info[i]->width + dx), nw);
+ nh = MAX((crtc_info[i]->y + crtc_info[i]->height + dy), nh);
+ }
+ //not out of bounds
+
+ //resize if necessary
+ if (!(((nw > cw) ||
+ (nh > ch)) ||
+ ecore_x_randr_screen_current_size_set(root, nw, nh,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset)))
+ goto _ecore_x_randr_move_crtcs_fail_free_crtc_info;
+
+ //actually move all the crtcs, keep their rotation and mode.
+ for (i = 0; i < ncrtc; i++)
+ {
+ if (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL,
+ Ecore_X_Randr_Unset,
+ (crtc_info[i]->x + dx),
+ (crtc_info[i]->y + dy),
+ crtc_info[i]->mode,
+ crtc_info[i]->rotation))
+ {
+ ret = EINA_FALSE;
+ break;
+ }
+ }
+ if (i < ncrtc)
+ {
+ //something went wrong, let's try to move the already moved crtcs
+ //back.
+ while (i-- >= 0)
+ ecore_x_randr_crtc_settings_set(root,
+ crtcs[i],
+ NULL,
+ Ecore_X_Randr_Unset,
+ (crtc_info[i]->x - dx),
+ (crtc_info[i]->y - dy),
+ crtc_info[i]->mode,
+ crtc_info[i]->rotation);
+ }
+
+ for (i = 0; i < ncrtc; i++)
+ {
+ XRRFreeCrtcInfo(crtc_info[i]);
+ }
+ }
+
+ XRRFreeScreenResources(res);
+
+ return ret;
+_ecore_x_randr_move_crtcs_fail_free_crtc_info:
+ while (i-- > 0)
+ XRRFreeCrtcInfo(crtc_info[i]);
+ XRRFreeScreenResources(res);
+ return EINA_FALSE;
+#else
+ return EINA_FALSE;
+#endif
+}
+
+/**
+ * @brief removes unused screen space. The most upper left CRTC is set to 0x0
+ * and all other CRTCs dx,dy respectively.
+ * @param root the window's screen which will be reset.
+ */
+EAPI void
+ecore_x_randr_screen_reset(Ecore_X_Window root)
+{
+#ifdef ECORE_XRANDR
+ XRRCrtcInfo *crtc_info = NULL;
+ XRRScreenResources *res = NULL;
+ //the 100000 are just a random huge number.
+ int i, dx_min = 100000, dy_min = 100000, w_n = 0, h_n = 0, nenabled_crtcs = 0;
+
+ if (!_ecore_x_randr_root_validate(root) ||
+ !(res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root)))
+ return;
+
+ Ecore_X_Randr_Crtc enabled_crtcs[res->ncrtc];
+
+ for (i = 0; i < res->ncrtc; i++)
+ {
+ if (!(crtc_info =
+ XRRGetCrtcInfo(_ecore_x_disp, res,
+ res->crtcs[i])) ||
+ (crtc_info->mode == Ecore_X_Randr_None) ||
+ (crtc_info->mode == Ecore_X_Randr_Unset)
+ || ((crtc_info->noutput == 0)))
+ continue;
+
+ enabled_crtcs[nenabled_crtcs++] = res->crtcs[i];
+
+ if ((crtc_info->x + crtc_info->width) > w_n)
+ w_n = (crtc_info->x + crtc_info->width);
+
+ if ((crtc_info->y + crtc_info->height) > h_n)
+ h_n = (crtc_info->y + crtc_info->height);
+
+ if (crtc_info->x < dx_min)
+ dx_min = crtc_info->x;
+ if (crtc_info->y < dy_min)
+ dy_min = crtc_info->y;
+
+ XRRFreeCrtcInfo(crtc_info);
+ }
+ fprintf(stderr, "E_RANDR: babam, resize! Trying to move all CRTCs with dx %d and dy %d", dx_min, dy_min);
+ if ((dx_min > 0) || (dy_min > 0))
+ {
+ if (ecore_x_randr_move_crtcs(root, enabled_crtcs, nenabled_crtcs, -dx_min, -dy_min))
+ {
+ w_n -= dx_min;
+ h_n -= dy_min;
+ }
+ }
+ ecore_x_randr_screen_current_size_set(root,
+ w_n,
+ h_n,
+ Ecore_X_Randr_Unset,
+ Ecore_X_Randr_Unset);
+#endif
+}