From e7e09623ef9051357f53f4af4e0d62f763a9333d Mon Sep 17 00:00:00 2001 From: Leif Middelschulte Date: Sat, 14 Aug 2010 10:21:03 +0000 Subject: [PATCH] From: Leif Middelschulte patch for ecore-x xrandr 1.3 support - breaks previous api. final api change (i know about) before we go alpha. in to svn we go. SVN revision: 51109 --- legacy/ecore/src/lib/ecore_x/Ecore_X.h | 449 +++- legacy/ecore/src/lib/ecore_x/xlib/Makefile.am | 3 + .../src/lib/ecore_x/xlib/ecore_x_events.c | 22 +- .../src/lib/ecore_x/xlib/ecore_x_inline.x | 7 + .../src/lib/ecore_x/xlib/ecore_x_randr.c | 360 +--- .../src/lib/ecore_x/xlib/ecore_x_randr_11.c | 329 +++ .../src/lib/ecore_x/xlib/ecore_x_randr_12.c | 1898 +++++++++++++++++ .../src/lib/ecore_x/xlib/ecore_x_randr_13.c | 62 + 8 files changed, 2753 insertions(+), 377 deletions(-) create mode 100644 legacy/ecore/src/lib/ecore_x/xlib/ecore_x_inline.x create mode 100644 legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_11.c create mode 100644 legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12.c create mode 100644 legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_13.c diff --git a/legacy/ecore/src/lib/ecore_x/Ecore_X.h b/legacy/ecore/src/lib/ecore_x/Ecore_X.h index 49c815db28..9966b53110 100644 --- a/legacy/ecore/src/lib/ecore_x/Ecore_X.h +++ b/legacy/ecore/src/lib/ecore_x/Ecore_X.h @@ -70,6 +70,7 @@ typedef Ecore_X_ID Ecore_X_Randr_Output; 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; @@ -167,20 +168,34 @@ typedef enum _Ecore_X_Window_Stack_Mode { 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_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 { - 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_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, @@ -360,6 +375,9 @@ typedef struct _Ecore_X_Event_Startup_Sequence Ecore_X_Event_Startup_Sequence; 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; @@ -697,42 +715,46 @@ struct _Ecore_X_Event_Sync_Alarm 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 @@ -2451,52 +2473,339 @@ EAPI int ecore_x_xregion_rect_contain(Ecore_X_XRegion *region Ecore_X_Rectangle *rect); /* ecore_x_randr.c */ -typedef struct _Ecore_X_Screen_Size Ecore_X_Screen_Size; -struct _Ecore_X_Screen_Size + +/* 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. + */ + +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 { - int width, height; -}; + 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; -typedef struct _Ecore_X_Screen_Refresh_Rate Ecore_X_Screen_Refresh_Rate; -struct _Ecore_X_Screen_Refresh_Rate -{ - int rate; -}; +EAPI int ecore_x_randr_version_get( + void); +EAPI const Eina_Bool ecore_x_randr_query(void); -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( +/* 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); -EAPI int ecore_x_randr_screen_refresh_rate_set( - Ecore_X_Window root, - Ecore_X_Screen_Size size, - Ecore_X_Screen_Refresh_Rate rate); +/* ecore_x_randr_12.c */ +EAPI void +ecore_x_randr_events_select(Ecore_X_Window win, + Eina_Bool on); + +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; diff --git a/legacy/ecore/src/lib/ecore_x/xlib/Makefile.am b/legacy/ecore/src/lib/ecore_x/xlib/Makefile.am index d4b068f69d..65303a4b4d 100644 --- a/legacy/ecore/src/lib/ecore_x/xlib/Makefile.am +++ b/legacy/ecore/src/lib/ecore_x/xlib/Makefile.am @@ -34,6 +34,9 @@ ecore_x.c \ ecore_x_dnd.c \ ecore_x_sync.c \ ecore_x_randr.c \ +ecore_x_randr_11.c \ +ecore_x_randr_12.c \ +ecore_x_randr_13.c \ ecore_x_fixes.c \ ecore_x_damage.c \ ecore_x_composite.c \ diff --git a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_events.c b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_events.c index 6486671912..c33a5efb5f 100644 --- a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_events.c +++ b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_events.c @@ -2246,13 +2246,13 @@ _ecore_x_event_handle_randr_change(XEvent *xevent) e->win = randr_event->window; e->root = randr_event->root; - e->width = randr_event->width; - e->height = randr_event->height; + e->size.width = randr_event->width; + e->size.height = randr_event->height; e->time = randr_event->timestamp; e->config_time = randr_event->config_timestamp; - e->mm_width = randr_event->mwidth; - e->mm_height = randr_event->mheight; - e->rotation = randr_event->rotation; + e->size.width_mm = randr_event->mwidth; + e->size.height_mm = randr_event->mheight; + e->orientation = randr_event->rotation; e->subpixel_order = randr_event->subpixel_order; ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL); } /* _ecore_x_event_handle_randr_change */ @@ -2272,11 +2272,11 @@ _ecore_x_event_handle_randr_notify_crtc_change(const XRRNotifyEvent *xevent) e->win = randr_event->window; e->crtc = randr_event->crtc; e->mode = randr_event->mode; - e->rotation = randr_event->rotation; - e->x = randr_event->x; - e->y = randr_event->y; - e->width = randr_event->width; - e->height = randr_event->height; + e->orientation = randr_event->rotation; + e->geo.x = randr_event->x; + e->geo.y = randr_event->y; + e->geo.w = randr_event->width; + e->geo.h = randr_event->height; ecore_event_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, e, NULL, NULL); } /* _ecore_x_event_handle_randr_notify_crtc_change */ @@ -2296,7 +2296,7 @@ _ecore_x_event_handle_randr_notify_output_change(const XRRNotifyEvent *xevent) e->output = randr_event->output; e->crtc = randr_event->crtc; e->mode = randr_event->mode; - e->rotation = randr_event->rotation; + e->orientation = randr_event->rotation; e->connection = randr_event->connection; e->subpixel_order = randr_event->subpixel_order; ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, e, NULL, NULL); diff --git a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_inline.x b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_inline.x new file mode 100644 index 0000000000..b3d02bc142 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_inline.x @@ -0,0 +1,7 @@ +#ifndef ECORE_X_INLINE_X +#define ECORE_X_INLINE_X +inline Eina_Bool _ecore_x_randr_root_validate(Ecore_X_Window root); +inline Eina_Bool _ecore_x_randr_output_validate(Ecore_X_Window root, + Ecore_X_Randr_Output + output); +#endif diff --git a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr.c b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr.c index 35526ec694..e193c99c89 100644 --- a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr.c +++ b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr.c @@ -2,15 +2,27 @@ # include #endif /* ifdef HAVE_CONFIG_H */ -#include - #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 @@ -21,313 +33,69 @@ _ecore_x_randr_init(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; + _randr_available = EINA_FALSE; -#else /* ifdef ECORE_XRANDR */ - _randr_available = 0; -#endif /* ifdef ECORE_XRANDR */ -} /* _ecore_x_randr_init */ +#else + _randr_available = EINA_FALSE; +#endif +} -EAPI int +/* + * @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 +} diff --git a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_11.c b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_11.c new file mode 100644 index 0000000000..341146fae7 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_11.c @@ -0,0 +1,329 @@ +/* + * vim:ts=8:sw=3:sts=8:expandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" +#include "ecore_x_inline.x" + +#define Ecore_X_Randr_None 0 +#ifdef ECORE_XRANDR + +#define RANDR_1_1 ((1 << 16) | 1) + +#define RANDR_VALIDATE_ROOT(screen,\ + root) ((screen =\ + XRRRootToScreen(_ecore_x_disp,\ + root)) != -1) +#define RANDR_CHECK_1_1_RET(ret) if(_randr_version < RANDR_1_1) return ret + +extern XRRScreenResources * (*_ecore_x_randr_get_screen_resources)(Display * + dpy, + Window + window); +extern int _randr_version; +#endif /* ifdef ECORE_XRANDR */ + +/* + * @param root window which's primary output will be queried + */ +EAPI Ecore_X_Randr_Orientation +ecore_x_randr_screen_primary_output_orientations_get(Ecore_X_Window root) +{ +#ifdef ECORE_XRANDR + Rotation rot = Ecore_X_Randr_None, crot; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rot = + XRRRotations(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, + root), &crot); + return rot; +#else /* ifdef ECORE_XRANDR */ + return Ecore_X_Randr_None; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_orientations_get */ + +/* + * @param root window which's primary output will be queried + * @return the current orientation of the root window's screen primary output + */ +EAPI Ecore_X_Randr_Orientation +ecore_x_randr_screen_primary_output_orientation_get(Ecore_X_Window root) +{ +#ifdef ECORE_XRANDR + Rotation crot = Ecore_X_Randr_None; + XRRRotations(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, + root), &crot); + return crot; +#else /* ifdef ECORE_XRANDR */ + return Ecore_X_Randr_None; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_orientation_get */ + +/* + * @brief sets a given screen's primary output's orientation + * @param root window which's screen's primary output will be queried + * @param orientation orientation which should be set for the root window's screen primary output + * @return EINA_TRUE if the primary output's orientation could be successfully altered + */ +EAPI Eina_Bool +ecore_x_randr_screen_primary_output_orientation_set( + Ecore_X_Window root, + Ecore_X_Randr_Orientation + orientation) +{ +#ifdef ECORE_XRANDR + XRRScreenConfiguration *xrr_screen_cfg = NULL; + int sizeid; + Rotation crot; + Eina_Bool ret = EINA_FALSE; + if (!(xrr_screen_cfg = XRRGetScreenInfo(_ecore_x_disp, root))) + return EINA_FALSE; + + sizeid = XRRConfigCurrentConfiguration(xrr_screen_cfg, &crot); + if (!XRRSetScreenConfig(_ecore_x_disp, xrr_screen_cfg, root, sizeid, + orientation, CurrentTime)) + ret = EINA_TRUE; + + if (xrr_screen_cfg) + XRRFreeScreenConfigInfo(xrr_screen_cfg); + + return ret; +#else /* ifdef ECORE_XRANDR */ + return EINA_FALSE; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_orientation_set */ + +/* + * @brief gets a screen's primary output's possible sizes + * @param root window which's primary output will be queried + * @param num number of sizes reported as supported by the screen's primary output + * @return an array of sizes reported as supported by the screen's primary output or - if query failed - NULL + */ +EAPI Ecore_X_Randr_Screen_Size_MM * +ecore_x_randr_screen_primary_output_sizes_get(Ecore_X_Window root, int *num) +{ +#ifdef ECORE_XRANDR + Ecore_X_Randr_Screen_Size_MM *ret = NULL; + XRRScreenSize *sizes; + int i, n; + + /* we don't have to free sizes, because they're hold in a cache inside X*/ + sizes = + XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, + root), &n); + ret = calloc(n, sizeof(Ecore_X_Randr_Screen_Size_MM)); + 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; + ret[i].width_mm = sizes[i].mwidth; + ret[i].height_mm = sizes[i].mheight; + } + return ret; +#else /* ifdef ECORE_XRANDR */ + return NULL; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_sizes_get */ + +/* + * @brief get the current set size of a given screen's primary output + * @param root window which's primary output will be queried + * @param w the current size's width + * @param h the current size's height + * @param w_mm the current size's width in mm + * @param h_mm the current size's height in mm + * @param size_index of current set size to be used with ecore_x_randr_primary_output_size_set() + */ +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) +{ +#ifdef ECORE_XRANDR + XRRScreenSize *sizes; + XRRScreenConfiguration *sc = NULL; + int index; + Rotation orientation; + int n; + + if (!(sc = XRRGetScreenInfo(_ecore_x_disp, root))) + { + ERR("Couldn't get screen information for %d", root); + return; + } + + index = XRRConfigCurrentConfiguration(sc, &orientation); + + sizes = + XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, + root), &n); + if ((index < n) && (index >= 0)) + { + if (w) + *w = sizes[index].width; + + if (h) + *h = sizes[index].height; + + if (w_mm) + *w_mm = sizes[index].mwidth; + + if (h_mm) + *h_mm = sizes[index].mheight; + + if (size_index) + *size_index = index; + } + + XRRFreeScreenConfigInfo(sc); +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_current_size_get */ + +/* + * @brief sets a given screen's primary output size, but disables all other outputs at the same time + * @param root window which's primary output will be queried + * @param size_index within the list of sizes reported as supported by the root window's screen primary output + * @return EINA_TRUE on success, EINA_FALSE on failure due to e.g. invalid times + */ +EAPI Eina_Bool +ecore_x_randr_screen_primary_output_size_set(Ecore_X_Window root, + int size_index) +{ +#ifdef ECORE_XRANDR + XRRScreenConfiguration *sc = NULL; + XRRScreenSize *sizes; + Eina_Bool ret = EINA_FALSE; + int nsizes = 0; + + if (size_index >= 0 && _ecore_x_randr_root_validate(root)) + { + sizes = + XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, + root), &nsizes); + + if (size_index < nsizes) + { + sc = XRRGetScreenInfo(_ecore_x_disp, root); + if (!XRRSetScreenConfig(_ecore_x_disp, sc, + root, size_index, + ECORE_X_RANDR_ORIENTATION_ROT_0, CurrentTime)) + { + ret = EINA_TRUE; + } + + if (sc) + XRRFreeScreenConfigInfo(sc); + } + } + + return ret; +#else /* ifdef ECORE_XRANDR */ + return EINA_FALSE; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_size_set */ + +/* + * @param root window which's primary output will be queried + * @return currently used refresh rate or - if request failed or RandRR is not available - 0.0 + */ +EAPI Ecore_X_Randr_Refresh_Rate +ecore_x_randr_screen_primary_output_current_refresh_rate_get( + Ecore_X_Window root) +{ +#ifdef ECORE_XRANDR + Ecore_X_Randr_Refresh_Rate ret = 0.0; + XRRScreenConfiguration *sc = NULL; + + if (!_ecore_x_randr_root_validate(root) || + !(sc = XRRGetScreenInfo(_ecore_x_disp, root))) + return ret; + + ret = XRRConfigCurrentRate(sc); + if (sc) + XRRFreeScreenConfigInfo(sc); + + return ret; +#else /* ifdef ECORE_XRANDR */ + return 0.0; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_current_refresh_rate_get */ + +/* + * @param root window which's primary output will be queried + * @param size_index referencing the size to query valid refresh rates for + * @return currently used refresh rate or - if request failed or RandRR is not available - NULL + */ +EAPI Ecore_X_Randr_Refresh_Rate * +ecore_x_randr_screen_primary_output_refresh_rates_get(Ecore_X_Window root, + int size_index, + int *num) +{ +#ifdef ECORE_XRANDR + Ecore_X_Randr_Refresh_Rate *ret = NULL, *rates = NULL; + Ecore_X_Randr_Screen scr; + int n; + + if (num + && RANDR_VALIDATE_ROOT(scr, root) + && (rates = XRRRates(_ecore_x_disp, scr, size_index, &n))) + { + if (rates && (ret = malloc(sizeof(Ecore_X_Randr_Refresh_Rate) * n))) + { + memcpy(ret, rates, (sizeof(Ecore_X_Randr_Refresh_Rate) * n)); + *num = n; + } + } + + return ret; +#else /* ifdef ECORE_XRANDR */ + return NULL; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_refresh_rates_get */ + +//>= 1.1 +/* + * @brief sets the current primary output's refresh rate + * @param root window which's primary output will be queried + * @param size_index referencing the size to be set + * @param rate the refresh rate to be set + * @return EINA_TRUE on success else EINA_FALSE + */ +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) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_1_RET(EINA_FALSE); + Eina_Bool ret = EINA_FALSE; + XRRScreenConfiguration *sc = NULL; + + if (!(sc = XRRGetScreenInfo(_ecore_x_disp, root))) + return ret; + + if (!XRRSetScreenConfigAndRate(_ecore_x_disp, sc, + root, size_index, + RR_Rotate_0, rate, CurrentTime)) + ret = EINA_TRUE; + + XRRFreeScreenConfigInfo(sc); + return ret; +#else /* ifdef ECORE_XRANDR */ + return EINA_FALSE; +#endif /* ifdef ECORE_XRANDR */ +} /* ecore_x_randr_screen_primary_output_refresh_rate_set */ diff --git a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12.c b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12.c new file mode 100644 index 0000000000..ea6e7b3eba --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12.c @@ -0,0 +1,1898 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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 +} diff --git a/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_13.c b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_13.c new file mode 100644 index 0000000000..6e237305a9 --- /dev/null +++ b/legacy/ecore/src/lib/ecore_x/xlib/ecore_x_randr_13.c @@ -0,0 +1,62 @@ +/* + * vim:ts=8:sw=3:sts=8:expandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#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_3 ((1 << 16) | 3) +#define RANDR_CHECK_1_3_RET(ret) if(_randr_version < RANDR_1_3) return ret + +extern XRRScreenResources * (*_ecore_x_randr_get_screen_resources)(Display * + dpy, + Window + window); +extern int _randr_version; +#endif + +/* + * @param root window which's screen should be queried + * @return Ecore_X_Randr_Ouptut_Id or - if query failed or none is set - Ecore_X_Randr_None + */ +EAPI Ecore_X_Randr_Output +ecore_x_randr_primary_output_get(Ecore_X_Window root) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_3_RET(Ecore_X_Randr_None); + if (!_ecore_x_randr_root_validate(root)) + return Ecore_X_Randr_None; + + return XRRGetOutputPrimary(_ecore_x_disp, root); +#else + return Ecore_X_Randr_None; +#endif +} + +/* + * @param root window which's screen should be queried + * @param output that should be set as given root window's screen primary output + */ +EAPI void +ecore_x_randr_primary_output_set(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_3_RET(); + + if (_ecore_x_randr_output_validate(root, output)) + { + XRRSetOutputPrimary(_ecore_x_disp, root, output); + } + +#endif +}