diff options
Diffstat (limited to 'src/lib/ecore_x')
80 files changed, 52231 insertions, 0 deletions
diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h new file mode 100644 index 0000000000..b3fc0fabab --- /dev/null +++ b/src/lib/ecore_x/Ecore_X.h @@ -0,0 +1,2407 @@ +#ifndef _ECORE_X_H +#define _ECORE_X_H + +#include <Eina.h> + +#ifdef EAPI +# undef EAPI +#endif // ifdef EAPI + +#ifdef _MSC_VER +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else // ifdef BUILDING_DLL +# define EAPI __declspec(dllimport) +# endif // ifdef BUILDING_DLL +#else // ifdef _MSC_VER +# ifdef __GNUC__ +# if __GNUC__ >= 4 +# define EAPI __attribute__ ((visibility("default"))) +# else // if __GNUC__ >= 4 +# define EAPI +# endif // if __GNUC__ >= 4 +# else // ifdef __GNUC__ +# define EAPI +# endif // ifdef __GNUC__ +#endif // ifdef _MSC_VER + +#include <sys/types.h> + +/** + * @file + * @brief Ecore functions for dealing with the X Windows System + * + * Ecore_X provides a wrapper and convenience functions for using the + * X Windows System. Function groups for this part of the library + * include the following: + * @li @ref Ecore_X_Init_Group + * @li @ref Ecore_X_Display_Attr_Group + * @li @ref Ecore_X_Flush_Group + */ + +typedef unsigned int Ecore_X_ID; +#ifndef _ECORE_X_WINDOW_PREDEF +typedef Ecore_X_ID Ecore_X_Window; +#endif // ifndef _ECORE_X_WINDOW_PREDEF +typedef void *Ecore_X_Visual; +typedef Ecore_X_ID Ecore_X_Pixmap; +typedef Ecore_X_ID Ecore_X_Drawable; +#ifdef HAVE_ECORE_X_XCB +typedef Ecore_X_ID Ecore_X_GC; +#else // ifdef HAVE_ECORE_X_XCB +typedef void *Ecore_X_GC; +#endif /* HAVE_ECORE_X_XCB */ +typedef Ecore_X_ID Ecore_X_Atom; +typedef Ecore_X_ID Ecore_X_Colormap; +typedef Ecore_X_ID Ecore_X_Time; +typedef Ecore_X_ID Ecore_X_Cursor; +typedef void Ecore_X_Display; +typedef void Ecore_X_Connection; +typedef void Ecore_X_Screen; +typedef Ecore_X_ID Ecore_X_Sync_Counter; +typedef Ecore_X_ID Ecore_X_Sync_Alarm; +typedef void Ecore_X_XRegion; + +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; + +#ifdef __cplusplus +extern "C" { +#endif // ifdef __cplusplus + +typedef struct _Ecore_X_Rectangle +{ + int x, y; + unsigned int width, height; +} Ecore_X_Rectangle; + +typedef struct _Ecore_X_Icon +{ + unsigned int width, height; + unsigned int *data; +} Ecore_X_Icon; + +typedef enum _Ecore_X_GC_Value_Mask +{ + ECORE_X_GC_VALUE_MASK_FUNCTION = (1L << 0), + ECORE_X_GC_VALUE_MASK_PLANE_MASK = (1L << 1), + ECORE_X_GC_VALUE_MASK_FOREGROUND = (1L << 2), + ECORE_X_GC_VALUE_MASK_BACKGROUND = (1L << 3), + ECORE_X_GC_VALUE_MASK_LINE_WIDTH = (1L << 4), + ECORE_X_GC_VALUE_MASK_LINE_STYLE = (1L << 5), + ECORE_X_GC_VALUE_MASK_CAP_STYLE = (1L << 6), + ECORE_X_GC_VALUE_MASK_JOIN_STYLE = (1L << 7), + ECORE_X_GC_VALUE_MASK_FILL_STYLE = (1L << 8), + ECORE_X_GC_VALUE_MASK_FILL_RULE = (1L << 9), + ECORE_X_GC_VALUE_MASK_TILE = (1L << 10), + ECORE_X_GC_VALUE_MASK_STIPPLE = (1L << 11), + ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_X = (1L << 12), + ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_Y = (1L << 13), + ECORE_X_GC_VALUE_MASK_FONT = (1L << 14), + ECORE_X_GC_VALUE_MASK_SUBWINDOW_MODE = (1L << 15), + ECORE_X_GC_VALUE_MASK_GRAPHICS_EXPOSURES = (1L << 16), + ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_X = (1L << 17), + ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_Y = (1L << 18), + ECORE_X_GC_VALUE_MASK_CLIP_MASK = (1L << 19), + ECORE_X_GC_VALUE_MASK_DASH_OFFSET = (1L << 20), + ECORE_X_GC_VALUE_MASK_DASH_LIST = (1L << 21), + ECORE_X_GC_VALUE_MASK_ARC_MODE = (1L << 22) +} Ecore_X_GC_Value_Mask; + +typedef enum _Ecore_X_Composite_Update_Type +{ + ECORE_X_COMPOSITE_UPDATE_AUTOMATIC, + ECORE_X_COMPOSITE_UPDATE_MANUAL +} Ecore_X_Composite_Update_Type; + +/** + * @typedef _Ecore_X_Window_State + * Defines the different states of the window of Ecore_X. + */ +typedef enum _Ecore_X_Window_State +{ + ECORE_X_WINDOW_STATE_UNKNOWN = 0, + ECORE_X_WINDOW_STATE_ICONIFIED, /** The window is iconified. */ + ECORE_X_WINDOW_STATE_MODAL, /** The window is a modal dialog box. */ + ECORE_X_WINDOW_STATE_STICKY, /** The window manager should keep the window's position fixed + * even if the virtual desktop scrolls. */ + ECORE_X_WINDOW_STATE_MAXIMIZED_VERT, /** The window has the maximum vertical size. */ + ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ, /** The window has the maximum horizontal size. */ + ECORE_X_WINDOW_STATE_SHADED, /** The window is shaded. */ + ECORE_X_WINDOW_STATE_SKIP_TASKBAR, /** The window should not be included in the taskbar. */ + ECORE_X_WINDOW_STATE_SKIP_PAGER, /** The window should not be included in the pager. */ + ECORE_X_WINDOW_STATE_HIDDEN, /** The window is invisible (i.e. minimized/iconified) */ + ECORE_X_WINDOW_STATE_FULLSCREEN, /** The window should fill the entire screen and have no + * window border/decorations */ + ECORE_X_WINDOW_STATE_ABOVE, + ECORE_X_WINDOW_STATE_BELOW, + ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION +} Ecore_X_Window_State; + +typedef enum _Ecore_X_Window_State_Action +{ + ECORE_X_WINDOW_STATE_ACTION_REMOVE, + ECORE_X_WINDOW_STATE_ACTION_ADD, + ECORE_X_WINDOW_STATE_ACTION_TOGGLE +} Ecore_X_Window_State_Action; + +typedef enum _Ecore_X_Window_Stack_Mode +{ + ECORE_X_WINDOW_STACK_ABOVE = 0, + ECORE_X_WINDOW_STACK_BELOW = 1, + ECORE_X_WINDOW_STACK_TOP_IF = 2, + ECORE_X_WINDOW_STACK_BOTTOM_IF = 3, + ECORE_X_WINDOW_STACK_OPPOSITE = 4 +} Ecore_X_Window_Stack_Mode; + +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_NONE = 6, + ECORE_X_RANDR_OUTPUT_POLICY_ASK = 7 +} 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, + ECORE_X_RENDER_SUBPIXEL_ORDER_HORIZONTAL_RGB = 1, + ECORE_X_RENDER_SUBPIXEL_ORDER_HORIZONTAL_BGR = 2, + ECORE_X_RENDER_SUBPIXEL_ORDER_VERTICAL_RGB = 3, + ECORE_X_RENDER_SUBPIXEL_ORDER_VERTICAL_BGR = 4, + ECORE_X_RENDER_SUBPIXEL_ORDER_NONE = 5 +} Ecore_X_Render_Subpixel_Order; + +typedef enum _Ecore_X_Randr_Edid_Display_Interface_Type +{ + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_UNDEFINED, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DVI, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_HDMI_A, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_HDMI_B, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_MDDI, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT +} Ecore_X_Randr_Edid_Display_Interface_Type; + +typedef enum _Ecore_X_Randr_Edid_Display_Colorscheme +{ + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_MONOCHROME_GRAYSCALE = 0x00, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB = 0x08, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_NON_RGB = 0x10, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_UNDEFINED = 0x18, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_4_4_4 = 0x444000, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_4_4 = 0x444, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_2_2 = 0x422 +} Ecore_X_Randr_Edid_Display_Colorscheme; + +typedef enum _Ecore_X_Randr_Edid_Aspect_Ratio +{ + ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3 = 0x0, + ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9 = 0x1, + ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10 = 0x2, + ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4 = 0x4, + ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9 = 0x8 +} Ecore_X_Randr_Edid_Aspect_Ratio; + +#define ECORE_X_RANDR_EDID_UNKNOWN_VALUE -1 + +#define ECORE_X_SELECTION_TARGET_TARGETS "TARGETS" +#define ECORE_X_SELECTION_TARGET_TEXT "TEXT" +#define ECORE_X_SELECTION_TARGET_COMPOUND_TEXT "COMPOUND_TEXT" +#define ECORE_X_SELECTION_TARGET_STRING "STRING" +#define ECORE_X_SELECTION_TARGET_UTF8_STRING "UTF8_STRING" +#define ECORE_X_SELECTION_TARGET_FILENAME "FILENAME" + +#define ECORE_X_DND_VERSION 5 + +typedef enum _Ecore_X_Selection +{ + ECORE_X_SELECTION_PRIMARY, + ECORE_X_SELECTION_SECONDARY, + ECORE_X_SELECTION_XDND, + ECORE_X_SELECTION_CLIPBOARD, + ECORE_X_SELECTION_OTHER +} Ecore_X_Selection; + +typedef enum _Ecore_X_Event_Mode +{ + ECORE_X_EVENT_MODE_NORMAL, + ECORE_X_EVENT_MODE_WHILE_GRABBED, + ECORE_X_EVENT_MODE_GRAB, + ECORE_X_EVENT_MODE_UNGRAB +} Ecore_X_Event_Mode; + +typedef enum _Ecore_X_Event_Detail +{ + ECORE_X_EVENT_DETAIL_ANCESTOR, + ECORE_X_EVENT_DETAIL_VIRTUAL, + ECORE_X_EVENT_DETAIL_INFERIOR, + ECORE_X_EVENT_DETAIL_NON_LINEAR, + ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL, + ECORE_X_EVENT_DETAIL_POINTER, + ECORE_X_EVENT_DETAIL_POINTER_ROOT, + ECORE_X_EVENT_DETAIL_DETAIL_NONE +} Ecore_X_Event_Detail; + +typedef enum _Ecore_X_Event_Mask +{ + ECORE_X_EVENT_MASK_NONE = 0L, + ECORE_X_EVENT_MASK_KEY_DOWN = (1L << 0), + ECORE_X_EVENT_MASK_KEY_UP = (1L << 1), + ECORE_X_EVENT_MASK_MOUSE_DOWN = (1L << 2), + ECORE_X_EVENT_MASK_MOUSE_UP = (1L << 3), + ECORE_X_EVENT_MASK_MOUSE_IN = (1L << 4), + ECORE_X_EVENT_MASK_MOUSE_OUT = (1L << 5), + ECORE_X_EVENT_MASK_MOUSE_MOVE = (1L << 6), + ECORE_X_EVENT_MASK_WINDOW_DAMAGE = (1L << 15), + ECORE_X_EVENT_MASK_WINDOW_VISIBILITY = (1L << 16), + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE = (1L << 17), + ECORE_X_EVENT_MASK_WINDOW_RESIZE_MANAGE = (1L << 18), + ECORE_X_EVENT_MASK_WINDOW_MANAGE = (1L << 19), + ECORE_X_EVENT_MASK_WINDOW_CHILD_CONFIGURE = (1L << 20), + ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE = (1L << 21), + ECORE_X_EVENT_MASK_WINDOW_PROPERTY = (1L << 22), + ECORE_X_EVENT_MASK_WINDOW_COLORMAP = (1L << 23), + ECORE_X_EVENT_MASK_WINDOW_GRAB = (1L << 24), + ECORE_X_EVENT_MASK_MOUSE_WHEEL = (1L << 29), + ECORE_X_EVENT_MASK_WINDOW_FOCUS_IN = (1L << 30), + ECORE_X_EVENT_MASK_WINDOW_FOCUS_OUT = (1L << 31) +} Ecore_X_Event_Mask; + +typedef enum _Ecore_X_Gravity +{ + ECORE_X_GRAVITY_FORGET = 0, + ECORE_X_GRAVITY_UNMAP = 0, + ECORE_X_GRAVITY_NW = 1, + ECORE_X_GRAVITY_N = 2, + ECORE_X_GRAVITY_NE = 3, + ECORE_X_GRAVITY_W = 4, + ECORE_X_GRAVITY_CENTER = 5, + ECORE_X_GRAVITY_E = 6, + ECORE_X_GRAVITY_SW = 7, + ECORE_X_GRAVITY_S = 8, + ECORE_X_GRAVITY_SE = 9, + ECORE_X_GRAVITY_STATIC = 10 +} Ecore_X_Gravity; + +/* Needed for ecore_x_region_window_shape_set */ +typedef enum _Ecore_X_Shape_Type +{ + ECORE_X_SHAPE_BOUNDING, + ECORE_X_SHAPE_CLIP, + ECORE_X_SHAPE_INPUT +} Ecore_X_Shape_Type; + +typedef enum _Ecore_X_Mapping_Type +{ + ECORE_X_MAPPING_MODIFIER, + ECORE_X_MAPPING_KEYBOARD, + ECORE_X_MAPPING_MOUSE +} Ecore_X_Mapping_Type; + +typedef enum _Ecore_X_Randr_Property_Change +{ + ECORE_X_RANDR_PROPERTY_CHANGE_ADD, + ECORE_X_RANDR_PROPERTY_CHANGE_DEL +} Ecore_X_Randr_Property_Change; + +typedef enum _Ecore_X_Netwm_Direction +{ + ECORE_X_NETWM_DIRECTION_SIZE_TL = 0, + ECORE_X_NETWM_DIRECTION_SIZE_T = 1, + ECORE_X_NETWM_DIRECTION_SIZE_TR = 2, + ECORE_X_NETWM_DIRECTION_SIZE_R = 3, + ECORE_X_NETWM_DIRECTION_SIZE_BR = 4, + ECORE_X_NETWM_DIRECTION_SIZE_B = 5, + ECORE_X_NETWM_DIRECTION_SIZE_BL = 6, + ECORE_X_NETWM_DIRECTION_SIZE_L = 7, + ECORE_X_NETWM_DIRECTION_MOVE = 8, + ECORE_X_NETWM_DIRECTION_CANCEL = 11, +} Ecore_X_Netwm_Direction; + +/** + * @typedef _Ecore_X_Error_Code + * Defines the error codes of Ecore_X which wraps the X Window Systems + * protocol's errors. + * + * @since 1.7.0 + */ +typedef enum _Ecore_X_Error_Code +{ + /** Everything is okay. */ + ECORE_X_ERROR_CODE_SUCCESS = 0, /** Bad request code */ + ECORE_X_ERROR_CODE_BAD_REQUEST = 1, /** Int parameter out of range */ + ECORE_X_ERROR_CODE_BAD_VALUE = 2, /** Parameter not a Window */ + ECORE_X_ERROR_CODE_BAD_WINDOW = 3, /** Parameter not a Pixmap */ + ECORE_X_ERROR_CODE_BAD_PIXMAP = 4, /** Parameter not an Atom */ + ECORE_X_ERROR_CODE_BAD_ATOM = 5, /** Parameter not a Cursor */ + ECORE_X_ERROR_CODE_BAD_CURSOR = 6, /** Parameter not a Font */ + ECORE_X_ERROR_CODE_BAD_FONT = 7, /** Parameter mismatch */ + ECORE_X_ERROR_CODE_BAD_MATCH = 8, /** Parameter not a Pixmap or Window */ + ECORE_X_ERROR_CODE_BAD_DRAWABLE = 9, /** Bad access */ + ECORE_X_ERROR_CODE_BAD_ACCESS = 10, /** Insufficient resources */ + ECORE_X_ERROR_CODE_BAD_ALLOC = 11, /** No such colormap */ + ECORE_X_ERROR_CODE_BAD_COLOR = 12, /** Parameter not a GC */ + ECORE_X_ERROR_CODE_BAD_GC = 13, /** Choice not in range or already used */ + ECORE_X_ERROR_CODE_BAD_ID_CHOICE = 14, /** Font or color name doesn't exist */ + ECORE_X_ERROR_CODE_BAD_NAME = 15, /** Request length incorrect */ + ECORE_X_ERROR_CODE_BAD_LENGTH = 16, /** Server is defective */ + ECORE_X_ERROR_CODE_BAD_IMPLEMENTATION = 17, +} Ecore_X_Error_Code; + +typedef struct _Ecore_X_Event_Mouse_In Ecore_X_Event_Mouse_In; +typedef struct _Ecore_X_Event_Mouse_Out Ecore_X_Event_Mouse_Out; +typedef struct _Ecore_X_Event_Window_Focus_In Ecore_X_Event_Window_Focus_In; +typedef struct _Ecore_X_Event_Window_Focus_Out Ecore_X_Event_Window_Focus_Out; +typedef struct _Ecore_X_Event_Window_Keymap Ecore_X_Event_Window_Keymap; +typedef struct _Ecore_X_Event_Window_Damage Ecore_X_Event_Window_Damage; +typedef struct _Ecore_X_Event_Window_Visibility_Change Ecore_X_Event_Window_Visibility_Change; +typedef struct _Ecore_X_Event_Window_Create Ecore_X_Event_Window_Create; +typedef struct _Ecore_X_Event_Window_Destroy Ecore_X_Event_Window_Destroy; +typedef struct _Ecore_X_Event_Window_Hide Ecore_X_Event_Window_Hide; +typedef struct _Ecore_X_Event_Window_Show Ecore_X_Event_Window_Show; +typedef struct _Ecore_X_Event_Window_Show_Request Ecore_X_Event_Window_Show_Request; +typedef struct _Ecore_X_Event_Window_Reparent Ecore_X_Event_Window_Reparent; +typedef struct _Ecore_X_Event_Window_Configure Ecore_X_Event_Window_Configure; +typedef struct _Ecore_X_Event_Window_Configure_Request Ecore_X_Event_Window_Configure_Request; +typedef struct _Ecore_X_Event_Window_Gravity Ecore_X_Event_Window_Gravity; +typedef struct _Ecore_X_Event_Window_Resize_Request Ecore_X_Event_Window_Resize_Request; +typedef struct _Ecore_X_Event_Window_Stack Ecore_X_Event_Window_Stack; +typedef struct _Ecore_X_Event_Window_Stack_Request Ecore_X_Event_Window_Stack_Request; +typedef struct _Ecore_X_Event_Window_Property Ecore_X_Event_Window_Property; +typedef struct _Ecore_X_Event_Window_Colormap Ecore_X_Event_Window_Colormap; +typedef struct _Ecore_X_Event_Mapping_Change Ecore_X_Event_Mapping_Change; +typedef struct _Ecore_X_Event_Window_Mapping Ecore_X_Event_Window_Mapping; +typedef struct _Ecore_X_Event_Selection_Clear Ecore_X_Event_Selection_Clear; +typedef struct _Ecore_X_Event_Selection_Request Ecore_X_Event_Selection_Request; +typedef struct _Ecore_X_Event_Selection_Notify Ecore_X_Event_Selection_Notify; +typedef struct _Ecore_X_Event_Fixes_Selection_Notify Ecore_X_Event_Fixes_Selection_Notify; +typedef struct _Ecore_X_Selection_Data Ecore_X_Selection_Data; +typedef struct _Ecore_X_Selection_Data_Files Ecore_X_Selection_Data_Files; +typedef struct _Ecore_X_Selection_Data_Text Ecore_X_Selection_Data_Text; +typedef struct _Ecore_X_Selection_Data_Targets Ecore_X_Selection_Data_Targets; +typedef struct _Ecore_X_Event_Xdnd_Enter Ecore_X_Event_Xdnd_Enter; +typedef struct _Ecore_X_Event_Xdnd_Position Ecore_X_Event_Xdnd_Position; +typedef struct _Ecore_X_Event_Xdnd_Status Ecore_X_Event_Xdnd_Status; +typedef struct _Ecore_X_Event_Xdnd_Leave Ecore_X_Event_Xdnd_Leave; +typedef struct _Ecore_X_Event_Xdnd_Drop Ecore_X_Event_Xdnd_Drop; +typedef struct _Ecore_X_Event_Xdnd_Finished Ecore_X_Event_Xdnd_Finished; +typedef struct _Ecore_X_Event_Client_Message Ecore_X_Event_Client_Message; +typedef struct _Ecore_X_Event_Window_Shape Ecore_X_Event_Window_Shape; +typedef struct _Ecore_X_Event_Screensaver_Notify Ecore_X_Event_Screensaver_Notify; +typedef struct _Ecore_X_Event_Gesture_Notify_Flick Ecore_X_Event_Gesture_Notify_Flick; +typedef struct _Ecore_X_Event_Gesture_Notify_Pan Ecore_X_Event_Gesture_Notify_Pan; +typedef struct _Ecore_X_Event_Gesture_Notify_PinchRotation Ecore_X_Event_Gesture_Notify_PinchRotation; +typedef struct _Ecore_X_Event_Gesture_Notify_Tap Ecore_X_Event_Gesture_Notify_Tap; +typedef struct _Ecore_X_Event_Gesture_Notify_TapNHold Ecore_X_Event_Gesture_Notify_TapNHold; +typedef struct _Ecore_X_Event_Gesture_Notify_Hold Ecore_X_Event_Gesture_Notify_Hold; +typedef struct _Ecore_X_Event_Gesture_Notify_Group Ecore_X_Event_Gesture_Notify_Group; +typedef struct _Ecore_X_Event_Sync_Counter Ecore_X_Event_Sync_Counter; +typedef struct _Ecore_X_Event_Sync_Alarm Ecore_X_Event_Sync_Alarm; +typedef struct _Ecore_X_Event_Screen_Change Ecore_X_Event_Screen_Change; +typedef struct _Ecore_X_Event_Randr_Crtc_Change Ecore_X_Event_Randr_Crtc_Change; +typedef struct _Ecore_X_Event_Randr_Output_Change Ecore_X_Event_Randr_Output_Change; +typedef struct _Ecore_X_Event_Randr_Output_Property_Notify Ecore_X_Event_Randr_Output_Property_Notify; + +typedef struct _Ecore_X_Event_Window_Delete_Request Ecore_X_Event_Window_Delete_Request; +typedef struct _Ecore_X_Event_Window_Move_Resize_Request Ecore_X_Event_Window_Move_Resize_Request; +typedef struct _Ecore_X_Event_Window_State_Request Ecore_X_Event_Window_State_Request; +typedef struct _Ecore_X_Event_Frame_Extents_Request Ecore_X_Event_Frame_Extents_Request; +typedef struct _Ecore_X_Event_Ping Ecore_X_Event_Ping; +typedef struct _Ecore_X_Event_Desktop_Change Ecore_X_Event_Desktop_Change; + +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; + +typedef struct _Ecore_X_Xdnd_Position Ecore_X_Xdnd_Position; + +struct _Ecore_X_Event_Mouse_In +{ + int modifiers; + int x, y; + Eina_Bool same_screen : 1; + struct + { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Window root_win; + Ecore_X_Event_Mode mode; + Ecore_X_Event_Detail detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Mouse_Out +{ + int modifiers; + int x, y; + int same_screen; + struct + { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Window root_win; + Ecore_X_Event_Mode mode; + Ecore_X_Event_Detail detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Focus_In +{ + Ecore_X_Window win; + Ecore_X_Event_Mode mode; + Ecore_X_Event_Detail detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Focus_Out +{ + Ecore_X_Window win; + Ecore_X_Event_Mode mode; + Ecore_X_Event_Detail detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Keymap +{ + Ecore_X_Window win; +}; + +struct _Ecore_X_Event_Window_Damage +{ + Ecore_X_Window win; + int x, y, w, h; + int count; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Visibility_Change +{ + Ecore_X_Window win; + int fully_obscured; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Create +{ + Ecore_X_Window win; + Ecore_X_Window parent; + int override; + int x, y, w, h; + int border; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Destroy +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Hide +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Show +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Show_Request +{ + Ecore_X_Window win; + Ecore_X_Window parent; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Reparent +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Window parent; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Configure +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Window abovewin; + int x, y, w, h; + int border; + Eina_Bool override : 1; + Eina_Bool from_wm : 1; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Configure_Request +{ + Ecore_X_Window win; + Ecore_X_Window parent_win; + Ecore_X_Window abovewin; + int x, y, w, h; + int border; + Ecore_X_Window_Stack_Mode detail; + unsigned long value_mask; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Gravity +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Resize_Request +{ + Ecore_X_Window win; + int w, h; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Stack +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Window_Stack_Mode detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Stack_Request +{ + Ecore_X_Window win; + Ecore_X_Window parent; + Ecore_X_Window_Stack_Mode detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Property +{ + Ecore_X_Window win; + Ecore_X_Atom atom; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Colormap +{ + Ecore_X_Window win; + Ecore_X_Colormap cmap; + Eina_Bool installed : 1; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Mapping_Change +{ + Ecore_X_Mapping_Type type; + int keycode; + int num; +}; + +struct _Ecore_X_Event_Selection_Clear +{ + Ecore_X_Window win; + Ecore_X_Selection selection; + Ecore_X_Atom atom; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Selection_Request +{ + Ecore_X_Window owner; + Ecore_X_Window requestor; + Ecore_X_Time time; + Ecore_X_Atom selection; + Ecore_X_Atom target; + Ecore_X_Atom property; +}; + +typedef enum +{ + ECORE_X_OWNER_CHANGE_REASON_NEW_OWNER, + ECORE_X_OWNER_CHANGE_REASON_DESTROY, + ECORE_X_OWNER_CHANGE_REASON_CLOSE +} Ecore_X_Owner_Change_Reason; + +struct _Ecore_X_Event_Fixes_Selection_Notify +{ + Ecore_X_Window win; + Ecore_X_Window owner; + Ecore_X_Time time; + Ecore_X_Time selection_time; + Ecore_X_Selection selection; + Ecore_X_Atom atom; + Ecore_X_Owner_Change_Reason reason; +}; + +struct _Ecore_X_Event_Selection_Notify +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Selection selection; + Ecore_X_Atom atom; + char *target; + void *data; +}; + +struct _Ecore_X_Selection_Data +{ + enum + { + ECORE_X_SELECTION_CONTENT_NONE, + ECORE_X_SELECTION_CONTENT_TEXT, + ECORE_X_SELECTION_CONTENT_FILES, + ECORE_X_SELECTION_CONTENT_TARGETS, + ECORE_X_SELECTION_CONTENT_CUSTOM + } content; + unsigned char *data; + int length; + int format; + int (*free)(void *data); +}; + +struct _Ecore_X_Selection_Data_Files +{ + Ecore_X_Selection_Data data; + char **files; + int num_files; +}; + +struct _Ecore_X_Selection_Data_Text +{ + Ecore_X_Selection_Data data; + char *text; +}; + +struct _Ecore_X_Selection_Data_Targets +{ + Ecore_X_Selection_Data data; + char **targets; + int num_targets; +}; + +struct _Ecore_X_Event_Xdnd_Enter +{ + Ecore_X_Window win, source; + + char **types; + int num_types; +}; + +struct _Ecore_X_Event_Xdnd_Position +{ + Ecore_X_Window win, source; + struct + { + int x, y; + } position; + Ecore_X_Atom action; +}; + +struct _Ecore_X_Xdnd_Position +{ + Ecore_X_Window win, prev; + struct + { + int x, y; + } position; +}; + +struct _Ecore_X_Event_Xdnd_Status +{ + Ecore_X_Window win, target; + Eina_Bool will_accept : 1; + Ecore_X_Rectangle rectangle; + Ecore_X_Atom action; +}; + +struct _Ecore_X_Event_Xdnd_Leave +{ + Ecore_X_Window win, source; +}; + +struct _Ecore_X_Event_Xdnd_Drop +{ + Ecore_X_Window win, source; + Ecore_X_Atom action; + struct + { + int x, y; + } position; +}; + +struct _Ecore_X_Event_Xdnd_Finished +{ + Ecore_X_Window win, target; + Eina_Bool completed : 1; + Ecore_X_Atom action; +}; + +struct _Ecore_X_Event_Client_Message +{ + Ecore_X_Window win; + Ecore_X_Atom message_type; + int format; + union + { + char b[20]; + short s[10]; + long l[5]; + } data; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Shape +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Shape_Type type; + int x, y, w, h; + Eina_Bool shaped : 1; +}; + +struct _Ecore_X_Event_Screensaver_Notify +{ + Ecore_X_Window win; + Eina_Bool on : 1; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Sync_Counter +{ + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Sync_Alarm +{ + Ecore_X_Time time; + 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; + Ecore_X_Randr_Screen_Size_MM size; /* in pixel and millimeters */ + Ecore_X_Time time; + Ecore_X_Time config_time; + 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_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_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_Window win; + Ecore_X_Randr_Output output; + Ecore_X_Atom property; + Ecore_X_Time time; + Ecore_X_Randr_Property_Change state; +}; + +struct _Ecore_X_Event_Window_Delete_Request +{ + Ecore_X_Window win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Title_Change +{ + Ecore_X_Window win; + char *title; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Visible_Title_Change +{ + Ecore_X_Window win; + char *title; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Icon_Name_Change +{ + Ecore_X_Window win; + char *name; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change +{ + Ecore_X_Window win; + char *name; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Client_Machine_Change +{ + Ecore_X_Window win; + char *name; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Name_Class_Change +{ + Ecore_X_Window win; + char *name; + char *clas; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Pid_Change +{ + Ecore_X_Window win; + pid_t pid; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Prop_Desktop_Change +{ + Ecore_X_Window win; + long desktop; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Startup_Sequence +{ + Ecore_X_Window win; +}; + +struct _Ecore_X_Event_Window_Move_Resize_Request +{ + Ecore_X_Window win; + int x, y; + int direction; + int button; + int source; +}; + +struct _Ecore_X_Event_Window_State_Request +{ + Ecore_X_Window win; + Ecore_X_Window_State_Action action; + Ecore_X_Window_State state[2]; + int source; +}; + +struct _Ecore_X_Event_Frame_Extents_Request +{ + Ecore_X_Window win; +}; + +struct _Ecore_X_Event_Ping +{ + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Desktop_Change +{ + Ecore_X_Window win; + unsigned int desk; + int source; +}; + +struct _Ecore_X_Event_Generic +{ + int extension; + int evtype; + unsigned int cookie; + void *data; +}; + +EAPI extern int ECORE_X_EVENT_ANY; /**< low level event dependent on + backend in use, if Xlib will be XEvent, if XCB will be xcb_generic_event_t. + @warning avoid using it. + */ +EAPI extern int ECORE_X_EVENT_MOUSE_IN; +EAPI extern int ECORE_X_EVENT_MOUSE_OUT; +EAPI extern int ECORE_X_EVENT_WINDOW_FOCUS_IN; +EAPI extern int ECORE_X_EVENT_WINDOW_FOCUS_OUT; +EAPI extern int ECORE_X_EVENT_WINDOW_KEYMAP; +EAPI extern int ECORE_X_EVENT_WINDOW_DAMAGE; +EAPI extern int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE; +EAPI extern int ECORE_X_EVENT_WINDOW_CREATE; +EAPI extern int ECORE_X_EVENT_WINDOW_DESTROY; +EAPI extern int ECORE_X_EVENT_WINDOW_HIDE; +EAPI extern int ECORE_X_EVENT_WINDOW_SHOW; +EAPI extern int ECORE_X_EVENT_WINDOW_SHOW_REQUEST; +EAPI extern int ECORE_X_EVENT_WINDOW_REPARENT; +EAPI extern int ECORE_X_EVENT_WINDOW_CONFIGURE; +EAPI extern int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST; +EAPI extern int ECORE_X_EVENT_WINDOW_GRAVITY; +EAPI extern int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST; +EAPI extern int ECORE_X_EVENT_WINDOW_STACK; +EAPI extern int ECORE_X_EVENT_WINDOW_STACK_REQUEST; +EAPI extern int ECORE_X_EVENT_WINDOW_PROPERTY; +EAPI extern int ECORE_X_EVENT_WINDOW_COLORMAP; +EAPI extern int ECORE_X_EVENT_WINDOW_MAPPING; +EAPI extern int ECORE_X_EVENT_MAPPING_CHANGE; +EAPI extern int ECORE_X_EVENT_SELECTION_CLEAR; +EAPI extern int ECORE_X_EVENT_SELECTION_REQUEST; +EAPI extern int ECORE_X_EVENT_SELECTION_NOTIFY; +EAPI extern int ECORE_X_EVENT_FIXES_SELECTION_NOTIFY; +EAPI extern int ECORE_X_EVENT_CLIENT_MESSAGE; +EAPI extern int ECORE_X_EVENT_WINDOW_SHAPE; +EAPI extern int ECORE_X_EVENT_SCREENSAVER_NOTIFY; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_FLICK; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_PAN; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_TAP; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_HOLD; +EAPI extern int ECORE_X_EVENT_GESTURE_NOTIFY_GROUP; +EAPI extern int ECORE_X_EVENT_SYNC_COUNTER; +EAPI extern int ECORE_X_EVENT_SYNC_ALARM; +EAPI extern int ECORE_X_EVENT_SCREEN_CHANGE; +EAPI extern int ECORE_X_EVENT_RANDR_CRTC_CHANGE; +EAPI extern int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE; +EAPI extern int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY; +EAPI extern int ECORE_X_EVENT_DAMAGE_NOTIFY; + +EAPI extern int ECORE_X_EVENT_WINDOW_DELETE_REQUEST; + +EAPI extern int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST; +EAPI extern int ECORE_X_EVENT_WINDOW_STATE_REQUEST; +EAPI extern int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST; +EAPI extern int ECORE_X_EVENT_PING; +EAPI extern int ECORE_X_EVENT_DESKTOP_CHANGE; + +EAPI extern int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW; +EAPI extern int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE; +EAPI extern int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE; +EAPI extern int ECORE_X_EVENT_XKB_STATE_NOTIFY; /** @since 1.7 */ +EAPI extern int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY; /** @since 1.7 */ + +EAPI extern int ECORE_X_EVENT_GENERIC; + +EAPI extern int ECORE_X_EVENT_XDND_ENTER; +EAPI extern int ECORE_X_EVENT_XDND_POSITION; +EAPI extern int ECORE_X_EVENT_XDND_STATUS; +EAPI extern int ECORE_X_EVENT_XDND_LEAVE; +EAPI extern int ECORE_X_EVENT_XDND_DROP; +EAPI extern int ECORE_X_EVENT_XDND_FINISHED; + +EAPI extern int ECORE_X_MODIFIER_SHIFT; /**< @since 1.7 */ +EAPI extern int ECORE_X_MODIFIER_CTRL; /**< @since 1.7 */ +EAPI extern int ECORE_X_MODIFIER_ALT; /**< @since 1.7 */ +EAPI extern int ECORE_X_MODIFIER_WIN; /**< @since 1.7 */ +EAPI extern int ECORE_X_MODIFIER_ALTGR; /**< @since 1.7 */ + +EAPI extern int ECORE_X_LOCK_SCROLL; +EAPI extern int ECORE_X_LOCK_NUM; +EAPI extern int ECORE_X_LOCK_CAPS; +EAPI extern int ECORE_X_LOCK_SHIFT; + +EAPI extern int ECORE_X_RAW_BUTTON_PRESS; /**< @since 1.8 */ +EAPI extern int ECORE_X_RAW_BUTTON_RELEASE; /**< @since 1.8 */ +EAPI extern int ECORE_X_RAW_MOTION; /**< @since 1.8 */ + +typedef enum _Ecore_X_WM_Protocol +{ + /** If enabled the window manager will be asked to send a + * delete message instead of just closing (destroying) the window. */ + ECORE_X_WM_PROTOCOL_DELETE_REQUEST, + + /** If enabled the window manager will be told that the window + * explicitly sets input focus. */ + ECORE_X_WM_PROTOCOL_TAKE_FOCUS, + + /** If enabled the window manager can ping the window to check + * if it is alive. */ + ECORE_X_NET_WM_PROTOCOL_PING, + + /** If enabled the window manager can sync updating with the + * window (?) */ + ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST, + + /** Number of defined items */ + ECORE_X_WM_PROTOCOL_NUM +} Ecore_X_WM_Protocol; + +typedef enum _Ecore_X_Window_Input_Mode +{ + /** The window can never be focused */ + ECORE_X_WINDOW_INPUT_MODE_NONE, + + /** The window can be focused by the WM but doesn't focus itself */ + ECORE_X_WINDOW_INPUT_MODE_PASSIVE, + + /** The window sets the focus itself if one of its sub-windows + * already is focused */ + ECORE_X_WINDOW_INPUT_MODE_ACTIVE_LOCAL, + + /** The window sets the focus itself even if another window + * is currently focused */ + ECORE_X_WINDOW_INPUT_MODE_ACTIVE_GLOBAL +} Ecore_X_Window_Input_Mode; + +/** + * @typedef _Ecore_X_Window_State_Hint + * Defines the different state hint of the window of Ecore_X. + */ +typedef enum _Ecore_X_Window_State_Hint +{ + /** Do not provide any state hint to the window manager */ + ECORE_X_WINDOW_STATE_HINT_NONE = -1, + + /** The window wants to remain hidden and NOT iconified */ + ECORE_X_WINDOW_STATE_HINT_WITHDRAWN, + + /** The window wants to be mapped normally */ + ECORE_X_WINDOW_STATE_HINT_NORMAL, + + /** The window wants to start in an iconified state */ + ECORE_X_WINDOW_STATE_HINT_ICONIC +} Ecore_X_Window_State_Hint; + +typedef enum _Ecore_X_Window_Type +{ + ECORE_X_WINDOW_TYPE_UNKNOWN = 0, + ECORE_X_WINDOW_TYPE_DESKTOP, + ECORE_X_WINDOW_TYPE_DOCK, + ECORE_X_WINDOW_TYPE_TOOLBAR, + ECORE_X_WINDOW_TYPE_MENU, + ECORE_X_WINDOW_TYPE_UTILITY, + ECORE_X_WINDOW_TYPE_SPLASH, + ECORE_X_WINDOW_TYPE_DIALOG, + ECORE_X_WINDOW_TYPE_NORMAL, + ECORE_X_WINDOW_TYPE_DROPDOWN_MENU, + ECORE_X_WINDOW_TYPE_POPUP_MENU, + ECORE_X_WINDOW_TYPE_TOOLTIP, + ECORE_X_WINDOW_TYPE_NOTIFICATION, + ECORE_X_WINDOW_TYPE_COMBO, + ECORE_X_WINDOW_TYPE_DND +} Ecore_X_Window_Type; + +typedef enum _Ecore_X_Action +{ + ECORE_X_ACTION_MOVE, + ECORE_X_ACTION_RESIZE, + ECORE_X_ACTION_MINIMIZE, + ECORE_X_ACTION_SHADE, + ECORE_X_ACTION_STICK, + ECORE_X_ACTION_MAXIMIZE_HORZ, + ECORE_X_ACTION_MAXIMIZE_VERT, + ECORE_X_ACTION_FULLSCREEN, + ECORE_X_ACTION_CHANGE_DESKTOP, + ECORE_X_ACTION_CLOSE, + ECORE_X_ACTION_ABOVE, + ECORE_X_ACTION_BELOW +} Ecore_X_Action; + +typedef enum _Ecore_X_Window_Configure_Mask +{ + ECORE_X_WINDOW_CONFIGURE_MASK_X = (1 << 0), + ECORE_X_WINDOW_CONFIGURE_MASK_Y = (1 << 1), + ECORE_X_WINDOW_CONFIGURE_MASK_W = (1 << 2), + ECORE_X_WINDOW_CONFIGURE_MASK_H = (1 << 3), + ECORE_X_WINDOW_CONFIGURE_MASK_BORDER_WIDTH = (1 << 4), + ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING = (1 << 5), + ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE = (1 << 6) +} Ecore_X_Window_Configure_Mask; + +typedef enum _Ecore_X_Virtual_Keyboard_State +{ + ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN = 0, + ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF, + ECORE_X_VIRTUAL_KEYBOARD_STATE_ON, + ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA, + ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC, + ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN, + ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER, + ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX, + ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL, + ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD, + ECORE_X_VIRTUAL_KEYBOARD_STATE_IP, + ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST, + ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE, + ECORE_X_VIRTUAL_KEYBOARD_STATE_URL, + ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD, + ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME +} Ecore_X_Virtual_Keyboard_State; + +typedef enum _Ecore_X_Illume_Mode +{ + ECORE_X_ILLUME_MODE_UNKNOWN = 0, + ECORE_X_ILLUME_MODE_SINGLE, + ECORE_X_ILLUME_MODE_DUAL_TOP, + ECORE_X_ILLUME_MODE_DUAL_LEFT +} Ecore_X_Illume_Mode; + +typedef enum _Ecore_X_Illume_Quickpanel_State +{ + ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN = 0, + ECORE_X_ILLUME_QUICKPANEL_STATE_OFF, + ECORE_X_ILLUME_QUICKPANEL_STATE_ON +} Ecore_X_Illume_Quickpanel_State; + +typedef enum _Ecore_X_Illume_Indicator_State +{ + ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN = 0, + ECORE_X_ILLUME_INDICATOR_STATE_OFF, + ECORE_X_ILLUME_INDICATOR_STATE_ON +} Ecore_X_Illume_Indicator_State; + +typedef enum _Ecore_X_Illume_Clipboard_State +{ + ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN = 0, + ECORE_X_ILLUME_CLIPBOARD_STATE_OFF, + ECORE_X_ILLUME_CLIPBOARD_STATE_ON +} Ecore_X_Illume_Clipboard_State; + +typedef enum _Ecore_X_Illume_Indicator_Opacity_Mode +{ + ECORE_X_ILLUME_INDICATOR_OPACITY_UNKNOWN = 0, + ECORE_X_ILLUME_INDICATOR_OPAQUE, + ECORE_X_ILLUME_INDICATOR_TRANSLUCENT, + ECORE_X_ILLUME_INDICATOR_TRANSPARENT +} Ecore_X_Illume_Indicator_Opacity_Mode; + +typedef enum _Ecore_X_Illume_Window_State +{ + ECORE_X_ILLUME_WINDOW_STATE_NORMAL = 0, + ECORE_X_ILLUME_WINDOW_STATE_FLOATING +} Ecore_X_Illume_Window_State; + +/* Window layer constants */ +#define ECORE_X_WINDOW_LAYER_BELOW 2 +#define ECORE_X_WINDOW_LAYER_NORMAL 4 +#define ECORE_X_WINDOW_LAYER_ABOVE 6 + +/* Property list operations */ +#define ECORE_X_PROP_LIST_REMOVE 0 +#define ECORE_X_PROP_LIST_ADD 1 +#define ECORE_X_PROP_LIST_TOGGLE 2 + +EAPI int ecore_x_init(const char *name); +EAPI int ecore_x_shutdown(void); +EAPI int ecore_x_disconnect(void); +EAPI Ecore_X_Display *ecore_x_display_get(void); +EAPI Ecore_X_Connection *ecore_x_connection_get(void); +EAPI int ecore_x_fd_get(void); +EAPI Ecore_X_Screen *ecore_x_default_screen_get(void); +EAPI void ecore_x_screen_size_get(const Ecore_X_Screen *screen, int *w, int *h); +EAPI int ecore_x_screen_count_get(void); +EAPI int ecore_x_screen_index_get(const Ecore_X_Screen *screen); +EAPI Ecore_X_Screen *ecore_x_screen_get(int index); + +EAPI void ecore_x_double_click_time_set(double t); +EAPI double ecore_x_double_click_time_get(void); +EAPI void ecore_x_flush(void); +EAPI void ecore_x_sync(void); +EAPI void ecore_x_killall(Ecore_X_Window root); +EAPI void ecore_x_kill(Ecore_X_Window win); +EAPI int ecore_x_dpi_get(void); +EAPI Eina_Bool ecore_x_bell(int percent); +EAPI unsigned int ecore_x_visual_id_get(Ecore_X_Visual visual); + +EAPI Ecore_X_Visual ecore_x_default_visual_get(Ecore_X_Display *disp, Ecore_X_Screen *screen); +EAPI Ecore_X_Colormap ecore_x_default_colormap_get(Ecore_X_Display *disp, Ecore_X_Screen *screen); +EAPI int ecore_x_default_depth_get(Ecore_X_Display *disp, Ecore_X_Screen *screen); + +EAPI Ecore_X_Time ecore_x_current_time_get(void); + +EAPI void ecore_x_error_handler_set(void (*func)(void *data), const void *data); +EAPI void ecore_x_io_error_handler_set(void (*func)(void *data), const void *data); +EAPI int ecore_x_error_request_get(void); +EAPI int ecore_x_error_code_get(void); +EAPI Ecore_X_ID ecore_x_error_resource_id_get(void); + +EAPI void ecore_x_event_mask_set(Ecore_X_Window w, Ecore_X_Event_Mask mask); +EAPI void ecore_x_event_mask_unset(Ecore_X_Window w, Ecore_X_Event_Mask mask); + +EAPI Eina_Bool ecore_x_selection_notify_send(Ecore_X_Window requestor, Ecore_X_Atom selection, Ecore_X_Atom target, Ecore_X_Atom property, Ecore_X_Time time); +EAPI Eina_Bool ecore_x_selection_primary_set(Ecore_X_Window w, const void *data, int size); +EAPI Eina_Bool ecore_x_selection_primary_clear(void); +EAPI Eina_Bool ecore_x_selection_secondary_set(Ecore_X_Window w, const void *data, int size); +EAPI Eina_Bool ecore_x_selection_secondary_clear(void); +EAPI Eina_Bool ecore_x_selection_xdnd_set(Ecore_X_Window w, const void *data, int size); +EAPI Eina_Bool ecore_x_selection_xdnd_clear(void); +EAPI Eina_Bool ecore_x_selection_clipboard_set(Ecore_X_Window w, const void *data, int size); +EAPI Eina_Bool ecore_x_selection_clipboard_clear(void); +EAPI void ecore_x_selection_primary_request(Ecore_X_Window w, const char *target); +EAPI void ecore_x_selection_secondary_request(Ecore_X_Window w, const char *target); +EAPI void ecore_x_selection_xdnd_request(Ecore_X_Window w, const char *target); +EAPI void ecore_x_selection_clipboard_request(Ecore_X_Window w, const char *target); +EAPI Eina_Bool ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret, int *len, Ecore_X_Atom *targprop, int *targsize); +EAPI void ecore_x_selection_converter_add(char *target, Eina_Bool (*func)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *, int *)); +EAPI void ecore_x_selection_converter_atom_add(Ecore_X_Atom target, Eina_Bool (*func)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *tprop, int *tsize)); +EAPI void ecore_x_selection_converter_del(char *target); +EAPI void ecore_x_selection_converter_atom_del(Ecore_X_Atom target); +EAPI void ecore_x_selection_parser_add(const char *target, void *(*func)(const char *target, void *data, int size, int format)); +EAPI void ecore_x_selection_parser_del(const char *target); +EAPI void ecore_x_selection_owner_set(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Time tm); +EAPI Ecore_X_Window ecore_x_selection_owner_get(Ecore_X_Atom atom); +EAPI Eina_Bool ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *targprop, int *s); /** @since 1.8 */ + +EAPI void ecore_x_dnd_aware_set(Ecore_X_Window win, Eina_Bool on); +EAPI int ecore_x_dnd_version_get(Ecore_X_Window win); +EAPI Eina_Bool ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type); +EAPI void ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, Eina_Bool on); +EAPI void ecore_x_dnd_types_set(Ecore_X_Window win, const char **types, unsigned int num_types); +EAPI void ecore_x_dnd_actions_set(Ecore_X_Window win, Ecore_X_Atom *actions, unsigned int num_actions); +EAPI Eina_Bool ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size); +EAPI Eina_Bool ecore_x_dnd_drop(void); +EAPI void ecore_x_dnd_send_status(Eina_Bool will_accept, Eina_Bool suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action); +EAPI void ecore_x_dnd_send_finished(void); +EAPI void ecore_x_dnd_source_action_set(Ecore_X_Atom action); +EAPI Ecore_X_Atom ecore_x_dnd_source_action_get(void); +EAPI void ecore_x_dnd_callback_pos_update_set(void (*cb)(void *, Ecore_X_Xdnd_Position *data), const void *data); + +EAPI Ecore_X_Window ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h); +EAPI Ecore_X_Window ecore_x_window_override_new(Ecore_X_Window parent, int x, int y, int w, int h); +EAPI int ecore_x_window_argb_get(Ecore_X_Window win); +EAPI Ecore_X_Window ecore_x_window_manager_argb_new(Ecore_X_Window parent, int x, int y, int w, int h); +EAPI Ecore_X_Window ecore_x_window_argb_new(Ecore_X_Window parent, int x, int y, int w, int h); +EAPI Ecore_X_Window ecore_x_window_override_argb_new(Ecore_X_Window parent, int x, int y, int w, int h); +EAPI Ecore_X_Window ecore_x_window_input_new(Ecore_X_Window parent, int x, int y, int w, int h); +EAPI void ecore_x_window_configure(Ecore_X_Window win, Ecore_X_Window_Configure_Mask mask, int x, int y, int w, int h, int border_width, Ecore_X_Window sibling, int stack_mode); +EAPI void ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor c); +EAPI void ecore_x_window_free(Ecore_X_Window win); +EAPI void ecore_x_window_ignore_set(Ecore_X_Window win, int ignore); +EAPI Ecore_X_Window *ecore_x_window_ignore_list(int *num); + +EAPI void ecore_x_window_delete_request_send(Ecore_X_Window win); +EAPI void ecore_x_window_show(Ecore_X_Window win); +EAPI void ecore_x_window_hide(Ecore_X_Window win); +EAPI void ecore_x_window_move(Ecore_X_Window win, int x, int y); +EAPI void ecore_x_window_resize(Ecore_X_Window win, int w, int h); +EAPI void ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_focus(Ecore_X_Window win); +EAPI void ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time t); +EAPI Ecore_X_Window ecore_x_window_focus_get(void); +EAPI void ecore_x_window_raise(Ecore_X_Window win); +EAPI void ecore_x_window_lower(Ecore_X_Window win); +EAPI void ecore_x_window_reparent(Ecore_X_Window win, Ecore_X_Window new_parent, int x, int y); +EAPI void ecore_x_window_size_get(Ecore_X_Window win, int *w, int *h); +EAPI void ecore_x_window_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h); +EAPI int ecore_x_window_border_width_get(Ecore_X_Window win); +EAPI void ecore_x_window_border_width_set(Ecore_X_Window win, int width); +EAPI int ecore_x_window_depth_get(Ecore_X_Window win); +EAPI void ecore_x_window_cursor_show(Ecore_X_Window win, Eina_Bool show); +EAPI void ecore_x_window_defaults_set(Ecore_X_Window win); +EAPI int ecore_x_window_visible_get(Ecore_X_Window win); +EAPI Ecore_X_Window ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, int x, int y, Ecore_X_Window *skip, int skip_num); +EAPI Ecore_X_Window ecore_x_window_shadow_parent_get(Ecore_X_Window root, Ecore_X_Window win); +EAPI void ecore_x_window_shadow_tree_flush(void); +EAPI Ecore_X_Window ecore_x_window_root_get(Ecore_X_Window win); +EAPI Ecore_X_Window ecore_x_window_at_xy_get(int x, int y); +EAPI Ecore_X_Window ecore_x_window_at_xy_with_skip_get(int x, int y, Ecore_X_Window *skip, int skip_num); +EAPI Ecore_X_Window ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, int x, int y); +EAPI Ecore_X_Window ecore_x_window_parent_get(Ecore_X_Window win); + +EAPI void ecore_x_window_background_color_set(Ecore_X_Window win, unsigned short r, unsigned short g, unsigned short b); +EAPI void ecore_x_window_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav); +EAPI void ecore_x_window_pixel_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav); +EAPI void ecore_x_window_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pmap); +EAPI void ecore_x_window_area_clear(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_area_expose(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_override_set(Ecore_X_Window win, Eina_Bool override); + +EAPI void ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom, unsigned int *val, unsigned int num); +EAPI int ecore_x_window_prop_card32_get(Ecore_X_Window win, Ecore_X_Atom atom, unsigned int *val, unsigned int len); +EAPI int ecore_x_window_prop_card32_list_get(Ecore_X_Window win, Ecore_X_Atom atom, unsigned int **plst); + +EAPI void ecore_x_window_prop_xid_set(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom type, Ecore_X_ID *lst, unsigned int num); +EAPI int ecore_x_window_prop_xid_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom type, Ecore_X_ID *lst, unsigned int len); +EAPI int ecore_x_window_prop_xid_list_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom type, Ecore_X_ID **plst); +EAPI void ecore_x_window_prop_xid_list_change(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom type, Ecore_X_ID item, int op); +EAPI void ecore_x_window_prop_atom_set(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom *val, unsigned int num); +EAPI int ecore_x_window_prop_atom_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom *val, unsigned int len); +EAPI int ecore_x_window_prop_atom_list_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom **plst); +EAPI void ecore_x_window_prop_atom_list_change(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Atom item, int op); +EAPI void ecore_x_window_prop_window_set(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Window *val, unsigned int num); +EAPI int ecore_x_window_prop_window_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Window *val, unsigned int len); +EAPI int ecore_x_window_prop_window_list_get(Ecore_X_Window win, Ecore_X_Atom atom, Ecore_X_Window **plst); + +EAPI Ecore_X_Atom ecore_x_window_prop_any_type(void); +EAPI void ecore_x_window_prop_property_set(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Atom format, int size, void *data, int number); +EAPI int ecore_x_window_prop_property_get(Ecore_X_Window win, Ecore_X_Atom property, Ecore_X_Atom type, int size, unsigned char **data, int *num); +EAPI void ecore_x_window_prop_property_del(Ecore_X_Window win, Ecore_X_Atom property); +EAPI Ecore_X_Atom *ecore_x_window_prop_list(Ecore_X_Window win, int *num_ret); +EAPI void ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom type, const char *str); +EAPI char *ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom type); +EAPI Eina_Bool ecore_x_window_prop_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol); +EAPI Ecore_X_WM_Protocol *ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, int *num_ret); + +EAPI void ecore_x_window_shape_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask); +EAPI void ecore_x_window_shape_window_set(Ecore_X_Window win, Ecore_X_Window shape_win); +EAPI void ecore_x_window_shape_window_set_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y); +EAPI void ecore_x_window_shape_rectangle_set(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_rectangles_set(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num); +EAPI void ecore_x_window_shape_input_rectangle_set(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_input_rectangles_set(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num); +EAPI void ecore_x_window_shape_input_rectangle_add(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_rectangle_subtract(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_input_rectangle_subtract(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_input_window_set_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y); +EAPI void ecore_x_window_shape_input_window_set(Ecore_X_Window win, Ecore_X_Window shape_win); +EAPI void ecore_x_window_shape_window_add(Ecore_X_Window win, Ecore_X_Window shape_win); +EAPI void ecore_x_window_shape_window_add_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y); +EAPI void ecore_x_window_shape_input_window_add_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y); +EAPI void ecore_x_window_shape_rectangle_add(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_input_rectangle_clip(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_window_shape_rectangles_add(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num); +EAPI void ecore_x_window_shape_input_rectangles_add(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num); +EAPI Ecore_X_Rectangle *ecore_x_window_shape_rectangles_get(Ecore_X_Window win, int *num_ret); +EAPI Ecore_X_Rectangle *ecore_x_window_shape_input_rectangles_get(Ecore_X_Window win, int *num_ret); +EAPI void ecore_x_window_shape_events_select(Ecore_X_Window win, Eina_Bool on); +EAPI void ecore_x_window_shape_input_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask); + +EAPI Ecore_X_Pixmap ecore_x_pixmap_new(Ecore_X_Window win, int w, int h, int dep); +EAPI void ecore_x_pixmap_free(Ecore_X_Pixmap pmap); +EAPI void ecore_x_pixmap_paste(Ecore_X_Pixmap pmap, Ecore_X_Drawable dest, Ecore_X_GC gc, int sx, int sy, int w, int h, int dx, int dy); +EAPI void ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, int *x, int *y, int *w, int *h); +EAPI int ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap); + +EAPI Ecore_X_GC ecore_x_gc_new(Ecore_X_Drawable draw, Ecore_X_GC_Value_Mask value_mask, const unsigned int *value_list); +EAPI void ecore_x_gc_free(Ecore_X_GC gc); +EAPI void ecore_x_gc_foreground_set(Ecore_X_GC gc, unsigned long foreground); +EAPI void ecore_x_gc_background_set(Ecore_X_GC gc, unsigned long background); + +EAPI Eina_Bool ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Event_Mask mask, long d0, long d1, long d2, long d3, long d4); +EAPI Eina_Bool ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type, const void *data, int len); +EAPI Eina_Bool ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y); +EAPI Eina_Bool ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b); +EAPI Eina_Bool ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b); +EAPI Eina_Bool ecore_x_mouse_in_send(Ecore_X_Window win, int x, int y); +EAPI Eina_Bool ecore_x_mouse_out_send(Ecore_X_Window win, int x, int y); + +EAPI void ecore_x_drawable_geometry_get(Ecore_X_Drawable d, int *x, int *y, int *w, int *h); +EAPI int ecore_x_drawable_border_width_get(Ecore_X_Drawable d); +EAPI int ecore_x_drawable_depth_get(Ecore_X_Drawable d); +EAPI void ecore_x_drawable_rectangle_fill(Ecore_X_Drawable d, Ecore_X_GC gc, int x, int y, int width, int height); + +EAPI Eina_Bool ecore_x_cursor_color_supported_get(void); +EAPI Ecore_X_Cursor ecore_x_cursor_new(Ecore_X_Window win, int *pixels, int w, int h, int hot_x, int hot_y); +EAPI void ecore_x_cursor_free(Ecore_X_Cursor c); +EAPI Ecore_X_Cursor ecore_x_cursor_shape_get(int shape); +EAPI void ecore_x_cursor_size_set(int size); +EAPI int ecore_x_cursor_size_get(void); + +/* FIXME: these funcs need categorising */ +EAPI Ecore_X_Window *ecore_x_window_root_list(int *num_ret); +EAPI Ecore_X_Window ecore_x_window_root_first_get(void); +EAPI Eina_Bool ecore_x_window_manage(Ecore_X_Window win); +EAPI void ecore_x_window_container_manage(Ecore_X_Window win); +EAPI void ecore_x_window_client_manage(Ecore_X_Window win); +EAPI void ecore_x_window_sniff(Ecore_X_Window win); +EAPI void ecore_x_window_client_sniff(Ecore_X_Window win); + +EAPI Ecore_X_Atom ecore_x_atom_get(const char *name); +EAPI void ecore_x_atoms_get(const char **names, int num, Ecore_X_Atom *atoms); +EAPI char *ecore_x_atom_name_get(Ecore_X_Atom atom); + +EAPI void ecore_x_icccm_init(void); +EAPI void ecore_x_icccm_state_set(Ecore_X_Window win, Ecore_X_Window_State_Hint state); +EAPI Ecore_X_Window_State_Hint ecore_x_icccm_state_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_delete_window_send(Ecore_X_Window win, Ecore_X_Time t); +EAPI void ecore_x_icccm_take_focus_send(Ecore_X_Window win, Ecore_X_Time t); +EAPI void ecore_x_icccm_save_yourself_send(Ecore_X_Window win, Ecore_X_Time t); +EAPI void ecore_x_icccm_move_resize_send(Ecore_X_Window win, int x, int y, int w, int h); +EAPI void ecore_x_icccm_hints_set(Ecore_X_Window win, Eina_Bool accepts_focus, Ecore_X_Window_State_Hint initial_state, Ecore_X_Pixmap icon_pixmap, Ecore_X_Pixmap icon_mask, Ecore_X_Window icon_window, Ecore_X_Window window_group, Eina_Bool is_urgent); +EAPI Eina_Bool ecore_x_icccm_hints_get(Ecore_X_Window win, Eina_Bool *accepts_focus, Ecore_X_Window_State_Hint *initial_state, Ecore_X_Pixmap *icon_pixmap, Ecore_X_Pixmap *icon_mask, Ecore_X_Window *icon_window, Ecore_X_Window *window_group, Eina_Bool *is_urgent); +EAPI void ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win, Eina_Bool request_pos, Ecore_X_Gravity gravity, int min_w, int min_h, int max_w, int max_h, int base_w, int base_h, int step_x, int step_y, double min_aspect, double max_aspect); +EAPI Eina_Bool ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win, Eina_Bool *request_pos, Ecore_X_Gravity *gravity, int *min_w, int *min_h, int *max_w, int *max_h, int *base_w, int *base_h, int *step_x, int *step_y, double *min_aspect, double *max_aspect); +EAPI void ecore_x_icccm_title_set(Ecore_X_Window win, const char *t); +EAPI char *ecore_x_icccm_title_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win, Ecore_X_Atom *protos, int num); +EAPI void ecore_x_icccm_protocol_set(Ecore_X_Window win, Ecore_X_WM_Protocol protocol, Eina_Bool on); +EAPI Eina_Bool ecore_x_icccm_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol); +EAPI void ecore_x_icccm_name_class_set(Ecore_X_Window win, const char *n, const char *c); +EAPI void ecore_x_icccm_name_class_get(Ecore_X_Window win, char **n, char **c); +EAPI char *ecore_x_icccm_client_machine_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_command_set(Ecore_X_Window win, int argc, char **argv); +EAPI void ecore_x_icccm_command_get(Ecore_X_Window win, int *argc, char ***argv); +EAPI char *ecore_x_icccm_icon_name_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_icon_name_set(Ecore_X_Window win, const char *t); +EAPI void ecore_x_icccm_colormap_window_set(Ecore_X_Window win, Ecore_X_Window subwin); +EAPI void ecore_x_icccm_colormap_window_unset(Ecore_X_Window win, Ecore_X_Window subwin); +EAPI void ecore_x_icccm_transient_for_set(Ecore_X_Window win, Ecore_X_Window forwin); +EAPI void ecore_x_icccm_transient_for_unset(Ecore_X_Window win); +EAPI Ecore_X_Window ecore_x_icccm_transient_for_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_window_role_set(Ecore_X_Window win, const char *role); +EAPI char *ecore_x_icccm_window_role_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_client_leader_set(Ecore_X_Window win, Ecore_X_Window l); +EAPI Ecore_X_Window ecore_x_icccm_client_leader_get(Ecore_X_Window win); +EAPI void ecore_x_icccm_iconic_request_send(Ecore_X_Window win, Ecore_X_Window root); + +typedef enum _Ecore_X_MWM_Hint_Func +{ + ECORE_X_MWM_HINT_FUNC_ALL = (1 << 0), + ECORE_X_MWM_HINT_FUNC_RESIZE = (1 << 1), + ECORE_X_MWM_HINT_FUNC_MOVE = (1 << 2), + ECORE_X_MWM_HINT_FUNC_MINIMIZE = (1 << 3), + ECORE_X_MWM_HINT_FUNC_MAXIMIZE = (1 << 4), + ECORE_X_MWM_HINT_FUNC_CLOSE = (1 << 5) +} Ecore_X_MWM_Hint_Func; + +typedef enum _Ecore_X_MWM_Hint_Decor +{ + ECORE_X_MWM_HINT_DECOR_ALL = (1 << 0), + ECORE_X_MWM_HINT_DECOR_BORDER = (1 << 1), + ECORE_X_MWM_HINT_DECOR_RESIZEH = (1 << 2), + ECORE_X_MWM_HINT_DECOR_TITLE = (1 << 3), + ECORE_X_MWM_HINT_DECOR_MENU = (1 << 4), + ECORE_X_MWM_HINT_DECOR_MINIMIZE = (1 << 5), + ECORE_X_MWM_HINT_DECOR_MAXIMIZE = (1 << 6) +} Ecore_X_MWM_Hint_Decor; + +typedef enum _Ecore_X_MWM_Hint_Input +{ + ECORE_X_MWM_HINT_INPUT_MODELESS = 0, + ECORE_X_MWM_HINT_INPUT_PRIMARY_APPLICATION_MODAL = 1, + ECORE_X_MWM_HINT_INPUT_SYSTEM_MODAL = 2, + ECORE_X_MWM_HINT_INPUT_FULL_APPLICATION_MODAL = 3 +} Ecore_X_MWM_Hint_Input; + +EAPI Eina_Bool ecore_x_mwm_hints_get(Ecore_X_Window win, Ecore_X_MWM_Hint_Func *fhint, Ecore_X_MWM_Hint_Decor *dhint, Ecore_X_MWM_Hint_Input *ihint); +EAPI void ecore_x_mwm_borderless_set(Ecore_X_Window win, Eina_Bool borderless); + +/* netwm */ +EAPI void ecore_x_netwm_init(void); +EAPI void ecore_x_netwm_shutdown(void); +EAPI void ecore_x_netwm_wm_identify(Ecore_X_Window root, Ecore_X_Window check, const char *wm_name); +EAPI void ecore_x_netwm_supported_set(Ecore_X_Window root, Ecore_X_Atom *supported, int num); +EAPI Eina_Bool ecore_x_netwm_supported_get(Ecore_X_Window root, Ecore_X_Atom **supported, int *num); +EAPI void ecore_x_netwm_desk_count_set(Ecore_X_Window root, unsigned int n_desks); +EAPI void ecore_x_netwm_desk_roots_set(Ecore_X_Window root, Ecore_X_Window *vroots, unsigned int n_desks); +EAPI void ecore_x_netwm_desk_names_set(Ecore_X_Window root, const char **names, unsigned int n_desks); +EAPI void ecore_x_netwm_desk_size_set(Ecore_X_Window root, unsigned int width, unsigned int height); +EAPI void ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, unsigned int *areas, unsigned int n_desks); +EAPI unsigned int *ecore_x_netwm_desk_workareas_get(Ecore_X_Window root, unsigned int *n_desks); +EAPI void ecore_x_netwm_desk_current_set(Ecore_X_Window root, unsigned int desk); +EAPI void ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, unsigned int *origins, unsigned int n_desks); +EAPI void ecore_x_netwm_desk_layout_set(Ecore_X_Window root, int orientation, int columns, int rows, int starting_corner); +EAPI void ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, Eina_Bool on); +EAPI void ecore_x_netwm_client_list_set(Ecore_X_Window root, Ecore_X_Window *p_clients, unsigned int n_clients); +EAPI void ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, Ecore_X_Window *p_clients, unsigned int n_clients); +EAPI void ecore_x_netwm_client_active_set(Ecore_X_Window root, Ecore_X_Window win); +EAPI void ecore_x_netwm_client_active_request(Ecore_X_Window root, Ecore_X_Window win, int type, Ecore_X_Window current_win); +EAPI void ecore_x_netwm_name_set(Ecore_X_Window win, const char *name); +EAPI int ecore_x_netwm_name_get(Ecore_X_Window win, char **name); +EAPI void ecore_x_netwm_startup_id_set(Ecore_X_Window win, const char *id); +EAPI int ecore_x_netwm_startup_id_get(Ecore_X_Window win, char **id); +EAPI void ecore_x_netwm_visible_name_set(Ecore_X_Window win, const char *name); +EAPI int ecore_x_netwm_visible_name_get(Ecore_X_Window win, char **name); +EAPI void ecore_x_netwm_icon_name_set(Ecore_X_Window win, const char *name); +EAPI int ecore_x_netwm_icon_name_get(Ecore_X_Window win, char **name); +EAPI void ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, const char *name); +EAPI int ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, char **name); +EAPI void ecore_x_netwm_desktop_set(Ecore_X_Window win, unsigned int desk); +EAPI Eina_Bool ecore_x_netwm_desktop_get(Ecore_X_Window win, unsigned int *desk); +EAPI void ecore_x_netwm_strut_set(Ecore_X_Window win, int left, int right, int top, int bottom); +EAPI Eina_Bool ecore_x_netwm_strut_get(Ecore_X_Window win, int *left, int *right, int *top, int *bottom); +EAPI void ecore_x_netwm_strut_partial_set(Ecore_X_Window win, int left, int right, int top, int bottom, int left_start_y, int left_end_y, int right_start_y, int right_end_y, int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x); +EAPI Eina_Bool ecore_x_netwm_strut_partial_get(Ecore_X_Window win, int *left, int *right, int *top, int *bottom, int *left_start_y, int *left_end_y, int *right_start_y, int *right_end_y, int *top_start_x, int *top_end_x, int *bottom_start_x, int *bottom_end_x); + +EAPI void ecore_x_netwm_icons_set(Ecore_X_Window win, Ecore_X_Icon *icon, int num); + +EAPI Eina_Bool ecore_x_netwm_icons_get(Ecore_X_Window win, Ecore_X_Icon **icon, int *num); +EAPI void ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, int x, int y, int width, int height); +EAPI Eina_Bool ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, int *x, int *y, int *width, int *height); +EAPI void ecore_x_netwm_pid_set(Ecore_X_Window win, int pid); +EAPI Eina_Bool ecore_x_netwm_pid_get(Ecore_X_Window win, int *pid); +EAPI void ecore_x_netwm_handled_icons_set(Ecore_X_Window win); +EAPI Eina_Bool ecore_x_netwm_handled_icons_get(Ecore_X_Window win); +EAPI void ecore_x_netwm_user_time_set(Ecore_X_Window win, unsigned int time); +EAPI Eina_Bool ecore_x_netwm_user_time_get(Ecore_X_Window win, unsigned int *time); +EAPI void ecore_x_netwm_window_state_set(Ecore_X_Window win, Ecore_X_Window_State *state, unsigned int num); +EAPI Eina_Bool ecore_x_netwm_window_state_get(Ecore_X_Window win, Ecore_X_Window_State **state, unsigned int *num); +EAPI void ecore_x_netwm_window_type_set(Ecore_X_Window win, Ecore_X_Window_Type type); +EAPI Eina_Bool ecore_x_netwm_window_type_get(Ecore_X_Window win, Ecore_X_Window_Type *type); +EAPI int ecore_x_netwm_window_types_get(Ecore_X_Window win, Ecore_X_Window_Type **types); +EAPI Eina_Bool ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, Ecore_X_Action action); +EAPI void ecore_x_netwm_allowed_action_set(Ecore_X_Window win, Ecore_X_Action *action, unsigned int num); +EAPI Eina_Bool ecore_x_netwm_allowed_action_get(Ecore_X_Window win, Ecore_X_Action **action, unsigned int *num); +EAPI void ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity); +EAPI Eina_Bool ecore_x_netwm_opacity_get(Ecore_X_Window win, unsigned int *opacity); +EAPI void ecore_x_netwm_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb); +EAPI Eina_Bool ecore_x_netwm_frame_size_get(Ecore_X_Window win, int *fl, int *fr, int *ft, int *fb); +EAPI Eina_Bool ecore_x_netwm_sync_counter_get(Ecore_X_Window win, Ecore_X_Sync_Counter *counter); +EAPI void ecore_x_netwm_ping_send(Ecore_X_Window win); +EAPI void ecore_x_netwm_sync_request_send(Ecore_X_Window win, unsigned int serial); +EAPI void ecore_x_netwm_state_request_send(Ecore_X_Window win, Ecore_X_Window root, Ecore_X_Window_State s1, Ecore_X_Window_State s2, Eina_Bool set); +EAPI void ecore_x_netwm_desktop_request_send(Ecore_X_Window win, Ecore_X_Window root, unsigned int desktop); +EAPI void ecore_x_netwm_moveresize_request_send(Ecore_X_Window win, int x, int y, Ecore_X_Netwm_Direction direction, unsigned int button); + +EAPI void ecore_x_e_init(void); +EAPI void ecore_x_e_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb); +EAPI void ecore_x_e_virtual_keyboard_set(Ecore_X_Window win, unsigned int is_keyboard); +EAPI Eina_Bool ecore_x_e_virtual_keyboard_get(Ecore_X_Window win); +EAPI void ecore_x_e_virtual_keyboard_state_set(Ecore_X_Window win, Ecore_X_Virtual_Keyboard_State state); +EAPI Ecore_X_Virtual_Keyboard_State ecore_x_e_virtual_keyboard_state_get(Ecore_X_Window win); +EAPI void ecore_x_e_virtual_keyboard_state_send(Ecore_X_Window win, Ecore_X_Virtual_Keyboard_State state); + +/* Illume functions */ +EAPI void ecore_x_e_illume_zone_set(Ecore_X_Window win, Ecore_X_Window zone); +EAPI Ecore_X_Window ecore_x_e_illume_zone_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_zone_list_set(Ecore_X_Window win, Ecore_X_Window *zones, unsigned int n_zones); +EAPI void ecore_x_e_illume_conformant_set(Ecore_X_Window win, unsigned int is_conformant); +EAPI Eina_Bool ecore_x_e_illume_conformant_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_mode_set(Ecore_X_Window win, Ecore_X_Illume_Mode mode); +EAPI Ecore_X_Illume_Mode ecore_x_e_illume_mode_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_mode_send(Ecore_X_Window win, Ecore_X_Illume_Mode mode); +EAPI void ecore_x_e_illume_focus_back_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_focus_forward_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_focus_home_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_close_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_home_new_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_home_del_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_next_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_prev_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_activate_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_read_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_read_next_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_read_prev_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_up_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_access_action_down_send(Ecore_X_Window win); + +EAPI void ecore_x_e_illume_drag_set(Ecore_X_Window win, unsigned int drag); +EAPI Eina_Bool ecore_x_e_illume_drag_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_drag_locked_set(Ecore_X_Window win, unsigned int is_locked); +EAPI Eina_Bool ecore_x_e_illume_drag_locked_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_drag_start_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_drag_end_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_indicator_geometry_set(Ecore_X_Window win, int x, int y, int w, int h); +EAPI Eina_Bool ecore_x_e_illume_indicator_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h); +EAPI void ecore_x_e_illume_softkey_geometry_set(Ecore_X_Window win, int x, int y, int w, int h); +EAPI Eina_Bool ecore_x_e_illume_softkey_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h); +EAPI void ecore_x_e_illume_keyboard_geometry_set(Ecore_X_Window win, int x, int y, int w, int h); +EAPI Eina_Bool ecore_x_e_illume_keyboard_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h); +EAPI void ecore_x_e_illume_quickpanel_set(Ecore_X_Window win, unsigned int is_quickpanel); +EAPI Eina_Bool ecore_x_e_illume_quickpanel_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_state_set(Ecore_X_Window win, Ecore_X_Illume_Quickpanel_State state); +EAPI Ecore_X_Illume_Quickpanel_State ecore_x_e_illume_quickpanel_state_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_state_send(Ecore_X_Window win, Ecore_X_Illume_Quickpanel_State state); +EAPI void ecore_x_e_illume_quickpanel_state_toggle(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_priority_major_set(Ecore_X_Window win, unsigned int priority); +EAPI int ecore_x_e_illume_quickpanel_priority_major_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_priority_minor_set(Ecore_X_Window win, unsigned int priority); +EAPI int ecore_x_e_illume_quickpanel_priority_minor_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_zone_set(Ecore_X_Window win, unsigned int zone); +EAPI int ecore_x_e_illume_quickpanel_zone_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_zone_request_send(Ecore_X_Window win); +EAPI void ecore_x_e_illume_quickpanel_position_update_send(Ecore_X_Window win); + +EAPI void ecore_x_e_illume_clipboard_state_set(Ecore_X_Window win, Ecore_X_Illume_Clipboard_State state); + +EAPI Ecore_X_Illume_Clipboard_State ecore_x_e_illume_clipboard_state_get(Ecore_X_Window win); + +EAPI void ecore_x_e_illume_clipboard_geometry_set(Ecore_X_Window win, int x, int y, int w, int h); +EAPI Eina_Bool ecore_x_e_illume_clipboard_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h); +EAPI void ecore_x_e_comp_sync_counter_set(Ecore_X_Window win, Ecore_X_Sync_Counter counter); +EAPI Ecore_X_Sync_Counter ecore_x_e_comp_sync_counter_get(Ecore_X_Window win); +EAPI void ecore_x_e_comp_sync_draw_done_send(Ecore_X_Window root, Ecore_X_Window win); +EAPI void ecore_x_e_comp_sync_draw_size_done_send(Ecore_X_Window root, Ecore_X_Window win, int w, int h); +EAPI void ecore_x_e_comp_sync_supported_set(Ecore_X_Window root, Eina_Bool enabled); +EAPI Eina_Bool ecore_x_e_comp_sync_supported_get(Ecore_X_Window root); +EAPI void ecore_x_e_comp_sync_begin_send(Ecore_X_Window win); +EAPI void ecore_x_e_comp_sync_end_send(Ecore_X_Window win); +EAPI void ecore_x_e_comp_sync_cancel_send(Ecore_X_Window win); + +EAPI void ecore_x_e_comp_flush_send(Ecore_X_Window win); +EAPI void ecore_x_e_comp_dump_send(Ecore_X_Window win); +EAPI void ecore_x_e_comp_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pixmap); +EAPI Ecore_X_Pixmap ecore_x_e_comp_pixmap_get(Ecore_X_Window win); + +EAPI char *ecore_x_e_window_profile_get(Ecore_X_Window win); +EAPI void ecore_x_e_window_profile_set(Ecore_X_Window win, const char *profile); +EAPI void ecore_x_e_window_profile_list_set(Ecore_X_Window win, const char **profiles, unsigned int num_profiles); +EAPI Eina_Bool ecore_x_e_window_profile_list_get(Ecore_X_Window win, const char ***profiles, int *ret_num); + +EAPI Ecore_X_Sync_Alarm ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter); +EAPI Eina_Bool ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm); +EAPI Eina_Bool ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, unsigned int *val); +EAPI Ecore_X_Sync_Counter ecore_x_sync_counter_new(int val); +EAPI void ecore_x_sync_counter_free(Ecore_X_Sync_Counter counter); +EAPI void ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, int by); +EAPI void ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, int val); + +EAPI void ecore_x_sync_counter_set(Ecore_X_Sync_Counter counter, int val); +EAPI void ecore_x_sync_counter_2_set(Ecore_X_Sync_Counter counter, int val_hi, unsigned int val_lo); +EAPI Eina_Bool ecore_x_sync_counter_2_query(Ecore_X_Sync_Counter counter, int *val_hi, unsigned int *val_lo); + +EAPI int ecore_x_xinerama_screen_count_get(void); +EAPI Eina_Bool ecore_x_xinerama_screen_geometry_get(int screen, int *x, int *y, int *w, int *h); + +EAPI Eina_Bool ecore_x_screensaver_event_available_get(void); +EAPI int ecore_x_screensaver_idle_time_get(void); +EAPI void ecore_x_screensaver_set(int timeout, int interval, int prefer_blanking, int allow_exposures); +EAPI void ecore_x_screensaver_timeout_set(int timeout); +EAPI int ecore_x_screensaver_timeout_get(void); +EAPI void ecore_x_screensaver_blank_set(int timeout); +EAPI int ecore_x_screensaver_blank_get(void); +EAPI void ecore_x_screensaver_expose_set(int timeout); +EAPI int ecore_x_screensaver_expose_get(void); +EAPI void ecore_x_screensaver_interval_set(int timeout); +EAPI int ecore_x_screensaver_interval_get(void); +EAPI void ecore_x_screensaver_event_listen_set(Eina_Bool on); +EAPI Eina_Bool ecore_x_screensaver_custom_blanking_enable(void); /** @since 1.7 */ +EAPI Eina_Bool ecore_x_screensaver_custom_blanking_disable(void); /** @since 1.7 */ + +/* FIXME: these funcs need categorising */ + +typedef struct _Ecore_X_Window_Attributes +{ + Ecore_X_Window root; + int x, y, w, h; + int border; + int depth; + Eina_Bool visible : 1; + Eina_Bool viewable : 1; + Eina_Bool override : 1; + Eina_Bool input_only : 1; + Eina_Bool save_under : 1; + struct + { + Ecore_X_Event_Mask mine; + Ecore_X_Event_Mask all; + Ecore_X_Event_Mask no_propagate; + } event_mask; + Ecore_X_Gravity window_gravity; + Ecore_X_Gravity pixel_gravity; + Ecore_X_Colormap colormap; + Ecore_X_Visual visual; + /* FIXME: missing + * int map_installed; + * Screen *screen; + */ +} Ecore_X_Window_Attributes; + +EAPI Eina_Bool ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret); +EAPI void ecore_x_window_save_set_add(Ecore_X_Window win); +EAPI void ecore_x_window_save_set_del(Ecore_X_Window win); +EAPI Ecore_X_Window *ecore_x_window_children_get(Ecore_X_Window win, int *num); + +EAPI Eina_Bool ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold); +EAPI Eina_Bool ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold); +EAPI Eina_Bool ecore_x_pointer_mapping_set(unsigned char *map, int nmap); +EAPI Eina_Bool ecore_x_pointer_mapping_get(unsigned char *map, int nmap); +EAPI Eina_Bool ecore_x_pointer_grab(Ecore_X_Window win); +EAPI Eina_Bool ecore_x_pointer_confine_grab(Ecore_X_Window win); +EAPI void ecore_x_pointer_ungrab(void); +EAPI Eina_Bool ecore_x_pointer_warp(Ecore_X_Window win, int x, int y); +EAPI Eina_Bool ecore_x_keyboard_grab(Ecore_X_Window win); +EAPI void ecore_x_keyboard_ungrab(void); +EAPI void ecore_x_grab(void); +EAPI void ecore_x_ungrab(void); +EAPI void ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, int event_type, void *event), void *data); +EAPI void ecore_x_window_button_grab(Ecore_X_Window win, int button, Ecore_X_Event_Mask event_mask, int mod, int any_mod); +EAPI void ecore_x_window_button_ungrab(Ecore_X_Window win, int button, int mod, int any_mod); +EAPI void ecore_x_window_key_grab(Ecore_X_Window win, const char *key, int mod, int any_mod); +EAPI void ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key, int mod, int any_mod); + +EAPI void ecore_x_focus_reset(void); +EAPI void ecore_x_events_allow_all(void); +EAPI void ecore_x_pointer_last_xy_get(int *x, int *y); +EAPI void ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y); + +/* ecore_x_region.c */ +EAPI Ecore_X_XRegion *ecore_x_xregion_new(void); +EAPI void ecore_x_xregion_free(Ecore_X_XRegion *region); +EAPI Eina_Bool ecore_x_xregion_set(Ecore_X_XRegion *region, Ecore_X_GC gc); +EAPI void ecore_x_xregion_translate(Ecore_X_XRegion *region, int x, int y); +EAPI Eina_Bool ecore_x_xregion_intersect(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2); +EAPI Eina_Bool ecore_x_xregion_union(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2); +EAPI Eina_Bool ecore_x_xregion_union_rect(Ecore_X_XRegion *dst, Ecore_X_XRegion *src, Ecore_X_Rectangle *rect); +EAPI Eina_Bool ecore_x_xregion_subtract(Ecore_X_XRegion *dst, Ecore_X_XRegion *r1, Ecore_X_XRegion *r2); +EAPI Eina_Bool ecore_x_xregion_is_empty(Ecore_X_XRegion *region); +EAPI Eina_Bool ecore_x_xregion_is_equal(Ecore_X_XRegion *r1, Ecore_X_XRegion *r2); +EAPI Eina_Bool ecore_x_xregion_point_contain(Ecore_X_XRegion *region, int x, int y); +EAPI Eina_Bool ecore_x_xregion_rect_contain(Ecore_X_XRegion *region, Ecore_X_Rectangle *rect); + +/* ecore_x_randr.c */ + +/* 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) must 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 +{ + 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 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_Orientation ecore_x_randr_screen_primary_output_orientation_get(Ecore_X_Window root); +EAPI Eina_Bool ecore_x_randr_screen_primary_output_orientation_set(Ecore_X_Window root, 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 *num); + +/** + * @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); +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 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 ecore_x_randr_mode_info_add(Ecore_X_Window root, Ecore_X_Randr_Mode_Info *mode_info); +EAPI void ecore_x_randr_mode_del(Ecore_X_Randr_Mode mode); +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_window_outputs_get(Ecore_X_Window window, 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_window_crtcs_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 Eina_Bool ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output, Ecore_X_Randr_Mode mode); +EAPI void ecore_x_randr_output_mode_del(Ecore_X_Randr_Output output, Ecore_X_Randr_Mode mode); +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_12_edid.c */ + +/** + * @brief Validates the header from raw EDID data. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if the header is valid, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_has_valid_header(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Checks whether a display's EDID has a valid checksum. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if the checksum is valid, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_info_has_valid_checksum(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the encoded version from raw EDID data. + * + * The return value has the minor version in the lowest 8 bits, and the major + * version in all the rest of the bits. i.e. + * + * minor = (version & 0x000000ff); + * major = (version & 0xffffff00) >> 8; + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded major and minor version encasuplated an int. + */ +EAPI int ecore_x_randr_edid_version_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the encoded manufacturer from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded manufacturer identifier. + */ +EAPI char *ecore_x_randr_edid_manufacturer_name_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the encoded name from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded manufacturer identifier. + */ +EAPI char *ecore_x_randr_edid_display_name_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the encoded ASCII from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded ASCII display identifier. + */ +EAPI char *ecore_x_randr_edid_display_ascii_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the encoded serial identifier from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded serial identifier. + */ +EAPI char *ecore_x_randr_edid_display_serial_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the encoded model number from raw EDID data. + * + * The manufacturer ID table is necessary for a useful description. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded model number. + */ +EAPI int ecore_x_randr_edid_model_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the manufacturer serial number from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded serial manufacturer serial number. + */ +EAPI int ecore_x_randr_edid_manufacturer_serial_number_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the manufacturer model number from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The manufacturer's model number. + */ +EAPI int ecore_x_randr_edid_manufacturer_model_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Looks up the DPMS support from raw EDID data. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if DPMS is supported in some way, @c EINA_FALSE + * otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_available_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Looks up the DPMS Standby support from raw EDID data. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if DPMS Standby is supported, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_standby_available_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Looks up the DPMS Suspend support from raw EDID data. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if DPMS Suspend is supported, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_suspend_available_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Looks up the DPMS Off support from raw EDID data. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if DPMS Off is supported, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_off_available_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the preferred aspect ratio from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The preferred aspect ratio. + */ +EAPI Ecore_X_Randr_Edid_Aspect_Ratio ecore_x_randr_edid_display_aspect_ratio_preferred_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the supported aspect ratios from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The supported aspect ratios. + */ +EAPI Ecore_X_Randr_Edid_Aspect_Ratio ecore_x_randr_edid_display_aspect_ratios_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the supported colorschemes from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The supported colorschemes. + */ +EAPI Ecore_X_Randr_Edid_Display_Colorscheme ecore_x_randr_edid_display_colorscheme_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the display type from raw EDID data. + * + * @param edid The edid structure. + * @param edid_length Length of the edid structure. + * @return @c EINA_TRUE, if the display is a digital one, @c EINA_FALSE + * otherwise. + */ +EAPI Eina_Bool ecore_x_randr_edid_display_type_digital_get(unsigned char *edid, unsigned long edid_length); + +/** + * @brief Get the display interface type from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The interface type. + */ +EAPI Ecore_X_Randr_Edid_Display_Interface_Type ecore_x_randr_edid_display_interface_type_get(unsigned char *edid, unsigned long edid_length); + +/* ecore_x_randr_12.c */ + +EAPI Eina_Bool ecore_x_randr_output_backlight_available(void); +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); +/* WTF - these dont exist in ecore-x!!!! +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; + +/* XFixes Extension Support */ +typedef Ecore_X_ID Ecore_X_Region; + +typedef enum _Ecore_X_Region_Type +{ + ECORE_X_REGION_BOUNDING, + ECORE_X_REGION_CLIP +} Ecore_X_Region_Type; + +EAPI Ecore_X_Region ecore_x_region_new(Ecore_X_Rectangle *rects, int num); +EAPI Ecore_X_Region ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap); +EAPI Ecore_X_Region ecore_x_region_new_from_window(Ecore_X_Window win, Ecore_X_Region_Type type); +EAPI Ecore_X_Region ecore_x_region_new_from_gc(Ecore_X_GC gc); +EAPI Ecore_X_Region ecore_x_region_new_from_picture(Ecore_X_Picture picture); +EAPI void ecore_x_region_free(Ecore_X_Region region); +EAPI void ecore_x_region_set(Ecore_X_Region region, Ecore_X_Rectangle *rects, int num); +EAPI void ecore_x_region_copy(Ecore_X_Region dest, Ecore_X_Region source); +EAPI void ecore_x_region_combine(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2); +EAPI void ecore_x_region_intersect(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2); +EAPI void ecore_x_region_subtract(Ecore_X_Region dest, Ecore_X_Region source1, Ecore_X_Region source2); +EAPI void ecore_x_region_invert(Ecore_X_Region dest, Ecore_X_Rectangle *bounds, Ecore_X_Region source); +EAPI void ecore_x_region_translate(Ecore_X_Region region, int dx, int dy); +EAPI void ecore_x_region_extents(Ecore_X_Region dest, Ecore_X_Region source); +EAPI Ecore_X_Rectangle *ecore_x_region_fetch(Ecore_X_Region region, int *num, Ecore_X_Rectangle *bounds); +EAPI void ecore_x_region_expand(Ecore_X_Region dest, Ecore_X_Region source, unsigned int left, unsigned int right, unsigned int top, unsigned int bottom); +EAPI void ecore_x_region_gc_clip_set(Ecore_X_Region region, Ecore_X_GC gc, int x_origin, int y_origin); +EAPI void ecore_x_region_window_shape_set(Ecore_X_Region region, Ecore_X_Window win, Ecore_X_Shape_Type type, int x_offset, int y_offset); +EAPI void ecore_x_region_picture_clip_set(Ecore_X_Region region, Ecore_X_Picture picture, int x_origin, int y_origin); + +/** + * xfixes selection notification request. + * + * This lets you choose which selections you want to get notifications for. + * @param selection The selection atom. + * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise. + * @since 1.1.0 + */ +EAPI Eina_Bool ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection); + +/* XComposite Extension Support */ +EAPI Eina_Bool ecore_x_composite_query(void); +EAPI void ecore_x_composite_redirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type); +EAPI void ecore_x_composite_redirect_subwindows(Ecore_X_Window win, Ecore_X_Composite_Update_Type type); +EAPI void ecore_x_composite_unredirect_window(Ecore_X_Window win, Ecore_X_Composite_Update_Type type); +EAPI void ecore_x_composite_unredirect_subwindows(Ecore_X_Window win, Ecore_X_Composite_Update_Type type); +EAPI Ecore_X_Pixmap ecore_x_composite_name_window_pixmap_get(Ecore_X_Window win); +EAPI void ecore_x_composite_window_events_disable(Ecore_X_Window win); +EAPI void ecore_x_composite_window_events_enable(Ecore_X_Window win); +EAPI Ecore_X_Window ecore_x_composite_render_window_enable(Ecore_X_Window root); +EAPI void ecore_x_composite_render_window_disable(Ecore_X_Window root); + +/* XDamage Extension Support */ +typedef Ecore_X_ID Ecore_X_Damage; + +typedef enum _Ecore_X_Damage_Report_Level +{ + ECORE_X_DAMAGE_REPORT_RAW_RECTANGLES, + ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES, + ECORE_X_DAMAGE_REPORT_BOUNDING_BOX, + ECORE_X_DAMAGE_REPORT_NON_EMPTY +} Ecore_X_Damage_Report_Level; + +struct _Ecore_X_Event_Damage +{ + Ecore_X_Damage_Report_Level level; + Ecore_X_Drawable drawable; + Ecore_X_Damage damage; + int more; + Ecore_X_Time time; + Ecore_X_Rectangle area; + Ecore_X_Rectangle geometry; +}; + +typedef struct _Ecore_X_Event_Damage Ecore_X_Event_Damage; + +struct _Ecore_X_Event_Xkb +{ + int group; +}; +typedef struct _Ecore_X_Event_Xkb Ecore_X_Event_Xkb; /** @since 1.7 */ + +EAPI Eina_Bool ecore_x_damage_query(void); +EAPI Ecore_X_Damage ecore_x_damage_new(Ecore_X_Drawable d, Ecore_X_Damage_Report_Level level); +EAPI void ecore_x_damage_free(Ecore_X_Damage damage); +EAPI void ecore_x_damage_subtract(Ecore_X_Damage damage, Ecore_X_Region repair, Ecore_X_Region parts); + +EAPI Eina_Bool ecore_x_screen_is_composited(int screen); +EAPI void ecore_x_screen_is_composited_set(int screen, Ecore_X_Window win); + +EAPI Eina_Bool ecore_x_dpms_query(void); +EAPI Eina_Bool ecore_x_dpms_capable_get(void); +EAPI Eina_Bool ecore_x_dpms_enabled_get(void); +EAPI void ecore_x_dpms_enabled_set(int enabled); +EAPI void ecore_x_dpms_timeouts_get(unsigned int *standby, unsigned int *suspend, unsigned int *off); +EAPI Eina_Bool ecore_x_dpms_timeouts_set(unsigned int standby, unsigned int suspend, unsigned int off); +EAPI unsigned int ecore_x_dpms_timeout_standby_get(void); +EAPI unsigned int ecore_x_dpms_timeout_suspend_get(void); +EAPI unsigned int ecore_x_dpms_timeout_off_get(void); +EAPI void ecore_x_dpms_timeout_standby_set(unsigned int new_timeout); +EAPI void ecore_x_dpms_timeout_suspend_set(unsigned int new_timeout); +EAPI void ecore_x_dpms_timeout_off_set(unsigned int new_timeout); + +EAPI Eina_Bool ecore_x_test_fake_key_down(const char *key); +EAPI Eina_Bool ecore_x_test_fake_key_up(const char *key); +EAPI Eina_Bool ecore_x_test_fake_key_press(const char *key); +EAPI const char *ecore_x_keysym_string_get(int keysym); + +/** + * Given a keyname, return the keycode representing that key + * @param keyname The key from which to get the keycode. + * @return The keycode of the key. + * + * @since 1.2.0 + */ +EAPI int ecore_x_keysym_keycode_get(const char *keyname); + +typedef struct _Ecore_X_Image Ecore_X_Image; + +EAPI Ecore_X_Image *ecore_x_image_new(int w, int h, Ecore_X_Visual vis, int depth); +EAPI void ecore_x_image_free(Ecore_X_Image *im); +EAPI Eina_Bool ecore_x_image_get(Ecore_X_Image *im, Ecore_X_Drawable draw, int x, int y, int sx, int sy, int w, int h); +EAPI void ecore_x_image_put(Ecore_X_Image *im, Ecore_X_Drawable draw, Ecore_X_GC gc, int x, int y, int sx, int sy, int w, int h); +EAPI void *ecore_x_image_data_get(Ecore_X_Image *im, int *bpl, int *rows, int *bpp); +EAPI Eina_Bool ecore_x_image_is_argb32_get(Ecore_X_Image *im); + +EAPI Eina_Bool ecore_x_image_to_argb_convert(void *src, int sbpp, int sbpl, Ecore_X_Colormap c, Ecore_X_Visual v, int x, int y, int w, int h, unsigned int *dst, int dbpl, int dx, int dy); + +EAPI Eina_Bool ecore_x_input_multi_select(Ecore_X_Window win); +EAPI Eina_Bool ecore_x_input_raw_select(Ecore_X_Window win); /**< @since 1.8 */ + +EAPI Eina_Bool ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win); + +typedef enum _Ecore_X_Gesture_Event_Mask +{ + ECORE_X_GESTURE_EVENT_MASK_NONE = 0L, + ECORE_X_GESTURE_EVENT_MASK_FLICK = (1L << 0), + ECORE_X_GESTURE_EVENT_MASK_PAN = (1L << 1), + ECORE_X_GESTURE_EVENT_MASK_PINCHROTATION = (1L << 2), + ECORE_X_GESTURE_EVENT_MASK_TAP = (1L << 3), + ECORE_X_GESTURE_EVENT_MASK_TAPNHOLD = (1L << 4), + ECORE_X_GESTURE_EVENT_MASK_HOLD = (1L << 5), + ECORE_X_GESTURE_EVENT_MASK_GROUP = (1L << 6) +} Ecore_X_Gesture_Event_Mask; + +typedef enum _Ecore_X_Gesture_Event_Type +{ + ECORE_X_GESTURE_EVENT_FLICK, + ECORE_X_GESTURE_EVENT_PAN, + ECORE_X_GESTURE_EVENT_PINCHROTATION, + ECORE_X_GESTURE_EVENT_TAP, + ECORE_X_GESTURE_EVENT_TAPNHOLD, + ECORE_X_GESTURE_EVENT_HOLD, + ECORE_X_GESTURE_EVENT_GROUP +} Ecore_X_Gesture_Event_Type; + +typedef enum _Ecore_X_Gesture_Event_Subtype +{ + ECORE_X_GESTURE_END, + ECORE_X_GESTURE_BEGIN, + ECORE_X_GESTURE_UPDATE, + ECORE_X_GESTURE_DONE +} Ecore_X_Gesture_Event_Subtype; + +typedef enum _Ecore_X_Gesture_Group_Subtype +{ + ECORE_X_GESTURE_GROUP_REMOVED, + ECORE_X_GESTURE_GROUP_ADDED, + ECORE_X_GESTURE_GROUP_CURRENT +} Ecore_X_Gesture_Group_Subtype; + +typedef enum _Ecore_X_Gesture_Direction +{ + ECORE_X_GESTURE_NORTHWARD, + ECORE_X_GESTURE_NORTHEASTWARD, + ECORE_X_GESTURE_EASTWARD, + ECORE_X_GESTURE_SOUTHEASTWARD, + ECORE_X_GESTURE_SOUTHWARD, + ECORE_X_GESTURE_SOUTHWESTWARD, + ECORE_X_GESTURE_WESTWARD, + ECORE_X_GESTURE_NORTHWESTWARD +} Ecore_X_Gesture_Direction; + +struct _Ecore_X_Event_Gesture_Notify_Flick +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Event_Subtype subtype; + int num_fingers; + int distance; + Ecore_X_Time duration; + Ecore_X_Gesture_Direction direction; + double angle; +}; + +struct _Ecore_X_Event_Gesture_Notify_Pan +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Event_Subtype subtype; + int num_fingers; + int dx; + int dy; + int distance; + Ecore_X_Time duration; + Ecore_X_Gesture_Direction direction; +}; + +struct _Ecore_X_Event_Gesture_Notify_PinchRotation +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Event_Subtype subtype; + int num_fingers; + int distance; + int cx; + int cy; + double zoom; + double angle; +}; + +struct _Ecore_X_Event_Gesture_Notify_Tap +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Event_Subtype subtype; + int num_fingers; + int cx; + int cy; + int tap_repeat; + Ecore_X_Time interval; +}; + +struct _Ecore_X_Event_Gesture_Notify_TapNHold +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Event_Subtype subtype; + int num_fingers; + int cx; + int cy; + Ecore_X_Time interval; + Ecore_X_Time hold_time; +}; + +struct _Ecore_X_Event_Gesture_Notify_Hold +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Event_Subtype subtype; + int num_fingers; + int cx; + int cy; + Ecore_X_Time hold_time; +}; + +struct _Ecore_X_Event_Gesture_Notify_Group +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Gesture_Group_Subtype subtype; + int num_groups; + int group_id; +}; + +EAPI Eina_Bool ecore_x_gesture_supported(void); + +EAPI Eina_Bool ecore_x_gesture_events_select(Ecore_X_Window win, Ecore_X_Gesture_Event_Mask mask); + +EAPI Ecore_X_Gesture_Event_Mask ecore_x_gesture_events_selected_get(Ecore_X_Window win); + +EAPI Eina_Bool ecore_x_gesture_event_grab(Ecore_X_Window win, Ecore_X_Gesture_Event_Type type, int num_fingers); + +EAPI Eina_Bool ecore_x_gesture_event_ungrab(Ecore_X_Window win, Ecore_X_Gesture_Event_Type type, int num_fingers); + +EAPI void ecore_x_e_illume_indicator_state_set(Ecore_X_Window win, Ecore_X_Illume_Indicator_State state); +EAPI Ecore_X_Illume_Indicator_State ecore_x_e_illume_indicator_state_get(Ecore_X_Window win); +EAPI void ecore_x_e_illume_indicator_state_send(Ecore_X_Window win, Ecore_X_Illume_Indicator_State state); + +EAPI void ecore_x_e_illume_indicator_opacity_set(Ecore_X_Window win, Ecore_X_Illume_Indicator_Opacity_Mode mode); + +EAPI Ecore_X_Illume_Indicator_Opacity_Mode ecore_x_e_illume_indicator_opacity_get(Ecore_X_Window win); + +EAPI void ecore_x_e_illume_indicator_opacity_send(Ecore_X_Window win, Ecore_X_Illume_Indicator_Opacity_Mode mode); + +EAPI void +ecore_x_e_illume_window_state_set(Ecore_X_Window win, + Ecore_X_Illume_Window_State state); + +EAPI Ecore_X_Illume_Window_State ecore_x_e_illume_window_state_get(Ecore_X_Window win); +EAPI void ecore_x_xkb_select_group(int group); /* @since 1.7 */ + +#ifdef __cplusplus +} +#endif // ifdef __cplusplus + +#include <Ecore_X_Atoms.h> +#include <Ecore_X_Cursor.h> + +#endif // ifndef _ECORE_X_H diff --git a/src/lib/ecore_x/Ecore_X_Atoms.h b/src/lib/ecore_x/Ecore_X_Atoms.h new file mode 100644 index 0000000000..ca6351d839 --- /dev/null +++ b/src/lib/ecore_x/Ecore_X_Atoms.h @@ -0,0 +1,292 @@ +#ifndef _ECORE_X_ATOMS_H +#define _ECORE_X_ATOMS_H + +/** + * @file + * @brief Ecore X atoms + */ + +/* generic atoms */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_ATOM; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_CARDINAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_FILE_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_STRING; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_TEXT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WINDOW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_PIXMAP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_VISUALID; + +/* dnd atoms */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_XDND; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_XDND; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_AWARE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ENTER; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_TYPE_LIST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_POSITION; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_COPY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_MOVE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_PRIVATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_ASK; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LIST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LINK; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_DESCRIPTION; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_PROXY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_STATUS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_LEAVE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_DROP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_XDND_FINISHED; + +/* dnd atoms that need to be exposed to the application interface */ +EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_COPY; +EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_MOVE; +EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_LINK; +EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_ASK; +EAPI extern Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE; + +/* old E atom */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE; + +/* old Gnome atom */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER; + +/* ICCCM: client properties */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_ICON_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_NORMAL_HINTS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_SIZE_HINTS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_HINTS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CLASS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_TRANSIENT_FOR; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_PROTOCOLS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_WINDOWS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_COMMAND; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_MACHINE; + +/* ICCCM: window manager properties */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_ICON_SIZE; + +/* ICCCM: WM_STATEproperty */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CHANGE_STATE; + +/* ICCCM: WM_PROTOCOLS properties */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_TAKE_FOCUS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_SAVE_YOURSELF; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_DELETE_WINDOW; + +/* ICCCM: WM_COLORMAP properties */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_NOTIFY; + +/* ICCCM: session management properties */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SM_CLIENT_ID; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_LEADER; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_WM_WINDOW_ROLE; + +/* Motif WM atom */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_MOTIF_WM_HINTS; + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTED; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST_STACKING; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_GEOMETRY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_VIEWPORT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CURRENT_DESKTOP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_NAMES; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_ACTIVE_WINDOW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WORKAREA; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_VIRTUAL_ROOTS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_LAYOUT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_SHOWING_DESKTOP; + +/* pager */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_CLOSE_WINDOW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_MOVERESIZE_WINDOW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_MOVERESIZE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_RESTACK_WINDOW; + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_DESKTOP; + +/* window type */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND; + +/* state */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MODAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_STICKY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SHADED; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_HIDDEN; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_ABOVE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_BELOW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION; + +/* allowed actions */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MOVE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_RESIZE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_SHADE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_STICK; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CLOSE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_ABOVE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_BELOW; + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT_PARTIAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_GEOMETRY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_PID; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_HANDLED_ICONS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_USER_TIME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_ID; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_PING; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_OPACITY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADOW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_PRIMARY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_SECONDARY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD; + +/* currently E specific virtual keyboard extension, aim to submit to netwm spec + * later */ + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME; + +/* Illume specific atoms */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ZONE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ZONE_LIST; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CONFORMANT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_SINGLE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_BACK; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_HOME; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_HOME_NEW; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_HOME_DEL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLOSE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_START; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_END; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_ON; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_AVAILABLE_ANGLE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_WINDOW_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN; + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_COUNTER; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_BEGIN; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_END; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_CANCEL; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_FLUSH; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_DUMP; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_COMP_PIXMAP; + +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIDEO_PARENT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_VIDEO_POSITION; + +/* currently elementary and E specific extension */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_PROFILE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_PROFILE_LIST; + +/* for sliding window */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_STATE; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_GEOMETRY; + +/* for SDB(Samsung Debug Bridge) */ +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SDB_SERVER_CONNECT; +EAPI extern Ecore_X_Atom ECORE_X_ATOM_SDB_SERVER_DISCONNECT; +#endif /* _ECORE_X_ATOMS_H */ diff --git a/src/lib/ecore_x/Ecore_X_Cursor.h b/src/lib/ecore_x/Ecore_X_Cursor.h new file mode 100644 index 0000000000..807541e596 --- /dev/null +++ b/src/lib/ecore_x/Ecore_X_Cursor.h @@ -0,0 +1,87 @@ +#ifndef _ECORE_X_CURSOR_H +#define _ECORE_X_CURSOR_H + +/** + * @file + * @brief Defines the various cursor types for the X Windows system. + */ + +#define ECORE_X_CURSOR_X 0 +#define ECORE_X_CURSOR_ARROW 2 +#define ECORE_X_CURSOR_BASED_ARROW_DOWN 4 +#define ECORE_X_CURSOR_UP 6 +#define ECORE_X_CURSOR_BOAT 8 +#define ECORE_X_CURSOR_BOGOSITY 10 +#define ECORE_X_CURSOR_BOTTOM_LEFT_CORNER 12 +#define ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER 14 +#define ECORE_X_CURSOR_BOTTOM_SIDE 16 +#define ECORE_X_CURSOR_BOTTOM_TEE 18 +#define ECORE_X_CURSOR_BOX_SPIRAL 20 +#define ECORE_X_CURSOR_CENTER_PTR 22 +#define ECORE_X_CURSOR_CIRCLE 24 +#define ECORE_X_CURSOR_CLOCK 26 +#define ECORE_X_CURSOR_COFFEE_MUG 28 +#define ECORE_X_CURSOR_CROSS 30 +#define ECORE_X_CURSOR_CROSS_REVERSE 32 +#define ECORE_X_CURSOR_CROSSHAIR 34 +#define ECORE_X_CURSOR_DIAMOND_CROSS 36 +#define ECORE_X_CURSOR_DOT 38 +#define ECORE_X_CURSOR_DOT_BOX_MASK 40 +#define ECORE_X_CURSOR_DOUBLE_ARROW 42 +#define ECORE_X_CURSOR_DRAFT_LARGE 44 +#define ECORE_X_CURSOR_DRAFT_SMALL 46 +#define ECORE_X_CURSOR_DRAPED_BOX 48 +#define ECORE_X_CURSOR_EXCHANGE 50 +#define ECORE_X_CURSOR_FLEUR 52 +#define ECORE_X_CURSOR_GOBBLER 54 +#define ECORE_X_CURSOR_GUMBY 56 +#define ECORE_X_CURSOR_HAND1 58 +#define ECORE_X_CURSOR_HAND2 60 +#define ECORE_X_CURSOR_HEART 62 +#define ECORE_X_CURSOR_ICON 64 +#define ECORE_X_CURSOR_IRON_CROSS 66 +#define ECORE_X_CURSOR_LEFT_PTR 68 +#define ECORE_X_CURSOR_LEFT_SIDE 70 +#define ECORE_X_CURSOR_LEFT_TEE 72 +#define ECORE_X_CURSOR_LEFTBUTTON 74 +#define ECORE_X_CURSOR_LL_ANGLE 76 +#define ECORE_X_CURSOR_LR_ANGLE 78 +#define ECORE_X_CURSOR_MAN 80 +#define ECORE_X_CURSOR_MIDDLEBUTTON 82 +#define ECORE_X_CURSOR_MOUSE 84 +#define ECORE_X_CURSOR_PENCIL 86 +#define ECORE_X_CURSOR_PIRATE 88 +#define ECORE_X_CURSOR_PLUS 90 +#define ECORE_X_CURSOR_QUESTION_ARROW 92 +#define ECORE_X_CURSOR_RIGHT_PTR 94 +#define ECORE_X_CURSOR_RIGHT_SIDE 96 +#define ECORE_X_CURSOR_RIGHT_TEE 98 +#define ECORE_X_CURSOR_RIGHTBUTTON 100 +#define ECORE_X_CURSOR_RTL_LOGO 102 +#define ECORE_X_CURSOR_SAILBOAT 104 +#define ECORE_X_CURSOR_SB_DOWN_ARROW 106 +#define ECORE_X_CURSOR_SB_H_DOUBLE_ARROW 108 +#define ECORE_X_CURSOR_SB_LEFT_ARROW 110 +#define ECORE_X_CURSOR_SB_RIGHT_ARROW 112 +#define ECORE_X_CURSOR_SB_UP_ARROW 114 +#define ECORE_X_CURSOR_SB_V_DOUBLE_ARROW 116 +#define ECORE_X_CURSOR_SHUTTLE 118 +#define ECORE_X_CURSOR_SIZING 120 +#define ECORE_X_CURSOR_SPIDER 122 +#define ECORE_X_CURSOR_SPRAYCAN 124 +#define ECORE_X_CURSOR_STAR 126 +#define ECORE_X_CURSOR_TARGET 128 +#define ECORE_X_CURSOR_TCROSS 130 +#define ECORE_X_CURSOR_TOP_LEFT_ARROW 132 +#define ECORE_X_CURSOR_TOP_LEFT_CORNER 134 +#define ECORE_X_CURSOR_TOP_RIGHT_CORNER 136 +#define ECORE_X_CURSOR_TOP_SIDE 138 +#define ECORE_X_CURSOR_TOP_TEE 140 +#define ECORE_X_CURSOR_TREK 142 +#define ECORE_X_CURSOR_UL_ANGLE 144 +#define ECORE_X_CURSOR_UMBRELLA 146 +#define ECORE_X_CURSOR_UR_ANGLE 148 +#define ECORE_X_CURSOR_WATCH 150 +#define ECORE_X_CURSOR_XTERM 152 + +#endif // ifndef _ECORE_X_CURSOR_H diff --git a/src/lib/ecore_x/ecore_x_atoms_decl.h b/src/lib/ecore_x/ecore_x_atoms_decl.h new file mode 100644 index 0000000000..155283efe6 --- /dev/null +++ b/src/lib/ecore_x/ecore_x_atoms_decl.h @@ -0,0 +1,602 @@ +/* generic atoms */ +EAPI Ecore_X_Atom ECORE_X_ATOM_ATOM = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_CARDINAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_FILE_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_STRING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_TEXT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_PIXMAP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_VISUALID = 0; + +/* dnd atoms */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_XDND = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_XDND = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_AWARE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ENTER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_TYPE_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_POSITION = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_COPY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_MOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_PRIVATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_ASK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LINK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_DESCRIPTION = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_PROXY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_STATUS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_LEAVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_DROP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_XDND_FINISHED = 0; + +/* dnd atoms that need to be exposed to the application interface */ +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_COPY = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_MOVE = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_LINK = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_ASK = 0; +EAPI Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE = 0; + +/* old E atom */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE = 0; + +/* old Gnome atom */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER = 0; + +/* ICCCM atoms */ + +/* ICCCM: client properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_ICON_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_NORMAL_HINTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_SIZE_HINTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_HINTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CLASS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_TRANSIENT_FOR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_PROTOCOLS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_WINDOWS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_COMMAND = 0; /* obsolete */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_MACHINE = 0; /* obsolete */ + +/* ICCCM: window manager properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_ICON_SIZE = 0; + +/* ICCCM: WM_STATE property */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CHANGE_STATE = 0; + +/* ICCCM: WM_PROTOCOLS properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_TAKE_FOCUS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_SAVE_YOURSELF = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_DELETE_WINDOW = 0; + +/* ICCCM: WM_COLORMAP properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_NOTIFY = 0; + +/* ICCCM: session management properties */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SM_CLIENT_ID = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_LEADER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_WM_WINDOW_ROLE = 0; + +/* Motif WM atom */ +EAPI Ecore_X_Atom ECORE_X_ATOM_MOTIF_WM_HINTS = 0; + +/* NetWM 1.3 atoms (http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html) */ + +/* + * NetWM: Root Window Properties and related messages (complete) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST_STACKING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_VIEWPORT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CURRENT_DESKTOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_NAMES = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_ACTIVE_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WORKAREA = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_VIRTUAL_ROOTS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_LAYOUT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_SHOWING_DESKTOP = 0; + +/* + * NetWM: Other Root Window Messages (complete) + */ + +/* pager */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_CLOSE_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_MOVERESIZE_WINDOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_MOVERESIZE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_RESTACK_WINDOW = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS = 0; + +/* + * NetWM: Application Window Properties (complete) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_DESKTOP = 0; + +/* window type */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND = 0; + +/* state */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MODAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_STICKY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SHADED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_HIDDEN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_ABOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_BELOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION = 0; + +/* allowed actions */ +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_RESIZE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_SHADE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_STICK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CLOSE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_ABOVE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_BELOW = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT_PARTIAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_PID = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_HANDLED_ICONS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_USER_TIME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_ID = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS = 0; + +/* + * NetWM: Window Manager Protocols (complete) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_PING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER = 0; + +/* + * NetWM: Not in the spec + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_OPACITY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADOW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_SHADE = 0; + +/* + * Startup Notification (http://standards.freedesktop.org/startup-notification-spec/startup-notification-0.1.txt) + */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_NET_STARTUP_INFO = 0; + +/* selection atoms */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_PRIMARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_SECONDARY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD = 0; + +/* currently E specific virtual keyboard extension, aim to submit to netwm spec + * later */ + +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME = 0; + +/* currently E specific illume extension */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ZONE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ZONE_LIST = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CONFORMANT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_SINGLE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_BACK = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_FOCUS_HOME = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLOSE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_HOME_NEW = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_HOME_DEL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_START = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_DRAG_END = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_ON = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE= 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_AVAILABLE_ANGLE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_WINDOW_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_COUNTER = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_BEGIN = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_END = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_SYNC_CANCEL = 0; + +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_FLUSH = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_DUMP = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_COMP_PIXMAP = 0; + +/* currently Emotion and E17 specific extension */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIDEO_PARENT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_VIDEO_POSITION = 0; + +/* for sliding window */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_STATE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_GEOMETRY = 0; + +/* for SDB(Samsung Debug Bridge) */ +EAPI Ecore_X_Atom ECORE_X_ATOM_SDB_SERVER_CONNECT = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_SDB_SERVER_DISCONNECT = 0; + +/* currently elementary and E specific extension */ +EAPI Ecore_X_Atom ECORE_X_ATOM_E_PROFILE = 0; +EAPI Ecore_X_Atom ECORE_X_ATOM_E_PROFILE_LIST = 0; + +typedef struct _Atom_Item Atom_Item; + +struct _Atom_Item +{ + const char *name; + Ecore_X_Atom *atom; +}; + +const Atom_Item atom_items[] = +{ + { "ATOM", &ECORE_X_ATOM_ATOM }, + { "CARDINAL", &ECORE_X_ATOM_CARDINAL }, + { "COMPOUND_TEXT", &ECORE_X_ATOM_COMPOUND_TEXT }, + { "FILE_NAME", &ECORE_X_ATOM_FILE_NAME }, + { "STRING", &ECORE_X_ATOM_STRING }, + { "TEXT", &ECORE_X_ATOM_TEXT }, + { "UTF8_STRING", &ECORE_X_ATOM_UTF8_STRING }, + { "WINDOW", &ECORE_X_ATOM_WINDOW }, + { "PIXMAP", &ECORE_X_ATOM_PIXMAP }, + { "VISUALID", &ECORE_X_ATOM_VISUALID }, + + { "JXSelectionWindowProperty", &ECORE_X_ATOM_SELECTION_PROP_XDND }, + { "XdndSelection", &ECORE_X_ATOM_SELECTION_XDND }, + { "XdndAware", &ECORE_X_ATOM_XDND_AWARE }, + { "XdndEnter", &ECORE_X_ATOM_XDND_ENTER }, + { "XdndTypeList", &ECORE_X_ATOM_XDND_TYPE_LIST }, + { "XdndPosition", &ECORE_X_ATOM_XDND_POSITION }, + { "XdndActionCopy", &ECORE_X_ATOM_XDND_ACTION_COPY }, + { "XdndActionMove", &ECORE_X_ATOM_XDND_ACTION_MOVE }, + { "XdndActionPrivate", &ECORE_X_ATOM_XDND_ACTION_PRIVATE }, + { "XdndActionAsk", &ECORE_X_ATOM_XDND_ACTION_ASK }, + { "XdndActionList", &ECORE_X_ATOM_XDND_ACTION_LIST }, + { "XdndActionLink", &ECORE_X_ATOM_XDND_ACTION_LINK }, + { "XdndActionDescription", &ECORE_X_ATOM_XDND_ACTION_DESCRIPTION }, + { "XdndProxy", &ECORE_X_ATOM_XDND_PROXY }, + { "XdndStatus", &ECORE_X_ATOM_XDND_STATUS }, + { "XdndLeave", &ECORE_X_ATOM_XDND_LEAVE }, + { "XdndDrop", &ECORE_X_ATOM_XDND_DROP }, + { "XdndFinished", &ECORE_X_ATOM_XDND_FINISHED }, + + { "XdndActionCopy", &ECORE_X_DND_ACTION_COPY }, + { "XdndActionMove", &ECORE_X_DND_ACTION_MOVE }, + { "XdndActionLink", &ECORE_X_DND_ACTION_LINK }, + { "XdndActionAsk", &ECORE_X_DND_ACTION_ASK }, + { "XdndActionPrivate", &ECORE_X_DND_ACTION_PRIVATE }, + + { "_E_FRAME_SIZE", &ECORE_X_ATOM_E_FRAME_SIZE }, + + { "_WIN_LAYER", &ECORE_X_ATOM_WIN_LAYER }, + + { "WM_NAME", &ECORE_X_ATOM_WM_NAME }, + { "WM_ICON_NAME", &ECORE_X_ATOM_WM_ICON_NAME }, + { "WM_NORMAL_HINTS", &ECORE_X_ATOM_WM_NORMAL_HINTS }, + { "WM_SIZE_HINTS", &ECORE_X_ATOM_WM_SIZE_HINTS }, + { "WM_HINTS", &ECORE_X_ATOM_WM_HINTS }, + { "WM_CLASS", &ECORE_X_ATOM_WM_CLASS }, + { "WM_TRANSIENT_FOR", &ECORE_X_ATOM_WM_TRANSIENT_FOR }, + { "WM_PROTOCOLS", &ECORE_X_ATOM_WM_PROTOCOLS }, + { "WM_COLORMAP_WINDOWS", &ECORE_X_ATOM_WM_COLORMAP_WINDOWS }, + { "WM_COMMAND", &ECORE_X_ATOM_WM_COMMAND }, + { "WM_CLIENT_MACHINE", &ECORE_X_ATOM_WM_CLIENT_MACHINE }, + + { "WM_STATE", &ECORE_X_ATOM_WM_STATE }, + { "WM_ICON_SIZE", &ECORE_X_ATOM_WM_ICON_SIZE }, + + { "WM_CHANGE_STATE", &ECORE_X_ATOM_WM_CHANGE_STATE }, + + { "WM_TAKE_FOCUS", &ECORE_X_ATOM_WM_TAKE_FOCUS }, + { "WM_SAVE_YOURSELF", &ECORE_X_ATOM_WM_SAVE_YOURSELF }, + { "WM_DELETE_WINDOW", &ECORE_X_ATOM_WM_DELETE_WINDOW }, + + { "WM_COLORMAP_NOTIFY", &ECORE_X_ATOM_WM_COLORMAP_NOTIFY }, + + { "SM_CLIENT_ID", &ECORE_X_ATOM_SM_CLIENT_ID }, + { "WM_CLIENT_LEADER", &ECORE_X_ATOM_WM_CLIENT_LEADER }, + { "WM_WINDOW_ROLE", &ECORE_X_ATOM_WM_WINDOW_ROLE }, + + { "_MOTIF_WM_HINTS", &ECORE_X_ATOM_MOTIF_WM_HINTS }, + + { "_NET_SUPPORTED", &ECORE_X_ATOM_NET_SUPPORTED }, + { "_NET_CLIENT_LIST", &ECORE_X_ATOM_NET_CLIENT_LIST }, + { "_NET_CLIENT_LIST_STACKING", &ECORE_X_ATOM_NET_CLIENT_LIST_STACKING }, + { "_NET_NUMBER_OF_DESKTOPS", &ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS }, + { "_NET_DESKTOP_GEOMETRY", &ECORE_X_ATOM_NET_DESKTOP_GEOMETRY }, + { "_NET_DESKTOP_VIEWPORT", &ECORE_X_ATOM_NET_DESKTOP_VIEWPORT }, + { "_NET_CURRENT_DESKTOP", &ECORE_X_ATOM_NET_CURRENT_DESKTOP }, + { "_NET_DESKTOP_NAMES", &ECORE_X_ATOM_NET_DESKTOP_NAMES }, + { "_NET_ACTIVE_WINDOW", &ECORE_X_ATOM_NET_ACTIVE_WINDOW }, + { "_NET_WORKAREA", &ECORE_X_ATOM_NET_WORKAREA }, + { "_NET_SUPPORTING_WM_CHECK", &ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK }, + { "_NET_VIRTUAL_ROOTS", &ECORE_X_ATOM_NET_VIRTUAL_ROOTS }, + { "_NET_DESKTOP_LAYOUT", &ECORE_X_ATOM_NET_DESKTOP_LAYOUT }, + { "_NET_SHOWING_DESKTOP", &ECORE_X_ATOM_NET_SHOWING_DESKTOP }, + + { "_NET_CLOSE_WINDOW", &ECORE_X_ATOM_NET_CLOSE_WINDOW }, + { "_NET_MOVERESIZE_WINDOW", &ECORE_X_ATOM_NET_MOVERESIZE_WINDOW }, + { "_NET_WM_MOVERESIZE", &ECORE_X_ATOM_NET_WM_MOVERESIZE }, + { "_NET_RESTACK_WINDOW", &ECORE_X_ATOM_NET_RESTACK_WINDOW }, + + { "_NET_REQUEST_FRAME_EXTENTS", &ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS }, + + { "_NET_WM_NAME", &ECORE_X_ATOM_NET_WM_NAME }, + { "_NET_WM_VISIBLE_NAME", &ECORE_X_ATOM_NET_WM_VISIBLE_NAME }, + { "_NET_WM_ICON_NAME", &ECORE_X_ATOM_NET_WM_ICON_NAME }, + { "_NET_WM_VISIBLE_ICON_NAME", &ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME }, + { "_NET_WM_DESKTOP", &ECORE_X_ATOM_NET_WM_DESKTOP }, + + { "_NET_WM_WINDOW_TYPE", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE }, + { "_NET_WM_WINDOW_TYPE_DESKTOP", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP }, + { "_NET_WM_WINDOW_TYPE_DOCK", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK }, + { "_NET_WM_WINDOW_TYPE_TOOLBAR", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR }, + { "_NET_WM_WINDOW_TYPE_MENU", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU }, + { "_NET_WM_WINDOW_TYPE_UTILITY", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY }, + { "_NET_WM_WINDOW_TYPE_SPLASH", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH }, + { "_NET_WM_WINDOW_TYPE_DIALOG", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG }, + { "_NET_WM_WINDOW_TYPE_NORMAL", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL }, + { "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU", + &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU }, + { "_NET_WM_WINDOW_TYPE_POPUP_MENU", + &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU }, + { "_NET_WM_WINDOW_TYPE_TOOLTIP", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP }, + { "_NET_WM_WINDOW_TYPE_NOTIFICATION", + &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION }, + { "_NET_WM_WINDOW_TYPE_COMBO", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO }, + { "_NET_WM_WINDOW_TYPE_DND", &ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND }, + + { "_NET_WM_STATE", &ECORE_X_ATOM_NET_WM_STATE }, + { "_NET_WM_STATE_MODAL", &ECORE_X_ATOM_NET_WM_STATE_MODAL }, + { "_NET_WM_STATE_STICKY", &ECORE_X_ATOM_NET_WM_STATE_STICKY }, + { "_NET_WM_STATE_MAXIMIZED_VERT", + &ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT }, + { "_NET_WM_STATE_MAXIMIZED_HORZ", + &ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ }, + { "_NET_WM_STATE_SHADED", &ECORE_X_ATOM_NET_WM_STATE_SHADED }, + { "_NET_WM_STATE_SKIP_TASKBAR", &ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR }, + { "_NET_WM_STATE_SKIP_PAGER", &ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER }, + { "_NET_WM_STATE_HIDDEN", &ECORE_X_ATOM_NET_WM_STATE_HIDDEN }, + { "_NET_WM_STATE_FULLSCREEN", &ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN }, + { "_NET_WM_STATE_ABOVE", &ECORE_X_ATOM_NET_WM_STATE_ABOVE }, + { "_NET_WM_STATE_BELOW", &ECORE_X_ATOM_NET_WM_STATE_BELOW }, + { "_NET_WM_STATE_DEMANDS_ATTENTION", + &ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION }, + + { "_NET_WM_ALLOWED_ACTIONS", &ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS }, + { "_NET_WM_ACTION_MOVE", &ECORE_X_ATOM_NET_WM_ACTION_MOVE }, + { "_NET_WM_ACTION_RESIZE", &ECORE_X_ATOM_NET_WM_ACTION_RESIZE }, + { "_NET_WM_ACTION_MINIMIZE", &ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE }, + { "_NET_WM_ACTION_SHADE", &ECORE_X_ATOM_NET_WM_ACTION_SHADE }, + { "_NET_WM_ACTION_STICK", &ECORE_X_ATOM_NET_WM_ACTION_STICK }, + { "_NET_WM_ACTION_MAXIMIZE_HORZ", + &ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ }, + { "_NET_WM_ACTION_MAXIMIZE_VERT", + &ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT }, + { "_NET_WM_ACTION_FULLSCREEN", &ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN }, + { "_NET_WM_ACTION_CHANGE_DESKTOP", + &ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP }, + { "_NET_WM_ACTION_CLOSE", &ECORE_X_ATOM_NET_WM_ACTION_CLOSE }, + { "_NET_WM_ACTION_ABOVE", &ECORE_X_ATOM_NET_WM_ACTION_ABOVE }, + { "_NET_WM_ACTION_BELOW", &ECORE_X_ATOM_NET_WM_ACTION_BELOW }, + + { "_NET_WM_STRUT", &ECORE_X_ATOM_NET_WM_STRUT }, + { "_NET_WM_STRUT_PARTIAL", &ECORE_X_ATOM_NET_WM_STRUT_PARTIAL }, + { "_NET_WM_ICON_GEOMETRY", &ECORE_X_ATOM_NET_WM_ICON_GEOMETRY }, + { "_NET_WM_ICON", &ECORE_X_ATOM_NET_WM_ICON }, + { "_NET_WM_PID", &ECORE_X_ATOM_NET_WM_PID }, + { "_NET_WM_HANDLED_ICONS", &ECORE_X_ATOM_NET_WM_HANDLED_ICONS }, + { "_NET_WM_USER_TIME", &ECORE_X_ATOM_NET_WM_USER_TIME }, + { "_NET_STARTUP_ID", &ECORE_X_ATOM_NET_STARTUP_ID }, + { "_NET_FRAME_EXTENTS", &ECORE_X_ATOM_NET_FRAME_EXTENTS }, + + { "_NET_WM_PING", &ECORE_X_ATOM_NET_WM_PING }, + { "_NET_WM_SYNC_REQUEST", &ECORE_X_ATOM_NET_WM_SYNC_REQUEST }, + { "_NET_WM_SYNC_REQUEST_COUNTER", + &ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER }, + + { "_NET_WM_WINDOW_OPACITY", &ECORE_X_ATOM_NET_WM_WINDOW_OPACITY }, + { "_NET_WM_WINDOW_SHADOW", &ECORE_X_ATOM_NET_WM_WINDOW_SHADOW }, + { "_NET_WM_WINDOW_SHADE", &ECORE_X_ATOM_NET_WM_WINDOW_SHADE }, + + { "TARGETS", &ECORE_X_ATOM_SELECTION_TARGETS }, + { "CLIPBOARD", &ECORE_X_ATOM_SELECTION_CLIPBOARD }, + { "PRIMARY", &ECORE_X_ATOM_SELECTION_PRIMARY }, + { "SECONDARY", &ECORE_X_ATOM_SELECTION_SECONDARY }, + { "_ECORE_SELECTION_PRIMARY", &ECORE_X_ATOM_SELECTION_PROP_PRIMARY }, + { "_ECORE_SELECTION_SECONDARY", &ECORE_X_ATOM_SELECTION_PROP_SECONDARY }, + { "_ECORE_SELECTION_CLIPBOARD", &ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD }, + + { "_E_VIRTUAL_KEYBOARD", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD }, + { "_E_VIRTUAL_KEYBOARD_STATE", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE }, + { "_E_VIRTUAL_KEYBOARD_ON", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON }, + { "_E_VIRTUAL_KEYBOARD_OFF", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF }, + { "_E_VIRTUAL_KEYBOARD_ALPHA", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA }, + { "_E_VIRTUAL_KEYBOARD_NUMERIC", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC }, + { "_E_VIRTUAL_KEYBOARD_PIN", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN }, + { "_E_VIRTUAL_KEYBOARD_PHONE_NUMBER", + &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER }, + { "_E_VIRTUAL_KEYBOARD_HEX", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX }, + { "_E_VIRTUAL_KEYBOARD_TERMINAL", + &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL }, + { "_E_VIRTUAL_KEYBOARD_PASSWORD", + &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD }, + { "_E_VIRTUAL_KEYBOARD_IP", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP }, + { "_E_VIRTUAL_KEYBOARD_HOST", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST }, + { "_E_VIRTUAL_KEYBOARD_FILE", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE }, + { "_E_VIRTUAL_KEYBOARD_URL", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL }, + { "_E_VIRTUAL_KEYBOARD_KEYPAD", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD }, + { "_E_VIRTUAL_KEYBOARD_J2ME", &ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME }, + + { "_E_ILLUME_ZONE", &ECORE_X_ATOM_E_ILLUME_ZONE }, + { "_E_ILLUME_ZONE_LIST", &ECORE_X_ATOM_E_ILLUME_ZONE_LIST }, + { "_E_ILLUME_CONFORMANT", &ECORE_X_ATOM_E_ILLUME_CONFORMANT }, + { "_E_ILLUME_MODE", &ECORE_X_ATOM_E_ILLUME_MODE }, + { "_E_ILLUME_MODE_SINGLE", &ECORE_X_ATOM_E_ILLUME_MODE_SINGLE }, + { "_E_ILLUME_MODE_DUAL_TOP", &ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP }, + { "_E_ILLUME_MODE_DUAL_LEFT", &ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT }, + { "_E_ILLUME_FOCUS_BACK", &ECORE_X_ATOM_E_ILLUME_FOCUS_BACK }, + { "_E_ILLUME_FOCUS_FORWARD", &ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD }, + { "_E_ILLUME_FOCUS_HOME", &ECORE_X_ATOM_E_ILLUME_FOCUS_HOME }, + { "_E_ILLUME_CLOSE", &ECORE_X_ATOM_E_ILLUME_CLOSE }, + { "_E_ILLUME_HOME_NEW", &ECORE_X_ATOM_E_ILLUME_HOME_NEW }, + { "_E_ILLUME_HOME_DEL", &ECORE_X_ATOM_E_ILLUME_HOME_DEL }, + { "_E_ILLUME_DRAG", &ECORE_X_ATOM_E_ILLUME_DRAG }, + { "_E_ILLUME_DRAG_LOCKED", &ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED }, + { "_E_ILLUME_DRAG_START", &ECORE_X_ATOM_E_ILLUME_DRAG_START }, + { "_E_ILLUME_DRAG_END", &ECORE_X_ATOM_E_ILLUME_DRAG_END }, + { "_E_ILLUME_INDICATOR_GEOMETRY", + &ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY }, + { "_E_ILLUME_SOFTKEY_GEOMETRY", &ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY }, + { "_E_ILLUME_KEYBOARD_GEOMETRY", &ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY }, + { "_E_ILLUME_QUICKPANEL", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL }, + { "_E_ILLUME_QUICKPANEL_STATE", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE }, + { "_E_ILLUME_QUICKPANEL_STATE_TOGGLE", + &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE }, + { "_E_ILLUME_QUICKPANEL_ON", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON }, + { "_E_ILLUME_QUICKPANEL_OFF", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF }, + { "_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR", + &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR }, + { "_E_ILLUME_QUICKPANEL_PRIORITY_MINOR", + &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR }, + { "_E_ILLUME_QUICKPANEL_ZONE", &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE }, + { "_E_ILLUME_QUICKPANEL_POSITION_UPDATE", + &ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE }, + { "_E_ILLUME_INDICATOR_STATE", &ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE }, + { "_E_ILLUME_INDICATOR_ON", &ECORE_X_ATOM_E_ILLUME_INDICATOR_ON }, + { "_E_ILLUME_INDICATOR_OFF", &ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF }, + { "_E_ILLUME_INDICATOR_OPACITY_MODE", &ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE }, + { "_E_ILLUME_INDICATOR_OPAQUE", &ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE }, + { "_E_ILLUME_INDICATOR_TRANSLUCENT", &ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT }, + { "_E_ILLUME_INDICATOR_TRANSPARENT", &ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT }, + { "_E_ILLUME_ROTATE_WINDOW_AVAILABLE_ANGLES", &ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_AVAILABLE_ANGLE }, + { "_E_ILLUME_ROTATE_WINDOW_ANGLE", &ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE }, + { "_E_ILLUME_ROTATE_ROOT_ANGLE", &ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE }, + { "_E_ILLUME_CLIPBOARD_STATE", &ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE }, + { "_E_ILLUME_CLIPBOARD_ON", &ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON }, + { "_E_ILLUME_CLIPBOARD_OFF", &ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF }, + { "_E_ILLUME_CLIPBOARD_GEOMETRY", &ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY }, + { "_E_ILLUME_WINDOW_STATE", &ECORE_X_ATOM_E_ILLUME_WINDOW_STATE }, + { "_E_ILLUME_WINDOW_STATE_NORMAL", &ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL }, + { "_E_ILLUME_WINDOW_STATE_FLOATING", &ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING }, + { "_E_ILLUME_ACCESS_CONTROL", &ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL }, + { "_E_ILLUME_ACCESS_ACTION_NEXT", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT }, + { "_E_ILLUME_ACCESS_ACTION_PREV", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV }, + { "_E_ILLUME_ACCESS_ACTION_ACTIVATE", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE }, + { "_E_ILLUME_ACCESS_ACTION_READ", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ }, + { "_E_ILLUME_ACCESS_ACTION_READ_NEXT", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT }, + { "_E_ILLUME_ACCESS_ACTION_READ_PREV", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV }, + { "_E_ILLUME_ACCESS_ACTION_UP", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP }, + { "_E_ILLUME_ACCESS_ACTION_DOWN", &ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN }, + { "_E_COMP_SYNC_COUNTER", &ECORE_X_ATOM_E_COMP_SYNC_COUNTER }, + { "_E_COMP_SYNC_DRAW_DONE", &ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE }, + { "_E_COMP_SYNC_SUPPORTED", &ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED }, + { "_E_COMP_SYNC_BEGIN", &ECORE_X_ATOM_E_COMP_SYNC_BEGIN }, + { "_E_COMP_SYNC_END", &ECORE_X_ATOM_E_COMP_SYNC_END }, + { "_E_COMP_SYNC_CANCEL", &ECORE_X_ATOM_E_COMP_SYNC_CANCEL }, + + { "_E_COMP_FLUSH", &ECORE_X_ATOM_E_COMP_FLUSH }, + { "_E_COMP_DUMP", &ECORE_X_ATOM_E_COMP_DUMP }, + { "_E_COMP_PIXMAP", &ECORE_X_ATOM_E_COMP_PIXMAP }, + { "_E_VIDEO_PARENT", &ECORE_X_ATOM_E_VIDEO_PARENT }, + { "_E_VIDEO_POSITION", &ECORE_X_ATOM_E_VIDEO_POSITION } +}; + diff --git a/src/lib/ecore_x/xcb/ecore_xcb.c b/src/lib/ecore_x/xcb/ecore_xcb.c new file mode 100644 index 0000000000..2f1e1a2601 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb.c @@ -0,0 +1,1583 @@ +#include "ecore_xcb_private.h" +#include <X11/Xlib-xcb.h> +#include <dlfcn.h> + +/* local function prototypes */ +static int _ecore_xcb_shutdown(Eina_Bool close_display); +static Eina_Bool _ecore_xcb_fd_handle(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED); +static Eina_Bool _ecore_xcb_fd_handle_buff(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED); +static Eina_Bool _ecore_xcb_idle_enter(void *data EINA_UNUSED); + +/* local variables */ +static int _ecore_xcb_init_count = 0; +static int _ecore_xcb_grab_count = 0; +static Ecore_Fd_Handler *_ecore_xcb_fd_handler = NULL; +static xcb_generic_event_t *_ecore_xcb_event_buffered = NULL; +static Ecore_Idle_Enterer *_ecore_xcb_idle_enterer = NULL; + +/* external variables */ +int _ecore_xcb_log_dom = -1; +Ecore_X_Display *_ecore_xcb_display = NULL; +Ecore_X_Connection *_ecore_xcb_conn = NULL; +Ecore_X_Screen *_ecore_xcb_screen = NULL; +Ecore_X_Atom _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_NUM]; +double _ecore_xcb_double_click_time = 0.25; + +/** + * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions + * + * Functions that start and shut down the Ecore X Library. + */ + +/** + * Initialize the X display connection to the given display. + * + * @param name Display target name. If @c NULL, the default display is + * assumed. + * @return The number of times the library has been initialized without + * being shut down. 0 is returned if an error occurs. + * @ingroup Ecore_X_Init_Group + */ +EAPI int +ecore_x_init(const char *name) +{ + char *gl = NULL; + uint32_t mask, list[1]; + + /* check if we have initialized already */ + if (++_ecore_xcb_init_count != 1) + return _ecore_xcb_init_count; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + /* try to initialize eina */ + if (!eina_init()) return --_ecore_xcb_init_count; + + /* setup ecore_xcb log domain */ + _ecore_xcb_log_dom = + eina_log_domain_register("ecore_x", ECORE_XCB_DEFAULT_LOG_COLOR); + if (_ecore_xcb_log_dom < 0) + { + EINA_LOG_ERR("Cannot create Ecore Xcb log domain"); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + + /* try to initialize ecore */ + if (!ecore_init()) + { + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + eina_shutdown(); + return --_ecore_xcb_init_count; + } + + /* try to initialize ecore_event */ + if (!ecore_event_init()) + { + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + ecore_shutdown(); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + + /* NB: XLib has XInitThreads */ + + /* check for env var which says we are not going to use GL @ all + * + * NB: This is done because if someone wants a 'pure' xcb implementation + * of ecore_x, all they need do is export this variable in the environment + * and ecore_x will not use xlib stuff at all. + * + * The upside is you can get pure xcb-based ecore_x (w/ all the speed), but + * there is a down-side here in that you cannot get OpenGL without XLib :( + */ + if ((gl = getenv("ECORE_X_NO_XLIB"))) + { + /* we found the env var that says 'Yes, we are not ever gonna try + * OpenGL so it is safe to not use XLib at all' */ + + /* try to connect to the display server */ + _ecore_xcb_conn = xcb_connect(name, NULL); + } + else + { + /* env var was not specified, so we will assume that the user + * may want opengl @ some point. connect this way for opengl to work */ + void *libxcb, *libxlib; + Display *(*_real_display)(const char *display); + xcb_connection_t *(*_real_connection)(Display * dpy); + void (*_real_queue)(Display *dpy, enum XEventQueueOwner owner); + int (*_real_close)(Display *dpy); +#ifdef EVAS_FRAME_QUEUING + Status (*_real_threads)(void); +#endif + + /* want to dlopen here to avoid actual library linkage */ + libxlib = dlopen("libX11.so", (RTLD_LAZY | RTLD_GLOBAL)); + if (!libxlib) + libxlib = dlopen("libX11.so.6", (RTLD_LAZY | RTLD_GLOBAL)); + if (!libxlib) + libxlib = dlopen("libX11.so.6.3.0", (RTLD_LAZY | RTLD_GLOBAL)); + if (!libxlib) + { + ERR("Could not dlsym to libX11"); + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + ecore_event_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + + libxcb = dlopen("libX11-xcb.so", (RTLD_LAZY | RTLD_GLOBAL)); + if (!libxcb) + libxcb = dlopen("libX11-xcb.so.1", (RTLD_LAZY | RTLD_GLOBAL)); + if (!libxcb) + libxcb = dlopen("libX11-xcb.so.1.0.0", (RTLD_LAZY | RTLD_GLOBAL)); + if (!libxcb) + { + ERR("Could not dlsym to libX11-xcb"); + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + ecore_event_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + + _real_display = dlsym(libxlib, "XOpenDisplay"); + _real_close = dlsym(libxlib, "XCloseDisplay"); + _real_connection = dlsym(libxcb, "XGetXCBConnection"); + _real_queue = dlsym(libxcb, "XSetEventQueueOwner"); +#ifdef EVAS_FRAME_QUEUING + _real_threads = dlsym(libxlib, "XInitThreads"); +#endif + + if (_real_display) + { +#ifdef EVAS_FRAME_QUEUING + if (_real_threads) _real_threads(); +#endif + _ecore_xcb_display = _real_display(name); + if (!_ecore_xcb_display) + { + ERR("Could not open Display via XLib"); + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + ecore_event_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + if (_real_connection) + _ecore_xcb_conn = _real_connection(_ecore_xcb_display); + if (!_ecore_xcb_conn) + { + ERR("Could not get XCB Connection from XLib"); + + if (_real_close) _real_close(_ecore_xcb_display); + + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + ecore_event_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + if (_real_queue) + _real_queue(_ecore_xcb_display, XCBOwnsEventQueue); + } + } + + if (xcb_connection_has_error(_ecore_xcb_conn)) + { + CRIT("XCB Connection has error"); + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + ecore_event_shutdown(); + ecore_shutdown(); + eina_shutdown(); + return --_ecore_xcb_init_count; + } + + /* grab the default screen */ + _ecore_xcb_screen = + xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data; + + /* NB: This method of init/finalize extensions first, then atoms + * Does end up being 2 round trips to X, BUT if we do extensions init then + * atoms init first, and call the 'finalize' functions later, we end up + * being slower, so it's a trade-off. This current method clocks in + * around 0.003 for fetching atoms VS 0.010 for init both then finalize */ + + /* prefetch extension data */ + _ecore_xcb_extensions_init(); + + /* finalize extensions */ + _ecore_xcb_extensions_finalize(); + + /* set keyboard autorepeat */ + mask = XCB_KB_AUTO_REPEAT_MODE; + list[0] = XCB_AUTO_REPEAT_MODE_ON; + xcb_change_keyboard_control(_ecore_xcb_conn, mask, list); + + /* setup xcb events */ + _ecore_xcb_events_init(); + + /* setup xcb keymasks */ + _ecore_xcb_keymap_init(); + + /* finalize xcb keymasks */ + _ecore_xcb_keymap_finalize(); + + /* setup ecore fd handler */ + _ecore_xcb_fd_handler = + ecore_main_fd_handler_add(xcb_get_file_descriptor(_ecore_xcb_conn), + ECORE_FD_READ, _ecore_xcb_fd_handle, + _ecore_xcb_conn, _ecore_xcb_fd_handle_buff, + _ecore_xcb_conn); + + if (!_ecore_xcb_fd_handler) + return _ecore_xcb_shutdown(EINA_TRUE); + + /* prefetch atoms */ + _ecore_xcb_atoms_init(); + + /* finalize atoms */ + _ecore_xcb_atoms_finalize(); + + /* icccm_init: dummy function */ + ecore_x_icccm_init(); + + /* setup netwm */ + ecore_x_netwm_init(); + + /* old e hints init: dummy function */ + ecore_x_e_init(); + + _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = + ECORE_X_ATOM_WM_DELETE_WINDOW; + _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = + ECORE_X_ATOM_WM_TAKE_FOCUS; + _ecore_xcb_atoms_wm_protocol[ECORE_X_NET_WM_PROTOCOL_PING] = + ECORE_X_ATOM_NET_WM_PING; + _ecore_xcb_atoms_wm_protocol[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = + ECORE_X_ATOM_NET_WM_SYNC_REQUEST; + + /* setup selection */ + _ecore_xcb_selection_init(); + + /* setup dnd */ + _ecore_xcb_dnd_init(); + + _ecore_xcb_idle_enterer = + ecore_idle_enterer_add(_ecore_xcb_idle_enter, NULL); + + return _ecore_xcb_init_count; +} + +/** + * Shuts down the Ecore X library. + * + * In shutting down the library, the X display connection is terminated + * and any event handlers for it are removed. + * + * @return The number of times the library has been initialized without + * being shut down. + * @ingroup Ecore_X_Init_Group + */ +EAPI int +ecore_x_shutdown(void) +{ + return _ecore_xcb_shutdown(EINA_TRUE); +} + +/** + * Shuts down the Ecore X library. + * + * As ecore_x_shutdown, except do not close Display, only connection. + * + * @return The number of times the library has been initialized without + * being shut down. 0 is returned if an error occurs. + * @ingroup Ecore_X_Init_Group + */ +EAPI int +ecore_x_disconnect(void) +{ + return _ecore_xcb_shutdown(EINA_FALSE); +} + +/** + * @defgroup Ecore_X_Flush_Group X Synchronization Functions + * + * Functions that ensure that all commands that have been issued by the + * Ecore X library have been sent to the server. + */ + +/** + * Sends all X commands in the X Display buffer. + * @ingroup Ecore_X_Flush_Group + */ +EAPI void +ecore_x_flush(void) +{ +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + CHECK_XCB_CONN; + xcb_flush(_ecore_xcb_conn); +} + +/** + * Retrieves the Ecore_X_Screen handle used for the current X connection. + * @return The current default screen. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI Ecore_X_Screen * +ecore_x_default_screen_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return (Ecore_X_Screen *)_ecore_xcb_screen; +} + +EAPI Ecore_X_Connection * +ecore_x_connection_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + CHECK_XCB_CONN; + return (Ecore_X_Connection *)_ecore_xcb_conn; +} + +/** + * Return the last event time + */ +EAPI Ecore_X_Time +ecore_x_current_time_get(void) +{ + return _ecore_xcb_events_last_time_get(); +} + +/** + * Flushes the command buffer and waits until all requests have been + * processed by the server. + * @ingroup Ecore_X_Flush_Group + */ +EAPI void +ecore_x_sync(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + CHECK_XCB_CONN; + free(xcb_get_input_focus_reply(_ecore_xcb_conn, + xcb_get_input_focus_unchecked(_ecore_xcb_conn), + NULL)); +} + +EAPI void +ecore_x_grab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + CHECK_XCB_CONN; + _ecore_xcb_grab_count++; + if (_ecore_xcb_grab_count == 1) + xcb_grab_server(_ecore_xcb_conn); +} + +EAPI void +ecore_x_ungrab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + CHECK_XCB_CONN; + _ecore_xcb_grab_count--; + if (_ecore_xcb_grab_count < 0) _ecore_xcb_grab_count = 0; + if (_ecore_xcb_grab_count == 0) + xcb_ungrab_server(_ecore_xcb_conn); +} + +/** + * Send client message with given type and format 32. + * + * @param win The window the message is sent to. + * @param type The client message type. + * @param mask The mask of the message to be sent. + * @param d0 The client message data item 1 + * @param d1 The client message data item 2 + * @param d2 The client message data item 3 + * @param d3 The client message data item 4 + * @param d4 The client message data item 5 + * + * @return @c EINA_TRUE on success @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type, + Ecore_X_Event_Mask mask, + long d0, long d1, long d2, long d3, long d4) +{ + xcb_client_message_event_t ev; + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = type; + ev.data.data32[0] = (uint32_t)d0; + ev.data.data32[1] = (uint32_t)d1; + ev.data.data32[2] = (uint32_t)d2; + ev.data.data32[3] = (uint32_t)d3; + ev.data.data32[4] = (uint32_t)d4; + + cookie = xcb_send_event(_ecore_xcb_conn, 0, win, mask, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + DBG("Problem Sending Event"); + DBG("\tType: %d", type); + DBG("\tWin: %d", win); + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +/** + * Send client message with given type and format 8. + * + * @param win The window the message is sent to. + * @param type The client message type. + * @param data Data to be sent. + * @param len Number of data bytes, max @c 20. + * + * @return @c EINA_TRUE on success @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type, + const void *data, int len) +{ + xcb_client_message_event_t ev; + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 8; + ev.window = win; + ev.type = type; + if (len > 20) len = 20; + memcpy(ev.data.data8, data, len); + memset(ev.data.data8 + len, 0, 20 - len); + + cookie = xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + DBG("Problem Sending Event"); + DBG("\tType: %d", type); + DBG("\tWin: %d", win); + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b) +{ + xcb_translate_coordinates_cookie_t cookie; + xcb_translate_coordinates_reply_t *reply; + xcb_button_press_event_t ev; + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + Ecore_X_Window root = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ecore_x_window_root_get(win); + cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y); + reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + memset(&ev, 0, sizeof(xcb_button_press_event_t)); + + ev.response_type = XCB_BUTTON_PRESS; + ev.event = win; + ev.child = win; + ev.root = root; + ev.event_x = x; + ev.event_y = y; + ev.same_screen = 1; + ev.state = 1 << b; + ev.detail = b; // xcb uses detail for button + ev.root_x = reply->dst_x; + ev.root_y = reply->dst_y; + ev.time = ecore_x_current_time_get(); + free(reply); + + vcookie = xcb_send_event(_ecore_xcb_conn, 1, win, + XCB_EVENT_MASK_BUTTON_PRESS, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b) +{ + xcb_translate_coordinates_cookie_t cookie; + xcb_translate_coordinates_reply_t *reply; + xcb_button_release_event_t ev; + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + Ecore_X_Window root = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ecore_x_window_root_get(win); + cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y); + reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + memset(&ev, 0, sizeof(xcb_button_release_event_t)); + + ev.response_type = XCB_BUTTON_RELEASE; + ev.event = win; + ev.child = win; + ev.root = root; + ev.event_x = x; + ev.event_y = y; + ev.same_screen = 1; + ev.state = 0; + ev.root_x = reply->dst_x; + ev.root_y = reply->dst_y; + ev.detail = b; // xcb uses detail for button + ev.time = ecore_x_current_time_get(); + free(reply); + + vcookie = xcb_send_event(_ecore_xcb_conn, 1, win, + XCB_EVENT_MASK_BUTTON_RELEASE, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y) +{ + xcb_translate_coordinates_cookie_t cookie; + xcb_translate_coordinates_reply_t *reply; + xcb_motion_notify_event_t ev; + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + Ecore_X_Window root = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ecore_x_window_root_get(win); + cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y); + reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + memset(&ev, 0, sizeof(xcb_motion_notify_event_t)); + + ev.response_type = XCB_MOTION_NOTIFY; + ev.event = win; + ev.child = win; + ev.root = root; + ev.event_x = x; + ev.event_y = y; + ev.same_screen = 1; + ev.state = 0; + ev.detail = 0; // xcb uses 'detail' for is_hint + ev.root_x = reply->dst_x; + ev.root_y = reply->dst_y; + ev.time = ecore_x_current_time_get(); + free(reply); + + vcookie = xcb_send_event(_ecore_xcb_conn, 1, win, + XCB_EVENT_MASK_POINTER_MOTION, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_mouse_in_send(Ecore_X_Window win, int x, int y) +{ + xcb_translate_coordinates_cookie_t cookie; + xcb_translate_coordinates_reply_t *reply; + xcb_enter_notify_event_t ev; + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + Ecore_X_Window root = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ecore_x_window_root_get(win); + cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y); + reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + memset(&ev, 0, sizeof(xcb_enter_notify_event_t)); + + ev.response_type = XCB_ENTER_NOTIFY; + ev.event = win; + ev.child = win; + ev.root = root; + ev.event_x = x; + ev.event_y = y; + ev.same_screen_focus = 1; + ev.mode = XCB_NOTIFY_MODE_NORMAL; + ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR; + /* ev.focus = 0; */ + ev.state = 0; + ev.root_x = reply->dst_x; + ev.root_y = reply->dst_y; + ev.time = ecore_x_current_time_get(); + free(reply); + + vcookie = xcb_send_event(_ecore_xcb_conn, 1, win, + XCB_EVENT_MASK_ENTER_WINDOW, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_mouse_out_send(Ecore_X_Window win, int x, int y) +{ + xcb_translate_coordinates_cookie_t cookie; + xcb_translate_coordinates_reply_t *reply; + xcb_leave_notify_event_t ev; + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + Ecore_X_Window root = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ecore_x_window_root_get(win); + cookie = xcb_translate_coordinates(_ecore_xcb_conn, win, root, x, y); + reply = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + memset(&ev, 0, sizeof(xcb_leave_notify_event_t)); + + ev.response_type = XCB_LEAVE_NOTIFY; + ev.event = win; + ev.child = win; + ev.root = root; + ev.event_x = x; + ev.event_y = y; + ev.same_screen_focus = 1; + ev.mode = XCB_NOTIFY_MODE_NORMAL; + ev.detail = XCB_NOTIFY_DETAIL_NONLINEAR; + /* ev.focus = 0; */ + ev.state = 0; + ev.root_x = reply->dst_x; + ev.root_y = reply->dst_y; + ev.time = ecore_x_current_time_get(); + free(reply); + + vcookie = xcb_send_event(_ecore_xcb_conn, 1, win, + XCB_EVENT_MASK_LEAVE_WINDOW, (const char *)&ev); + + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_keyboard_grab(Ecore_X_Window win) +{ + xcb_grab_keyboard_cookie_t cookie; + xcb_grab_keyboard_reply_t *reply; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = + xcb_grab_keyboard_unchecked(_ecore_xcb_conn, 0, win, XCB_CURRENT_TIME, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); + reply = xcb_grab_keyboard_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + free(reply); + return EINA_TRUE; +} + +EAPI void +ecore_x_keyboard_ungrab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_ungrab_keyboard(_ecore_xcb_conn, XCB_CURRENT_TIME); +} + +EAPI void +ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y) +{ + xcb_query_pointer_cookie_t cookie; + xcb_query_pointer_reply_t *reply; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +// if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + if (x) *x = -1; + if (y) *y = -1; + + cookie = xcb_query_pointer_unchecked(_ecore_xcb_conn, win); + reply = xcb_query_pointer_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + if (x) *x = reply->win_x; + if (y) *y = reply->win_y; + free(reply); +} + +EAPI Eina_Bool +ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold) +{ + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + vcookie = + xcb_change_pointer_control_checked(_ecore_xcb_conn, + accel_num, accel_denom, threshold, + 1, 1); + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold) +{ + xcb_get_pointer_control_cookie_t cookie; + xcb_get_pointer_control_reply_t *reply; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (accel_num) *accel_num = 0; + if (accel_denom) *accel_denom = 0; + if (threshold) *threshold = 0; + + cookie = xcb_get_pointer_control_unchecked(_ecore_xcb_conn); + reply = xcb_get_pointer_control_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + if (accel_num) *accel_num = reply->acceleration_numerator; + if (accel_denom) *accel_denom = reply->acceleration_denominator; + if (threshold) *threshold = reply->threshold; + free(reply); + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_pointer_mapping_set(unsigned char *map, int nmap) +{ + xcb_set_pointer_mapping_cookie_t cookie; + xcb_set_pointer_mapping_reply_t *reply; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_set_pointer_mapping_unchecked(_ecore_xcb_conn, nmap, map); + reply = xcb_set_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + if (reply->status == XCB_MAPPING_STATUS_SUCCESS) + ret = EINA_TRUE; + + free(reply); + return ret; +} + +EAPI Eina_Bool +ecore_x_pointer_mapping_get(unsigned char *map, int nmap) +{ + xcb_get_pointer_mapping_cookie_t cookie; + xcb_get_pointer_mapping_reply_t *reply; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (map) *map = 0; + nmap = 0; + + cookie = xcb_get_pointer_mapping_unchecked(_ecore_xcb_conn); + reply = xcb_get_pointer_mapping_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + nmap = xcb_get_pointer_mapping_map_length(reply); + if (nmap <= 0) + { + free(reply); + return EINA_FALSE; + } + + if (map) + { + uint8_t *tmp; + int i = 0; + + tmp = xcb_get_pointer_mapping_map(reply); + for (i = 0; i < nmap; i++) + map[i] = tmp[i]; + } + + free(reply); + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_pointer_grab(Ecore_X_Window win) +{ + xcb_grab_pointer_cookie_t cookie; + xcb_grab_pointer_reply_t *reply; + uint16_t mask; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + mask = (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION); + + cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask, + XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC, + XCB_NONE, XCB_NONE, XCB_CURRENT_TIME); + reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE; + + free(reply); + return ret; +} + +EAPI Eina_Bool +ecore_x_pointer_confine_grab(Ecore_X_Window win) +{ + xcb_grab_pointer_cookie_t cookie; + xcb_grab_pointer_reply_t *reply; + uint16_t mask; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + mask = (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION); + + cookie = xcb_grab_pointer_unchecked(_ecore_xcb_conn, 0, win, mask, + XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC, + win, XCB_NONE, XCB_CURRENT_TIME); + reply = xcb_grab_pointer_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + ret = (reply->status == XCB_GRAB_STATUS_SUCCESS) ? EINA_TRUE : EINA_FALSE; + + free(reply); + return ret; +} + +EAPI void +ecore_x_pointer_ungrab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_ungrab_pointer(_ecore_xcb_conn, XCB_CURRENT_TIME); +} + +EAPI Eina_Bool +ecore_x_pointer_warp(Ecore_X_Window win, int x, int y) +{ + xcb_void_cookie_t vcookie; + xcb_generic_error_t *err; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + vcookie = + xcb_warp_pointer_checked(_ecore_xcb_conn, XCB_NONE, win, 0, 0, 0, 0, x, y); + err = xcb_request_check(_ecore_xcb_conn, vcookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +/** + * Invoke the standard system beep to alert users + * + * @param percent The volume at which the bell rings. Must be in the range + * [-100,+100]. If percent >= 0, the final volume will be: + * base - [(base * percent) / 100] + percent + * Otherwise, it's calculated as: + * base + [(base * percent) / 100] + * where @c base is the bell's base volume as set by XChangeKeyboardControl(3). + * + * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_bell(int percent) +{ + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; + + CHECK_XCB_CONN; + + // FIXME: Use unchecked version after development is ironed out + cookie = xcb_bell_checked(_ecore_xcb_conn, percent); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI void +ecore_x_display_size_get(Ecore_X_Display *dsp EINA_UNUSED, int *w, int *h) +{ + xcb_screen_t *screen; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + /* grab the default screen */ + screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data; + if (w) *w = screen->width_in_pixels; + if (h) *h = screen->height_in_pixels; +} + +EAPI unsigned long +ecore_x_display_black_pixel_get(Ecore_X_Display *dsp EINA_UNUSED) +{ + xcb_screen_t *screen; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + /* grab the default screen */ + screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data; + return screen->black_pixel; +} + +EAPI unsigned long +ecore_x_display_white_pixel_get(Ecore_X_Display *dsp EINA_UNUSED) +{ + xcb_screen_t *screen; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + /* grab the default screen */ + screen = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).data; + return screen->white_pixel; +} + +EAPI void +ecore_x_pointer_last_xy_get(int *x, int *y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (x) *x = _ecore_xcb_event_last_root_x; + if (y) *y = _ecore_xcb_event_last_root_y; +} + +EAPI void +ecore_x_focus_reset(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_set_input_focus(_ecore_xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + XCB_CURRENT_TIME); +// ecore_x_flush(); +} + +EAPI void +ecore_x_events_allow_all(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_allow_events(_ecore_xcb_conn, XCB_ALLOW_ASYNC_BOTH, XCB_CURRENT_TIME); +// ecore_x_flush(); +} + +/** + * Kill a specific client + * + * You can kill a specific client owning window @p win + * + * @param win Window of the client to be killed + */ +EAPI void +ecore_x_kill(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_kill_client(_ecore_xcb_conn, win); +// ecore_x_flush(); +} + +/** + * Kill all clients with subwindows under a given window. + * + * You can kill all clients connected to the X server by using + * @ref ecore_x_window_root_list to get a list of root windows, and + * then passing each root window to this function. + * + * @param root The window whose children will be killed. + */ +EAPI void +ecore_x_killall(Ecore_X_Window root) +{ + int screens = 0, i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + ecore_x_grab(); + + screens = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem; + + /* Traverse window tree starting from root, and drag each + * before the firing squad */ + for (i = 0; i < screens; ++i) + { + xcb_query_tree_cookie_t cookie; + xcb_query_tree_reply_t *reply; + + cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, root); + reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + xcb_window_t *wins = NULL; + int tree_c_len, j = 0; + + wins = xcb_query_tree_children(reply); + tree_c_len = xcb_query_tree_children_length(reply); + for (j = 0; j < tree_c_len; j++) + xcb_kill_client(_ecore_xcb_conn, wins[j]); + free(reply); + } + } + + ecore_x_ungrab(); + ecore_x_sync(); // needed +} + +/** + * Return the screen DPI + * + * This is a simplistic call to get DPI. It does not account for differing + * DPI in the x amd y axes nor does it account for multihead or xinerama and + * xrander where different parts of the screen may have differen DPI etc. + * + * @return the general screen DPI (dots/pixels per inch). + */ +EAPI int +ecore_x_dpi_get(void) +{ + uint16_t mw = 0, w = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + mw = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_millimeters; + if (mw <= 0) return 75; + w = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels; + return (((w * 254) / mw) + 5) / 10; +} + +/** + * @defgroup Ecore_X_Display_Attr_Group X Display Attributes + * + * Functions that set and retrieve X display attributes. + */ + +/** + * Retrieves the Ecore_X_Display handle used for the current X connection. + * @return The current X display. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI Ecore_X_Display * +ecore_x_display_get(void) +{ + char *gl = NULL; + + CHECK_XCB_CONN; + + /* if we have the 'dont use xlib' env var, then we are not using + * XLib and thus cannot return a real XDisplay. + * + * NB: This may break EFL in some places and needs lots of testing !!! */ + if ((gl = getenv("ECORE_X_NO_XLIB"))) + return (Ecore_X_Display *)_ecore_xcb_conn; + else /* we can safely return an XDisplay var */ + return (Ecore_X_Display *)_ecore_xcb_display; +} + +/** + * Retrieves the X display file descriptor. + * @return The current X display file descriptor. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI int +ecore_x_fd_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + return xcb_get_file_descriptor(_ecore_xcb_conn); +} + +EAPI void +ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, int type, void *event), + void *data) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_window_grab_replay_func = func; + _ecore_xcb_window_grab_replay_data = data; +} + +/** + * Retrieves the size of an Ecore_X_Screen. + * @param screen the handle to the screen to query. + * @param w where to return the width. May be NULL. Returns 0 on errors. + * @param h where to return the height. May be NULL. Returns 0 on errors. + * @ingroup Ecore_X_Display_Attr_Group + * @see ecore_x_default_screen_get() + * + * @since 1.1 + */ +EAPI void +ecore_x_screen_size_get(const Ecore_X_Screen *screen, int *w, int *h) +{ + xcb_screen_t *s; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (w) *w = 0; + if (h) *h = 0; + if (!(s = (xcb_screen_t *)screen)) return; + if (w) *w = s->width_in_pixels; + if (h) *h = s->height_in_pixels; +} + +/** + * Retrieves the count of screens. + * + * @return The count of screens. + * @ingroup Ecore_X_Display_Attr_Group + * + * @since 1.1 + */ +EAPI int +ecore_x_screen_count_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + return xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn)); +} + +/** + * Retrieves the index number of the given screen. + * + * @param screen The screen for which index will be gotten. + * @return The index number of the screen. + * @ingroup Ecore_X_Display_Attr_Group + * + * @since 1.1 + */ +EAPI int +ecore_x_screen_index_get(const Ecore_X_Screen *screen) +{ + xcb_screen_iterator_t iter; + int i = 0; + + CHECK_XCB_CONN; + + iter = + xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (; iter.rem; xcb_screen_next(&iter)) + { + if (iter.data == (xcb_screen_t *)screen) + return i; + i++; + } + + return 0; +} + +/** + * Retrieves the screen based on index number. + * + * @param idx The index that will be used to retrieve the screen. + * @return The Ecore_X_Screen at this index. + * @ingroup Ecore_X_Display_Attr_Group + * + * @since 1.1 + */ +EAPI Ecore_X_Screen * +ecore_x_screen_get(int idx) +{ + xcb_screen_iterator_t iter; + int i = 0; + + CHECK_XCB_CONN; + + iter = + xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (i = 0; iter.rem; xcb_screen_next(&iter), i++) + if (i == idx) return iter.data; + + return NULL; +} + +EAPI unsigned int +ecore_x_visual_id_get(Ecore_X_Visual visual) +{ + return ((xcb_visualtype_t *)visual)->visual_id; +} + +/** + * Retrieve the default Visual. + * + * @param disp The Display to get the Default Visual from + * @param screen The Screen. + * + * @return The default visual. + * @since 1.1.0 + */ +EAPI Ecore_X_Visual +ecore_x_default_visual_get(Ecore_X_Display *disp EINA_UNUSED, Ecore_X_Screen *screen) +{ + xcb_screen_t *s; + xcb_depth_iterator_t diter; + xcb_visualtype_iterator_t viter; + + CHECK_XCB_CONN; + + s = (xcb_screen_t *)screen; + diter = xcb_screen_allowed_depths_iterator(s); + for (; diter.rem; xcb_depth_next(&diter)) + { + viter = xcb_depth_visuals_iterator(diter.data); + for (; viter.rem; xcb_visualtype_next(&viter)) + { + if (viter.data->visual_id == s->root_visual) + return viter.data; + } + } + return 0; +} + +/** + * Retrieve the default Colormap. + * + * @param disp The Display to get the Default Colormap from + * @param screen The Screen. + * + * @return The default colormap. + * @since 1.1.0 + */ +EAPI Ecore_X_Colormap +ecore_x_default_colormap_get(Ecore_X_Display *disp EINA_UNUSED, Ecore_X_Screen *screen) +{ + xcb_screen_t *s; + + s = (xcb_screen_t *)screen; + return s->default_colormap; +} + +/** + * Retrieve the default depth. + * + * @param disp The Display to get the Default Depth from + * @param screen The Screen. + * + * @return The default depth. + * @since 1.1.0 + */ +EAPI int +ecore_x_default_depth_get(Ecore_X_Display *disp EINA_UNUSED, Ecore_X_Screen *screen) +{ + xcb_screen_t *s; + + s = (xcb_screen_t *)screen; + return s->root_depth; +} + +EAPI void +ecore_x_xkb_select_group(int group) +{ + // XXX: implement me */ +} + +/** + * Sets the timeout for a double and triple clicks to be flagged. + * + * This sets the time between clicks before the double_click flag is + * set in a button down event. If 3 clicks occur within double this + * time, the triple_click flag is also set. + * + * @param t The time in seconds + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI void +ecore_x_double_click_time_set(double t) +{ + if (t < 0.0) t = 0.0; + _ecore_xcb_double_click_time = t; +} + +/** + * Retrieves the double and triple click flag timeout. + * + * See @ref ecore_x_double_click_time_set for more information. + * + * @return The timeout for double clicks in seconds. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI double +ecore_x_double_click_time_get(void) +{ + return _ecore_xcb_double_click_time; +} + +/* local function prototypes */ +static int +_ecore_xcb_shutdown(Eina_Bool close_display) +{ + if (--_ecore_xcb_init_count != 0) + return _ecore_xcb_init_count; + + if (!_ecore_xcb_conn) + return _ecore_xcb_init_count; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + ecore_idle_enterer_del(_ecore_xcb_idle_enterer); + _ecore_xcb_idle_enterer = NULL; + + if (_ecore_xcb_fd_handler) + ecore_main_fd_handler_del(_ecore_xcb_fd_handler); + + /* disconnect from display server */ + if (close_display) + xcb_disconnect(_ecore_xcb_conn); + else + { + close(xcb_get_file_descriptor(_ecore_xcb_conn)); + _ecore_xcb_conn = NULL; + } + + /* shutdown events */ + _ecore_xcb_events_shutdown(); + + /* shutdown input extension */ + _ecore_xcb_input_shutdown(); + + /* shutdown gesture extension */ + _ecore_xcb_gesture_shutdown(); + + /* shutdown selection */ + _ecore_xcb_selection_shutdown(); + + /* shutdown dnd */ + _ecore_xcb_dnd_shutdown(); + + /* shutdown netwm */ + ecore_x_netwm_shutdown(); + + /* shutdown keymap */ + _ecore_xcb_keymap_shutdown(); + + /* shutdown ecore_event */ + ecore_event_shutdown(); + + /* shutdown ecore */ + ecore_shutdown(); + + /* unregister log domain */ + eina_log_domain_unregister(_ecore_xcb_log_dom); + _ecore_xcb_log_dom = -1; + + /* shutdown eina */ + eina_shutdown(); + + return _ecore_xcb_init_count; +} + +static Eina_Bool +_ecore_xcb_fd_handle(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + xcb_connection_t *conn; + xcb_generic_event_t *ev = NULL; + + conn = (xcb_connection_t *)data; + + if (_ecore_xcb_event_buffered) + { + _ecore_xcb_events_handle(_ecore_xcb_event_buffered); + free(_ecore_xcb_event_buffered); + _ecore_xcb_event_buffered = NULL; + } + +// xcb_flush(conn); + + while ((ev = xcb_poll_for_event(conn))) + { + /* NB: Ecore Xlib uses filterevent for xim, but xcb does not support + * xim, so no need for it here */ + + /* check for errors first */ + if (xcb_connection_has_error(conn)) + { + xcb_generic_error_t *err; + + err = (xcb_generic_error_t *)ev; + _ecore_xcb_io_error_handle(err); + } + else + { + /* FIXME: Filter event for XIM */ + _ecore_xcb_events_handle(ev); + free(ev); + } + } + + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_ecore_xcb_fd_handle_buff(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + xcb_connection_t *conn; + xcb_generic_event_t *ev = NULL; + + conn = (xcb_connection_t *)data; + ev = xcb_poll_for_event(conn); + if (ev) + { + /* check for errors first */ + if (xcb_connection_has_error(conn)) + { + xcb_generic_error_t *err; + + err = (xcb_generic_error_t *)ev; + _ecore_xcb_io_error_handle(err); + return ECORE_CALLBACK_CANCEL; + } + _ecore_xcb_event_buffered = ev; + return ECORE_CALLBACK_RENEW; + } + return ECORE_CALLBACK_CANCEL; +} + +static Eina_Bool +_ecore_xcb_idle_enter(void *data EINA_UNUSED) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_flush(_ecore_xcb_conn); + return ECORE_CALLBACK_RENEW; +} diff --git a/src/lib/ecore_x/xcb/ecore_xcb_atoms.c b/src/lib/ecore_x/xcb/ecore_xcb_atoms.c new file mode 100644 index 0000000000..c8c217eec7 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_atoms.c @@ -0,0 +1,149 @@ +#include "ecore_xcb_private.h" +#include "ecore_x_atoms_decl.h" + +/* NB: Increment if you add new atoms */ +#define ECORE_X_ATOMS_COUNT 199 + +/* local function prototypes */ + +/* local variables */ +static xcb_intern_atom_cookie_t cookies[ECORE_X_ATOMS_COUNT]; + +void +_ecore_xcb_atoms_init(void) +{ + int i = 0, num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + num = (sizeof(atom_items) / sizeof(Atom_Item)); + for (i = 0; i < num; i++) + { + cookies[i] = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, + strlen(atom_items[i].name), atom_items[i].name); + } +} + +void +_ecore_xcb_atoms_finalize(void) +{ + int i = 0, num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + num = (sizeof(atom_items) / sizeof(Atom_Item)); + for (i = 0; i < num; i++) + { + xcb_intern_atom_reply_t *reply = NULL; + + if (!(reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], 0))) + continue; + *(atom_items[i].atom) = reply->atom; + free(reply); + } +} + +/** + * @defgroup Ecore_X_Atom_Group XCB Atom Functions + * + * Functions that operate on atoms + */ + +/** + * Retrieves the atom value associated to a name. + * + * @param name Unused. + * @return Associated atom value. + * + * Retrieves the atom value associated to a name. The reply is the + * returned value of the function ecore_xcb_intern_atom_reply(). If + * @p reply is @c NULL, the NULL atom is returned. Otherwise, the atom + * associated to the name is returned. + * + * @ingroup Ecore_X_Atom_Group + */ +EAPI Ecore_X_Atom +ecore_x_atom_get(const char *name) +{ + xcb_intern_atom_cookie_t cookie; + xcb_intern_atom_reply_t *reply; + Ecore_X_Atom a; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(name), name); + reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return XCB_ATOM_NONE; + a = reply->atom; + free(reply); + return a; +} + +/** + * Retrieves the name of the given atom. + * + * @param atom + * @return The name of the atom. + * + * @ingroup Ecore_X_Atom_Group + */ +EAPI char * +ecore_x_atom_name_get(Ecore_X_Atom atom) +{ + xcb_get_atom_name_cookie_t cookie; + xcb_get_atom_name_reply_t *reply; + char *name; + int len = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, atom); + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + len = xcb_get_atom_name_name_length(reply); + name = (char *)malloc(sizeof(char) * (len + 1)); + if (!name) + { + free(reply); + return NULL; + } + memcpy(name, xcb_get_atom_name_name(reply), len); + name[len] = '\0'; + + free(reply); + return name; +} + +EAPI void +ecore_x_atoms_get(const char **names, + int num, + Ecore_X_Atom *atoms) +{ + xcb_intern_atom_cookie_t cookies[num]; + int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + for (i = 0; i < num; i++) + { + cookies[i] = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, + strlen(names[i]), names[i]); + } + for (i = 0; i < num; i++) + { + xcb_intern_atom_reply_t *reply = NULL; + + if (!(reply = xcb_intern_atom_reply(_ecore_xcb_conn, cookies[i], 0))) + continue; + atoms[i] = reply->atom; + free(reply); + } +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_composite.c b/src/lib/ecore_x/xcb/ecore_xcb_composite.c new file mode 100644 index 0000000000..0d3b44e4aa --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_composite.c @@ -0,0 +1,290 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_COMPOSITE +# include <xcb/composite.h> +#endif + +/* local variables */ +static Eina_Bool _composite_avail = EINA_FALSE; + +void +_ecore_xcb_composite_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_COMPOSITE + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_composite_id); +#endif +} + +void +_ecore_xcb_composite_finalize(void) +{ +#ifdef ECORE_XCB_COMPOSITE + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_COMPOSITE + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_composite_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_composite_query_version_cookie_t cookie; + xcb_composite_query_version_reply_t *reply; + + cookie = + xcb_composite_query_version_unchecked(_ecore_xcb_conn, + XCB_COMPOSITE_MAJOR_VERSION, + XCB_COMPOSITE_MINOR_VERSION); + reply = + xcb_composite_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { +// if ((reply->major_version >= XCB_COMPOSITE_MAJOR_VERSION) && + if (reply->minor_version >= XCB_COMPOSITE_MINOR_VERSION) + { +# ifdef ECORE_XCB_RENDER + if (_ecore_xcb_render_avail_get()) + { +# ifdef ECORE_XCB_XFIXES + if (_ecore_xcb_xfixes_avail_get()) + _composite_avail = EINA_TRUE; +# endif + } +# endif + } + + free(reply); + } + } +#endif +} + +/** + * @defgroup Ecore_X_Composite_Group X Composite Extension Functions + * + * Functions related to the X Composite Extension + */ + +/** + * Return whether the Composite Extension is available + * + * @return @c EINA_TRUE is the Composite Extension is available, @c EINA_FALSE + * if not. + * + * @ingroup Ecore_X_Composite_Group + */ +EAPI Eina_Bool +ecore_x_composite_query(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _composite_avail; +} + +EAPI void +ecore_x_composite_redirect_window(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_COMPOSITE + uint8_t update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = XCB_COMPOSITE_REDIRECT_MANUAL; + break; + } + xcb_composite_redirect_window(_ecore_xcb_conn, win, update); +// ecore_x_flush(); +#endif +} + +EAPI void +ecore_x_composite_redirect_subwindows(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_COMPOSITE + uint8_t update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = XCB_COMPOSITE_REDIRECT_MANUAL; + break; + } + xcb_composite_redirect_subwindows(_ecore_xcb_conn, win, update); +// ecore_x_flush(); +#endif +} + +EAPI void +ecore_x_composite_unredirect_window(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_COMPOSITE + uint8_t update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = XCB_COMPOSITE_REDIRECT_MANUAL; + break; + } + xcb_composite_unredirect_window(_ecore_xcb_conn, win, update); +// ecore_x_flush(); +#endif +} + +EAPI void +ecore_x_composite_unredirect_subwindows(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_COMPOSITE + uint8_t update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = XCB_COMPOSITE_REDIRECT_AUTOMATIC; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = XCB_COMPOSITE_REDIRECT_MANUAL; + break; + } + xcb_composite_unredirect_subwindows(_ecore_xcb_conn, win, update); +// ecore_x_flush(); +#endif +} + +EAPI Ecore_X_Pixmap +ecore_x_composite_name_window_pixmap_get(Ecore_X_Window win) +{ +#ifdef ECORE_XCB_COMPOSITE + Ecore_X_Pixmap pmap = XCB_NONE; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return XCB_NONE; + +#ifdef ECORE_XCB_COMPOSITE + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_composite_name_window_pixmap(_ecore_xcb_conn, win, pmap); +// ecore_x_flush(); +#endif + + return pmap; +} + +EAPI void +ecore_x_composite_window_events_disable(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_SHAPE + ecore_x_window_shape_input_rectangle_set(win, -1, -1, 1, 1); +// ecore_x_flush(); +#else + return; + win = 0; +#endif +} + +EAPI void +ecore_x_composite_window_events_enable(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_SHAPE + ecore_x_window_shape_input_rectangle_set(win, 0, 0, 65535, 65535); +// ecore_x_flush(); +#else + return; + win = 0; +#endif +} + +EAPI Ecore_X_Window +ecore_x_composite_render_window_enable(Ecore_X_Window root) +{ + Ecore_X_Window win = 0; +#ifdef ECORE_XCB_COMPOSITE + xcb_composite_get_overlay_window_cookie_t cookie; + xcb_composite_get_overlay_window_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return 0; + +#ifdef ECORE_XCB_COMPOSITE + cookie = xcb_composite_get_overlay_window_unchecked(_ecore_xcb_conn, root); + reply = + xcb_composite_get_overlay_window_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return win; + + win = reply->overlay_win; + free(reply); + + ecore_x_composite_window_events_disable(win); +// ecore_x_flush(); +#endif + + return win; +} + +EAPI void +ecore_x_composite_render_window_disable(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_composite_avail) return; + +#ifdef ECORE_XCB_COMPOSITE + xcb_composite_release_overlay_window(_ecore_xcb_conn, win); +// ecore_x_flush(); +#endif +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_cursor.c b/src/lib/ecore_x/xcb/ecore_xcb_cursor.c new file mode 100644 index 0000000000..755df04e4f --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_cursor.c @@ -0,0 +1,400 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_CURSOR +# include <xcb/render.h> +# include <xcb/xcb_renderutil.h> +#endif + +/* local function prototypes */ +#ifdef ECORE_XCB_CURSOR +static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format_get(void); +#endif +static void _ecore_xcb_cursor_default_size_get(void); +static void _ecore_xcb_cursor_dpi_size_get(void); +static void _ecore_xcb_cursor_guess_size(void); +#ifdef ECORE_XCB_CURSOR +static Ecore_X_Cursor _ecore_xcb_cursor_image_load_cursor(xcb_image_t *img, + int hot_x, + int hot_y); +#endif +static void _ecore_xcb_cursor_image_destroy(xcb_image_t *img); + +/* local variables */ +static int _ecore_xcb_cursor_size = 0; +static Eina_Bool _ecore_xcb_cursor = EINA_FALSE; +#ifdef ECORE_XCB_CURSOR +static uint32_t _ecore_xcb_cursor_format_id = 0; +// static xcb_render_pictforminfo_t *_ecore_xcb_cursor_format = NULL; +#endif + +void +_ecore_xcb_cursor_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* NB: No-op */ +} + +void +_ecore_xcb_cursor_finalize(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_CURSOR + _ecore_xcb_cursor = _ecore_xcb_render_argb_get(); + + /* find render pict format */ + if (_ecore_xcb_cursor_format_id <= 0) + _ecore_xcb_cursor_format_id = _ecore_xcb_cursor_format_get()->id; +#endif + + /* try to grab cursor size from XDefaults */ + _ecore_xcb_cursor_default_size_get(); + + /* if that failed, try to get it from Xft Dpi setting */ + if (_ecore_xcb_cursor_size == 0) + _ecore_xcb_cursor_dpi_size_get(); + + /* if that failed, try to guess from display size */ + if (_ecore_xcb_cursor_size == 0) + _ecore_xcb_cursor_guess_size(); + + /* NB: Would normally add theme stuff here, but E cursor does not support + * xcursor themes. Delay parsing that stuff out until such time if/when the + * user selects to use X Cursor, rather than E cursor */ +} + +EAPI Eina_Bool +ecore_x_cursor_color_supported_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_cursor; +} + +EAPI Ecore_X_Cursor +ecore_x_cursor_new(Ecore_X_Window win, + int *pixels, + int w, + int h, + int hot_x, + int hot_y) +{ + Ecore_X_Cursor cursor = 0; + xcb_image_t *img; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_CURSOR + if (_ecore_xcb_cursor) + { + img = _ecore_xcb_image_create_native(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, + 32, NULL, (w * h * sizeof(int)), + (uint8_t *)pixels); + cursor = _ecore_xcb_cursor_image_load_cursor(img, hot_x, hot_y); + _ecore_xcb_cursor_image_destroy(img); + return cursor; + } + else +#endif + { + Ecore_X_GC gc; + xcb_pixmap_t pmap, mask; + uint32_t *pix; + uint8_t fr = 0x00, fg = 0x00, fb = 0x00; + uint8_t br = 0xff, bg = 0xff, bb = 0xff; + uint32_t brightest = 0, darkest = 255 * 3; + uint16_t x, y; + const uint32_t dither[2][2] = + { + {0, 2}, + {3, 1} + }; + + img = _ecore_xcb_image_create_native(w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, + 1, NULL, ~0, NULL); + if (img->data) free(img->data); + img->data = malloc(img->size); + + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, 1, pmap, win, w, h); + mask = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, 1, mask, win, w, h); + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint8_t r, g, b, a; + + a = (pix[0] >> 24) & 0xff; + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8) & 0xff; + b = (pix[0]) & 0xff; + if (a > 0) + { + if ((uint32_t)(r + g + b) > brightest) + { + brightest = r + g + b; + br = r; + bg = g; + bb = b; + } + + if ((uint32_t)(r + g + b) < darkest) + { + darkest = r + g + b; + fr = r; + fg = g; + fb = b; + } + } + pix++; + } + } + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint32_t v; + uint8_t r, g, b; + int32_t d1, d2; + + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8) & 0xff; + b = (pix[0]) & 0xff; + d1 = + ((r - fr) * (r - fr)) + + ((g - fg) * (g - fg)) + + ((b - fb) * (b - fb)); + d2 = + ((r - br) * (r - br)) + + ((g - bg) * (g - bg)) + + ((b - bb) * (b - bb)); + if (d1 + d2) + { + v = (((d2 * 255) / (d1 + d2)) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) + v = 1; + else + v = 0; + } + else + v = 0; + + xcb_image_put_pixel(img, x, y, v); + pix++; + } + } + + gc = ecore_x_gc_new(pmap, 0, NULL); + xcb_put_image(_ecore_xcb_conn, img->format, pmap, gc, w, h, + 0, 0, 0, img->depth, img->size, img->data); + ecore_x_gc_free(gc); + + pix = (uint32_t *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + uint32_t v; + + v = (((pix[0] >> 24) & 0xff) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) + v = 1; + else + v = 0; + + xcb_image_put_pixel(img, x, y, v); + pix++; + } + } + + gc = ecore_x_gc_new(mask, 0, NULL); + xcb_put_image(_ecore_xcb_conn, img->format, mask, gc, w, h, + 0, 0, 0, img->depth, img->size, img->data); + ecore_x_gc_free(gc); + + if (img->data) free(img->data); + _ecore_xcb_cursor_image_destroy(img); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_create_cursor(_ecore_xcb_conn, cursor, pmap, mask, + fr << 8 | fr, fg << 8 | fg, fb << 8 | fb, + br << 8 | br, bg << 8 | bg, bb << 8 | bb, + hot_x, hot_y); + + xcb_free_pixmap(_ecore_xcb_conn, pmap); + xcb_free_pixmap(_ecore_xcb_conn, mask); + + return cursor; + } + + return 0; +} + +EAPI void +ecore_x_cursor_free(Ecore_X_Cursor c) +{ +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_free_cursor(_ecore_xcb_conn, c); +} + +/* + * Returns the cursor for the given shape. + * Note that the return value must not be freed with + * ecore_x_cursor_free()! + */ +EAPI Ecore_X_Cursor +ecore_x_cursor_shape_get(int shape) +{ + Ecore_X_Cursor cursor = 0; + xcb_font_t font; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + font = xcb_generate_id(_ecore_xcb_conn); + xcb_open_font(_ecore_xcb_conn, font, strlen("cursor"), "cursor"); + + cursor = xcb_generate_id(_ecore_xcb_conn); + /* FIXME: Add request check ?? */ + xcb_create_glyph_cursor(_ecore_xcb_conn, cursor, font, font, + shape, shape + 1, 0, 0, 0, 65535, 65535, 65535); + + xcb_close_font(_ecore_xcb_conn, font); + return cursor; +} + +EAPI void +ecore_x_cursor_size_set(int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_cursor_size = size; + /* NB: May need to adjust size of current cursors here */ +} + +EAPI int +ecore_x_cursor_size_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_cursor_size; +} + +/* local functions */ +#ifdef ECORE_XCB_CURSOR +static xcb_render_pictforminfo_t * +_ecore_xcb_cursor_format_get(void) +{ + const xcb_render_query_pict_formats_reply_t *reply; + xcb_render_pictforminfo_t *ret = NULL; + + CHECK_XCB_CONN; + + reply = xcb_render_util_query_formats(_ecore_xcb_conn); + if (reply) + ret = xcb_render_util_find_standard_format(reply, + XCB_PICT_STANDARD_ARGB_32); + + return ret; +} + +#endif + +static void +_ecore_xcb_cursor_default_size_get(void) +{ + char *s = NULL; + int v = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + s = getenv("XCURSOR_SIZE"); + if (!s) + { + _ecore_xcb_xdefaults_init(); + v = _ecore_xcb_xdefaults_int_get("Xcursor", "size"); + _ecore_xcb_xdefaults_shutdown(); + } + else + v = atoi(s); + if (v) _ecore_xcb_cursor_size = ((v * 16) / 72); +} + +static void +_ecore_xcb_cursor_dpi_size_get(void) +{ + int v = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_xdefaults_init(); + v = _ecore_xcb_xdefaults_int_get("Xft", "dpi"); + if (v) _ecore_xcb_cursor_size = ((v * 16) / 72); + _ecore_xcb_xdefaults_shutdown(); +} + +static void +_ecore_xcb_cursor_guess_size(void) +{ + int w = 0, h = 0, s = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_screen_size_get(_ecore_xcb_screen, &w, &h); + if (h < w) s = h; + else s = w; + _ecore_xcb_cursor_size = (s / 48); +} + +#ifdef ECORE_XCB_CURSOR +static Ecore_X_Cursor +_ecore_xcb_cursor_image_load_cursor(xcb_image_t *img, + int hot_x, + int hot_y) +{ + Ecore_X_Cursor cursor = 0; + Ecore_X_GC gc; + xcb_pixmap_t pmap; + xcb_render_picture_t pict; + + CHECK_XCB_CONN; + + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, img->depth, pmap, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + img->width, img->height); + + gc = ecore_x_gc_new(pmap, 0, NULL); + xcb_put_image(_ecore_xcb_conn, img->format, pmap, gc, + img->width, img->height, 0, 0, 0, img->depth, + img->size, img->data); + ecore_x_gc_free(gc); + + pict = xcb_generate_id(_ecore_xcb_conn); + xcb_render_create_picture(_ecore_xcb_conn, pict, pmap, + _ecore_xcb_cursor_format_id, 0, NULL); + xcb_free_pixmap(_ecore_xcb_conn, pmap); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_render_create_cursor(_ecore_xcb_conn, cursor, pict, hot_x, hot_y); + xcb_render_free_picture(_ecore_xcb_conn, pict); + + return cursor; +} + +#endif + +static void +_ecore_xcb_cursor_image_destroy(xcb_image_t *img) +{ + CHECK_XCB_CONN; + if (img) xcb_image_destroy(img); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_damage.c b/src/lib/ecore_x/xcb/ecore_xcb_damage.c new file mode 100644 index 0000000000..deb3b9cb49 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_damage.c @@ -0,0 +1,155 @@ +#include "ecore_xcb_private.h" +# ifdef ECORE_XCB_DAMAGE +# include <xcb/damage.h> +# endif + +/* local variables */ +static Eina_Bool _damage_avail = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_damage = -1; + +void +_ecore_xcb_damage_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_DAMAGE + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_damage_id); +#endif +} + +void +_ecore_xcb_damage_finalize(void) +{ +#ifdef ECORE_XCB_DAMAGE + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_DAMAGE + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_damage_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_damage_query_version_cookie_t cookie; + xcb_damage_query_version_reply_t *reply; + + cookie = + xcb_damage_query_version_unchecked(_ecore_xcb_conn, + XCB_DAMAGE_MAJOR_VERSION, + XCB_DAMAGE_MINOR_VERSION); + reply = xcb_damage_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + _damage_avail = EINA_TRUE; + free(reply); + } + + if (_damage_avail) + _ecore_xcb_event_damage = ext_reply->first_event; + } +#endif +} + +/** + * @defgroup Ecore_X_Damage_Group X Damage Extension Functions + * + * Functions related to the X Damage Extension. + */ + +EAPI Eina_Bool +ecore_x_damage_query(void) +{ + return _damage_avail; +} + +/** + * Create a damage object + * + * @param drawable The drawable to monitor + * @param level The level of the damage report + * @return The damage object + * + * Creates a damage object to monitor changes to @p drawable, + * with the level @p level. + * + * @ingroup Ecore_X_Damage_Group + */ +EAPI Ecore_X_Damage +ecore_x_damage_new(Ecore_X_Drawable drawable, + Ecore_X_Damage_Report_Level level) +{ + Ecore_X_Damage damage = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_damage_avail) return 0; + +#ifdef ECORE_XCB_DAMAGE + damage = xcb_generate_id(_ecore_xcb_conn); + xcb_damage_create(_ecore_xcb_conn, damage, drawable, level); +// ecore_x_flush(); +#endif + + return damage; +} + +/** + * Destroy a damage object + * + * @param damage The damage object to destroy + * + * Destroys the damage object @p damage + * + * @ingroup Ecore_X_Damage_Group + */ +EAPI void +ecore_x_damage_free(Ecore_X_Damage damage) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_damage_avail) return; + +#ifdef ECORE_XCB_DAMAGE + xcb_damage_destroy(_ecore_xcb_conn, damage); +// ecore_x_flush(); +#endif +} + +/** + * Synchronously modifies the region + * + * @param damage The damage object to destroy + * @param repair The repair region + * @param parts The parts region + * + * Synchronously modifies the regions in the following manner: + * If @p repair is @c XCB_NONE: + * 1) parts = damage + * 2) damage = \<empty\> + * Otherwise: + * 1) parts = damage INTERSECT repair + * 2) damage = damage - parts + * 3) Generate DamageNotify for remaining damage areas + * + * @ingroup Ecore_X_Damage_Group + */ +EAPI void +ecore_x_damage_subtract(Ecore_X_Damage damage, + Ecore_X_Region repair, + Ecore_X_Region parts) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_damage_avail) return; + +#ifdef ECORE_XCB_DAMAGE + xcb_damage_subtract(_ecore_xcb_conn, damage, repair, parts); +// ecore_x_flush(); +#endif +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_dnd.c b/src/lib/ecore_x/xcb/ecore_xcb_dnd.c new file mode 100644 index 0000000000..80ae6b4c5d --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_dnd.c @@ -0,0 +1,688 @@ +#include "ecore_xcb_private.h" + +#ifndef MIN +# define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +/* local structures */ +typedef struct _Version_Cache_Item +{ + Ecore_X_Window win; + int ver; +} Version_Cache_Item; + +/* local function prototypes */ +static Eina_Bool _ecore_xcb_dnd_converter_copy(char *target EINA_UNUSED, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *tprop EINA_UNUSED, + int *count EINA_UNUSED); + +/* local variables */ +static int _ecore_xcb_dnd_init_count = 0; +static Ecore_X_DND_Source *_source = NULL; +static Ecore_X_DND_Target *_target = NULL; +static Version_Cache_Item *_version_cache = NULL; +static int _version_cache_num = 0, _version_cache_alloc = 0; +static void (*_posupdatecb)(void *, + Ecore_X_Xdnd_Position *); +static void *_posupdatedata; + +/* external variables */ +EAPI int ECORE_X_EVENT_XDND_ENTER = 0; +EAPI int ECORE_X_EVENT_XDND_POSITION = 0; +EAPI int ECORE_X_EVENT_XDND_STATUS = 0; +EAPI int ECORE_X_EVENT_XDND_LEAVE = 0; +EAPI int ECORE_X_EVENT_XDND_DROP = 0; +EAPI int ECORE_X_EVENT_XDND_FINISHED = 0; + +void +_ecore_xcb_dnd_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!_ecore_xcb_dnd_init_count) + { + _source = calloc(1, sizeof(Ecore_X_DND_Source)); + if (!_source) return; + _source->version = ECORE_X_DND_VERSION; + _source->win = XCB_NONE; + _source->dest = XCB_NONE; + _source->state = ECORE_X_DND_SOURCE_IDLE; + _source->prev.window = 0; + + _target = calloc(1, sizeof(Ecore_X_DND_Target)); + if (!_target) + { + free(_source); + _source = NULL; + return; + } + _target->win = XCB_NONE; + _target->source = XCB_NONE; + _target->state = ECORE_X_DND_TARGET_IDLE; + + ECORE_X_EVENT_XDND_ENTER = ecore_event_type_new(); + ECORE_X_EVENT_XDND_POSITION = ecore_event_type_new(); + ECORE_X_EVENT_XDND_STATUS = ecore_event_type_new(); + ECORE_X_EVENT_XDND_LEAVE = ecore_event_type_new(); + ECORE_X_EVENT_XDND_DROP = ecore_event_type_new(); + ECORE_X_EVENT_XDND_FINISHED = ecore_event_type_new(); + } + _ecore_xcb_dnd_init_count++; +} + +void +_ecore_xcb_dnd_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_dnd_init_count--; + if (_ecore_xcb_dnd_init_count > 0) return; + if (_source) free(_source); + _source = NULL; + if (_target) free(_target); + _target = NULL; + _ecore_xcb_dnd_init_count = 0; +} + +EAPI void +ecore_x_dnd_send_status(Eina_Bool will_accept, + Eina_Bool suppress, + Ecore_X_Rectangle rect, + Ecore_X_Atom action) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) return; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + _target->will_accept = will_accept; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.type = ECORE_X_ATOM_XDND_STATUS; + ev.format = 32; + ev.window = _target->source; + ev.data.data32[0] = _target->win; + ev.data.data32[1] = 0; + if (will_accept) ev.data.data32[1] |= 0x1UL; + if (!suppress) ev.data.data32[1] |= 0x2UL; + + ev.data.data32[2] = rect.x; + ev.data.data32[2] <<= 16; + ev.data.data32[2] |= rect.y; + ev.data.data32[3] = rect.width; + ev.data.data32[3] <<= 16; + ev.data.data32[3] |= rect.height; + + if (will_accept) + ev.data.data32[4] = action; + else + ev.data.data32[4] = XCB_NONE; + _target->accepted_action = action; + + xcb_send_event(_ecore_xcb_conn, 0, _target->source, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI Eina_Bool +ecore_x_dnd_drop(void) +{ + xcb_client_message_event_t ev; + Eina_Bool status = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + if (_source->dest) + { + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = _source->dest; + + if (_source->will_accept) + { + ev.type = ECORE_X_ATOM_XDND_DROP; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + ev.data.data32[2] = _source->time; + + xcb_send_event(_ecore_xcb_conn, 0, _source->dest, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + _source->state = ECORE_X_DND_SOURCE_DROPPED; + status = EINA_TRUE; + } + else + { + ev.type = ECORE_X_ATOM_XDND_LEAVE; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, _source->dest, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + _source->state = ECORE_X_DND_SOURCE_IDLE; + } + } + else + { + ecore_x_selection_xdnd_clear(); + _source->state = ECORE_X_DND_SOURCE_IDLE; + } + + ecore_x_window_ignore_set(_source->win, 0); + _source->prev.window = 0; + + return status; +} + +EAPI void +ecore_x_dnd_aware_set(Ecore_X_Window win, + Eina_Bool on) +{ + Ecore_X_Atom prop_data = ECORE_X_DND_VERSION; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (on) + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE, + ECORE_X_ATOM_ATOM, 32, &prop_data, 1); + else + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE); +} + +EAPI int +ecore_x_dnd_version_get(Ecore_X_Window win) +{ + unsigned char *data; + int num = 0; + Version_Cache_Item *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (_source->state == ECORE_X_DND_SOURCE_DRAGGING) + { + if (_version_cache) + { + int i = 0; + + for (i = 0; i < _version_cache_num; i++) + { + if (_version_cache[i].win == win) + return _version_cache[i].ver; + } + } + } + + if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE, + ECORE_X_ATOM_ATOM, 32, &data, &num)) + { + int version = 0; + + version = (int)*data; + free(data); + if (_source->state == ECORE_X_DND_SOURCE_DRAGGING) + { + _version_cache_num++; + if (_version_cache_num > _version_cache_alloc) + _version_cache_alloc += 16; + t = realloc(_version_cache, + _version_cache_alloc * sizeof(Version_Cache_Item)); + if (!t) return 0; + _version_cache = t; + _version_cache[_version_cache_num - 1].win = win; + _version_cache[_version_cache_num - 1].ver = version; + } + return version; + } + + if (_source->state == ECORE_X_DND_SOURCE_DRAGGING) + { + _version_cache_num++; + if (_version_cache_num > _version_cache_alloc) + _version_cache_alloc += 16; + t = realloc(_version_cache, + _version_cache_alloc * sizeof(Version_Cache_Item)); + if (!t) return 0; + _version_cache = t; + _version_cache[_version_cache_num - 1].win = win; + _version_cache[_version_cache_num - 1].ver = 0; + } + + return 0; +} + +EAPI Eina_Bool +ecore_x_dnd_type_isset(Ecore_X_Window win, + const char *type) +{ + int num = 0, i = 0; + Eina_Bool ret = EINA_FALSE; + unsigned char *data; + Ecore_X_Atom *atoms, atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, &data, &num)) + return ret; + + atom = ecore_x_atom_get(type); + atoms = (Ecore_X_Atom *)data; + for (i = 0; i < num; ++i) + { + if (atom == atoms[i]) + { + ret = EINA_TRUE; + break; + } + } + + free(data); + return ret; +} + +EAPI void +ecore_x_dnd_type_set(Ecore_X_Window win, + const char *type, + Eina_Bool on) +{ + Ecore_X_Atom atom, *oldset = NULL, *newset = NULL; + int i = 0, j = 0, num = 0; + unsigned char *data = NULL, *old_data = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + atom = ecore_x_atom_get(type); + ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, &old_data, &num); + oldset = (Ecore_X_Atom *)old_data; + if (on) + { + if (ecore_x_dnd_type_isset(win, type)) + { + free(old_data); + return; + } + newset = calloc(num + 1, sizeof(Ecore_X_Atom)); + if (!newset) return; + data = (unsigned char *)newset; + for (i = 0; i < num; i++) + newset[i + 1] = oldset[i]; + newset[0] = atom; + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, data, num + 1); + } + else + { + if (!ecore_x_dnd_type_isset(win, type)) + { + free(old_data); + return; + } + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); + if (!newset) + { + free(old_data); + return; + } + data = (unsigned char *)newset; + for (i = 0; i < num; i++) + if (oldset[i] != atom) + newset[j++] = oldset[i]; + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, data, num - 1); + } + free(oldset); + free(newset); +} + +EAPI void +ecore_x_dnd_types_set(Ecore_X_Window win, + const char **types, + unsigned int num_types) +{ + Ecore_X_Atom *newset = NULL; + unsigned int i; + unsigned char *data = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!num_types) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_TYPE_LIST); + else + { + newset = calloc(num_types, sizeof(Ecore_X_Atom)); + if (!newset) return; + + data = (unsigned char *)newset; + for (i = 0; i < num_types; i++) + { + newset[i] = ecore_x_atom_get(types[i]); + ecore_x_selection_converter_atom_add(newset[i], + _ecore_xcb_dnd_converter_copy); + } + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, data, + num_types); + free(newset); + } +} + +EAPI void +ecore_x_dnd_actions_set(Ecore_X_Window win, + Ecore_X_Atom *actions, + unsigned int num_actions) +{ + unsigned int i; + unsigned char *data = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!num_actions) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_ACTION_LIST); + else + { + data = (unsigned char *)actions; + for (i = 0; i < num_actions; i++) + ecore_x_selection_converter_atom_add(actions[i], + _ecore_xcb_dnd_converter_copy); + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_ACTION_LIST, + ECORE_X_ATOM_ATOM, 32, data, + num_actions); + } +} + +/** + * The DND position update cb is called Ecore_X sends a DND position to a + * client. + * + * It essentially mirrors some of the data sent in the position message. + * Generally this cb should be set just before position update is called. + * Please note well you need to look after your own data pointer if someone + * trashes you position update cb set. + * + * It is considered good form to clear this when the dnd event finishes. + * + * @param cb Callback to updated each time ecore_x sends a position update. + * @param data User data. + */ +EAPI void +ecore_x_dnd_callback_pos_update_set(void (*cb)(void *, Ecore_X_Xdnd_Position *data), + const void *data) +{ + _posupdatecb = cb; + _posupdatedata = (void *)data; +} + +EAPI Eina_Bool +ecore_x_dnd_begin(Ecore_X_Window source, + unsigned char *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_dnd_version_get(source)) return EINA_FALSE; + + /* Take ownership of XdndSelection */ + if (!ecore_x_selection_xdnd_set(source, data, size)) return EINA_FALSE; + + if (_version_cache) + { + free(_version_cache); + _version_cache = NULL; + _version_cache_num = 0; + _version_cache_alloc = 0; + } + + ecore_x_window_shadow_tree_flush(); + + _source->win = source; + ecore_x_window_ignore_set(_source->win, 1); + _source->state = ECORE_X_DND_SOURCE_DRAGGING; + _source->time = _ecore_xcb_events_last_time_get(); + _source->prev.window = 0; + + /* Default Accepted Action: move */ + _source->action = ECORE_X_ATOM_XDND_ACTION_MOVE; + _source->accepted_action = XCB_NONE; + _source->dest = XCB_NONE; + + return EINA_TRUE; +} + +EAPI void +ecore_x_dnd_send_finished(void) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) return; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.type = ECORE_X_ATOM_XDND_FINISHED; + ev.window = _target->source; + ev.data.data32[0] = _target->win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + if (_target->will_accept) + { + ev.data.data32[1] |= 0x1UL; + ev.data.data32[2] = _target->accepted_action; + } + + xcb_send_event(_ecore_xcb_conn, 0, _target->source, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + _target->state = ECORE_X_DND_TARGET_IDLE; +} + +EAPI void +ecore_x_dnd_source_action_set(Ecore_X_Atom action) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _source->action = action; + if (_source->prev.window) + _ecore_xcb_dnd_drag(_source->prev.window, + _source->prev.x, _source->prev.y); +} + +Ecore_X_DND_Source * +_ecore_xcb_dnd_source_get(void) +{ + return _source; +} + +Ecore_X_DND_Target * +_ecore_xcb_dnd_target_get(void) +{ + return _target; +} + +void +_ecore_xcb_dnd_drag(Ecore_X_Window root, + int x, + int y) +{ + xcb_client_message_event_t ev; + Ecore_X_Window win, *skip; + Ecore_X_Xdnd_Position pos; + int num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (_source->state != ECORE_X_DND_SOURCE_DRAGGING) return; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + + skip = ecore_x_window_ignore_list(&num); + win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num); + while ((win) && !(ecore_x_dnd_version_get(win))) + win = ecore_x_window_shadow_parent_get(root, win); + + if ((_source->dest) && (win != _source->dest)) + { + ev.window = _source->dest; + ev.type = ECORE_X_ATOM_XDND_LEAVE; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, _source->dest, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + _source->suppress = 0; + } + + if (win) + { + int x1, x2, y1, y2; + + _source->version = MIN(ECORE_X_DND_VERSION, + ecore_x_dnd_version_get(win)); + if (win != _source->dest) + { + int i = 0; + unsigned char *data; + Ecore_X_Atom *types; + + ecore_x_window_prop_property_get(_source->win, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, + &data, &num); + types = (Ecore_X_Atom *)data; + ev.window = win; + ev.type = ECORE_X_ATOM_XDND_ENTER; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + if (num > 3) + ev.data.data32[1] |= 0x1UL; + else + ev.data.data32[1] &= 0xfffffffeUL; + ev.data.data32[1] |= ((unsigned long)_source->version) << 24; + + for (i = 2; i < 5; i++) + ev.data.data32[i] = 0; + for (i = 0; i < MIN(num, 3); ++i) + ev.data.data32[i + 2] = types[i]; + free(data); + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + _source->await_status = 0; + _source->will_accept = 0; + } + + x1 = _source->rectangle.x; + x2 = _source->rectangle.x + _source->rectangle.width; + y1 = _source->rectangle.y; + y2 = _source->rectangle.y + _source->rectangle.height; + + if ((!_source->await_status) || (!_source->suppress) || + ((x < x1) || (x > x2) || (y < y1) || (y > y2))) + { + ev.window = win; + ev.type = ECORE_X_ATOM_XDND_POSITION; + ev.data.data32[0] = _source->win; + ev.data.data32[1] = 0; + ev.data.data32[2] = ((x << 16) & 0xffff0000) | (y & 0xffff); + ev.data.data32[3] = _source->time; + ev.data.data32[4] = _source->action; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + _source->await_status = 1; + } + } + + if (_posupdatecb) + { + pos.position.x = x; + pos.position.y = y; + pos.win = win; + pos.prev = _source->dest; + _posupdatecb(_posupdatedata, &pos); + } + + _source->prev.x = x; + _source->prev.y = y; + _source->prev.window = root; + _source->dest = win; +} + +EAPI Ecore_X_Atom +ecore_x_dnd_source_action_get(void) +{ + return _source->action; +} + +/* local functions */ +static Eina_Bool +_ecore_xcb_dnd_converter_copy(char *target EINA_UNUSED, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *tprop EINA_UNUSED, + int *count EINA_UNUSED) +{ + Ecore_Xcb_Textproperty text_prop; + Ecore_Xcb_Encoding_Style style = XcbTextStyle; + char *mystr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((!data) || (!size)) return EINA_FALSE; + + mystr = calloc(1, size + 1); + if (!mystr) return EINA_FALSE; + + memcpy(mystr, data, size); + if (_ecore_xcb_mb_textlist_to_textproperty(&mystr, 1, style, &text_prop)) + { + int len; + + len = strlen((char *)text_prop.value) + 1; + if (!(*data_ret = malloc(len))) + { + free(mystr); + return EINA_FALSE; + } + memcpy(*data_ret, text_prop.value, len); + *size_ret = len; + free(text_prop.value); + free(mystr); + return EINA_TRUE; + } + else + { + free(mystr); + return EINA_FALSE; + } +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_dpms.c b/src/lib/ecore_x/xcb/ecore_xcb_dpms.c new file mode 100644 index 0000000000..39ef589dd1 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_dpms.c @@ -0,0 +1,320 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_DAMAGE +# include <xcb/dpms.h> +#endif + +/* local variables */ +static Eina_Bool _dpms_avail = EINA_FALSE; + +void +_ecore_xcb_dpms_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_DPMS + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_dpms_id); +#endif +} + +void +_ecore_xcb_dpms_finalize(void) +{ +#ifdef ECORE_XCB_DPMS + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_DPMS + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_dpms_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_dpms_get_version_cookie_t cookie; + xcb_dpms_get_version_reply_t *reply; + + cookie = + xcb_dpms_get_version_unchecked(_ecore_xcb_conn, + XCB_DPMS_MAJOR_VERSION, + XCB_DPMS_MINOR_VERSION); + reply = xcb_dpms_get_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if (reply->server_major_version >= 1) + _dpms_avail = EINA_TRUE; + free(reply); + } + } +#endif +} + +/** + * @defgroup Ecore_X_DPMS_Group X DPMS Extension Functions + * + * Functions related to the X DPMS Extension + */ + +/** + * Checks if the DPMS extension is available or not. + * + * @return @c EINA_TRUE if the DPMS extension is available, + * @c EINA_FALSE otherwise. + * + * Return @c EINA_TRUE if the X server supports the DPMS Extension version 1.0, + * @c EINA_FALSE otherwise. + * + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_query(void) +{ +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _dpms_avail; +} + +/** + * Checks if the X server is capable of DPMS. + * @return @c 1 if the X server is capable of DPMS, @c 0 otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_capable_get(void) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_DPMS + xcb_dpms_capable_cookie_t cookie; + xcb_dpms_capable_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_dpms_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_DPMS + cookie = xcb_dpms_capable_unchecked(_ecore_xcb_conn); + reply = xcb_dpms_capable_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + ret = reply->capable; + free(reply); + } +#endif + + return ret; +} + +/** + * Checks the DPMS state of the display. + * @return @c EINA_TRUE if DPMS is enabled, @c EINA_FALSE otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_enabled_get(void) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_DPMS + xcb_dpms_info_cookie_t cookie; + xcb_dpms_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_dpms_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_DPMS + cookie = xcb_dpms_info_unchecked(_ecore_xcb_conn); + reply = xcb_dpms_info_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + if (reply->state) ret = EINA_TRUE; + free(reply); +#endif + + return ret; +} + +/** + * Sets the DPMS state of the display. + * @param enabled @c 0 to disable DPMS characteristics of the server, enable it otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_enabled_set(int enabled) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_dpms_avail) return; + +#ifdef ECORE_XCB_DPMS + if (enabled) + xcb_dpms_enable(_ecore_xcb_conn); + else + xcb_dpms_disable(_ecore_xcb_conn); +#endif +} + +/** + * Gets the timeouts. The values are in unit of seconds. + * @param standby Amount of time of inactivity before standby mode will be invoked. + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * @param off Amount of time of inactivity before the monitor is shut off. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeouts_get(unsigned int *standby, + unsigned int *suspend, + unsigned int *off) +{ +#ifdef ECORE_XCB_DPMS + xcb_dpms_get_timeouts_cookie_t cookie; + xcb_dpms_get_timeouts_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (standby) *standby = 0; + if (suspend) *suspend = 0; + if (off) *off = 0; + + if (!_dpms_avail) return; + +#ifdef ECORE_XCB_DPMS + cookie = xcb_dpms_get_timeouts_unchecked(_ecore_xcb_conn); + reply = xcb_dpms_get_timeouts_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + if (standby) *standby = reply->standby_timeout; + if (suspend) *suspend = reply->suspend_timeout; + if (off) *off = reply->off_timeout; + free(reply); +#endif +} + +/** + * Sets the timeouts. The values are in unit of seconds. + * + * @param standby Amount of time of inactivity before standby mode will be invoked. + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * @param off Amount of time of inactivity before the monitor is shut off. + * @return @c EINA_TRUE on success, @c EINA_FALSE on failure. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_timeouts_set(unsigned int standby, + unsigned int suspend, + unsigned int off) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_dpms_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_DPMS + // FIXME: Add request check + xcb_dpms_set_timeouts(_ecore_xcb_conn, standby, suspend, off); + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + +/** + * Returns the amount of time of inactivity before standby mode is invoked. + * @return The standby timeout value. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_standby_get(void) +{ + unsigned int standby = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_dpms_timeouts_get(&standby, NULL, NULL); + return standby; +} + +/** + * Returns the amount of time of inactivity before the second level of + * power saving is invoked. + * @return The suspend timeout value. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_suspend_get(void) +{ + unsigned int suspend = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_dpms_timeouts_get(NULL, &suspend, NULL); + return suspend; +} + +/** + * Returns the amount of time of inactivity before the third and final + * level of power saving is invoked. + * @return The off timeout value. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_off_get(void) +{ + unsigned int off = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_dpms_timeouts_get(NULL, NULL, &off); + return off; +} + +/** + * Sets the standby timeout (in unit of seconds). + * @param new_timeout Amount of time of inactivity before standby mode will be invoked. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_standby_set(unsigned int new_timeout) +{ + unsigned int standby = 0, suspend = 0, off = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_dpms_timeouts_get(&standby, &suspend, &off); + ecore_x_dpms_timeouts_set(new_timeout, suspend, off); +} + +/** + * Sets the suspend timeout (in unit of seconds). + * @param new_timeout Amount of time of inactivity before the screen is placed into suspend mode. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_suspend_set(unsigned int new_timeout) +{ + unsigned int standby = 0, suspend = 0, off = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_dpms_timeouts_get(&standby, &suspend, &off); + ecore_x_dpms_timeouts_set(standby, new_timeout, off); +} + +/** + * Sets the off timeout (in unit of seconds). + * @param new_timeout Amount of time of inactivity before the monitor is shut off. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_off_set(unsigned int new_timeout) +{ + unsigned int standby = 0, suspend = 0, off = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_dpms_timeouts_get(&standby, &suspend, &off); + ecore_x_dpms_timeouts_set(standby, suspend, new_timeout); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_drawable.c b/src/lib/ecore_x/xcb/ecore_xcb_drawable.c new file mode 100644 index 0000000000..4e9a3564ce --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_drawable.c @@ -0,0 +1,123 @@ +#include "ecore_xcb_private.h" + +/** + * @defgroup Ecore_X_Drawable_Group X Drawable Functions + * + * Functions that operate on drawables. + */ + +/** + * Fill the specified rectangle on a drawable. + * @param d The given drawable. + * @param gc The graphic context that controls the fill rules. + * @param x The X coordinate of the top-left corner of the rectangle. + * @param y The Y coordinate of the top-left corner of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + */ +EAPI void +ecore_x_drawable_rectangle_fill(Ecore_X_Drawable draw, + Ecore_X_GC gc, + int x, + int y, + int w, + int h) +{ + xcb_rectangle_t rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_poly_fill_rectangle(_ecore_xcb_conn, draw, gc, 1, + (const xcb_rectangle_t *)&rect); +// ecore_x_flush(); +} + +/** + * Retrieves the geometry of the given drawable. + * @param d The given drawable. + * @param x Pointer to an integer into which the X position is to be stored. + * @param y Pointer to an integer into which the Y position is to be stored. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI void +ecore_x_drawable_geometry_get(Ecore_X_Drawable draw, + int *x, + int *y, + int *w, + int *h) +{ + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = 0; + if (h) *h = 0; + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, draw); + reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + if (x) *x = reply->x; + if (y) *y = reply->y; + if (w) *w = (int)reply->width; + if (h) *h = (int)reply->height; + free(reply); +} + +/** + * Retrieves the width of the border of the given drawable. + * @param d The given drawable. + * @return The border width of the given drawable. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI int +ecore_x_drawable_border_width_get(Ecore_X_Drawable d) +{ + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, d); + reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + ret = (int)reply->border_width; + free(reply); + return ret; +} + +/** + * Retrieves the depth of the given drawable. + * @param d The given drawable. + * @return The depth of the given drawable. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI int +ecore_x_drawable_depth_get(Ecore_X_Drawable d) +{ + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, d); + reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + ret = (int)reply->depth; + free(reply); + return ret; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_e.c b/src/lib/ecore_x/xcb/ecore_xcb_e.c new file mode 100644 index 0000000000..82d94b634f --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_e.c @@ -0,0 +1,1576 @@ +#include "ecore_xcb_private.h" + +/* local function prototypes */ +static Ecore_X_Atom _ecore_xcb_e_vkbd_atom_get(Ecore_X_Virtual_Keyboard_State state); +static Ecore_X_Virtual_Keyboard_State _ecore_xcb_e_vkbd_state_get(Ecore_X_Atom atom); +static Ecore_X_Atom _ecore_xcb_e_quickpanel_atom_get(Ecore_X_Illume_Quickpanel_State state); +static Ecore_X_Illume_Quickpanel_State _ecore_xcb_e_quickpanel_state_get(Ecore_X_Atom atom); +static Ecore_X_Atom _ecore_xcb_e_illume_atom_get(Ecore_X_Illume_Mode mode); +static Ecore_X_Illume_Mode _ecore_xcb_e_illume_mode_get(Ecore_X_Atom atom); +static Ecore_X_Atom _ecore_xcb_e_indicator_atom_get(Ecore_X_Illume_Indicator_State state); +static Ecore_X_Illume_Indicator_State _ecore_xcb_e_indicator_state_get(Ecore_X_Atom atom); + +EAPI void +ecore_x_e_init(void) +{ +} + +EAPI void +ecore_x_e_comp_sync_draw_done_send(Ecore_X_Window root, + Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE; + ev.data.data32[0] = win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_sync_draw_size_done_send(Ecore_X_Window root, + Ecore_X_Window win, + int w, + int h) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE; + ev.data.data32[0] = win; + ev.data.data32[1] = 1; + ev.data.data32[2] = w; + ev.data.data32[3] = h; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_sync_counter_set(Ecore_X_Window win, + Ecore_X_Sync_Counter counter) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (counter) + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER, + ECORE_X_ATOM_CARDINAL, &counter, 1); + else + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER); +} + +EAPI Ecore_X_Sync_Counter +ecore_x_e_comp_sync_counter_get(Ecore_X_Window win) +{ + Ecore_X_Sync_Counter counter = 0; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = ecore_x_window_prop_xid_get(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER, + ECORE_X_ATOM_CARDINAL, &counter, 1); + if (ret != 1) return 0; + return counter; +} + +EAPI Eina_Bool +ecore_x_e_comp_sync_supported_get(Ecore_X_Window root) +{ + Ecore_X_Window win, win2; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + ret = + ecore_x_window_prop_xid_get(root, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + if ((ret == 1) && (win)) + { + ret = + ecore_x_window_prop_xid_get(win, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win2, 1); + if ((ret == 1) && (win2 == win)) + return EINA_TRUE; + } + return EINA_FALSE; +} + +EAPI void +ecore_x_e_window_profile_list_set(Ecore_X_Window win, + const char **profiles, + unsigned int num_profiles) +{ + Ecore_X_Atom *atoms; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!win) + return; + + if (!num_profiles) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_PROFILE_LIST); + else + { + atoms = alloca(num_profiles * sizeof(Ecore_X_Atom)); + ecore_x_atoms_get(profiles, num_profiles, atoms); + ecore_x_window_prop_property_set(win, + ECORE_X_ATOM_E_PROFILE_LIST, + ECORE_X_ATOM_ATOM, 32, (void *)atoms, + num_profiles); + } +} + +EAPI Eina_Bool +ecore_x_e_window_profile_list_get(Ecore_X_Window win, + const char ***profiles, + int *ret_num) +{ + unsigned char *data = NULL; + Ecore_X_Atom *atoms; + int num, i; + + if (ret_num) + *ret_num = 0; + + if (profiles) + *profiles = NULL; + + if (!win) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_E_PROFILE_LIST, + ECORE_X_ATOM_ATOM, 32, &data, &num)) + return EINA_FALSE; + + if (ret_num) + *ret_num = num; + + if (profiles) + { + (*profiles) = calloc(num, sizeof(char *)); + if (!(*profiles)) + { + if (ret_num) + *ret_num = 0; + + if (data) + free(data); + + return EINA_FALSE; + } + + atoms = (Ecore_X_Atom *)data; + for (i = 0; i < num; i++) + (*profiles)[i] = ecore_x_atom_name_get(atoms[i]); + } + + if (data) + free(data); + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_window_profile_set(Ecore_X_Window win, + const char *profile) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!win) + return; + + if (!profile) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_PROFILE); + else + { + atom = ecore_x_atom_get(profile); + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_E_PROFILE, + ECORE_X_ATOM_ATOM, 32, (void *)&atom, 1); + } +} + +EAPI char * +ecore_x_e_window_profile_get(Ecore_X_Window win) +{ + Ecore_X_Atom *atom = NULL; + unsigned char *data; + char *profile = NULL; + int num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_E_PROFILE, + ECORE_X_ATOM_ATOM, 32, &data, &num)) + return NULL; + + if (data) + atom = (Ecore_X_Atom *)data; + + if (atom) + profile = ecore_x_atom_name_get(atom[0]); + + return profile; +} + +EAPI void +ecore_x_e_comp_sync_supported_set(Ecore_X_Window root, + Eina_Bool enabled) +{ + Ecore_X_Window win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + if (enabled) + { + win = ecore_x_window_new(root, 1, 2, 3, 4); + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + ecore_x_window_prop_xid_set(root, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + } + else + { + int ret = 0; + + ret = ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + if ((ret == 1) && (win)) + { + ecore_x_window_prop_property_del(root, + ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED); + ecore_x_window_free(win); + } + } +} + +EAPI void +ecore_x_e_comp_sync_begin_send(Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_SYNC_BEGIN; + ev.data.data32[0] = win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_sync_end_send(Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_SYNC_END; + ev.data.data32[0] = win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_sync_cancel_send(Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_SYNC_CANCEL; + ev.data.data32[0] = win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_flush_send(Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_FLUSH; + ev.data.data32[0] = win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_dump_send(Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_E_COMP_DUMP; + ev.data.data32[0] = win; + ev.data.data32[1] = 0; + ev.data.data32[2] = 0; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_e_comp_pixmap_set(Ecore_X_Window win, + Ecore_X_Pixmap pixmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (pixmap) + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_PIXMAP, + ECORE_X_ATOM_PIXMAP, &pixmap, 1); + else + ecore_x_window_prop_property_del(win, pixmap); +} + +EAPI Ecore_X_Pixmap +ecore_x_e_comp_pixmap_get(Ecore_X_Window win) +{ + Ecore_X_Pixmap pixmap = 0; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = ecore_x_window_prop_xid_get(win, ECORE_X_ATOM_E_COMP_PIXMAP, + ECORE_X_ATOM_PIXMAP, &pixmap, 1); + if (ret != 1) return 0; + return pixmap; +} + +EAPI void +ecore_x_e_frame_size_set(Ecore_X_Window win, + int fl, + int fr, + int ft, + int fb) +{ + uint32_t frames[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + frames[0] = fl; + frames[1] = fr; + frames[2] = ft; + frames[3] = fb; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_FRAME_SIZE, frames, 4); +} + +EAPI Ecore_X_Virtual_Keyboard_State +ecore_x_e_virtual_keyboard_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE, + &atom, 1)) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN; + + return _ecore_xcb_e_vkbd_state_get(atom); +} + +EAPI void +ecore_x_e_virtual_keyboard_state_set(Ecore_X_Window win, + Ecore_X_Virtual_Keyboard_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + atom = _ecore_xcb_e_vkbd_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE, + &atom, 1); +} + +EAPI void +ecore_x_e_virtual_keyboard_state_send(Ecore_X_Window win, + Ecore_X_Virtual_Keyboard_State state) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_xcb_e_vkbd_atom_get(state), + 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_virtual_keyboard_set(Ecore_X_Window win, + unsigned int is_keyboard) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD, + &is_keyboard, 1); +} + +EAPI Eina_Bool +ecore_x_e_virtual_keyboard_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI int +ecore_x_e_illume_quickpanel_priority_major_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR, + &val, 1)) + return 0; + + return val; +} + +EAPI void +ecore_x_e_illume_quickpanel_priority_major_set(Ecore_X_Window win, + unsigned int priority) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR, + &priority, 1); +} + +EAPI int +ecore_x_e_illume_quickpanel_priority_minor_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR, + &val, 1)) + return 0; + + return val; +} + +EAPI void +ecore_x_e_illume_quickpanel_priority_minor_set(Ecore_X_Window win, + unsigned int priority) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR, + &priority, 1); +} + +EAPI void +ecore_x_e_illume_quickpanel_zone_set(Ecore_X_Window win, + unsigned int zone) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE, + &zone, 1); +} + +EAPI int +ecore_x_e_illume_quickpanel_zone_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE, + &val, 1)) + return 0; + + return val; +} + +EAPI void +ecore_x_e_illume_quickpanel_position_update_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI Eina_Bool +ecore_x_e_illume_conformant_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_CONFORMANT, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_conformant_set(Ecore_X_Window win, + unsigned int is_conformant) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_CONFORMANT, + &is_conformant, 1); +} + +EAPI void +ecore_x_e_illume_softkey_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_softkey_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = 0; + if (h) *h = 0; + + if (ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY, + geom, 4) != 4) + return EINA_FALSE; + + if (x) *x = geom[0]; + if (y) *y = geom[1]; + if (w) *w = geom[2]; + if (h) *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_illume_indicator_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_indicator_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = 0; + if (h) *h = 0; + + if (ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY, + geom, 4) != 4) + return EINA_FALSE; + + if (x) *x = geom[0]; + if (y) *y = geom[1]; + if (w) *w = geom[2]; + if (h) *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_illume_keyboard_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_keyboard_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = 0; + if (h) *h = 0; + + if (ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY, + geom, 4) != 4) + return EINA_FALSE; + + if (x) *x = geom[0]; + if (y) *y = geom[1]; + if (w) *w = geom[2]; + if (h) *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_illume_quickpanel_set(Ecore_X_Window win, + unsigned int is_quickpanel) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL, + &is_quickpanel, 1); +} + +EAPI Eina_Bool +ecore_x_e_illume_quickpanel_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_quickpanel_state_set(Ecore_X_Window win, + Ecore_X_Illume_Quickpanel_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + atom = _ecore_xcb_e_quickpanel_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Quickpanel_State +ecore_x_e_illume_quickpanel_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE, + &atom, 1)) + return ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN; + + return _ecore_xcb_e_quickpanel_state_get(atom); +} + +EAPI void +ecore_x_e_illume_quickpanel_state_send(Ecore_X_Window win, + Ecore_X_Illume_Quickpanel_State state) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_xcb_e_quickpanel_atom_get(state), + 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_quickpanel_state_toggle(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 0, 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_xcb_e_clipboard_atom_get(Ecore_X_Illume_Clipboard_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_CLIPBOARD_STATE_ON: + return ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON; + case ECORE_X_ILLUME_CLIPBOARD_STATE_OFF: + return ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF; + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Clipboard_State +_ecore_xcb_e_clipboard_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON) + return ECORE_X_ILLUME_CLIPBOARD_STATE_ON; + + if (atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF) + return ECORE_X_ILLUME_CLIPBOARD_STATE_OFF; + + return ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_clipboard_state_set(Ecore_X_Window win, + Ecore_X_Illume_Clipboard_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_xcb_e_clipboard_atom_get(state); + + ecore_x_window_prop_atom_set(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Clipboard_State +ecore_x_e_illume_clipboard_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE, + &atom, 1)) + return ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN; + return _ecore_xcb_e_clipboard_state_get(atom); +} + +EAPI void +ecore_x_e_illume_clipboard_geometry_set(Ecore_X_Window win, + int x, int y, int w, int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_clipboard_geometry_get(Ecore_X_Window win, + int *x, int *y, int *w, int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY, + geom, 4); + if (ret != 4) return EINA_FALSE; + + if (x) *x = geom[0]; + if (y) *y = geom[1]; + if (w) *w = geom[2]; + if (h) *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_illume_mode_set(Ecore_X_Window win, + Ecore_X_Illume_Mode mode) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + atom = _ecore_xcb_e_illume_atom_get(mode); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_MODE, &atom, 1); +} + +EAPI Ecore_X_Illume_Mode +ecore_x_e_illume_mode_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_ILLUME_MODE, &atom, 1)) + return ECORE_X_ILLUME_MODE_UNKNOWN; + + return _ecore_xcb_e_illume_mode_get(atom); +} + +EAPI void +ecore_x_e_illume_mode_send(Ecore_X_Window win, + Ecore_X_Illume_Mode mode) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_MODE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_xcb_e_illume_atom_get(mode), + 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_focus_back_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_BACK, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_focus_forward_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_focus_home_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_HOME, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_close_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_CLOSE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_home_new_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_HOME_NEW, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_home_del_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_HOME_DEL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_next_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_prev_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_activate_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_read_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_read_next_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_read_prev_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_up_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_down_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_drag_set(Ecore_X_Window win, + unsigned int drag) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_DRAG, &drag, 1); +} + +EAPI void +ecore_x_e_illume_drag_locked_set(Ecore_X_Window win, + unsigned int is_locked) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED, + &is_locked, 1); +} + +EAPI Eina_Bool +ecore_x_e_illume_drag_locked_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_e_illume_drag_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_DRAG, &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_drag_start_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_DRAG_START, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_drag_end_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_DRAG_END, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_zone_set(Ecore_X_Window win, + Ecore_X_Window zone) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(win, ECORE_X_ATOM_E_ILLUME_ZONE, &zone, 1); +} + +EAPI Ecore_X_Window +ecore_x_e_illume_zone_get(Ecore_X_Window win) +{ + Ecore_X_Window zone; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_window_get(win, ECORE_X_ATOM_E_ILLUME_ZONE, + &zone, 1)) + return 0; + + return zone; +} + +EAPI void +ecore_x_e_illume_zone_list_set(Ecore_X_Window win, + Ecore_X_Window *zones, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(win, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, + zones, num); +} + +/* local functions */ +static Ecore_X_Atom +_ecore_xcb_e_vkbd_atom_get(Ecore_X_Virtual_Keyboard_State state) +{ + switch (state) + { + case ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_ON: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_IP: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_URL: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME; + + default: + break; + } + return 0; +} + +static Ecore_X_Virtual_Keyboard_State +_ecore_xcb_e_vkbd_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_ON; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_IP; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_URL; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD; + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME; + + return ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_xcb_e_quickpanel_atom_get(Ecore_X_Illume_Quickpanel_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_QUICKPANEL_STATE_ON: + return ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON; + + case ECORE_X_ILLUME_QUICKPANEL_STATE_OFF: + return ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Quickpanel_State +_ecore_xcb_e_quickpanel_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON) + return ECORE_X_ILLUME_QUICKPANEL_STATE_ON; + if (atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF) + return ECORE_X_ILLUME_QUICKPANEL_STATE_OFF; + + return ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_xcb_e_illume_atom_get(Ecore_X_Illume_Mode mode) +{ + switch (mode) + { + case ECORE_X_ILLUME_MODE_SINGLE: + return ECORE_X_ATOM_E_ILLUME_MODE_SINGLE; + + case ECORE_X_ILLUME_MODE_DUAL_TOP: + return ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP; + + case ECORE_X_ILLUME_MODE_DUAL_LEFT: + return ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT; + + default: + break; + } + return ECORE_X_ILLUME_MODE_UNKNOWN; +} + +static Ecore_X_Illume_Mode +_ecore_xcb_e_illume_mode_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_MODE_SINGLE) + return ECORE_X_ILLUME_MODE_SINGLE; + if (atom == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP) + return ECORE_X_ILLUME_MODE_DUAL_TOP; + if (atom == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT) + return ECORE_X_ILLUME_MODE_DUAL_LEFT; + + return ECORE_X_ILLUME_MODE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_xcb_e_indicator_atom_get(Ecore_X_Illume_Indicator_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_INDICATOR_STATE_ON: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_ON; + + case ECORE_X_ILLUME_INDICATOR_STATE_OFF: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Indicator_State +_ecore_xcb_e_indicator_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_ON) + return ECORE_X_ILLUME_INDICATOR_STATE_ON; + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF) + return ECORE_X_ILLUME_INDICATOR_STATE_OFF; + + return ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_indicator_state_set(Ecore_X_Window win, + Ecore_X_Illume_Indicator_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + atom = _ecore_xcb_e_indicator_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Indicator_State +ecore_x_e_illume_indicator_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE, + &atom, 1)) + return ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN; + + return _ecore_xcb_e_indicator_state_get(atom); +} + +EAPI void +ecore_x_e_illume_indicator_state_send(Ecore_X_Window win, + Ecore_X_Illume_Indicator_State state) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_xcb_e_indicator_atom_get(state), + 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_x_e_indicator_opacity_atom_get(Ecore_X_Illume_Indicator_Opacity_Mode mode) +{ + switch (mode) + { + case ECORE_X_ILLUME_INDICATOR_OPAQUE: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE; + + case ECORE_X_ILLUME_INDICATOR_TRANSLUCENT: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT; + + case ECORE_X_ILLUME_INDICATOR_TRANSPARENT: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Indicator_Opacity_Mode +_ecore_x_e_indicator_opacity_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE) + return ECORE_X_ILLUME_INDICATOR_OPAQUE; + + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT) + return ECORE_X_ILLUME_INDICATOR_TRANSLUCENT; + + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT) + return ECORE_X_ILLUME_INDICATOR_TRANSPARENT; + + return ECORE_X_ILLUME_INDICATOR_OPACITY_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_indicator_opacity_set(Ecore_X_Window win, + Ecore_X_Illume_Indicator_Opacity_Mode mode) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_indicator_opacity_atom_get(mode); + ecore_x_window_prop_atom_set(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Indicator_Opacity_Mode +ecore_x_e_illume_indicator_opacity_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE, + &atom, 1)) + return ECORE_X_ILLUME_INDICATOR_OPACITY_UNKNOWN; + + return _ecore_x_e_indicator_opacity_get(atom); +} + +EAPI void +ecore_x_e_illume_indicator_opacity_send(Ecore_X_Window win, + Ecore_X_Illume_Indicator_Opacity_Mode mode) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_x_e_indicator_opacity_atom_get(mode), + 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_x_e_illume_window_state_atom_get(Ecore_X_Illume_Window_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_WINDOW_STATE_NORMAL: + return ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL; + + case ECORE_X_ILLUME_WINDOW_STATE_FLOATING: + return ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Window_State +_ecore_x_e_illume_window_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL) + return ECORE_X_ILLUME_WINDOW_STATE_NORMAL; + + if (atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING) + return ECORE_X_ILLUME_WINDOW_STATE_FLOATING; + + return ECORE_X_ILLUME_WINDOW_STATE_NORMAL; +} + +EAPI void +ecore_x_e_illume_window_state_set(Ecore_X_Window win, + Ecore_X_Illume_Window_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_illume_window_state_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_WINDOW_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Window_State +ecore_x_e_illume_window_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_WINDOW_STATE, + &atom, 1)) + return ECORE_X_ILLUME_WINDOW_STATE_NORMAL; + + return _ecore_x_e_illume_window_state_get(atom); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_error.c b/src/lib/ecore_x/xcb/ecore_xcb_error.c new file mode 100644 index 0000000000..fc329265d5 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_error.c @@ -0,0 +1,123 @@ +#include "ecore_xcb_private.h" +#include <xcb/xcb_event.h> + +/* local variables */ +static void (*_error_func)(void *data) = NULL; +static void *_error_data = NULL; +static void (*_io_error_func)(void *data) = NULL; +static void *_io_error_data = NULL; +static int _error_request_code = 0; +static int _error_code = 0; +static Ecore_X_ID _error_resource_id = 0; + +/** + * Set the error handler. + * @param func The error handler function + * @param data The data to be passed to the handler function + * + * Set the X error handler function + */ +EAPI void +ecore_x_error_handler_set(void (*func)(void *data), + const void *data) +{ + _error_func = func; + _error_data = (void *)data; +} + +/** + * Set the I/O error handler. + * @param func The I/O error handler function + * @param data The data to be passed to the handler function + * + * Set the X I/O error handler function + */ +EAPI void +ecore_x_io_error_handler_set(void (*func)(void *data), + const void *data) +{ + _io_error_func = func; + _io_error_data = (void *)data; +} + +/** + * Get the request code that caused the error. + * @return The request code causing the X error + * + * Return the X request code that caused the last X error + */ +EAPI int +ecore_x_error_request_get(void) +{ + return _error_request_code; +} + +/** + * Get the error code from the error. + * @return The error code from the X error + * + * Return the error code from the last X error + */ +EAPI int +ecore_x_error_code_get(void) +{ + return _error_code; +} + +/** + * Get the resource id that caused the error. + * @return The resource id causing the X error + * + * Return the X resource id that caused the last X error + */ +EAPI Ecore_X_ID +ecore_x_error_resource_id_get(void) +{ + return _error_resource_id; +} + +int +_ecore_xcb_error_handle(xcb_generic_error_t *err) +{ + WRN("Got Error:"); + WRN("\tEvent: %s", xcb_event_get_request_label(err->major_code)); + WRN("\tError: %s", xcb_event_get_error_label(err->error_code)); + +#ifdef OLD_XCB_VERSION + if (err->error_code == XCB_EVENT_ERROR_BAD_VALUE) + WRN("\tBad Value: %d", ((xcb_value_error_t *)err)->bad_value); + else if (err->error_code == XCB_EVENT_ERROR_BAD_WINDOW) + WRN("\tBad Window: %d", ((xcb_window_error_t *)err)->bad_value); +#else + if (err->error_code == XCB_VALUE) + WRN("\tBad Value: %d", ((xcb_value_error_t *)err)->bad_value); + else if (err->error_code == XCB_WINDOW) + WRN("\tBad Window: %d", ((xcb_window_error_t *)err)->bad_value); +#endif + + _error_request_code = err->sequence; + _error_code = err->error_code; + _error_resource_id = err->resource_id; + if (_error_func) + _error_func(_error_data); + + return 0; +} + +int +_ecore_xcb_io_error_handle(xcb_generic_error_t *err) +{ + CRIT("IO Error:"); + if (err) + { + CRIT("\tRequest: %d", err->sequence); + CRIT("\tCode: %d", err->error_code); + } + if (_io_error_func) + _io_error_func(_io_error_data); + else + exit(-1); + + return 0; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_events.c b/src/lib/ecore_x/xcb/ecore_xcb_events.c new file mode 100644 index 0000000000..9cc86f62a8 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_events.c @@ -0,0 +1,2824 @@ +#include "ecore_xcb_private.h" +//#include "Ecore_X_Atoms.h" +#include <langinfo.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xcb_event.h> +# ifdef ECORE_XCB_DAMAGE +# include <xcb/damage.h> +# endif +# ifdef ECORE_XCB_RANDR +# include <xcb/randr.h> +# endif +# ifdef ECORE_XCB_SCREENSAVER +# include <xcb/screensaver.h> +# endif +# ifdef ECORE_XCB_SYNC +# include <xcb/sync.h> +# endif +# ifdef ECORE_XCB_XFIXES +# include <xcb/xfixes.h> +# endif +# ifdef ECORE_XCB_XGESTURE +# include <xcb/gesture.h> +# endif + +#ifndef CODESET +# define CODESET "INVALID" +#endif + +typedef struct _Ecore_X_Mouse_Down_Info +{ + EINA_INLIST; + int dev; + Ecore_X_Time last_time; + Ecore_X_Time last_last_time; + Ecore_X_Window last_win; + Ecore_X_Window last_last_win; + Ecore_X_Window last_event_win; + Ecore_X_Window last_last_event_win; + Eina_Bool did_double : 1; + Eina_Bool did_triple : 1; +} Ecore_X_Mouse_Down_Info; + +/* local function prototypes */ +static void _ecore_xcb_event_handle_any_event(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_key_press(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_key_release(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_button_press(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_button_release(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_motion_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_enter_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_leave_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_keymap_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_focus_in(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_focus_out(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_expose(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_graphics_exposure(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_visibility_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_create_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_destroy_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_map_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_unmap_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_map_request(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_reparent_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_configure_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_configure_request(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gravity_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_resize_request(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_circulate_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_circulate_request(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_property_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_selection_clear(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_selection_request(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_selection_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_colormap_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_client_message(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_mapping_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_damage_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_randr_change(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_randr_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_randr_crtc_change(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_randr_output_change(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_randr_output_property_change(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_screensaver_notify(xcb_generic_event_t *event); +#ifdef ECORE_XCB_XGESTURE +static void _ecore_xcb_event_handle_gesture_notify_flick(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gesture_notify_pan(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gesture_notify_pinchrotation(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gesture_notify_tap(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gesture_notify_tapnhold(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gesture_notify_hold(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_gesture_notify_group(xcb_generic_event_t *event); +#endif +#ifdef ECORE_XCB_SHAPE +static void _ecore_xcb_event_handle_shape_change(xcb_generic_event_t *event); +#endif +static void _ecore_xcb_event_handle_sync_counter(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_sync_alarm(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_xfixes_selection_notify(xcb_generic_event_t *event EINA_UNUSED); +static void _ecore_xcb_event_handle_xfixes_cursor_notify(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_generic_event(xcb_generic_event_t *event); +static void _ecore_xcb_event_handle_input_event(xcb_generic_event_t *event); + +static void _ecore_xcb_event_key_press(xcb_generic_event_t *event); +static void _ecore_xcb_event_key_release(xcb_generic_event_t *event); +static void _ecore_xcb_event_mouse_move_free(void *data EINA_UNUSED, + void *event); +static Ecore_X_Event_Mode _ecore_xcb_event_mode_get(uint8_t mode); +static Ecore_X_Event_Detail _ecore_xcb_event_detail_get(uint8_t detail); +static void _ecore_xcb_event_xdnd_enter_free(void *data EINA_UNUSED, + void *event); +static void _ecore_xcb_event_selection_notify_free(void *data EINA_UNUSED, + void *event); +static void _ecore_xcb_event_generic_event_free(void *data, + void *event); +static void _ecore_xcb_event_mouse_down_info_clear(void); +static Ecore_X_Mouse_Down_Info *_ecore_xcb_event_mouse_down_info_get(int dev); + +/* local variables */ +static Eina_Bool _ecore_xcb_event_last_mouse_move = EINA_FALSE; +//static Ecore_Event *_ecore_xcb_event_last_mouse_move_event = NULL; +static Eina_Inlist *_ecore_xcb_mouse_down_info_list = NULL; +static Ecore_X_Time _ecore_xcb_event_last_time; +static Ecore_X_Window _ecore_xcb_event_last_window = 0; + +/* public variables */ +int16_t _ecore_xcb_event_last_root_x = 0; +int16_t _ecore_xcb_event_last_root_y = 0; + +EAPI int ECORE_X_EVENT_ANY = 0; +EAPI int ECORE_X_EVENT_MOUSE_IN = 0; +EAPI int ECORE_X_EVENT_MOUSE_OUT = 0; +EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0; +EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0; +EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0; +EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0; +EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0; +EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0; +EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0; +EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0; +EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_STACK = 0; +EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0; +EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0; +EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0; +EAPI int ECORE_X_EVENT_MAPPING_CHANGE = 0; +EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0; +EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0; +EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0; +EAPI int ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = 0; +EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0; +EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_FLICK = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PAN = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAP = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_HOLD = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_GROUP = 0; +EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0; +EAPI int ECORE_X_EVENT_SYNC_ALARM = 0; +EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0; +EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0; +EAPI int ECORE_X_EVENT_RANDR_CRTC_CHANGE = 0; +EAPI int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = 0; +EAPI int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = 0; +EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0; +EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0; +EAPI int ECORE_X_EVENT_PING = 0; +EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0; +EAPI int ECORE_X_EVENT_XKB_STATE_NOTIFY = 0; +EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0; +EAPI int ECORE_X_EVENT_GENERIC = 0; + +EAPI int ECORE_X_RAW_BUTTON_PRESS = 0; +EAPI int ECORE_X_RAW_BUTTON_RELEASE = 0; +EAPI int ECORE_X_RAW_MOTION = 0; + +void +_ecore_xcb_events_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ECORE_X_EVENT_ANY) + { + ECORE_X_EVENT_ANY = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_IN = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_OUT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_FOCUS_IN = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_FOCUS_OUT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_KEYMAP = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DAMAGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CREATE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DESTROY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_HIDE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHOW = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHOW_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_REPARENT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CONFIGURE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_GRAVITY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STACK = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STACK_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROPERTY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_COLORMAP = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_MAPPING = ecore_event_type_new(); + ECORE_X_EVENT_MAPPING_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_CLEAR = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_CLIENT_MESSAGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHAPE = ecore_event_type_new(); + ECORE_X_EVENT_SCREENSAVER_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_FLICK = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_PAN = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_TAP = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_HOLD = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_GROUP = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_COUNTER = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new(); + ECORE_X_EVENT_SCREEN_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_RANDR_CRTC_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_DAMAGE_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_DESKTOP_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STATE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_PING = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = ecore_event_type_new(); + ECORE_X_EVENT_XKB_STATE_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_GENERIC = ecore_event_type_new(); + + ECORE_X_RAW_BUTTON_PRESS = ecore_event_type_new(); + ECORE_X_RAW_BUTTON_RELEASE = ecore_event_type_new(); + ECORE_X_RAW_MOTION = ecore_event_type_new(); + } +} + +void +_ecore_xcb_events_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_event_mouse_down_info_clear(); + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +// if (_ecore_xcb_event_last_mouse_move_event) +// { +// ecore_event_del(_ecore_xcb_event_last_mouse_move_event); +// _ecore_xcb_event_last_mouse_move_event = NULL; +// } +} + +void +_ecore_xcb_events_handle(xcb_generic_event_t *ev) +{ + uint8_t response = 0; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + /* strip highest bit (set if event is generated) */ + response = (ev->response_type & ~0x80); + if (response == 0) + { + xcb_generic_error_t *err; + + err = (xcb_generic_error_t *)ev; + + /* NB: There is no way to check access of destroyed windows, + * so trap those cases and ignore. We also ignore BadValue from + * xcb_grab/ungrab_button (happens when we are using any_mod) + * and a few others */ +#ifdef OLD_XCB_VERSION + if (err->error_code == XCB_EVENT_ERROR_BAD_WINDOW) return; + else if (err->error_code == XCB_EVENT_ERROR_BAD_MATCH) + { + if ((err->major_code == XCB_SET_INPUT_FOCUS) || + (err->major_code == XCB_CONFIGURE_WINDOW)) + return; + } + else if (err->error_code == XCB_EVENT_ERROR_BAD_VALUE) + { + if ((err->major_code == XCB_KILL_CLIENT) || + (err->major_code == XCB_GRAB_BUTTON) || + (err->major_code == XCB_UNGRAB_BUTTON)) + return; + } +#else + if (err->error_code == XCB_WINDOW) return; + else if (err->error_code == XCB_MATCH) + { + if ((err->major_code == XCB_SET_INPUT_FOCUS) || + (err->major_code == XCB_CONFIGURE_WINDOW)) + return; + } + else if (err->error_code == XCB_VALUE) + { + if ((err->major_code == XCB_KILL_CLIENT) || + (err->major_code == XCB_GRAB_BUTTON) || + (err->major_code == XCB_UNGRAB_BUTTON)) + return; + } +#endif + WRN("Got Event Error:"); + WRN("\tMajor Code: %d", err->major_code); + WRN("\tMinor Code: %d", err->minor_code); + WRN("\tRequest: %s", xcb_event_get_request_label(err->major_code)); + WRN("\tError: %s", xcb_event_get_error_label(err->error_code)); + if (err->error_code == 2) // bad value + WRN("\tValue: %d", ((xcb_value_error_t *)err)->bad_value); + else if (err->error_code == 8) // bad match + WRN("\tMatch: %d", ((xcb_match_error_t *)err)->bad_value); + + if (err->major_code == XCB_SEND_EVENT) + { + WRN("\tSend Event Error"); + WRN("\t\tSeq: %d", ev->sequence); + WRN("\t\tFull Seq: %d", ev->full_sequence); + WRN("\t\tType: %d", ev->response_type); + } + /* if (err->major_code == 148) */ + /* { */ + /* printf("GOT 148 Error\n"); */ + /* } */ + return; + } + + /* FIXME: Filter event for xim when xcb supports xim */ + + _ecore_xcb_event_handle_any_event(ev); + + if (response == XCB_KEY_PRESS) + _ecore_xcb_event_handle_key_press(ev); + else if (response == XCB_KEY_RELEASE) + _ecore_xcb_event_handle_key_release(ev); + else if (response == XCB_BUTTON_PRESS) + _ecore_xcb_event_handle_button_press(ev); + else if (response == XCB_BUTTON_RELEASE) + _ecore_xcb_event_handle_button_release(ev); + else if (response == XCB_MOTION_NOTIFY) + _ecore_xcb_event_handle_motion_notify(ev); + else if (response == XCB_ENTER_NOTIFY) + _ecore_xcb_event_handle_enter_notify(ev); + else if (response == XCB_LEAVE_NOTIFY) + _ecore_xcb_event_handle_leave_notify(ev); + else if (response == XCB_KEYMAP_NOTIFY) + _ecore_xcb_event_handle_keymap_notify(ev); + else if (response == XCB_FOCUS_IN) + _ecore_xcb_event_handle_focus_in(ev); + else if (response == XCB_FOCUS_OUT) + _ecore_xcb_event_handle_focus_out(ev); + else if (response == XCB_EXPOSE) + _ecore_xcb_event_handle_expose(ev); + else if (response == XCB_GRAPHICS_EXPOSURE) + _ecore_xcb_event_handle_graphics_exposure(ev); + else if (response == XCB_VISIBILITY_NOTIFY) + _ecore_xcb_event_handle_visibility_notify(ev); + else if (response == XCB_CREATE_NOTIFY) + _ecore_xcb_event_handle_create_notify(ev); + else if (response == XCB_DESTROY_NOTIFY) + _ecore_xcb_event_handle_destroy_notify(ev); + else if (response == XCB_MAP_NOTIFY) + _ecore_xcb_event_handle_map_notify(ev); + else if (response == XCB_UNMAP_NOTIFY) + _ecore_xcb_event_handle_unmap_notify(ev); + else if (response == XCB_MAP_REQUEST) + _ecore_xcb_event_handle_map_request(ev); + else if (response == XCB_REPARENT_NOTIFY) + _ecore_xcb_event_handle_reparent_notify(ev); + else if (response == XCB_CONFIGURE_NOTIFY) + _ecore_xcb_event_handle_configure_notify(ev); + else if (response == XCB_CONFIGURE_REQUEST) + _ecore_xcb_event_handle_configure_request(ev); + else if (response == XCB_GRAVITY_NOTIFY) + _ecore_xcb_event_handle_gravity_notify(ev); + else if (response == XCB_RESIZE_REQUEST) + _ecore_xcb_event_handle_resize_request(ev); + else if (response == XCB_CIRCULATE_NOTIFY) + _ecore_xcb_event_handle_circulate_notify(ev); + else if (response == XCB_CIRCULATE_REQUEST) + _ecore_xcb_event_handle_circulate_request(ev); + else if (response == XCB_PROPERTY_NOTIFY) + _ecore_xcb_event_handle_property_notify(ev); + else if (response == XCB_SELECTION_CLEAR) + _ecore_xcb_event_handle_selection_clear(ev); + else if (response == XCB_SELECTION_REQUEST) + _ecore_xcb_event_handle_selection_request(ev); + else if (response == XCB_SELECTION_NOTIFY) + _ecore_xcb_event_handle_selection_notify(ev); + else if (response == XCB_COLORMAP_NOTIFY) + _ecore_xcb_event_handle_colormap_notify(ev); + else if (response == XCB_CLIENT_MESSAGE) + _ecore_xcb_event_handle_client_message(ev); + else if (response == XCB_MAPPING_NOTIFY) + _ecore_xcb_event_handle_mapping_notify(ev); + else if (response == 35) /* GenericEvent == 35 */ + _ecore_xcb_event_handle_generic_event(ev); +#ifdef ECORE_XCB_DAMAGE + else if ((_ecore_xcb_event_damage >= 0) && + (response == (_ecore_xcb_event_damage + XCB_DAMAGE_NOTIFY))) + _ecore_xcb_event_handle_damage_notify(ev); +#endif +#ifdef ECORE_XCB_RANDR + else if ((_ecore_xcb_event_randr >= 0) && + (response == + _ecore_xcb_event_randr + XCB_RANDR_SCREEN_CHANGE_NOTIFY)) + _ecore_xcb_event_handle_randr_change(ev); + else if ((_ecore_xcb_event_randr >= 0) && + (response == (_ecore_xcb_event_randr + XCB_RANDR_NOTIFY))) + _ecore_xcb_event_handle_randr_notify(ev); +#endif +#ifdef ECORE_XCB_SCREENSAVER + else if ((_ecore_xcb_event_screensaver >= 0) && + (response == + _ecore_xcb_event_screensaver + XCB_SCREENSAVER_NOTIFY)) + _ecore_xcb_event_handle_screensaver_notify(ev); +#endif +#ifdef ECORE_XCB_XGESTURE + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_FLICK)) + _ecore_xcb_event_handle_gesture_notify_flick(ev); + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_PAN)) + _ecore_xcb_event_handle_gesture_notify_pan(ev); + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_PINCH_ROTATION)) + _ecore_xcb_event_handle_gesture_notify_pinchrotation(ev); + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_TAP)) + _ecore_xcb_event_handle_gesture_notify_tap(ev); + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_TAP_N_HOLD)) + _ecore_xcb_event_handle_gesture_notify_tapnhold(ev); + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_HOLD)) + _ecore_xcb_event_handle_gesture_notify_hold(ev); + else if ((_ecore_xcb_event_gesture >= 0) && + (response == + _ecore_xcb_event_gesture + XCB_GESTURE_NOTIFY_GROUP)) + _ecore_xcb_event_handle_gesture_notify_group(ev); +#endif +#ifdef ECORE_XCB_SHAPE + else if ((_ecore_xcb_event_shape >= 0) && + (response == (_ecore_xcb_event_shape + XCB_SHAPE_NOTIFY))) + _ecore_xcb_event_handle_shape_change(ev); +#endif +#ifdef ECORE_XCB_SYNC + else if ((_ecore_xcb_event_sync >= 0) && + (response == (_ecore_xcb_event_sync + XCB_SYNC_COUNTER_NOTIFY))) + _ecore_xcb_event_handle_sync_counter(ev); + else if ((_ecore_xcb_event_sync >= 0) && + (response == (_ecore_xcb_event_sync + XCB_SYNC_ALARM_NOTIFY))) + _ecore_xcb_event_handle_sync_alarm(ev); +#endif +#ifdef ECORE_XCB_XFIXES + else if ((_ecore_xcb_event_xfixes >= 0) && + (response == + _ecore_xcb_event_xfixes + XCB_XFIXES_SELECTION_NOTIFY)) + _ecore_xcb_event_handle_xfixes_selection_notify(ev); + else if ((_ecore_xcb_event_xfixes >= 0) && + (response == (_ecore_xcb_event_xfixes + XCB_XFIXES_CURSOR_NOTIFY))) + _ecore_xcb_event_handle_xfixes_cursor_notify(ev); +#endif +} + +Ecore_X_Time +_ecore_xcb_events_last_time_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_event_last_time; +} + +EAPI void +ecore_x_event_mask_set(Ecore_X_Window win, + Ecore_X_Event_Mask mask) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, win); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + + list = (mask | reply->your_event_mask); + free(reply); + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_event_mask_unset(Ecore_X_Window win, + Ecore_X_Event_Mask mask) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, win); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + + list = (reply->your_event_mask & ~mask); + free(reply); + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); +// ecore_x_flush(); +} + +unsigned int +_ecore_xcb_events_modifiers_get(unsigned int state) +{ + unsigned int modifiers = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (state & ECORE_X_MODIFIER_SHIFT) + modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + if (state & ECORE_X_MODIFIER_CTRL) + modifiers |= ECORE_EVENT_MODIFIER_CTRL; + if (state & ECORE_X_MODIFIER_ALT) + modifiers |= ECORE_EVENT_MODIFIER_ALT; + if (state & ECORE_X_MODIFIER_WIN) + modifiers |= ECORE_EVENT_MODIFIER_WIN; + if (state & ECORE_X_MODIFIER_ALTGR) + modifiers |= ECORE_EVENT_MODIFIER_ALTGR; + if (state & ECORE_X_LOCK_SCROLL) + modifiers |= ECORE_EVENT_LOCK_SCROLL; + if (state & ECORE_X_LOCK_CAPS) + modifiers |= ECORE_EVENT_LOCK_CAPS; + if (state & ECORE_X_LOCK_NUM) + modifiers |= ECORE_EVENT_LOCK_NUM; + if (state & ECORE_X_LOCK_SHIFT) + modifiers |= ECORE_EVENT_LOCK_SHIFT; + + return modifiers; +} + +/* local functions */ +static void +_ecore_xcb_event_handle_any_event(xcb_generic_event_t *event) +{ + xcb_generic_event_t *ev; + +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ev = malloc(sizeof(xcb_generic_event_t)); + if (!ev) return; + + memcpy(ev, event, sizeof(xcb_generic_event_t)); + ecore_event_add(ECORE_X_EVENT_ANY, ev, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_key_press(xcb_generic_event_t *event) +{ + _ecore_xcb_event_key_press(event); +} + +static void +_ecore_xcb_event_handle_key_release(xcb_generic_event_t *event) +{ + _ecore_xcb_event_key_release(event); +} + +static void +_ecore_xcb_event_handle_button_press(xcb_generic_event_t *event) +{ + xcb_button_press_event_t *ev; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + + ev = (xcb_button_press_event_t *)event; + if ((ev->detail > 3) && (ev->detail < 8)) + { + Ecore_Event_Mouse_Wheel *e; + + if (!(e = malloc(sizeof(Ecore_Event_Mouse_Wheel)))) return; + + e->timestamp = ev->time; + e->modifiers = _ecore_xcb_events_modifiers_get(ev->state); + switch (ev->detail) + { + case 4: + e->direction = 0; + e->z = -1; + break; + + case 5: + e->direction = 0; + e->z = 1; + break; + + case 6: + e->direction = 1; + e->z = -1; + break; + + case 7: + e->direction = 1; + e->z = 1; + break; + + default: + e->direction = 0; + e->z = 0; + break; + } + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) + e->window = ev->child; + else + e->window = ev->event; + + e->event_window = ev->event; + e->same_screen = ev->same_screen; + e->root_window = ev->root; + + _ecore_xcb_event_last_time = e->timestamp; + _ecore_xcb_event_last_window = e->window; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + + ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL); + + _ecore_xcb_window_grab_allow_events(ev->event, ev->child, + ECORE_EVENT_MOUSE_WHEEL, + e, ev->time); + } + else + { + Ecore_Event_Mouse_Button *e; + unsigned int child_win = 0; + + child_win = (ev->child ? ev->child : ev->event); + + _ecore_xcb_event_mouse_move(ev->time, ev->state, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y, + ev->event, child_win, + ev->root, ev->same_screen, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + + e = _ecore_xcb_event_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN, + ev->time, + ev->state, ev->detail, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y, ev->event, + child_win, + ev->root, ev->same_screen, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + if (e) + _ecore_xcb_window_grab_allow_events(ev->event, ev->child, + ECORE_EVENT_MOUSE_BUTTON_DOWN, + e, ev->time); + } +} + +static void +_ecore_xcb_event_handle_button_release(xcb_generic_event_t *event) +{ + xcb_button_release_event_t *ev; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_button_release_event_t *)event; + if ((ev->detail <= 3) || (ev->detail > 7)) + { + _ecore_xcb_event_mouse_move(ev->time, ev->state, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y, + ev->event, + (ev->child ? ev->child : ev->event), + ev->root, ev->same_screen, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + + _ecore_xcb_event_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP, ev->time, + ev->state, ev->detail, + ev->event_x, ev->event_y, ev->root_x, + ev->root_y, ev->event, + (ev->child ? ev->child : ev->event), + ev->root, ev->same_screen, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + } +} + +static void +_ecore_xcb_event_handle_motion_notify(xcb_generic_event_t *event) +{ + xcb_motion_notify_event_t *ev; + + ev = (xcb_motion_notify_event_t *)event; + + /* if (_ecore_xcb_event_last_mouse_move_event) */ + /* { */ + /* ecore_event_del(_ecore_xcb_event_last_mouse_move_event); */ + /* _ecore_xcb_event_last_mouse_move = EINA_FALSE; */ + /* _ecore_xcb_event_last_mouse_move_event = NULL; */ + /* } */ + + _ecore_xcb_event_mouse_move(ev->time, ev->state, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y, + ev->event, + (ev->child ? ev->child : ev->event), + ev->root, ev->same_screen, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + _ecore_xcb_event_last_mouse_move = EINA_TRUE; + + _ecore_xcb_dnd_drag(ev->root, ev->root_x, ev->root_y); +} + +static void +_ecore_xcb_event_handle_enter_notify(xcb_generic_event_t *event) +{ + xcb_enter_notify_event_t *ev; + Ecore_X_Event_Mouse_In *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_enter_notify_event_t *)event; + + _ecore_xcb_event_mouse_move(ev->time, ev->state, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y, + ev->event, + (ev->child ? ev->child : ev->event), + ev->root, ev->same_screen_focus, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Mouse_In)))) return; + + e->modifiers = _ecore_xcb_events_modifiers_get(ev->state); + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) + e->win = ev->child; + else + e->win = ev->event; + e->event_win = ev->event; + e->same_screen = ev->same_screen_focus; + e->root_win = ev->root; + e->mode = _ecore_xcb_event_mode_get(ev->mode); + e->detail = _ecore_xcb_event_detail_get(ev->detail); + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + + ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_leave_notify(xcb_generic_event_t *event) +{ + xcb_leave_notify_event_t *ev; + Ecore_X_Event_Mouse_Out *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_enter_notify_event_t *)event; + + _ecore_xcb_event_mouse_move(ev->time, ev->state, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y, + ev->event, + (ev->child ? ev->child : ev->event), + ev->root, ev->same_screen_focus, + 0, 1, 1, 1.0, 0.0, + ev->event_x, ev->event_y, + ev->root_x, ev->root_y); + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out)))) return; + + e->modifiers = _ecore_xcb_events_modifiers_get(ev->state); + e->x = ev->event_x; + e->y = ev->event_y; + e->root.x = ev->root_x; + e->root.y = ev->root_y; + if (ev->child) + e->win = ev->child; + else + e->win = ev->event; + e->event_win = ev->event; + e->same_screen = ev->same_screen_focus; + e->root_win = ev->root; + e->mode = _ecore_xcb_event_mode_get(ev->mode); + e->detail = _ecore_xcb_event_detail_get(ev->detail); + + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + _ecore_xcb_event_last_window = e->win; + _ecore_xcb_event_last_root_x = e->root.x; + _ecore_xcb_event_last_root_y = e->root.y; + + ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_keymap_notify(xcb_generic_event_t *event EINA_UNUSED) +{ +// LOGFN(__FILE__, __LINE__, __FUNCTION__); + + // FIXME: handle this event type + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +} + +static void +_ecore_xcb_event_handle_focus_in(xcb_generic_event_t *event) +{ + xcb_focus_in_event_t *ev; + Ecore_X_Event_Window_Focus_In *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_focus_in_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In)))) return; + + e->win = ev->event; + e->mode = _ecore_xcb_event_mode_get(ev->mode); + e->detail = _ecore_xcb_event_detail_get(ev->detail); + + e->time = _ecore_xcb_event_last_time; + _ecore_xcb_event_last_time = e->time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_focus_out(xcb_generic_event_t *event) +{ + xcb_focus_out_event_t *ev; + Ecore_X_Event_Window_Focus_Out *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_focus_out_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out)))) return; + + e->win = ev->event; + e->mode = _ecore_xcb_event_mode_get(ev->mode); + e->detail = _ecore_xcb_event_detail_get(ev->detail); + + e->time = _ecore_xcb_event_last_time; + _ecore_xcb_event_last_time = e->time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_expose(xcb_generic_event_t *event) +{ + xcb_expose_event_t *ev; + Ecore_X_Event_Window_Damage *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_expose_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Damage)))) return; + + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->count = ev->count; + + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_graphics_exposure(xcb_generic_event_t *event) +{ + xcb_graphics_exposure_event_t *ev; + Ecore_X_Event_Window_Damage *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_graphics_exposure_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Damage)))) return; + + e->win = ev->drawable; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->count = ev->count; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_visibility_notify(xcb_generic_event_t *event) +{ + xcb_visibility_notify_event_t *ev; + Ecore_X_Event_Window_Visibility_Change *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_visibility_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change)))) + return; + + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + if (ev->state == XCB_VISIBILITY_FULLY_OBSCURED) + e->fully_obscured = 1; + else + e->fully_obscured = 0; + + ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_create_notify(xcb_generic_event_t *event) +{ + xcb_create_notify_event_t *ev; + Ecore_X_Event_Window_Create *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_create_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Create)))) return; + + e->win = ev->window; + e->parent = ev->parent; + if (ev->override_redirect) + e->override = 1; + else + e->override = 0; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->border = ev->border_width; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_destroy_notify(xcb_generic_event_t *event) +{ + xcb_destroy_notify_event_t *ev; + Ecore_X_Event_Window_Destroy *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_destroy_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy)))) return; + + e->win = ev->window; + e->event_win = ev->event; + if (e->win == _ecore_xcb_event_last_window) + _ecore_xcb_event_last_window = 0; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_map_notify(xcb_generic_event_t *event) +{ + xcb_map_notify_event_t *ev; + Ecore_X_Event_Window_Show *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_map_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Show)))) return; + + e->win = ev->window; + e->event_win = ev->event; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_unmap_notify(xcb_generic_event_t *event) +{ + xcb_unmap_notify_event_t *ev; + Ecore_X_Event_Window_Hide *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_unmap_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Hide)))) return; + + e->win = ev->window; + e->event_win = ev->event; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_map_request(xcb_generic_event_t *event) +{ + xcb_map_request_event_t *ev; + Ecore_X_Event_Window_Show_Request *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_map_request_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request)))) return; + + e->win = ev->window; + e->parent = ev->parent; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_reparent_notify(xcb_generic_event_t *event) +{ + xcb_reparent_notify_event_t *ev; + Ecore_X_Event_Window_Reparent *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_reparent_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent)))) return; + + e->win = ev->window; + e->event_win = ev->event; + e->parent = ev->parent; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_configure_notify(xcb_generic_event_t *event) +{ + xcb_configure_notify_event_t *ev; + Ecore_X_Event_Window_Configure *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_configure_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Configure)))) return; + + e->win = ev->window; + e->event_win = ev->event; + e->abovewin = ev->above_sibling; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->border = ev->border_width; + e->override = ev->override_redirect; + /* send_event is bit 7 (0x80) of response_type */ + e->from_wm = ((ev->response_type & 0x80) ? 1 : 0); + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_configure_request(xcb_generic_event_t *event) +{ + xcb_configure_request_event_t *ev; + Ecore_X_Event_Window_Configure_Request *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_configure_request_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request)))) + return; + + e->win = ev->window; + e->parent_win = ev->parent; + e->abovewin = ev->sibling; + e->x = ev->x; + e->y = ev->y; + e->w = ev->width; + e->h = ev->height; + e->border = ev->border_width; + e->value_mask = ev->value_mask; + switch (ev->stack_mode) + { + case XCB_STACK_MODE_ABOVE: + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + break; + + case XCB_STACK_MODE_BELOW: + e->detail = ECORE_X_WINDOW_STACK_BELOW; + break; + + case XCB_STACK_MODE_TOP_IF: + e->detail = ECORE_X_WINDOW_STACK_TOP_IF; + break; + + case XCB_STACK_MODE_BOTTOM_IF: + e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF; + break; + + case XCB_STACK_MODE_OPPOSITE: + e->detail = ECORE_X_WINDOW_STACK_OPPOSITE; + break; + } + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_gravity_notify(xcb_generic_event_t *event EINA_UNUSED) +{ +/* + xcb_gravity_notify_event_t *ev; + Ecore_X_Event_Window_Gravity *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_gravity_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Gravity)))) return; + + e->win = ev->window; + e->event_win = ev->event; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_GRAVITY, e, NULL, NULL); + */ +} + +static void +_ecore_xcb_event_handle_resize_request(xcb_generic_event_t *event) +{ + xcb_resize_request_event_t *ev; + Ecore_X_Event_Window_Resize_Request *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_resize_request_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request)))) return; + + e->win = ev->window; + e->w = ev->width; + e->h = ev->height; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_circulate_notify(xcb_generic_event_t *event) +{ + xcb_circulate_notify_event_t *ev; + Ecore_X_Event_Window_Stack *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_circulate_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Stack)))) return; + + e->win = ev->window; + e->event_win = ev->event; + if (ev->place == XCB_PLACE_ON_TOP) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else + e->detail = ECORE_X_WINDOW_STACK_BELOW; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_circulate_request(xcb_generic_event_t *event) +{ + xcb_circulate_request_event_t *ev; + Ecore_X_Event_Window_Stack_Request *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_circulate_request_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request)))) return; + + e->win = ev->window; + e->parent = ev->event; + if (ev->place == XCB_PLACE_ON_TOP) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else + e->detail = ECORE_X_WINDOW_STACK_BELOW; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_property_notify(xcb_generic_event_t *event) +{ + xcb_property_notify_event_t *ev; + Ecore_X_Event_Window_Property *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_property_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Property)))) return; + + e->win = ev->window; + e->atom = ev->atom; + e->time = ev->time; + _ecore_xcb_event_last_time = e->time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_selection_clear(xcb_generic_event_t *event) +{ + xcb_selection_clear_event_t *ev; + Ecore_X_Event_Selection_Clear *e; + Ecore_X_Atom sel; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_selection_clear_event_t *)event; + if (!(e = malloc(sizeof(Ecore_X_Event_Selection_Clear)))) return; + + e->win = ev->owner; + e->atom = sel = ev->selection; + if (sel == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + e->selection = ECORE_X_SELECTION_OTHER; + e->time = ev->time; + + ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_selection_request(xcb_generic_event_t *event) +{ + xcb_selection_request_event_t *ev; + Ecore_X_Event_Selection_Request *e; + Ecore_X_Selection_Intern *sd; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_selection_request_event_t *)event; + if (!(e = malloc(sizeof(Ecore_X_Event_Selection_Request)))) return; + + e->owner = ev->owner; + e->requestor = ev->requestor; + e->selection = ev->selection; + e->target = ev->target; + e->property = ev->property; + e->time = ev->time; + + ecore_event_add(ECORE_X_EVENT_SELECTION_REQUEST, e, NULL, NULL); + + if ((sd = _ecore_xcb_selection_get(ev->selection)) && + (sd->win == ev->owner)) + { + Ecore_X_Selection_Intern *si; + + si = _ecore_xcb_selection_get(ev->selection); + if (si->data) + { + Ecore_X_Atom property = XCB_NONE, type; + void *data = NULL; + int len = 0, typesize = 0; + + type = ev->target; + typesize = 8; + len = sd->length; + + if (!ecore_x_selection_convert(ev->selection, ev->target, + &data, &len, &type, &typesize)) + property = XCB_NONE; + else if (data) + { + ecore_x_window_prop_property_set(ev->requestor, ev->property, + type, typesize, data, len); + property = ev->property; + free(data); + } + ecore_x_selection_notify_send(ev->requestor, ev->selection, + ev->target, property, ev->time); + } + } +} + +static void +_ecore_xcb_event_handle_selection_notify(xcb_generic_event_t *event) +{ + xcb_selection_notify_event_t *ev; + Ecore_X_Event_Selection_Notify *e; + unsigned char *data = NULL; + Ecore_X_Atom selection; + int num = 0, format = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_selection_notify_event_t *)event; + selection = ev->selection; + if (ev->target == ECORE_X_ATOM_SELECTION_TARGETS) + { + format = + ecore_x_window_prop_property_get(ev->requestor, ev->property, + XCB_ATOM_ATOM, 32, &data, &num); + if (!format) + { + /* fallback if targets handling is not working and try get the + * selection directly */ + xcb_convert_selection(_ecore_xcb_conn, ev->requestor, + selection, selection, + ECORE_X_ATOM_UTF8_STRING, XCB_CURRENT_TIME); + return; + } + } + else + format = ecore_x_window_prop_property_get(ev->requestor, ev->property, + XCB_GET_PROPERTY_TYPE_ANY, 8, + &data, &num); + + e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify)); + if (!e) return; + e->win = ev->requestor; + e->time = ev->time; + e->atom = selection; + e->target = _ecore_xcb_selection_target_get(ev->target); + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + e->selection = ECORE_X_SELECTION_XDND; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + e->selection = ECORE_X_SELECTION_OTHER; + + e->data = _ecore_xcb_selection_parse(e->target, data, num, format); + + ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, + _ecore_xcb_event_selection_notify_free, NULL); +} + +static void +_ecore_xcb_event_handle_colormap_notify(xcb_generic_event_t *event) +{ + xcb_colormap_notify_event_t *ev; + Ecore_X_Event_Window_Colormap *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_colormap_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Colormap)))) return; + + e->win = ev->window; + e->cmap = ev->colormap; + if (ev->state == XCB_COLORMAP_STATE_INSTALLED) + e->installed = 1; + else + e->installed = 0; + e->time = _ecore_xcb_event_last_time; + + ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_client_message(xcb_generic_event_t *event) +{ + xcb_client_message_event_t *ev; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_client_message_event_t *)event; + + /* Special client message event handling here. need to put LOTS of if */ + /* checks here and generate synthetic events per special message known */ + /* otherwise generate generic client message event. this would handle*/ + /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */ + + if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS) && (ev->format == 32) && + (ev->data.data32[0] == ECORE_X_ATOM_WM_DELETE_WINDOW)) + { + Ecore_X_Event_Window_Delete_Request *e; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request)))) + return; + e->win = ev->window; + e->time = _ecore_xcb_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_NET_WM_MOVERESIZE) && + (ev->format == 32) && (ev->data.data32[2] < 9)) + { + Ecore_X_Event_Window_Move_Resize_Request *e; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request)))) + return; + e->win = ev->window; + e->x = ev->data.data32[0]; + e->y = ev->data.data32[1]; + e->direction = ev->data.data32[2]; + e->button = ev->data.data32[3]; + e->source = ev->data.data32[4]; + ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_XDND_ENTER) + { + Ecore_X_Event_Xdnd_Enter *e; + Ecore_X_DND_Target *target; + + DBG("Got Xdnd Enter Event"); + if (!(e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter)))) return; + target = _ecore_xcb_dnd_target_get(); + target->state = ECORE_X_DND_TARGET_ENTERED; + target->source = ev->data.data32[0]; + target->win = ev->window; + target->version = (int)(ev->data.data32[1] >> 24); + if (target->version > ECORE_X_DND_VERSION) + { + WRN("DND: Requested version %d but we only support up to %d", + target->version, ECORE_X_DND_VERSION); + free(e); + return; + } + if (ev->data.data32[1] & 0x1UL) + { + unsigned char *data; + Ecore_X_Atom *types; + int num_ret = 0; + + if (!ecore_x_window_prop_property_get(target->source, + ECORE_X_ATOM_XDND_TYPE_LIST, + ECORE_X_ATOM_ATOM, 32, + &data, &num_ret)) + { + WRN("DND: Could not fetch data type list from source window"); + free(e); + return; + } + types = (Ecore_X_Atom *)data; + e->types = calloc(num_ret, sizeof(char *)); + if (e->types) + { + int i = 0; + + for (i = 0; i < num_ret; i++) + e->types[i] = ecore_x_atom_name_get(types[i]); + } + e->num_types = num_ret; + } + else + { + int i = 0; + + e->types = calloc(3, sizeof(char *)); + if (e->types) + { + while ((i < 3) && (ev->data.data32[i + 2])) + { + e->types[i] = + ecore_x_atom_name_get(ev->data.data32[i + 2]); + i++; + } + } + e->num_types = i; + } + + e->win = target->win; + e->source = target->source; + ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e, + _ecore_xcb_event_xdnd_enter_free, NULL); + } + else if (ev->type == ECORE_X_ATOM_XDND_POSITION) + { + Ecore_X_Event_Xdnd_Position *e; + Ecore_X_DND_Target *target; + + DBG("Got Xdnd Position Event"); + target = _ecore_xcb_dnd_target_get(); + if ((target->source != (Ecore_X_Window)ev->data.data32[0]) || + (target->win != ev->window)) return; + target->pos.x = ev->data.data32[2] >> 16; + target->pos.y = ev->data.data32[2] & 0xFFFFUL; + target->action = ev->data.data32[4]; + target->time = (target->version >= 1) ? + (Ecore_X_Time)ev->data.data32[3] : XCB_CURRENT_TIME; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position)); + if (!e) return; + e->win = target->win; + e->source = target->source; + e->position.x = target->pos.x; + e->position.y = target->pos.y; + e->action = target->action; + ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_XDND_STATUS) + { + Ecore_X_Event_Xdnd_Status *e; + Ecore_X_DND_Source *source; + + DBG("Got Xdnd Status Event"); + source = _ecore_xcb_dnd_source_get(); + if ((source->win != ev->window) || + (source->dest != (Ecore_X_Window)ev->data.data32[0])) + return; + + source->await_status = 0; + source->will_accept = ev->data.data32[1] & 0x1UL; + source->suppress = (ev->data.data32[1] & 0x2UL) ? 0 : 1; + source->rectangle.x = ev->data.data32[2] >> 16; + source->rectangle.y = ev->data.data32[2] & 0xFFFFUL; + source->rectangle.width = ev->data.data32[3] >> 16; + source->rectangle.height = ev->data.data32[3] & 0xFFFFUL; + source->accepted_action = ev->data.data32[4]; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status)); + if (!e) return; + e->win = source->win; + e->target = source->dest; + e->will_accept = source->will_accept; + e->rectangle.x = source->rectangle.x; + e->rectangle.y = source->rectangle.y; + e->rectangle.width = source->rectangle.width; + e->rectangle.height = source->rectangle.height; + e->action = source->accepted_action; + + ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_XDND_LEAVE) + { + Ecore_X_Event_Xdnd_Leave *e; + Ecore_X_DND_Target *target; + + DBG("Got Xdnd Leave Event"); + target = _ecore_xcb_dnd_target_get(); + if ((target->source != (Ecore_X_Window)ev->data.data32[0]) || + (target->win != ev->window)) + return; + target->state = ECORE_X_DND_TARGET_IDLE; + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave)); + if (!e) return; + e->win = ev->window; + e->source = (Ecore_X_Window)ev->data.data32[0]; + ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_XDND_DROP) + { + Ecore_X_Event_Xdnd_Drop *e; + Ecore_X_DND_Target *target; + + DBG("Got Xdnd Drop Event"); + target = _ecore_xcb_dnd_target_get(); + if ((target->source != (Ecore_X_Window)ev->data.data32[0]) || + (target->win != ev->window)) + return; + target->time = (target->version >= 1) ? + (Ecore_X_Time)ev->data.data32[2] : _ecore_xcb_event_last_time; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop)); + if (!e) return; + e->win = target->win; + e->source = target->source; + e->action = target->action; + e->position.x = target->pos.x; + e->position.y = target->pos.y; + ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_XDND_FINISHED) + { + Ecore_X_Event_Xdnd_Finished *e; + Ecore_X_DND_Source *source; + Eina_Bool completed = EINA_TRUE; + + DBG("Got Xdnd Finished Event"); + source = _ecore_xcb_dnd_source_get(); + if ((source->win != ev->window) || + (source->dest != (Ecore_X_Window)ev->data.data32[0])) + return; + if ((source->version < 5) || (ev->data.data32[1] & 0x1UL)) + { + ecore_x_selection_xdnd_clear(); + source->state = ECORE_X_DND_SOURCE_IDLE; + } + else if (source->version >= 5) + { + completed = EINA_FALSE; + source->state = ECORE_X_DND_SOURCE_CONVERTING; + /* FIXME: Probably need to add a timer to switch back to idle + * and discard the selection data */ + } + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished)))) + return; + e->win = source->win; + e->target = source->dest; + e->completed = completed; + if (source->version >= 5) + { + source->accepted_action = ev->data.data32[2]; + e->action = source->accepted_action; + } + else + { + source->accepted_action = 0; + e->action = source->action; + } + ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_NET_WM_STATE) + { + Ecore_X_Event_Window_State_Request *e; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request)))) + return; + e->win = ev->window; + if (ev->data.data32[0] == 0) + e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE; + else if (ev->data.data32[0] == 1) + e->action = ECORE_X_WINDOW_STATE_ACTION_ADD; + else if (ev->data.data32[0] == 2) + e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE; + else + { + free(e); + return; + } + e->state[0] = _ecore_xcb_netwm_window_state_get(ev->data.data32[1]); + if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN) + { + /* FIXME */ + } + e->state[1] = _ecore_xcb_netwm_window_state_get(ev->data.data32[2]); + if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN) + { + /* FIXME */ + } + e->source = ev->data.data32[3]; + ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL); + } +#ifdef OLD_XCB_VERSION + else if ((ev->type == ECORE_X_ATOM_WM_CHANGE_STATE) && + (ev->format == 32) && (ev->data.data32[0] == XCB_WM_STATE_ICONIC)) +#else + else if ((ev->type == ECORE_X_ATOM_WM_CHANGE_STATE) && (ev->format == 32) && + (ev->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC)) +#endif + { + Ecore_X_Event_Window_State_Request *e; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request)))) + return; + e->win = ev->window; + e->action = ECORE_X_WINDOW_STATE_ACTION_ADD; + e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED; + ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_NET_WM_DESKTOP) && (ev->format == 32)) + { + Ecore_X_Event_Desktop_Change *e; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change)))) + return; + e->win = ev->window; + e->desk = ev->data.data32[0]; + e->source = ev->data.data32[1]; + ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL); + } + else if (ev->type == ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS) + { + Ecore_X_Event_Frame_Extents_Request *e; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request)))) + return; + e->win = ev->window; + ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL); + } + else if ((ev->type == ECORE_X_ATOM_WM_PROTOCOLS) && + ((Ecore_X_Atom)ev->data.data32[0] == ECORE_X_ATOM_NET_WM_PING) && + (ev->format == 32)) + { + Ecore_X_Event_Ping *e; + Ecore_X_Window root = 0; + int count = 0; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Ping)))) return; + e->win = ev->window; + e->time = ev->data.data32[1]; + e->event_win = ev->data.data32[2]; + ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL); + + CHECK_XCB_CONN; + + count = xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn)); + if (count > 1) + root = ecore_x_window_root_get(e->win); + else + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + if (ev->window != root) + { + ev->window = root; + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), + (const char *)&ev); +// ecore_x_flush(); + } + } + else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) && + (ev->format == 8)) + { + _ecore_xcb_netwm_startup_info_begin(ev->window, ev->data.data8[0]); + } + else if ((ev->type == ECORE_X_ATOM_NET_STARTUP_INFO) && (ev->format == 8)) + { + _ecore_xcb_netwm_startup_info(ev->window, ev->data.data8[0]); + } + else if ((ev->type == 27777) && (ev->data.data32[0] == 0x7162534) && + (ev->format == 32)) // && (ev->window = _private_window)) + { + if (ev->data.data32[1] == 0x10000001) + _ecore_xcb_window_button_grab_remove(ev->data.data32[2]); + else if (ev->data.data32[1] == 0x10000002) + _ecore_xcb_window_key_grab_remove(ev->data.data32[2]); + } + else + { + Ecore_X_Event_Client_Message *e; + int i = 0; + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Client_Message)))) + return; + + e->win = ev->window; + e->message_type = ev->type; + e->format = ev->format; + for (i = 0; i < 5; i++) + e->data.l[i] = ev->data.data32[i]; + ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL); + } +} + +static void +_ecore_xcb_event_handle_mapping_notify(xcb_generic_event_t *event) +{ + xcb_mapping_notify_event_t *ev; + Ecore_X_Event_Mapping_Change *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + + ev = (xcb_mapping_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Mapping_Change)))) return; + + _ecore_xcb_keymap_refresh(ev); + _ecore_xcb_modifiers_get(); + + switch (ev->request) + { + case XCB_MAPPING_MODIFIER: + e->type = ECORE_X_MAPPING_MODIFIER; + break; + + case XCB_MAPPING_KEYBOARD: + e->type = ECORE_X_MAPPING_KEYBOARD; + break; + + case XCB_MAPPING_POINTER: + default: + e->type = ECORE_X_MAPPING_MOUSE; + break; + } + e->keycode = ev->first_keycode; + e->num = ev->count; + + ecore_event_add(ECORE_X_EVENT_MAPPING_CHANGE, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_damage_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_DAMAGE + xcb_damage_notify_event_t *ev; + Ecore_X_Event_Damage *e; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +#ifdef ECORE_XCB_DAMAGE + ev = (xcb_damage_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Damage)))) return; + + e->level = ev->level; + e->drawable = ev->drawable; + e->damage = ev->damage; + e->time = ev->timestamp; + e->area.x = ev->area.x; + e->area.y = ev->area.y; + e->area.width = ev->area.width; + e->area.height = ev->area.height; + e->geometry.x = ev->geometry.x; + e->geometry.y = ev->geometry.y; + e->geometry.width = ev->geometry.width; + e->geometry.height = ev->geometry.height; + + ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_randr_change(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_screen_change_notify_event_t *ev; + Ecore_X_Event_Screen_Change *e; +#endif + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + ev = (xcb_randr_screen_change_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Screen_Change)))) return; + + e->win = ev->request_window; + e->root = ev->root; + e->size.width = ev->width; + e->size.height = ev->height; + e->time = ev->timestamp; + e->config_time = ev->config_timestamp; + e->size.width_mm = ev->mwidth; + e->size.height_mm = ev->mheight; + e->orientation = ev->rotation; + e->subpixel_order = ev->subpixel_order; + + ecore_event_add(ECORE_X_EVENT_SCREEN_CHANGE, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_randr_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_notify_event_t *ev; +#endif + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + ev = (xcb_randr_notify_event_t *)event; + switch (ev->subCode) + { + case XCB_RANDR_NOTIFY_CRTC_CHANGE: + _ecore_xcb_event_handle_randr_crtc_change(event); + break; + + case XCB_RANDR_NOTIFY_OUTPUT_CHANGE: + _ecore_xcb_event_handle_randr_output_change(event); + break; + + case XCB_RANDR_NOTIFY_OUTPUT_PROPERTY: + _ecore_xcb_event_handle_randr_output_property_change(event); + break; + + default: + break; + } +#endif +} + +static void +_ecore_xcb_event_handle_randr_crtc_change(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_notify_event_t *ev; + Ecore_X_Event_Randr_Crtc_Change *e; +#endif + +#ifdef ECORE_XCB_RANDR + ev = (xcb_randr_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Randr_Crtc_Change)))) + return; + + e->win = ev->u.cc.window; + e->crtc = ev->u.cc.crtc; + e->mode = ev->u.cc.mode; + e->orientation = ev->u.cc.rotation; + e->geo.x = ev->u.cc.x; + e->geo.y = ev->u.cc.y; + e->geo.w = ev->u.cc.width; + e->geo.h = ev->u.cc.height; + + ecore_event_add(ECORE_X_EVENT_RANDR_CRTC_CHANGE, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_randr_output_change(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_notify_event_t *ev; + Ecore_X_Event_Randr_Output_Change *e; +#endif + +#ifdef ECORE_XCB_RANDR + ev = (xcb_randr_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Change)))) + return; + + e->win = ev->u.oc.window; + e->output = ev->u.oc.output; + e->crtc = ev->u.oc.crtc; + e->mode = ev->u.oc.mode; + e->orientation = ev->u.oc.rotation; + e->connection = ev->u.oc.connection; + e->subpixel_order = ev->u.oc.subpixel_order; + + ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_CHANGE, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_randr_output_property_change(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_notify_event_t *ev; + Ecore_X_Event_Randr_Output_Property_Notify *e; +#endif + +#ifdef ECORE_XCB_RANDR + ev = (xcb_randr_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Property_Notify)))) + return; + + e->win = ev->u.op.window; + e->output = ev->u.op.output; + e->property = ev->u.op.atom; + e->time = ev->u.op.timestamp; + if (ev->u.op.status == XCB_PROPERTY_NEW_VALUE) + e->state = ECORE_X_RANDR_PROPERTY_CHANGE_ADD; + else + e->state = ECORE_X_RANDR_PROPERTY_CHANGE_DEL; + + ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_screensaver_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_notify_event_t *ev; + Ecore_X_Event_Screensaver_Notify *e; +#endif + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +#ifdef ECORE_XCB_SCREENSAVER + ev = (xcb_screensaver_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify)))) return; + + e->win = ev->window; + e->on = EINA_FALSE; + if ((ev->state == XCB_SCREENSAVER_STATE_ON) || + (ev->state == XCB_SCREENSAVER_STATE_CYCLE)) e->on = EINA_TRUE; + e->time = ev->time; + + ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL); +#endif +} + +#ifdef ECORE_XCB_XGESTURE +static void +_ecore_xcb_event_handle_gesture_notify_flick(xcb_generic_event_t *event) +{ + xcb_gesture_notify_flick_event_t *ev; + Ecore_X_Event_Gesture_Notify_Flick *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_flick_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Flick)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_fingers = ev->num_finger; + e->distance = ev->distance; + e->duration = ev->duration; + e->direction = ev->direction; + e->angle = XFixedToDouble(ev->angle); + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_FLICK, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_gesture_notify_pan(xcb_generic_event_t *event) +{ + xcb_gesture_notify_pan_event_t *ev; + Ecore_X_Event_Gesture_Notify_Pan *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_pan_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Pan)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_fingers = ev->num_finger; + e->dx = ev->dx; + e->dy = ev->dy; + e->distance = ev->distance; + e->duration = ev->duration; + e->direction = ev->direction; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_PAN, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_gesture_notify_pinchrotation(xcb_generic_event_t *event) +{ + xcb_gesture_notify_pinch_rotation_event_t *ev; + Ecore_X_Event_Gesture_Notify_PinchRotation *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_pinch_rotation_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_PinchRotation)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_fingers = ev->num_finger; + e->distance = ev->distance; + e->cx = ev->cx; + e->cy = ev->cy; + e->zoom = XFixedToDouble(ev->zoom); + e->angle = XFixedToDouble(ev->angle); + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_gesture_notify_tap(xcb_generic_event_t *event) +{ + xcb_gesture_notify_tap_event_t *ev; + Ecore_X_Event_Gesture_Notify_Tap *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_tap_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Tap)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_fingers = ev->num_finger; + e->cx = ev->cx; + e->cy = ev->cy; + e->tap_repeat = ev->tap_repeat; + e->interval = ev->interval; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_TAP, e, NULL, NULL); +} + +static void +_ecore_xcb_event_handle_gesture_notify_tapnhold(xcb_generic_event_t *event) +{ + xcb_gesture_notify_tap_n_hold_event_t *ev; + Ecore_X_Event_Gesture_Notify_TapNHold *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_tap_n_hold_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_TapNHold)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_fingers = ev->num_finger; + e->cx = ev->cx; + e->cy = ev->cy; + e->interval = ev->interval; + e->hold_time = ev->holdtime; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD, e, NULL, NULL); +} + +static void + _ecore_xcb_event_handle_gesture_notify_hold(xcb_generic_event_t *event) +{ + xcb_gesture_notify_hold_event_t *ev; + Ecore_X_Event_Gesture_Notify_Hold *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_hold_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Hold)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_fingers = ev->num_finger; + e->cx = ev->cx; + e->cy = ev->cy; + e->hold_time = ev->holdtime; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_HOLD, e, NULL, NULL); +} + +static void + _ecore_xcb_event_handle_gesture_notify_group(xcb_generic_event_t *event) +{ + xcb_gesture_notify_group_event_t *ev; + Ecore_X_Event_Gesture_Notify_Group *e; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + fprintf(stderr, "[ECORE_XCB][%s]...\n", __FUNCTION__); + + ev = (xcb_gesture_notify_group_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Group)))) return; + + e->win = ev->window; + e->time = ev->time; + e->subtype = ev->kind; + e->num_groups = ev->num_group; + e->group_id = ev->groupid; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_GROUP, e, NULL, NULL); +} +#endif + +#ifdef ECORE_XCB_SHAPE +static void +_ecore_xcb_event_handle_shape_change(xcb_generic_event_t *event) +{ + xcb_shape_notify_event_t *ev; + Ecore_X_Event_Window_Shape *e; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + ev = (xcb_shape_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Window_Shape)))) return; + + e->win = ev->affected_window; + e->time = ev->server_time; + switch (ev->shape_kind) + { + case XCB_SHAPE_SK_BOUNDING: + e->type = ECORE_X_SHAPE_BOUNDING; + break; + + case XCB_SHAPE_SK_CLIP: + e->type = ECORE_X_SHAPE_CLIP; + break; + + case XCB_SHAPE_SK_INPUT: + e->type = ECORE_X_SHAPE_INPUT; + break; + + default: + break; + } + e->x = ev->extents_x; + e->y = ev->extents_y; + e->w = ev->extents_width; + e->h = ev->extents_height; + e->shaped = ev->shaped; + + ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL); +} + +#endif + +static void +_ecore_xcb_event_handle_sync_counter(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_counter_notify_event_t *ev; + Ecore_X_Event_Sync_Counter *e; +#endif + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + +#ifdef ECORE_XCB_SYNC + ev = (xcb_sync_counter_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter)))) return; + + e->time = ev->timestamp; + + ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_sync_alarm(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_alarm_notify_event_t *ev; + Ecore_X_Event_Sync_Alarm *e; +#endif + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +#ifdef ECORE_XCB_SYNC + ev = (xcb_sync_alarm_notify_event_t *)event; + if (!(e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm)))) return; + + e->time = ev->timestamp; + e->alarm = ev->alarm; + + ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_xfixes_selection_notify(xcb_generic_event_t *event) +{ +#ifdef ECORE_XCB_XFIXES + Ecore_X_Event_Fixes_Selection_Notify *e; + Ecore_X_Atom sel; + xcb_xfixes_selection_notify_event_t *ev; +#endif + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; +#ifdef ECORE_XCB_XFIXES + ev = (xcb_xfixes_selection_notify_event_t *)event; + + if (!(e = calloc(1, sizeof(*e)))) return; + + e->win = ev->window; + e->owner = ev->owner; + e->time = ev->timestamp; + e->selection_time = ev->selection_timestamp; + e->atom = sel = ev->selection; + if (sel == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + e->selection = ECORE_X_SELECTION_OTHER; + e->reason = ev->subtype; + + ecore_event_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, e, NULL, NULL); +#endif +} + +static void +_ecore_xcb_event_handle_xfixes_cursor_notify(xcb_generic_event_t *event EINA_UNUSED) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +// FIXME: TBD +} + +static void +_ecore_xcb_event_handle_generic_event(xcb_generic_event_t *event) +{ + xcb_ge_event_t *ev; + Ecore_X_Event_Generic *e; + + ev = (xcb_ge_event_t *)event; + + /* pad0 *IS* extension - bug in xcb */ + if (ev->pad0 == _ecore_xcb_event_input) + { + _ecore_xcb_event_handle_input_event(event); +// FIXME: should we generate generic events as WELL as input events? +// return; + } + + if (!(e = calloc(1, sizeof(Ecore_X_Event_Generic)))) + return; + + DBG("Handle Generic Event: %d", ev->event_type); + + e->cookie = ev->sequence; + /* NB: These are bugs in xcb ge_event structure. The struct should have a + * field for extension & data, but does not. + * + * XCB people have been notified of this issue */ + e->extension = ev->pad0; + /* e->data = ev->pad1; */ + if (ev->length > 0) + { + int len = ev->length * sizeof(int); + e->data = malloc(len); + if (e->data) memcpy(e->data, &(event[1]), len); + } + + e->evtype = ev->event_type; + + ecore_event_add(ECORE_X_EVENT_GENERIC, e, + _ecore_xcb_event_generic_event_free, e->data); +} + +static void +_ecore_xcb_event_handle_input_event(xcb_generic_event_t *event) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_input_handle_event(event); +} + +static void +_ecore_xcb_event_key_press(xcb_generic_event_t *event) +{ + Ecore_Event_Key *e; + xcb_keysym_t sym = XCB_NO_SYMBOL; + xcb_keycode_t keycode = 0; + xcb_key_press_event_t *xevent; + char *keyname = NULL, *key = NULL; + char *compose = NULL; + char compose_buffer[256]; + int val = 0; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + + xevent = (xcb_key_press_event_t *)event; + keycode = xevent->detail; + + sym = _ecore_xcb_keymap_keycode_to_keysym(keycode, xevent->state); + keyname = _ecore_xcb_keymap_keysym_to_string(sym); + if (!keyname) + { + char buff[256]; + + snprintf(buff, sizeof(buff), "Keycode-%i", keycode); + keyname = buff; + } + + val = + _ecore_xcb_keymap_lookup_string(keycode, xevent->state, compose_buffer, + sizeof(compose_buffer), &sym); + if (val > 0) + { + compose_buffer[val] = 0; + compose = + eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer); + if (!compose) + ERR("Ecore_X cannot convert input key string '%s' to UTF-8. " + "Is Eina built with iconv support?", compose_buffer); + } + + key = _ecore_xcb_keymap_keysym_to_string(sym); + if (!key) key = keyname; + + e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + + (compose ? strlen(compose) : 0) + 3); + if (e) + { + e->keyname = (char *)(e + 1); + e->key = e->keyname + strlen(keyname) + 1; + + e->compose = NULL; + if (compose) e->compose = (e->key + strlen(key) + 1); + e->string = e->compose; + + strcpy((char *)e->keyname, keyname); + strcpy((char *)e->key, key); + if (compose) strcpy((char *)e->compose, compose); + + e->modifiers = _ecore_xcb_events_modifiers_get(xevent->state); + e->timestamp = xevent->time; + e->window = xevent->child ? xevent->child : xevent->event; + e->event_window = xevent->event; + e->same_screen = xevent->same_screen; + e->root_window = xevent->root; + + DBG("Sending Key Down Event: %s", e->keyname); + ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL); + } + _ecore_xcb_event_last_time = xevent->time; +} + +static void +_ecore_xcb_event_key_release(xcb_generic_event_t *event) +{ + Ecore_Event_Key *e; + xcb_keysym_t sym = XCB_NO_SYMBOL; + xcb_keycode_t keycode = 0; + xcb_key_release_event_t *xevent; + char *keyname = NULL, *key = NULL; + char *compose = NULL; + char compose_buffer[256]; + int val = 0; + + _ecore_xcb_event_last_mouse_move = EINA_FALSE; + + xevent = (xcb_key_release_event_t *)event; + keycode = xevent->detail; + + sym = _ecore_xcb_keymap_keycode_to_keysym(keycode, xevent->state); + keyname = _ecore_xcb_keymap_keysym_to_string(sym); + if (!keyname) + { + char buff[256]; + + snprintf(buff, sizeof(buff), "Keycode-%i", keycode); + keyname = buff; + } + + val = + _ecore_xcb_keymap_lookup_string(keycode, xevent->state, compose_buffer, + sizeof(compose_buffer), &sym); + if (val > 0) + { + compose_buffer[val] = 0; + compose = + eina_str_convert(nl_langinfo(CODESET), "UTF-8", compose_buffer); +// tmp = compose; + } + + key = _ecore_xcb_keymap_keysym_to_string(sym); + if (!key) key = keyname; + + e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + + (compose ? strlen(compose) : 0) + 3); + if (e) + { + e->keyname = (char *)(e + 1); + e->key = e->keyname + strlen(keyname) + 1; + + e->compose = NULL; + if (compose) e->compose = (e->key + strlen(key) + 1); + e->string = e->compose; + + strcpy((char *)e->keyname, keyname); + strcpy((char *)e->key, key); + if (compose) strcpy((char *)e->compose, compose); + + e->modifiers = _ecore_xcb_events_modifiers_get(xevent->state); + e->timestamp = xevent->time; + e->window = xevent->child ? xevent->child : xevent->event; + e->event_window = xevent->event; + e->same_screen = xevent->same_screen; + e->root_window = xevent->root; + + ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL); + } + _ecore_xcb_event_last_time = xevent->time; +} + +void +_ecore_xcb_event_mouse_move(uint16_t timestamp, + uint16_t modifiers, + int16_t x, + int16_t y, + int16_t root_x, + int16_t root_y, + xcb_window_t event_win, + xcb_window_t win, + xcb_window_t root_win, + uint8_t same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + int16_t mx, + int16_t my, + int16_t mrx, + int16_t mry) +{ + Ecore_Event_Mouse_Move *e; + Ecore_Event *event; + + if (!(e = malloc(sizeof(Ecore_Event_Mouse_Move)))) return; + + e->window = win; + e->root_window = root_win; + e->timestamp = timestamp; + e->same_screen = same_screen; + e->event_window = event_win; + e->modifiers = _ecore_xcb_events_modifiers_get(modifiers); + e->x = x; + e->y = y; + e->root.x = root_x; + e->root.y = root_y; + e->multi.device = dev; + e->multi.radius = ((radx + rady) / 2); + e->multi.radius_x = radx; + e->multi.radius_y = rady; + e->multi.pressure = pressure; + e->multi.angle = angle; + e->multi.x = mx; + e->multi.y = my; + e->multi.root.x = mrx; + e->multi.root.y = mry; + + event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, e, + _ecore_xcb_event_mouse_move_free, NULL); + + _ecore_xcb_event_last_time = e->timestamp; + _ecore_xcb_event_last_window = e->window; + _ecore_xcb_event_last_root_x = root_x; + _ecore_xcb_event_last_root_y = root_y; +// _ecore_xcb_event_last_mouse_move_event = event; +} + +static void +_ecore_xcb_event_mouse_move_free(void *data EINA_UNUSED, + void *event) +{ + Ecore_Event_Mouse_Move *ev; + + ev = event; +// if (_ecore_xcb_event_last_mouse_move_event) +// { +// _ecore_xcb_event_last_mouse_move = EINA_FALSE; +// _ecore_xcb_event_last_mouse_move_event = NULL; +// } + if (ev) free(ev); +} + +Ecore_Event_Mouse_Button * +_ecore_xcb_event_mouse_button(int event, + uint16_t timestamp, + uint16_t modifiers, + xcb_button_t buttons, + int16_t x, + int16_t y, + int16_t root_x, + int16_t root_y, + xcb_window_t event_win, + xcb_window_t win, + xcb_window_t root_win, + uint8_t same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + int16_t mx, + int16_t my, + int16_t mrx, + int16_t mry) +{ + Ecore_Event_Mouse_Button *e; + Ecore_X_Mouse_Down_Info *info = NULL; + + if (!(e = malloc(sizeof(Ecore_Event_Mouse_Button)))) return NULL; + + e->window = win; + e->root_window = root_win; + e->timestamp = timestamp; + e->same_screen = same_screen; + e->event_window = event_win; + e->buttons = buttons; + e->modifiers = _ecore_xcb_events_modifiers_get(modifiers); + e->double_click = 0; + e->triple_click = 0; + e->x = x; + e->y = y; + e->root.x = root_x; + e->root.y = root_y; + + if ((info = _ecore_xcb_event_mouse_down_info_get(dev))) + { + if ((event == ECORE_EVENT_MOUSE_BUTTON_DOWN) && + (info->did_triple)) + { + info->last_win = 0; + info->last_last_win = 0; + info->last_event_win = 0; + info->last_time = 0; + info->last_last_time = 0; + } + if (event_win == win) + { + if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN) + { + if (((int)(timestamp - info->last_time) <= + (int)(1000 * _ecore_xcb_double_click_time)) && + (win == info->last_win) && + (event_win == info->last_event_win)) + { + e->double_click = 1; + info->did_double = EINA_TRUE; + } + else + { + info->did_double = EINA_FALSE; + info->did_triple = EINA_FALSE; + } + if (((int)(timestamp - info->last_last_time) <= + (int)(2 * 1000 * _ecore_xcb_double_click_time)) && + (win == info->last_win) && + (win == info->last_last_win) && + (event_win == info->last_event_win) && + (event_win == info->last_last_event_win)) + { + e->triple_click = 1; + info->did_triple = EINA_TRUE; + } + else + info->did_triple = EINA_FALSE; + } + else + { + if (info->did_double) e->double_click = 1; + if (info->did_triple) e->triple_click = 1; + } + } + } + + /* NB: Comment out right now because _ecore_xcb_mouse_up_count is + * only used here...nowhere else in the code */ + + /* if ((event == ECORE_EVENT_MOUSE_BUTTON_DOWN) && */ + /* (!e->double_click) && (!e->triple_click)) */ + /* _ecore_xcb_mouse_up_count = 0; */ + + e->multi.device = dev; + e->multi.radius = ((radx + rady) / 2); + e->multi.radius_x = radx; + e->multi.radius_y = rady; + e->multi.pressure = pressure; + e->multi.angle = angle; + e->multi.x = mx; + e->multi.y = my; + e->multi.root.x = mrx; + e->multi.root.y = mry; + + _ecore_xcb_event_last_time = e->timestamp; + _ecore_xcb_event_last_window = e->window; + _ecore_xcb_event_last_root_x = root_x; + _ecore_xcb_event_last_root_y = root_y; + + ecore_event_add(event, e, NULL, NULL); + + if ((info) && (event == ECORE_EVENT_MOUSE_BUTTON_DOWN) && + (win == event_win) && (!info->did_triple)) + { + info->last_last_win = info->last_win; + info->last_win = win; + info->last_last_event_win = info->last_event_win; + info->last_event_win = event_win; + info->last_last_time = info->last_time; + info->last_time = timestamp; + } + + return e; +} + +static Ecore_X_Event_Mode +_ecore_xcb_event_mode_get(uint8_t mode) +{ + switch (mode) + { + case XCB_NOTIFY_MODE_NORMAL: + return ECORE_X_EVENT_MODE_NORMAL; + + case XCB_NOTIFY_MODE_WHILE_GRABBED: + return ECORE_X_EVENT_MODE_WHILE_GRABBED; + + case XCB_NOTIFY_MODE_GRAB: + return ECORE_X_EVENT_MODE_GRAB; + + case XCB_NOTIFY_MODE_UNGRAB: + return ECORE_X_EVENT_MODE_UNGRAB; + + default: + return ECORE_X_EVENT_MODE_NORMAL; + } +} + +static Ecore_X_Event_Detail +_ecore_xcb_event_detail_get(uint8_t detail) +{ + switch (detail) + { + case XCB_NOTIFY_DETAIL_ANCESTOR: + return ECORE_X_EVENT_DETAIL_ANCESTOR; + + case XCB_NOTIFY_DETAIL_VIRTUAL: + return ECORE_X_EVENT_DETAIL_VIRTUAL; + + case XCB_NOTIFY_DETAIL_INFERIOR: + return ECORE_X_EVENT_DETAIL_INFERIOR; + + case XCB_NOTIFY_DETAIL_NONLINEAR: + return ECORE_X_EVENT_DETAIL_NON_LINEAR; + + case XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL: + return ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + + case XCB_NOTIFY_DETAIL_POINTER: + return ECORE_X_EVENT_DETAIL_POINTER; + + case XCB_NOTIFY_DETAIL_POINTER_ROOT: + return ECORE_X_EVENT_DETAIL_POINTER_ROOT; + + case XCB_NOTIFY_DETAIL_NONE: + default: + return ECORE_X_EVENT_DETAIL_ANCESTOR; + } +} + +static void +_ecore_xcb_event_xdnd_enter_free(void *data EINA_UNUSED, + void *event) +{ + Ecore_X_Event_Xdnd_Enter *e; + int i = 0; + + e = event; + for (i = 0; i < e->num_types; i++) + free(e->types[i]); + free(e->types); + free(e); +} + +static void +_ecore_xcb_event_selection_notify_free(void *data EINA_UNUSED, + void *event) +{ + Ecore_X_Event_Selection_Notify *e; + Ecore_X_Selection_Data *sel; + + e = event; + if (!(sel = e->data)) return; + if (sel->free) sel->free(sel); + free(e->target); + free(e); +} + +static void +_ecore_xcb_event_generic_event_free(void *data, + void *event) +{ + Ecore_X_Event_Generic *e; + + e = (Ecore_X_Event_Generic *)event; + if (e->data) free(data); + free(e); +} + +static void +_ecore_xcb_event_mouse_down_info_clear(void) +{ + Eina_Inlist *l; + Ecore_X_Mouse_Down_Info *info = NULL; + + l = _ecore_xcb_mouse_down_info_list; + while (l) + { + info = EINA_INLIST_CONTAINER_GET(l, Ecore_X_Mouse_Down_Info); + l = eina_inlist_remove(l, l); + free(info); + } + _ecore_xcb_mouse_down_info_list = NULL; +} + +static Ecore_X_Mouse_Down_Info * +_ecore_xcb_event_mouse_down_info_get(int dev) +{ + Eina_Inlist *l; + Ecore_X_Mouse_Down_Info *info = NULL; + + l = _ecore_xcb_mouse_down_info_list; + EINA_INLIST_FOREACH(l, info) + if (info->dev == dev) return info; + + if (!(info = calloc(1, sizeof(Ecore_X_Mouse_Down_Info)))) return NULL; + + info->dev = dev; + l = eina_inlist_append(l, (Eina_Inlist *)info); + _ecore_xcb_mouse_down_info_list = l; + + return info; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_extensions.c b/src/lib/ecore_x/xcb/ecore_xcb_extensions.c new file mode 100644 index 0000000000..40c10ac05b --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_extensions.c @@ -0,0 +1,148 @@ +#include "ecore_xcb_private.h" + +void +_ecore_xcb_extensions_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_big_requests_id); + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_shm_id); + +#ifdef ECORE_XCB_SHAPE + _ecore_xcb_shape_init(); +#endif + +#ifdef ECORE_XCB_SCREENSAVER + _ecore_xcb_screensaver_init(); +#endif + +#ifdef ECORE_XCB_SYNC + _ecore_xcb_sync_init(); +#endif + +#ifdef ECORE_XCB_RANDR + _ecore_xcb_randr_init(); +#endif + +#ifdef ECORE_XCB_XFIXES + _ecore_xcb_xfixes_init(); +#endif + +#ifdef ECORE_XCB_DAMAGE + _ecore_xcb_damage_init(); +#endif + +#ifdef ECORE_XCB_RENDER + _ecore_xcb_render_init(); +#endif + +#ifdef ECORE_XCB_COMPOSITE + _ecore_xcb_composite_init(); +#endif + +#ifdef ECORE_XCB_DPMS + _ecore_xcb_dpms_init(); +#endif + +#ifdef ECORE_XCB_DPMS + _ecore_xcb_dpms_init(); +#endif + +#ifdef ECORE_XCB_CURSOR + _ecore_xcb_cursor_init(); +#endif + +#ifdef ECORE_XCB_XINERAMA + _ecore_xcb_xinerama_init(); +#endif + +#ifdef ECORE_XCB_XINPUT + _ecore_xcb_input_init(); +#endif + +#ifdef ECORE_XCB_GESTURE + _ecore_xcb_gesture_init(); +#endif + +/* #ifdef ECORE_XCB_DRI */ +/* _ecore_xcb_dri_init(); */ +/* #endif */ + +#ifdef ECORE_XCB_XTEST + _ecore_xcb_xtest_init(); +#endif + + xcb_prefetch_maximum_request_length(_ecore_xcb_conn); +} + +void +_ecore_xcb_extensions_finalize(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xcb_get_extension_data(_ecore_xcb_conn, &xcb_big_requests_id); + xcb_get_extension_data(_ecore_xcb_conn, &xcb_shm_id); + +#ifdef ECORE_XCB_SHAPE + _ecore_xcb_shape_finalize(); +#endif + +#ifdef ECORE_XCB_SCREENSAVER + _ecore_xcb_screensaver_finalize(); +#endif + +#ifdef ECORE_XCB_SYNC + _ecore_xcb_sync_finalize(); +#endif + +#ifdef ECORE_XCB_RANDR + _ecore_xcb_randr_finalize(); +#endif + +#ifdef ECORE_XCB_XFIXES + _ecore_xcb_xfixes_finalize(); +#endif + +#ifdef ECORE_XCB_DAMAGE + _ecore_xcb_damage_finalize(); +#endif + +#ifdef ECORE_XCB_RENDER + _ecore_xcb_render_finalize(); +#endif + +#ifdef ECORE_XCB_COMPOSITE + _ecore_xcb_composite_finalize(); +#endif + +#ifdef ECORE_XCB_DPMS + _ecore_xcb_dpms_finalize(); +#endif + +#ifdef ECORE_XCB_CURSOR + _ecore_xcb_cursor_finalize(); +#endif + +#ifdef ECORE_XCB_XINERAMA + _ecore_xcb_xinerama_finalize(); +#endif + +#ifdef ECORE_XCB_XINPUT + _ecore_xcb_input_finalize(); +#endif + +#ifdef ECORE_XCB_GESTURE + _ecore_xcb_gesture_finalize(); +#endif + +/* #ifdef ECORE_XCB_DRI */ +/* _ecore_xcb_dri_finalize(); */ +/* #endif */ + +#ifdef ECORE_XCB_XTEST + _ecore_xcb_xtest_finalize(); +#endif + + xcb_get_maximum_request_length(_ecore_xcb_conn); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_gc.c b/src/lib/ecore_x/xcb/ecore_xcb_gc.c new file mode 100644 index 0000000000..d811b54594 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_gc.c @@ -0,0 +1,173 @@ +#include "ecore_xcb_private.h" + +/** + * Creates a new default graphics context associated with the given + * drawable. + * @param draw Drawable to create graphics context with. If @c 0 is + * given instead, the default root window is used. + * @param value_mask Bitmask values. + * @param value_list List of values. The order of values must be the + * same than the corresponding bitmaks. + * @return The new default graphics context. + */ +EAPI Ecore_X_GC +ecore_x_gc_new(Ecore_X_Drawable drawable, + Ecore_X_GC_Value_Mask value_mask, + const unsigned int *value_list) +{ + xcb_gcontext_t gc; + uint32_t vmask = 0; + int i = 0, mask = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!drawable) drawable = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + for (i = 0, mask = 1; i <= 22; i++, mask <<= 1) + { + switch (mask & value_mask) + { + case ECORE_X_GC_VALUE_MASK_FUNCTION: + vmask |= XCB_GC_FUNCTION; + break; + + case ECORE_X_GC_VALUE_MASK_PLANE_MASK: + vmask |= XCB_GC_PLANE_MASK; + break; + + case ECORE_X_GC_VALUE_MASK_FOREGROUND: + vmask |= XCB_GC_FOREGROUND; + break; + + case ECORE_X_GC_VALUE_MASK_BACKGROUND: + vmask |= XCB_GC_BACKGROUND; + break; + + case ECORE_X_GC_VALUE_MASK_LINE_WIDTH: + vmask |= XCB_GC_LINE_WIDTH; + break; + + case ECORE_X_GC_VALUE_MASK_LINE_STYLE: + vmask |= XCB_GC_LINE_STYLE; + break; + + case ECORE_X_GC_VALUE_MASK_CAP_STYLE: + vmask |= XCB_GC_CAP_STYLE; + break; + + case ECORE_X_GC_VALUE_MASK_JOIN_STYLE: + vmask |= XCB_GC_JOIN_STYLE; + break; + + case ECORE_X_GC_VALUE_MASK_FILL_STYLE: + vmask |= XCB_GC_FILL_STYLE; + break; + + case ECORE_X_GC_VALUE_MASK_FILL_RULE: + vmask |= XCB_GC_FILL_RULE; + break; + + case ECORE_X_GC_VALUE_MASK_TILE: + vmask |= XCB_GC_TILE; + break; + + case ECORE_X_GC_VALUE_MASK_STIPPLE: + vmask |= XCB_GC_STIPPLE; + break; + + case ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_X: + vmask |= XCB_GC_TILE_STIPPLE_ORIGIN_X; + break; + + case ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_Y: + vmask |= XCB_GC_TILE_STIPPLE_ORIGIN_Y; + break; + + case ECORE_X_GC_VALUE_MASK_FONT: + vmask |= XCB_GC_FONT; + break; + + case ECORE_X_GC_VALUE_MASK_SUBWINDOW_MODE: + vmask |= XCB_GC_SUBWINDOW_MODE; + break; + + case ECORE_X_GC_VALUE_MASK_GRAPHICS_EXPOSURES: + vmask |= XCB_GC_GRAPHICS_EXPOSURES; + break; + + case ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_X: + vmask |= XCB_GC_CLIP_ORIGIN_X; + break; + + case ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_Y: + vmask |= XCB_GC_CLIP_ORIGIN_Y; + break; + + case ECORE_X_GC_VALUE_MASK_CLIP_MASK: + vmask |= XCB_GC_CLIP_MASK; + break; + + case ECORE_X_GC_VALUE_MASK_DASH_OFFSET: + vmask |= XCB_GC_DASH_OFFSET; + break; + + case ECORE_X_GC_VALUE_MASK_DASH_LIST: + vmask |= XCB_GC_DASH_LIST; + break; + + case ECORE_X_GC_VALUE_MASK_ARC_MODE: + vmask |= XCB_GC_ARC_MODE; + break; + } + } + + gc = xcb_generate_id(_ecore_xcb_conn); + xcb_create_gc(_ecore_xcb_conn, gc, drawable, vmask, value_list); + +// ecore_x_flush(); + return gc; +} + +/** + * Deletes and frees the given graphics context. + * @param gc The given graphics context. + */ +EAPI void +ecore_x_gc_free(Ecore_X_GC gc) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_free_gc(_ecore_xcb_conn, gc); +// ecore_x_flush(); +} + +EAPI void +ecore_x_gc_foreground_set(Ecore_X_GC gc, + unsigned long foreground) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = foreground; + xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_FOREGROUND, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_gc_background_set(Ecore_X_GC gc, + unsigned long background) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = background; + xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_BACKGROUND, &list); +// ecore_x_flush(); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_gesture.c b/src/lib/ecore_x/xcb/ecore_xcb_gesture.c new file mode 100644 index 0000000000..27c13167af --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_gesture.c @@ -0,0 +1,203 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_XGESTURE +# include <xcb/gesture.h> +# include <xcb/xcb_event.h> +#endif + +/* local variables */ +static Eina_Bool _gesture_available = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_gesture = -1; + +void +_ecore_xcb_gesture_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XGESTURE + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_gesture_id); +#endif +} + +void +_ecore_xcb_gesture_finalize(void) +{ +#ifdef ECORE_XCB_XGESTURE + xcb_gesture_query_version_cookie_t cookie; + xcb_gesture_query_version_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XGESTURE + cookie = + xcb_gesture_query_version_unchecked(_ecore_xcb_conn); + reply = + xcb_gesture_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + _gesture_available = EINA_TRUE; + free(reply); + } + + if (_gesture_available) + { + const xcb_query_extension_reply_t *ext_reply; + + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_gesture_id); + if (ext_reply) + _ecore_xcb_event_gesture = ext_reply->first_event; + } +#endif +} + +void +_ecore_xcb_gesture_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +EAPI Eina_Bool +ecore_x_gesture_supported(void) +{ + return _gesture_available; +} + +#ifdef ECORE_XCB_XGESTURE +EAPI Eina_Bool +ecore_x_gesture_events_select(Ecore_X_Window win, + Ecore_X_Gesture_Event_Mask mask) +#else +EAPI Eina_Bool +ecore_x_gesture_events_select(Ecore_X_Window win EINA_UNUSED, + Ecore_X_Gesture_Event_Mask mask EINA_UNUSED) +#endif + +{ +#ifdef ECORE_XCB_XGESTURE + if (!_gesture_available) return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN + + xcb_gesture_select_events(_ecore_xcb_conn, win, mask); + + return EINA_TRUE; +#else + return EINA_FALSE; +#endif +} + +#ifdef ECORE_XCB_XGESTURE +EAPI Ecore_X_Gesture_Event_Mask +ecore_x_gesture_events_selected_get(Ecore_X_Window win) +#else +EAPI Ecore_X_Gesture_Event_Mask +ecore_x_gesture_events_selected_get(Ecore_X_Window win EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XGESTURE + xcb_gesture_get_selected_events_cookie_t ecookie; + xcb_gesture_get_selected_events_reply_t *ereply; + Ecore_X_Gesture_Event_Mask mask = ECORE_X_GESTURE_EVENT_MASK_NONE; + + if (!_gesture_available) return mask; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN + + ecookie = xcb_gesture_get_selected_events(_ecore_xcb_conn, win); + ereply = + xcb_gesture_get_selected_events_reply(_ecore_xcb_conn, ecookie, NULL); + if (ereply) + { + mask = ereply->mask; + free(ereply); + } + + return mask; +#else + return ECORE_X_GESTURE_EVENT_MASK_NONE; +#endif +} + +#ifdef ECORE_XCB_XGESTURE +EAPI Eina_Bool +ecore_x_gesture_event_grab(Ecore_X_Window win, + Ecore_X_Gesture_Event_Type type, + int num_fingers) +#else +EAPI Eina_Bool +ecore_x_gesture_event_grab(Ecore_X_Window win EINA_UNUSED, + Ecore_X_Gesture_Event_Type type EINA_UNUSED, + int num_fingers EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XGESTURE + Eina_Bool status = EINA_TRUE; + xcb_gesture_grab_event_cookie_t ecookie; + xcb_gesture_grab_event_reply_t *ereply; + + if (!_gesture_available) return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN + + ecookie = + xcb_gesture_grab_event(_ecore_xcb_conn, win, type, num_fingers, 0L); + ereply = xcb_gesture_grab_event_reply(_ecore_xcb_conn, ecookie, NULL); + + if (ereply) + { + if (ereply->status) status = EINA_FALSE; + free(ereply); + } + else + status = EINA_FALSE; + + return status; +#else + return EINA_FALSE; +#endif +} + +#ifdef ECORE_XCB_XGESTURE +EAPI Eina_Bool +ecore_x_gesture_event_ungrab(Ecore_X_Window win, + Ecore_X_Gesture_Event_Type type, + int num_fingers) +#else +EAPI Eina_Bool +ecore_x_gesture_event_ungrab(Ecore_X_Window win EINA_UNUSED, + Ecore_X_Gesture_Event_Type type EINA_UNUSED, + int num_fingers EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XGESTURE + Eina_Bool status = EINA_TRUE; + xcb_gesture_ungrab_event_cookie_t ecookie; + xcb_gesture_ungrab_event_reply_t *ereply; + + if (!_gesture_available) return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN + + ecookie = + xcb_gesture_ungrab_event(_ecore_xcb_conn, win, type, num_fingers, 0L); + ereply = xcb_gesture_ungrab_event_reply(_ecore_xcb_conn, ecookie, NULL); + + if (ereply) + { + if (ereply->status) status = EINA_FALSE; + free(ereply); + } + else + status = EINA_FALSE; + + return status; +#else + return EINA_FALSE; +#endif +} diff --git a/src/lib/ecore_x/xcb/ecore_xcb_icccm.c b/src/lib/ecore_x/xcb/ecore_xcb_icccm.c new file mode 100644 index 0000000000..8dea8617d1 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_icccm.c @@ -0,0 +1,1569 @@ +#include "ecore_xcb_private.h" +#include <xcb/xcb_icccm.h> + +EAPI void +ecore_x_icccm_init(void) +{ +} + +/** + * Sets the WM_COMMAND property for @a win. + * + * @param win The window. + * @param argc Number of arguments. + * @param argv Arguments. + */ +EAPI void +ecore_x_icccm_command_set(Ecore_X_Window win, + int argc, + char **argv) +{ + void *buf; + char *b; + int nbytes, i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + for (i = 0, nbytes = 0; i < argc; i++) + if (argv[i]) nbytes += strlen(argv[i]) + 1; + + buf = malloc(sizeof(char) * nbytes); + if (!buf) return; + + b = (char *)buf; + for (i = 0; i < argc; i++) + { + if (argv[i]) + { + strcpy(b, argv[i]); + b += strlen(argv[i]) + 1; + } + else + *b++ = '\0'; + } + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + ECORE_X_ATOM_WM_COMMAND, ECORE_X_ATOM_STRING, 8, + nbytes, buf); + free(buf); +} + +/** + * Get the WM_COMMAND property for @a win. + * + * Return the command of a window. String must be free'd when done with. + * + * @param win The window. + * @param argc Number of arguments. + * @param argv Arguments. + */ +EAPI void +ecore_x_icccm_command_get(Ecore_X_Window win, + int *argc, + char ***argv) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + int len = 0; + char **v, *data, *cp, *start; + int c = 0, i = 0, j = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (argc) *argc = 0; + if (argv) *argv = NULL; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, + ECORE_X_ATOM_WM_COMMAND, + XCB_GET_PROPERTY_TYPE_ANY, + 0, 1000000L); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + + if ((reply->type != ECORE_X_ATOM_STRING) || (reply->format != 8)) + { + free(reply); + return; + } + + len = reply->value_len; + if (len < 1) + { + free(reply); + return; + } + + data = (char *)xcb_get_property_value(reply); + if (len && (data[len - 1] == '\0')) + len--; + + c = 1; + for (cp = (char *)data, i = len; i > 0; cp++, i--) + if (*cp == '\0') c++; + + v = (char **)malloc((c + 1) * sizeof(char *)); + if (!v) + { + free(reply); + return; + } + + start = (char *)malloc((len + 1) * sizeof(char)); + if (!start) + { + free(reply); + free(v); + return; + } + + memcpy(start, (char *)data, len); + start[len] = '\0'; + for (cp = start, i = len + 1, j = 0; i > 0; cp++, i--) + { + if (*cp == '\0') + { + v[j] = start; + start = (cp + 1); + j++; + } + } + + if (c < 1) + { + free(reply); + free(v); + return; + } + + if (argc) *argc = c; + + if (argv) + { + (*argv) = malloc(c * sizeof(char *)); + if (!*argv) + { + free(reply); + free(v); + if (argc) *argc = 0; + return; + } + + for (i = 0; i < c; i++) + { + if (v[i]) + (*argv)[i] = strdup(v[i]); + else + (*argv)[i] = strdup(""); + } + } + + free(reply); + free(v); +} + +EAPI char * +ecore_x_icccm_title_get(Ecore_X_Window win) +{ + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_t prop; +#else + xcb_icccm_get_text_property_reply_t prop; +#endif + uint8_t ret = 0; + char *title = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return NULL; +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_name_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_name_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#else + cookie = xcb_icccm_get_wm_name_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_name_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#endif + if (ret == 0) return NULL; + if (prop.name_len < 1) + { +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return NULL; + } + + if (!(title = malloc((prop.name_len + 1) * sizeof(char *)))) + { +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return NULL; + } + memcpy(title, prop.name, sizeof(char *) * prop.name_len); + title[prop.name_len] = '\0'; + + if (prop.encoding != ECORE_X_ATOM_UTF8_STRING) + { + Ecore_Xcb_Textproperty tp; + int count = 0; + char **list = NULL; + Eina_Bool ret = EINA_FALSE; + + tp.value = strdup(title); + tp.nitems = prop.name_len; + tp.encoding = prop.encoding; +#ifdef HAVE_ICONV + ret = _ecore_xcb_utf8_textproperty_to_textlist(&tp, &list, &count); +#else + ret = _ecore_xcb_mb_textproperty_to_textlist(&tp, &list, &count); +#endif + if (ret) + { + if (count > 0) + title = strdup(list[0]); + + if (list) free(list); + } + } + +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return title; +} + +EAPI void +ecore_x_icccm_title_set(Ecore_X_Window win, + const char *title) +{ + Ecore_Xcb_Textproperty prop; + char *list[1]; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!title) return; + + prop.value = NULL; + list[0] = strdup(title); + +#ifdef HAVE_ICONV + ret = _ecore_xcb_utf8_textlist_to_textproperty(list, 1, XcbUTF8StringStyle, + &prop); +#else + ret = _ecore_xcb_mb_textlist_to_textproperty(list, 1, XcbStdICCTextStyle, + &prop); +#endif + + if (ret) + { +#ifdef OLD_XCB_VERSION + xcb_set_wm_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, + strlen(prop.value), prop.value); +#else + xcb_icccm_set_wm_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, 8, + strlen(prop.value), prop.value); +#endif + if (prop.value) free(prop.value); + } + else +#ifdef OLD_XCB_VERSION + xcb_set_wm_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, + strlen(title), title); +#else + xcb_icccm_set_wm_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, 8, + strlen(title), title); +#endif + free(list[0]); +} + +/** + * Get a window name & class. + * @param win The window + * @param n The name string + * @param c The class string + * + * Get a window name * class + */ +EAPI void +ecore_x_icccm_name_class_get(Ecore_X_Window win, + char **name, + char **class) +{ + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_get_wm_class_reply_t prop; +#else + xcb_icccm_get_wm_class_reply_t prop; +#endif + uint8_t ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (name) *name = NULL; + if (class) *class = NULL; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_class_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_class_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#else + cookie = xcb_icccm_get_wm_class_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_class_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#endif + if (ret == 0) return; + + if (name) *name = strdup(prop.instance_name); + if (class) *class = strdup(prop.class_name); + +#ifdef OLD_XCB_VERSION + xcb_get_wm_class_reply_wipe(&prop); +#else + xcb_icccm_get_wm_class_reply_wipe(&prop); +#endif +} + +/** + * Set a window name & class. + * @param win The window + * @param n The name string + * @param c The class string + * + * Set a window name * class + */ +EAPI void +ecore_x_icccm_name_class_set(Ecore_X_Window win, + const char *name, + const char *class) +{ + char *class_string, *s; + int length_name, length_class; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + length_name = strlen(name); + length_class = strlen(class); + class_string = + (char *)malloc(sizeof(char) * (length_name + length_class + 2)); + if (!class_string) return; + + s = class_string; + if (length_name) + { + strcpy(s, name); + s += length_name + 1; + } + else + *s++ = '\0'; + + if (length_class) + strcpy(s, class); + else + *s = '\0'; + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + ECORE_X_ATOM_WM_CLASS, ECORE_X_ATOM_STRING, 8, + length_name + length_class + 2, (void *)class_string); + free(class_string); +} + +/** + * Specify that a window is transient for another top-level window and should be handled accordingly. + * @param win the transient window + * @param forwin the toplevel window + */ +EAPI void +ecore_x_icccm_transient_for_set(Ecore_X_Window win, + Ecore_X_Window forwindow) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + ECORE_X_ATOM_WM_TRANSIENT_FOR, ECORE_X_ATOM_WINDOW, 32, + 1, (void *)&forwindow); +} + +/** + * Remove the transient_for setting from a window. + * @param win The window + */ +EAPI void +ecore_x_icccm_transient_for_unset(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_WM_TRANSIENT_FOR); +} + +/** + * Get the window this window is transient for, if any. + * @param win The window to check + * @return The window ID of the top-level window, or 0 if the property does not exist. + */ +EAPI Ecore_X_Window +ecore_x_icccm_transient_for_get(Ecore_X_Window win) +{ + Ecore_X_Window forwin = 0; + xcb_get_property_cookie_t cookie; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_transient_for_unchecked(_ecore_xcb_conn, win); + xcb_get_wm_transient_for_reply(_ecore_xcb_conn, cookie, &forwin, NULL); +#else + cookie = xcb_icccm_get_wm_transient_for_unchecked(_ecore_xcb_conn, win); + xcb_icccm_get_wm_transient_for_reply(_ecore_xcb_conn, cookie, &forwin, NULL); +#endif + + return forwin; +} + +/** + * Get the window role. + * @param win The window + * @return The window's role string. + */ +EAPI char * +ecore_x_icccm_window_role_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_WINDOW_ROLE); +} + +/** + * Set the window role hint. + * @param win The window + * @param role The role string + */ +EAPI void +ecore_x_icccm_window_role_set(Ecore_X_Window win, + const char *role) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_WINDOW_ROLE, role); +} + +/** + * Get the window's client leader. + * @param win The window + * @return The window's client leader window, or 0 if unset + */ +EAPI Ecore_X_Window +ecore_x_icccm_client_leader_get(Ecore_X_Window win) +{ + Ecore_X_Window leader; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (ecore_x_window_prop_window_get(win, ECORE_X_ATOM_WM_CLIENT_LEADER, + &leader, 1) > 0) + return leader; + + return 0; +} + +/** + * Set the window's client leader. + * @param win The window + * @param l The client leader window + * + * All non-transient top-level windows created by an app other than + * the main window must have this property set to the app's main window. + */ +EAPI void +ecore_x_icccm_client_leader_set(Ecore_X_Window win, + Ecore_X_Window leader) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(win, ECORE_X_ATOM_WM_CLIENT_LEADER, + &leader, 1); +} + +EAPI Ecore_X_Window_State_Hint +ecore_x_icccm_state_get(Ecore_X_Window win) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + Ecore_X_Window_State_Hint hint = ECORE_X_WINDOW_STATE_HINT_NONE; + uint8_t *prop; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = + xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, + ECORE_X_ATOM_WM_STATE, ECORE_X_ATOM_WM_STATE, + 0L, 0x7fffffff); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return hint; + if ((reply->type == 0) || (reply->format != 8) || (reply->value_len != 2)) + { + free(reply); + return hint; + } + + prop = (uint8_t *)xcb_get_property_value(reply); +#ifdef OLD_XCB_VERSION + switch (prop[0]) + { + case XCB_WM_STATE_WITHDRAWN: + hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + break; + + case XCB_WM_STATE_NORMAL: + hint = ECORE_X_WINDOW_STATE_HINT_NORMAL; + break; + + case XCB_WM_STATE_ICONIC: + hint = ECORE_X_WINDOW_STATE_HINT_ICONIC; + break; + + default: + break; + } +#else + switch (prop[0]) + { + case XCB_ICCCM_WM_STATE_WITHDRAWN: + hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + break; + + case XCB_ICCCM_WM_STATE_NORMAL: + hint = ECORE_X_WINDOW_STATE_HINT_NORMAL; + break; + + case XCB_ICCCM_WM_STATE_ICONIC: + hint = ECORE_X_WINDOW_STATE_HINT_ICONIC; + break; + + default: + break; + } +#endif + + free(reply); + return hint; +} + +EAPI void +ecore_x_icccm_state_set(Ecore_X_Window win, + Ecore_X_Window_State_Hint state) +{ +#ifdef OLD_XCB_VERSION + xcb_wm_hints_t hints; +#else + xcb_icccm_wm_hints_t hints; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef OLD_XCB_VERSION + xcb_wm_hints_set_none(&hints); + + hints.flags = XCB_WM_HINT_STATE; + + if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + xcb_wm_hints_set_withdrawn(&hints); + else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + xcb_wm_hints_set_normal(&hints); + else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + xcb_wm_hints_set_iconic(&hints); + + xcb_set_wm_hints(_ecore_xcb_conn, win, &hints); +#else + xcb_icccm_wm_hints_set_none(&hints); + + hints.flags = XCB_ICCCM_WM_HINT_STATE; + + if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + xcb_icccm_wm_hints_set_withdrawn(&hints); + else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + xcb_icccm_wm_hints_set_normal(&hints); + else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + xcb_icccm_wm_hints_set_iconic(&hints); + + xcb_icccm_set_wm_hints(_ecore_xcb_conn, win, &hints); +#endif +} + +EAPI void +ecore_x_icccm_delete_window_send(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_DELETE_WINDOW, t, 0, 0, 0); +} + +EAPI void +ecore_x_icccm_hints_set(Ecore_X_Window win, + Eina_Bool accepts_focus, + Ecore_X_Window_State_Hint initial_state, + Ecore_X_Pixmap icon_pixmap, + Ecore_X_Pixmap icon_mask, + Ecore_X_Window icon_window, + Ecore_X_Window window_group, + Eina_Bool is_urgent) +{ +#ifdef OLD_XCB_VERSION + xcb_wm_hints_t hints; +#else + xcb_icccm_wm_hints_t hints; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef OLD_XCB_VERSION + xcb_wm_hints_set_none(&hints); + xcb_wm_hints_set_input(&hints, accepts_focus); + + if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + xcb_wm_hints_set_withdrawn(&hints); + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + xcb_wm_hints_set_normal(&hints); + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + xcb_wm_hints_set_iconic(&hints); + + if (icon_pixmap != 0) xcb_wm_hints_set_icon_pixmap(&hints, icon_pixmap); + if (icon_mask != 0) xcb_wm_hints_set_icon_mask(&hints, icon_mask); + if (icon_window != 0) xcb_wm_hints_set_icon_window(&hints, icon_window); + if (window_group != 0) xcb_wm_hints_set_window_group(&hints, window_group); + if (is_urgent) xcb_wm_hints_set_urgency(&hints); + + xcb_set_wm_hints(_ecore_xcb_conn, win, &hints); +#else + xcb_icccm_wm_hints_set_none(&hints); + xcb_icccm_wm_hints_set_input(&hints, accepts_focus); + + if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + xcb_icccm_wm_hints_set_withdrawn(&hints); + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + xcb_icccm_wm_hints_set_normal(&hints); + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + xcb_icccm_wm_hints_set_iconic(&hints); + + if (icon_pixmap != 0) + xcb_icccm_wm_hints_set_icon_pixmap(&hints, icon_pixmap); + if (icon_mask != 0) + xcb_icccm_wm_hints_set_icon_mask(&hints, icon_mask); + if (icon_window != 0) + xcb_icccm_wm_hints_set_icon_window(&hints, icon_window); + if (window_group != 0) + xcb_icccm_wm_hints_set_window_group(&hints, window_group); + if (is_urgent) + xcb_icccm_wm_hints_set_urgency(&hints); + + xcb_icccm_set_wm_hints(_ecore_xcb_conn, win, &hints); +#endif +} + +EAPI Eina_Bool +ecore_x_icccm_hints_get(Ecore_X_Window win, + Eina_Bool *accepts_focus, + Ecore_X_Window_State_Hint *initial_state, + Ecore_X_Pixmap *icon_pixmap, + Ecore_X_Pixmap *icon_mask, + Ecore_X_Window *icon_window, + Ecore_X_Window *window_group, + Eina_Bool *is_urgent) +{ + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_wm_hints_t hints; +#else + xcb_icccm_wm_hints_t hints; +#endif + uint8_t ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (accepts_focus) *accepts_focus = EINA_TRUE; + if (initial_state) *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + if (icon_pixmap) *icon_pixmap = 0; + if (icon_mask) *icon_mask = 0; + if (icon_window) *icon_window = 0; + if (window_group) *window_group = 0; + if (is_urgent) *is_urgent = EINA_FALSE; + +#ifdef OLD_XCB_VERSION + xcb_wm_hints_set_none(&hints); + cookie = xcb_get_wm_hints_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_hints_reply(_ecore_xcb_conn, cookie, &hints, NULL); +#else + xcb_icccm_wm_hints_set_none(&hints); + cookie = xcb_icccm_get_wm_hints_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_hints_reply(_ecore_xcb_conn, cookie, &hints, NULL); +#endif + if (!ret) return EINA_FALSE; + +#ifdef OLD_XCB_VERSION + if ((hints.flags & XCB_WM_HINT_INPUT) && (accepts_focus)) +#else + if ((hints.flags & XCB_ICCCM_WM_HINT_INPUT) && (accepts_focus)) +#endif + { + if (hints.input) + *accepts_focus = EINA_TRUE; + else + *accepts_focus = EINA_FALSE; + } + +#ifdef OLD_XCB_VERSION + if ((hints.flags & XCB_WM_HINT_STATE) && (initial_state)) + { + if (hints.initial_state == XCB_WM_STATE_WITHDRAWN) + *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else if (hints.initial_state == XCB_WM_STATE_NORMAL) + *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + else if (hints.initial_state == XCB_WM_STATE_ICONIC) + *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC; + } + + if ((hints.flags & XCB_WM_HINT_ICON_PIXMAP) && (icon_pixmap)) + *icon_pixmap = hints.icon_pixmap; + + if ((hints.flags & XCB_WM_HINT_ICON_MASK) && (icon_mask)) + *icon_mask = hints.icon_mask; + + if ((hints.flags & XCB_WM_HINT_ICON_WINDOW) && (icon_window)) + *icon_window = hints.icon_window; + + if ((hints.flags & XCB_WM_HINT_WINDOW_GROUP) && (window_group)) + *window_group = hints.window_group; + + if ((hints.flags & XCB_WM_HINT_X_URGENCY) && (is_urgent)) + *is_urgent = EINA_TRUE; +#else + if ((hints.flags & XCB_ICCCM_WM_HINT_STATE) && (initial_state)) + { + if (hints.initial_state == XCB_ICCCM_WM_STATE_WITHDRAWN) + *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else if (hints.initial_state == XCB_ICCCM_WM_STATE_NORMAL) + *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + else if (hints.initial_state == XCB_ICCCM_WM_STATE_ICONIC) + *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC; + } + + if ((hints.flags & XCB_ICCCM_WM_HINT_ICON_PIXMAP) && (icon_pixmap)) + *icon_pixmap = hints.icon_pixmap; + + if ((hints.flags & XCB_ICCCM_WM_HINT_ICON_MASK) && (icon_mask)) + *icon_mask = hints.icon_mask; + + if ((hints.flags & XCB_ICCCM_WM_HINT_ICON_WINDOW) && (icon_window)) + *icon_window = hints.icon_window; + + if ((hints.flags & XCB_ICCCM_WM_HINT_WINDOW_GROUP) && (window_group)) + *window_group = hints.window_group; + + if ((hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) && (is_urgent)) + *is_urgent = EINA_TRUE; +#endif + + return EINA_TRUE; +} + +/** + * Get a window icon name. + * @param win The window + * @return The windows icon name string + * + * Return the icon name of a window. String must be free'd when done with. + */ +EAPI char * +ecore_x_icccm_icon_name_get(Ecore_X_Window win) +{ + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_t prop; +#else + xcb_icccm_get_text_property_reply_t prop; +#endif + uint8_t ret = 0; + char *tmp = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return NULL; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_icon_name_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_icon_name_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#else + cookie = xcb_icccm_get_wm_icon_name_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_icon_name_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#endif + if (ret == 0) return NULL; + + if (prop.name_len < 1) + { +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return NULL; + } + + if (!(tmp = malloc((prop.name_len + 1) * sizeof(char *)))) + { +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return NULL; + } + memcpy(tmp, prop.name, sizeof(char *) * prop.name_len); + tmp[prop.name_len] = '\0'; + + if (prop.encoding != ECORE_X_ATOM_UTF8_STRING) + { + Ecore_Xcb_Textproperty tp; + int count = 0; + char **list = NULL; + Eina_Bool ret = EINA_FALSE; + + tp.value = strdup(tmp); + tp.nitems = prop.name_len; + tp.encoding = prop.encoding; +#ifdef HAVE_ICONV + ret = _ecore_xcb_utf8_textproperty_to_textlist(&tp, &list, &count); +#else + ret = _ecore_xcb_mb_textproperty_to_textlist(&tp, &list, &count); +#endif + if (ret) + { + if (count > 0) + tmp = strdup(list[0]); + + if (list) free(list); + } + } + +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return tmp; +} + +/** + * Set a window icon name. + * @param win The window + * @param t The icon name string + * + * Set a window icon name + */ +EAPI void +ecore_x_icccm_icon_name_set(Ecore_X_Window win, + const char *name) +{ + Ecore_Xcb_Textproperty prop; + char *list[1]; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!win) || (!name)) return; + + prop.value = NULL; + list[0] = strdup(name); + +#ifdef HAVE_ICONV + ret = _ecore_xcb_utf8_textlist_to_textproperty(list, 1, XcbUTF8StringStyle, + &prop); +#else + ret = _ecore_xcb_mb_textlist_to_textproperty(list, 1, XcbStdICCTextStyle, + &prop); +#endif + + if (ret) + { +#ifdef OLD_XCB_VERSION + xcb_set_wm_icon_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, + strlen(prop.value), prop.value); +#else + xcb_icccm_set_wm_icon_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, + 8, strlen(prop.value), prop.value); +#endif + if (prop.value) free(prop.value); + } + else +#ifdef OLD_XCB_VERSION + xcb_set_wm_icon_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, + strlen(name), name); +#else + xcb_icccm_set_wm_icon_name(_ecore_xcb_conn, win, ECORE_X_ATOM_STRING, + 8, strlen(name), name); +#endif + + free(list[0]); +} + +EAPI void +ecore_x_icccm_iconic_request_send(Ecore_X_Window win, + Ecore_X_Window root) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_WM_CHANGE_STATE; +#ifdef OLD_XCB_VERSION + ev.data.data32[0] = XCB_WM_STATE_ICONIC; +#else + ev.data.data32[0] = XCB_ICCCM_WM_STATE_ICONIC; +#endif + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT), + (const char *)&ev); +// ecore_x_flush(); +} + +/** + * Set or unset a wm protocol property. + * @param win The Window + * @param protocol The protocol to enable/disable + * @param on On/Off + */ +EAPI void +ecore_x_icccm_protocol_set(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol, + Eina_Bool on) +{ + Ecore_X_Atom proto; + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_t protos; +#else + xcb_icccm_get_wm_protocols_reply_t protos; +#endif + int i = 0, count = 0, set = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) return; + proto = _ecore_xcb_atoms_wm_protocol[protocol]; +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_protocols_unchecked(_ecore_xcb_conn, win, proto); + if (!xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protos, NULL)) +#else + cookie = xcb_icccm_get_wm_protocols_unchecked(_ecore_xcb_conn, win, proto); + if (!xcb_icccm_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protos, NULL)) +#endif + count = 0; + else + count = protos.atoms_len; + + for (i = 0; i < count; i++) + { + if (protos.atoms[i] == proto) + { + set = 1; + break; + } + } + + if (on) + { + if (!set) + { + Ecore_X_Atom *atoms = NULL; + + atoms = malloc((count + 1) * sizeof(Ecore_X_Atom)); + if (atoms) + { + for (i = 0; i < count; i++) + atoms[i] = protos.atoms[i]; + atoms[count] = proto; +#ifdef OLD_XCB_VERSION + xcb_set_wm_protocols(_ecore_xcb_conn, + ECORE_X_ATOM_WM_PROTOCOLS, + win, count, atoms); +#else + xcb_icccm_set_wm_protocols(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS, + count, atoms); +#endif + free(atoms); + } + } + } + else + { + if (set) + { + for (i = 0; i < count; i++) + { + if (protos.atoms[i] == proto) + { + int j = 0; + + for (j = (i + 1); j < count; j++) + protos.atoms[j - 1] = protos.atoms[j]; + if (count > 1) +#ifdef OLD_XCB_VERSION + xcb_set_wm_protocols(_ecore_xcb_conn, + ECORE_X_ATOM_WM_PROTOCOLS, + win, count - 1, protos.atoms); +#else + xcb_icccm_set_wm_protocols(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS, + count - 1, protos.atoms); +#endif + else + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_WM_PROTOCOLS); + break; + } + } + } + } + +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_wipe(&protos); +#else + xcb_icccm_get_wm_protocols_reply_wipe(&protos); +#endif +} + +/** + * Determines whether a protocol is set for a window. + * @param win The Window + * @param protocol The protocol to query + * @return 1 if the protocol is set, else 0. + */ +EAPI Eina_Bool +ecore_x_icccm_protocol_isset(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol) +{ + Ecore_X_Atom proto; + Eina_Bool ret = EINA_FALSE; + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_t reply; +#else + xcb_icccm_get_wm_protocols_reply_t reply; +#endif + uint8_t val = 0; + unsigned int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) return EINA_FALSE; + + proto = _ecore_xcb_atoms_wm_protocol[protocol]; +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_protocols_unchecked(_ecore_xcb_conn, win, proto); + val = xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &reply, NULL); +#else + cookie = xcb_icccm_get_wm_protocols_unchecked(_ecore_xcb_conn, win, proto); + val = xcb_icccm_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &reply, NULL); +#endif + if (!val) return EINA_FALSE; + + for (i = 0; i < reply.atoms_len; i++) + if (reply.atoms[i] == proto) + { + ret = EINA_TRUE; + break; + } + +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_wipe(&reply); +#else + xcb_icccm_get_wm_protocols_reply_wipe(&reply); +#endif + + return ret; +} + +/** + * Set protocol atoms explicitly + * @param win The Window + * @param protos An array of protocol atoms + * @param num the number of members of the array + */ +EAPI void +ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win, + Ecore_X_Atom *protos, + int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num > 0) +#ifdef OLD_XCB_VERSION + xcb_set_wm_protocols(_ecore_xcb_conn, ECORE_X_ATOM_WM_PROTOCOLS, + win, num, protos); +#else + xcb_icccm_set_wm_protocols(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS, num, protos); +#endif + else + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_WM_PROTOCOLS); +} + +EAPI Eina_Bool +ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win, + Eina_Bool *request_pos, + Ecore_X_Gravity *gravity, + int *min_w, + int *min_h, + int *max_w, + int *max_h, + int *base_w, + int *base_h, + int *step_x, + int *step_y, + double *min_aspect, + double *max_aspect) +{ + xcb_size_hints_t hints; + xcb_get_property_cookie_t cookie; + uint8_t ret = 0; + int32_t minw = 0, minh = 0; + int32_t maxw = 32767, maxh = 32767; + int32_t basew = -1, baseh = -1; + int32_t stepx = -1, stepy = -1; + double mina = 0.0, maxa = 0.0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (request_pos) *request_pos = EINA_FALSE; + if (gravity) *gravity = ECORE_X_GRAVITY_NW; + if (min_w) *min_w = minw; + if (min_h) *min_h = minh; + if (max_w) *max_w = maxw; + if (max_h) *max_h = maxh; + if (base_w) *base_w = basew; + if (base_h) *base_h = baseh; + if (step_x) *step_x = stepx; + if (step_y) *step_y = stepy; + if (min_aspect) *min_aspect = mina; + if (max_aspect) *max_aspect = maxa; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_normal_hints_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_normal_hints_reply(_ecore_xcb_conn, cookie, &hints, NULL); +#else + cookie = xcb_icccm_get_wm_normal_hints_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_normal_hints_reply(_ecore_xcb_conn, cookie, + &hints, NULL); +#endif + if (!ret) return EINA_FALSE; + +#ifdef OLD_XCB_VERSION + if ((hints.flags & XCB_SIZE_HINT_US_POSITION) || + (hints.flags & XCB_SIZE_HINT_P_POSITION)) +#else + if ((hints.flags & XCB_ICCCM_SIZE_HINT_US_POSITION) || + (hints.flags & XCB_ICCCM_SIZE_HINT_P_POSITION)) +#endif + { + if (request_pos) *request_pos = EINA_TRUE; + } + +#ifdef OLD_XCB_VERSION + if (hints.flags & XCB_SIZE_HINT_P_WIN_GRAVITY) +#else + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_WIN_GRAVITY) +#endif + { + if (gravity) *gravity = hints.win_gravity; + } + +#ifdef OLD_XCB_VERSION + if (hints.flags & XCB_SIZE_HINT_P_MIN_SIZE) +#else + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_MIN_SIZE) +#endif + { + minw = hints.min_width; + minh = hints.min_height; + } + +#ifdef OLD_XCB_VERSION + if (hints.flags & XCB_SIZE_HINT_P_MAX_SIZE) +#else + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_MAX_SIZE) +#endif + { + maxw = hints.max_width; + maxh = hints.max_height; + if (maxw < minw) maxw = minw; + if (maxh < minh) maxh = minh; + } + +#ifdef OLD_XCB_VERSION + if (hints.flags & XCB_SIZE_HINT_BASE_SIZE) +#else + if (hints.flags & XCB_ICCCM_SIZE_HINT_BASE_SIZE) +#endif + { + basew = hints.base_width; + baseh = hints.base_height; + if (basew > minw) minw = basew; + if (baseh > minh) minh = baseh; + } + +#ifdef OLD_XCB_VERSION + if (hints.flags & XCB_SIZE_HINT_P_RESIZE_INC) +#else + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_RESIZE_INC) +#endif + { + stepx = hints.width_inc; + stepy = hints.height_inc; + if (stepx < 1) stepx = 1; + if (stepy < 1) stepy = 1; + } + +#ifdef OLD_XCB_VERSION + if (hints.flags & XCB_SIZE_HINT_P_ASPECT) +#else + if (hints.flags & XCB_ICCCM_SIZE_HINT_P_ASPECT) +#endif + { + if (hints.min_aspect_den > 0) + mina = ((double)hints.min_aspect_num) / ((double)hints.min_aspect_den); + + if (hints.max_aspect_den > 0) + maxa = ((double)hints.max_aspect_num) / ((double)hints.max_aspect_den); + } + + if (min_w) *min_w = minw; + if (min_h) *min_h = minh; + if (max_w) *max_w = maxw; + if (max_h) *max_h = maxh; + if (base_w) *base_w = basew; + if (base_h) *base_h = baseh; + if (step_x) *step_x = stepx; + if (step_y) *step_y = stepy; + if (min_aspect) *min_aspect = mina; + if (max_aspect) *max_aspect = maxa; + + return EINA_TRUE; +} + +EAPI void +ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win, + Eina_Bool request_pos, + Ecore_X_Gravity gravity, + int min_w, + int min_h, + int max_w, + int max_h, + int base_w, + int base_h, + int step_x, + int step_y, + double min_aspect, + double max_aspect) +{ + xcb_get_property_cookie_t cookie; + xcb_size_hints_t hints; + uint8_t ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_normal_hints_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_normal_hints_reply(_ecore_xcb_conn, cookie, &hints, NULL); +#else + cookie = xcb_icccm_get_wm_normal_hints_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_normal_hints_reply(_ecore_xcb_conn, cookie, + &hints, NULL); +#endif + if (!ret) memset(&hints, 0, sizeof(xcb_size_hints_t)); + + hints.flags = 0; + +#ifdef OLD_XCB_VERSION + if (request_pos) + hints.flags |= XCB_SIZE_HINT_US_POSITION; + + if (gravity != ECORE_X_GRAVITY_NW) + xcb_size_hints_set_win_gravity(&hints, gravity); + if ((min_w > 0) || (min_h > 0)) + xcb_size_hints_set_min_size(&hints, min_w, min_h); + if ((max_w > 0) || (max_h > 0)) + xcb_size_hints_set_max_size(&hints, max_w, max_h); + if ((base_w > 0) || (base_h > 0)) + xcb_size_hints_set_base_size(&hints, base_w, base_h); + if ((step_x > 1) || (step_y > 1)) + xcb_size_hints_set_resize_inc(&hints, step_x, step_y); + if ((min_aspect > 0.0) || (max_aspect > 0.0)) + xcb_size_hints_set_aspect(&hints, + (int32_t)(min_aspect * 10000), 10000, + (int32_t)(max_aspect * 10000), 10000); + + xcb_set_wm_normal_hints(_ecore_xcb_conn, win, &hints); +#else + if (request_pos) + hints.flags |= XCB_ICCCM_SIZE_HINT_US_POSITION; + + if (gravity != ECORE_X_GRAVITY_NW) + xcb_icccm_size_hints_set_win_gravity(&hints, gravity); + if ((min_w > 0) || (min_h > 0)) + xcb_icccm_size_hints_set_min_size(&hints, min_w, min_h); + if ((max_w > 0) || (max_h > 0)) + xcb_icccm_size_hints_set_max_size(&hints, max_w, max_h); + if ((base_w > 0) || (base_h > 0)) + xcb_icccm_size_hints_set_base_size(&hints, base_w, base_h); + if ((step_x > 1) || (step_y > 1)) + xcb_icccm_size_hints_set_resize_inc(&hints, step_x, step_y); + if ((min_aspect > 0.0) || (max_aspect > 0.0)) + xcb_icccm_size_hints_set_aspect(&hints, + (int32_t)(min_aspect * 10000), 10000, + (int32_t)(max_aspect * 10000), 10000); + + xcb_icccm_set_wm_normal_hints(_ecore_xcb_conn, win, &hints); +#endif +} + +EAPI void +ecore_x_icccm_move_resize_send(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + xcb_configure_notify_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + + memset(&ev, 0, sizeof(xcb_configure_notify_event_t)); + + ev.response_type = XCB_CONFIGURE_NOTIFY; + ev.event = win; + ev.window = win; + ev.above_sibling = XCB_NONE; + ev.x = x; + ev.y = y; + ev.width = w; + ev.height = h; + ev.border_width = 0; + ev.override_redirect = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *)&ev); +// ecore_x_flush(); +} + +/** + * Get a window client machine string. + * @param win The window + * @return The windows client machine string + * + * Return the client machine of a window. String must be free'd when done with. + */ +EAPI char * +ecore_x_icccm_client_machine_get(Ecore_X_Window win) +{ + xcb_get_property_cookie_t cookie; +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_t prop; +#else + xcb_icccm_get_text_property_reply_t prop; +#endif + uint8_t ret = 0; + char *tmp = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_client_machine_unchecked(_ecore_xcb_conn, win); + ret = xcb_get_wm_client_machine_reply(_ecore_xcb_conn, cookie, &prop, NULL); +#else + cookie = xcb_icccm_get_wm_client_machine_unchecked(_ecore_xcb_conn, win); + ret = xcb_icccm_get_wm_client_machine_reply(_ecore_xcb_conn, cookie, + &prop, NULL); +#endif + if (ret == 0) return NULL; + + tmp = malloc((prop.name_len + 1) * sizeof(char *)); + if (!tmp) + { +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + return NULL; + } + memcpy(tmp, prop.name, sizeof(char *) * prop.name_len); + tmp[prop.name_len] = '\0'; + +#ifdef OLD_XCB_VERSION + xcb_get_text_property_reply_wipe(&prop); +#else + xcb_icccm_get_text_property_reply_wipe(&prop); +#endif + + return tmp; +} + +EAPI void +ecore_x_icccm_take_focus_send(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + XCB_EVENT_MASK_NO_EVENT, + ECORE_X_ATOM_WM_TAKE_FOCUS, t, 0, 0, 0); +} + +EAPI void +ecore_x_icccm_save_yourself_send(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + XCB_EVENT_MASK_NO_EVENT, + ECORE_X_ATOM_WM_SAVE_YOURSELF, t, 0, 0, 0); +} + +/** + * Add a subwindow to the list of windows that need a different colormap installed. + * @param win The toplevel window + * @param subwin The subwindow to be added to the colormap windows list + */ +EAPI void +ecore_x_icccm_colormap_window_set(Ecore_X_Window win, + Ecore_X_Window subwin) +{ + int num = 0, i = 0; + unsigned char *odata = NULL, *data = NULL; + Ecore_X_Window *newset = NULL, *oldset = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, 32, &odata, &num)) + { + if (!(newset = calloc(1, sizeof(Ecore_X_Window)))) return; + newset[0] = subwin; + num = 1; + data = (unsigned char *)newset; + } + else + { + if (!(newset = calloc(num + 1, sizeof(Ecore_X_Window)))) return; + oldset = (Ecore_X_Window *)odata; + for (i = 0; i < num; i++) + { + if (oldset[i] == subwin) + { + if (odata) free(odata); + odata = NULL; + free(newset); + return; + } + newset[i] = oldset[i]; + } + newset[num++] = subwin; + if (odata) free(odata); + data = (unsigned char *)newset; + } + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, 32, data, num); + free(newset); +} + +/** + * Remove a window from the list of colormap windows. + * @param win The toplevel window + * @param subwin The window to be removed from the colormap window list. + */ +EAPI void +ecore_x_icccm_colormap_window_unset(Ecore_X_Window win, + Ecore_X_Window subwin) +{ + int num = 0, i = 0, j = 0, k = 0; + unsigned char *odata = NULL, *data = NULL; + Ecore_X_Window *newset = NULL, *oldset = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, 32, &odata, &num)) + return; + + oldset = (Ecore_X_Window *)odata; + for (i = 0; i < num; i++) + { + if (oldset[i] == subwin) + { + if (num == 1) + { + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS); + if (odata) free(odata); + odata = NULL; + return; + } + else + { + newset = calloc(num - 1, sizeof(Ecore_X_Window)); + data = (unsigned char *)newset; + for (j = 0; j < num; ++j) + if (oldset[j] != subwin) + newset[k++] = oldset[j]; + + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + ECORE_X_ATOM_WINDOW, 32, data, k); + if (odata) free(odata); + odata = NULL; + free(newset); + return; + } + } + } + if (odata) free(odata); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_image.c b/src/lib/ecore_x/xcb/ecore_xcb_image.c new file mode 100644 index 0000000000..8e221101b0 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_image.c @@ -0,0 +1,738 @@ +#include "ecore_xcb_private.h" +#include <sys/ipc.h> +#include <sys/shm.h> +#include <xcb/xcb_event.h> +#include <xcb/shm.h> + +struct _Ecore_X_Image +{ + xcb_shm_segment_info_t shminfo; + xcb_image_t *xim; + Ecore_X_Visual vis; + int depth, w, h; + int bpl, bpp, rows; + unsigned char *data; + Eina_Bool shm : 1; +}; + +/* local function prototypes */ +static void _ecore_xcb_image_shm_check(void); +static void _ecore_xcb_image_shm_create(Ecore_X_Image *im); +static xcb_format_t *_ecore_xcb_image_find_format(const xcb_setup_t *setup, + uint8_t depth); + +/* local variables */ +static int _ecore_xcb_image_shm_can = -1; + +EAPI Ecore_X_Image * +ecore_x_image_new(int w, + int h, + Ecore_X_Visual vis, + int depth) +{ + Ecore_X_Image *im; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(im = calloc(1, sizeof(Ecore_X_Image)))) return NULL; + im->w = w; + im->h = h; + im->vis = vis; + im->depth = depth; + _ecore_xcb_image_shm_check(); + im->shm = _ecore_xcb_image_shm_can; + return im; +} + +EAPI void +ecore_x_image_free(Ecore_X_Image *im) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!im) return; + if (im->shm) + { + if (im->xim) + { + xcb_shm_detach(_ecore_xcb_conn, im->shminfo.shmseg); + xcb_image_destroy(im->xim); + shmdt(im->shminfo.shmaddr); + shmctl(im->shminfo.shmid, IPC_RMID, 0); + } + } + else if (im->xim) + { + if (im->xim->data) free(im->xim->data); + im->xim->data = NULL; + xcb_image_destroy(im->xim); + } + + free(im); +// ecore_x_flush(); +} + +EAPI Eina_Bool +ecore_x_image_get(Ecore_X_Image *im, + Ecore_X_Drawable draw, + int x, + int y, + int sx, + int sy, + int w, + int h) +{ + Eina_Bool ret = EINA_TRUE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (im->shm) + { + if (!im->xim) _ecore_xcb_image_shm_create(im); + if (!im->xim) return EINA_FALSE; + + if ((sx == 0) && (w == im->w)) + { + im->xim->data = (uint8_t *)im->data + (im->xim->stride * sy) + + (sx * im->bpp); + im->xim->width = w; + im->xim->height = h; + + ecore_x_grab(); + if (!xcb_image_shm_get(_ecore_xcb_conn, draw, im->xim, + im->shminfo, x, y, 0xffffffff)) + { + DBG("\tImage Shm Get Failed"); + ret = EINA_FALSE; + } + ecore_x_ungrab(); + ecore_x_sync(); // needed + } + else + { + Ecore_X_Image *tim; + + tim = ecore_x_image_new(w, h, im->vis, im->depth); + if (tim) + { + ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h); + if (ret) + { + unsigned char *spixels, *pixels; + int sbpp = 0, sbpl = 0, srows = 0; + int bpp = 0, bpl = 0, rows = 0; + + spixels = + ecore_x_image_data_get(tim, &sbpl, &srows, &sbpp); + pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp); + if ((spixels) && (pixels)) + { + unsigned char *p, *sp; + int r = 0; + + p = (pixels + (sy * bpl) + (sx * bpp)); + sp = spixels; + for (r = srows; r > 0; r--) + { + memcpy(p, sp, sbpl); + p += bpl; + sp += sbpl; + } + } + } + ecore_x_image_free(tim); + } + } + } + else + { + ret = EINA_FALSE; + ecore_x_grab(); + im->xim = + xcb_image_get(_ecore_xcb_conn, draw, x, y, w, h, + 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP); + if (!im->xim) ret = EINA_FALSE; + ecore_x_ungrab(); + ecore_x_sync(); // needed + + if (im->xim) + { + im->data = (unsigned char *)im->xim->data; + im->bpl = im->xim->stride; + im->rows = im->xim->height; + if (im->xim->bpp <= 8) + im->bpp = 1; + else if (im->xim->bpp <= 16) + im->bpp = 2; + else + im->bpp = 4; + } + } + + return ret; +} + +EAPI void * +ecore_x_image_data_get(Ecore_X_Image *im, + int *bpl, + int *rows, + int *bpp) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!im) return NULL; + if (!im->xim) _ecore_xcb_image_shm_create(im); + if (!im->xim) return NULL; + + if (bpl) *bpl = im->bpl; + if (rows) *rows = im->rows; + if (bpp) *bpp = im->bpp; + + return im->data; +} + +EAPI void +ecore_x_image_put(Ecore_X_Image *im, + Ecore_X_Drawable draw, + Ecore_X_GC gc, + int x, + int y, + int sx, + int sy, + int w, + int h) +{ + Ecore_X_GC tgc = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!gc) + { + uint32_t mask, values[1]; + + tgc = xcb_generate_id(_ecore_xcb_conn); + mask = XCB_GC_SUBWINDOW_MODE; + values[0] = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS; + xcb_create_gc(_ecore_xcb_conn, tgc, draw, mask, values); + gc = tgc; + } + if (!im->xim) _ecore_xcb_image_shm_create(im); + if (im->xim) + { + if (im->shm) + xcb_shm_put_image(_ecore_xcb_conn, draw, gc, im->xim->width, + im->xim->height, sx, sy, w, h, x, y, + im->xim->depth, im->xim->format, 0, + im->shminfo.shmseg, + im->xim->data - im->shminfo.shmaddr); +// xcb_image_shm_put(_ecore_xcb_conn, draw, gc, im->xim, +// im->shminfo, sx, sy, x, y, w, h, 0); + else + xcb_image_put(_ecore_xcb_conn, draw, gc, im->xim, sx, sy, 0); + } + if (tgc) ecore_x_gc_free(tgc); + ecore_x_sync(); +} + +EAPI Eina_Bool +ecore_x_image_is_argb32_get(Ecore_X_Image *im) +{ + xcb_visualtype_t *vis; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + vis = (xcb_visualtype_t *)im->vis; + if (!im->xim) _ecore_xcb_image_shm_create(im); + + if (((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) || + (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) && + (im->depth >= 24) && (vis->red_mask == 0xff0000) && + (vis->green_mask == 0x00ff00) && (vis->blue_mask == 0x0000ff)) + { +#ifdef WORDS_BIGENDIAN + if (im->xim->byte_order == XCB_IMAGE_ORDER_MSB_FIRST) return EINA_TRUE; +#else + if (im->xim->byte_order == XCB_IMAGE_ORDER_LSB_FIRST) return EINA_TRUE; +#endif + } + + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_image_to_argb_convert(void *src, + int sbpp, + int sbpl, + Ecore_X_Colormap c, + Ecore_X_Visual v, + int x, + int y, + int w, + int h, + unsigned int *dst, + int dbpl, + int dx, + int dy) +{ + xcb_visualtype_t *vis; + uint32_t *cols; + int n = 0, nret = 0, i, row, mode = 0; + unsigned int pal[256], r, g, b; + enum + { + rgbnone = 0, + rgb565, + bgr565, + rgbx555, + argbx888, + abgrx888, + rgba888x, + bgra888x, + argbx666 + }; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + sbpp *= 8; + + vis = (xcb_visualtype_t *)v; + n = vis->colormap_entries; + if ((n <= 256) && + ((vis->_class == XCB_VISUAL_CLASS_PSEUDO_COLOR) || + (vis->_class == XCB_VISUAL_CLASS_STATIC_COLOR) || + (vis->_class == XCB_VISUAL_CLASS_GRAY_SCALE) || + (vis->_class == XCB_VISUAL_CLASS_STATIC_GRAY))) + { + xcb_query_colors_cookie_t cookie; + xcb_query_colors_reply_t *reply; + + if (!c) + { + c = (xcb_colormap_t)((xcb_screen_t *) + _ecore_xcb_screen)->default_colormap; + } + + cols = alloca(n * sizeof(uint32_t)); + for (i = 0; i < n; i++) + cols[i] = i; + + cookie = xcb_query_colors_unchecked(_ecore_xcb_conn, c, n, cols); + reply = xcb_query_colors_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + xcb_rgb_iterator_t iter; + xcb_rgb_t *ret; + + iter = xcb_query_colors_colors_iterator(reply); + ret = xcb_query_colors_colors(reply); + if (ret) + { + for (i = 0; iter.rem; xcb_rgb_next(&iter), i++) + { + pal[i] = 0xff000000 | + ((iter.data->red >> 8) << 16) | + ((iter.data->green >> 8) << 8) | + ((iter.data->blue >> 8)); + } + nret = n; + } + free(reply); + } + } + else if ((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) || + (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) + { + if ((vis->red_mask == 0x00ff0000) && + (vis->green_mask == 0x0000ff00) && + (vis->blue_mask == 0x000000ff)) + mode = argbx888; + else if ((vis->red_mask == 0x000000ff) && + (vis->green_mask == 0x0000ff00) && + (vis->blue_mask == 0x00ff0000)) + mode = abgrx888; + else if ((vis->red_mask == 0xff000000) && + (vis->green_mask == 0x00ff0000) && + (vis->blue_mask == 0x0000ff00)) + mode = rgba888x; + else if ((vis->red_mask == 0x0000ff00) && + (vis->green_mask == 0x00ff0000) && + (vis->blue_mask == 0xff000000)) + mode = bgra888x; + else if ((vis->red_mask == 0x0003f000) && + (vis->green_mask == 0x00000fc0) && + (vis->blue_mask == 0x0000003f)) + mode = argbx666; + else if ((vis->red_mask == 0x0000f800) && + (vis->green_mask == 0x000007e0) && + (vis->blue_mask == 0x0000001f)) + mode = rgb565; + else if ((vis->red_mask == 0x0000001f) && + (vis->green_mask == 0x000007e0) && + (vis->blue_mask == 0x0000f800)) + mode = bgr565; + else if ((vis->red_mask == 0x00007c00) && + (vis->green_mask == 0x000003e0) && + (vis->blue_mask == 0x0000001f)) + mode = rgbx555; + else + return EINA_FALSE; + } + for (row = 0; row < h; row++) + { + unsigned char *s8; + unsigned short *s16; + unsigned int *s32, *dp, *de; + + dp = ((unsigned int *)(((unsigned char *)dst) + + ((dy + row) * dbpl))) + dx; + de = dp + w; + switch (sbpp) + { + case 8: + s8 = ((unsigned char *)(((unsigned char *)src) + + ((y + row) * sbpl))) + x; + if (nret > 0) + { + while (dp < de) + { + *dp = pal[*s8]; + s8++; dp++; + } + } + else + return EINA_FALSE; + break; + + case 16: + s16 = ((unsigned short *)(((unsigned char *)src) + + ((y + row) * sbpl))) + x; + switch (mode) + { + case rgb565: + while (dp < de) + { + r = (*s16 & 0xf800) << 8; + g = (*s16 & 0x07e0) << 5; + b = (*s16 & 0x001f) << 3; + r |= (r >> 5) & 0xff0000; + g |= (g >> 6) & 0x00ff00; + b |= (b >> 5); + *dp = 0xff000000 | r | g | b; + s16++; dp++; + } + break; + + case bgr565: + while (dp < de) + { + r = (*s16 & 0x001f) << 19; + g = (*s16 & 0x07e0) << 5; + b = (*s16 & 0xf800) >> 8; + r |= (r >> 5) & 0xff0000; + g |= (g >> 6) & 0x00ff00; + b |= (b >> 5); + *dp = 0xff000000 | r | g | b; + s16++; dp++; + } + break; + + case rgbx555: + while (dp < de) + { + r = (*s16 & 0x7c00) << 9; + g = (*s16 & 0x03e0) << 6; + b = (*s16 & 0x001f) << 3; + r |= (r >> 5) & 0xff0000; + g |= (g >> 5) & 0x00ff00; + b |= (b >> 5); + *dp = 0xff000000 | r | g | b; + s16++; dp++; + } + break; + + default: + return EINA_FALSE; + break; + } + break; + + case 24: + case 32: + s32 = ((unsigned int *)(((unsigned char *)src) + + ((y + row) * sbpl))) + x; + switch (mode) + { + case argbx888: + while (dp < de) + { + *dp = 0xff000000 | *s32; + s32++; dp++; + } + break; + + case abgrx888: + while (dp < de) + { + r = *s32 & 0x000000ff; + g = *s32 & 0x0000ff00; + b = *s32 & 0x00ff0000; + *dp = 0xff000000 | (r << 16) | (g) | (b >> 16); + s32++; dp++; + } + break; + + case rgba888x: + while (dp < de) + { + *dp = 0xff000000 | (*s32 >> 8); + s32++; dp++; + } + break; + + case bgra888x: + while (dp < de) + { + r = *s32 & 0x0000ff00; + g = *s32 & 0x00ff0000; + b = *s32 & 0xff000000; + *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24); + s32++; dp++; + } + break; + + case argbx666: + while (dp < de) + { + r = (*s32 & 0x3f000) << 6; + g = (*s32 & 0x00fc0) << 4; + b = (*s32 & 0x0003f) << 2; + r |= (r >> 6) & 0xff0000; + g |= (g >> 6) & 0x00ff00; + b |= (b >> 6); + *dp = 0xff000000 | r | g | b; + s32++; dp++; + } + break; + + default: + return EINA_FALSE; + break; + } + break; + break; + + default: + return EINA_FALSE; + break; + } + } + return EINA_TRUE; +} + +/* local functions */ +static void +_ecore_xcb_image_shm_check(void) +{ +// xcb_shm_query_version_reply_t *reply; + xcb_shm_segment_info_t shminfo; + xcb_shm_get_image_cookie_t cookie; + xcb_shm_get_image_reply_t *ireply; + xcb_image_t *img = 0; + uint8_t depth = 0; + + if (_ecore_xcb_image_shm_can != -1) return; + CHECK_XCB_CONN; + + /* reply = */ + /* xcb_shm_query_version_reply(_ecore_xcb_conn, */ + /* xcb_shm_query_version(_ecore_xcb_conn), NULL); */ + /* if (!reply) */ + /* { */ + /* _ecore_xcb_image_shm_can = 0; */ + /* return; */ + /* } */ + + /* if ((reply->major_version < 1) || */ + /* ((reply->major_version == 1) && (reply->minor_version == 0))) */ + /* { */ + /* _ecore_xcb_image_shm_can = 0; */ + /* free(reply); */ + /* return; */ + /* } */ + + /* free(reply); */ + + depth = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth; + + ecore_x_sync(); // needed + + img = _ecore_xcb_image_create_native(1, 1, XCB_IMAGE_FORMAT_Z_PIXMAP, + depth, NULL, ~0, NULL); + if (!img) + { + _ecore_xcb_image_shm_can = 0; + return; + } + + shminfo.shmid = + shmget(IPC_PRIVATE, img->stride * img->height, (IPC_CREAT | 0666)); + if (shminfo.shmid == (uint32_t)-1) + { + xcb_image_destroy(img); + _ecore_xcb_image_shm_can = 0; + return; + } + + shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); + img->data = shminfo.shmaddr; + if (img->data == (uint8_t *)-1) + { + xcb_image_destroy(img); + _ecore_xcb_image_shm_can = 0; + return; + } + + shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn); + xcb_shm_attach(_ecore_xcb_conn, shminfo.shmseg, shminfo.shmid, 0); + + cookie = + xcb_shm_get_image(_ecore_xcb_conn, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + 0, 0, img->width, img->height, + 0xffffffff, img->format, + shminfo.shmseg, img->data - shminfo.shmaddr); + + ecore_x_sync(); // needed + + ireply = xcb_shm_get_image_reply(_ecore_xcb_conn, cookie, NULL); + if (ireply) + { + _ecore_xcb_image_shm_can = 1; + free(ireply); + } + else + _ecore_xcb_image_shm_can = 0; + + xcb_shm_detach(_ecore_xcb_conn, shminfo.shmseg); + xcb_image_destroy(img); + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); +} + +static void +_ecore_xcb_image_shm_create(Ecore_X_Image *im) +{ + CHECK_XCB_CONN; + + im->xim = + _ecore_xcb_image_create_native(im->w, im->h, XCB_IMAGE_FORMAT_Z_PIXMAP, + im->depth, NULL, ~0, NULL); + if (!im->xim) return; + + im->shminfo.shmid = shmget(IPC_PRIVATE, im->xim->size, (IPC_CREAT | 0666)); + if (im->shminfo.shmid == (uint32_t)-1) + { + xcb_image_destroy(im->xim); + return; + } + + im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0); + im->xim->data = im->shminfo.shmaddr; + if ((!im->xim->data) || (im->xim->data == (uint8_t *)-1)) + { + DBG("Shm Create No Image Data"); + xcb_image_destroy(im->xim); + shmdt(im->shminfo.shmaddr); + shmctl(im->shminfo.shmid, IPC_RMID, 0); + return; + } + + im->shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn); + xcb_shm_attach(_ecore_xcb_conn, im->shminfo.shmseg, im->shminfo.shmid, 0); + + im->data = (unsigned char *)im->xim->data; + im->bpl = im->xim->stride; + im->rows = im->xim->height; + if (im->xim->bpp <= 8) + im->bpp = 1; + else if (im->xim->bpp <= 16) + im->bpp = 2; + else + im->bpp = 4; +} + +xcb_image_t * +_ecore_xcb_image_create_native(int w, + int h, + xcb_image_format_t format, + uint8_t depth, + void *base, + uint32_t bytes, + uint8_t *data) +{ + static uint8_t dpth = 0; + static xcb_format_t *fmt = NULL; + const xcb_setup_t *setup; + xcb_image_format_t xif; + + CHECK_XCB_CONN; + + /* NB: We cannot use xcb_image_create_native as it only creates images + * using MSB_FIRST, so this routine recreates that function and uses + * the endian-ness of the server setup */ + setup = xcb_get_setup(_ecore_xcb_conn); + xif = format; + + if ((xif == XCB_IMAGE_FORMAT_Z_PIXMAP) && (depth == 1)) + xif = XCB_IMAGE_FORMAT_XY_PIXMAP; + + if (dpth != depth) + { + dpth = depth; + fmt = _ecore_xcb_image_find_format(setup, depth); + if (!fmt) return 0; + } + + switch (xif) + { + case XCB_IMAGE_FORMAT_XY_BITMAP: + if (depth != 1) return 0; + + case XCB_IMAGE_FORMAT_XY_PIXMAP: + case XCB_IMAGE_FORMAT_Z_PIXMAP: + return xcb_image_create(w, h, xif, + fmt->scanline_pad, + fmt->depth, fmt->bits_per_pixel, + setup->bitmap_format_scanline_unit, + setup->image_byte_order, + setup->bitmap_format_bit_order, + base, bytes, data); + + default: + break; + } + + return 0; +} + +static xcb_format_t * +_ecore_xcb_image_find_format(const xcb_setup_t *setup, + uint8_t depth) +{ + xcb_format_t *fmt, *fmtend; + + CHECK_XCB_CONN; + + fmt = xcb_setup_pixmap_formats(setup); + fmtend = fmt + xcb_setup_pixmap_formats_length(setup); + for (; fmt != fmtend; ++fmt) + if (fmt->depth == depth) + return fmt; + + return 0; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_input.c b/src/lib/ecore_x/xcb/ecore_xcb_input.c new file mode 100644 index 0000000000..6cf3ebf6e6 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_input.c @@ -0,0 +1,274 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_XINPUT +# include <xcb/xinput.h> +# include <xcb/xcb_event.h> +#endif + +/* FIXME: this is a guess. can't find defines for touch events in xcb libs + * online */ +/* these are not yet defined in xcb support for xi2 - so manually create */ +#ifndef XCB_INPUT_DEVICE_TOUCH_BEGIN +#define XCB_INPUT_DEVICE_TOUCH_BEGIN 18 +#endif +#ifndef XCB_INPUT_DEVICE_TOUCH_END +#define XCB_INPUT_DEVICE_TOUCH_END 19 +#endif +#ifndef XCB_INPUT_DEVICE_TOUCH_UPDATE +#define XCB_INPUT_DEVICE_TOUCH_UPDATE 21 +#endif + +#ifndef XCB_INPUT_POINTER_EMULATED_MASK +#define XCB_INPUT_POINTER_EMULATED_MASK (1 << 16) +#endif + +/* local variables */ +static Eina_Bool _input_avail = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_input = 0; + +void +_ecore_xcb_input_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XINPUT + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_input_id); +#endif +} + +void +_ecore_xcb_input_finalize(void) +{ +#ifdef ECORE_XCB_XINPUT + xcb_input_get_extension_version_cookie_t cookie; + xcb_input_get_extension_version_reply_t *reply; + char buff[128]; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XINPUT + cookie = + xcb_input_get_extension_version_unchecked(_ecore_xcb_conn, 127, buff); + reply = + xcb_input_get_extension_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + _input_avail = EINA_TRUE; + free(reply); + } + + if (_input_avail) + { + const xcb_query_extension_reply_t *ext_reply; + + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_input_id); + if (ext_reply) + _ecore_xcb_event_input = ext_reply->first_event; + } +#endif +} + +void +_ecore_xcb_input_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +void +#ifdef ECORE_XCB_XINPUT +_ecore_xcb_input_handle_event(xcb_generic_event_t *event) +#else +_ecore_xcb_input_handle_event(xcb_generic_event_t * event EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XINPUT + xcb_ge_event_t *ev; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + /* FIXME: look at xlib ecore_x_xi2.c to copy logic in when i can find an + * xcb-input lib to test with */ +#ifdef ECORE_XCB_XINPUT + ev = (xcb_ge_event_t *)event; + switch (ev->event_type) + { + case XCB_INPUT_DEVICE_MOTION_NOTIFY: + { + xcb_input_device_motion_notify_event_t *de; + unsigned int child_win = 0; + + de = (xcb_input_device_motion_notify_event_t *)ev->pad1; + child_win = (de->child ? de->child : de->event); + _ecore_xcb_event_mouse_move(de->time, de->state, de->event_x, + de->event_y, de->root_x, de->root_y, + de->event, child_win, de->root, + de->same_screen, de->device_id, + 1, 1, 1.0, 0.0, + de->event_x, de->event_y, + de->root_x, de->root_y); + } + break; + + case XCB_INPUT_DEVICE_BUTTON_PRESS: + { + xcb_input_device_button_press_event_t *de; + unsigned int child_win = 0; + + de = (xcb_input_device_button_press_event_t *)ev->pad1; + child_win = (de->child ? de->child : de->event); + _ecore_xcb_event_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN, + de->time, de->state, de->detail, + de->event_x, de->event_y, + de->root_x, de->root_y, de->event, + child_win, de->root, + de->same_screen, de->device_id, + 1, 1, 1.0, 0.0, + de->event_x, de->event_y, + de->root_x, de->root_y); + } + break; + + case XCB_INPUT_DEVICE_BUTTON_RELEASE: + { + xcb_input_device_button_release_event_t *de; + unsigned int child_win = 0; + + de = (xcb_input_device_button_release_event_t *)ev->pad1; + child_win = (de->child ? de->child : de->event); + _ecore_xcb_event_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP, + de->time, de->state, de->detail, + de->event_x, de->event_y, + de->root_x, de->root_y, de->event, + child_win, de->root, + de->same_screen, de->device_id, + 1, 1, 1.0, 0.0, + de->event_x, de->event_y, + de->root_x, de->root_y); + } + break; + + case XCB_INPUT_DEVICE_TOUCH_UPDATE: + { + xcb_input_device_motion_notify_event_t *de; + unsigned int child_win = 0; + + de = (xcb_input_device_motion_notify_event_t *)ev->pad1; + child_win = (de->child ? de->child : de->event); + _ecore_xcb_event_mouse_move(de->time, de->state, de->event_x, + de->event_y, de->root_x, de->root_y, + de->event, child_win, de->root, + de->same_screen, de->device_id, + 1, 1, 1.0, 0.0, + de->event_x, de->event_y, + de->root_x, de->root_y); + } + break; + + case XCB_INPUT_DEVICE_TOUCH_BEGIN: + { + xcb_input_device_button_press_event_t *de; + unsigned int child_win = 0; + + de = (xcb_input_device_button_press_event_t *)ev->pad1; + child_win = (de->child ? de->child : de->event); + _ecore_xcb_event_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN, + de->time, de->state, de->detail, + de->event_x, de->event_y, + de->root_x, de->root_y, de->event, + child_win, de->root, + de->same_screen, de->device_id, + 1, 1, 1.0, 0.0, + de->event_x, de->event_y, + de->root_x, de->root_y); + } + break; + + case XCB_INPUT_DEVICE_TOUCH_END: + { + xcb_input_device_button_release_event_t *de; + unsigned int child_win = 0; + + de = (xcb_input_device_button_release_event_t *)ev->pad1; + child_win = (de->child ? de->child : de->event); + _ecore_xcb_event_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP, + de->time, de->state, de->detail, + de->event_x, de->event_y, + de->root_x, de->root_y, de->event, + child_win, de->root, + de->same_screen, de->device_id, + 1, 1, 1.0, 0.0, + de->event_x, de->event_y, + de->root_x, de->root_y); + } + break; + + default: + break; + } +#endif +} + +EAPI Eina_Bool +ecore_x_input_multi_select(Ecore_X_Window win) +{ + Eina_Bool find = EINA_FALSE; +#ifdef ECORE_XCB_XINPUT + xcb_input_list_input_devices_cookie_t dcookie; + xcb_input_list_input_devices_reply_t *dreply; + xcb_input_device_info_iterator_t diter; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_input_avail) return EINA_FALSE; + + /* FIXME: i can't seemingly test this! no xcb input lib so can't look and + * test and look at types etc. - look at xlib code and copy logic over + * when we can */ +#ifdef ECORE_XCB_XINPUT + dcookie = xcb_input_list_input_devices_unchecked(_ecore_xcb_conn); + dreply = + xcb_input_list_input_devices_reply(_ecore_xcb_conn, dcookie, NULL); + if (!dreply) return EINA_FALSE; + + diter = xcb_input_list_input_devices_devices_iterator(dreply); + while (diter.rem) + { + xcb_input_device_info_t *dev; + const xcb_input_event_class_t iclass[] = + { + XCB_INPUT_DEVICE_BUTTON_PRESS, + XCB_INPUT_DEVICE_BUTTON_RELEASE, + XCB_INPUT_DEVICE_MOTION_NOTIFY, + XCB_INPUT_DEVICE_TOUCH_BEGIN, + XCB_INPUT_DEVICE_TOUCH_END, + XCB_INPUT_DEVICE_TOUCH_UPDATE + }; + + dev = diter.data; + if (dev->device_use == XCB_INPUT_DEVICE_USE_IS_X_EXTENSION_DEVICE) + { + DBG("Device %d", dev->device_id); + DBG("\tType: %d", dev->device_type); + DBG("\tNum Classes: %d", dev->num_class_info); + DBG("\tUse: %d", dev->device_use); + + xcb_input_select_extension_event(_ecore_xcb_conn, win, + sizeof(iclass) / sizeof(xcb_input_event_class_t), + iclass); + find = EINA_TRUE; + } + xcb_input_device_info_next(&diter); + } + free(dreply); +#endif + + return find; + win = 0; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_keymap.c b/src/lib/ecore_x/xcb/ecore_xcb_keymap.c new file mode 100644 index 0000000000..6c112464b0 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_keymap.c @@ -0,0 +1,491 @@ +#include "ecore_xcb_private.h" +#define NEED_KEYSYM_TABLE +#define NEED_VTABLE +#include "ecore_xcb_keysym_table.h" +#include <xcb/xcb_keysyms.h> +#include <X11/keysym.h> + +/* local function prototypes */ +static int _ecore_xcb_keymap_mask_get(void *reply, + xcb_keysym_t sym); +static xcb_keysym_t _ecore_xcb_keymap_string_to_keysym(const char *str); +static int _ecore_xcb_keymap_translate_key(xcb_keycode_t keycode, + unsigned int modifiers, + unsigned int *modifiers_return, + xcb_keysym_t *keysym_return); +static int _ecore_xcb_keymap_translate_keysym(xcb_keysym_t keysym, + unsigned int modifiers, + char *buffer, + int bytes); + +/* local variables */ +static xcb_key_symbols_t *_ecore_xcb_keysyms; +static int _ecore_xcb_mode_switch = 0; + +/* public variables */ +EAPI int ECORE_X_MODIFIER_SHIFT = 0; +EAPI int ECORE_X_MODIFIER_CTRL = 0; +EAPI int ECORE_X_MODIFIER_ALT = 0; +EAPI int ECORE_X_MODIFIER_WIN = 0; +EAPI int ECORE_X_MODIFIER_ALTGR = 0; +EAPI int ECORE_X_LOCK_SCROLL = 0; +EAPI int ECORE_X_LOCK_NUM = 0; +EAPI int ECORE_X_LOCK_CAPS = 0; +EAPI int ECORE_X_LOCK_SHIFT = 0; + +void +_ecore_xcb_keymap_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_keysyms = xcb_key_symbols_alloc(_ecore_xcb_conn); +} + +void +_ecore_xcb_keymap_finalize(void) +{ + xcb_get_modifier_mapping_cookie_t cookie; + xcb_get_modifier_mapping_reply_t *reply; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_modifier_mapping_unchecked(_ecore_xcb_conn); + reply = xcb_get_modifier_mapping_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + { + xcb_key_symbols_free(_ecore_xcb_keysyms); + return; + } + + _ecore_xcb_mode_switch = _ecore_xcb_keymap_mask_get(reply, XK_Mode_switch); + + ECORE_X_MODIFIER_SHIFT = _ecore_xcb_keymap_mask_get(reply, XK_Shift_L); + ECORE_X_MODIFIER_CTRL = _ecore_xcb_keymap_mask_get(reply, XK_Control_L); + + ECORE_X_MODIFIER_ALT = _ecore_xcb_keymap_mask_get(reply, XK_Alt_L); + if (!ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_ALT = _ecore_xcb_keymap_mask_get(reply, XK_Meta_L); + if (!ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_ALT = _ecore_xcb_keymap_mask_get(reply, XK_Super_L); + + ECORE_X_MODIFIER_WIN = _ecore_xcb_keymap_mask_get(reply, XK_Super_L); + if (!ECORE_X_MODIFIER_WIN) + ECORE_X_MODIFIER_WIN = _ecore_xcb_keymap_mask_get(reply, XK_Meta_L); + + ECORE_X_MODIFIER_ALTGR = _ecore_xcb_keymap_mask_get(reply, XK_Mode_switch); + + if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_WIN = 0; + if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL) + ECORE_X_MODIFIER_ALT = 0; + + ECORE_X_LOCK_SCROLL = _ecore_xcb_keymap_mask_get(reply, XK_Scroll_Lock); + ECORE_X_LOCK_NUM = _ecore_xcb_keymap_mask_get(reply, XK_Num_Lock); + ECORE_X_LOCK_CAPS = _ecore_xcb_keymap_mask_get(reply, XK_Caps_Lock); + ECORE_X_LOCK_SHIFT = _ecore_xcb_keymap_mask_get(reply, XK_Shift_Lock); +} + +void +_ecore_xcb_modifiers_get(void) +{ + _ecore_xcb_keymap_finalize(); +} + +void +_ecore_xcb_keymap_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (_ecore_xcb_keysyms) xcb_key_symbols_free(_ecore_xcb_keysyms); +} + +void +_ecore_xcb_keymap_refresh(xcb_mapping_notify_event_t *event) +{ + CHECK_XCB_CONN; + xcb_refresh_keyboard_mapping(_ecore_xcb_keysyms, event); +} + +xcb_keysym_t +_ecore_xcb_keymap_keycode_to_keysym(xcb_keycode_t keycode, + int col) +{ + xcb_keysym_t key0, key1; + + CHECK_XCB_CONN; + if (col & _ecore_xcb_mode_switch) + { + key0 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 4); + key1 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 5); + } + else + { + key0 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 0); + key1 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 1); + } + + if (key1 == XCB_NO_SYMBOL) + key1 = key0; + + if ((col & ECORE_X_LOCK_NUM) && + ((xcb_is_keypad_key(key1)) || (xcb_is_private_keypad_key(key1)))) + { + if ((col & XCB_MOD_MASK_SHIFT) || + ((col & XCB_MOD_MASK_LOCK) && (col & ECORE_X_LOCK_SHIFT))) + return key0; + else + return key1; + } + else if (!(col & XCB_MOD_MASK_SHIFT) && !(col & XCB_MOD_MASK_LOCK)) + return key0; + else if (!(col & XCB_MOD_MASK_SHIFT) && + (col & XCB_MOD_MASK_LOCK && (col & ECORE_X_LOCK_CAPS))) + return key1; + else if ((col & XCB_MOD_MASK_SHIFT) && + (col & XCB_MOD_MASK_LOCK) && (col & ECORE_X_LOCK_CAPS)) + return key0; + else if ((col & XCB_MOD_MASK_SHIFT) || + (col & XCB_MOD_MASK_LOCK && (col & ECORE_X_LOCK_SHIFT))) + return key1; + + return XCB_NO_SYMBOL; +} + +xcb_keycode_t * +_ecore_xcb_keymap_keysym_to_keycode(xcb_keysym_t keysym) +{ + CHECK_XCB_CONN; + return xcb_key_symbols_get_keycode(_ecore_xcb_keysyms, keysym); +} + +char * +_ecore_xcb_keymap_keysym_to_string(xcb_keysym_t keysym) +{ + int i = 0, n = 0, h = 0, idx = 0; + const unsigned char *entry; + unsigned char val1, val2, val3, val4; + + CHECK_XCB_CONN; + if (!keysym) return NULL; + if (keysym == XK_VoidSymbol) keysym = 0; + if (keysym <= 0x1fffffff) + { + val1 = (keysym >> 24); + val2 = ((keysym >> 16) & 0xff); + val3 = ((keysym >> 8) & 0xff); + val4 = (keysym & 0xff); + i = keysym % VTABLESIZE; + h = i + 1; + n = VMAXHASH; + while ((idx = hashKeysym[i])) + { + entry = &_ecore_xcb_keytable[idx]; + if ((entry[0] == val1) && (entry[1] == val2) && + (entry[2] == val3) && (entry[3] == val4)) + return (char *)entry + 4; + if (!--n) break; + i += h; + if (i >= VTABLESIZE) i -= VTABLESIZE; + } + } + + if ((keysym >= 0x01000100) && (keysym <= 0x0110ffff)) + { + xcb_keysym_t val; + char *s = NULL; + int i = 0; + + val = (keysym & 0xffffff); + if (val & 0xff0000) + i = 10; + else + i = 6; + + if (!(s = malloc(i))) return NULL; + i--; + s[i--] = '\0'; + for (; i; i--) + { + val1 = (val & 0xf); + val >>= 4; + if (val1 < 10) + s[i] = '0' + val1; + else + s[i] = 'A' + val1 - 10; + } + s[i] = 'U'; + return s; + } + + return NULL; +} + +xcb_keycode_t +_ecore_xcb_keymap_string_to_keycode(const char *key) +{ + if (!strncmp(key, "Keycode-", 8)) + return atoi(key + 8); + else + { + xcb_keysym_t keysym = XCB_NO_SYMBOL; + xcb_keycode_t *keycodes, keycode = 0; + int i = 0; + + CHECK_XCB_CONN; + + keysym = _ecore_xcb_keymap_string_to_keysym(key); + if (keysym == XCB_NO_SYMBOL) return XCB_NO_SYMBOL; + + keycodes = _ecore_xcb_keymap_keysym_to_keycode(keysym); + if (!keycodes) return XCB_NO_SYMBOL; + + while (keycodes[i] != XCB_NO_SYMBOL) + { + if (keycodes[i] != 0) + { + keycode = keycodes[i]; + break; + } + i++; + } + return keycode; + } +} + +int +_ecore_xcb_keymap_lookup_string(xcb_keycode_t keycode, + int state, + char *buffer, + int bytes, + xcb_keysym_t *sym) +{ + unsigned int modifiers = 0; + xcb_keysym_t keysym; + + CHECK_XCB_CONN; + if (!_ecore_xcb_keymap_translate_key(keycode, state, &modifiers, &keysym)) + return 0; + + if (sym) *sym = keysym; + + return _ecore_xcb_keymap_translate_keysym(keysym, state, buffer, bytes); +} + +EAPI const char * +ecore_x_keysym_string_get(int keysym) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_keymap_keysym_to_string(keysym); +} + +EAPI int +ecore_x_keysym_keycode_get(const char *keyname) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_keymap_string_to_keycode(keyname); +} + +/* local functions */ +static int +_ecore_xcb_keymap_mask_get(void *reply, + xcb_keysym_t sym) +{ + xcb_get_modifier_mapping_reply_t *rep; + xcb_keysym_t sym2; + int mask = 0; + const int masks[8] = + { + XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL, + XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4, + XCB_MOD_MASK_5 + }; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + rep = (xcb_get_modifier_mapping_reply_t *)reply; + if ((rep) && (rep->keycodes_per_modifier > 0)) + { + int i = 0; + xcb_keycode_t *modmap; + + modmap = xcb_get_modifier_mapping_keycodes(rep); + for (i = 0; i < (8 * rep->keycodes_per_modifier); i++) + { + int j = 0; + + for (j = 0; j < 8; j++) + { + sym2 = + xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, + modmap[i], j); + if (sym2 != 0) break; + } + if (sym2 == sym) + { + mask = masks[i / rep->keycodes_per_modifier]; + break; + } + } + } + + return mask; +} + +static xcb_keysym_t +_ecore_xcb_keymap_string_to_keysym(const char *str) +{ + int i = 0, n = 0, h = 0; + unsigned long sig = 0; + const char *p = NULL; + int c = 0, idx = 0; + const unsigned char *entry; + unsigned char sig1, sig2; + long unsigned int val; + + p = str; + while ((c = *p++)) + sig = (sig << 1) + c; + + i = (sig % KTABLESIZE); + h = i + 1; + sig1 = (sig >> 8) & 0xff; + sig2 = sig & 0xff; + n = KMAXHASH; + + while ((idx = hashString[i])) + { + entry = &_ecore_xcb_keytable[idx]; + if ((entry[0] == sig1) && (entry[1] == sig2) && + !strcmp(str, (char *)entry + 6)) + { + val = ((entry[2] << 24) | (entry[3] << 16) | + (entry[4] << 8) | (entry[5])); + if (!val) val = 0xffffff; + return val; + } + if (!--n) break; + i += h; + if (i >= KTABLESIZE) i -= KTABLESIZE; + } + + if (*str == 'U') + { + val = 0; + for (p = &str[1]; *p; p++) + { + c = *p; + if (('0' <= c) && (c <= '9')) + val = (val << 4) + c - '0'; + else if (('a' <= c) && (c <= 'f')) + val = (val << 4) + c - 'a' + 10; + else if (('A' <= c) && (c <= 'F')) + val = (val << 4) + c - 'A' + 10; + else + return XCB_NO_SYMBOL; + if (val > 0x10ffff) return XCB_NO_SYMBOL; + } + if ((val < 0x20) || ((val > 0x7e) && (val < 0xa0))) + return XCB_NO_SYMBOL; + if (val < 0x100) return val; + return val | 0x01000000; + } + + if ((strlen(str) > 2) && (str[0] == '0') && (str[1] == 'x')) + { + char *tmp = NULL; + + val = strtoul(str, &tmp, 16); + if ((val == ULONG_MAX) || ((tmp) && (*tmp != '\0'))) + return XCB_NO_SYMBOL; + else + return val; + } + + if (!strncmp(str, "XF86_", 5)) + { + long unsigned int ret; + char *tmp; + + tmp = strdup(str); + if (!tmp) return XCB_NO_SYMBOL; + memmove(&tmp[4], &tmp[5], strlen(str) - 5 + 1); + ret = _ecore_xcb_keymap_string_to_keysym(tmp); + free(tmp); + return ret; + } + + return XCB_NO_SYMBOL; +} + +static int +_ecore_xcb_keymap_translate_key(xcb_keycode_t keycode, + unsigned int modifiers, + unsigned int *modifiers_return, + xcb_keysym_t *keysym_return) +{ + xcb_keysym_t sym; + + if (!_ecore_xcb_keysyms) return 0; + + sym = _ecore_xcb_keymap_keycode_to_keysym(keycode, modifiers); + + if (modifiers_return) + *modifiers_return = ((XCB_MOD_MASK_SHIFT | XCB_MOD_MASK_LOCK) | + _ecore_xcb_mode_switch | ECORE_X_LOCK_NUM); + if (keysym_return) + *keysym_return = sym; + + return 1; +} + +static int +_ecore_xcb_keymap_translate_keysym(xcb_keysym_t keysym, + unsigned int modifiers, + char *buffer, + int bytes) +{ + unsigned long hbytes = 0; + unsigned char c; + + if (!keysym) return 0; + hbytes = (keysym >> 8); + + if (!(bytes && + ((hbytes == 0) || + ((hbytes == 0xFF) && + (((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) || + (keysym == XK_Return) || (keysym == XK_Escape) || + (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) || + (keysym == XK_KP_Enter) || + ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) || + (keysym == XK_KP_Equal) || (keysym == XK_Delete)))))) + return 0; + + if (keysym == XK_KP_Space) + c = (XK_space & 0x7F); + else if (hbytes == 0xFF) + c = (keysym & 0x7F); + else + c = (keysym & 0xFF); + + if (modifiers & ECORE_X_MODIFIER_CTRL) + { + if (((c >= '@') && (c < '\177')) || c == ' ') + c &= 0x1F; + else if (c == '2') + c = '\000'; + else if ((c >= '3') && (c <= '7')) + c -= ('3' - '\033'); + else if (c == '8') + c = '\177'; + else if (c == '/') + c = '_' & 0x1F; + } + buffer[0] = c; + return 1; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_mwm.c b/src/lib/ecore_x/xcb/ecore_xcb_mwm.c new file mode 100644 index 0000000000..6c9533136f --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_mwm.c @@ -0,0 +1,104 @@ +#include "ecore_xcb_private.h" +//#include "Ecore_X_Atoms.h" + +#define ECORE_X_MWM_HINTS_FUNCTIONS (1 << 0) +#define ECORE_X_MWM_HINTS_DECORATIONS (1 << 1) +#define ECORE_X_MWM_HINTS_INPUT_MODE (1 << 2) +#define ECORE_X_MWM_HINTS_STATUS (1 << 3) + +typedef struct _mwmhints +{ + uint32_t flags; + uint32_t functions; + uint32_t decorations; + int32_t inputmode; + uint32_t status; +} MWMHints; + +/** + * @defgroup Ecore_X_MWM_Group MWM related functions. + * + * Functions related to MWM. + */ + +/** + * Sets the borderless flag of a window using MWM. + * + * @param win The window. + * @param borderless The borderless flag. + * + * @ingroup Ecore_X_MWM_Group + */ +EAPI void +ecore_x_mwm_borderless_set(Ecore_X_Window win, + Eina_Bool borderless) +{ + uint32_t data[5] = { 0, 0, 0, 0, 0 }; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + data[0] = 2; + data[2] = !borderless; + + ecore_x_window_prop_property_set(win, + ECORE_X_ATOM_MOTIF_WM_HINTS, + ECORE_X_ATOM_MOTIF_WM_HINTS, 32, + (void *)data, 5); +} + +EAPI Eina_Bool +ecore_x_mwm_hints_get(Ecore_X_Window win, + Ecore_X_MWM_Hint_Func *fhint, + Ecore_X_MWM_Hint_Decor *dhint, + Ecore_X_MWM_Hint_Input *ihint) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + MWMHints *mwmhints = NULL; + int ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = + xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, + ECORE_X_ATOM_MOTIF_WM_HINTS, + ECORE_X_ATOM_MOTIF_WM_HINTS, 0, UINT_MAX); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + if ((reply->format != 32) || (reply->value_len == 0)) + { + free(reply); + return EINA_FALSE; + } + + mwmhints = xcb_get_property_value(reply); + if (reply->value_len >= 4) + { + if (dhint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_DECORATIONS) + *dhint = mwmhints->decorations; + else + *dhint = ECORE_X_MWM_HINT_DECOR_ALL; + } + if (fhint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_FUNCTIONS) + *fhint = mwmhints->functions; + else + *fhint = ECORE_X_MWM_HINT_FUNC_ALL; + } + if (ihint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_INPUT_MODE) + *ihint = mwmhints->inputmode; + else + *ihint = ECORE_X_MWM_HINT_INPUT_MODELESS; + } + ret = EINA_TRUE; + } + free(reply); + return ret; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_netwm.c b/src/lib/ecore_x/xcb/ecore_xcb_netwm.c new file mode 100644 index 0000000000..ae801d3407 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_netwm.c @@ -0,0 +1,1604 @@ +#include "ecore_xcb_private.h" + +/* local function prototypes */ +/* static void _ecore_xcb_netwm_startup_info_free(void *data); */ +static Ecore_X_Atom _ecore_xcb_netwm_window_type_atom_get(Ecore_X_Window_Type type); +static Ecore_X_Window_Type _ecore_xcb_netwm_window_type_type_get(Ecore_X_Atom atom); +static Ecore_X_Atom _ecore_xcb_netwm_window_state_atom_get(Ecore_X_Window_State state); +static Ecore_X_Atom _ecore_xcb_netwm_action_atom_get(Ecore_X_Action action); + +/* local variables */ +//static Eina_Hash *_startup_info = NULL; + +/* local structures */ +typedef struct _Ecore_Xcb_Startup_Info Ecore_Xcb_Startup_Info; +struct _Ecore_Xcb_Startup_Info +{ + Ecore_X_Window win; + int init, size; + char *buffer; + int length; + + /* sequence info fields */ + char *id, *name; + int screen; + char *bin, *icon; + int desktop, timestamp; + char *description, *wmclass; + int silent; +}; + +EAPI void +ecore_x_netwm_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +// _startup_info = +// eina_hash_string_superfast_new(_ecore_xcb_netwm_startup_info_free); +} + +EAPI void +ecore_x_netwm_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +// if (_startup_info) eina_hash_free(_startup_info); +// _startup_info = NULL; +} + +EAPI Eina_Bool +ecore_x_netwm_pid_get(Ecore_X_Window win, + int *pid) +{ + uint32_t tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID, &tmp, 1)) + return EINA_FALSE; + + if (pid) *pid = tmp; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_pid_set(Ecore_X_Window win, + int pid) +{ + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + tmp = pid; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID, &tmp, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_window_type_get(Ecore_X_Window win, + Ecore_X_Window_Type *type) +{ + Ecore_X_Atom *atoms; + int num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (type) *type = ECORE_X_WINDOW_TYPE_NORMAL; + + num = + ecore_x_window_prop_atom_list_get(win, + ECORE_X_ATOM_NET_WM_WINDOW_TYPE, &atoms); + if ((type) && (num >= 1) && (atoms)) + *type = _ecore_xcb_netwm_window_type_type_get(atoms[0]); + + if (atoms) free(atoms); + + if (num >= 1) return EINA_TRUE; + return EINA_FALSE; +} + +EAPI void +ecore_x_netwm_window_type_set(Ecore_X_Window win, + Ecore_X_Window_Type type) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + atom = _ecore_xcb_netwm_window_type_atom_get(type); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, &atom, 1); +} + +EAPI int +ecore_x_netwm_window_types_get(Ecore_X_Window win, + Ecore_X_Window_Type **types) +{ + int num = 0, i = 0; + Ecore_X_Atom *atoms = NULL; + Ecore_X_Window_Type *atoms2 = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (types) *types = NULL; + num = + ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atoms); + if ((num <= 0) || (!atoms)) + { + if (atoms) free(atoms); + return 0; + } + + atoms2 = malloc(num * sizeof(Ecore_X_Window_Type)); + if (!atoms2) + { + if (atoms) free(atoms); + return 0; + } + + for (i = 0; i < num; i++) + atoms2[i] = _ecore_xcb_netwm_window_type_type_get(atoms[i]); + if (atoms) free(atoms); + + if (types) + *types = atoms2; + else + free(atoms2); + + return num; +} + +EAPI int +ecore_x_netwm_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (name) + *name = ecore_x_window_prop_string_get(win, ECORE_X_ATOM_NET_WM_NAME); + return 1; +} + +EAPI void +ecore_x_netwm_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_NET_WM_NAME, name); +} + +EAPI void +ecore_x_netwm_opacity_set(Ecore_X_Window win, + unsigned int opacity) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &opacity, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_opacity_get(Ecore_X_Window win, + unsigned int *opacity) +{ + unsigned int tmp = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &tmp, 1)) + return EINA_FALSE; + + if (opacity) *opacity = tmp; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_wm_identify(Ecore_X_Window root, + Ecore_X_Window check, + const char *wm_name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, + &check, 1); + ecore_x_window_prop_string_set(check, ECORE_X_ATOM_NET_WM_NAME, wm_name); + ecore_x_window_prop_string_set(root, ECORE_X_ATOM_NET_WM_NAME, wm_name); + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, + &check, 1); +} + +EAPI void +ecore_x_netwm_supported_set(Ecore_X_Window root, + Ecore_X_Atom *supported, + int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_atom_set(root, ECORE_X_ATOM_NET_SUPPORTED, + supported, num); +} + +EAPI Eina_Bool +ecore_x_netwm_supported_get(Ecore_X_Window root, + Ecore_X_Atom **supported, + int *num) +{ + int num_ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (num) *num = 0; + if (supported) *supported = NULL; + + num_ret = + ecore_x_window_prop_atom_list_get(root, ECORE_X_ATOM_NET_SUPPORTED, + supported); + if (num_ret <= 0) return EINA_FALSE; + if (num) *num = num_ret; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_desk_count_set(Ecore_X_Window root, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS, + &n_desks, 1); +} + +EAPI void +ecore_x_netwm_desk_roots_set(Ecore_X_Window root, + Ecore_X_Window *vroots, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, + vroots, n_desks); +} + +EAPI void +ecore_x_netwm_desk_names_set(Ecore_X_Window root, + const char **names, + unsigned int n_desks) +{ + char ss[32], *buf = NULL, *t = NULL; + const char *s; + uint32_t len = 0, i, l; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + for (i = 0; i < n_desks; i++) + { + s = ((names) ? names[i] : NULL); + if (!s) + { + /* Default to "Desk-<number>" */ + sprintf(ss, "Desk-%d", i); + s = ss; + } + + l = strlen(s) + 1; + t = realloc(buf, len + 1); + if (t) + { + buf = t; + memcpy(buf + len, s, l); + } + len += l; + } + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, root, + ECORE_X_ATOM_NET_DESKTOP_NAMES, + ECORE_X_ATOM_UTF8_STRING, 8, len, (const void *)buf); +// ecore_x_flush(); + free(buf); +} + +EAPI void +ecore_x_netwm_desk_size_set(Ecore_X_Window root, + unsigned int width, + unsigned int height) +{ + uint32_t size[2]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + size[0] = width; + size[1] = height; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, + size, 2); +} + +EAPI void +ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, + unsigned int *origins, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT, + origins, (2 * n_desks)); +} + +EAPI void +ecore_x_netwm_desk_layout_set(Ecore_X_Window root, + int orientation, + int columns, + int rows, + int starting_corner) +{ + unsigned int layout[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + layout[0] = orientation; + layout[1] = columns; + layout[2] = rows; + layout[3] = starting_corner; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT, + layout, 4); +} + +EAPI void +ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, + unsigned int *areas, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas, + 4 * n_desks); +} + +EAPI unsigned int * +ecore_x_netwm_desk_workareas_get(Ecore_X_Window root, unsigned int *n_desks) +{ + int ret; + unsigned int *areas = NULL; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ret = ecore_x_window_prop_card32_list_get(root, ECORE_X_ATOM_NET_WORKAREA, + &areas); + if (!areas) + { + if (n_desks) *n_desks = 0; + return 0; + } + if (n_desks) *n_desks = ret / 4; + return areas; +} + +EAPI void +ecore_x_netwm_desk_current_set(Ecore_X_Window root, + unsigned int desk) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, + &desk, 1); +} + +EAPI void +ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, + Eina_Bool on) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + val = ((on) ? 1 : 0); + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, + &val, 1); +} + +EAPI int +ecore_x_netwm_startup_id_get(Ecore_X_Window win, + char **id) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (id) + { + *id = + ecore_x_window_prop_string_get(win, ECORE_X_ATOM_NET_STARTUP_ID); + } + + return 1; +} + +EAPI void +ecore_x_netwm_startup_id_set(Ecore_X_Window win, + const char *id) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id); +} + +EAPI void +ecore_x_netwm_state_request_send(Ecore_X_Window win, + Ecore_X_Window root, + Ecore_X_Window_State s1, + Ecore_X_Window_State s2, + Eina_Bool set) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_NET_WM_STATE; + ev.data.data32[0] = !!set; + ev.data.data32[1] = _ecore_xcb_netwm_window_state_atom_get(s1); + ev.data.data32[2] = _ecore_xcb_netwm_window_state_atom_get(s2); + /* 1 == normal client, if used in a pager this should be 2 */ + ev.data.data32[3] = 1; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_netwm_window_state_set(Ecore_X_Window win, + Ecore_X_Window_State *state, + unsigned int num) +{ + Ecore_X_Atom *set; + unsigned int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!num) + { + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE); + return; + } + + set = malloc(num * sizeof(Ecore_X_Atom)); + if (!set) return; + + for (i = 0; i < num; i++) + set[i] = _ecore_xcb_netwm_window_state_atom_get(state[i]); + + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_STATE, set, num); + free(set); +} + +EAPI Eina_Bool +ecore_x_netwm_window_state_get(Ecore_X_Window win, + Ecore_X_Window_State **state, + unsigned int *num) +{ + Ecore_X_Atom *atoms; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (num) *num = 0; + if (state) *state = NULL; + + ret = + ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_STATE, &atoms); + + if (ret <= 0) return EINA_FALSE; + + if (state) + { + *state = malloc(ret * sizeof(Ecore_X_Window_State)); + if (*state) + { + int i = 0; + + for (i = 0; i < ret; i++) + (*state)[i] = _ecore_xcb_netwm_window_state_get(atoms[i]); + if (num) *num = ret; + } + } + + free(atoms); + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_client_active_set(Ecore_X_Window root, + Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(root, + ECORE_X_ATOM_NET_ACTIVE_WINDOW, &win, 1); +} + +EAPI void +ecore_x_netwm_client_active_request(Ecore_X_Window root, + Ecore_X_Window win, + int type, + Ecore_X_Window current_win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_NET_ACTIVE_WINDOW; + ev.data.data32[0] = type; + ev.data.data32[1] = XCB_CURRENT_TIME; + ev.data.data32[2] = current_win; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_netwm_client_list_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST, + p_clients, n_clients); +} + +EAPI void +ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING, + p_clients, n_clients); +} + +EAPI Eina_Bool +ecore_x_screen_is_composited(int screen) +{ + char buff[32]; + xcb_get_selection_owner_cookie_t ocookie; + xcb_get_selection_owner_reply_t *oreply; + Ecore_X_Window win; + static Ecore_X_Atom atom = XCB_NONE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + snprintf(buff, sizeof(buff), "_NET_WM_CM_S%i", screen); + + if (atom == XCB_NONE) + { + xcb_intern_atom_cookie_t acookie; + xcb_intern_atom_reply_t *areply; + + acookie = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(buff), buff); + areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL); + if (!areply) return EINA_FALSE; + atom = areply->atom; + free(areply); + } + if (atom == XCB_NONE) return EINA_FALSE; + + ocookie = xcb_get_selection_owner_unchecked(_ecore_xcb_conn, atom); + oreply = xcb_get_selection_owner_reply(_ecore_xcb_conn, ocookie, NULL); + if (!oreply) return EINA_FALSE; + win = oreply->owner; + free(oreply); + + return (win != XCB_NONE) ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_screen_is_composited_set(int screen, + Ecore_X_Window win) +{ + static Ecore_X_Atom atom = XCB_NONE; + char buff[32]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + snprintf(buff, sizeof(buff), "_NET_WM_CM_S%i", screen); + if (atom == XCB_NONE) + { + xcb_intern_atom_cookie_t acookie; + xcb_intern_atom_reply_t *areply; + + acookie = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 0, strlen(buff), buff); + areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL); + if (!areply) return; + atom = areply->atom; + free(areply); + } + if (atom == XCB_NONE) return; + xcb_set_selection_owner(_ecore_xcb_conn, win, atom, + _ecore_xcb_events_last_time_get()); +} + +EAPI void +ecore_x_netwm_ping_send(Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_WM_PROTOCOLS; + ev.data.data32[0] = ECORE_X_ATOM_NET_WM_PING; + ev.data.data32[1] = ecore_x_current_time_get(); + ev.data.data32[2] = win; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_netwm_frame_size_set(Ecore_X_Window win, + int fl, + int fr, + int ft, + int fb) +{ + uint32_t frames[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + frames[0] = fl; + frames[1] = fr; + frames[2] = ft; + frames[3] = fb; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_FRAME_EXTENTS, + frames, 4); +} + +EAPI Eina_Bool +ecore_x_netwm_frame_size_get(Ecore_X_Window win, + int *fl, + int *fr, + int *ft, + int *fb) +{ + int ret = 0; + unsigned int frames[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_FRAME_EXTENTS, + frames, 4); + if (ret != 4) return EINA_FALSE; + + if (fl) *fl = frames[0]; + if (fr) *fr = frames[1]; + if (ft) *ft = frames[2]; + if (fb) *fb = frames[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_sync_request_send(Ecore_X_Window win, + unsigned int serial) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + + /* FIXME: Maybe need XSyncIntToValue ?? */ + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_WM_PROTOCOLS; + ev.data.data32[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST; + ev.data.data32[1] = _ecore_xcb_events_last_time_get(); + ev.data.data32[2] = serial; + ev.data.data32[3] = 0; + ev.data.data32[4] = 0; + + xcb_send_event(_ecore_xcb_conn, 0, win, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_netwm_desktop_set(Ecore_X_Window win, + unsigned int desk) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_desktop_get(Ecore_X_Window win, + unsigned int *desk) +{ + unsigned int tmp = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP, + &tmp, 1)) + return EINA_FALSE; + + if (desk) *desk = tmp; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_desktop_request_send(Ecore_X_Window win, + Ecore_X_Window root, + unsigned int desktop) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!root) root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_NET_WM_DESKTOP; + ev.data.data32[0] = desktop; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +// ecore_x_flush(); +} + +EAPI void +ecore_x_netwm_moveresize_request_send(Ecore_X_Window win, + int x, + int y, + Ecore_X_Netwm_Direction direction, + unsigned int button) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = ECORE_X_ATOM_NET_WM_MOVERESIZE; + ev.data.data32[0] = x; + ev.data.data32[1] = y; + ev.data.data32[2] = direction; + ev.data.data32[3] = button; + ev.data.data32[4] = 1; + + xcb_send_event(_ecore_xcb_conn, 0, win, + (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY), (const char *)&ev); +} + +EAPI void +ecore_x_netwm_handled_icons_set(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); +} + +EAPI Eina_Bool +ecore_x_netwm_handled_icons_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0)) + return EINA_FALSE; + + return EINA_TRUE; +} + +EAPI int +ecore_x_netwm_icon_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (name) + { + *name = + ecore_x_window_prop_string_get(win, ECORE_X_ATOM_NET_WM_ICON_NAME); + } + + return 1; +} + +EAPI void +ecore_x_netwm_icon_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME, name); +} + +EAPI void +ecore_x_netwm_icons_set(Ecore_X_Window win, + Ecore_X_Icon *icon, + int num) +{ + unsigned int *data, *p, *p2; + unsigned int i, size, x, y; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + size = 0; + for (i = 0; i < (unsigned int)num; i++) + { + size += 2 + (icon[i].width * icon[i].height); + } + data = malloc(size * sizeof(unsigned int)); + if (!data) return; + p = data; + for (i = 0; i < (unsigned int)num; i++) + { + p[0] = icon[i].width; + p[1] = icon[i].height; + p += 2; + p2 = icon[i].data; + for (y = 0; y < icon[i].height; y++) + { + for (x = 0; x < icon[i].width; x++) + { + unsigned int r, g, b, a; + + a = (*p2 >> 24) & 0xff; + r = (*p2 >> 16) & 0xff; + g = (*p2 >> 8 ) & 0xff; + b = (*p2 ) & 0xff; + if ((a > 0) && (a < 255)) + { + r = (r * 255) / a; + g = (g * 255) / a; + b = (b * 255) / a; + } + *p = (a << 24) | (r << 16) | (g << 8) | b; + p++; + p2++; + } + } + } + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON, + data, size); + free(data); +} + +EAPI Eina_Bool +ecore_x_netwm_icons_get(Ecore_X_Window win, + Ecore_X_Icon **icon, + int *num) +{ + int num_ret = 0; + unsigned int i = 0, len = 0, icons = 0; + unsigned int *data, *p, *src; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (num) *num = 0; + if (icon) *icon = NULL; + + num_ret = + ecore_x_window_prop_card32_list_get(win, ECORE_X_ATOM_NET_WM_ICON, &data); + + if ((num_ret <= 0) || (!data)) + { + if (data) free(data); + return EINA_FALSE; + } + if (num_ret < 2) + { + if (data) free(data); + return EINA_FALSE; + } + + icons = 0; + p = data; + while (p) + { + len = (p[0] * p[1]); + p += (len + 2); + if ((p - data) > num_ret) + { + if (data) free(data); + return EINA_FALSE; + } + icons++; + if ((p - data) == num_ret) p = NULL; + } + if (num) *num = icons; + if (!icon) + { + if (data) free(data); + return EINA_TRUE; + } + + *icon = malloc(icons * sizeof(Ecore_X_Icon)); + if (!(*icon)) + { + if (data) free(data); + return EINA_FALSE; + } + + /* Fetch the icons */ + p = data; + for (i = 0; i < icons; i++) + { + unsigned int *ps, *pd, *pe; + + len = p[0] * p[1]; + ((*icon)[i]).width = p[0]; + ((*icon)[i]).height = p[1]; + src = &(p[2]); + ((*icon)[i]).data = malloc(len * sizeof(unsigned int)); + if (!((*icon)[i]).data) + { + while (i) + free(((*icon)[--i]).data); + free(*icon); + free(data); + return EINA_FALSE; + } + + pd = ((*icon)[i]).data; + ps = src; + pe = ps + len; + for (; ps < pe; ps++) + { + unsigned int r, g, b, a; + + a = (*ps >> 24) & 0xff; + r = (((*ps >> 16) & 0xff) * a) / 255; + g = (((*ps >> 8) & 0xff) * a) / 255; + b = (((*ps) & 0xff) * a) / 255; + *pd = (a << 24) | (r << 16) | (g << 8) | (b); + pd++; + } + p += (len + 2); + } + + if (data) free(data); + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = + ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, + geom, 4); + if (ret != 4) return EINA_FALSE; + if (x) *x = geom[0]; + if (y) *y = geom[1]; + if (w) *w = geom[2]; + if (h) *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_strut_set(Ecore_X_Window win, + int l, + int r, + int t, + int b) +{ + unsigned int strut[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + strut[0] = l; + strut[1] = r; + strut[2] = t; + strut[3] = b; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4); +} + +EAPI Eina_Bool +ecore_x_netwm_strut_get(Ecore_X_Window win, + int *l, + int *r, + int *t, + int *b) +{ + unsigned int strut[4]; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = + ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4); + if (ret != 4) return EINA_FALSE; + + if (l) *l = strut[0]; + if (r) *r = strut[1]; + if (t) *t = strut[2]; + if (b) *b = strut[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_strut_partial_set(Ecore_X_Window win, + int left, + int right, + int top, + int bottom, + int left_start_y, + int left_end_y, + int right_start_y, + int right_end_y, + int top_start_x, + int top_end_x, + int bottom_start_x, + int bottom_end_x) +{ + unsigned int strut[12]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + strut[0] = left; + strut[1] = right; + strut[2] = top; + strut[3] = bottom; + strut[4] = left_start_y; + strut[5] = left_end_y; + strut[6] = right_start_y; + strut[7] = right_end_y; + strut[8] = top_start_x; + strut[9] = top_end_x; + strut[10] = bottom_start_x; + strut[11] = bottom_end_x; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, + strut, 12); +} + +EAPI Eina_Bool +ecore_x_netwm_strut_partial_get(Ecore_X_Window win, + int *left, + int *right, + int *top, + int *bottom, + int *left_start_y, + int *left_end_y, + int *right_start_y, + int *right_end_y, + int *top_start_x, + int *top_end_x, + int *bottom_start_x, + int *bottom_end_x) +{ + unsigned int strut[12]; + int ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ret = + ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, + strut, 12); + if (ret != 12) return EINA_FALSE; + + if (left) *left = strut[0]; + if (right) *right = strut[1]; + if (top) *top = strut[2]; + if (bottom) *bottom = strut[3]; + if (left_start_y) *left_start_y = strut[4]; + if (left_end_y) *left_end_y = strut[5]; + if (right_start_y) *right_start_y = strut[6]; + if (right_end_y) *right_end_y = strut[7]; + if (top_start_x) *top_start_x = strut[8]; + if (top_end_x) *top_end_x = strut[9]; + if (bottom_start_x) *bottom_start_x = strut[10]; + if (bottom_end_x) *bottom_end_x = strut[11]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_user_time_set(Ecore_X_Window win, + unsigned int t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME, &t, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_user_time_get(Ecore_X_Window win, + unsigned int *t) +{ + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME, + &tmp, 1)) + return EINA_FALSE; + + if (t) *t = tmp; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_visible_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME, + name); +} + +EAPI int +ecore_x_netwm_visible_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (name) + *name = ecore_x_window_prop_string_get(win, + ECORE_X_ATOM_NET_WM_VISIBLE_NAME); + return 1; +} + +EAPI void +ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, + name); +} + +EAPI int +ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (name) + { + *name = + ecore_x_window_prop_string_get(win, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME); + } + + return 1; +} + +EAPI Eina_Bool +ecore_x_netwm_sync_counter_get(Ecore_X_Window win, + Ecore_X_Sync_Counter *counter) +{ + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER, + &tmp, 1)) + return EINA_FALSE; + + if (counter) *counter = tmp; + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, + Ecore_X_Action action) +{ + int num = 0, i = 0; + Ecore_X_Atom *atoms, atom; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + num = + ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atoms); + if (num <= 0) return EINA_FALSE; + + atom = _ecore_xcb_netwm_action_atom_get(action); + for (i = 0; i < num; i++) + { + if (atoms[i] == atom) + { + ret = EINA_TRUE; + break; + } + } + + if (atoms) free(atoms); + return ret; +} + +EAPI Eina_Bool +ecore_x_netwm_allowed_action_get(Ecore_X_Window win, + Ecore_X_Action **action, + unsigned int *num) +{ + Ecore_X_Atom *atoms; + int num_ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (num) *num = 0; + if (action) *action = NULL; + + num_ret = + ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + &atoms); + if (num_ret <= 0) return EINA_FALSE; + if (action) + { + *action = malloc(num_ret * sizeof(Ecore_X_Action)); + if (*action) + { + int i = 0; + + for (i = 0; i < num_ret; i++) + (*action)[i] = _ecore_xcb_netwm_action_atom_get(atoms[i]); + } + if (num) *num = num_ret; + } + free(atoms); + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_allowed_action_set(Ecore_X_Window win, + Ecore_X_Action *action, + unsigned int num) +{ + Ecore_X_Atom *set; + unsigned int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!num) + { + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS); + return; + } + + set = malloc(num * sizeof(Ecore_X_Atom)); + if (!set) return; + + for (i = 0; i < num; i++) + set[i] = _ecore_xcb_netwm_action_atom_get(action[i]); + + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + set, num); + free(set); +} + +/* local functions */ +int +_ecore_xcb_netwm_startup_info_begin(Ecore_X_Window win EINA_UNUSED, + uint8_t data EINA_UNUSED) +{ + // TODO: TBD + return 1; +} + +int +_ecore_xcb_netwm_startup_info(Ecore_X_Window win EINA_UNUSED, + uint8_t data EINA_UNUSED) +{ + // TODO: TBD + return 1; +} + +/* static void */ +/* _ecore_xcb_netwm_startup_info_free(void *data) */ +/* { */ +/* Ecore_Xcb_Startup_Info *info; */ + +/* LOGFN(__FILE__, __LINE__, __FUNCTION__); */ + +/* if (!(info = data)) return; */ +/* if (info->buffer) free(info->buffer); */ +/* if (info->id) free(info->id); */ +/* if (info->name) free(info->name); */ +/* if (info->bin) free(info->bin); */ +/* if (info->icon) free(info->icon); */ +/* if (info->description) free(info->description); */ +/* if (info->wmclass) free(info->wmclass); */ +/* free(info); */ +/* } */ + +static Ecore_X_Atom +_ecore_xcb_netwm_window_type_atom_get(Ecore_X_Window_Type type) +{ + switch (type) + { + case ECORE_X_WINDOW_TYPE_DESKTOP: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP; + + case ECORE_X_WINDOW_TYPE_DOCK: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK; + + case ECORE_X_WINDOW_TYPE_TOOLBAR: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; + + case ECORE_X_WINDOW_TYPE_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU; + + case ECORE_X_WINDOW_TYPE_UTILITY: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY; + + case ECORE_X_WINDOW_TYPE_SPLASH: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH; + + case ECORE_X_WINDOW_TYPE_DIALOG: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG; + + case ECORE_X_WINDOW_TYPE_NORMAL: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL; + + case ECORE_X_WINDOW_TYPE_DROPDOWN_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU; + + case ECORE_X_WINDOW_TYPE_POPUP_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU; + + case ECORE_X_WINDOW_TYPE_TOOLTIP: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP; + + case ECORE_X_WINDOW_TYPE_NOTIFICATION: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION; + + case ECORE_X_WINDOW_TYPE_COMBO: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO; + + case ECORE_X_WINDOW_TYPE_DND: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND; + + default: + return 0; + } +} + +static Ecore_X_Window_Type +_ecore_xcb_netwm_window_type_type_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP) + return ECORE_X_WINDOW_TYPE_DESKTOP; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK) + return ECORE_X_WINDOW_TYPE_DOCK; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR) + return ECORE_X_WINDOW_TYPE_TOOLBAR; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU) + return ECORE_X_WINDOW_TYPE_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY) + return ECORE_X_WINDOW_TYPE_UTILITY; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH) + return ECORE_X_WINDOW_TYPE_SPLASH; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG) + return ECORE_X_WINDOW_TYPE_DIALOG; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL) + return ECORE_X_WINDOW_TYPE_NORMAL; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) + return ECORE_X_WINDOW_TYPE_DROPDOWN_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU) + return ECORE_X_WINDOW_TYPE_POPUP_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP) + return ECORE_X_WINDOW_TYPE_TOOLTIP; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION) + return ECORE_X_WINDOW_TYPE_NOTIFICATION; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO) + return ECORE_X_WINDOW_TYPE_COMBO; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND) + return ECORE_X_WINDOW_TYPE_DND; + else + return ECORE_X_WINDOW_TYPE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_xcb_netwm_window_state_atom_get(Ecore_X_Window_State state) +{ + switch (state) + { + case ECORE_X_WINDOW_STATE_MODAL: + return ECORE_X_ATOM_NET_WM_STATE_MODAL; + + case ECORE_X_WINDOW_STATE_STICKY: + return ECORE_X_ATOM_NET_WM_STATE_STICKY; + + case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT: + return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT; + + case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ: + return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ; + + case ECORE_X_WINDOW_STATE_SHADED: + return ECORE_X_ATOM_NET_WM_STATE_SHADED; + + case ECORE_X_WINDOW_STATE_SKIP_TASKBAR: + return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR; + + case ECORE_X_WINDOW_STATE_SKIP_PAGER: + return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER; + + case ECORE_X_WINDOW_STATE_HIDDEN: + return ECORE_X_ATOM_NET_WM_STATE_HIDDEN; + + case ECORE_X_WINDOW_STATE_FULLSCREEN: + return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN; + + case ECORE_X_WINDOW_STATE_ABOVE: + return ECORE_X_ATOM_NET_WM_STATE_ABOVE; + + case ECORE_X_WINDOW_STATE_BELOW: + return ECORE_X_ATOM_NET_WM_STATE_BELOW; + + case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION: + return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION; + + default: + return 0; + } +} + +Ecore_X_Window_State +_ecore_xcb_netwm_window_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_NET_WM_STATE_MODAL) + return ECORE_X_WINDOW_STATE_MODAL; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_STICKY) + return ECORE_X_WINDOW_STATE_STICKY; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT) + return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ) + return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_SHADED) + return ECORE_X_WINDOW_STATE_SHADED; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR) + return ECORE_X_WINDOW_STATE_SKIP_TASKBAR; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER) + return ECORE_X_WINDOW_STATE_SKIP_PAGER; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_HIDDEN) + return ECORE_X_WINDOW_STATE_HIDDEN; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN) + return ECORE_X_WINDOW_STATE_FULLSCREEN; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_ABOVE) + return ECORE_X_WINDOW_STATE_ABOVE; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_BELOW) + return ECORE_X_WINDOW_STATE_BELOW; + else if (atom == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION) + return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION; + else + return ECORE_X_WINDOW_STATE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_xcb_netwm_action_atom_get(Ecore_X_Action action) +{ + switch (action) + { + case ECORE_X_ACTION_MOVE: + return ECORE_X_ATOM_NET_WM_ACTION_MOVE; + + case ECORE_X_ACTION_RESIZE: + return ECORE_X_ATOM_NET_WM_ACTION_RESIZE; + + case ECORE_X_ACTION_MINIMIZE: + return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; + + case ECORE_X_ACTION_SHADE: + return ECORE_X_ATOM_NET_WM_ACTION_SHADE; + + case ECORE_X_ACTION_STICK: + return ECORE_X_ATOM_NET_WM_ACTION_STICK; + + case ECORE_X_ACTION_MAXIMIZE_HORZ: + return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; + + case ECORE_X_ACTION_MAXIMIZE_VERT: + return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; + + case ECORE_X_ACTION_FULLSCREEN: + return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; + + case ECORE_X_ACTION_CHANGE_DESKTOP: + return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; + + case ECORE_X_ACTION_CLOSE: + return ECORE_X_ATOM_NET_WM_ACTION_CLOSE; + + case ECORE_X_ACTION_ABOVE: + return ECORE_X_ATOM_NET_WM_ACTION_ABOVE; + + case ECORE_X_ACTION_BELOW: + return ECORE_X_ATOM_NET_WM_ACTION_BELOW; + + default: + return 0; + } +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_pixmap.c b/src/lib/ecore_x/xcb/ecore_xcb_pixmap.c new file mode 100644 index 0000000000..f9bf525f7a --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_pixmap.c @@ -0,0 +1,128 @@ +#include "ecore_xcb_private.h" + +/** + * @defgroup Ecore_X_Pixmap_Group X Pixmap Functions + * + * Functions that operate on pixmaps. + */ + +/** + * Creates a new pixmap. + * @param win Window used to determine which screen of the display the + * pixmap should be created on. If 0, the default root window + * is used. + * @param w Width of the new pixmap. + * @param h Height of the new pixmap. + * @param dep Depth of the pixmap. If 0, the default depth of the default + * screen is used. + * @return New pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI Ecore_X_Pixmap +ecore_x_pixmap_new(Ecore_X_Window win, + int w, + int h, + int dep) +{ + Ecore_X_Pixmap pmap; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (win == 0) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + if (dep == 0) dep = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth; + + pmap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, dep, pmap, win, w, h); + +// ecore_x_flush(); + return pmap; +} + +/** + * Deletes the reference to the given pixmap. + * + * If no other clients have a reference to the given pixmap, the server + * will destroy it. + * + * @param pmap The given pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_free(Ecore_X_Pixmap pmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_free_pixmap(_ecore_xcb_conn, pmap); +// ecore_x_flush(); +} + +/** + * Pastes a rectangular area of the given pixmap onto the given drawable. + * @param pmap The given pixmap. + * @param dest The given drawable. + * @param gc The graphics context which governs which operation will + * be used to paste the area onto the drawable. + * @param sx The X position of the area on the pixmap. + * @param sy The Y position of the area on the pixmap. + * @param w The width of the area. + * @param h The height of the area. + * @param dx The X position at which to paste the area on @p dest. + * @param dy The Y position at which to paste the area on @p dest. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_paste(Ecore_X_Pixmap pmap, + Ecore_X_Drawable dest, + Ecore_X_GC gc, + int sx, + int sy, + int w, + int h, + int dx, + int dy) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_copy_area(_ecore_xcb_conn, pmap, dest, gc, sx, sy, dx, dy, w, h); +// ecore_x_flush(); +} + +/** + * Retrieves the size of the given pixmap. + * @param pmap The given pixmap. + * @param x Pointer to an integer in which to store the X position. + * @param y Pointer to an integer in which to store the Y position. + * @param w Pointer to an integer in which to store the width. + * @param h Pointer to an integer in which to store the height. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, + int *x, + int *y, + int *w, + int *h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (pmap) + ecore_x_drawable_geometry_get(pmap, x, y, w, h); +} + +/** + * Retrieves the depth of the given pixmap. + * @param pmap The given pixmap. + * @return The depth of the pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI int +ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_drawable_depth_get(pmap); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_private.h b/src/lib/ecore_x/xcb/ecore_xcb_private.h new file mode 100644 index 0000000000..240210ca0d --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_private.h @@ -0,0 +1,468 @@ +#ifndef __ECORE_XCB_PRIVATE_H__ +# define __ECORE_XCB_PRIVATE_H__ + +//# define LOGFNS 1 + +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +# include <unistd.h> // included for close & gethostname functions + +/* generic xcb includes */ +# include <xcb/xcb.h> +# include <xcb/bigreq.h> +# include <xcb/shm.h> +# include <xcb/xcb_image.h> + +/* EFL includes */ +# include "Ecore.h" +# include "Ecore_Input.h" +# include "Ecore_X.h" + +/* logging */ +extern int _ecore_xcb_log_dom; + +# ifdef ECORE_XCB_DEFAULT_LOG_COLOR +# undef ECORE_XCB_DEFAULT_LOG_COLOR +# endif +# define ECORE_XCB_DEFAULT_LOG_COLOR EINA_COLOR_BLUE + +# ifdef ERR +# undef ERR +# endif +# define ERR(...) EINA_LOG_DOM_ERR(_ecore_xcb_log_dom, __VA_ARGS__) + +# ifdef DBG +# undef DBG +# endif +# define DBG(...) EINA_LOG_DOM_DBG(_ecore_xcb_log_dom, __VA_ARGS__) + +# ifdef INF +# undef INF +# endif +# define INF(...) EINA_LOG_DOM_INFO(_ecore_xcb_log_dom, __VA_ARGS__) + +# ifdef WRN +# undef WRN +# endif +# define WRN(...) EINA_LOG_DOM_WARN(_ecore_xcb_log_dom, __VA_ARGS__) + +# ifdef CRIT +# undef CRIT +# endif +# define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_xcb_log_dom, __VA_ARGS__) + +# ifdef LOGFNS +# include <stdio.h> +# define LOGFN(fl, ln, fn) printf("-ECORE-XCB: %25s: %5i - %s\n", fl, ln, fn); +# else +# define LOGFN(fl, ln, fn) +# endif + +# ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +# endif + +# ifndef MIN +# define MIN(x, y) (((x) > (y)) ? (y) : (x)) +# endif + +# ifndef MAX +# define MAX(a, b) ((a < b) ? b : a) +# endif + +#define CHECK_XCB_CONN \ + { \ + if (xcb_connection_has_error(_ecore_xcb_conn)) \ + { \ + DBG("XCB Connection Has Error !!"); \ + _ecore_xcb_io_error_handle(NULL); \ + } \ + } + +/* enums */ +typedef enum _Ecore_Xcb_Encoding_Style Ecore_Xcb_Encoding_Style; + +enum _Ecore_Xcb_Encoding_Style +{ + XcbStringStyle, + XcbCompoundTextStyle, + XcbTextStyle, + XcbStdICCTextStyle, + XcbUTF8StringStyle +}; + +/* structures */ +typedef struct _Ecore_X_DND_Source Ecore_X_DND_Source; +typedef struct _Ecore_X_DND_Target Ecore_X_DND_Target; +typedef struct _Ecore_X_Selection_Intern Ecore_X_Selection_Intern; +typedef struct _Ecore_X_Selection_Converter Ecore_X_Selection_Converter; +typedef struct _Ecore_X_Selection_Parser Ecore_X_Selection_Parser; +typedef struct _Ecore_Xcb_Textproperty Ecore_Xcb_Textproperty; + +struct _Ecore_X_DND_Source +{ + int version; + Ecore_X_Window win, dest; + + enum + { + ECORE_X_DND_SOURCE_IDLE, + ECORE_X_DND_SOURCE_DRAGGING, + ECORE_X_DND_SOURCE_DROPPED, + ECORE_X_DND_SOURCE_CONVERTING + } state; + + struct + { + short x, y; + unsigned short width, height; + } rectangle; + + struct + { + Ecore_X_Window window; + int x, y; + } prev; + + Ecore_X_Time time; + + Ecore_X_Atom action, accepted_action; + + int will_accept, suppress; + int await_status; +}; + +struct _Ecore_X_DND_Target +{ + int version; + Ecore_X_Window win, source; + + enum + { + ECORE_X_DND_TARGET_IDLE, + ECORE_X_DND_TARGET_ENTERED + } state; + + struct + { + int x, y; + } pos; + + Ecore_X_Time time; + + Ecore_X_Atom action, accepted_action; + int will_accept; +}; + +struct _Ecore_X_Selection_Intern +{ + Ecore_X_Window win; + Ecore_X_Atom selection; + unsigned char *data; + int length; + Ecore_X_Time time; +}; + +struct _Ecore_X_Selection_Converter +{ + Ecore_X_Atom target; + Eina_Bool (*convert)(char *target, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *type, + int *size_type); + Ecore_X_Selection_Converter *next; +}; + +struct _Ecore_X_Selection_Parser +{ + char *target; + void *(*parse)(const char *target, void *data, int size, int format); + Ecore_X_Selection_Parser *next; +}; + +struct _Ecore_Xcb_Textproperty +{ + char *value; + Ecore_X_Atom encoding; + unsigned int format, nitems; +}; + +/* external variables */ +extern Ecore_X_Connection *_ecore_xcb_conn; +extern Ecore_X_Screen *_ecore_xcb_screen; +extern double _ecore_xcb_double_click_time; +extern int16_t _ecore_xcb_event_last_root_x; +extern int16_t _ecore_xcb_event_last_root_y; + +/* external variables for extension events */ +extern int _ecore_xcb_event_damage; +extern int _ecore_xcb_event_randr; +extern int _ecore_xcb_event_screensaver; +extern int _ecore_xcb_event_shape; +extern int _ecore_xcb_event_sync; +extern int _ecore_xcb_event_xfixes; +extern int _ecore_xcb_event_input; +extern int _ecore_xcb_event_gesture; + +extern Ecore_X_Atom _ecore_xcb_atoms_wm_protocol[ECORE_X_WM_PROTOCOL_NUM]; + +extern int _ecore_xcb_button_grabs_num; +extern int _ecore_xcb_key_grabs_num; +extern Ecore_X_Window *_ecore_xcb_button_grabs; +extern Ecore_X_Window *_ecore_xcb_key_grabs; +extern Eina_Bool (*_ecore_xcb_window_grab_replay_func)(void *data, + int type, + void *event); +extern void *_ecore_xcb_window_grab_replay_data; + +/* private function prototypes */ +void _ecore_xcb_error_handler_init(void); +void _ecore_xcb_error_handler_shutdown(void); + +void _ecore_xcb_atoms_init(void); +void _ecore_xcb_atoms_finalize(void); + +void _ecore_xcb_extensions_init(void); +void _ecore_xcb_extensions_finalize(void); + +void _ecore_xcb_shape_init(void); +void _ecore_xcb_shape_finalize(void); + +void _ecore_xcb_screensaver_init(void); +void _ecore_xcb_screensaver_finalize(void); + +void _ecore_xcb_sync_init(void); +void _ecore_xcb_sync_finalize(void); +void _ecore_xcb_sync_magic_send(int val, + Ecore_X_Window win); + +void _ecore_xcb_render_init(void); +void _ecore_xcb_render_finalize(void); +Eina_Bool _ecore_xcb_render_argb_get(void); +Eina_Bool _ecore_xcb_render_anim_get(void); +Eina_Bool _ecore_xcb_render_avail_get(void); + +Eina_Bool _ecore_xcb_render_visual_supports_alpha(Ecore_X_Visual visual); +uint32_t _ecore_xcb_render_find_visual_id(int type, + Eina_Bool check_alpha); +Ecore_X_Visual *_ecore_xcb_render_visual_get(int visual_id); + +void _ecore_xcb_randr_init(void); +void _ecore_xcb_randr_finalize(void); + +void _ecore_xcb_gesture_init(void); +void _ecore_xcb_gesture_finalize(void); +void _ecore_xcb_gesture_shutdown(void); + +void _ecore_xcb_xfixes_init(void); +void _ecore_xcb_xfixes_finalize(void); +Eina_Bool _ecore_xcb_xfixes_avail_get(void); + +void _ecore_xcb_damage_init(void); +void _ecore_xcb_damage_finalize(void); + +void _ecore_xcb_composite_init(void); +void _ecore_xcb_composite_finalize(void); + +void _ecore_xcb_dpms_init(void); +void _ecore_xcb_dpms_finalize(void); + +void _ecore_xcb_cursor_init(void); +void _ecore_xcb_cursor_finalize(void); + +void _ecore_xcb_xinerama_init(void); +void _ecore_xcb_xinerama_finalize(void); + +void _ecore_xcb_dnd_init(void); +void _ecore_xcb_dnd_shutdown(void); +Ecore_X_DND_Source *_ecore_xcb_dnd_source_get(void); +Ecore_X_DND_Target *_ecore_xcb_dnd_target_get(void); +void _ecore_xcb_dnd_drag(Ecore_X_Window root, + int x, + int y); + +void _ecore_xcb_selection_init(void); +void _ecore_xcb_selection_shutdown(void); +void *_ecore_xcb_selection_parse(const char *target, + void *data, + int size, + int format); +char *_ecore_xcb_selection_target_get(Ecore_X_Atom target); +Ecore_X_Selection_Intern *_ecore_xcb_selection_get(Ecore_X_Atom selection); + +# ifdef HAVE_ICONV +Eina_Bool _ecore_xcb_utf8_textlist_to_textproperty(char **list, + int count, + Ecore_Xcb_Encoding_Style style, + Ecore_Xcb_Textproperty *ret); +# endif +Eina_Bool _ecore_xcb_mb_textlist_to_textproperty(char **list, + int count, + Ecore_Xcb_Encoding_Style style, + Ecore_Xcb_Textproperty *ret); +Eina_Bool _ecore_xcb_textlist_to_textproperty(const char *type, + char **list, + int count, + Ecore_Xcb_Encoding_Style style, + Ecore_Xcb_Textproperty *ret); + +# ifdef HAVE_ICONV +Eina_Bool _ecore_xcb_utf8_textproperty_to_textlist(const Ecore_Xcb_Textproperty *text_prop, + char ***list_ret, + int *count_ret); +# endif +Eina_Bool _ecore_xcb_mb_textproperty_to_textlist(const Ecore_Xcb_Textproperty *text_prop, + char ***list_ret, + int *count_ret); +Eina_Bool _ecore_xcb_textproperty_to_textlist(const Ecore_Xcb_Textproperty *text_prop, + const char *type, + char ***list_ret, + int *count_ret); + +void _ecore_xcb_events_init(void); +void _ecore_xcb_events_shutdown(void); +void _ecore_xcb_events_handle(xcb_generic_event_t *ev); +Ecore_X_Time _ecore_xcb_events_last_time_get(void); +unsigned int _ecore_xcb_events_modifiers_get(unsigned int state); +void _ecore_xcb_event_mouse_move(uint16_t timestamp, + uint16_t modifiers, + int16_t x, + int16_t y, + int16_t root_x, + int16_t root_y, + xcb_window_t event_win, + xcb_window_t win, + xcb_window_t root_win, + uint8_t same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + int16_t mx, + int16_t my, + int16_t mrx, + int16_t mry); +Ecore_Event_Mouse_Button *_ecore_xcb_event_mouse_button(int event, + uint16_t timestamp, + uint16_t modifiers, + xcb_button_t buttons, + int16_t x, + int16_t y, + int16_t root_x, + int16_t root_y, + xcb_window_t event_win, + xcb_window_t win, + xcb_window_t root_win, + uint8_t same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + int16_t mx, + int16_t my, + int16_t mrx, + int16_t mry); + +void _ecore_xcb_keymap_init(void); +void _ecore_xcb_keymap_finalize(void); +void _ecore_xcb_keymap_shutdown(void); +void _ecore_xcb_keymap_refresh(xcb_mapping_notify_event_t *event); +xcb_keysym_t _ecore_xcb_keymap_keycode_to_keysym(xcb_keycode_t keycode, + int col); +xcb_keycode_t *_ecore_xcb_keymap_keysym_to_keycode(xcb_keysym_t keysym); +char *_ecore_xcb_keymap_keysym_to_string(xcb_keysym_t keysym); +xcb_keycode_t _ecore_xcb_keymap_string_to_keycode(const char *key); +int _ecore_xcb_keymap_lookup_string(xcb_keycode_t keycode, + int state, + char *buffer, + int bytes, + xcb_keysym_t *sym); + +void _ecore_xcb_input_init(void); +void _ecore_xcb_input_finalize(void); +void _ecore_xcb_input_shutdown(void); +# ifdef ECORE_XCB_XINPUT +void _ecore_xcb_input_handle_event(xcb_generic_event_t *event); +# else +void _ecore_xcb_input_handle_event(xcb_generic_event_t *event); +# endif + +void _ecore_xcb_dri_init(void); +void _ecore_xcb_dri_finalize(void); + +void _ecore_xcb_xtest_init(void); +void _ecore_xcb_xtest_finalize(void); + +Ecore_X_Window _ecore_xcb_window_root_of_screen_get(int screen); +void _ecore_xcb_window_prop_string_utf8_set(Ecore_X_Window win, + Ecore_X_Atom atom, + const char *str); +Ecore_X_Visual _ecore_xcb_window_visual_get(Ecore_X_Window win); +void _ecore_xcb_window_button_grab_remove(Ecore_X_Window win); +void _ecore_xcb_window_key_grab_remove(Ecore_X_Window win); +void _ecore_xcb_window_grab_allow_events(Ecore_X_Window event_win, + Ecore_X_Window child_win, + int type, + void *event, + Ecore_X_Time timestamp); + +int _ecore_xcb_netwm_startup_info_begin(Ecore_X_Window win, + uint8_t data); +int _ecore_xcb_netwm_startup_info(Ecore_X_Window win, + uint8_t data); +Ecore_X_Window_State _ecore_xcb_netwm_window_state_get(Ecore_X_Atom atom); + +int _ecore_xcb_error_handle(xcb_generic_error_t *err); +int _ecore_xcb_io_error_handle(xcb_generic_error_t *err); + +xcb_image_t *_ecore_xcb_image_create_native(int w, + int h, + xcb_image_format_t format, + uint8_t depth, + void *base, + uint32_t bytes, + uint8_t *data); + +void _ecore_xcb_xdefaults_init(void); +void _ecore_xcb_xdefaults_shutdown(void); +char *_ecore_xcb_xdefaults_string_get(const char *prog, + const char *param); +int _ecore_xcb_xdefaults_int_get(const char *prog, + const char *param); + +void _ecore_xcb_modifiers_get(void); + +#endif diff --git a/src/lib/ecore_x/xcb/ecore_xcb_randr.c b/src/lib/ecore_x/xcb/ecore_xcb_randr.c new file mode 100644 index 0000000000..a2a4e6271f --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_randr.c @@ -0,0 +1,3807 @@ +/* TODO: List of missing functions + * + * ecore_x_randr_crtc_clone_set + * ecore_x_randr_output_crtc_set + * ecore_x_randr_edid_version_get + * ecore_x_randr_edid_info_has_valid_checksum + * ecore_x_randr_edid_manufacturer_name_get + * ecore_x_randr_edid_display_ascii_get + * ecore_x_randr_edid_display_serial_get + * ecore_x_randr_edid_model_get + * ecore_x_randr_edid_manufacturer_serial_number_get + * ecore_x_randr_edid_manufacturer_model_get + * ecore_x_randr_edid_dpms_available_get + * ecore_x_randr_edid_dpms_standby_available_get + * ecore_x_randr_edid_dpms_suspend_available_get + * ecore_x_randr_edid_dpms_off_available_get + * ecore_x_randr_edid_display_aspect_ratio_preferred_get + * ecore_x_randr_edid_display_aspect_ratios_get + * ecore_x_randr_edid_display_colorscheme_get + * ecore_x_randr_edid_display_type_digital_get + * ecore_x_randr_edid_display_interface_type_get + * ecore_x_randr_screen_backlight_level_set + * ecore_x_randr_output_subpixel_order_get + * ecore_x_randr_output_wired_clones_get + * ecore_x_randr_output_compatibility_list_get + * ecore_x_randr_output_signal_formats_get + * ecore_x_randr_output_signal_format_set + * ecore_x_randr_output_signal_properties_get + * ecore_x_randr_output_connector_number_get + * ecore_x_randr_output_connector_type_get + * ecore_x_randr_crtc_panning_area_get + * ecore_x_randr_crtc_panning_area_set + * ecore_x_randr_crtc_tracking_area_get + * ecore_x_randr_crtc_tracking_area_set + * ecore_x_randr_crtc_border_area_get + * ecore_x_randr_crtc_border_area_set + */ + +#include "ecore_xcb_private.h" +# ifdef ECORE_XCB_RANDR +# include <xcb/randr.h> +# endif + +#define Ecore_X_Randr_None 0 +#define Ecore_X_Randr_Unset -1 + +#define RANDR_1_1 ((1 << 16) | 1) +#define RANDR_1_2 ((1 << 16) | 2) +#define RANDR_1_3 ((1 << 16) | 3) + +#define RANDR_CHECK_1_1_RET(ret) if (_randr_version < RANDR_1_1) return ret +#define RANDR_CHECK_1_2_RET(ret) if (_randr_version < RANDR_1_2) return ret +#define RANDR_CHECK_1_3_RET(ret) if (_randr_version < RANDR_1_3) return ret + +#define ECORE_X_RANDR_EDID_VERSION_13 ((1 << 8) | 3) +#define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR 0x12 +#define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR 0x13 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK 0x36 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE 3 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT 5 +#define _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX 13 + +#define _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \ + for (block = edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK; block <= (edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK + (3 * 18)); block += 18) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) \ + _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \ + if ((block[0] == 0) && (block[1] == 0)) + +/* local function prototypes */ +static Eina_Bool _ecore_xcb_randr_output_validate(Ecore_X_Window root, + Ecore_X_Randr_Output output); +static Eina_Bool _ecore_xcb_randr_crtc_validate(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc); +static Eina_Bool _ecore_xcb_randr_root_validate(Ecore_X_Window root); +static int _ecore_xcb_randr_root_to_screen(Ecore_X_Window root); +#ifdef ECORE_XCB_RANDR +static xcb_randr_get_screen_resources_reply_t *_ecore_xcb_randr_12_get_resources(Ecore_X_Window win); +static xcb_randr_get_screen_resources_current_reply_t *_ecore_xcb_randr_13_get_resources(Ecore_X_Window win); +#endif +static xcb_timestamp_t _ecore_xcb_randr_12_get_resource_timestamp(Ecore_X_Window win); +static xcb_timestamp_t _ecore_xcb_randr_13_get_resource_timestamp(Ecore_X_Window win); + +static Ecore_X_Randr_Mode *_ecore_xcb_randr_12_output_modes_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num, + int *npreferred); +static Ecore_X_Randr_Mode *_ecore_xcb_randr_13_output_modes_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num, + int *npreferred); +static Ecore_X_Randr_Mode_Info *_ecore_xcb_randr_12_mode_info_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode); +static Ecore_X_Randr_Mode_Info *_ecore_xcb_randr_13_mode_info_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode); +static Ecore_X_Randr_Mode_Info **_ecore_xcb_randr_12_modes_info_get(Ecore_X_Window root, + int *num); +static Ecore_X_Randr_Mode_Info **_ecore_xcb_randr_13_modes_info_get(Ecore_X_Window root, + int *num); +static void _ecore_xcb_randr_12_mode_size_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode, + int *w, + int *h); +static void _ecore_xcb_randr_13_mode_size_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode, + int *w, + int *h); +static Ecore_X_Randr_Output *_ecore_xcb_randr_12_output_clones_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num); +static Ecore_X_Randr_Output *_ecore_xcb_randr_13_output_clones_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num); +static Ecore_X_Randr_Crtc *_ecore_xcb_randr_12_output_possible_crtcs_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num); +static Ecore_X_Randr_Crtc *_ecore_xcb_randr_13_output_possible_crtcs_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num); +static char *_ecore_xcb_randr_12_output_name_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *len); +static char *_ecore_xcb_randr_13_output_name_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *len); +static Ecore_X_Randr_Connection_Status _ecore_xcb_randr_12_output_connection_status_get(Ecore_X_Window root, + Ecore_X_Randr_Output output); +static Ecore_X_Randr_Connection_Status _ecore_xcb_randr_13_output_connection_status_get(Ecore_X_Window root, + Ecore_X_Randr_Output output); +static Ecore_X_Randr_Output *_ecore_xcb_randr_12_outputs_get(Ecore_X_Window root, + int *num); +static Ecore_X_Randr_Output *_ecore_xcb_randr_13_outputs_get(Ecore_X_Window root, + int *num); +static Ecore_X_Randr_Crtc _ecore_xcb_randr_12_output_crtc_get(Ecore_X_Window root, + Ecore_X_Randr_Output output); +static Ecore_X_Randr_Crtc _ecore_xcb_randr_13_output_crtc_get(Ecore_X_Window root, + Ecore_X_Randr_Output output); + +/* local variables */ +static Eina_Bool _randr_avail = EINA_FALSE; +static int _randr_version = -1; + +/* external variables */ +int _ecore_xcb_event_randr = -1; + +void +_ecore_xcb_randr_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_RANDR + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_randr_id); +#endif +} + +void +_ecore_xcb_randr_finalize(void) +{ +#ifdef ECORE_XCB_RANDR + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_RANDR + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_randr_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_randr_query_version_cookie_t cookie; + xcb_randr_query_version_reply_t *reply; + + cookie = + xcb_randr_query_version_unchecked(_ecore_xcb_conn, + XCB_RANDR_MAJOR_VERSION, + XCB_RANDR_MINOR_VERSION); + reply = xcb_randr_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if ((reply->major_version >= XCB_RANDR_MAJOR_VERSION) && + (reply->minor_version >= XCB_RANDR_MINOR_VERSION)) + _randr_avail = EINA_TRUE; + + _randr_version = + ((reply->major_version << 16) | reply->minor_version); + + free(reply); + } + + if (_randr_avail) + _ecore_xcb_event_randr = ext_reply->first_event; + } +#endif +} + +static Eina_Bool +#ifdef ECORE_XCB_RANDR +_ecore_xcb_randr_root_validate(Ecore_X_Window root) +#else +_ecore_xcb_randr_root_validate(Ecore_X_Window root EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_RANDR + Ecore_X_Randr_Screen scr = -1; +# define RANDR_VALIDATE_ROOT(screen, root) \ + ((screen == _ecore_xcb_randr_root_to_screen(root)) != -1) +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_RANDR + if ((root) && RANDR_VALIDATE_ROOT(scr, root)) + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + +static int +_ecore_xcb_randr_root_to_screen(Ecore_X_Window root) +{ + int count = 0, num = 0; + + CHECK_XCB_CONN; + + count = xcb_setup_roots_length(xcb_get_setup(_ecore_xcb_conn)); + for (num = 0; num < count; num++) + if (_ecore_xcb_window_root_of_screen_get(num) == root) + return num; + + return -1; +} + +/* public functions */ + +/* + * @brief Query whether RandR is available or not. + * + * @return @c EINA_TRUE if extension is available, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_randr_query(void) +{ + return _randr_avail; +} + +/* + * @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_version_get(void) +{ + return _randr_version; +} + +/* + * @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) +{ + int ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + ret = reply->rotations; + free(reply); + } +#endif + + return ret; +} + +/* + * @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) +{ + int ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + ret = reply->rotation; + free(reply); + } +#endif + + return ret; +} + +/* + * @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 @c 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) +{ + int ret = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + xcb_randr_set_screen_config_cookie_t scookie; + xcb_randr_set_screen_config_reply_t *sreply; + + scookie = + xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root, + XCB_CURRENT_TIME, + reply->config_timestamp, + reply->sizeID, orientation, + reply->rate); + sreply = + xcb_randr_set_screen_config_reply(_ecore_xcb_conn, scookie, NULL); + if (!sreply) + ret = EINA_FALSE; + else + { + ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ? + EINA_TRUE : EINA_FALSE; + free(sreply); + } + free(reply); + } +#endif + + return ret; +} + +/* + * @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_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; + Ecore_X_Randr_Screen_Size_MM *ret = NULL; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + int len = 0, i = 0; + xcb_randr_screen_size_t *sizes; + + len = xcb_randr_get_screen_info_sizes_length(reply); + sizes = xcb_randr_get_screen_info_sizes(reply); + if ((!sizes) || (len <= 0)) + { + free(reply); + return NULL; + } + if (num) *num = len; + ret = calloc(len, sizeof(Ecore_X_Randr_Screen_Size_MM)); + if (!ret) + { + free(reply); + return NULL; + } + for (i = 0; i < len; 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; + } + + free(reply); + } + + return ret; +#else + return NULL; +#endif +} + +/* + * @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_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + int len = 0, idx = 0; + xcb_randr_screen_size_t *sizes; + + len = xcb_randr_get_screen_info_sizes_length(reply); + sizes = xcb_randr_get_screen_info_sizes(reply); + if ((!sizes) || (len <= 0)) + { + free(reply); + return; + } + idx = reply->sizeID; + if ((idx < len) && (idx >= 0)) + { + if (w) *w = sizes[idx].width; + if (h) *h = sizes[idx].height; + if (w_mm) *w_mm = sizes[idx].mwidth; + if (h_mm) *h_mm = sizes[idx].mheight; + if (size_index) *size_index = idx; + } + + free(reply); + } +#endif +} + +/* + * @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 @c EINA_TRUE on success, @c 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) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if (!((size_index >= 0) && (_ecore_xcb_randr_root_validate(root)))) + return EINA_FALSE; + + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + int len = 0; + + len = xcb_randr_get_screen_info_sizes_length(reply); + if (len <= 0) + { + free(reply); + return EINA_FALSE; + } + if ((size_index < len) && (size_index >= 0)) + { + xcb_randr_set_screen_config_cookie_t scookie; + xcb_randr_set_screen_config_reply_t *sreply; + + scookie = + xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root, + XCB_CURRENT_TIME, + reply->config_timestamp, + size_index, + reply->rotation, + reply->rate); + sreply = + xcb_randr_set_screen_config_reply(_ecore_xcb_conn, + scookie, NULL); + if (!sreply) + ret = EINA_FALSE; + else + { + ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ? + EINA_TRUE : EINA_FALSE; + free(sreply); + } + } + + free(reply); + } +#endif + return ret; +} + +/* + * @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_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; + Ecore_X_Randr_Refresh_Rate ret = 0.0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if (!_ecore_xcb_randr_root_validate(root)) return ret; + + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + ret = reply->rate; + free(reply); + } + + return ret; +#else + return 0.0; +#endif +} + +/* + * @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_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; + Ecore_X_Randr_Refresh_Rate *ret = NULL; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if (!_ecore_xcb_randr_root_validate(root)) return ret; + + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + int len = 0; + + len = xcb_randr_get_screen_info_rates_length(reply); + if (num) *num = len; + + ret = malloc(sizeof(Ecore_X_Randr_Refresh_Rate) * len); + if (ret) + { + xcb_randr_refresh_rates_iterator_t iter; + int i = 0; + + iter = xcb_randr_get_screen_info_rates_iterator(reply); + while (i++ < size_index) + xcb_randr_refresh_rates_next(&iter); + + memcpy(ret, xcb_randr_refresh_rates_rates(iter.data), + sizeof(Ecore_X_Randr_Refresh_Rate) * len); + } + free(reply); + } + + return ret; +#else + return NULL; +#endif +} + +/* + * @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 @c EINA_TRUE on success, @c EINA_FALSE otherwise. + */ +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) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_info_cookie_t cookie; + xcb_randr_get_screen_info_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if (_randr_version < RANDR_1_1) return EINA_FALSE; + + cookie = xcb_randr_get_screen_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_info_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + xcb_randr_set_screen_config_cookie_t scookie; + xcb_randr_set_screen_config_reply_t *sreply; + + scookie = + xcb_randr_set_screen_config_unchecked(_ecore_xcb_conn, root, + XCB_CURRENT_TIME, + reply->config_timestamp, + size_index, + reply->rotation, rate); + sreply = + xcb_randr_set_screen_config_reply(_ecore_xcb_conn, + scookie, NULL); + if (!sreply) + ret = EINA_FALSE; + else + { + ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ? + EINA_TRUE : EINA_FALSE; + free(sreply); + } + free(reply); + } +#endif + + return ret; +} + +/* + * @brief Free detailed mode information. The pointer handed in will be set to + * @c 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) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + RANDR_CHECK_1_2_RET(); + + if (!mode_info) return; + + if (mode_info->name) free(mode_info->name); + free(mode_info); + mode_info = NULL; +} + +/* + * @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) +{ + Ecore_X_Randr_Output ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_output_primary_cookie_t cookie; + xcb_randr_get_output_primary_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_3_RET(Ecore_X_Randr_None); + + if (!_ecore_xcb_randr_root_validate(root)) + return Ecore_X_Randr_None; + + cookie = xcb_randr_get_output_primary_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_output_primary_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + ret = reply->output; + free(reply); + } +#endif + return ret; +} + +/* + * @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) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_3_RET(); + + if ((output) && (_ecore_xcb_randr_root_validate(root))) + xcb_randr_set_output_primary(_ecore_xcb_conn, root, output); +#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) +{ + Ecore_X_Randr_Mode *modes = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (_randr_version >= RANDR_1_3) + { + modes = + _ecore_xcb_randr_13_output_modes_get(root, output, num, npreferred); + } + else if (_randr_version == RANDR_1_2) + { + modes = + _ecore_xcb_randr_12_output_modes_get(root, output, num, npreferred); + } +#endif + + return modes; +} + +EAPI Eina_Bool +ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output, Ecore_X_Randr_Mode mode) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None)) + return EINA_FALSE; + + xcb_randr_add_output_mode(_ecore_xcb_conn, output, mode); + return EINA_TRUE; +#endif + return EINA_FALSE; +} + +/* + * @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) +{ + Ecore_X_Randr_Mode_Info *ret = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (!_ecore_xcb_randr_root_validate(root)) return NULL; + + if (_randr_version >= RANDR_1_3) + ret = _ecore_xcb_randr_13_mode_info_get(root, mode); + else if (_randr_version == RANDR_1_2) + ret = _ecore_xcb_randr_12_mode_info_get(root, mode); +#endif + return ret; +} + +/* + * @brief add a mode to a display + * @param root window to which's screen's ressources are added + * @param mode_info + * @return Ecore_X_Randr_Mode of the added mode. Ecore_X_Randr_None if mode + * adding failed. + * @since 1.2.0 + */ +EAPI Ecore_X_Randr_Mode +ecore_x_randr_mode_info_add(Ecore_X_Window root, Ecore_X_Randr_Mode_Info *mode_info) +{ + Ecore_X_Randr_Mode mode = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_randr_create_mode_cookie_t cookie; + xcb_randr_create_mode_reply_t *reply; + xcb_randr_mode_info_t info; + int namelen = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if (!mode_info) return Ecore_X_Randr_None; + if (!_ecore_xcb_randr_root_validate(root)) return Ecore_X_Randr_None; + + namelen = strlen(mode_info->name); + + memset(&info, 0, sizeof(info)); + info.width = mode_info->width; + info.height = mode_info->height; + info.dot_clock = mode_info->dotClock; + info.hsync_start = mode_info->hSyncStart; + info.hsync_end = mode_info->hSyncEnd; + info.htotal = mode_info->hTotal; + info.hskew = mode_info->hSkew; + info.vsync_start = mode_info->vSyncStart; + info.vsync_end = mode_info->vSyncEnd; + info.vtotal = mode_info->vTotal; + info.mode_flags = mode_info->modeFlags; + info.name_len = namelen; + + cookie = + xcb_randr_create_mode_unchecked(_ecore_xcb_conn, root, info, + namelen, mode_info->name); + reply = xcb_randr_create_mode_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + mode = mode_info->xid; + free(reply); + } +#endif + return mode; +} + +/* + * @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) +{ + Ecore_X_Randr_Mode_Info **ret = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num) *num = 0; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (!_ecore_xcb_randr_root_validate(root)) return NULL; + + if (_randr_version >= RANDR_1_3) + ret = _ecore_xcb_randr_13_modes_info_get(root, num); + else if (_randr_version == RANDR_1_2) + ret = _ecore_xcb_randr_12_modes_info_get(root, num); +#endif + return ret; +} + +/** + * @brief Gets the width and hight of a given mode. + * + * @param root Window which's screen's ressources are queried. + * @param mode The mode which's size is to be looked up. + * @param w Width of given mode in px. + * @param 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) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(); + + if (mode == Ecore_X_Randr_None) return; + + if (_randr_version >= RANDR_1_3) + _ecore_xcb_randr_13_mode_size_get(root, mode, w, h); + else if (_randr_version == RANDR_1_2) + _ecore_xcb_randr_12_mode_size_get(root, mode, w, h); +#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. + * @param output The XID of the output. + * @param length Length of the byte-array. If @c NULL, request will fail. + * @return EDID information of the output. + */ +EAPI unsigned char * +ecore_x_randr_output_edid_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + unsigned long *length) +{ + unsigned char *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_output_property_cookie_t cookie; + xcb_randr_get_output_property_reply_t *reply; + Ecore_X_Atom atom; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if ((!length) || (!_ecore_xcb_randr_output_validate(root, output))) + return NULL; + + atom = ecore_x_atom_get("EDID"); + cookie = + xcb_randr_get_output_property_unchecked(_ecore_xcb_conn, output, atom, + XCB_GET_PROPERTY_TYPE_ANY, + 0, 100, 0, 0); + reply = + xcb_randr_get_output_property_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if ((reply->type == XCB_ATOM_INTEGER) && (reply->format == 8)) + { + if (length) *length = reply->num_items; + if ((ret = malloc(reply->num_items * sizeof(unsigned char)))) + { + memcpy(ret, xcb_randr_get_output_property_data(reply), + (reply->num_items * sizeof(unsigned char))); + } + } + free(reply); + } +#endif + return ret; +} + +/** + * @brief Gets the outputs which might be used simultaneously on the same CRTC. + * + * @param root Window that this information should be queried for. + * @param output The output which's clones we concern. + * @param num Number of possible clones. + * @return The existing outputs, @c NULL otherwise. + */ +EAPI Ecore_X_Randr_Output * +ecore_x_randr_output_clones_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num) +{ + Ecore_X_Randr_Output *outputs = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (output == Ecore_X_Randr_None) return NULL; + + if (_randr_version >= RANDR_1_3) + outputs = _ecore_xcb_randr_13_output_clones_get(root, output, num); + else if (_randr_version == RANDR_1_2) + outputs = _ecore_xcb_randr_12_output_clones_get(root, output, num); +#endif + return outputs; +} + +EAPI Ecore_X_Randr_Crtc * +ecore_x_randr_output_possible_crtcs_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num) +{ + Ecore_X_Randr_Crtc *crtcs = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (output == Ecore_X_Randr_None) return NULL; + + if (_randr_version >= RANDR_1_3) + crtcs = _ecore_xcb_randr_13_output_possible_crtcs_get(root, output, num); + else if (_randr_version == RANDR_1_2) + crtcs = _ecore_xcb_randr_12_output_possible_crtcs_get(root, output, num); +#endif + return crtcs; +} + +/** + * @brief gets the given output's name as reported by X + * @param root the window which's screen will be queried + * @param output The output name given to be reported. + * @param 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) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (output == Ecore_X_Randr_None) return NULL; + + if (_randr_version >= RANDR_1_3) + return _ecore_xcb_randr_13_output_name_get(root, output, len); + else if (_randr_version == RANDR_1_2) + return _ecore_xcb_randr_12_output_name_get(root, output, len); +#endif + + return NULL; +} + +EAPI Ecore_X_Randr_Connection_Status +ecore_x_randr_output_connection_status_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN); + + if (output == Ecore_X_Randr_None) + return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN; + + if (_randr_version >= RANDR_1_3) + return _ecore_xcb_randr_13_output_connection_status_get(root, output); + else if (_randr_version == RANDR_1_2) + return _ecore_xcb_randr_12_output_connection_status_get(root, output); +#endif + + return ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN; +} + +EAPI Ecore_X_Randr_Output * +ecore_x_randr_outputs_get(Ecore_X_Window root, + int *num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (_randr_version >= RANDR_1_3) + return _ecore_xcb_randr_13_outputs_get(root, num); + else if (_randr_version == RANDR_1_2) + return _ecore_xcb_randr_12_outputs_get(root, num); +#endif + + return NULL; +} + +EAPI Ecore_X_Randr_Crtc +ecore_x_randr_output_crtc_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(Ecore_X_Randr_None); + + if (output == Ecore_X_Randr_None) return Ecore_X_Randr_None; + + if (_randr_version >= RANDR_1_3) + return _ecore_xcb_randr_13_output_crtc_get(root, output); + else if (_randr_version == RANDR_1_2) + return _ecore_xcb_randr_12_output_crtc_get(root, output); +#endif + + return Ecore_X_Randr_None; +} + +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_XCB_RANDR + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + xcb_timestamp_t timestamp = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (w_mm) *w_mm = 0; + if (h_mm) *h_mm = 0; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(); + + if ((output != Ecore_X_Randr_None) && (_randr_version >= RANDR_1_3)) + { + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + timestamp = reply->config_timestamp; + free(reply); + } + else if ((output != Ecore_X_Randr_None) && (_randr_version == RANDR_1_2)) + { + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + timestamp = reply->config_timestamp; + free(reply); + } + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + if (w_mm) *w_mm = oreply->mm_width; + if (h_mm) *h_mm = oreply->mm_height; + free(oreply); + } +#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 + * coordinate will be assumed. + * @param y New y coordinate. If <0 (e.g. Ecore_X_Randr_Unset) the current y + * coordinate 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 @c EINA_TRUE if the configuration alteration was successful, + * @c EINA_FALSE otherwise. + */ +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) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ccookie; + xcb_randr_get_crtc_info_reply_t *creply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ccookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + creply = + xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ccookie, NULL); + if (creply) + { + xcb_randr_set_crtc_config_cookie_t scookie; + xcb_randr_set_crtc_config_reply_t *sreply; + + if ((mode == Ecore_X_Randr_None) || + (noutputs == Ecore_X_Randr_None)) + { + outputs = NULL; + noutputs = 0; + } + else if (noutputs == (int)Ecore_X_Randr_Unset) + { + outputs = xcb_randr_get_crtc_info_outputs(creply); + noutputs = creply->num_outputs; + } + if ((int)mode == Ecore_X_Randr_Unset) mode = creply->mode; + if (x < 0) x = creply->x; + if (y < 0) y = creply->y; + if ((int)orientation == Ecore_X_Randr_Unset) + orientation = creply->rotation; + + scookie = + xcb_randr_set_crtc_config_unchecked(_ecore_xcb_conn, + crtc, XCB_CURRENT_TIME, stamp, + x, y, mode, orientation, + noutputs, outputs); + sreply = + xcb_randr_set_crtc_config_reply(_ecore_xcb_conn, scookie, NULL); + if (sreply) + { + ret = (sreply->status == XCB_RANDR_SET_CONFIG_SUCCESS) ? + EINA_TRUE : EINA_FALSE; + free(sreply); + } + free(creply); + } +#endif + + return ret; +} + +/** + * @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 + * @c NULL CRTC will be disabled. + * @param noutputs Number of outputs in array to be used. Use + * Ecore_X_Randr_Unset (or @c -1) to use currently used outputs. + * @param mode XID of the mode to be set. If set to @c 0 the CRTC will be + * disabled. If set to @c -1 the call will fail. + * @return @c EINA_TRUE if mode setting was successful, @c EINA_FALSE + * otherwise. + */ +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) +{ + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if ((int)mode == Ecore_X_Randr_Unset) return ret; + ret = + ecore_x_randr_crtc_settings_set(root, crtc, outputs, noutputs, + Ecore_X_Randr_Unset, Ecore_X_Randr_Unset, + mode, Ecore_X_Randr_Unset); +#endif + + return ret; +} + +/** + * @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) +{ + Ecore_X_Randr_Mode ret = Ecore_X_Randr_Unset; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(Ecore_X_Randr_Unset); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + ret = oreply->mode; + free(oreply); + } +#endif + + return ret; +} + +EAPI Ecore_X_Randr_Orientation +ecore_x_randr_crtc_orientation_get(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc) +{ + Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(Ecore_X_Randr_None); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + ret = oreply->rotation; + free(oreply); + } +#endif + + return ret; +} + +EAPI Eina_Bool +ecore_x_randr_crtc_orientation_set(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc, + Ecore_X_Randr_Orientation orientation) +{ + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_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); + } +#endif + return ret; +} + +EAPI Ecore_X_Randr_Orientation +ecore_x_randr_crtc_orientations_get(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc) +{ + Ecore_X_Randr_Orientation ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(Ecore_X_Randr_None); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + oreply = + xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + ret = oreply->rotations; + free(oreply); + } +#endif + + return ret; +} + +/* + * @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) +{ + Ecore_X_Randr_Output *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_possible_outputs; + ret = malloc(sizeof(Ecore_X_Randr_Output) * + oreply->num_possible_outputs); + if (ret) + { + memcpy(ret, xcb_randr_get_crtc_info_possible(oreply), + sizeof(Ecore_X_Randr_Output) * + oreply->num_possible_outputs); + } + free(oreply); + } +#endif + + return ret; +} + +/* + * @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) +{ + Ecore_X_Randr_Crtc *ret = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (_randr_version >= RANDR_1_3) + { + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + if (num) *num = reply->num_crtcs; + ret = malloc(sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs); + if (ret) + memcpy(ret, xcb_randr_get_screen_resources_current_crtcs(reply), + sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs); + free(reply); + } + } + else if (_randr_version == RANDR_1_2) + { + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + if (num) *num = reply->num_crtcs; + ret = malloc(sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs); + if (ret) + memcpy(ret, xcb_randr_get_screen_resources_crtcs(reply), + sizeof(Ecore_X_Randr_Crtc) * reply->num_crtcs); + free(reply); + } + } +#endif + + return ret; +} + +/* + * @deprecated bad naming. Use ecore_x_randr_window_crtcs_get instead. + * @brief Get the CRTCs, which display a certain window. + * + * @param window Window the displaying CRTCs shall be found for. + * @param num The number of CRTCs displaying the window. + * @return Array of CRTCs that display a certain window. @c NULL if no CRTCs + * was found that displays the specified window. + */ +EAPI Ecore_X_Randr_Crtc * +ecore_x_randr_current_crtc_get(Ecore_X_Window window, + int *num) +{ + return ecore_x_randr_window_crtcs_get(window, num); +} + +/* + * @brief Get the CRTCs, which display a certain window. + * + * @param window Window the displaying crtcs shall be found for. + * @param num The number of crtcs displaying the window. + * @return Array of crtcs that display a certain window. @c NULL if no crtcs + * was found that displays the specified window. + * @since 1.2.0 + */ +EAPI Ecore_X_Randr_Crtc * +ecore_x_randr_window_crtcs_get(Ecore_X_Window window, + int *num) +{ +#ifdef ECORE_XCB_RANDR + Ecore_X_Window root; + Eina_Rectangle w_geo, c_geo; + Ecore_X_Randr_Crtc *crtcs, *ret = NULL; + Ecore_X_Randr_Mode mode; + int ncrtcs, i, nret = 0; + xcb_translate_coordinates_cookie_t cookie; + xcb_translate_coordinates_reply_t *trans; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + ecore_x_window_geometry_get(window, &w_geo.x, &w_geo.y, &w_geo.w, &w_geo.h); + + root = ecore_x_window_root_get(window); + crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs); + if (!crtcs) goto _ecore_x_randr_window_crtcs_get_fail; + + /* now get window RELATIVE to root window - thats what matters. */ + cookie = xcb_translate_coordinates(_ecore_xcb_conn, window, root, 0, 0); + trans = xcb_translate_coordinates_reply(_ecore_xcb_conn, cookie, NULL); + w_geo.x = trans->dst_x; + w_geo.y = trans->dst_y; + free(trans); + + ret = calloc(1, ncrtcs * sizeof(Ecore_X_Randr_Crtc)); + if (!ret) + { + free(crtcs); + goto _ecore_x_randr_window_crtcs_get_fail; + } + for (i = 0, nret = 0; i < ncrtcs; i++) + { + /* if crtc is not enabled, don't bother about it any further */ + mode = ecore_x_randr_crtc_mode_get(root, crtcs[i]); + if (mode == Ecore_X_Randr_None) continue; + + ecore_x_randr_crtc_geometry_get(root, crtcs[i], &c_geo.x, &c_geo.y, + &c_geo.w, &c_geo.h); + if (eina_rectangles_intersect(&w_geo, &c_geo)) + { + ret[nret] = crtcs[i]; + nret++; + } + } + free(crtcs); + + if (num) *num = nret; + return ret; + +_ecore_x_randr_window_crtcs_get_fail: +#endif + if (num) *num = 0; + return NULL; +} + +/* + * @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) +{ + Ecore_X_Randr_Output *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(NULL); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return ret; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_outputs; + ret = malloc(sizeof(Ecore_X_Randr_Output) * oreply->num_outputs); + if (ret) + memcpy(ret, xcb_randr_get_crtc_info_outputs(oreply), + sizeof(Ecore_X_Randr_Output) * oreply->num_outputs); + free(oreply); + } +#endif + + return ret; +} + +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_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtc, stamp); + oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + if (x) *x = oreply->x; + if (y) *y = oreply->y; + if (w) *w = oreply->width; + if (h) *h = oreply->height; + free(oreply); + } +#endif +} + +/** + * @brief Sets a CRTC relative to another one. + * + * @param root The window on which CRTC's position will be set. + * @param crtc_r1 The CRTC to be positioned. + * @param crtc_r2 The CRTC the position should be relative to. + * @param policy The relation between the crtcs. + * @param alignment In case CRTCs size differ, aligns CRTC1 accordingly at + * CRTC2's borders. + * @return @c EINA_TRUE if crtc could be successfully positioned, @c 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_XCB_RANDR + Eina_Rectangle r1, r2; + int w_max = 0, h_max = 0, cw = 0, ch = 0, xn = -1, yn = -1; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if ((ecore_x_randr_crtc_mode_get(root, crtc_r1) == 0) || + (ecore_x_randr_crtc_mode_get(root, crtc_r2) == 0)) + return EINA_FALSE; + + if ((!_ecore_xcb_randr_crtc_validate(root, crtc_r1) || + (!(crtc_r1 != crtc_r2) && (!_ecore_xcb_randr_crtc_validate(root, crtc_r2))))) + return EINA_FALSE; + + ecore_x_randr_crtc_geometry_get(root, crtc_r1, &r1.x, &r1.y, &r1.w, &r1.h); + ecore_x_randr_crtc_geometry_get(root, crtc_r2, &r2.x, &r2.y, &r2.w, &r2.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: + xn = (r2.x + r2.w); + if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE) + yn = -1; + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL) + yn = ((int)(((double)r2.h / 2.0) + (double)r2.y - ((double)r1.h / 2.0))); + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR) + yn = ((int)((double)ch / 2.0) - ((double)r1.h / 2.0)); + break; + + case ECORE_X_RANDR_OUTPUT_POLICY_LEFT: + xn = (r2.x - r1.w); + if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE) + yn = -1; + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL) + yn = ((int)(((double)r2.h / 2.0) + (double)r2.y - ((double)r1.h / 2.0))); + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR) + yn = ((int)((double)ch / 2.0) - ((double)r1.h / 2.0)); + break; + + case ECORE_X_RANDR_OUTPUT_POLICY_BELOW: + yn = (r2.y + r2.h); + if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE) + xn = -1; + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL) + xn = ((int)((((double)r2.x + (double)r2.w) / 2.0) - ((double)r1.w / 2.0))); + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR) + xn = ((int)((double)cw / 2.0)); + break; + + case ECORE_X_RANDR_OUTPUT_POLICY_ABOVE: + yn = (r2.y - r1.h); + if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_NONE) + xn = -1; + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_REL) + xn = ((int)((((double)r2.x + (double)r2.w) / 2.0) - ((double)r1.w / 2.0))); + else if (alignment == ECORE_X_RANDR_RELATIVE_ALIGNMENT_CENTER_SCR) + xn = ((int)((double)cw / 2.0)); + break; + + case ECORE_X_RANDR_OUTPUT_POLICY_CLONE: + return ecore_x_randr_crtc_pos_set(root, crtc_r1, r2.x, r2.y); + break; + + case ECORE_X_RANDR_OUTPUT_POLICY_NONE: + break; + default: + return EINA_FALSE; + } + + if ((xn == r1.x) && (yn == r1.x)) return EINA_TRUE; + if (((yn + r1.h) > h_max) || ((xn + r1.w) > w_max)) + return EINA_FALSE; + + return ecore_x_randr_crtc_pos_set(root, crtc_r1, xn, yn); +#endif + + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_randr_move_all_crtcs_but(Ecore_X_Window root, + const Ecore_X_Randr_Crtc *not_moved, + int num, + int dx, + int dy) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + Ecore_X_Randr_Crtc *crtcs = NULL, *move = NULL; + int i = 0, j = 0, k = 0, n = 0, total = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if ((num <= 0) || (!not_moved) || (!_ecore_xcb_randr_root_validate(root))) + return EINA_FALSE; + + crtcs = ecore_x_randr_crtcs_get(root, &total); + n = (total - num); + move = malloc(sizeof(Ecore_X_Randr_Crtc) * n); + if (move) + { + for (i = 0, k = 0; (i < total) && (k < n); i++) + { + for (j = 0; j < num; j++) + if (crtcs[i] == not_moved[j]) break; + if (j == num) + move[k++] = crtcs[i]; + } + ret = ecore_x_randr_move_crtcs(root, move, n, dx, dy); + free(move); + free(crtcs); + } +#endif + + return ret; +} + +EAPI void +ecore_x_randr_crtc_pos_get(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc, + int *x, + int *y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(); + + ecore_x_randr_crtc_geometry_get(root, crtc, x, y, NULL, NULL); +#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 @c 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) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_RANDR + int w = 0, h = 0, nw = 0, nh = 0; + Eina_Rectangle rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + ecore_x_randr_crtc_geometry_get(root, crtc, + &rect.x, &rect.y, &rect.w, &rect.h); + ecore_x_randr_screen_current_size_get(root, &w, &h, NULL, NULL); + if (x < 0) x = rect.x; + if (y < 0) y = rect.y; + if ((x + rect.w) > w) + nw = (x + rect.w); + if ((y + rect.h) > h) + nh = (y + rect.h); + + if ((nw != 0) || (nh != 0)) + { + if (!ecore_x_randr_screen_current_size_set(root, nw, nh, 0, 0)) + return EINA_FALSE; + } + + ret = ecore_x_randr_crtc_settings_set(root, crtc, NULL, -1, x, y, -1, -1); +#endif + + return ret; +} + +EAPI void +ecore_x_randr_crtc_size_get(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc, + int *w, + int *h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + 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) +{ + Ecore_X_Randr_Refresh_Rate ret = 0.0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(0.0); + + if (!_ecore_xcb_randr_crtc_validate(root, crtc)) return 0.0; + + if (_randr_version >= RANDR_1_3) + { + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_mode_info_iterator_t miter; + + miter = + xcb_randr_get_screen_resources_current_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + if (minfo->id == mode) + { + if ((minfo->htotal) && (minfo->vtotal)) + { + ret = ((double)minfo->dot_clock / + ((double)minfo->htotal * + (double)minfo->vtotal)); + } + break; + } + xcb_randr_mode_info_next(&miter); + } + free(reply); + } + } + else if (_randr_version == RANDR_1_2) + { + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_mode_info_iterator_t miter; + + miter = xcb_randr_get_screen_resources_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + if (minfo->id == mode) + { + if ((minfo->htotal) && (minfo->vtotal)) + { + ret = ((double)minfo->dot_clock / + ((double)minfo->htotal * + (double)minfo->vtotal)); + } + break; + } + xcb_randr_mode_info_next(&miter); + } + free(reply); + } + } +#endif + return ret; +} + +/* + * @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 necessary 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 @c 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 num, + int dx, + int dy) +{ + Eina_Bool ret = EINA_TRUE; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_crtc_info_reply_t *oreply[num]; + int i = 0, cw = 0, ch = 0; + int mw = 0, mh = 0, nw = 0, nh = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if (!_ecore_xcb_randr_root_validate(root)) return EINA_FALSE; + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + ecore_x_randr_screen_size_range_get(root, NULL, NULL, &mw, &mh); + ecore_x_randr_screen_current_size_get(root, &cw, &ch, NULL, NULL); + nw = cw; + nh = ch; + + for (i = 0; i < num; i++) + { + xcb_randr_get_crtc_info_cookie_t ocookie; + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtcs[i], + stamp); + oreply[i] = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply[i]) + { + if (((oreply[i]->x + dx) < 0) || + ((oreply[i]->y + dy) < 0) || + ((oreply[i]->x + oreply[i]->width + dx) > mw) || + ((oreply[i]->y + oreply[i]->height + dy) > mh)) + { + continue; + } + nw = MAX((int)(oreply[i]->x + oreply[i]->width + dx), nw); + nh = MAX((int)(oreply[i]->y + oreply[i]->height + dy), nh); + } + } + + if ((nw > cw) || (nh > ch)) + { + if (!ecore_x_randr_screen_current_size_set(root, nw, nh, -1, -1)) + { + for (i = 0; i < num; i++) + if (oreply[i]) free(oreply[i]); + + return EINA_FALSE; + } + } + + for (i = 0; ((i < num) && (oreply[i])); i++) + { + if (!oreply[i]) continue; + if (!ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL, -1, + (oreply[i]->x + dx), + (oreply[i]->y + dy), + oreply[i]->mode, + oreply[i]->rotation)) + { + ret = EINA_FALSE; + break; + } + } + + if (i < num) + { + while (i-- >= 0) + { + if (oreply[i]) + ecore_x_randr_crtc_settings_set(root, crtcs[i], NULL, -1, + (oreply[i]->x - dx), + (oreply[i]->y - dy), + oreply[i]->mode, + oreply[i]->rotation); + } + } + + for (i = 0; i < num; i++) + if (oreply[i]) free(oreply[i]); +#endif + + return ret; +} + +/** + * @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_XCB_RANDR + uint16_t mask = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if (on) + { + mask = XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE; + if (_randr_version >= ((1 << 16) | 2)) + { + mask |= (XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | + XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | + XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY); + } + } + + xcb_randr_select_input(_ecore_xcb_conn, win, mask); +#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_XCB_RANDR + xcb_timestamp_t stamp = 0; + Ecore_X_Randr_Crtc *crtcs = NULL; + int total = 0, i = 0, w = 0, h = 0; + int dx = 100000, dy = 100000, num = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + if (!_ecore_xcb_randr_root_validate(root)) return; + crtcs = ecore_x_randr_crtcs_get(root, &total); + + if (_randr_version >= RANDR_1_3) + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + else if (_randr_version == RANDR_1_2) + stamp = _ecore_xcb_randr_12_get_resource_timestamp(root); + + /* I hate declaring variables inside code like this, but we need the + * value of 'total' before we can */ + Ecore_X_Randr_Crtc enabled[total]; + + for (i = 0; i < total; i++) + { + xcb_randr_get_crtc_info_cookie_t ocookie; + xcb_randr_get_crtc_info_reply_t *oreply; + + ocookie = + xcb_randr_get_crtc_info_unchecked(_ecore_xcb_conn, crtcs[i], stamp); + oreply = xcb_randr_get_crtc_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (!oreply) continue; + if ((oreply->mode <= 0) || (oreply->num_outputs == 0)) + { + free(oreply); + continue; + } + + enabled[num++] = crtcs[i]; + if ((int)(oreply->x + oreply->width) > w) + w = (oreply->x + oreply->width); + if ((int)(oreply->y + oreply->height) > h) + h = (oreply->y + oreply->height); + + if (oreply->x < dx) dx = oreply->x; + if (oreply->y < dy) dy = oreply->y; + + free(oreply); + } + free(crtcs); + + if ((dx > 0) || (dy > 0)) + { + if (ecore_x_randr_move_crtcs(root, enabled, num, -dx, -dy)) + { + w -= dx; + h -= dy; + } + } + + ecore_x_randr_screen_current_size_set(root, w, h, -1, -1); +#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 *minw, + int *minh, + int *maxw, + int *maxh) +{ +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_size_range_cookie_t cookie; + xcb_randr_get_screen_size_range_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(); + + cookie = xcb_randr_get_screen_size_range_unchecked(_ecore_xcb_conn, root); + reply = xcb_randr_get_screen_size_range_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if (minw) *minw = reply->min_width; + if (minh) *minh = reply->min_height; + if (maxw) *maxw = reply->max_width; + if (maxh) *maxh = reply->max_height; + free(reply); + } +#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_XCB_RANDR + Ecore_X_Randr_Screen scr = 0; + xcb_screen_t *s; +# define RANDR_VALIDATE_ROOT(screen, root) \ + ((screen == _ecore_xcb_randr_root_to_screen(root)) != -1) +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(); + + if (!RANDR_VALIDATE_ROOT(scr, root)) return; + + s = ecore_x_screen_get(scr); + if (w) *w = s->width_in_pixels; + if (h) *h = s->height_in_pixels; + if (w_mm) *w_mm = s->width_in_millimeters; + if (h_mm) *h_mm = s->height_in_millimeters; +#endif +} + +/* + * @param root Window which's screen's size should be set. If invalid (e.g. + * @c 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 @c 0, current + * aspect is assumed. + * @param h_mm Height in mm the screen should be set to. If @c 0, current + * aspect is assumed. + * @return @c EINA_TRUE if request was successfully sent or screen is already + * in requested size, @c 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) +{ + Eina_Bool ret = EINA_TRUE; +#ifdef ECORE_XCB_RANDR + Ecore_X_Randr_Screen scr; + int wc = 0, hc = 0, w_mm_c = 0, h_mm_c = 0; + int mw = 0, mh = 0, xw = 0, xh = 0; +# define RANDR_VALIDATE_ROOT(screen, root) \ + ((screen == _ecore_xcb_randr_root_to_screen(root)) != -1) +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if (!RANDR_VALIDATE_ROOT(scr, root)) return EINA_FALSE; + ecore_x_randr_screen_current_size_get(root, &wc, &hc, &w_mm_c, &h_mm_c); + if ((w == wc) && (h == hc) && (w_mm == w_mm_c) && (h_mm == h_mm_c)) + return EINA_TRUE; + ecore_x_randr_screen_size_range_get(root, &mw, &mh, &xw, &xh); + if (((w != 1) && ((w < mw) || (w > xw))) || + ((h != -1) && ((h < mh) || (h > xh)))) return EINA_FALSE; + + if (w <= 0) + w = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels; + if (h <= 0) + h = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels; + + /* NB: Hmmmm, xlib version divides w_mm by width ... that seems wrong */ + if (w_mm <= 0) + w_mm = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_millimeters; + if (h_mm <= 0) + h_mm = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_millimeters; + + xcb_randr_set_screen_size(_ecore_xcb_conn, root, w, h, w_mm, h_mm); +#endif + + return ret; +} + +/* + * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead. + * @brief Get the outputs, which display a certain window. + * + * @param window Window the displaying outputs shall be found for. + * @param num The number of outputs displaying the window. + * @return Array of outputs that display a certain window. @c NULL if no + * outputs was found that displays the specified window. + */ + +Ecore_X_Randr_Output * +ecore_x_randr_current_output_get(Ecore_X_Window window, + int *num) +{ + return ecore_x_randr_window_outputs_get(window, num); +} + +/* + * @brief Get the outputs, which display a certain window. + * + * @param window Window the displaying outputs shall be found for. + * @param num The number of outputs displaying the window. + * @return Array of outputs that display a certain window. @c NULL if no + * outputs was found that displays the specified window. + */ +EAPI Ecore_X_Randr_Output * +ecore_x_randr_window_outputs_get(Ecore_X_Window window, + int *num) +{ +#ifdef ECORE_XCB_RANDR + Ecore_X_Window root; + Ecore_X_Randr_Crtc *crtcs; + Ecore_X_Randr_Output *outputs, *ret = NULL, *tret; + int ncrtcs, noutputs, i, nret = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num) *num = 0; + +#ifdef ECORE_XCB_RANDR + if (_randr_version < RANDR_1_2) goto _ecore_x_randr_current_output_get_fail; + + root = ecore_x_window_root_get(window); + if (!(crtcs = ecore_x_randr_window_crtcs_get(window, &ncrtcs))) + goto _ecore_x_randr_current_output_get_fail; + + for (i = 0, nret = 0; i < ncrtcs; i++) + { + + outputs = ecore_x_randr_crtc_outputs_get(root, crtcs[i], + &noutputs); + if (!outputs) + goto _ecore_x_randr_current_output_get_fail_free; + tret = realloc(ret, ((nret + noutputs) * sizeof(Ecore_X_Randr_Output))); + if (!tret) goto _ecore_x_randr_current_output_get_fail_free; + ret = tret; + memcpy(&ret[nret], outputs, (noutputs * sizeof(Ecore_X_Randr_Output))); + nret += noutputs; + free(outputs); + outputs = NULL; + } + free(crtcs); + + if (num) + *num = nret; + + return ret; + +_ecore_x_randr_current_output_get_fail_free: + free(outputs); + free(crtcs); + free(ret); +_ecore_x_randr_current_output_get_fail: +#endif + if (num) *num = 0; + return NULL; +} + +/* + * @brief get the backlight level of the given output + * @param root window which's screen should be queried + * @param output from which the backlight level should be retrieved + * @return the backlight level + */ +EAPI double +ecore_x_randr_output_backlight_level_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ +#ifdef ECORE_XCB_RANDR + Ecore_X_Atom _backlight; + xcb_intern_atom_cookie_t acookie; + xcb_intern_atom_reply_t *areply; + xcb_randr_get_output_property_cookie_t cookie; + xcb_randr_get_output_property_reply_t *reply; + xcb_randr_query_output_property_cookie_t qcookie; + xcb_randr_query_output_property_reply_t *qreply; + double dvalue; + long value, max, min; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(-1); + + acookie = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 1, + strlen("Backlight"), "Backlight"); + areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL); + + if (!areply) + { + ERR("Backlight property is not suppported on this server or driver"); + return -1; + } + else + { + _backlight = areply->atom; + free(areply); + } + + if (!_ecore_xcb_randr_output_validate(root, output)) + { + ERR("Invalid output"); + return -1; + } + + cookie = + xcb_randr_get_output_property_unchecked(_ecore_xcb_conn, + output, _backlight, + XCB_ATOM_NONE, 0, 4, 0, 0); + reply = + xcb_randr_get_output_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) + { + WRN("Backlight not supported on this output"); + return -1; + } + + if ((reply->format != 32) || (reply->num_items != 1) || + (reply->type != XCB_ATOM_INTEGER)) + { + free(reply); + return -1; + } + + value = *((long *)xcb_randr_get_output_property_data(reply)); + free (reply); + + /* I have the current value of the backlight */ + /* Now retrieve the min and max intensities of the output */ + qcookie = + xcb_randr_query_output_property_unchecked(_ecore_xcb_conn, + output, _backlight); + qreply = + xcb_randr_query_output_property_reply(_ecore_xcb_conn, qcookie, NULL); + if (qreply) + { + dvalue = -1; + if ((qreply->range) && + (xcb_randr_query_output_property_valid_values_length(qreply) == 2)) + { + int32_t *vals; + + vals = xcb_randr_query_output_property_valid_values(qreply); + /* finally convert the current value in the interval [0..1] */ + min = vals[0]; + max = vals[1]; + dvalue = ((double)(value - min)) / ((double)(max - min)); + } + free(qreply); + return dvalue; + } +#endif + return -1; +} + +/* + * @brief Set the backlight level of a given output. + * + * @param root Window which's screen should be queried. + * @param output That should be set. + * @param level For which the backlight should be set. + * @return @c EINA_TRUE in case of success. + */ +EAPI Eina_Bool +ecore_x_randr_output_backlight_level_set(Ecore_X_Window root, + Ecore_X_Randr_Output output, + double level) +{ +#ifdef ECORE_XCB_RANDR + Ecore_X_Atom _backlight; + xcb_intern_atom_cookie_t acookie; + xcb_intern_atom_reply_t *areply; + xcb_randr_query_output_property_cookie_t qcookie; + xcb_randr_query_output_property_reply_t *qreply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if ((level < 0) || (level > 1)) + { + ERR("Backlight level should be between 0 and 1"); + return EINA_FALSE; + } + + if (!_ecore_xcb_randr_output_validate(root, output)) + { + ERR("Wrong output value"); + return EINA_FALSE; + } + + acookie = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 1, + strlen("Backlight"), "Backlight"); + areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL); + if (!areply) + { + WRN("Backlight property is not suppported on this server or driver"); + return EINA_FALSE; + } + else + { + _backlight = areply->atom; + free(areply); + } + + qcookie = + xcb_randr_query_output_property_unchecked(_ecore_xcb_conn, + output, _backlight); + qreply = + xcb_randr_query_output_property_reply(_ecore_xcb_conn, qcookie, NULL); + if (qreply) + { + if ((qreply->range) && (qreply->length == 2)) + { + int32_t *vals; + double min, max, tmp; + long n; + + vals = xcb_randr_query_output_property_valid_values(qreply); + min = vals[0]; + max = vals[1]; + tmp = (level * (max - min)) + min; + n = tmp; + if (n > max) n = max; + if (n < min) n = min; + xcb_randr_change_output_property(_ecore_xcb_conn, output, + _backlight, XCB_ATOM_INTEGER, + 32, XCB_PROP_MODE_REPLACE, + 1, (unsigned char *)&n); + ecore_x_flush(); // needed + } + + free(qreply); + return EINA_TRUE; + } +#endif + return EINA_FALSE; +} + +/* + * @brief Check if a backlight is available. + * + * @return Whether a backlight is available. + */ +EAPI Eina_Bool +ecore_x_randr_output_backlight_available(void) +{ +#ifdef ECORE_XCB_RANDR + Ecore_X_Atom _backlight; + xcb_intern_atom_cookie_t acookie; + xcb_intern_atom_reply_t *areply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + acookie = + xcb_intern_atom_unchecked(_ecore_xcb_conn, 1, + strlen("Backlight"), "Backlight"); + areply = xcb_intern_atom_reply(_ecore_xcb_conn, acookie, NULL); + + if (!areply) + { + ERR("Backlight property is not suppported on this server or driver"); + return EINA_FALSE; + } + else + { + _backlight = areply->atom; + free(areply); + return EINA_TRUE; + } +#endif + return EINA_FALSE; +} + +EAPI int +ecore_x_randr_edid_version_get(unsigned char *edid, unsigned long edid_length) +{ + if ((edid_length > _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR) && + (ecore_x_randr_edid_has_valid_header(edid, edid_length))) + return (edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR] << 8) | + edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR]; + return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; +} + +EAPI char * +ecore_x_randr_edid_display_name_get(unsigned char *edid, unsigned long edid_length) +{ + unsigned char *block = NULL; + int version = 0; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL; + + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfc) + { + char *name, *p; + const char *edid_name; + + edid_name = (const char *)block + + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + name = + malloc(sizeof(char) * + _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + if (!name) return NULL; + + strncpy(name, edid_name, + (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + name[_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX] = 0; + for (p = name; *p; p++) + if ((*p < ' ') || (*p > '~')) *p = 0; + + return name; + } + } + return NULL; +} + +EAPI Eina_Bool +ecore_x_randr_edid_has_valid_header(unsigned char *edid, unsigned long edid_length) +{ + const unsigned char header[] = + { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 + }; + + if ((!edid) || (edid_length < 8)) return EINA_FALSE; + if (!memcmp(edid, header, 8)) return EINA_TRUE; + return EINA_FALSE; +} + +/* local functions */ +static Eina_Bool +_ecore_xcb_randr_output_validate(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if ((output) && (_ecore_xcb_randr_root_validate(root))) + { + if (_randr_version >= RANDR_1_3) + { + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + int len = 0, i = 0; + xcb_randr_output_t *outputs; + + len = + xcb_randr_get_screen_resources_current_outputs_length(reply); + outputs = + xcb_randr_get_screen_resources_current_outputs(reply); + for (i = 0; i < len; i++) + { + if (outputs[i] == output) + { + ret = EINA_TRUE; + break; + } + } + free(reply); + } + } + else if (_randr_version == RANDR_1_2) + { + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + int len = 0, i = 0; + xcb_randr_output_t *outputs; + + len = xcb_randr_get_screen_resources_outputs_length(reply); + outputs = xcb_randr_get_screen_resources_outputs(reply); + for (i = 0; i < len; i++) + { + if (outputs[i] == output) + { + ret = EINA_TRUE; + break; + } + } + free(reply); + } + } + } +#endif + return ret; +} + +/** + * @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 @c EINA_TRUE will be returned, else + * @c EINA_FALSE is returned. + */ +static Eina_Bool +_ecore_xcb_randr_crtc_validate(Ecore_X_Window root, + Ecore_X_Randr_Crtc crtc) +{ + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if (((int)crtc == Ecore_X_Randr_None) || ((int)crtc == Ecore_X_Randr_Unset)) + return ret; + + if ((crtc) && (_ecore_xcb_randr_root_validate(root))) + { + if (_randr_version >= RANDR_1_3) + { + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + int i = 0; + xcb_randr_crtc_t *crtcs; + + crtcs = xcb_randr_get_screen_resources_current_crtcs(reply); + for (i = 0; i < reply->num_crtcs; i++) + { + if (crtcs[i] == crtc) + { + ret = EINA_TRUE; + break; + } + } + free(reply); + } + } + else if (_randr_version == RANDR_1_2) + { + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + int i = 0; + xcb_randr_crtc_t *crtcs; + + crtcs = xcb_randr_get_screen_resources_crtcs(reply); + for (i = 0; i < reply->num_crtcs; i++) + { + if (crtcs[i] == crtc) + { + ret = EINA_TRUE; + break; + } + } + free(reply); + } + } + } +#endif + + return ret; +} + +static Ecore_X_Randr_Mode * +_ecore_xcb_randr_12_output_modes_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num, + int *npreferred) +{ + Ecore_X_Randr_Mode *modes = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_modes; + if (npreferred) *npreferred = oreply->num_preferred; + + modes = malloc(sizeof(Ecore_X_Randr_Mode) * + oreply->num_modes); + if (modes) + { + xcb_randr_mode_t *rmodes; + int len = 0; + + len = xcb_randr_get_output_info_modes_length(oreply); + rmodes = xcb_randr_get_output_info_modes(oreply); + memcpy(modes, rmodes, sizeof(Ecore_X_Randr_Mode) * len); + } + free(oreply); + } + free(reply); + } +#endif + return modes; +} + +static Ecore_X_Randr_Mode * +_ecore_xcb_randr_13_output_modes_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num, + int *npreferred) +{ + Ecore_X_Randr_Mode *modes = NULL; +#ifdef ECORE_XCB_RANDR + xcb_timestamp_t stamp = 0; + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + stamp = _ecore_xcb_randr_13_get_resource_timestamp(root); + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, stamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_modes; + if (npreferred) *npreferred = oreply->num_preferred; + + modes = malloc(sizeof(Ecore_X_Randr_Mode) * oreply->num_modes); + if (modes) + { + xcb_randr_mode_t *rmodes; + int len = 0; + + len = xcb_randr_get_output_info_modes_length(oreply); + rmodes = xcb_randr_get_output_info_modes(oreply); + memcpy(modes, rmodes, sizeof(Ecore_X_Randr_Mode) * len); + } + free(oreply); + } +#endif + return modes; +} + +static Ecore_X_Randr_Mode_Info * +_ecore_xcb_randr_12_mode_info_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode) +{ + Ecore_X_Randr_Mode_Info *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + if ((ret = malloc(sizeof(Ecore_X_Randr_Mode_Info)))) + { + uint8_t *nbuf; + xcb_randr_mode_info_iterator_t miter; + + nbuf = xcb_randr_get_screen_resources_names(reply); + miter = xcb_randr_get_screen_resources_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + nbuf += minfo->name_len; + + if (minfo->id == mode) + { + ret->xid = minfo->id; + ret->width = minfo->width; + ret->height = minfo->height; + ret->dotClock = minfo->dot_clock; + ret->hSyncStart = minfo->hsync_start; + ret->hSyncEnd = minfo->hsync_end; + ret->hTotal = minfo->htotal; + ret->vSyncStart = minfo->vsync_start; + ret->vSyncEnd = minfo->vsync_end; + ret->vTotal = minfo->vtotal; + ret->modeFlags = minfo->mode_flags; + + ret->name = NULL; + ret->nameLength = minfo->name_len; + if (ret->nameLength > 0) + { + ret->name = malloc(ret->nameLength + 1); + if (ret->name) + memcpy(ret->name, nbuf, ret->nameLength + 1); + } + + break; + } + xcb_randr_mode_info_next(&miter); + } + } + + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Mode_Info * +_ecore_xcb_randr_13_mode_info_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode) +{ + Ecore_X_Randr_Mode_Info *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + if ((ret = malloc(sizeof(Ecore_X_Randr_Mode_Info)))) + { + uint8_t *nbuf; + xcb_randr_mode_info_iterator_t miter; + + nbuf = xcb_randr_get_screen_resources_current_names(reply); + miter = + xcb_randr_get_screen_resources_current_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + nbuf += minfo->name_len; + + if (minfo->id == mode) + { + ret->xid = minfo->id; + ret->width = minfo->width; + ret->height = minfo->height; + ret->dotClock = minfo->dot_clock; + ret->hSyncStart = minfo->hsync_start; + ret->hSyncEnd = minfo->hsync_end; + ret->hTotal = minfo->htotal; + ret->vSyncStart = minfo->vsync_start; + ret->vSyncEnd = minfo->vsync_end; + ret->vTotal = minfo->vtotal; + ret->modeFlags = minfo->mode_flags; + + ret->name = NULL; + ret->nameLength = minfo->name_len; + if (ret->nameLength > 0) + { + ret->name = malloc(ret->nameLength + 1); + if (ret->name) + memcpy(ret->name, nbuf, ret->nameLength + 1); + } + + break; + } + xcb_randr_mode_info_next(&miter); + } + } + + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Mode_Info ** +_ecore_xcb_randr_12_modes_info_get(Ecore_X_Window root, + int *num) +{ + Ecore_X_Randr_Mode_Info **ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + if (num) *num = reply->num_modes; + ret = malloc(sizeof(Ecore_X_Randr_Mode_Info *) * reply->num_modes); + if (ret) + { + xcb_randr_mode_info_iterator_t miter; + int i = 0; + uint8_t *nbuf; + + nbuf = xcb_randr_get_screen_resources_names(reply); + miter = xcb_randr_get_screen_resources_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + nbuf += minfo->name_len; + if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info)))) + { + ret[i]->xid = minfo->id; + ret[i]->width = minfo->width; + ret[i]->height = minfo->height; + ret[i]->dotClock = minfo->dot_clock; + ret[i]->hSyncStart = minfo->hsync_start; + ret[i]->hSyncEnd = minfo->hsync_end; + ret[i]->hTotal = minfo->htotal; + ret[i]->vSyncStart = minfo->vsync_start; + ret[i]->vSyncEnd = minfo->vsync_end; + ret[i]->vTotal = minfo->vtotal; + ret[i]->modeFlags = minfo->mode_flags; + + ret[i]->name = NULL; + ret[i]->nameLength = minfo->name_len; + if (ret[i]->nameLength > 0) + { + ret[i]->name = malloc(ret[i]->nameLength + 1); + if (ret[i]->name) + memcpy(ret[i]->name, nbuf, + ret[i]->nameLength + 1); + } + } + else + { + while (i > 0) + free(ret[--i]); + free(ret); + ret = NULL; + break; + } + i++; + xcb_randr_mode_info_next(&miter); + } + } + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Mode_Info ** +_ecore_xcb_randr_13_modes_info_get(Ecore_X_Window root, + int *num) +{ + Ecore_X_Randr_Mode_Info **ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + if (num) *num = reply->num_modes; + ret = malloc(sizeof(Ecore_X_Randr_Mode_Info *) * reply->num_modes); + if (ret) + { + xcb_randr_mode_info_iterator_t miter; + int i = 0; + uint8_t *nbuf; + + nbuf = xcb_randr_get_screen_resources_current_names(reply); + miter = + xcb_randr_get_screen_resources_current_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + nbuf += minfo->name_len; + if ((ret[i] = malloc(sizeof(Ecore_X_Randr_Mode_Info)))) + { + ret[i]->xid = minfo->id; + ret[i]->width = minfo->width; + ret[i]->height = minfo->height; + ret[i]->dotClock = minfo->dot_clock; + ret[i]->hSyncStart = minfo->hsync_start; + ret[i]->hSyncEnd = minfo->hsync_end; + ret[i]->hTotal = minfo->htotal; + ret[i]->vSyncStart = minfo->vsync_start; + ret[i]->vSyncEnd = minfo->vsync_end; + ret[i]->vTotal = minfo->vtotal; + ret[i]->modeFlags = minfo->mode_flags; + + ret[i]->name = NULL; + ret[i]->nameLength = minfo->name_len; + if (ret[i]->nameLength > 0) + { + ret[i]->name = malloc(ret[i]->nameLength + 1); + if (ret[i]->name) + memcpy(ret[i]->name, nbuf, + ret[i]->nameLength + 1); + } + } + else + { + while (i > 0) + free(ret[--i]); + free(ret); + ret = NULL; + break; + } + i++; + xcb_randr_mode_info_next(&miter); + } + } + free(reply); + } +#endif + return ret; +} + +static void +_ecore_xcb_randr_12_mode_size_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode, + int *w, + int *h) +{ + if (w) *w = 0; + if (h) *h = 0; + +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_mode_info_iterator_t miter; + + miter = xcb_randr_get_screen_resources_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + if (minfo->id == mode) + { + if (w) *w = minfo->width; + if (h) *h = minfo->height; + break; + } + xcb_randr_mode_info_next(&miter); + } + free(reply); + } +#endif +} + +static void +_ecore_xcb_randr_13_mode_size_get(Ecore_X_Window root, + Ecore_X_Randr_Mode mode, + int *w, + int *h) +{ + if (w) *w = 0; + if (h) *h = 0; + +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_mode_info_iterator_t miter; + + miter = xcb_randr_get_screen_resources_current_modes_iterator(reply); + while (miter.rem) + { + xcb_randr_mode_info_t *minfo; + + minfo = miter.data; + if (minfo->id == mode) + { + if (w) *w = minfo->width; + if (h) *h = minfo->height; + break; + } + xcb_randr_mode_info_next(&miter); + } + free(reply); + } +#endif +} + +static Ecore_X_Randr_Output * +_ecore_xcb_randr_12_output_clones_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num) +{ + Ecore_X_Randr_Output *outputs = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_clones; + + outputs = + malloc(sizeof(Ecore_X_Randr_Output) * oreply->num_clones); + if (outputs) + { + memcpy(outputs, xcb_randr_get_output_info_clones(oreply), + sizeof(Ecore_X_Randr_Output) * oreply->num_clones); + } + free(oreply); + } + free(reply); + } +#endif + return outputs; +} + +static Ecore_X_Randr_Output * +_ecore_xcb_randr_13_output_clones_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num) +{ + Ecore_X_Randr_Output *outputs = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_clones; + + outputs = + malloc(sizeof(Ecore_X_Randr_Output) * oreply->num_clones); + if (outputs) + { + memcpy(outputs, xcb_randr_get_output_info_clones(oreply), + sizeof(Ecore_X_Randr_Output) * oreply->num_clones); + } + free(oreply); + } + free(reply); + } +#endif + return outputs; +} + +static Ecore_X_Randr_Crtc * +_ecore_xcb_randr_12_output_possible_crtcs_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num) +{ + Ecore_X_Randr_Crtc *crtcs = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_crtcs; + + crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs); + if (crtcs) + { + memcpy(crtcs, xcb_randr_get_output_info_crtcs(oreply), + sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs); + } + free(oreply); + } + free(reply); + } +#endif + return crtcs; +} + +static Ecore_X_Randr_Crtc * +_ecore_xcb_randr_13_output_possible_crtcs_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *num) +{ + Ecore_X_Randr_Crtc *crtcs = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + if (num) *num = oreply->num_crtcs; + + crtcs = malloc(sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs); + if (crtcs) + { + memcpy(crtcs, xcb_randr_get_output_info_crtcs(oreply), + sizeof(Ecore_X_Randr_Crtc) * oreply->num_crtcs); + } + free(oreply); + } + free(reply); + } +#endif + return crtcs; +} + +static char * +_ecore_xcb_randr_12_output_name_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *len) +{ + char *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + uint8_t *nbuf; + + nbuf = xcb_randr_get_output_info_name(oreply); + nbuf += oreply->name_len; + + if (len) *len = oreply->name_len; + if (oreply->name_len > 0) + { + ret = malloc(oreply->name_len + 1); + if (ret) + memcpy(ret, nbuf, oreply->name_len + 1); + } + + free(oreply); + } + free(reply); + } +#endif + return ret; +} + +static char * +_ecore_xcb_randr_13_output_name_get(Ecore_X_Window root, + Ecore_X_Randr_Output output, + int *len) +{ + char *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + uint8_t *nbuf; + + nbuf = xcb_randr_get_output_info_name(oreply); + nbuf += oreply->name_len; + + if (len) *len = oreply->name_len; + if (oreply->name_len > 0) + { + ret = malloc(oreply->name_len + 1); + if (ret) + memcpy(ret, nbuf, oreply->name_len + 1); + } + + free(oreply); + } + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Connection_Status +_ecore_xcb_randr_12_output_connection_status_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + Ecore_X_Randr_Connection_Status ret = ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + ret = oreply->connection; + free(oreply); + } + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Connection_Status +_ecore_xcb_randr_13_output_connection_status_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + Ecore_X_Randr_Connection_Status ret = ECORE_X_RANDR_CONNECTION_STATUS_UNKNOWN; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + ret = oreply->connection; + free(oreply); + } + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Output * +_ecore_xcb_randr_12_outputs_get(Ecore_X_Window root, + int *num) +{ + Ecore_X_Randr_Output *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + if (num) *num = reply->num_outputs; + ret = malloc(sizeof(Ecore_X_Randr_Output) * reply->num_outputs); + if (ret) + memcpy(ret, xcb_randr_get_screen_resources_outputs(reply), + sizeof(Ecore_X_Randr_Output) * reply->num_outputs); + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Output * +_ecore_xcb_randr_13_outputs_get(Ecore_X_Window root, + int *num) +{ + Ecore_X_Randr_Output *ret = NULL; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + if (num) *num = reply->num_outputs; + ret = malloc(sizeof(Ecore_X_Randr_Output) * reply->num_outputs); + if (ret) + memcpy(ret, xcb_randr_get_screen_resources_current_outputs(reply), + sizeof(Ecore_X_Randr_Output) * reply->num_outputs); + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Crtc +_ecore_xcb_randr_12_output_crtc_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + ret = oreply->crtc; + free(oreply); + } + free(reply); + } +#endif + return ret; +} + +static Ecore_X_Randr_Crtc +_ecore_xcb_randr_13_output_crtc_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ + Ecore_X_Randr_Crtc ret = Ecore_X_Randr_None; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(root); + if (reply) + { + xcb_randr_get_output_info_cookie_t ocookie; + xcb_randr_get_output_info_reply_t *oreply; + + ocookie = + xcb_randr_get_output_info_unchecked(_ecore_xcb_conn, output, + reply->config_timestamp); + oreply = xcb_randr_get_output_info_reply(_ecore_xcb_conn, + ocookie, NULL); + if (oreply) + { + ret = oreply->crtc; + free(oreply); + } + free(reply); + } +#endif + return ret; +} + +static xcb_randr_get_screen_resources_reply_t * +_ecore_xcb_randr_12_get_resources(Ecore_X_Window win) +{ + xcb_randr_get_screen_resources_cookie_t cookie; + xcb_randr_get_screen_resources_reply_t *reply; + + cookie = xcb_randr_get_screen_resources_unchecked(_ecore_xcb_conn, win); + reply = xcb_randr_get_screen_resources_reply(_ecore_xcb_conn, cookie, NULL); + return reply; +} + +static xcb_randr_get_screen_resources_current_reply_t * +_ecore_xcb_randr_13_get_resources(Ecore_X_Window win) +{ + xcb_randr_get_screen_resources_current_cookie_t cookie; + xcb_randr_get_screen_resources_current_reply_t *reply; + + cookie = + xcb_randr_get_screen_resources_current_unchecked(_ecore_xcb_conn, win); + reply = + xcb_randr_get_screen_resources_current_reply(_ecore_xcb_conn, + cookie, NULL); + return reply; +} + +static xcb_timestamp_t +_ecore_xcb_randr_12_get_resource_timestamp(Ecore_X_Window win) +{ + xcb_timestamp_t stamp = 0; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_reply_t *reply; + + reply = _ecore_xcb_randr_12_get_resources(win); + stamp = reply->config_timestamp; + free(reply); +#endif + return stamp; +} + +static xcb_timestamp_t +_ecore_xcb_randr_13_get_resource_timestamp(Ecore_X_Window win) +{ + xcb_timestamp_t stamp = 0; +#ifdef ECORE_XCB_RANDR + xcb_randr_get_screen_resources_current_reply_t *reply; + + reply = _ecore_xcb_randr_13_get_resources(win); + stamp = reply->config_timestamp; + free(reply); +#endif + return stamp; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_region.c b/src/lib/ecore_x/xcb/ecore_xcb_region.c new file mode 100644 index 0000000000..a221d8fc37 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_region.c @@ -0,0 +1,159 @@ +#include "ecore_xcb_private.h" +#include <pixman.h> + +/* + * [ ] XPolygonRegion + * [ ] XShrinkRegion + * [ ] XClipBox + * [ ] XXorRegion + */ + +EAPI Ecore_X_XRegion * +ecore_x_xregion_new() +{ + pixman_region16_t *region; + + region = (pixman_region16_t *)malloc(sizeof(pixman_region16_t)); + if (!region) return NULL; + + pixman_region_init(region); + + return (Ecore_X_XRegion *)region; +} + +EAPI void +ecore_x_xregion_free(Ecore_X_XRegion *region) +{ + if (!region) return; + + pixman_region_fini(region); + free(region); +} + +EAPI Eina_Bool +ecore_x_xregion_set(Ecore_X_XRegion *region, + Ecore_X_GC gc) +{ + xcb_rectangle_t *rects; + pixman_box16_t *boxes; + int num = 0, i = 0; + + CHECK_XCB_CONN; + + if (!region) return EINA_FALSE; + + boxes = pixman_region_rectangles((pixman_region16_t *)region, &num); + if ((!boxes) || (num == 0)) return EINA_FALSE; + + rects = (xcb_rectangle_t *)malloc(sizeof(xcb_rectangle_t) * num); + if (!rects) return EINA_FALSE; + + for (i = 0; i < num; i++) + { + rects[i].x = boxes[i].x1; + rects[i].y = boxes[i].y1; + rects[i].width = boxes[i].x2 - boxes[i].x1 + 1; + rects[i].height = boxes[i].y2 - boxes[i].y1 + 1; + } + + xcb_set_clip_rectangles(_ecore_xcb_conn, XCB_CLIP_ORDERING_YX_BANDED, + gc, 0, 0, num, rects); + +// ecore_x_flush(); + return EINA_TRUE; +} + +EAPI void +ecore_x_xregion_translate(Ecore_X_XRegion *region, + int x, + int y) +{ + if (!region) return; + + pixman_region_translate((pixman_region16_t *)region, x, y); +} + +EAPI Eina_Bool +ecore_x_xregion_intersect(Ecore_X_XRegion *dst, + Ecore_X_XRegion *r1, + Ecore_X_XRegion *r2) +{ + return pixman_region_intersect((pixman_region16_t *)dst, + (pixman_region16_t *)r1, + (pixman_region16_t *)r2); +} + +EAPI Eina_Bool +ecore_x_xregion_union(Ecore_X_XRegion *dst, + Ecore_X_XRegion *r1, + Ecore_X_XRegion *r2) +{ + return pixman_region_union((pixman_region16_t *)dst, + (pixman_region16_t *)r1, + (pixman_region16_t *)r2); +} + +EAPI Eina_Bool +ecore_x_xregion_union_rect(Ecore_X_XRegion *dst, + Ecore_X_XRegion *src, + Ecore_X_Rectangle *rect) +{ + return pixman_region_union_rect((pixman_region16_t *)dst, + (pixman_region16_t *)src, + rect->x, rect->y, rect->width, rect->height); +} + +EAPI Eina_Bool +ecore_x_xregion_subtract(Ecore_X_XRegion *dst, + Ecore_X_XRegion *rm, + Ecore_X_XRegion *rs) +{ + return pixman_region_subtract((pixman_region16_t *)dst, + (pixman_region16_t *)rm, + (pixman_region16_t *)rs); +} + +EAPI Eina_Bool +ecore_x_xregion_is_empty(Ecore_X_XRegion *region) +{ + if (!region) return EINA_TRUE; + + return !pixman_region_not_empty((pixman_region16_t *)region); +} + +EAPI Eina_Bool +ecore_x_xregion_is_equal(Ecore_X_XRegion *r1, + Ecore_X_XRegion *r2) +{ + if ((!r1) || (!r2)) return EINA_FALSE; + + return pixman_region_equal((pixman_region16_t *)r1, + (pixman_region16_t *)r2); +} + +EAPI Eina_Bool +ecore_x_xregion_point_contain(Ecore_X_XRegion *region, + int x, + int y) +{ + if (!region) return EINA_FALSE; + + return pixman_region_contains_point((pixman_region16_t *)region, x, y, NULL); +} + +EAPI Eina_Bool +ecore_x_xregion_rect_contain(Ecore_X_XRegion *region, + Ecore_X_Rectangle *rect) +{ + pixman_box16_t box; + + if ((!region) || (!rect)) return EINA_FALSE; + + box.x1 = rect->x; + box.y1 = rect->y; + box.x2 = rect->x + rect->width - 1; + box.y2 = rect->y + rect->height - 1; + + return pixman_region_contains_rectangle((pixman_region16_t *)region, &box); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_render.c b/src/lib/ecore_x/xcb/ecore_xcb_render.c new file mode 100644 index 0000000000..f36b4d2489 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_render.c @@ -0,0 +1,225 @@ +#include "ecore_xcb_private.h" +#include <ctype.h> // for isupper/tolower +#ifdef ECORE_XCB_RENDER +# include <xcb/render.h> +# include <xcb/xcb_renderutil.h> +#endif + +/* local function prototypes */ +static Eina_Bool _ecore_xcb_render_parse_boolean(char *v); + +/* local variables */ +static Eina_Bool _render_avail = EINA_FALSE; +static Eina_Bool _render_argb = EINA_FALSE; +static Eina_Bool _render_anim = EINA_FALSE; + +void +_ecore_xcb_render_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_RENDER + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_render_id); +#endif +} + +void +_ecore_xcb_render_finalize(void) +{ +#ifdef ECORE_XCB_RENDER + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_RENDER + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_render_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_render_query_version_cookie_t cookie; + xcb_render_query_version_reply_t *reply; + + cookie = + xcb_render_query_version_unchecked(_ecore_xcb_conn, + XCB_RENDER_MAJOR_VERSION, + XCB_RENDER_MINOR_VERSION); + reply = xcb_render_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { +// if ((reply->major_version >= XCB_RENDER_MAJOR_VERSION) && + if (reply->minor_version >= XCB_RENDER_MINOR_VERSION) + { + char *v = NULL; + + _render_avail = EINA_TRUE; + _ecore_xcb_xdefaults_init(); + if ((reply->major_version > 0) || (reply->minor_version >= 5)) + { + _render_argb = EINA_TRUE; + v = getenv("XCURSOR_CORE"); + if (!v) + v = _ecore_xcb_xdefaults_string_get("Xcursor", "core"); + if ((v) && (_ecore_xcb_render_parse_boolean(v))) + _render_argb = EINA_FALSE; + } + if ((_render_argb) && + ((reply->major_version > 0) || (reply->minor_version >= 8))) + { + _render_anim = EINA_TRUE; + v = getenv("XCURSOR_ANIM"); + if (!v) + v = _ecore_xcb_xdefaults_string_get("Xcursor", "anim"); + if ((v) && (_ecore_xcb_render_parse_boolean(v))) + _render_anim = EINA_FALSE; + } + _ecore_xcb_xdefaults_shutdown(); + } + } + free(reply); + } +#endif +} + +Eina_Bool +_ecore_xcb_render_avail_get(void) +{ + return _render_avail; +} + +Eina_Bool +_ecore_xcb_render_argb_get(void) +{ + return _render_argb; +} + +Eina_Bool +_ecore_xcb_render_anim_get(void) +{ + return _render_anim; +} + +Eina_Bool +_ecore_xcb_render_visual_supports_alpha(Ecore_X_Visual visual) +{ + Eina_Bool ret = EINA_FALSE; +#ifdef ECORE_XCB_RENDER + const xcb_render_query_pict_formats_reply_t *reply; + xcb_render_pictvisual_t *vis; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!visual) return EINA_FALSE; + if (!_render_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_RENDER + reply = xcb_render_util_query_formats(_ecore_xcb_conn); + if (!reply) return EINA_FALSE; + + vis = + xcb_render_util_find_visual_format(reply, + ((xcb_visualtype_t *)visual)->visual_id); + if (vis) + { + xcb_render_pictforminfo_t temp; + xcb_render_pictforminfo_t *format; + + temp.id = vis->format; + format = + xcb_render_util_find_format(reply, XCB_PICT_FORMAT_ID, &temp, 0); + + if ((format->type == XCB_RENDER_PICT_TYPE_DIRECT) && + (format->direct.alpha_mask)) + ret = EINA_TRUE; + } + +#endif + + return ret; +} + +uint32_t +_ecore_xcb_render_find_visual_id(int type, + Eina_Bool check_alpha) +{ +#ifdef ECORE_XCB_RENDER + const xcb_render_query_pict_formats_reply_t *reply; + xcb_render_pictvisual_t *visual = NULL; + xcb_render_pictscreen_iterator_t screens; + xcb_render_pictdepth_iterator_t depths; + xcb_render_pictvisual_iterator_t visuals; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_render_avail) return 0; + +#ifdef ECORE_XCB_RENDER + reply = xcb_render_util_query_formats(_ecore_xcb_conn); + if (!reply) return 0; + + for (screens = xcb_render_query_pict_formats_screens_iterator(reply); + screens.rem; xcb_render_pictscreen_next(&screens)) + { + for (depths = xcb_render_pictscreen_depths_iterator(screens.data); + depths.rem; xcb_render_pictdepth_next(&depths)) + { + for (visuals = xcb_render_pictdepth_visuals_iterator(depths.data); + visuals.rem; xcb_render_pictvisual_next(&visuals)) + { + xcb_render_pictforminfo_t temp; + xcb_render_pictforminfo_t *format; + + visual = visuals.data; + temp.id = visual->format; + + format = + xcb_render_util_find_format(reply, XCB_PICT_FORMAT_ID, + &temp, 0); + if (!format) continue; + if (format->type == type) + { + if (check_alpha) + { + if (format->direct.alpha_mask) + return visual->visual; + } + else + return visual->visual; + } + } + } + } +#endif + + return 0; +} + +/* local function prototypes */ +static Eina_Bool +_ecore_xcb_render_parse_boolean(char *v) +{ + char c; + + c = *v; + if (isupper((int)c)) + c = tolower(c); + if ((c == 't') || (c == 'y') || (c == '1')) + return EINA_TRUE; + if ((c == 'f') || (c == 'n') || (c == '0')) + return EINA_FALSE; + if (c == 'o') + { + char d; + + d = v[1]; + if (isupper((int)d)) + d = tolower(d); + if (d == 'n') return EINA_TRUE; + if (d == 'f') return EINA_FALSE; + } + return EINA_FALSE; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_screensaver.c b/src/lib/ecore_x/xcb/ecore_xcb_screensaver.c new file mode 100644 index 0000000000..6106450c88 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_screensaver.c @@ -0,0 +1,370 @@ +#include "ecore_xcb_private.h" +# ifdef ECORE_XCB_SCREENSAVER +# include <xcb/screensaver.h> +# endif + +/* local variables */ +static Eina_Bool _screensaver_avail = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_screensaver = -1; + +void +_ecore_xcb_screensaver_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_SCREENSAVER + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_screensaver_id); +#endif +} + +void +_ecore_xcb_screensaver_finalize(void) +{ +#ifdef ECORE_XCB_SCREENSAVER + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_SCREENSAVER + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_screensaver_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_screensaver_query_version_cookie_t cookie; + xcb_screensaver_query_version_reply_t *reply; + + cookie = + xcb_screensaver_query_version_unchecked(_ecore_xcb_conn, + XCB_SCREENSAVER_MAJOR_VERSION, + XCB_SCREENSAVER_MINOR_VERSION); + reply = + xcb_screensaver_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if ((reply->server_major_version >= XCB_SCREENSAVER_MAJOR_VERSION) && + (reply->server_minor_version >= XCB_SCREENSAVER_MINOR_VERSION)) + _screensaver_avail = EINA_TRUE; + + free(reply); + } + + if (_screensaver_avail) + _ecore_xcb_event_screensaver = ext_reply->first_event; + } +#endif +} + +EAPI int +ecore_x_screensaver_idle_time_get(void) +{ + int ret = 0; +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_query_info_cookie_t cookie; + xcb_screensaver_query_info_reply_t *reply; + Ecore_X_Window root; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return 0; + +#ifdef ECORE_XCB_SCREENSAVER + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + cookie = xcb_screensaver_query_info_unchecked(_ecore_xcb_conn, root); + reply = xcb_screensaver_query_info_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + ret = (reply->ms_until_server / 1000); + free(reply); +#endif + + return ret; +} + +EAPI void +ecore_x_screensaver_set(int timeout, + int interval, + int prefer_blanking, + int allow_exposures) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return; + +#ifdef ECORE_XCB_SCREENSAVER + xcb_set_screen_saver(_ecore_xcb_conn, + timeout, interval, prefer_blanking, allow_exposures); +#endif +} + +EAPI void +ecore_x_screensaver_timeout_set(int timeout) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; + uint16_t pint; + uint8_t pblank, pexpo; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + pint = reply->interval; + pblank = reply->prefer_blanking; + pexpo = reply->allow_exposures; + free(reply); + xcb_set_screen_saver(_ecore_xcb_conn, timeout, pint, pblank, pexpo); +#endif +} + +EAPI int +ecore_x_screensaver_timeout_get(void) +{ + int timeout = 0; +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return 0; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + timeout = reply->timeout; + free(reply); +#endif + + return timeout; +} + +EAPI void +ecore_x_screensaver_blank_set(int blank) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; + uint16_t pint, pto; + uint8_t pexpo; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + pto = reply->timeout; + pint = reply->interval; + pexpo = reply->allow_exposures; + free(reply); + xcb_set_screen_saver(_ecore_xcb_conn, pto, pint, blank, pexpo); +#endif +} + +EAPI int +ecore_x_screensaver_blank_get(void) +{ + int blank = 0; +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return 0; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + blank = reply->prefer_blanking; + free(reply); +#endif + + return blank; +} + +EAPI void +ecore_x_screensaver_expose_set(int expose) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; + uint16_t pint, pto; + uint8_t pblank; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + pto = reply->timeout; + pint = reply->interval; + pblank = reply->prefer_blanking; + free(reply); + xcb_set_screen_saver(_ecore_xcb_conn, pto, pint, pblank, expose); +#endif +} + +EAPI int +ecore_x_screensaver_expose_get(void) +{ + int expose = 0; +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return 0; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + expose = reply->allow_exposures; + free(reply); +#endif + + return expose; +} + +EAPI void +ecore_x_screensaver_interval_set(int interval) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; + uint16_t pto; + uint8_t pblank, pexpose; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + pto = reply->timeout; + pblank = reply->prefer_blanking; + pexpose = reply->allow_exposures; + free(reply); + xcb_set_screen_saver(_ecore_xcb_conn, pto, interval, pblank, pexpose); +#endif +} + +EAPI int +ecore_x_screensaver_interval_get(void) +{ + int interval = 0; +#ifdef ECORE_XCB_SCREENSAVER + xcb_get_screen_saver_cookie_t cookie; + xcb_get_screen_saver_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return 0; + +#ifdef ECORE_XCB_SCREENSAVER + cookie = xcb_get_screen_saver_unchecked(_ecore_xcb_conn); + reply = xcb_get_screen_saver_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + interval = reply->interval; + free(reply); +#endif + + return interval; +} + +EAPI void +ecore_x_screensaver_event_listen_set(Eina_Bool on) +{ +#ifdef ECORE_XCB_SCREENSAVER + Ecore_X_Window root; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_screensaver_avail) return; + +#ifdef ECORE_XCB_SCREENSAVER + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + if (on) + xcb_screensaver_select_input(_ecore_xcb_conn, root, + XCB_SCREENSAVER_EVENT_NOTIFY_MASK | + XCB_SCREENSAVER_EVENT_CYCLE_MASK); + else + xcb_screensaver_select_input(_ecore_xcb_conn, root, 0); +#endif +} + +EAPI Eina_Bool +ecore_x_screensaver_event_available_get(void) +{ + return _screensaver_avail; +} + +EAPI Eina_Bool +ecore_x_screensaver_custom_blanking_enable(void) +{ +#ifdef ECORE_XCB_SCREENSAVER + uint32_t mask_list[9]; + + xcb_screensaver_set_attributes_checked + (_ecore_xcb_conn, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + -9999, -9999, 1, 1, 0, + XCB_WINDOW_CLASS_INPUT_ONLY, + XCB_COPY_FROM_PARENT, XCB_COPY_FROM_PARENT, + 0, mask_list); + return EINA_TRUE; +#else + return EINA_FALSE; +#endif +} + +EAPI Eina_Bool +ecore_x_screensaver_custom_blanking_disable(void) +{ +#ifdef ECORE_XCB_SCREENSAVER + xcb_screensaver_unset_attributes_checked + (_ecore_xcb_conn, + ((xcb_screen_t *)_ecore_xcb_screen)->root); + return EINA_TRUE; +#else + return EINA_FALSE; +#endif +} diff --git a/src/lib/ecore_x/xcb/ecore_xcb_selection.c b/src/lib/ecore_x/xcb/ecore_xcb_selection.c new file mode 100644 index 0000000000..6d5c5aca4c --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_selection.c @@ -0,0 +1,1026 @@ +#include "ecore_xcb_private.h" +//#include "Ecore_X_Atoms.h" + +#define ECORE_XCB_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x)) + +/* local function prototypes */ +static void *_ecore_xcb_selection_parser_text(const char *target EINA_UNUSED, + void *data, + int size, + int format EINA_UNUSED); +static void *_ecore_xcb_selection_parser_files(const char *target, + void *data, + int size, + int format EINA_UNUSED); +static void *_ecore_xcb_selection_parser_targets(const char *target EINA_UNUSED, + void *data, + int size, + int format EINA_UNUSED); + +//static int _ecore_xcb_selection_data_free(void *data); +static int _ecore_xcb_selection_data_text_free(void *data); +static int _ecore_xcb_selection_data_targets_free(void *data); +static int _ecore_xcb_selection_data_files_free(void *data); +static int _ecore_xcb_selection_data_default_free(void *data); +static Eina_Bool _ecore_xcb_selection_set(Ecore_X_Window win, + const void *data, + int size, + Ecore_X_Atom selection); +static void _ecore_xcb_selection_request(Ecore_X_Window win, + Ecore_X_Atom selection, + const char *target); +static Ecore_X_Atom _ecore_xcb_selection_target_atom_get(const char *target); + +/* local variables */ +static Ecore_X_Selection_Intern _selections[4]; +static Ecore_X_Selection_Converter *_converters = NULL; +static Ecore_X_Selection_Parser *_parsers = NULL; + +/* local functions */ +void +_ecore_xcb_selection_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + memset(_selections, 0, sizeof(_selections)); + + /* init converters */ + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT, + ecore_x_selection_converter_text); + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING, + ecore_x_selection_converter_text); + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT, + ecore_x_selection_converter_text); + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING, + ecore_x_selection_converter_text); + + /* init parsers */ + ecore_x_selection_parser_add("text/plain", + _ecore_xcb_selection_parser_text); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING, + _ecore_xcb_selection_parser_text); + ecore_x_selection_parser_add("text/uri-list", + _ecore_xcb_selection_parser_files); + ecore_x_selection_parser_add("_NETSCAPE_URL", + _ecore_xcb_selection_parser_files); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS, + _ecore_xcb_selection_parser_targets); +} + +void +_ecore_xcb_selection_shutdown(void) +{ + Ecore_X_Selection_Converter *cnv; + Ecore_X_Selection_Parser *prs; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + /* free selection converters */ + cnv = _converters; + while (cnv) + { + Ecore_X_Selection_Converter *tmp; + + tmp = cnv->next; + free(cnv); + cnv = tmp; + } + _converters = NULL; + + /* free parsers */ + prs = _parsers; + while (prs) + { + Ecore_X_Selection_Parser *tmp; + + tmp = prs; + prs = prs->next; + free(tmp->target); + free(tmp); + } + _parsers = NULL; +} + +/* public functions */ +EAPI void +ecore_x_selection_converter_atom_add(Ecore_X_Atom target, + Eina_Bool (*func)(char *target, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *type, + int *size_type)) +{ + Ecore_X_Selection_Converter *cnv; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + cnv = _converters; + if (_converters) + { + while (1) + { + if (cnv->target == target) + { + cnv->convert = func; + return; + } + if (cnv->next) + cnv = cnv->next; + else + break; + } + cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter)); + if (!cnv->next) return; + cnv = cnv->next; + } + else + { + _converters = calloc(1, sizeof(Ecore_X_Selection_Converter)); + if (!_converters) return; + cnv = _converters; + } + cnv->target = target; + cnv->convert = func; +} + +EAPI void +ecore_x_selection_converter_add(char *target, + Eina_Bool (*func)(char *target, + void *data, + int size, + void **date_ret, + int *size_ret, + Ecore_X_Atom *atom_ret, + int *ret)) +{ + Ecore_X_Atom atarget; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((!func) || (!target)) return; + atarget = _ecore_xcb_selection_target_atom_get(target); + ecore_x_selection_converter_atom_add(atarget, func); +} + +EAPI void +ecore_x_selection_converter_del(char *target) +{ + Ecore_X_Atom atarget; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!target) return; + atarget = _ecore_xcb_selection_target_atom_get(target); + ecore_x_selection_converter_atom_del(atarget); +} + +EAPI void +ecore_x_selection_converter_atom_del(Ecore_X_Atom target) +{ + Ecore_X_Selection_Converter *conv, *pconv = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + conv = _converters; + while (conv) + { + if (conv->target == target) + { + if (pconv) + pconv->next = conv->next; + else + _converters = conv->next; + free(conv); + return; + } + pconv = conv; + conv = conv->next; + } +} + +EAPI void +ecore_x_selection_parser_add(const char *target, + void *(*func)(const char *target, void *data, int size, int format)) +{ + Ecore_X_Selection_Parser *prs; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!target) return; + prs = _parsers; + if (prs) + { + while (prs->next) + { + if (!strcmp(prs->target, target)) + { + prs->parse = func; + return; + } + prs = prs->next; + } + prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = prs->next; + } + else + { + _parsers = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = _parsers; + } + prs->target = strdup(target); + prs->parse = func; +} + +EAPI void +ecore_x_selection_parser_del(const char *target) +{ + Ecore_X_Selection_Parser *prs, *pprs = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!target) return; + + prs = _parsers; + while (prs) + { + if (!strcmp(prs->target, target)) + { + if (pprs) + pprs->next = prs->next; + else + _parsers = prs->next; + free(prs->target); + free(prs); + return; + } + pprs = prs; + prs = prs->next; + } +} + +/** + * Claim ownership of the PRIMARY selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_primary_set(Ecore_X_Window win, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(win, data, size, + ECORE_X_ATOM_SELECTION_PRIMARY); +} + +/** + * Release ownership of the primary selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_primary_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(XCB_NONE, NULL, 0, + ECORE_X_ATOM_SELECTION_PRIMARY); +} + +EAPI void +ecore_x_selection_primary_request(Ecore_X_Window win, + const char *target) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_PRIMARY, target); +} + +/** + * Claim ownership of the SECONDARY selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_secondary_set(Ecore_X_Window win, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(win, data, size, + ECORE_X_ATOM_SELECTION_SECONDARY); +} + +/** + * Release ownership of the secondary selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_secondary_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(XCB_NONE, NULL, 0, + ECORE_X_ATOM_SELECTION_SECONDARY); +} + +EAPI void +ecore_x_selection_secondary_request(Ecore_X_Window win, + const char *target) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_SECONDARY, target); +} + +/** + * Claim ownership of the XDND selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_xdnd_set(Ecore_X_Window win, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(win, data, size, + ECORE_X_ATOM_SELECTION_XDND); +} + +/** + * Release ownership of the XDND selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_xdnd_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(XCB_NONE, NULL, 0, + ECORE_X_ATOM_SELECTION_XDND); +} + +EAPI void +ecore_x_selection_xdnd_request(Ecore_X_Window win, + const char *target) +{ + Ecore_X_Atom atom; + Ecore_X_DND_Target *_target; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + _target = _ecore_xcb_dnd_target_get(); + atom = _ecore_xcb_selection_target_atom_get(target); + + xcb_convert_selection(_ecore_xcb_conn, win, ECORE_X_ATOM_SELECTION_XDND, + atom, ECORE_X_ATOM_SELECTION_PROP_XDND, _target->time); +} + +/** + * Claim ownership of the CLIPBOARD selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + * + * Get the converted data from a previous CLIPBOARD selection + * request. The buffer must be freed when done with. + */ +EAPI Eina_Bool +ecore_x_selection_clipboard_set(Ecore_X_Window win, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(win, data, size, + ECORE_X_ATOM_SELECTION_CLIPBOARD); +} + +/** + * Release ownership of the clipboard selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_clipboard_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_selection_set(XCB_NONE, NULL, 0, + ECORE_X_ATOM_SELECTION_CLIPBOARD); +} + +EAPI void +ecore_x_selection_clipboard_request(Ecore_X_Window win, + const char *target) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + _ecore_xcb_selection_request(win, ECORE_X_ATOM_SELECTION_CLIPBOARD, target); +} + +EAPI Eina_Bool +ecore_x_selection_convert(Ecore_X_Atom selection, + Ecore_X_Atom target, + void **data_ret, + int *size, + Ecore_X_Atom *targtype, + int *typesize) +{ + Ecore_X_Selection_Intern *sel; + Ecore_X_Selection_Converter *cnv; + void *data; + char *tgt_str; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + sel = _ecore_xcb_selection_get(selection); + tgt_str = _ecore_xcb_selection_target_get(target); + + for (cnv = _converters; cnv; cnv = cnv->next) + { + if (cnv->target == target) + { + int r = 0; + + r = cnv->convert(tgt_str, sel->data, sel->length, &data, size, + targtype, typesize); + free(tgt_str); + if (r) + { + if (data_ret) *data_ret = data; + return r; + } + else + return EINA_FALSE; + } + } + + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_selection_notify_send(Ecore_X_Window requestor, + Ecore_X_Atom selection, + Ecore_X_Atom target, + Ecore_X_Atom property, + Ecore_X_Time tim) +{ + xcb_selection_notify_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + memset(&ev, 0, sizeof(xcb_selection_notify_event_t)); + + ev.response_type = XCB_SELECTION_NOTIFY; + ev.requestor = requestor; + ev.selection = selection; + ev.target = target; + ev.property = property; + ev.time = tim; + + xcb_send_event(_ecore_xcb_conn, 0, requestor, + XCB_EVENT_MASK_NO_EVENT, (const char *)&ev); +// ecore_x_flush(); + + return EINA_TRUE; +} + +EAPI void +ecore_x_selection_owner_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Time tim) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_set_selection_owner(_ecore_xcb_conn, win, atom, tim); +} + +EAPI Ecore_X_Window +ecore_x_selection_owner_get(Ecore_X_Atom atom) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + Ecore_X_Window ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_selection_owner(_ecore_xcb_conn, atom); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + ret = reply->owner; + free(reply); + return ret; +} + +void * +_ecore_xcb_selection_parse(const char *target, + void *data, + int size, + int format) +{ + Ecore_X_Selection_Parser *prs; + Ecore_X_Selection_Data *sel; + + for (prs = _parsers; prs; prs = prs->next) + { + if (!strcmp(prs->target, target)) + { + sel = prs->parse(target, data, size, format); + if (sel) return sel; + } + } + + sel = calloc(1, sizeof(Ecore_X_Selection_Data)); + if (!sel) return NULL; + sel->free = _ecore_xcb_selection_data_default_free; + sel->length = size; + sel->format = format; + sel->data = data; + + return sel; +} + +Ecore_X_Selection_Intern * +_ecore_xcb_selection_get(Ecore_X_Atom selection) +{ + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + return &_selections[0]; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + return &_selections[1]; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + return &_selections[2]; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + return &_selections[3]; + else + return NULL; +} + +/* local functions */ +static Eina_Bool +_ecore_xcb_selection_set(Ecore_X_Window win, + const void *data, + int size, + Ecore_X_Atom selection) +{ + xcb_get_selection_owner_cookie_t cookie; + xcb_get_selection_owner_reply_t *reply; + int in = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_set_selection_owner(_ecore_xcb_conn, win, selection, XCB_CURRENT_TIME); + + cookie = xcb_get_selection_owner(_ecore_xcb_conn, selection); + reply = xcb_get_selection_owner_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + if (reply->owner != win) + { + free(reply); + return EINA_FALSE; + } + free(reply); + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + in = 0; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + in = 1; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + in = 2; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + in = 3; + else + return EINA_FALSE; + + if (data) + { + unsigned char *buff = NULL; + + _selections[in].win = win; + _selections[in].selection = selection; + _selections[in].length = size; + _selections[in].time = _ecore_xcb_events_last_time_get(); + + buff = malloc(size); + if (!buff) return EINA_FALSE; + memcpy(buff, data, size); + _selections[in].data = buff; + } + else if (_selections[in].data) + { + free(_selections[in].data); + memset(&_selections[in], 0, sizeof(Ecore_X_Selection_Data)); + } + + return EINA_TRUE; +} + +static void +_ecore_xcb_selection_request(Ecore_X_Window win, + Ecore_X_Atom selection, + const char *target) +{ + Ecore_X_Atom atarget, prop; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD; + else + return; + + atarget = _ecore_xcb_selection_target_atom_get(target); + + xcb_convert_selection(_ecore_xcb_conn, win, selection, atarget, prop, + XCB_CURRENT_TIME); +} + +EAPI Eina_Bool +ecore_x_selection_converter_text(char *target, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *type EINA_UNUSED, + int *size_type EINA_UNUSED) +{ + Ecore_Xcb_Encoding_Style style; + Ecore_Xcb_Textproperty ret; + char *str; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!data) || (!size)) return EINA_FALSE; + + if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) + style = XcbTextStyle; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) + style = XcbCompoundTextStyle; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) + style = XcbStringStyle; +#ifdef HAVE_ICONV + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) + style = XcbUTF8StringStyle; +#endif + else + return EINA_FALSE; + + str = alloca(size + 1); + memcpy(str, data, size); + str[size] = '\0'; + +#ifdef HAVE_ICONV + if (_ecore_xcb_utf8_textlist_to_textproperty(&str, 1, style, &ret)) + { + int size = 0; + + size = (strlen((char *)ret.value) + 1); + *data_ret = malloc(size); + if (!*data_ret) return EINA_FALSE; + memcpy(*data_ret, ret.value, size); + *size_ret = size; + if (ret.value) free(ret.value); + return EINA_TRUE; + } +#else + if (_ecore_xcb_mb_textlist_to_textproperty(&str, 1, style, &ret)) + { + int size = 0; + + size = (strlen((char *)ret.value) + 1); + *data_ret = malloc(size); + if (!*data_ret) return EINA_FALSE; + memcpy(*data_ret, ret.value, size); + *size_ret = size; + if (ret.value) free(ret.value); + return EINA_TRUE; + } +#endif + else + return EINA_TRUE; +} + +static void * +_ecore_xcb_selection_parser_text(const char *target EINA_UNUSED, + void *data, + int size, + int format EINA_UNUSED) +{ + Ecore_X_Selection_Data_Text *sel; + unsigned char *_data; + void *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(_data = data)) return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text)); + if (!sel) return NULL; + + if (_data && _data[size - 1]) + { + size++; + t = realloc(_data, size); + if (!t) + { + free(sel); + return NULL; + } + _data = t; + _data[size - 1] = 0; + } + sel->text = (char *)_data; + ECORE_XCB_SELECTION_DATA(sel)->length = size; + ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT; + ECORE_XCB_SELECTION_DATA(sel)->data = _data; + ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_text_free; + return sel; +} + +static void * +_ecore_xcb_selection_parser_files(const char *target, + void *data, + int size, + int format EINA_UNUSED) +{ + Ecore_X_Selection_Data_Files *sel; + char *_data, *tmp, *t, **t2; + int i = 0, is = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if ((strcmp(target, "text/uri-list")) && + (strcmp(target, "_NETSCAPE_URL"))) return NULL; + + if (!(_data = data)) return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files)); + if (!sel) return NULL; + + ECORE_XCB_SELECTION_DATA(sel)->free = _ecore_xcb_selection_data_files_free; + + if (_data && _data[size - 1]) + { + size++; + t = realloc(_data, size); + if (!t) + { + free(sel); + return NULL; + } + _data = t; + _data[size - 1] = 0; + } + + tmp = malloc(size); + if (!tmp) + { + free(sel); + return NULL; + } + + while ((is < size) && (_data[is])) + { + if ((i == 0) && (_data[is] == '#')) + { + for (; ((_data[is]) && (_data[is] != '\n')); is++) ; + } + else + { + if ((_data[is] != '\r') && (_data[is] != '\n')) + tmp[i++] = _data[is++]; + else + { + while ((_data[is] == '\r') || (_data[is] == '\n')) + is++; + tmp[i] = 0; + sel->num_files++; + t2 = realloc(sel->files, sel->num_files * sizeof(char *)); + if (t2) + { + sel->files = t2; + sel->files[sel->num_files - 1] = strdup(tmp); + } + tmp[0] = 0; + i = 0; + } + } + } + if (i > 0) + { + tmp[i] = 0; + sel->num_files++; + t2 = realloc(sel->files, sel->num_files * sizeof(char *)); + if (t2) + { + sel->files = t2; + sel->files[sel->num_files - 1] = strdup(tmp); + } + } + if (tmp) free(tmp); + if (_data) free(_data); + + ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES; + ECORE_XCB_SELECTION_DATA(sel)->length = sel->num_files; + + return ECORE_XCB_SELECTION_DATA(sel); +} + +static void * +_ecore_xcb_selection_parser_targets(const char *target EINA_UNUSED, + void *data, + int size, + int format EINA_UNUSED) +{ + Ecore_X_Selection_Data_Targets *sel; + unsigned long *targets; + int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!(targets = (unsigned long *)data)) return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets)); + if (!sel) return NULL; + + sel->num_targets = (size - 2); + sel->targets = malloc((size - 2) * sizeof(char *)); + if (!sel->targets) + { + free(sel); + return NULL; + } + + for (i = 2; i < size; i++) + { + xcb_get_atom_name_cookie_t cookie; + xcb_get_atom_name_reply_t *reply; + char *name = NULL; + int len = 0; + + cookie = xcb_get_atom_name_unchecked(_ecore_xcb_conn, targets[i]); + reply = xcb_get_atom_name_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + len = xcb_get_atom_name_name_length(reply); + name = (char *)malloc(sizeof(char) * (len + 1)); + if (name) + { + memcpy(name, xcb_get_atom_name_name(reply), len); + name[len] = '\0'; + sel->targets[i - 2] = name; + } + free(reply); + } + } + + ECORE_XCB_SELECTION_DATA(sel)->free = + _ecore_xcb_selection_data_targets_free; + ECORE_XCB_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS; + ECORE_XCB_SELECTION_DATA(sel)->length = size; + ECORE_XCB_SELECTION_DATA(sel)->data = data; + + return sel; +} + +/* + static int + _ecore_xcb_selection_data_free(void *data) + { + Ecore_X_Selection_Data *sel; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(sel = data)) return 0; + if (sel->data) free(sel->data); + free(sel); + return 1; + } + */ + +static int +_ecore_xcb_selection_data_text_free(void *data) +{ + Ecore_X_Selection_Data_Text *sel; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(sel = data)) return 0; + if (sel->text) free(sel->text); + free(sel); + return 1; +} + +static int +_ecore_xcb_selection_data_targets_free(void *data) +{ + Ecore_X_Selection_Data_Targets *sel; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(sel = data)) return 0; + if (sel->targets) free(sel->targets); + free(ECORE_XCB_SELECTION_DATA(sel)->data); + free(sel); + return 1; +} + +static int +_ecore_xcb_selection_data_files_free(void *data) +{ + Ecore_X_Selection_Data_Files *sel; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!(sel = data)) return 0; + if (sel->files) + { + int i = 0; + + for (i = 0; i < sel->num_files; i++) + if (sel->files[i]) free(sel->files[i]); + if (sel->files) free(sel->files); + } + free(sel); + return 0; +} + +static int +_ecore_xcb_selection_data_default_free(void *data) +{ + Ecore_X_Selection_Data *sel; + + if (!(sel = data)) return 1; + free(sel->data); + free(sel); + return 1; +} + +static Ecore_X_Atom +_ecore_xcb_selection_target_atom_get(const char *target) +{ + Ecore_X_Atom x_target; + + if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) + x_target = ECORE_X_ATOM_TEXT; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) + x_target = ECORE_X_ATOM_COMPOUND_TEXT; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) + x_target = ECORE_X_ATOM_STRING; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) + x_target = ECORE_X_ATOM_UTF8_STRING; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME)) + x_target = ECORE_X_ATOM_FILE_NAME; + else + x_target = ecore_x_atom_get(target); + + return x_target; +} + +char * +_ecore_xcb_selection_target_get(Ecore_X_Atom target) +{ + if (target == ECORE_X_ATOM_FILE_NAME) + return strdup(ECORE_X_SELECTION_TARGET_FILENAME); + else if (target == ECORE_X_ATOM_STRING) + return strdup(ECORE_X_SELECTION_TARGET_STRING); + else if (target == ECORE_X_ATOM_UTF8_STRING) + return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING); + else if (target == ECORE_X_ATOM_TEXT) + return strdup(ECORE_X_SELECTION_TARGET_TEXT); + else + return ecore_x_atom_name_get(target); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_shape.c b/src/lib/ecore_x/xcb/ecore_xcb_shape.c new file mode 100644 index 0000000000..913f1992b9 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_shape.c @@ -0,0 +1,50 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_SHAPE +# include <xcb/shape.h> +#endif + +/* external variables */ +int _ecore_xcb_event_shape = -1; + +void +_ecore_xcb_shape_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_SHAPE + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_shape_id); +#endif +} + +void +_ecore_xcb_shape_finalize(void) +{ +#ifdef ECORE_XCB_SHAPE + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_SHAPE + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_shape_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_shape_query_version_cookie_t cookie; + xcb_shape_query_version_reply_t *reply; + Eina_Bool _shape_avail; + + _shape_avail = EINA_FALSE; + cookie = xcb_shape_query_version_unchecked(_ecore_xcb_conn); + reply = xcb_shape_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + _shape_avail = EINA_TRUE; + free(reply); + } + + if (_shape_avail) + _ecore_xcb_event_shape = ext_reply->first_event; + } +#endif +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_sync.c b/src/lib/ecore_x/xcb/ecore_xcb_sync.c new file mode 100644 index 0000000000..75f4e4f2be --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_sync.c @@ -0,0 +1,338 @@ +#include "ecore_xcb_private.h" +# ifdef ECORE_XCB_SYNC +# include <xcb/sync.h> +# endif + +/* local variables */ +static Eina_Bool _sync_avail = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_sync = -1; + +void +_ecore_xcb_sync_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_SYNC + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_sync_id); +#endif +} + +void +_ecore_xcb_sync_finalize(void) +{ +#ifdef ECORE_XCB_SYNC + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_SYNC + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_sync_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_sync_initialize_cookie_t cookie; + xcb_sync_initialize_reply_t *reply; + + cookie = + xcb_sync_initialize_unchecked(_ecore_xcb_conn, + XCB_SYNC_MAJOR_VERSION, + XCB_SYNC_MINOR_VERSION); + reply = xcb_sync_initialize_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if (reply->major_version >= 3) _sync_avail = EINA_TRUE; + free(reply); + } + + if (_sync_avail) + _ecore_xcb_event_sync = ext_reply->first_event; + } +#endif +} + +void +_ecore_xcb_sync_magic_send(int val, + Ecore_X_Window win) +{ + xcb_client_message_event_t ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + memset(&ev, 0, sizeof(xcb_client_message_event_t)); + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.window = win; + ev.type = 27777; + ev.data.data32[0] = 0x7162534; + ev.data.data32[1] = (0x10000000 + val); + ev.data.data32[2] = win; + + xcb_send_event(_ecore_xcb_conn, 0, win, XCB_EVENT_MASK_NO_EVENT, + (const char *)&ev); +// ecore_x_flush(); +} + +/* public functions */ +EAPI Ecore_X_Sync_Alarm +ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter) +{ +#ifdef ECORE_XCB_SYNC + uint32_t list[6], mask; + xcb_sync_int64_t init; + Ecore_X_Sync_Alarm alarm; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return 0; + +#ifdef ECORE_XCB_SYNC + init.lo = 0; + init.hi = 0; + xcb_sync_set_counter(_ecore_xcb_conn, counter, init); + + mask = (XCB_SYNC_CA_COUNTER | XCB_SYNC_CA_VALUE_TYPE | + XCB_SYNC_CA_VALUE | XCB_SYNC_CA_TEST_TYPE | + XCB_SYNC_CA_DELTA | XCB_SYNC_CA_EVENTS); + list[0] = counter; + list[1] = XCB_SYNC_VALUETYPE_ABSOLUTE; + list[2] = 1; + list[3] = XCB_SYNC_TESTTYPE_POSITIVE_COMPARISON; + list[4] = 1; + list[5] = 1; + alarm = xcb_generate_id(_ecore_xcb_conn); + + xcb_sync_create_alarm(_ecore_xcb_conn, alarm, mask, list); + ecore_x_sync(); // needed + + return alarm; +#endif + return 0; +} + +EAPI Eina_Bool +ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!alarm)) return EINA_FALSE; + +#ifdef ECORE_XCB_SYNC + xcb_sync_destroy_alarm(_ecore_xcb_conn, alarm); +// ecore_x_flush(); + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, + unsigned int *val) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_query_counter_cookie_t cookie; + xcb_sync_query_counter_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return EINA_FALSE; + +#ifdef ECORE_XCB_SYNC + cookie = xcb_sync_query_counter_unchecked(_ecore_xcb_conn, counter); + reply = xcb_sync_query_counter_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + if (val) *val = (unsigned int)reply->counter_value.lo; + free(reply); + return EINA_TRUE; + } +#endif + return EINA_FALSE; +} + +EAPI void +ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, + int by) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_int64_t v; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return; + +#ifdef ECORE_XCB_SYNC + v.hi = (by < 0) ? ~0 : 0; + v.lo = by; + + xcb_sync_change_counter(_ecore_xcb_conn, counter, v); +// ecore_x_flush(); +#endif +} + +EAPI void +ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, + int val) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_query_counter_cookie_t cookie; + xcb_sync_query_counter_reply_t *reply; + xcb_sync_int64_t v1, v2; + xcb_sync_waitcondition_t cond; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return; + +#ifdef ECORE_XCB_SYNC + cookie = xcb_sync_query_counter_unchecked(_ecore_xcb_conn, counter); + reply = xcb_sync_query_counter_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + v1 = reply->counter_value; + free(reply); + + v1.hi = (val < 0) ? ~0 : 0; + v1.lo = val; + v2.hi = ((val + 1) < 0) ? ~0 : 0; + v2.lo = (val + 1); + + cond.trigger.counter = counter; + cond.trigger.wait_type = XCB_SYNC_VALUETYPE_ABSOLUTE; + cond.trigger.wait_value = v1; + cond.trigger.test_type = XCB_SYNC_TESTTYPE_POSITIVE_COMPARISON; + cond.event_threshold = v2; + + xcb_sync_await(_ecore_xcb_conn, 1, &cond); +// ecore_x_flush(); +#endif +} + +EAPI Ecore_X_Sync_Counter +ecore_x_sync_counter_new(int val) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_counter_t counter; + xcb_sync_int64_t v; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_sync_avail) return 0; + +#ifdef ECORE_XCB_SYNC + v.hi = (val < 0) ? ~0 : 0; + v.lo = val; + + counter = xcb_generate_id(_ecore_xcb_conn); + xcb_sync_create_counter(_ecore_xcb_conn, counter, v); +// ecore_x_flush(); + + return counter; +#endif + + return 0; +} + +EAPI void +ecore_x_sync_counter_free(Ecore_X_Sync_Counter counter) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return; + +#ifdef ECORE_XCB_SYNC + xcb_sync_destroy_counter(_ecore_xcb_conn, counter); +// ecore_x_flush(); +#endif +} + +EAPI void +ecore_x_sync_counter_set(Ecore_X_Sync_Counter counter, + int val) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_int64_t v; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return; + +#ifdef ECORE_XCB_SYNC + v.hi = (val < 0) ? ~0 : 0; + v.lo = val; + + xcb_sync_set_counter(_ecore_xcb_conn, counter, v); +// ecore_x_flush(); +#endif +} + +EAPI void +ecore_x_sync_counter_2_set(Ecore_X_Sync_Counter counter, + int val_hi, + unsigned int val_lo) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_int64_t v; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return; + +#ifdef ECORE_XCB_SYNC + v.hi = val_hi; + v.lo = val_lo; + + xcb_sync_set_counter(_ecore_xcb_conn, counter, v); +// ecore_x_flush(); +#endif +} + +EAPI Eina_Bool +ecore_x_sync_counter_2_query(Ecore_X_Sync_Counter counter, + int *val_hi, + unsigned int *val_lo) +{ +#ifdef ECORE_XCB_SYNC + xcb_sync_query_counter_cookie_t cookie; + xcb_sync_query_counter_reply_t *reply; + xcb_sync_int64_t value; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if ((!_sync_avail) || (!counter)) return EINA_FALSE; + +#ifdef ECORE_XCB_SYNC + cookie = + xcb_sync_query_counter_unchecked(_ecore_xcb_conn, + (xcb_sync_counter_t)counter); + reply = xcb_sync_query_counter_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + value = reply->counter_value; + free(reply); + if (val_hi) *val_hi = (int)value.hi; + if (val_lo) *val_lo = (unsigned int)value.lo; + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_textlist.c b/src/lib/ecore_x/xcb/ecore_xcb_textlist.c new file mode 100644 index 0000000000..2a5c854494 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_textlist.c @@ -0,0 +1,509 @@ +#include "ecore_xcb_private.h" +//#include "Ecore_X_Atoms.h" +#include <langinfo.h> +#ifdef HAVE_ICONV +# include <iconv.h> +#endif +#ifndef CODESET +# define CODESET "INVALID" +#endif + +static int _ecore_xcb_textlist_get_buffer_size(Eina_Bool is_wide, + void *list, + int count); +static int _ecore_xcb_textlist_get_wc_len(wchar_t *wstr); +static void *_ecore_xcb_textlist_alloc_list(Eina_Bool is_wide, + int count, + int nitems); +static void _ecore_xcb_textlist_copy_list(Eina_Bool is_wide, + void *text, + char **list, + int count); +static wchar_t *_ecore_xcb_textlist_copy_wchar(wchar_t *str1, + wchar_t *str2); +static int _ecore_xcb_textlist_len_wchar(wchar_t *str); + +#ifdef HAVE_ICONV +Eina_Bool +_ecore_xcb_utf8_textlist_to_textproperty(char **list, + int count, + Ecore_Xcb_Encoding_Style style, + Ecore_Xcb_Textproperty *ret) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_textlist_to_textproperty("utf8string", list, count, + style, ret); +} + +#endif + +Eina_Bool +_ecore_xcb_mb_textlist_to_textproperty(char **list, + int count, + Ecore_Xcb_Encoding_Style style, + Ecore_Xcb_Textproperty *ret) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_textlist_to_textproperty("multiByte", list, count, + style, ret); +} + +/* NB: This Function May Not Be Correct !!! + * (as I do not know text conversion, locales, etc, etc very well) + * + * Portions were ripped from libX11 XTextListToTextProperty + */ +Eina_Bool +_ecore_xcb_textlist_to_textproperty(const char *type, + char **list, + int count, + Ecore_Xcb_Encoding_Style style, + Ecore_Xcb_Textproperty *ret) +{ + Eina_Bool is_wide = EINA_FALSE; + Ecore_X_Atom encoding; + int len = 0, nitems = 0, i = 0; + size_t from_left = 0, to_left = 0; + int unconv_num = 0, val = 0; + char *buff, *to, *value, *from; + const char *to_type, *from_type; + char **mb = NULL; + wchar_t **wc = NULL; +#ifdef HAVE_ICONV + iconv_t conv; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!strcmp("wideChar", type)) is_wide = EINA_TRUE; + len = _ecore_xcb_textlist_get_buffer_size(is_wide, list, count); + if (!(buff = (char *)malloc(len * sizeof(char)))) return EINA_FALSE; + from_type = nl_langinfo(CODESET); + switch (style) + { + case XcbStringStyle: + case XcbStdICCTextStyle: + encoding = ECORE_X_ATOM_STRING; + to_type = nl_langinfo(CODESET); +// to_type = "string"; + break; + + case XcbUTF8StringStyle: + encoding = ECORE_X_ATOM_UTF8_STRING; + to_type = "UTF-8"; + break; + + case XcbCompoundTextStyle: + encoding = ECORE_X_ATOM_COMPOUND_TEXT; + to_type = nl_langinfo(CODESET); +// to_type = "compoundText"; + break; + + case XcbTextStyle: + encoding = ECORE_X_ATOM_TEXT; + to_type = nl_langinfo(CODESET); +// to_type = "multiByte"; + if (!is_wide) + { + nitems = 0; + mb = (char **)list; + to = buff; + for (i = 0; ((i < count) && (len > 0)); i++) + { + if (*mb) strcpy(to, *mb); + else *to = '\0'; + from_left = (*mb ? strlen(*mb) : 0) + 1; + nitems += from_left; + to += from_left; + mb++; + } + unconv_num = 0; + goto done; + } + break; + + default: + free(buff); + return EINA_FALSE; + break; + } + + if (count < 1) + { + nitems = 0; + goto done; + } + +retry: +#ifdef HAVE_ICONV + conv = iconv_open(to_type, from_type); +#endif + + if (is_wide) + wc = (wchar_t **)list; + else + mb = (char **)list; + + to = buff; + to_left = len; + unconv_num = 0; + for (i = 1; to_left > 0; i++) + { + if (is_wide) + { + from = (char *)*wc; + from_left = _ecore_xcb_textlist_get_wc_len(*wc); + wc++; + } + else + { + from = *mb; + from_left = (*mb ? strlen(*mb) : 0); + mb++; + } + +#ifdef HAVE_ICONV + val = iconv(conv, &from, &from_left, &to, &to_left); +#endif + if (val < 0) continue; + if ((val > 0) && (style == XcbStdICCTextStyle) && + (encoding == ECORE_X_ATOM_STRING)) + { +#ifdef HAVE_ICONV + iconv_close(conv); +#endif + encoding = ECORE_X_ATOM_COMPOUND_TEXT; + goto retry; + } + + unconv_num += val; + *to++ = '\0'; + to_left--; + if (i >= count) break; + } + +#ifdef HAVE_ICONV + iconv_close(conv); +#endif + nitems = (to - buff); + +done: + if (nitems <= 0) nitems = 1; + if (!(value = (char *)malloc(nitems * sizeof(char)))) + { + free(buff); + return EINA_FALSE; + } + if (nitems == 1) + *value = 0; + else + memcpy(value, buff, nitems); + nitems--; + free(buff); + + ret->value = value; + ret->encoding = encoding; + ret->format = 8; + ret->nitems = nitems; + + return EINA_TRUE; +} + +#ifdef HAVE_ICONV +Eina_Bool +_ecore_xcb_utf8_textproperty_to_textlist(const Ecore_Xcb_Textproperty *text_prop, + char ***list_ret, + int *count_ret) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_textproperty_to_textlist(text_prop, "utf8String", + list_ret, count_ret); +} + +#endif + +Eina_Bool +_ecore_xcb_mb_textproperty_to_textlist(const Ecore_Xcb_Textproperty *text_prop, + char ***list_ret, + int *count_ret) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return _ecore_xcb_textproperty_to_textlist(text_prop, "multiByte", + list_ret, count_ret); +} + +Eina_Bool +_ecore_xcb_textproperty_to_textlist(const Ecore_Xcb_Textproperty *text_prop, + const char *type, + char ***list_ret, + int *count_ret) +{ + Eina_Bool is_wide = EINA_FALSE; + Eina_Bool do_strcpy = EINA_FALSE; + const char *from_type; + char *buff, *to, *from; + char *lptr, *sptr; + int nitems = 0, len = 0, num = 0, ret = 0; + size_t from_left = 0, to_left = 0; +#ifdef HAVE_ICONV + iconv_t conv = 0; +#endif + + *list_ret = NULL; + *count_ret = 0; + if (!strcmp("wideChar", type)) is_wide = EINA_TRUE; + + nitems = text_prop->nitems; + if (nitems <= 0) return EINA_TRUE; + + if (text_prop->format != 8) return EINA_FALSE; + + from_type = nl_langinfo(CODESET); + if (text_prop->encoding == ECORE_X_ATOM_UTF8_STRING) + from_type = "UTF-8"; + + if (is_wide) + len = (text_prop->nitems + 1) * sizeof(wchar_t); + else + { + if (!strcmp(type, "utf8String")) + len = text_prop->nitems * 6 + 1; + else + len = text_prop->nitems * MB_CUR_MAX + 1; + } + + buff = (char *)malloc(len * sizeof(char)); + if (!buff) return EINA_FALSE; + + to = buff; + to_left = len; + + if (!strcmp(from_type, type)) + do_strcpy = EINA_TRUE; + else + { +#ifdef HAVE_ICONV + conv = iconv_open(type, from_type); +#endif + if (!conv) + { + free(buff); + return EINA_FALSE; + } + } + + lptr = sptr = text_prop->value; + num = *count_ret = 0; + while (1) + { + if ((nitems == 0) || (*sptr == 0)) + { + from = lptr; + from_left = sptr - lptr; + lptr = sptr; + if (do_strcpy) + { + int l = 0; + + l = MIN(from_left, to_left); + strncpy(to, from, l); + from += len; + to += len; + from_left -= l; + to_left -= l; + ret = 0; + } + else + ret = iconv(conv, &from, &from_left, &to, &to_left); + + if (ret < 0) continue; + num += ret; + (*count_ret)++; + if (nitems == 0) break; + lptr = ++sptr; + if (is_wide) + { + *((wchar_t *)to) = (wchar_t)0; + to += sizeof(wchar_t); + to_left -= sizeof(wchar_t); + } + else + { + *((char *)to) = '\0'; + to++; + to_left--; + } + } + else + sptr++; + + nitems--; + } + +#if HAVE_ICONV + if (!do_strcpy) iconv_close(conv); +#endif + + if (is_wide) + { + *((wchar_t *)to) = (wchar_t)0; + to_left -= sizeof(wchar_t); + } + else + { + *((char *)to) = '\0'; + to_left--; + } + + *list_ret = + _ecore_xcb_textlist_alloc_list(is_wide, *count_ret, (len - to_left)); + if (*list_ret) + _ecore_xcb_textlist_copy_list(is_wide, buff, *list_ret, *count_ret); + + free(buff); + + return EINA_TRUE; +} + +static int +_ecore_xcb_textlist_get_buffer_size(Eina_Bool is_wide, + void *list, + int count) +{ + int len = 0; + char **mb; + wchar_t **wc; + + if (!list) return 0; + if (is_wide) + { + wc = (wchar_t **)list; + for (; count-- > 0; wc++) + if (*wc) len += _ecore_xcb_textlist_get_wc_len(*wc) + 1; + len *= 5; + } + else + { + mb = (char **)list; + for (; count-- > 0; mb++) + if (*mb) len += strlen(*mb) + 1; + len *= 3; + } + len = (len / 2048 + 1) * 2048; + return len; +} + +static int +_ecore_xcb_textlist_get_wc_len(wchar_t *wstr) +{ + wchar_t *ptr; + + ptr = wstr; + while (*ptr) + ptr++; + + return ptr - wstr; +} + +static void * +_ecore_xcb_textlist_alloc_list(Eina_Bool is_wide, + int count, + int nitems) +{ + if (is_wide) + { + wchar_t **list; + + list = (wchar_t **)malloc(count * sizeof(wchar_t *)); + if (!list) return NULL; + *list = (wchar_t *)malloc(nitems * sizeof(wchar_t)); + if (!*list) + { + free(list); + return NULL; + } + return *list; + } + else + { + char **list; + + list = (char **)malloc(count * sizeof(char *)); + if (!list) return NULL; + *list = (char *)malloc(nitems * sizeof(char)); + if (!*list) + { + free(list); + return NULL; + } + return *list; + } +} + +static void +_ecore_xcb_textlist_copy_list(Eina_Bool is_wide, + void *text, + char **list, + int count) +{ + int len = 0; + + if (is_wide) + { + wchar_t *txt, *str, **wlist; + + txt = (wchar_t *)text; + wlist = (wchar_t **)list; + for (str = *wlist; count > 0; count--, wlist++) + { + _ecore_xcb_textlist_copy_wchar(str, txt); + *wlist = str; + len = (_ecore_xcb_textlist_len_wchar(str) + 1); + str += len; + txt += len; + } + } + else + { + char *txt, *str, **slist; + + txt = (char *)text; + slist = (char **)list; + for (str = *slist; count > 0; count--, slist++) + { + strcpy(str, txt); + *slist = str; + len = strlen(str) + 1; + str += len; + txt += len; + } + } +} + +static wchar_t * +_ecore_xcb_textlist_copy_wchar(wchar_t *str1, + wchar_t *str2) +{ + wchar_t *tmp; + + tmp = str1; + while ((*str1++ = *str2++)) + ; + return tmp; +} + +static int +_ecore_xcb_textlist_len_wchar(wchar_t *str) +{ + wchar_t *ptr; + + ptr = str; + while (*ptr) + ptr++; + return ptr - str; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_vsync.c b/src/lib/ecore_x/xcb/ecore_xcb_vsync.c new file mode 100644 index 0000000000..7888796f9a --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_vsync.c @@ -0,0 +1,375 @@ +#include "ecore_xcb_private.h" +# include <fcntl.h> +# include <dlfcn.h> +# include <X11/Xlib-xcb.h> + +#define ECORE_XCB_VSYNC_DRI2 1 +#define DRM_EVENT_CONTEXT_VERSION 2 + +#ifdef ECORE_XCB_VSYNC_DRI2 + +/* relevant header bits of dri/drm inlined here to avoid needing external */ +/* headers to build drm */ +typedef unsigned int drm_magic_t; + +typedef enum +{ + DRM_VBLANK_ABSOLUTE = 0x00000000, + DRM_VBLANK_RELATIVE = 0x00000001, + DRM_VBLANK_EVENT = 0x04000000, + DRM_VBLANK_FLIP = 0x08000000, + DRM_VBLANK_NEXTONMISS = 0x10000000, + DRM_VBLANK_SECONDARY = 0x20000000, + DRM_VBLANK_SIGNAL = 0x40000000 +} drmVBlankSeqType; + +typedef struct _drmVBlankReq +{ + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq; + +typedef struct _drmVBlankReply +{ + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec, tval_usec; +} drmVBlankReply; + +typedef union _drmVBlank +{ + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank; + +typedef struct _drmEventContext +{ + int version; + void (*vblank_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + void (*page_flip_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); +} drmEventContext; + +static int (*sym_drmClose)(int fd) = NULL; +static int (*sym_drmGetMagic)(int fd, + drm_magic_t *magic) = NULL; +static int (*sym_drmWaitVBlank)(int fd, + drmVBlank *vbl) = NULL; +static int (*sym_drmHandleEvent)(int fd, + drmEventContext *evctx) = NULL; + +/* dri */ +static Bool (*sym_DRI2QueryExtension)(Display *display, + int *eventBase, + int *errorBase) = NULL; +static Bool (*sym_DRI2QueryVersion)(Display *display, + int *major, + int *minor) = NULL; +static Bool (*sym_DRI2Connect)(Display *display, + XID window, + char **driverName, + char **deviceName) = NULL; +static Bool (*sym_DRI2Authenticate)(Display *display, + XID window, + drm_magic_t magic) = NULL; + +/* local function prototypes */ +static Eina_Bool _ecore_xcb_dri_link(void); +static Eina_Bool _ecore_xcb_dri_start(void); +static void _ecore_xcb_dri_shutdown(void); + +static Eina_Bool _ecore_xcb_dri_cb(void *data EINA_UNUSED, + Ecore_Fd_Handler *fdh EINA_UNUSED); +static void _ecore_xcb_dri_tick_begin(void *data EINA_UNUSED); +static void _ecore_xcb_dri_tick_end(void *data EINA_UNUSED); +static void _ecore_xcb_dri_tick_schedule(void); +static void _ecore_xcb_dri_vblank_handler(int fd EINA_UNUSED, + unsigned int frame EINA_UNUSED, + unsigned int sec EINA_UNUSED, + unsigned int usec EINA_UNUSED, + void *data EINA_UNUSED); + +/* local variables */ +static Ecore_X_Window _vsync_root = 0; +static int _drm_fd = -1; +static Ecore_Fd_Handler *_drm_fdh = NULL; +static unsigned int _drm_magic = 0; +static Eina_Bool _drm_event_busy = EINA_FALSE; +static void *_drm_lib = NULL; +static void *_dri_lib = NULL; +static drmEventContext _drm_evctx; +#endif + +void +_ecore_xcb_dri_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +void +_ecore_xcb_dri_finalize(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +EAPI Eina_Bool +ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win) +{ +#ifdef ECORE_XCB_VSYNC_DRI2 + Ecore_X_Window root; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_VSYNC_DRI2 + root = ecore_x_window_root_get(win); + if (root != _vsync_root) + { + _vsync_root = root; + if (_vsync_root) + { + if (!_ecore_xcb_dri_link()) + { + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + return EINA_FALSE; + } + _ecore_xcb_dri_shutdown(); + if (!_ecore_xcb_dri_start()) + { + _vsync_root = 0; + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + return EINA_FALSE; + } + ecore_animator_custom_source_tick_begin_callback_set + (_ecore_xcb_dri_tick_begin, NULL); + ecore_animator_custom_source_tick_end_callback_set + (_ecore_xcb_dri_tick_end, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); + } + else + { + if (_drm_fd >= 0) + { + _ecore_xcb_dri_shutdown(); + ecore_animator_custom_source_tick_begin_callback_set + (NULL, NULL); + ecore_animator_custom_source_tick_end_callback_set + (NULL, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + } + } + } + return EINA_TRUE; +#else + return EINA_FALSE; + win = 0; +#endif +} + +/* local functions */ +#ifdef ECORE_XCB_VSYNC_DRI2 +static Eina_Bool +_ecore_xcb_dri_link(void) +{ + const char *_drm_libs[] = + { + "libdrm.so.2", + "libdrm.so.1", + "libdrm.so.0", + "libdrm.so", + NULL, + }; + const char *_dri_libs[] = + { + "libdri2.so.2", + "libdri2.so.1", + "libdri2.so.0", + "libdri2.so", + "libGL.so.4", + "libGL.so.3", + "libGL.so.2", + "libGL.so.1", + "libGL.so.0", + "libGL.so", + NULL, + }; + int i = 0, fail = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +# define SYM(lib, xx) \ + do { \ + sym_## xx = dlsym(lib, #xx); \ + if (!(sym_## xx)) { \ + fprintf(stderr, "%s\n", dlerror()); \ + fail = 1; \ + } \ + } while (0); + + if (_drm_lib) return EINA_TRUE; + + for (i = 0; _drm_libs[i]; i++) + { + _drm_lib = dlopen(_drm_libs[i], (RTLD_LOCAL | RTLD_LAZY)); + if (_drm_lib) + { + fail = 0; + SYM(_drm_lib, drmClose); + SYM(_drm_lib, drmGetMagic); + SYM(_drm_lib, drmWaitVBlank); + SYM(_drm_lib, drmHandleEvent); + if (fail) + { + dlclose(_drm_lib); + _drm_lib = NULL; + } + else + break; + } + } + if (!_drm_lib) return EINA_FALSE; + for (i = 0; _dri_libs[i]; i++) + { + if ((_dri_lib = dlopen(_dri_libs[i], (RTLD_LOCAL | RTLD_LAZY)))) + { + fail = 0; + SYM(_dri_lib, DRI2QueryExtension); + SYM(_dri_lib, DRI2QueryVersion); + SYM(_dri_lib, DRI2Connect); + SYM(_dri_lib, DRI2Authenticate); + if (fail) + { + dlclose(_dri_lib); + _dri_lib = NULL; + } + else + break; + } + } + if (!_dri_lib) + { + dlclose(_drm_lib); + _drm_lib = NULL; + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_xcb_dri_start(void) +{ + Ecore_X_Display *disp; + int _dri2_event = 0, _dri2_error = 0; + int _dri2_major = 0, _dri2_minor = 0; + char *device = NULL, *driver = NULL; + + disp = ecore_x_display_get(); + if (!sym_DRI2QueryExtension(disp, &_dri2_event, &_dri2_error)) + return 0; + if (!sym_DRI2QueryVersion(disp, &_dri2_major, &_dri2_minor)) + return 0; + if (_dri2_major < 2) return 0; + if (!sym_DRI2Connect(disp, _vsync_root, &driver, &device)) + return 0; + + _drm_fd = open(device, O_RDWR); + if (_drm_fd < 0) return 0; + + sym_drmGetMagic(_drm_fd, &_drm_magic); + if (!sym_DRI2Authenticate(disp, _vsync_root, _drm_magic)) + { + close(_drm_fd); + _drm_fd = -1; + return EINA_FALSE; + } + + memset(&_drm_evctx, 0, sizeof(_drm_evctx)); + _drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; + _drm_evctx.vblank_handler = _ecore_xcb_dri_vblank_handler; + _drm_evctx.page_flip_handler = NULL; + + _drm_fdh = ecore_main_fd_handler_add(_drm_fd, ECORE_FD_READ, + _ecore_xcb_dri_cb, NULL, NULL, NULL); + if (!_drm_fdh) + { + close(_drm_fd); + _drm_fd = -1; + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static void +_ecore_xcb_dri_shutdown(void) +{ + if (_drm_fd >= 0) + { + close(_drm_fd); + _drm_fd = -1; + } + if (_drm_fdh) + { + ecore_main_fd_handler_del(_drm_fdh); + _drm_fdh = NULL; + } +} + +static Eina_Bool +_ecore_xcb_dri_cb(void *data EINA_UNUSED, + Ecore_Fd_Handler *fdh EINA_UNUSED) +{ + sym_drmHandleEvent(_drm_fd, &_drm_evctx); + return ECORE_CALLBACK_RENEW; +} + +static void +_ecore_xcb_dri_tick_begin(void *data EINA_UNUSED) +{ + _drm_event_busy = EINA_TRUE; + _ecore_xcb_dri_tick_schedule(); +} + +static void +_ecore_xcb_dri_tick_end(void *data EINA_UNUSED) +{ + _drm_event_busy = EINA_FALSE; +} + +static void +_ecore_xcb_dri_tick_schedule(void) +{ + drmVBlank vbl; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + vbl.request.type = (DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT); + vbl.request.sequence = 1; + vbl.request.signal = 0; + + sym_drmWaitVBlank(_drm_fd, &vbl); +} + +static void +_ecore_xcb_dri_vblank_handler(int fd EINA_UNUSED, + unsigned int frame EINA_UNUSED, + unsigned int sec EINA_UNUSED, + unsigned int usec EINA_UNUSED, + void *data EINA_UNUSED) +{ + ecore_animator_custom_tick(); + if (_drm_event_busy) _ecore_xcb_dri_tick_schedule(); +} + +#endif diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window.c b/src/lib/ecore_x/xcb/ecore_xcb_window.c new file mode 100644 index 0000000000..f8405fe1ec --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window.c @@ -0,0 +1,2238 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_RENDER +# include <xcb/render.h> +#endif +#ifdef ECORE_XCB_SHAPE +# include <xcb/shape.h> +#endif +#ifdef ECORE_XCB_XPRINT +#include <xcb/xprint.h> +#endif + +/* local function prototypes */ +static Ecore_X_Window _ecore_xcb_window_argb_internal_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h, + uint8_t override_redirect, + uint8_t save_under); +static Ecore_X_Window _ecore_xcb_window_at_xy_get(Ecore_X_Window base, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num); +static int _ecore_xcb_window_modifiers_get(unsigned int state); +static xcb_visualtype_t *_ecore_xcb_window_find_visual_by_id(xcb_visualid_t id); +#ifdef ECORE_XCB_XPRINT +static xcb_screen_t *_ecore_xcb_window_screen_of_display(int screen); +#endif + +/* local variables */ +static int ignore_num = 0; +static Ecore_X_Window *ignore_list = NULL; + +/* external variables */ +int _ecore_xcb_button_grabs_num = 0; +int _ecore_xcb_key_grabs_num = 0; +Ecore_X_Window *_ecore_xcb_button_grabs = NULL; +Ecore_X_Window *_ecore_xcb_key_grabs = NULL; +Eina_Bool (*_ecore_xcb_window_grab_replay_func)(void *data, + int type, + void *event); +void *_ecore_xcb_window_grab_replay_data; + +/** + * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions + * + * Functions that can be used to create an X window. + */ + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Ecore_X_Window win; + uint32_t mask, mask_list[9]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (parent == 0) + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + /* NB: Order here is very important due to xcb_cw_t enum */ + mask = (XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK | + XCB_CW_DONT_PROPAGATE); + + mask_list[0] = XCB_BACK_PIXMAP_NONE; + mask_list[1] = 0; + mask_list[2] = XCB_GRAVITY_NORTH_WEST; + mask_list[3] = XCB_GRAVITY_NORTH_WEST; + mask_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + mask_list[5] = 0; + mask_list[6] = 0; + mask_list[7] = (XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE); + mask_list[8] = XCB_EVENT_MASK_NO_EVENT; + + win = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, + win, parent, x, y, w, h, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, mask, mask_list); + + if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) + ecore_x_window_defaults_set(win); + + return win; +} + +/** + * Creates a window with the override redirect attribute set to @c True. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_override_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Ecore_X_Window win; + uint32_t mask, mask_list[9]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (parent == 0) + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + /* NB: Order here is very important due to xcb_cw_t enum */ + mask = (XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK | + XCB_CW_DONT_PROPAGATE); + + mask_list[0] = XCB_BACK_PIXMAP_NONE; + mask_list[1] = 0; + mask_list[2] = XCB_GRAVITY_NORTH_WEST; + mask_list[3] = XCB_GRAVITY_NORTH_WEST; + mask_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + mask_list[5] = 1; + mask_list[6] = 0; + mask_list[7] = (XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE); + mask_list[8] = XCB_EVENT_MASK_NO_EVENT; + + win = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, + win, parent, x, y, w, h, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, mask, mask_list); + + return win; +} + +/** + * Creates a new input window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_input_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Ecore_X_Window win; + uint32_t mask, mask_list[3]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__) + CHECK_XCB_CONN; + + if (parent == 0) + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + /* NB: Order here is very important due to xcb_cw_t enum */ + mask = (XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | + XCB_CW_DONT_PROPAGATE); + + mask_list[0] = 1; + mask_list[1] = (XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE); + mask_list[2] = XCB_EVENT_MASK_NO_EVENT; + + win = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, + win, parent, x, y, w, h, 0, + XCB_WINDOW_CLASS_INPUT_ONLY, + XCB_COPY_FROM_PARENT, mask, mask_list); + + return win; +} + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_manager_argb_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Ecore_X_Window win = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + win = _ecore_xcb_window_argb_internal_new(parent, x, y, w, h, 1, 0); + + return win; +} + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_argb_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Ecore_X_Window win = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + win = _ecore_xcb_window_argb_internal_new(parent, x, y, w, h, 0, 0); + + return win; +} + +/** + * Creates a window with the override redirect attribute set to @c True. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_override_argb_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Ecore_X_Window win = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + win = _ecore_xcb_window_argb_internal_new(parent, x, y, w, h, 1, 0); + + return win; +} + +/** + * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions + * + * Functions to destroy X windows. + */ + +/** + * Deletes the given window. + * @param win The given window. + * @ingroup Ecore_X_Window_Destroy_Group + */ +EAPI void +ecore_x_window_free(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (win) + { + /* xcb_destroy_notify_event_t ev; */ + /* Ecore_X_Window root; */ + + /* if (xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem == 1) */ + /* root = ((xcb_screen_t *)_ecore_xcb_screen)->root; */ + /* else */ + /* { */ + /* xcb_get_geometry_cookie_t cookie; */ + /* xcb_get_geometry_reply_t *reply; */ + + /* cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); */ + /* reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); */ + /* if (!reply) return; */ + /* root = reply->root; */ + /* free(reply); */ + /* } */ + + /* memset(&ev, 0, sizeof(xcb_destroy_notify_event_t)); */ + + /* ev.response_type = XCB_DESTROY_NOTIFY; */ + /* ev.window = win; */ + /* ev.event = root; */ + + /* xcb_send_event(_ecore_xcb_conn, 0, root, */ + /* XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | */ + /* XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, */ + /* (const char *)&ev); */ + + xcb_destroy_window(_ecore_xcb_conn, win); +// ecore_x_flush(); + } +} + +/** + * Sends a delete request to the given window. + * @param win The given window. + * @ingroup Ecore_X_Window_Destroy_Group + */ +EAPI void +ecore_x_window_delete_request_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return; + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + XCB_EVENT_MASK_NO_EVENT, + ECORE_X_ATOM_WM_DELETE_WINDOW, + XCB_CURRENT_TIME, 0, 0, 0); +} + +EAPI void +ecore_x_window_configure(Ecore_X_Window win, + Ecore_X_Window_Configure_Mask mask, + int x, + int y, + int w, + int h, + int border_width, + Ecore_X_Window sibling, + int stack_mode) +{ + uint16_t vmask = 0; + uint32_t vlist[7]; + unsigned int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + + if (mask & XCB_CONFIG_WINDOW_X) + { + vmask |= XCB_CONFIG_WINDOW_X; + vlist[i++] = x; + } + if (mask & XCB_CONFIG_WINDOW_Y) + { + vmask |= XCB_CONFIG_WINDOW_Y; + vlist[i++] = y; + } + if (mask & XCB_CONFIG_WINDOW_WIDTH) + { + vmask |= XCB_CONFIG_WINDOW_WIDTH; + vlist[i++] = w; + } + if (mask & XCB_CONFIG_WINDOW_HEIGHT) + { + vmask |= XCB_CONFIG_WINDOW_HEIGHT; + vlist[i++] = h; + } + if (mask & XCB_CONFIG_WINDOW_BORDER_WIDTH) + { + vmask |= XCB_CONFIG_WINDOW_BORDER_WIDTH; + vlist[i++] = border_width; + } + if (mask & XCB_CONFIG_WINDOW_SIBLING) + { + vmask |= XCB_CONFIG_WINDOW_SIBLING; + vlist[i++] = sibling; + } + if (mask & XCB_CONFIG_WINDOW_STACK_MODE) + { + vmask |= XCB_CONFIG_WINDOW_STACK_MODE; + vlist[i++] = stack_mode; + } + + xcb_configure_window(_ecore_xcb_conn, win, vmask, + (const uint32_t *)&vlist); +// ecore_x_flush(); +} + +/** + * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions + * + * Functions that change or retrieve the geometry of X windows. + */ + +/** + * Moves a window to the position @p x, @p y. + * + * The position is relative to the upper left hand corner of the + * parent window. + * + * @param win The window to move. + * @param x X position. + * @param y Y position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_move(Ecore_X_Window win, + int x, + int y) +{ + uint32_t list[2], mask; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + + mask = (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y); + list[0] = x; + list[1] = y; + + xcb_configure_window(_ecore_xcb_conn, win, mask, + (const uint32_t *)&list); +// ecore_x_flush(); +} + +/** + * Resizes a window. + * @param win The window to resize. + * @param w New width of the window. + * @param h New height of the window. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_resize(Ecore_X_Window win, + int w, + int h) +{ + uint32_t list[2], mask; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + if (w < 1) w = 1; + if (h < 1) h = 1; + + mask = (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT); + list[0] = w; + list[1] = h; + + xcb_configure_window(_ecore_xcb_conn, win, mask, + (const uint32_t *)&list); +// ecore_x_flush(); +} + +/** + * Moves and resizes a window. + * @param win The window to move and resize. + * @param x New X position of the window. + * @param y New Y position of the window. + * @param w New width of the window. + * @param h New height of the window. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_move_resize(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + uint32_t list[4], mask; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + if (w < 1) w = 1; + if (h < 1) h = 1; + + mask = (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT); + list[0] = x; + list[1] = y; + list[2] = w; + list[3] = h; + + xcb_configure_window(_ecore_xcb_conn, win, mask, + (const uint32_t *)&list); +// ecore_x_flush(); +} + +/** + * Retrieves the width of the border of the given window. + * @param win The given window. + * @return Width of the border of @p win. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI int +ecore_x_window_border_width_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!win) return 0; + return ecore_x_drawable_border_width_get(win); +} + +/** + * Sets the width of the border of the given window. + * @param win The given window. + * @param width The new border width. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_border_width_set(Ecore_X_Window win, + int border_width) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) return; + + list = border_width; + + xcb_configure_window(_ecore_xcb_conn, win, + XCB_CONFIG_WINDOW_BORDER_WIDTH, &list); +// ecore_x_flush(); +} + +/** + * @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions + * + * Functions that change the Z order of X windows. + */ + +/** + * Raises the given window. + * @param win The window to raise. + * @ingroup Ecore_X_Window_Z_Order_Group + */ +EAPI void +ecore_x_window_raise(Ecore_X_Window win) +{ + uint32_t list[] = { XCB_STACK_MODE_ABOVE }; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_configure_window(_ecore_xcb_conn, win, + XCB_CONFIG_WINDOW_STACK_MODE, list); +// ecore_x_flush(); +} + +/** + * Lowers the given window. + * @param win The window to lower. + * @ingroup Ecore_X_Window_Z_Order_Group + */ +EAPI void +ecore_x_window_lower(Ecore_X_Window win) +{ + uint32_t list[] = { XCB_STACK_MODE_BELOW }; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_configure_window(_ecore_xcb_conn, win, + XCB_CONFIG_WINDOW_STACK_MODE, list); +// ecore_x_flush(); +} + +/** + * Retrieves the depth of the given window. + * @param win The given window. + * @return Depth of the window. + */ +EAPI int +ecore_x_window_depth_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_drawable_depth_get(win); +} + +/** + * @defgroup Ecore_X_Window_Properties_Group X Window Property Functions + * + * Functions that set window properties. + */ + +/** + * Sets the default properties for the given window. + * + * The default properties set for the window are @c WM_CLIENT_MACHINE and + * @c _NET_WM_PID. + * + * @param win The given window. + * @ingroup Ecore_X_Window_Properties_Group + */ +EAPI void +ecore_x_window_defaults_set(Ecore_X_Window win) +{ + char buff[MAXHOSTNAMELEN], **argv; + int argc; + pid_t pid; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + gethostname(buff, MAXHOSTNAMELEN); + buff[MAXHOSTNAMELEN - 1] = '\0'; + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + ECORE_X_ATOM_WM_CLIENT_MACHINE, ECORE_X_ATOM_STRING, + 8, strlen(buff), buff); + + pid = getpid(); + ecore_x_netwm_pid_set(win, pid); + ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL); + ecore_app_args_get(&argc, &argv); + ecore_x_icccm_command_set(win, argc, argv); +} + +/** + * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions + * + * Functions to access and change the visibility of X windows. + */ + +/** + * Shows a window. + * + * Synonymous to "mapping" a window in X Window System terminology. + * + * @param win The window to show. + * @ingroup Ecore_X_Window_Visibility + */ +EAPI void +ecore_x_window_show(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (win) + xcb_map_window(_ecore_xcb_conn, win); +} + +/** + * Hides a window. + * + * Synonymous to "unmapping" a window in X Window System terminology. + * + * @param win The window to hide. + * @ingroup Ecore_X_Window_Visibility + */ +EAPI void +ecore_x_window_hide(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (win) + { + xcb_unmap_notify_event_t ev; + Ecore_X_Window root; + + if (xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)).rem == 1) + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + else + { + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); + reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + root = reply->root; + free(reply); + } + + xcb_unmap_window(_ecore_xcb_conn, win); + memset(&ev, 0, sizeof(xcb_unmap_notify_event_t)); + + ev.response_type = XCB_UNMAP_NOTIFY; + ev.window = win; + ev.event = root; + ev.from_configure = 0; + + xcb_send_event(_ecore_xcb_conn, 0, root, + (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT), + (const char *)&ev); + +// ecore_x_flush(); + } +} + +/** + * @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions + * + * Functions that give the focus to an X Window. + */ + +/** + * Sets the focus to the window @p win. + * @param win The window to focus. + * @ingroup Ecore_X_Window_Focus_Functions + */ +EAPI void +ecore_x_window_focus(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + xcb_set_input_focus(_ecore_xcb_conn, + XCB_INPUT_FOCUS_PARENT, win, XCB_CURRENT_TIME); +// ecore_x_flush(); +} + +/** + * Sets the focus to the given window at a specific time. + * @param win The window to focus. + * @param t When to set the focus to the window. + * @ingroup Ecore_X_Window_Focus_Functions + */ +EAPI void +ecore_x_window_focus_at_time(Ecore_X_Window win, + Ecore_X_Time time EINA_UNUSED) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + xcb_set_input_focus(_ecore_xcb_conn, + XCB_INPUT_FOCUS_PARENT, win, XCB_CURRENT_TIME); +// ecore_x_flush(); +} + +/** + * @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions + * + * Functions that retrieve or changes the parent window of a window. + */ + +/** + * Moves a window to within another window at a given position. + * @param win The window to reparent. + * @param new_parent The new parent window. + * @param x X position within new parent window. + * @param y Y position within new parent window. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_window_reparent(Ecore_X_Window win, + Ecore_X_Window parent, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (parent == 0) + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + xcb_reparent_window(_ecore_xcb_conn, win, parent, x, y); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_pixmap_set(Ecore_X_Window win, + Ecore_X_Pixmap pixmap) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = pixmap; + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_BACK_PIXMAP, &list); +// ecore_x_flush(); +} + +/** + * Sets the background color of the given window. + * @param win The given window + * @param r red value (0...65536, 16 bits) + * @param g green value (0...65536, 16 bits) + * @param b blue value (0...65536, 16 bits) + */ +EAPI void +ecore_x_window_background_color_set(Ecore_X_Window win, + unsigned short red, + unsigned short green, + unsigned short blue) +{ + xcb_alloc_color_cookie_t cookie; + xcb_alloc_color_reply_t *reply; + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = + xcb_alloc_color_unchecked(_ecore_xcb_conn, + ((xcb_screen_t *)_ecore_xcb_screen)->default_colormap, + red, green, blue); + reply = xcb_alloc_color_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return; + list = reply->pixel; + free(reply); + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_BACK_PIXEL, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_pixel_gravity_set(Ecore_X_Window win, + Ecore_X_Gravity gravity) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = gravity; + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_BIT_GRAVITY, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_gravity_set(Ecore_X_Window win, + Ecore_X_Gravity gravity) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = gravity; + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_WIN_GRAVITY, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_override_set(Ecore_X_Window win, + Eina_Bool override) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = override; + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_OVERRIDE_REDIRECT, &list); +// ecore_x_flush(); +} + +/** + * @brief Show the cursor on a window of type Ecore_X_Window. + * @param win The window for which the cursor will be showed. + * @param show Enables the show of the cursor on the window if equals EINA_TRUE, disables if equals EINA_FALSE. + */ +EAPI void +ecore_x_window_cursor_show(Ecore_X_Window win, + Eina_Bool show) +{ + uint32_t list = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + if (!show) + { + Ecore_X_Cursor cursor; + Ecore_X_Pixmap p, m; + Ecore_X_GC gc; + xcb_point_t point; + + p = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, 1, p, win, 1, 1); + m = xcb_generate_id(_ecore_xcb_conn); + xcb_create_pixmap(_ecore_xcb_conn, 1, m, win, 1, 1); + gc = xcb_generate_id(_ecore_xcb_conn); + xcb_create_gc(_ecore_xcb_conn, gc, win, 0, NULL); + xcb_change_gc(_ecore_xcb_conn, gc, XCB_GC_FOREGROUND, &list); + point.x = 0; + point.y = 0; + xcb_poly_point(_ecore_xcb_conn, XCB_COORD_MODE_ORIGIN, + win, gc, 1, &point); + xcb_free_gc(_ecore_xcb_conn, gc); + + cursor = xcb_generate_id(_ecore_xcb_conn); + xcb_create_cursor(_ecore_xcb_conn, cursor, + p, m, 0, 0, 0, 0, 0, 0, 0, 0); + list = cursor; + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_CURSOR, &list); + + xcb_free_cursor(_ecore_xcb_conn, cursor); + xcb_free_pixmap(_ecore_xcb_conn, m); + xcb_free_pixmap(_ecore_xcb_conn, p); + } + else + { + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_CURSOR, &list); + } +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_cursor_set(Ecore_X_Window win, + Ecore_X_Cursor cursor) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = cursor; + + xcb_change_window_attributes(_ecore_xcb_conn, win, XCB_CW_CURSOR, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_container_manage(Ecore_X_Window win) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY); + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_client_manage(Ecore_X_Window win) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = (XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY); + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); + +#ifdef ECORE_XCB_SHAPE + xcb_shape_select_input(_ecore_xcb_conn, win, EINA_TRUE); +#endif +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_sniff(Ecore_X_Window win) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = (XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_PROPERTY_CHANGE); + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_client_sniff(Ecore_X_Window win) +{ + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + list = (XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE); + + xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); +#ifdef ECORE_XCB_SHAPE + xcb_shape_select_input(_ecore_xcb_conn, win, EINA_TRUE); +#endif +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_area_clear(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_clear_area(_ecore_xcb_conn, 0, win, x, y, w, h); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_area_expose(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_clear_area(_ecore_xcb_conn, 1, win, x, y, w, h); +// ecore_x_flush(); +} + +EAPI void +ecore_x_window_save_set_add(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_INSERT, win); +} + +EAPI void +ecore_x_window_save_set_del(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_change_save_set(_ecore_xcb_conn, XCB_SET_MODE_DELETE, win); +} + +/** + * gets the window that has focus. + * @return The window that has focus. + * @ingroup Ecore_X_Window_Focus_Functions + */ +EAPI Ecore_X_Window +ecore_x_window_focus_get(void) +{ + xcb_get_input_focus_cookie_t cookie; + xcb_get_input_focus_reply_t *reply; + Ecore_X_Window focus = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_input_focus_unchecked(_ecore_xcb_conn); + reply = xcb_get_input_focus_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + focus = reply->focus; + free(reply); + return focus; +} + +EAPI int +ecore_x_window_argb_get(Ecore_X_Window win) +{ + uint8_t ret = 0; +#ifdef ECORE_XCB_RENDER + Ecore_X_Visual visual; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +// if (!win) return ret; + +#ifdef ECORE_XCB_RENDER + /* grab the window's visual */ + visual = _ecore_xcb_window_visual_get(win); + + /* check if this visual supports alpha */ + ret = _ecore_xcb_render_visual_supports_alpha(visual); +#endif + + return ret; +} + +EAPI Eina_Bool +ecore_x_window_manage(Ecore_X_Window win) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + xcb_void_cookie_t change_cookie; + xcb_generic_error_t *err; + uint32_t list; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_window_attributes(_ecore_xcb_conn, win); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + ecore_x_sync(); // needed + + list = (XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_RESIZE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + reply->your_event_mask); + free(reply); + + change_cookie = xcb_change_window_attributes(_ecore_xcb_conn, win, + XCB_CW_EVENT_MASK, &list); + + ecore_x_sync(); // needed + + err = xcb_request_check(_ecore_xcb_conn, change_cookie); + if (err) + { + _ecore_xcb_error_handle(err); + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_window_attributes_get(Ecore_X_Window win, + Ecore_X_Window_Attributes *att_ret) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + xcb_get_geometry_cookie_t gcookie; + xcb_get_geometry_reply_t *greply; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, win); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes)); + + if (reply->map_state != XCB_MAP_STATE_UNMAPPED) + att_ret->visible = EINA_TRUE; + + if (reply->map_state == XCB_MAP_STATE_VIEWABLE) + att_ret->viewable = EINA_TRUE; + + if (reply->override_redirect) + att_ret->override = EINA_TRUE; + + if (reply->_class == XCB_WINDOW_CLASS_INPUT_ONLY) + att_ret->input_only = EINA_TRUE; + + if (reply->save_under) + att_ret->save_under = EINA_TRUE; + + att_ret->event_mask.mine = reply->your_event_mask; + att_ret->event_mask.all = reply->all_event_masks; + att_ret->event_mask.no_propagate = reply->do_not_propagate_mask; + att_ret->window_gravity = reply->win_gravity; + att_ret->pixel_gravity = reply->bit_gravity; + att_ret->colormap = reply->colormap; + att_ret->visual = _ecore_xcb_window_find_visual_by_id(reply->visual); + + free(reply); + + gcookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); + greply = xcb_get_geometry_reply(_ecore_xcb_conn, gcookie, NULL); + if (!greply) return EINA_TRUE; + + /* xcb_translate_coordinates_reply_t *trans; */ + /* xcb_query_tree_cookie_t tcookie; */ + /* xcb_query_tree_reply_t *treply; */ + + /* tcookie = xcb_query_tree(_ecore_xcb_conn, win); */ + /* treply = xcb_query_tree_reply(_ecore_xcb_conn, tcookie, NULL); */ + + /* trans = */ + /* xcb_translate_coordinates_reply(_ecore_xcb_conn, */ + /* xcb_translate_coordinates(_ecore_xcb_conn, */ + /* win, treply->parent, greply->x, greply->y), NULL); */ + /* free(treply); */ + + att_ret->root = greply->root; + att_ret->depth = greply->depth; +// att_ret->x = trans->dst_x; +// att_ret->y = trans->dst_y; + att_ret->x = greply->x; + att_ret->y = greply->y; + att_ret->w = greply->width; + att_ret->h = greply->height; + att_ret->border = greply->border_width; + +// free(trans); + + free(greply); + return EINA_TRUE; +} + +/** + * Retrieves the size of the given window. + * @param win The given window. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_size_get(Ecore_X_Window win, + int *width, + int *height) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + ecore_x_drawable_geometry_get(win, NULL, NULL, width, height); +} + +/** + * Set if a window should be ignored. + * @param win The given window. + * @param ignore if to ignore + */ +EAPI void +ecore_x_window_ignore_set(Ecore_X_Window win, + int ignore) +{ + int i = 0, j = 0, count = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (ignore) + { + if (ignore_list) + { + for (i = 0; i < ignore_num; i++) + if (win == ignore_list[i]) return; + + ignore_list = + realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window)); + if (!ignore_list) return; + + ignore_list[ignore_num++] = win; + } + else + { + ignore_num = 0; + ignore_list = malloc(sizeof(Ecore_X_Window)); + if (!ignore_list) return; + ignore_list[ignore_num++] = win; + } + } + else + { + if (!ignore_list) return; + for (count = ignore_num, i = 0, j = 0; i < count; i++) + { + if (win != ignore_list[i]) + ignore_list[j++] = ignore_list[i]; + else + ignore_num--; + } + if (ignore_num <= 0) + { + free(ignore_list); + ignore_list = NULL; + return; + } + + ignore_list = + realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window)); + } +} + +/** + * Get the ignore list + * @param num number of windows in the list + * @return list of windows to ignore + */ +EAPI Ecore_X_Window * +ecore_x_window_ignore_list(int *num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (num) *num = ignore_num; + return ignore_list; +} + +/** + * Get a list of all the root windows on the server. + * + * @note The returned array will need to be freed after use. + * @param num_ret Pointer to integer to put number of windows returned in. + * @return An array of all the root windows. @c NULL is returned if memory + * could not be allocated for the list, or if @p num_ret is @c NULL. + */ +EAPI Ecore_X_Window * +ecore_x_window_root_list(int *num_ret) +{ + xcb_screen_iterator_t iter; + uint8_t i, num; + Ecore_X_Window *roots = NULL; +#ifdef ECORE_XCB_XPRINT + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!num_ret) return NULL; + if (num_ret) *num_ret = 0; + + /* if (xcb_connection_has_error(_ecore_xcb_conn)) */ + /* { */ + /* DBG("XCB Connection Has Error !!!"); */ + /* return NULL; */ + /* } */ + + num = ecore_x_screen_count_get(); + +#ifdef ECORE_XCB_XPRINT + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_x_print_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_x_print_print_query_screens_cookie_t cookie; + xcb_x_print_print_query_screens_reply_t *reply; + + cookie = xcb_x_print_print_query_screens_unchecked(_ecore_xcb_conn); + reply = + xcb_x_print_print_query_screens_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + xcb_window_t *screens; + int psnum = 0, overlap = 0, j = 0, k = 0; + + psnum = xcb_x_print_print_query_screens_roots_length(reply); + screens = xcb_x_print_print_query_screens_roots(reply); + for (i = 0; i < num; i++) + { + for (j = 0; j < psnum; j++) + { + xcb_screen_t *s; + + if ((s = _ecore_xcb_window_screen_of_display(i))) + { + if (s->root == screens[j]) + overlap++; + } + } + } + if (!(roots = malloc((num - overlap) + * sizeof(Ecore_X_Window)))) return NULL; + for (i = 0; i < num; i++) + { + Eina_Bool is_print = EINA_FALSE; + + for (j = 0; j < psnum; j++) + { + xcb_screen_t *s; + + if ((s = _ecore_xcb_window_screen_of_display(i))) + { + if (s->root == screens[j]) + { + is_print = EINA_TRUE; + break; + } + } + } + if (!is_print) + { + xcb_screen_t *s; + + if ((s = _ecore_xcb_window_screen_of_display(i))) + { + roots[k] = s->root; + k++; + } + } + } + if (num_ret) *num_ret = k; + free(reply); + } + else + { + /* Fallback to default method */ + iter = + xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + if (!(roots = malloc(num * sizeof(Ecore_X_Window)))) return NULL; + if (num_ret) *num_ret = num; + for (i = 0; iter.rem; xcb_screen_next(&iter), i++) + roots[i] = iter.data->root; + } + } + else + { + /* Fallback to default method */ + iter = + xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + if (!(roots = malloc(num * sizeof(Ecore_X_Window)))) return NULL; + if (num_ret) *num_ret = num; + for (i = 0; iter.rem; xcb_screen_next(&iter), i++) + roots[i] = iter.data->root; + } +#else + iter = + xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + if (!(roots = malloc(num * sizeof(Ecore_X_Window)))) return NULL; + if (num_ret) *num_ret = num; + for (i = 0; iter.rem; xcb_screen_next(&iter), i++) + roots[i] = iter.data->root; +#endif + + return roots; +} + +EAPI Ecore_X_Window * +ecore_x_window_children_get(Ecore_X_Window win, + int *num) +{ + xcb_query_tree_cookie_t cookie; + xcb_query_tree_reply_t *reply; + Ecore_X_Window *windows = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num) *num = 0; + cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, win); + reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + + if (num) *num = reply->children_len; + if (reply->children_len > 0) + { + windows = malloc(sizeof(Ecore_X_Window) * reply->children_len); + if (windows) + { + unsigned int i = 0; + xcb_window_t *w; + + w = xcb_query_tree_children(reply); + for (i = 0; i < reply->children_len; i++) + windows[i] = w[i]; + } + } + + free(reply); + return windows; +} + +/** + * Retrieves the root window a given window is on. + * @param win The window to get the root window of + * @return The root window of @p win + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_root_get(Ecore_X_Window win) +{ + xcb_get_geometry_cookie_t gcookie; + xcb_get_geometry_reply_t *greply; + Ecore_X_Window window = 0; + + /* LOGFN(__FILE__, __LINE__, __FUNCTION__); */ + CHECK_XCB_CONN; + + gcookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); + greply = xcb_get_geometry_reply(_ecore_xcb_conn, gcookie, NULL); + if (!greply) return 0; + window = greply->root; + free(greply); + + return window; +} + +EAPI Ecore_X_Window +ecore_x_window_root_first_get(void) +{ + return ((xcb_screen_t *)_ecore_xcb_screen)->root; +} + +/** + * Retrieves the geometry of the given window. + * + * Note that the x & y coordingates are relative to your parent. In + * particular for reparenting window managers - relative to you window border. + * If you want screen coordinates either walk the window tree to the root, + * else for ecore_evas applications see ecore_evas_geometry_get(). Elementary + * applications can use elm_win_screen_position_get(). + * + * @param win The given window. + * @param x Pointer to an integer in which the X position is to be stored. + * @param y Pointer to an integer in which the Y position is to be stored. + * @param w Pointer to an integer in which the width is to be stored. + * @param h Pointer to an integer in which the height is to be stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!win) win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + ecore_x_drawable_geometry_get(win, x, y, w, h); +} + +/** + * Retrieves the top, visible window at the given location. + * @param x The given X position. + * @param y The given Y position. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_get(int x, + int y) +{ + Ecore_X_Window root, win = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ecore_x_grab(); + win = _ecore_xcb_window_at_xy_get(root, 0, 0, x, y, NULL, 0); + ecore_x_ungrab(); + + return win ? win : root; +} + +/** + * Retrieves the top, visible window at the given location, + * but skips the windows in the list. + * @param x The given X position. + * @param y The given Y position. + * @param skip The list of windows to be skipped. + * @param skip_num The number of windows to be skipped. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_with_skip_get(int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Ecore_X_Window root, win = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + ecore_x_grab(); + win = _ecore_xcb_window_at_xy_get(root, 0, 0, x, y, skip, skip_num); + ecore_x_ungrab(); + + return win ? win : root; +} + +EAPI Ecore_X_Window +ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, + int x, + int y) +{ + Ecore_X_Window win = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + ecore_x_grab(); + win = _ecore_xcb_window_at_xy_get(begin, 0, 0, x, y, NULL, 0); + ecore_x_ungrab(); + + return win ? win : begin; +} + +/** + * Retrieves the parent window of the given window. + * @param win The given window. + * @return The parent window of @p win. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI Ecore_X_Window +ecore_x_window_parent_get(Ecore_X_Window win) +{ + xcb_query_tree_cookie_t cookie; + xcb_query_tree_reply_t *reply; + Ecore_X_Window window = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +// if (!win) return 0; + cookie = xcb_query_tree(_ecore_xcb_conn, win); + reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + window = reply->parent; + free(reply); + + return window; +} + +/** + * Finds out whether the given window is currently visible. + * @param win The given window. + * @return 1 if the window is visible, otherwise 0. + * @ingroup Ecore_X_Window_Visibility_Group + */ +EAPI int +ecore_x_window_visible_get(Ecore_X_Window win) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + int ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, win); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + if (reply->map_state == XCB_MAP_STATE_VIEWABLE) + ret = EINA_TRUE; + + free(reply); + return ret; +} + +EAPI void +ecore_x_window_button_grab(Ecore_X_Window win, + int button, + Ecore_X_Event_Mask mask, + int mod, + int any_mod) +{ + int i = 0; + uint16_t m, locks[8], ev; + uint8_t b; + Ecore_X_Window *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + b = button; + if (b == 0) + b = XCB_BUTTON_INDEX_ANY; + + m = _ecore_xcb_window_modifiers_get(mod); + if (any_mod) m = XCB_MOD_MASK_ANY; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + + ev = mask; + for (i = 0; i < 8; i++) + xcb_grab_button(_ecore_xcb_conn, 0, win, ev, + XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, + XCB_NONE, XCB_NONE, b, m | locks[i]); + + _ecore_xcb_button_grabs_num++; + t = realloc(_ecore_xcb_button_grabs, + _ecore_xcb_button_grabs_num * sizeof(Ecore_X_Window)); + if (!t) return; + + _ecore_xcb_button_grabs = t; + _ecore_xcb_button_grabs[_ecore_xcb_button_grabs_num - 1] = win; +} + +EAPI void +ecore_x_window_button_ungrab(Ecore_X_Window win, + int button, + int mod, + int any_mod) +{ + int i = 0; + uint16_t m = 0, locks[8]; + uint8_t b; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + b = button; + if (b == 0) b = XCB_BUTTON_INDEX_ANY; + + m = _ecore_xcb_window_modifiers_get(mod); + if (any_mod) m = XCB_MOD_MASK_ANY; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + + for (i = 0; i < 8; i++) + xcb_ungrab_button(_ecore_xcb_conn, b, win, m | locks[i]); + + _ecore_xcb_sync_magic_send(1, win); +} + +EAPI void +ecore_x_window_key_grab(Ecore_X_Window win, + const char *key, + int mod, + int any_mod) +{ + xcb_keycode_t keycode = XCB_NO_SYMBOL; + uint16_t m = 0, locks[8]; + int i = 0; + Ecore_X_Window *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + keycode = _ecore_xcb_keymap_string_to_keycode(key); + if (keycode == XCB_NO_SYMBOL) return; + + m = _ecore_xcb_window_modifiers_get(mod); + if (any_mod) m = XCB_MOD_MASK_ANY; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + + for (i = 0; i < 8; i++) + xcb_grab_key(_ecore_xcb_conn, 0, win, m | locks[i], + keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); + _ecore_xcb_key_grabs_num++; + t = realloc(_ecore_xcb_key_grabs, + _ecore_xcb_key_grabs_num * sizeof(Ecore_X_Window)); + if (!t) return; + _ecore_xcb_key_grabs = t; + _ecore_xcb_key_grabs[_ecore_xcb_key_grabs_num - 1] = win; +} + +EAPI void +ecore_x_window_key_ungrab(Ecore_X_Window win, + const char *key, + int mod, + int any_mod) +{ + xcb_keycode_t keycode = XCB_NO_SYMBOL; + uint16_t m = 0, locks[8]; + int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + keycode = _ecore_xcb_keymap_string_to_keycode(key); + if (keycode == XCB_NO_SYMBOL) return; + + m = _ecore_xcb_window_modifiers_get(mod); + if (any_mod) m = XCB_MOD_MASK_ANY; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + + for (i = 0; i < 8; i++) + xcb_ungrab_key(_ecore_xcb_conn, keycode, win, m | locks[i]); + + _ecore_xcb_sync_magic_send(2, win); +} + +/* local functions */ +Ecore_X_Window +_ecore_xcb_window_root_of_screen_get(int screen) +{ + xcb_screen_iterator_t iter; + + CHECK_XCB_CONN; + iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (; iter.rem; --screen, xcb_screen_next(&iter)) + if (screen == 0) + { + xcb_screen_t *s; + + if ((s = iter.data)) + return s->root; + } + return 0; +} + +static Ecore_X_Window +_ecore_xcb_window_argb_internal_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h, + uint8_t override_redirect, + uint8_t save_under) +{ + Ecore_X_Window win = 0; +#ifdef ECORE_XCB_RENDER + uint32_t value_list[10]; + uint32_t value_mask; + uint32_t vis; + Ecore_X_Colormap colormap; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_RENDER + if (parent == 0) + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + vis = + _ecore_xcb_render_find_visual_id(XCB_RENDER_PICT_TYPE_DIRECT, EINA_TRUE); + + colormap = xcb_generate_id(_ecore_xcb_conn); + xcb_create_colormap(_ecore_xcb_conn, XCB_COLORMAP_ALLOC_NONE, + colormap, parent, vis); + + value_mask = (XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | + XCB_CW_EVENT_MASK | XCB_CW_DONT_PROPAGATE | XCB_CW_COLORMAP); + + value_list[0] = XCB_BACK_PIXMAP_NONE; + value_list[1] = 0; + value_list[2] = XCB_GRAVITY_NORTH_WEST; + value_list[3] = XCB_GRAVITY_NORTH_WEST; + value_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + value_list[5] = override_redirect; + value_list[6] = save_under; + value_list[7] = (XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE); + value_list[8] = XCB_EVENT_MASK_NO_EVENT; + value_list[9] = colormap; + + win = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, 32, win, parent, x, y, w, h, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, vis, value_mask, + value_list); + + xcb_free_colormap(_ecore_xcb_conn, colormap); + + if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) + ecore_x_window_defaults_set(win); +#endif + + return win; +} + +static Ecore_X_Window +_ecore_xcb_window_at_xy_get(Ecore_X_Window base, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + xcb_query_tree_cookie_t cookie; + xcb_query_tree_reply_t *reply; + Ecore_X_Window *windows = NULL; + int wx, wy, ww, wh, num, i = 0; + Eina_Bool skipit = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!ecore_x_window_visible_get(base)) return 0; + + ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh); + wx += bx; + wy += by; + + if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh)))) + return 0; + + cookie = xcb_query_tree_unchecked(_ecore_xcb_conn, base); + reply = xcb_query_tree_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + + num = reply->children_len; + windows = xcb_query_tree_children(reply); + + for (i = (num - 1); i >= 0; --i) + { + skipit = EINA_FALSE; + + if (skip) + { + int j = 0; + + for (j = 0; j < skip_num; j++) + { + if (windows[i] == skip[j]) + { + skipit = EINA_TRUE; + goto onward; + } + } + } +onward: + if (!skipit) + { + Ecore_X_Window child = 0; + + child = + _ecore_xcb_window_at_xy_get(windows[i], + wx, wy, x, y, skip, skip_num); + if (child) + { + if (reply) free(reply); + return child; + } + } + } + + if (reply) free(reply); + return base; +} + +Ecore_X_Visual +_ecore_xcb_window_visual_get(Ecore_X_Window win) +{ + xcb_get_window_attributes_cookie_t cookie; + xcb_get_window_attributes_reply_t *reply; + Ecore_X_Visual visual = 0; + + CHECK_XCB_CONN; + + cookie = xcb_get_window_attributes(_ecore_xcb_conn, win); + reply = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + visual = _ecore_xcb_window_find_visual_by_id(reply->visual); + free(reply); + + return visual; +} + +void +_ecore_xcb_window_button_grab_remove(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (_ecore_xcb_button_grabs_num > 0) + { + int i = 0, shuffle = 0; + + for (i = 0; i < _ecore_xcb_button_grabs_num; i++) + { + if (shuffle) + _ecore_xcb_button_grabs[i - 1] = _ecore_xcb_button_grabs[i]; + + if ((!shuffle) && (_ecore_xcb_button_grabs[i] == win)) + shuffle = 1; + } + + if (shuffle) + { + Ecore_X_Window *t; + + _ecore_xcb_button_grabs_num--; + if (_ecore_xcb_button_grabs_num <= 0) + { + free(_ecore_xcb_button_grabs); + _ecore_xcb_button_grabs = NULL; + return; + } + + t = realloc(_ecore_xcb_button_grabs, + _ecore_xcb_button_grabs_num * sizeof(Ecore_X_Window)); + if (!t) return; + _ecore_xcb_button_grabs = t; + } + } +} + +void +_ecore_xcb_window_key_grab_remove(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (_ecore_xcb_key_grabs_num > 0) + { + int i = 0, shuffle = 0; + + for (i = 0; i < _ecore_xcb_key_grabs_num; i++) + { + if (shuffle) + _ecore_xcb_key_grabs[i - 1] = _ecore_xcb_key_grabs[i]; + + if ((!shuffle) && (_ecore_xcb_key_grabs[i] == win)) + shuffle = 1; + } + + if (shuffle) + { + Ecore_X_Window *t; + + _ecore_xcb_key_grabs_num--; + if (_ecore_xcb_key_grabs_num <= 0) + { + free(_ecore_xcb_key_grabs); + _ecore_xcb_key_grabs = NULL; + return; + } + + t = realloc(_ecore_xcb_key_grabs, + _ecore_xcb_key_grabs_num * sizeof(Ecore_X_Window)); + if (!t) return; + _ecore_xcb_key_grabs = t; + } + } +} + +void +_ecore_xcb_window_grab_allow_events(Ecore_X_Window event_win, + Ecore_X_Window child_win, + int type, + void *event, + Ecore_X_Time timestamp) +{ + int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + for (i = 0; i < _ecore_xcb_button_grabs_num; i++) + { + if ((_ecore_xcb_button_grabs[i] == event_win) || + (_ecore_xcb_button_grabs[i] == child_win)) + { + Eina_Bool replay = EINA_FALSE; + + if (_ecore_xcb_window_grab_replay_func) + { + replay = + _ecore_xcb_window_grab_replay_func(_ecore_xcb_window_grab_replay_data, + type, event); + } + if (replay) + { + xcb_allow_events(_ecore_xcb_conn, + XCB_ALLOW_REPLAY_POINTER, timestamp); + } + else + { + xcb_allow_events(_ecore_xcb_conn, + XCB_ALLOW_ASYNC_POINTER, timestamp); + } + break; + } + } +} + +static int +_ecore_xcb_window_modifiers_get(unsigned int state) +{ + int xmodifiers = 0; + + if (state & ECORE_EVENT_MODIFIER_SHIFT) + xmodifiers |= ECORE_X_MODIFIER_SHIFT; + if (state & ECORE_EVENT_MODIFIER_CTRL) + xmodifiers |= ECORE_X_MODIFIER_CTRL; + if (state & ECORE_EVENT_MODIFIER_ALT) + xmodifiers |= ECORE_X_MODIFIER_ALT; + if (state & ECORE_EVENT_MODIFIER_WIN) + xmodifiers |= ECORE_X_MODIFIER_WIN; + if (state & ECORE_EVENT_MODIFIER_ALTGR) + xmodifiers |= ECORE_X_MODIFIER_ALTGR; + if (state & ECORE_EVENT_LOCK_SCROLL) + xmodifiers |= ECORE_X_LOCK_SCROLL; + if (state & ECORE_EVENT_LOCK_NUM) + xmodifiers |= ECORE_X_LOCK_NUM; + if (state & ECORE_EVENT_LOCK_CAPS) + xmodifiers |= ECORE_X_LOCK_CAPS; + if (state & ECORE_EVENT_LOCK_SHIFT) + xmodifiers |= ECORE_X_LOCK_SHIFT; + + return xmodifiers; +} + +static xcb_visualtype_t * +_ecore_xcb_window_find_visual_by_id(xcb_visualid_t id) +{ + xcb_depth_iterator_t diter; + xcb_visualtype_iterator_t viter; + + CHECK_XCB_CONN; + diter = xcb_screen_allowed_depths_iterator(_ecore_xcb_screen); + for (; diter.rem; xcb_depth_next(&diter)) + { + viter = xcb_depth_visuals_iterator(diter.data); + for (; viter.rem; xcb_visualtype_next(&viter)) + { + if (viter.data->visual_id == id) + return viter.data; + } + } + return 0; +} + +#ifdef ECORE_XCB_XPRINT +static xcb_screen_t * +_ecore_xcb_window_screen_of_display(int screen) +{ + xcb_screen_iterator_t iter; + + CHECK_XCB_CONN; + iter = xcb_setup_roots_iterator(xcb_get_setup(_ecore_xcb_conn)); + for (; iter.rem; --screen, xcb_screen_next(&iter)) + if (screen == 0) + return iter.data; + + return NULL; +} + +#endif diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window_prop.c b/src/lib/ecore_x/xcb/ecore_xcb_window_prop.c new file mode 100644 index 0000000000..e00fdc1963 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window_prop.c @@ -0,0 +1,720 @@ +#include "ecore_xcb_private.h" +#include <xcb/xcb_icccm.h> + +EAPI int +ecore_x_window_prop_card32_get(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int *val, + unsigned int len) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + int num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, atom, + ECORE_X_ATOM_CARDINAL, 0, 0x7fffffff); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return -1; + + if ((reply->type != ECORE_X_ATOM_CARDINAL) || (reply->format != 32)) + num = -1; + else if (reply->value_len == 0) + num = 0; + else + { + if (reply->value_len < len) + len = reply->value_len; + + if (val) + { + unsigned int i = 0; + unsigned char *v; + + v = xcb_get_property_value(reply); + for (i = 0; i < len; i++) + val[i] = ((uint32_t *)v)[i]; + num = len; + } + } + + if (reply) free(reply); + return num; +} + +EAPI void +ecore_x_window_prop_card32_set(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int *val, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#if SIZEOF_INT == SIZEOF_LONG + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, atom, + ECORE_X_ATOM_CARDINAL, 32, num, (unsigned char *)val); +// ecore_x_flush(); +#else + long *v2; + unsigned int i; + + v2 = malloc(num * sizeof(long)); + if (!v2) return; + for (i = 0; i < num; i++) + v2[i] = val[i]; + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, atom, + ECORE_X_ATOM_CARDINAL, 32, num, (unsigned char *)v2); + free(v2); +// ecore_x_flush(); +#endif +} + +EAPI int +ecore_x_window_prop_card32_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int **list) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + int num = -1; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (list) *list = NULL; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, atom, + XCB_ATOM_CARDINAL, 0, 0x7fffffff); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return -1; + + if ((reply->type != XCB_ATOM_CARDINAL) || (reply->format != 32)) + num = -1; + else if ((reply->value_len == 0) || (!xcb_get_property_value(reply))) + num = 0; + else + { + num = reply->value_len; + if (list) + { + unsigned int *val; + void *data; + int i = 0; + + val = malloc(num * sizeof(unsigned int)); + if (!val) + { + free(reply); + return -1; + } + data = xcb_get_property_value(reply); + for (i = 0; i < num; i++) + val[i] = ((uint32_t *)data)[i]; + *list = val; + } + } + + free(reply); + return num; +} + +EAPI int +ecore_x_window_prop_atom_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom *list, + unsigned int len) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_ATOM, list, len); +} + +EAPI void +ecore_x_window_prop_atom_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom *list, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + /* xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, atom, */ + /* ECORE_X_ATOM_ATOM, 32, num, list); */ + ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_ATOM, list, num); +} + +EAPI void +ecore_x_window_prop_xid_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID *xids, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#if SIZEOF_INT == SIZEOF_LONG + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, atom, + type, 32, num, (unsigned char *)xids); +// ecore_x_flush(); +#else + long *v2; + unsigned int i; + + v2 = malloc(num * sizeof(long)); + if (!v2) return; + for (i = 0; i < num; i++) + v2[i] = xids[i]; + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, atom, + type, 32, num, (unsigned char *)v2); + free(v2); +// ecore_x_flush(); +#endif +} + +EAPI int +ecore_x_window_prop_xid_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID *xids, + unsigned int len) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + int num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + num = len; + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, atom, type, + 0, 0x7fffffff); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return -1; + + if ((reply->type != type) || (reply->format != 32)) + num = -1; + else if (reply->value_len == 0) + num = 0; + else + { + unsigned int i = 0; + unsigned char *v; + + if (reply->value_len < len) + len = reply->value_len; + + v = xcb_get_property_value(reply); + for (i = 0; i < len; i++) + xids[i] = ((uint32_t *)v)[i]; + + num = len; + } + + if (reply) free(reply); + return num; +} + +EAPI void +ecore_x_window_prop_string_set(Ecore_X_Window win, + Ecore_X_Atom type, + const char *str) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, type, + ECORE_X_ATOM_UTF8_STRING, 8, strlen(str), str); +// ecore_x_flush(); +} + +EAPI char * +ecore_x_window_prop_string_get(Ecore_X_Window win, + Ecore_X_Atom type) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + char *str = NULL; + int len = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + cookie = + xcb_get_property_unchecked(_ecore_xcb_conn, 0, + win ? win : ((xcb_screen_t *)_ecore_xcb_screen)->root, + type, XCB_GET_PROPERTY_TYPE_ANY, 0, 1000000L); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + + len = ((reply->value_len * reply->format) / 8); + str = (char *)malloc((len + 1) * sizeof(char)); + memcpy(str, xcb_get_property_value(reply), len); + str[len] = '\0'; + + if (reply->type != ECORE_X_ATOM_UTF8_STRING) + { + Ecore_Xcb_Textproperty prop; + int count = 0; + char **list = NULL; + Eina_Bool ret = EINA_FALSE; + + prop.value = strdup(str); + prop.nitems = len; + prop.encoding = reply->type; + +#ifdef HAVE_ICONV + ret = _ecore_xcb_utf8_textproperty_to_textlist(&prop, &list, &count); +#else + ret = _ecore_xcb_mb_textproperty_to_textlist(&prop, &list, &count); +#endif + if (ret) + { + if (count > 0) + str = strdup(list[0]); + else + str = strdup((char *)prop.value); + + if (list) free(list); + } + else + str = strdup((char *)prop.value); + } + + free(reply); + return str; +} + +EAPI int +ecore_x_window_prop_window_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window *list, + unsigned int len) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_window_prop_xid_get(win, atom, ECORE_X_ATOM_WINDOW, list, len); +} + +EAPI void +ecore_x_window_prop_window_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window *list, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_x_window_prop_xid_set(win, atom, ECORE_X_ATOM_WINDOW, list, num); +} + +EAPI int +ecore_x_window_prop_window_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window **plst) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_WINDOW, plst); +} + +EAPI Ecore_X_Atom +ecore_x_window_prop_any_type(void) +{ + return XCB_ATOM_ANY; +} + +EAPI void +ecore_x_window_prop_property_del(Ecore_X_Window win, + Ecore_X_Atom property) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + xcb_delete_property(_ecore_xcb_conn, win, property); +} + +EAPI void +ecore_x_window_prop_property_set(Ecore_X_Window win, + Ecore_X_Atom property, + Ecore_X_Atom type, + int size, + void *data, + int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (win == 0) + win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + if (size != 32) + { + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + property, type, size, num, (unsigned char *)data); +// ecore_x_flush(); + } + else + { + uint32_t *dat; + int i = 0, *ptr; + + dat = malloc(sizeof(uint32_t) * num); + if (dat) + { + for (ptr = (int *)data, i = 0; i < num; i++) + dat[i] = ptr[i]; + xcb_change_property(_ecore_xcb_conn, XCB_PROP_MODE_REPLACE, win, + property, type, size, num, + (unsigned char *)dat); + free(dat); +// ecore_x_flush(); + } + } +} + +EAPI int +ecore_x_window_prop_property_get(Ecore_X_Window win, + Ecore_X_Atom property, + Ecore_X_Atom type, + int size, + unsigned char **data, + int *num) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + int format = 0; + unsigned int i = 0; + void *value; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num) *num = 0; + + if (data) + *data = NULL; + else + return 0; + + if (win == 0) + win = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + cookie = + xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, + property, type, 0, UINT_MAX); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + if ((reply->format != size) || (reply->value_len == 0)) + { + free(reply); + return 0; + } + + if (!(*data = malloc(reply->value_len * reply->format / 8))) + { + free(reply); + return 0; + } + + value = xcb_get_property_value(reply); + switch (reply->format) + { + case 8: + for (i = 0; i < reply->value_len; i++) + (*data)[i] = ((unsigned char *)value)[i]; + break; + + case 16: + for (i = 0; i < reply->value_len; i++) + ((unsigned short *)*data)[i] = ((unsigned short *)value)[i]; + break; + + case 32: + for (i = 0; i < reply->value_len; i++) + ((unsigned int *)*data)[i] = ((uint32_t *)value)[i]; + break; + } + + if (num) *num = reply->value_len; + format = reply->format; + free(reply); + return format; +} + +EAPI int +ecore_x_window_prop_atom_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom **list) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ecore_x_window_prop_xid_list_get(win, atom, ECORE_X_ATOM_ATOM, list); +} + +EAPI void +ecore_x_window_prop_atom_list_change(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom item, + int op) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_xid_list_change(win, atom, ECORE_X_ATOM_ATOM, item, op); +} + +EAPI int +ecore_x_window_prop_xid_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID **xids) +{ + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; + int num = -1; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (xids) *xids = NULL; + + cookie = xcb_get_property_unchecked(_ecore_xcb_conn, 0, win, atom, type, + 0, 0x7fffffff); + reply = xcb_get_property_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return -1; + + if ((reply->type != type) || (reply->format != 32)) + num = -1; + else if ((reply->value_len == 0) || (!xcb_get_property_value(reply))) + num = 0; + else + { + Ecore_X_Atom *alst; + void *val; + + num = xcb_get_property_value_length(reply); + val = xcb_get_property_value(reply); + alst = malloc(num * sizeof(Ecore_X_ID)); + if (alst) + { + int i = 0; + + for (i = 0; i < num; i++) + alst[i] = ((uint32_t *)val)[i]; + *xids = alst; + } + } + + free(reply); + return num; +} + +EAPI void +ecore_x_window_prop_xid_list_change(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID item, + int op) +{ + Ecore_X_ID *lst; + int i = 0, num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst); + if (num < 0) return; + + for (i = 0; i < num; i++) + { + if (lst[i] == item) break; + } + + if (i < num) + { + if (op == ECORE_X_PROP_LIST_ADD) + goto done; + num--; + for (; i < num; i++) + lst[i] = lst[i + 1]; + } + else + { + if (op == ECORE_X_PROP_LIST_REMOVE) + goto done; + num++; + lst = realloc(lst, num * sizeof(Ecore_X_ID)); + lst[i] = item; + } + ecore_x_window_prop_xid_set(win, atom, type, lst, num); + +done: + if (lst) free(lst); +} + +EAPI Eina_Bool +ecore_x_window_prop_protocol_isset(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol) +{ + Eina_Bool ret = EINA_FALSE; + Ecore_X_Atom proto; +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_t protos; +#else + xcb_icccm_get_wm_protocols_reply_t protos; +#endif + xcb_get_property_cookie_t cookie; + uint8_t reply; + uint32_t count = 0, i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) return EINA_FALSE; + + proto = _ecore_xcb_atoms_wm_protocol[protocol]; +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_protocols_unchecked(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS); + reply = xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protos, NULL); +#else + cookie = xcb_icccm_get_wm_protocols_unchecked(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS); + reply = xcb_icccm_get_wm_protocols_reply(_ecore_xcb_conn, cookie, + &protos, NULL); +#endif + if (!reply) return EINA_FALSE; + + count = protos.atoms_len; + for (i = 0; i < count; i++) + { + if (protos.atoms[i] == proto) + { + ret = EINA_TRUE; + break; + } + } + +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_wipe(&protos); +#else + xcb_icccm_get_wm_protocols_reply_wipe(&protos); +#endif + return ret; +} + +EAPI Ecore_X_WM_Protocol * +ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, + int *num_ret) +{ +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_t protos; +#else + xcb_icccm_get_wm_protocols_reply_t protos; +#endif + xcb_get_property_cookie_t cookie; + uint8_t reply; + uint32_t count = 0, i = 0; + Ecore_X_WM_Protocol *prot_ret = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!num_ret) return NULL; + + *num_ret = 0; + +#ifdef OLD_XCB_VERSION + cookie = xcb_get_wm_protocols_unchecked(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS); + reply = xcb_get_wm_protocols_reply(_ecore_xcb_conn, cookie, &protos, NULL); +#else + cookie = xcb_icccm_get_wm_protocols_unchecked(_ecore_xcb_conn, win, + ECORE_X_ATOM_WM_PROTOCOLS); + reply = xcb_icccm_get_wm_protocols_reply(_ecore_xcb_conn, cookie, + &protos, NULL); +#endif + if (!reply) return NULL; + + count = protos.atoms_len; + if (count <= 0) + { +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_wipe(&protos); +#else + xcb_icccm_get_wm_protocols_reply_wipe(&protos); +#endif + return NULL; + } + + prot_ret = calloc(1, count * sizeof(Ecore_X_WM_Protocol)); + if (!prot_ret) + { +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_wipe(&protos); +#else + xcb_icccm_get_wm_protocols_reply_wipe(&protos); +#endif + return NULL; + } + + for (i = 0; i < count; i++) + { + Ecore_X_WM_Protocol j; + + prot_ret[i] = -1; + for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++) + { + if (_ecore_xcb_atoms_wm_protocol[j] == protos.atoms[i]) + prot_ret[i] = j; + } + } + + if (num_ret) *num_ret = count; + +#ifdef OLD_XCB_VERSION + xcb_get_wm_protocols_reply_wipe(&protos); +#else + xcb_icccm_get_wm_protocols_reply_wipe(&protos); +#endif + return prot_ret; +} + +EAPI Ecore_X_Atom * +ecore_x_window_prop_list(Ecore_X_Window win, + int *num) +{ + xcb_list_properties_cookie_t cookie; + xcb_list_properties_reply_t *reply; + xcb_atom_t *atm; + Ecore_X_Atom *atoms; + int i = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num) *num = 0; + + cookie = xcb_list_properties_unchecked(_ecore_xcb_conn, win); + reply = xcb_list_properties_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + + atoms = (Ecore_X_Atom *)malloc(reply->atoms_len * sizeof(Ecore_X_Atom)); + if (!atoms) + { + free(reply); + return NULL; + } + + atm = xcb_list_properties_atoms(reply); + for (i = 0; i < reply->atoms_len; i++) + atoms[i] = atm[i]; + + if (num) *num = reply->atoms_len; + free(reply); + + return atoms; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c b/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c new file mode 100644 index 0000000000..d46e306c8d --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window_shadow.c @@ -0,0 +1,410 @@ +#include "ecore_xcb_private.h" + +typedef struct _Shadow Shadow; +struct _Shadow +{ + Shadow *parent, **children; + Ecore_X_Window win; + int children_num; + short x, y; + unsigned short w, h; +}; + +static Eina_Bool _inside_rects(Shadow *s, + int x, + int y, + int bx, + int by, + Ecore_X_Rectangle *rects, + int num); + +//static int shadow_count = 0; +static Shadow **shadow_base = NULL; +static int shadow_num = 0; + +/* FIXME: round trips */ +static Shadow * +_ecore_x_window_tree_walk(Ecore_X_Window window) +{ + Shadow *s, **sl; + xcb_get_window_attributes_reply_t *reply_attr; + xcb_get_geometry_reply_t *reply_geom; + xcb_query_tree_reply_t *reply_tree; + xcb_get_window_attributes_cookie_t cookie_attr; + xcb_get_geometry_cookie_t cookie_geom; + xcb_query_tree_cookie_t cookie_tree; + int i, j; + + CHECK_XCB_CONN; + + cookie_attr = xcb_get_window_attributes_unchecked(_ecore_xcb_conn, window); + reply_attr = xcb_get_window_attributes_reply(_ecore_xcb_conn, cookie_attr, NULL); + if (!reply_attr) return NULL; + if (reply_attr->map_state != XCB_MAP_STATE_VIEWABLE) + { + free(reply_attr); + return NULL; + } + + free(reply_attr); + + cookie_geom = xcb_get_geometry_unchecked(_ecore_xcb_conn, window); + reply_geom = xcb_get_geometry_reply(_ecore_xcb_conn, cookie_geom, NULL); + if (!reply_geom) return NULL; + + if (!(s = calloc(1, sizeof(Shadow)))) + { + free(reply_geom); + return NULL; + } + + s->win = window; + s->x = reply_geom->x; + s->y = reply_geom->y; + s->w = reply_geom->width; + s->h = reply_geom->height; + + free(reply_geom); + + cookie_tree = xcb_query_tree_unchecked(_ecore_xcb_conn, window); + reply_tree = xcb_query_tree_reply(_ecore_xcb_conn, cookie_tree, NULL); + if (reply_tree) + { + xcb_window_t *list; + int num; + + num = xcb_query_tree_children_length(reply_tree); + list = xcb_query_tree_children(reply_tree); + + s->children = calloc(1, sizeof(Shadow *) * num); + if (s->children) + { + s->children_num = num; + for (i = 0; i < num; i++) + { + s->children[i] = _ecore_x_window_tree_walk(list[i]); + if (s->children[i]) + s->children[i]->parent = s; + } + /* compress list down */ + j = 0; + for (i = 0; i < num; i++) + { + if (s->children[i]) + { + s->children[j] = s->children[i]; + j++; + } + } + if (j == 0) + { + free(s->children); + s->children = NULL; + s->children_num = 0; + } + else + { + s->children_num = j; + sl = realloc(s->children, sizeof(Shadow *) * j); + if (sl) s->children = sl; + } + } + + free(reply_tree); + } + + return s; +} + +static void +_ecore_x_window_tree_shadow_free1(Shadow *s) +{ + int i = 0; + + if (!s) return; + if (s->children) + { + for (i = 0; i < s->children_num; i++) + { + if (s->children[i]) + _ecore_x_window_tree_shadow_free1(s->children[i]); + } + free(s->children); + } + + free(s); +} + +static void +_ecore_x_window_tree_shadow_free(void) +{ + int i = 0; + + if (!shadow_base) return; + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) continue; + _ecore_x_window_tree_shadow_free1(shadow_base[i]); + } + free(shadow_base); + shadow_base = NULL; + shadow_num = 0; +} + +static void +_ecore_x_window_tree_shadow_populate(void) +{ + Ecore_X_Window *roots = NULL; + int i = 0, num = 0; + + if ((roots = ecore_x_window_root_list(&num))) + { + shadow_base = calloc(1, sizeof(Shadow *) * num); + if (shadow_base) + { + shadow_num = num; + for (i = 0; i < num; i++) + shadow_base[i] = _ecore_x_window_tree_walk(roots[i]); + } + + free(roots); + } +} + +/* + static void + _ecore_x_window_tree_shadow_start(void) + { + shadow_count++; + if (shadow_count > 1) return; + _ecore_x_window_tree_shadow_populate(); + } + + static void + _ecore_x_window_tree_shadow_stop(void) + { + shadow_count--; + if (shadow_count != 0) return; + _ecore_x_window_tree_shadow_free(); + } + */ + +Shadow * +_ecore_x_window_shadow_tree_find_shadow(Shadow *s, + Ecore_X_Window win) +{ + Shadow *ss; + int i = 0; + + if (s->win == win) return s; + + if (s->children) + { + for (i = 0; i < s->children_num; i++) + { + if (!s->children[i]) continue; + + if ((ss = + _ecore_x_window_shadow_tree_find_shadow(s->children[i], win))) + return ss; + } + } + + return NULL; +} + +Shadow * +_ecore_x_window_shadow_tree_find(Ecore_X_Window base) +{ + Shadow *s; + int i = 0; + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) continue; + + if ((s = + _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base))) + return s; + } + return NULL; +} + +static Ecore_X_Window +_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Ecore_X_Window child; + Ecore_X_Rectangle *rects; + int i = 0, j = 0, wx = 0, wy = 0, num = 0; + + wx = s->x + bx; + wy = s->y + by; + if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h)))) + return 0; + + rects = ecore_x_window_shape_rectangles_get(s->win, &num); + if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; + num = 0; + rects = ecore_x_window_shape_input_rectangles_get(s->win, &num); + if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; + + if (s->children) + { + int skipit = 0; + + for (i = s->children_num - 1; i >= 0; --i) + { + if (!s->children[i]) continue; + + skipit = 0; + if (skip) + { + for (j = 0; j < skip_num; j++) + { + if (s->children[i]->win == skip[j]) + { + skipit = 1; + goto onward; + } + } + } +onward: + if (!skipit) + { + if ((child = + _ecore_x_window_shadow_tree_at_xy_get_shadow(s->children[i], wx, wy, x, y, skip, skip_num))) + return child; + } + } + } + + return s->win; +} + +static Ecore_X_Window +_ecore_x_window_shadow_tree_at_xy_get(Ecore_X_Window base, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Shadow *s; + + if (!shadow_base) + { + _ecore_x_window_tree_shadow_populate(); + if (!shadow_base) return 0; + } + + s = _ecore_x_window_shadow_tree_find(base); + if (!s) return 0; + + return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, bx, by, x, y, skip, skip_num); +} + +static Eina_Bool +_inside_rects(Shadow *s, + int x, + int y, + int bx, + int by, + Ecore_X_Rectangle *rects, + int num) +{ + Eina_Bool inside = EINA_FALSE; + int i = 0; + + if (!rects) return EINA_FALSE; + for (i = 0; i < num; i++) + { + if ((x >= s->x + bx + rects[i].x) && + (y >= s->y + by + rects[i].y) && + (x < (int)(s->x + bx + rects[i].x + rects[i].width)) && + (y < (int)(s->y + by + rects[i].y + rects[i].height))) + { + inside = EINA_TRUE; + break; + } + } + free(rects); + return inside; +} + +/** + * Retrieves the top, visible window at the given location, + * but skips the windows in the list. This uses a shadow tree built from the + * window tree that is only updated the first time + * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time + * it is called after a ecore_x_window_shadow_tree_flush() + * @param base The base window to start searching from (normally root). + * @param x The given X position. + * @param y The given Y position. + * @param skip The list of windows to be skipped. + * @param skip_num The number of windows to be skipped. + * @return The window at the desired position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + return _ecore_x_window_shadow_tree_at_xy_get(base, 0, 0, x, y, skip, skip_num); +} + +/** + * Retrieves the parent window a given window has. This uses the shadow window + * tree. + * @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead + * @param win The window to get the parent window of + * @return The parent window of @p win + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_shadow_parent_get(Ecore_X_Window root EINA_UNUSED, + Ecore_X_Window win) +{ + Shadow *s; + int i = 0; + + if (!shadow_base) + { + _ecore_x_window_tree_shadow_populate(); + if (!shadow_base) return 0; + } + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) continue; + + s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win); + if (s) + { + if (!s->parent) return 0; + return s->parent->win; + } + } + return 0; +} + +/** + * Flushes the window shadow tree so nothing is stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_shadow_tree_flush(void) +{ + _ecore_x_window_tree_shadow_free(); +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window_shape.c b/src/lib/ecore_x/xcb/ecore_xcb_window_shape.c new file mode 100644 index 0000000000..6206a51833 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_window_shape.c @@ -0,0 +1,790 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_SHAPE +# include <xcb/shape.h> +#endif + +/** + * @defgroup Ecore_X_Window_Shape X Window Shape Functions + * + * These functions use the shape extension of the X server to change + * shape of given windows. + */ + +/** + * Sets the input shape of the given window to that given by the pixmap @p mask. + * @param win The given window. + * @param mask A 1-bit depth pixmap that provides the new input shape of the + * window. + * @ingroup Ecore_X_Window_Shape + */ +EAPI void +ecore_x_window_shape_input_mask_set(Ecore_X_Window win, + Ecore_X_Pixmap mask) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_mask(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, + win, 0, 0, mask); +// ecore_x_flush(); +#else + return; + win = 0; + mask = 0; +#endif +} + +/** + * Sets the shape of the given window to that given by the pixmap @p mask. + * @param win The given window. + * @param mask A 2-bit depth pixmap that provides the new shape of the + * window. + * @ingroup Ecore_X_Window_Shape + */ +EAPI void +ecore_x_window_shape_mask_set(Ecore_X_Window win, + Ecore_X_Pixmap mask) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_mask(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, + win, 0, 0, mask); +// ecore_x_flush(); +#else + return; + win = 0; + mask = 0; +#endif +} + +EAPI void +ecore_x_window_shape_window_set(Ecore_X_Window win, + Ecore_X_Window shape_win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, + XCB_SHAPE_SK_BOUNDING, win, 0, 0, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; +#endif +} + +EAPI void +ecore_x_window_shape_window_set_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, + XCB_SHAPE_SK_BOUNDING, win, x, y, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; + x = 0; + y = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangles_set(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t *rect = NULL; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!rects) return; + +#ifdef ECORE_XCB_SHAPE + if (num > 0) + { + int i = 0; + + if (!(rect = malloc(sizeof(xcb_rectangle_t) * num))) + return; + + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, num, (xcb_rectangle_t *)rect); + + if (rect) free(rect); +// ecore_x_flush(); +#else + return; + win = 0; + num = 0; + rects = NULL; +#endif +} + +EAPI void +ecore_x_window_shape_window_add(Ecore_X_Window win, + Ecore_X_Window shape_win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, + XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, + win, 0, 0, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; +#endif +} + +EAPI void +ecore_x_window_shape_window_add_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, + XCB_SHAPE_SK_BOUNDING, XCB_SHAPE_SK_BOUNDING, + win, x, y, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; + x = 0; + y = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_add(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_subtract(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SUBTRACT, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_INTERSECT, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangles_add(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t *rect = NULL; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + if (num > 0) + { + int i = 0; + + if (!(rect = malloc(sizeof(xcb_rectangle_t) * num))) + return; + + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, + XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, num, (xcb_rectangle_t *)&rect); + + if (rect) free(rect); +// ecore_x_flush(); +#else + return; + win = 0; + num = 0; + rects = NULL; +#endif +} + +EAPI Ecore_X_Rectangle * +ecore_x_window_shape_rectangles_get(Ecore_X_Window win, + int *num_ret) +{ + Ecore_X_Rectangle *rects = NULL; +#ifdef ECORE_XCB_SHAPE + xcb_shape_get_rectangles_cookie_t cookie; + xcb_shape_get_rectangles_reply_t *reply; + xcb_rectangle_t *r; + unsigned int i = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num_ret) *num_ret = 0; + +#ifdef ECORE_XCB_SHAPE + cookie = + xcb_shape_get_rectangles(_ecore_xcb_conn, win, XCB_SHAPE_SK_BOUNDING); + reply = xcb_shape_get_rectangles_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + if (num_ret) *num_ret = reply->rectangles_len; + + if (reply->rectangles_len < 1) + { + free(reply); + if (num_ret) *num_ret = 0; + return NULL; + } + + rects = malloc(sizeof(Ecore_X_Rectangle) * reply->rectangles_len); + if (!rects) + { + free(reply); + if (num_ret) *num_ret = 0; + return NULL; + } + r = xcb_shape_get_rectangles_rectangles(reply); + for (i = 0; i < reply->rectangles_len; i++) + { + rects[i].x = r[i].x; + rects[i].y = r[i].y; + rects[i].width = r[i].width; + rects[i].height = r[i].height; + } + + free(reply); + + return rects; +#else + return rects; + win = 0; +#endif +} + +EAPI void +ecore_x_window_shape_events_select(Ecore_X_Window win, + Eina_Bool on) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_select_input(_ecore_xcb_conn, win, on); +// ecore_x_flush(); +#else + return; + win = 0; + on = 0; +#endif +} + +EAPI Ecore_X_Rectangle * +ecore_x_window_shape_input_rectangles_get(Ecore_X_Window win, + int *num_ret) +{ + Ecore_X_Rectangle *rects = NULL; +#ifdef ECORE_XCB_SHAPE + xcb_shape_get_rectangles_cookie_t cookie; + xcb_shape_get_rectangles_reply_t *reply; + xcb_rectangle_t *r; + unsigned int i = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num_ret) *num_ret = 0; + +#ifdef ECORE_XCB_SHAPE + cookie = + xcb_shape_get_rectangles(_ecore_xcb_conn, win, XCB_SHAPE_SK_INPUT); + reply = xcb_shape_get_rectangles_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + if (num_ret) *num_ret = reply->rectangles_len; + + if (reply->rectangles_len < 1) + { + free(reply); + if (num_ret) *num_ret = 0; + return NULL; + } + + rects = malloc(sizeof(Ecore_X_Rectangle) * reply->rectangles_len); + if (!rects) + { + free(reply); + if (num_ret) *num_ret = 0; + return NULL; + } + r = xcb_shape_get_rectangles_rectangles(reply); + for (i = 0; i < reply->rectangles_len; i++) + { + rects[i].x = r[i].x; + rects[i].y = r[i].y; + rects[i].width = r[i].width; + rects[i].height = r[i].height; + } + + free(reply); + + return rects; +#else + xcb_get_geometry_cookie_t cookie; + xcb_get_geometry_reply_t *reply; + + if (!(rects = malloc(sizeof(Ecore_X_Rectangle)))) + return NULL; + + /* get geometry */ + cookie = xcb_get_geometry_unchecked(_ecore_xcb_conn, win); + reply = xcb_get_geometry_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + rects[0].x = reply->x; + rects[0].y = reply->y; + rects[0].width = reply->width; + rects[0].height = reply->height; + free(reply); + } + if (num_ret) *num_ret = 1; + return rects; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangles_set(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t *rect = NULL; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!rects) return; + +#ifdef ECORE_XCB_SHAPE + if (num > 0) + { + int i = 0; + + if (!(rect = malloc(sizeof(xcb_rectangle_t) * num))) + return; + + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, num, (xcb_rectangle_t *)rect); + + if (rect) free(rect); +// ecore_x_flush(); +#else + return; + win = 0; + num = 0; + rects = NULL; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangle_subtract(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SUBTRACT, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangle_add(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangle_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_SET, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_window_set_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, + XCB_SHAPE_SK_INPUT, win, x, y, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; + x = 0; + y = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_window_add_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, XCB_SHAPE_SK_INPUT, + XCB_SHAPE_SK_INPUT, win, x, y, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; + x = 0; + y = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_window_set(Ecore_X_Window win, + Ecore_X_Window shape_win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + xcb_shape_combine(_ecore_xcb_conn, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, + XCB_SHAPE_SK_INPUT, win, 0, 0, shape_win); +// ecore_x_flush(); +#else + return; + win = 0; + shape_win = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangle_clip(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t rect; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_INTERSECT, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, 1, &rect); +// ecore_x_flush(); +#else + return; + win = 0; + x = 0; + y = 0; + w = 0; + h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangles_add(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_SHAPE + xcb_rectangle_t *rect = NULL; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + +#ifdef ECORE_XCB_SHAPE + if (num > 0) + { + int i = 0; + + if (!(rect = malloc(sizeof(xcb_rectangle_t) * num))) + return; + + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + + xcb_shape_rectangles(_ecore_xcb_conn, XCB_SHAPE_SO_UNION, + XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_UNSORTED, + win, 0, 0, num, (xcb_rectangle_t *)&rect); + + if (rect) free(rect); +// ecore_x_flush(); +#else + return; + win = 0; + num = 0; + rects = NULL; +#endif +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_xdefaults.c b/src/lib/ecore_x/xcb/ecore_xcb_xdefaults.c new file mode 100644 index 0000000000..e0e56102e2 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_xdefaults.c @@ -0,0 +1,116 @@ +#include "ecore_xcb_private.h" +#include <fnmatch.h> + +/* local function prototypes */ +static Eina_Bool _ecore_xcb_xdefaults_glob_match(const char *str, + const char *glob); + +/* local variables */ +static Eina_File *_ecore_xcb_xdefaults_file = NULL; +static char *_ecore_xcb_xdefaults_data = NULL; + +void +_ecore_xcb_xdefaults_init(void) +{ + char buff[PATH_MAX]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + snprintf(buff, sizeof(buff), "%s/.Xdefaults", getenv("HOME")); + if ((_ecore_xcb_xdefaults_file = eina_file_open(buff, EINA_FALSE))) + { + eina_mmap_safety_enabled_set(EINA_TRUE); + + _ecore_xcb_xdefaults_data = + eina_file_map_all(_ecore_xcb_xdefaults_file, EINA_FILE_SEQUENTIAL); + } +} + +void +_ecore_xcb_xdefaults_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!_ecore_xcb_xdefaults_file) return; + if (_ecore_xcb_xdefaults_data) + eina_file_map_free(_ecore_xcb_xdefaults_file, _ecore_xcb_xdefaults_data); + if (_ecore_xcb_xdefaults_file) eina_file_close(_ecore_xcb_xdefaults_file); +} + +char * +_ecore_xcb_xdefaults_string_get(const char *prog, + const char *param) +{ + char buff[1024], ret[1024]; + char *str = NULL; + char **ea = NULL; + unsigned int count = 0, i = 0; + + if ((!_ecore_xcb_xdefaults_data) || (!_ecore_xcb_xdefaults_file)) + return NULL; + + snprintf(buff, sizeof(buff), "*%s*.*%s*", prog, param); + + str = _ecore_xcb_xdefaults_data; + ea = eina_str_split_full(str, "\n", -1, &count); + for (i = 0; i < count; i++) + { + if (_ecore_xcb_xdefaults_glob_match(ea[i], buff)) + sscanf(ea[i], "%*[^:]:%*[ ]%s", ret); + } + if ((ea) && (ea[0])) + { + free(ea[0]); + free(ea); + } + + return strdup(ret); +} + +int +_ecore_xcb_xdefaults_int_get(const char *prog, + const char *param) +{ + char buff[1024]; + char *str = NULL; + char **ea = NULL; + unsigned int count = 0, i = 0; + int ret = -1; + + if ((!_ecore_xcb_xdefaults_data) || (!_ecore_xcb_xdefaults_file)) + return 0; + + snprintf(buff, sizeof(buff), "*%s*.*%s*", prog, param); + + str = _ecore_xcb_xdefaults_data; + ea = eina_str_split_full(str, "\n", -1, &count); + for (i = 0; i < count; i++) + { + if (_ecore_xcb_xdefaults_glob_match(ea[i], buff)) + sscanf(ea[i], "%*[^:]:%*[ ]%d", &ret); + } + if ((ea) && (ea[0])) + { + free(ea[0]); + free(ea); + } + + return ret; +} + +/* local functions */ +static Eina_Bool +_ecore_xcb_xdefaults_glob_match(const char *str, + const char *glob) +{ + if ((!str) || (!glob)) return EINA_FALSE; + if (glob[0] == 0) + { + if (str[0] == 0) return EINA_TRUE; + return EINA_FALSE; + } + if (!strcmp(glob, "*")) return EINA_TRUE; + if (!fnmatch(glob, str, 0)) return EINA_TRUE; + return EINA_FALSE; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_xfixes.c b/src/lib/ecore_x/xcb/ecore_xcb_xfixes.c new file mode 100644 index 0000000000..58444cdf1f --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_xfixes.c @@ -0,0 +1,744 @@ +#include "ecore_xcb_private.h" +# ifdef ECORE_XCB_XFIXES +# include <xcb/xfixes.h> +# endif + +/* local function prototypes */ +static xcb_rectangle_t *_ecore_xcb_rect_to_xcb(Ecore_X_Rectangle *rects, + int num); +static Ecore_X_Rectangle *_ecore_xcb_rect_to_ecore(xcb_rectangle_t *rects, + int num); + +/* local variables */ +static Eina_Bool _xfixes_avail = EINA_FALSE; + +/* external variables */ +int _ecore_xcb_event_xfixes = -1; + +void +_ecore_xcb_xfixes_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XFIXES + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xfixes_id); +#endif +} + +void +_ecore_xcb_xfixes_finalize(void) +{ +#ifdef ECORE_XCB_XFIXES + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XFIXES + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xfixes_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_xfixes_query_version_cookie_t cookie; + xcb_xfixes_query_version_reply_t *reply; + + cookie = + xcb_xfixes_query_version_unchecked(_ecore_xcb_conn, + XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + reply = xcb_xfixes_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + /* NB: XFixes Extension >= 3 needed for shape stuff. + * for now, I am removing this check so that it matches the + * xlib code closer. If the extension version ends up being + * that important, then re-enable this */ + + /* if (reply->major_version >= 3) */ + _xfixes_avail = EINA_TRUE; + free(reply); + } + + if (_xfixes_avail) + _ecore_xcb_event_xfixes = ext_reply->first_event; + } +#endif +} + +EAPI Eina_Bool +ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection) +{ +#ifdef ECORE_XCB_XFIXES + Ecore_X_Window root = 0; + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; + int mask = 0; +#endif + + CHECK_XCB_CONN; + + if (!_xfixes_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_XFIXES + root = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + mask = (XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | + XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE); + + cookie = + xcb_xfixes_select_selection_input_checked(_ecore_xcb_conn, root, + selection, mask); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + + return EINA_TRUE; +#endif + return EINA_FALSE; +} + +Eina_Bool +_ecore_xcb_xfixes_avail_get(void) +{ + return _xfixes_avail; +} + +/** + * @defgroup Ecore_X_Fixes_Group X Fixes Extension Functions + * + * Functions related to the X Fixes extension. + */ + +/** + * Create a region from rectangles. + * @param rects The rectangles used to initialize the region. + * @param num The number of rectangles. + * @return The newly created region. + * + * Create a region initialized to the specified list of rectangles + * @p rects. The rectangles may be specified in any order, their union + * becomes the region. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new(Ecore_X_Rectangle *rects, + int num) +{ + Ecore_X_Region region = 0; +#ifdef ECORE_XCB_XFIXES + xcb_rectangle_t *xrects; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return 0; + +#ifdef ECORE_XCB_XFIXES + xrects = _ecore_xcb_rect_to_xcb(rects, num); + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region(_ecore_xcb_conn, region, num, xrects); + free(xrects); +// ecore_x_flush(); +#endif + + return region; +} + +/** + * Create a region from a pixmap. + * @param bitmap The bitmap used to initialize the region. + * @return The newly created region. + * + * Creates a region initialized to the set of 'one' pixels in @p bitmap + * (which must be of depth 1, else Match error). + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap) +{ + Ecore_X_Region region = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return 0; + +#ifdef ECORE_XCB_XFIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_bitmap(_ecore_xcb_conn, region, bitmap); +// ecore_x_flush(); +#endif + + return region; +} + +/** + * Create a region from a window. + * @param win The window used to initialize the region. + * @param type The type of the region. + * @return The newly created region. + * + * Creates a region initialized to the specified @p window region. See + * the Shape extension for the definition of Bounding and Clip + * regions. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_window(Ecore_X_Window win, + Ecore_X_Region_Type type) +{ + Ecore_X_Region region = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return 0; + +#ifdef ECORE_XCB_XFIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_window(_ecore_xcb_conn, region, win, type); +// ecore_x_flush(); +#endif + + return region; +} + +/** + * Create a region from a graphic context. + * @param gc The graphic context used to initialize the region. + * @return The newly created region. + * + * Creates a region initialized from the clip list of @p gc. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_gc(Ecore_X_GC gc) +{ + Ecore_X_Region region = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return 0; + +#ifdef ECORE_XCB_XFIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_gc(_ecore_xcb_conn, region, gc); +// ecore_x_flush(); +#endif + + return region; +} + +/** + * Create a region from a picture. + * @param picture The picture used to initialize the region. + * @return The newly created region. + * + * Creates a region initialized from the clip list of @p picture. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Region +ecore_x_region_new_from_picture(Ecore_X_Picture picture) +{ + Ecore_X_Region region = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return 0; + +#ifdef ECORE_XCB_XFIXES + region = xcb_generate_id(_ecore_xcb_conn); + xcb_xfixes_create_region_from_picture(_ecore_xcb_conn, region, picture); +// ecore_x_flush(); +#endif + + return region; +} + +/** + * Destroy a region. + * @param region The region to destroy. + * + * Destroy the specified @p region. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_free(Ecore_X_Region region) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_destroy_region(_ecore_xcb_conn, region); +// ecore_x_flush(); +#endif +} + +/** + * Set the content of a region. + * @param region The region to destroy. + * @param rects The rectangles used to set the region. + * @param num The number of rectangles. + * + * Replace the current contents of @p region with the region formed + * by the union of the rectangles @p rects. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_set(Ecore_X_Region region, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XCB_XFIXES + xcb_rectangle_t *xrects; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xrects = _ecore_xcb_rect_to_xcb(rects, num); + xcb_xfixes_set_region(_ecore_xcb_conn, region, num, xrects); + free(xrects); +// ecore_x_flush(); +#endif +} + +/** + * Copy the content of a region. + * @param dest The destination region. + * @param source The source region. + * + * Replace the contents of @p dest with the contents of @p source. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_copy(Ecore_X_Region dest, + Ecore_X_Region source) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + + // NB: Hmmmm...this may need converting to/fro xcb_rectangle_t +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_copy_region(_ecore_xcb_conn, source, dest); +// ecore_x_flush(); +#endif +} + +/** + * Make the union of two regions. + * @param dest The destination region. + * @param source1 The first source region. + * @param source2 The second source region. + * + * Replace the contents of @p dest with the union of @p source1 and + * @p source2. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_combine(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_union_region(_ecore_xcb_conn, source1, source2, dest); +// ecore_x_flush(); +#endif +} + +/** + * Make the intersection of two regions. + * @param dest The destination region. + * @param source1 The first source region. + * @param source2 The second source region. + * + * Replace the contents of @p dest with the intersection of @p source1 and + * @p source2. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_intersect(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_intersect_region(_ecore_xcb_conn, source1, source2, dest); +// ecore_x_flush(); +#endif +} + +/** + * Make the subtraction of two regions. + * @param dest The destination region. + * @param source1 The first source region. + * @param source2 The second source region. + * + * Replace the contents of @p dest with the subtraction of @p source1 by + * @p source2. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_subtract(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_subtract_region(_ecore_xcb_conn, source1, source2, dest); +// ecore_x_flush(); +#endif +} + +/** + * Make the subtraction of regions by bounds. + * @param dest The destination region. + * @param bounds The bounds. + * @param source The source region. + * + * The @p source region is subtracted from the region specified by + * @p bounds. The result is placed in @p dest, replacing its + * contents. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_invert(Ecore_X_Region dest, + Ecore_X_Rectangle *bounds, + Ecore_X_Region source) +{ +#ifdef ECORE_XCB_XFIXES + xcb_rectangle_t xrects; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xrects.x = bounds->x; + xrects.y = bounds->y; + xrects.width = bounds->width; + xrects.height = bounds->height; + + xcb_xfixes_invert_region(_ecore_xcb_conn, source, xrects, dest); +// ecore_x_flush(); +#endif +} + +/** + * Translate a region. + * @param region The region to translate. + * @param dx The horizontal translation. + * @param dy The vertical translation. + * + * The @p region is translated by @p dx and @p dy in place. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_translate(Ecore_X_Region region, + int dx, + int dy) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_translate_region(_ecore_xcb_conn, region, dx, dy); +// ecore_x_flush(); +#endif +} + +/** + * Extent a region. + * @param dest The destination region. + * @param source The source region. + * + * The extents of the @p source region are placed in @p dest. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_extents(Ecore_X_Region dest, + Ecore_X_Region source) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_region_extents(_ecore_xcb_conn, source, dest); +// ecore_x_flush(); +#endif +} + +/** + * Return the rectangles that compose a region. + * @param region The region (Unused). + * @param num The number of returned rectangles. + * @param bounds The returned bounds of the region. + * @return The returned rectangles. + * + * @ingroup Ecore_X_Fixes_Group + */ +EAPI Ecore_X_Rectangle * +ecore_x_region_fetch(Ecore_X_Region region, + int *num, + Ecore_X_Rectangle *bounds) +{ + Ecore_X_Rectangle extents = { 0, 0, 0, 0 }; + Ecore_X_Rectangle *rects = NULL; +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_fetch_region_cookie_t cookie; + xcb_xfixes_fetch_region_reply_t *reply; + xcb_rectangle_t *r; + int n = 0; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (num) *num = 0; + if (bounds) *bounds = extents; + if (!_xfixes_avail) return NULL; + +#ifdef ECORE_XCB_XFIXES + cookie = xcb_xfixes_fetch_region_unchecked(_ecore_xcb_conn, region); + reply = xcb_xfixes_fetch_region_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return NULL; + + r = xcb_xfixes_fetch_region_rectangles(reply); + n = xcb_xfixes_fetch_region_rectangles_length(reply); + rects = _ecore_xcb_rect_to_ecore(r, n); + if (num) *num = n; + + /* rects = (Ecore_X_Rectangle *)malloc(n * sizeof(Ecore_X_Rectangle)); */ + /* if (!rects) */ + /* { */ + /* free(reply); */ + /* return NULL; */ + /* } */ + + /* for (i = 0; i < n; i++) */ + /* { */ + /* rects[i].x = r[i].x; */ + /* rects[i].y = r[i].y; */ + /* rects[i].width = r[i].width; */ + /* rects[i].height = r[i].height; */ + /* } */ + + (*bounds).x = reply->extents.x; + (*bounds).y = reply->extents.y; + (*bounds).width = reply->extents.width; + (*bounds).height = reply->extents.height; + + free(reply); +#endif + + return rects; +} + +/** + * Expand a region. + * @param dest The destination region. + * @param source The source region. + * @param left The number of pixels to add on the left. + * @param right The number of pixels to add on the right. + * @param top The number of pixels to add at the top. + * @param bottom The number of pixels to add at the bottom. + * + * Put in @p dest the area specified by expanding each rectangle in + * the @p source region by the specified number of pixels to the + * @p left, @p right, @p top and @p bottom. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_expand(Ecore_X_Region dest, + Ecore_X_Region source, + unsigned int left, + unsigned int right, + unsigned int top, + unsigned int bottom) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_expand_region(_ecore_xcb_conn, source, dest, left, right, top, bottom); +// ecore_x_flush(); +#endif +} + +/** + * Change clip-mask in a graphic context to the specified region. + * @param region The region to change. + * @param gc The clip-mask graphic context. + * @param x The horizontal translation. + * @param y The vertical translation. + * + * Changes clip-mask in @p gc to the specified @p region and + * sets the clip origin with the values of @p x_origin and @p y_origin. + * Output will be clippped to remain contained within the region. The + * clip origin is interpreted relative to the origin of whatever + * destination drawable is specified in a graphics request. The + * region is interpreted relative to the clip origin. Future changes + * to region have no effect on the gc clip-mask. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_gc_clip_set(Ecore_X_Region region, + Ecore_X_GC gc, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_set_gc_clip_region(_ecore_xcb_conn, gc, region, x, y); +// ecore_x_flush(); +#endif +} + +/** + * Change the shape extension of a window. + * @param region The region. + * @param dest The window whose shape is changed. + * @param type The kind of shape. + * @param x The horizontal offset. + * @param y The vertical offset. + * + * Set the specified Shape extension region of @p window to @p region, + * offset by @p x_offset and @p y_offset. Future changes to region + * have no effect on the window shape. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_window_shape_set(Ecore_X_Region region, + Ecore_X_Window dest, + Ecore_X_Shape_Type type, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_set_window_shape_region(_ecore_xcb_conn, dest, type, x, y, region); +// ecore_x_flush(); +#endif +} + +/** + * Change clip-mask in picture to the specified region. + * @param region The region. + * @param picture The picture. + * @param x The X coordinate of the origin. + * @param y The Y coordinate of the origin. + * + * Changes clip-mask in picture to the specified @p region + * and sets the clip origin. Input and output will be clipped to + * remain contained within the region. The clip origin is interpreted + * relative to the origin of the drawable associated with @p picture. The + * region is interpreted relative to the clip origin. Future changes + * to region have no effect on the picture clip-mask. + * @ingroup Ecore_X_Fixes_Group + */ +EAPI void +ecore_x_region_picture_clip_set(Ecore_X_Region region, + Ecore_X_Picture picture, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xfixes_avail) return; + +#ifdef ECORE_XCB_XFIXES + xcb_xfixes_set_picture_clip_region(_ecore_xcb_conn, picture, region, x, y); +// ecore_x_flush(); +#endif +} + +/* local function prototypes */ +static xcb_rectangle_t * +_ecore_xcb_rect_to_xcb(Ecore_X_Rectangle *rects, + int num) +{ + xcb_rectangle_t *xrect; + int i = 0; + + if (!num) return NULL; + + xrect = malloc(sizeof(xcb_rectangle_t) * num); + if (!xrect) return NULL; + + for (i = 0; i < num; i++) + { + xrect[i].x = rects[i].x; + xrect[i].y = rects[i].y; + xrect[i].width = rects[i].width; + xrect[i].height = rects[i].height; + } + + return xrect; +} + +static Ecore_X_Rectangle * +_ecore_xcb_rect_to_ecore(xcb_rectangle_t *rects, + int num) +{ + Ecore_X_Rectangle *erect; + int i = 0; + + if (!num) return NULL; + + erect = malloc(sizeof(Ecore_X_Rectangle) * num); + if (!erect) return NULL; + + for (i = 0; i < num; i++) + { + erect[i].x = rects[i].x; + erect[i].y = rects[i].y; + erect[i].width = rects[i].width; + erect[i].height = rects[i].height; + } + + return erect; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_xinerama.c b/src/lib/ecore_x/xcb/ecore_xcb_xinerama.c new file mode 100644 index 0000000000..37a2339e9b --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_xinerama.c @@ -0,0 +1,139 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_XINERAMA +# include <xcb/xinerama.h> +#endif + +/* local variables */ +static Eina_Bool _xinerama_avail = EINA_FALSE; +static Eina_Bool _xinerama_active = EINA_FALSE; + +void +_ecore_xcb_xinerama_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XINERAMA + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_xinerama_id); +#endif +} + +void +_ecore_xcb_xinerama_finalize(void) +{ +#ifdef ECORE_XCB_XINERAMA + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XINERAMA + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_xinerama_id); + if ((ext_reply) && (ext_reply->present)) + { + xcb_xinerama_query_version_cookie_t cookie; + xcb_xinerama_query_version_reply_t *reply; + + cookie = + xcb_xinerama_query_version_unchecked(_ecore_xcb_conn, + XCB_XINERAMA_MAJOR_VERSION, + XCB_XINERAMA_MINOR_VERSION); + reply = + xcb_xinerama_query_version_reply(_ecore_xcb_conn, cookie, NULL); + if (reply) + { + _xinerama_avail = EINA_TRUE; + // NB: Do we need to compare version numbers here ? + free(reply); + } + + if (_xinerama_avail) + { + xcb_xinerama_is_active_cookie_t acookie; + xcb_xinerama_is_active_reply_t *areply; + + acookie = xcb_xinerama_is_active_unchecked(_ecore_xcb_conn); + areply = + xcb_xinerama_is_active_reply(_ecore_xcb_conn, acookie, NULL); + if (areply) + { + _xinerama_active = areply->state; + free(areply); + } + } + } +#endif +} + +EAPI int +ecore_x_xinerama_screen_count_get(void) +{ + int count = 0; +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_query_screens_cookie_t cookie; + xcb_xinerama_query_screens_reply_t *reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_xinerama_avail) return 0; + +#ifdef ECORE_XCB_XINERAMA + cookie = xcb_xinerama_query_screens_unchecked(_ecore_xcb_conn); + reply = + xcb_xinerama_query_screens_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return 0; + count = reply->number; +#endif + + return count; +} + +EAPI Eina_Bool +ecore_x_xinerama_screen_geometry_get(int screen, + int *x, + int *y, + int *w, + int *h) +{ +#ifdef ECORE_XCB_XINERAMA + xcb_xinerama_query_screens_cookie_t cookie; + xcb_xinerama_query_screens_reply_t *reply; + xcb_xinerama_screen_info_t *info; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = ((xcb_screen_t *)_ecore_xcb_screen)->width_in_pixels; + if (h) *h = ((xcb_screen_t *)_ecore_xcb_screen)->height_in_pixels; + + if (!_xinerama_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_XINERAMA + cookie = xcb_xinerama_query_screens_unchecked(_ecore_xcb_conn); + reply = + xcb_xinerama_query_screens_reply(_ecore_xcb_conn, cookie, NULL); + if (!reply) return EINA_FALSE; + + info = xcb_xinerama_query_screens_screen_info(reply); + if (!info) + { + free(reply); + return EINA_FALSE; + } + + if (x) *x = info[screen].x_org; + if (y) *y = info[screen].y_org; + if (w) *w = info[screen].width; + if (h) *h = info[screen].height; + + free(reply); + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + diff --git a/src/lib/ecore_x/xcb/ecore_xcb_xtest.c b/src/lib/ecore_x/xcb/ecore_xcb_xtest.c new file mode 100644 index 0000000000..7f76b2ccb5 --- /dev/null +++ b/src/lib/ecore_x/xcb/ecore_xcb_xtest.c @@ -0,0 +1,215 @@ +#include "ecore_xcb_private.h" +#ifdef ECORE_XCB_XTEST +# include <xcb/xtest.h> +# include <X11/keysym.h> +#endif + +/* local variables */ +static Eina_Bool _test_avail = EINA_FALSE; + +void +_ecore_xcb_xtest_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XTEST + xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_test_id); +#endif +} + +void +_ecore_xcb_xtest_finalize(void) +{ +#ifdef ECORE_XCB_XTEST + const xcb_query_extension_reply_t *ext_reply; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +#ifdef ECORE_XCB_XTEST + ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_test_id); + if ((ext_reply) && (ext_reply->present)) + _test_avail = EINA_TRUE; +#endif +} + +EAPI Eina_Bool +#ifdef ECORE_XCB_XTEST +ecore_x_test_fake_key_down(const char *key) +#else +ecore_x_test_fake_key_down(const char *key EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XTEST + xcb_keycode_t keycode = 0; + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_test_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_XTEST + keycode = _ecore_xcb_keymap_string_to_keycode(key); + if (keycode == XCB_NO_SYMBOL) return EINA_FALSE; + + cookie = + xcb_test_fake_input(_ecore_xcb_conn, XCB_KEY_PRESS, + keycode, XCB_CURRENT_TIME, + ((xcb_screen_t *)_ecore_xcb_screen)->root, 0, 0, 0); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + +EAPI Eina_Bool +#ifdef ECORE_XCB_XTEST +ecore_x_test_fake_key_up(const char *key) +#else +ecore_x_test_fake_key_up(const char *key EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XTEST + xcb_keycode_t keycode = 0; + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_test_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_XTEST + keycode = _ecore_xcb_keymap_string_to_keycode(key); + if (keycode == XCB_NO_SYMBOL) return EINA_FALSE; + + cookie = + xcb_test_fake_input(_ecore_xcb_conn, XCB_KEY_RELEASE, + keycode, XCB_CURRENT_TIME, + ((xcb_screen_t *)_ecore_xcb_screen)->root, 0, 0, 0); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + return EINA_TRUE; +#endif + + return EINA_FALSE; +} + +EAPI Eina_Bool +#ifdef ECORE_XCB_XTEST +ecore_x_test_fake_key_press(const char *key) +#else +ecore_x_test_fake_key_press(const char *key EINA_UNUSED) +#endif +{ +#ifdef ECORE_XCB_XTEST + xcb_keycode_t keycode = 0; + xcb_keysym_t keysym = 0; + xcb_keycode_t shift_code = 0; + xcb_void_cookie_t cookie; + xcb_generic_error_t *err; + Eina_Bool shift = EINA_FALSE; +#endif + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (!_test_avail) return EINA_FALSE; + +#ifdef ECORE_XCB_XTEST + keycode = _ecore_xcb_keymap_string_to_keycode(key); + keysym = _ecore_xcb_keymap_keycode_to_keysym(keycode, 0); + if (keysym == XCB_NO_SYMBOL) + { + keysym = _ecore_xcb_keymap_keycode_to_keysym(keycode, 1); + if (keysym != XCB_NO_SYMBOL) + shift = EINA_TRUE; + } + + if (shift) + { + xcb_keycode_t *keycodes; + int i = 0; + + keycodes = _ecore_xcb_keymap_keysym_to_keycode(XK_Shift_L); + while (keycodes[i] != XCB_NO_SYMBOL) + { + if (keycodes[i] != 0) + { + shift_code = keycodes[i]; + break; + } + i++; + } + } + + if (shift) + { + cookie = + xcb_test_fake_input(_ecore_xcb_conn, XCB_KEY_PRESS, + shift_code, XCB_CURRENT_TIME, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + 0, 0, 0); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + } + + cookie = + xcb_test_fake_input(_ecore_xcb_conn, XCB_KEY_PRESS, + keycode, XCB_CURRENT_TIME, + ((xcb_screen_t *)_ecore_xcb_screen)->root, 0, 0, 0); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + cookie = + xcb_test_fake_input(_ecore_xcb_conn, XCB_KEY_RELEASE, + keycode, XCB_CURRENT_TIME, + ((xcb_screen_t *)_ecore_xcb_screen)->root, 0, 0, 0); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + + if (shift) + { + cookie = + xcb_test_fake_input(_ecore_xcb_conn, XCB_KEY_RELEASE, + shift_code, XCB_CURRENT_TIME, + ((xcb_screen_t *)_ecore_xcb_screen)->root, + 0, 0, 0); + err = xcb_request_check(_ecore_xcb_conn, cookie); + if (err) + { + free(err); + return EINA_FALSE; + } + } + + return EINA_TRUE; +#endif + + return EINA_FALSE; +} diff --git a/src/lib/ecore_x/xlib/ecore_x.c b/src/lib/ecore_x/xlib/ecore_x.c new file mode 100644 index 0000000000..d9b81bc0f8 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x.c @@ -0,0 +1,2242 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +//#define LOGRT 1 + +#ifdef LOGRT +#include <dlfcn.h> +#endif /* ifdef LOGRT */ + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" +#include "Ecore_Input.h" + +static Eina_Bool _ecore_x_fd_handler(void *data, + Ecore_Fd_Handler *fd_handler); +static Eina_Bool _ecore_x_fd_handler_buf(void *data, + Ecore_Fd_Handler *fd_handler); +static int _ecore_x_key_mask_get(KeySym sym); +static int _ecore_x_event_modifier(unsigned int state); + +static Ecore_Fd_Handler *_ecore_x_fd_handler_handle = NULL; + +static const int AnyXEvent = 0; /* 0 can be used as there are no event types + * with index 0 and 1 as they are used for + * errors + */ + +static int _ecore_x_event_shape_id = 0; +static int _ecore_x_event_screensaver_id = 0; +static int _ecore_x_event_sync_id = 0; +int _ecore_xlib_log_dom = -1; + +#ifdef ECORE_XRANDR +static int _ecore_x_event_randr_id = 0; +#endif /* ifdef ECORE_XRANDR */ +#ifdef ECORE_XFIXES +static int _ecore_x_event_fixes_selection_id = 0; +#endif /* ifdef ECORE_XFIXES */ +#ifdef ECORE_XDAMAGE +static int _ecore_x_event_damage_id = 0; +#endif /* ifdef ECORE_XDAMAGE */ +#ifdef ECORE_XGESTURE +static int _ecore_x_event_gesture_id = 0; +#endif /* ifdef ECORE_XGESTURE */ +#ifdef ECORE_XKB +static int _ecore_x_event_xkb_id = 0; +#endif /* ifdef ECORE_XKB */ +static int _ecore_x_event_handlers_num = 0; +static void (**_ecore_x_event_handlers) (XEvent * event) = NULL; + +static int _ecore_x_init_count = 0; +static int _ecore_x_grab_count = 0; + +Display *_ecore_x_disp = NULL; +double _ecore_x_double_click_time = 0.25; +Time _ecore_x_event_last_time = 0; +Window _ecore_x_event_last_win = 0; +int _ecore_x_event_last_root_x = 0; +int _ecore_x_event_last_root_y = 0; +Eina_Bool _ecore_x_xcursor = EINA_FALSE; + +Ecore_X_Window _ecore_x_private_win = 0; + +Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; + +EAPI int ECORE_X_EVENT_ANY = 0; +EAPI int ECORE_X_EVENT_MOUSE_IN = 0; +EAPI int ECORE_X_EVENT_MOUSE_OUT = 0; +EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0; +EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0; +EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0; +EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0; +EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0; +EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0; +EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0; +EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0; +EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_STACK = 0; +EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0; +EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0; +EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0; +EAPI int ECORE_X_EVENT_MAPPING_CHANGE = 0; +EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0; +EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0; +EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0; +EAPI int ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = 0; +EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0; +EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0; +EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_FLICK; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PAN; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAP; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_HOLD; +EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_GROUP; +EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0; +EAPI int ECORE_X_EVENT_SYNC_ALARM = 0; +EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0; +EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0; +EAPI int ECORE_X_EVENT_RANDR_CRTC_CHANGE = 0; +EAPI int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = 0; +EAPI int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = 0; +EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0; +EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0; +EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0; +EAPI int ECORE_X_EVENT_PING = 0; +EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0; + +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0; +EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0; + +EAPI int ECORE_X_EVENT_XKB_STATE_NOTIFY = 0; +EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0; + + +EAPI int ECORE_X_EVENT_GENERIC = 0; + +EAPI int ECORE_X_MODIFIER_SHIFT = 0; +EAPI int ECORE_X_MODIFIER_CTRL = 0; +EAPI int ECORE_X_MODIFIER_ALT = 0; +EAPI int ECORE_X_MODIFIER_WIN = 0; +EAPI int ECORE_X_MODIFIER_ALTGR = 0; + +EAPI int ECORE_X_LOCK_SCROLL = 0; +EAPI int ECORE_X_LOCK_NUM = 0; +EAPI int ECORE_X_LOCK_CAPS = 0; +EAPI int ECORE_X_LOCK_SHIFT = 0; + +EAPI int ECORE_X_RAW_BUTTON_PRESS = 0; +EAPI int ECORE_X_RAW_BUTTON_RELEASE = 0; +EAPI int ECORE_X_RAW_MOTION = 0; + +#ifdef LOGRT +static double t0 = 0.0; +static Status (*_logrt_real_reply)(Display *disp, + void *rep, + int extra, + Bool discard) = NULL; +static void +_logrt_init(void) +{ + void *lib; + + lib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY); + if (!lib) + lib = dlopen("libX11.so.6", RTLD_GLOBAL | RTLD_LAZY); + + if (!lib) + lib = dlopen("libX11.so.6.3", RTLD_GLOBAL | RTLD_LAZY); + + if (!lib) + lib = dlopen("libX11.so.6.3.0", RTLD_GLOBAL | RTLD_LAZY); + + _logrt_real_reply = dlsym(lib, "_XReply"); + t0 = ecore_time_get(); +} + +Status +_XReply(Display *disp, + void *rep, + int extra, + Bool discard) +{ + void *bt[128]; + int i, n; + char **sym; + + n = backtrace(bt, 128); + if (n > 0) + { + sym = backtrace_symbols(bt, n); + printf("ROUNDTRIP: %4.4f :", ecore_time_get() - t0); + if (sym) + { + for (i = n - 1; i > 0; i--) + { + char *fname = strchr(sym[i], '('); + if (fname) + { + char *tsym = alloca(strlen(fname) + 1); + char *end; + strcpy(tsym, fname + 1); + end = strchr(tsym, '+'); + if (end) + { + *end = 0; + printf("%s", tsym); + } + else + printf("???"); + } + else + printf("???"); + + if (i > 1) + printf(" > "); + } + printf("\n"); + } + } + + // fixme: logme + return _logrt_real_reply(disp, rep, extra, discard); +} + +#endif /* ifdef LOGRT */ + +/* wrapper to use XkbKeycodeToKeysym when possible */ +KeySym +_ecore_x_XKeycodeToKeysym(Display *display, KeyCode keycode, int idx) +{ +#ifdef ECORE_XKB + return XkbKeycodeToKeysym(display, keycode, 0, idx); +#else + return XKeycodeToKeysym(display, keycode, idx); +#endif +} + +void +_ecore_x_modifiers_get(void) +{ + /* everything has these... unless its like a pda... :) */ + ECORE_X_MODIFIER_SHIFT = _ecore_x_key_mask_get(XK_Shift_L); + ECORE_X_MODIFIER_CTRL = _ecore_x_key_mask_get(XK_Control_L); + + /* apple's xdarwin has no alt!!!! */ + ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Alt_L); + if (!ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Meta_L); + + if (!ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Super_L); + + /* the windows key... a valid modifier :) */ + ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Super_L); + if (!ECORE_X_MODIFIER_WIN) + ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Meta_L); + + ECORE_X_MODIFIER_ALTGR = _ecore_x_key_mask_get(XK_Mode_switch); + + if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT) + ECORE_X_MODIFIER_WIN = 0; + + if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL) + ECORE_X_MODIFIER_ALT = 0; + + ECORE_X_LOCK_SCROLL = _ecore_x_key_mask_get(XK_Scroll_Lock); + ECORE_X_LOCK_NUM = _ecore_x_key_mask_get(XK_Num_Lock); + ECORE_X_LOCK_CAPS = _ecore_x_key_mask_get(XK_Caps_Lock); + ECORE_X_LOCK_SHIFT = _ecore_x_key_mask_get(XK_Shift_Lock); +} + +/** + * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions + * + * Functions that start and shut down the Ecore X Library. + */ + +/** + * Initialize the X display connection to the given display. + * + * @param name Display target name. If @c NULL, the default display is + * assumed. + * @return The number of times the library has been initialized without + * being shut down. 0 is returned if an error occurs. + * @ingroup Ecore_X_Init_Group + */ +EAPI int +ecore_x_init(const char *name) +{ + int shape_base = 0; + int shape_err_base = 0; +#ifdef ECORE_XSS + int screensaver_base = 0; + int screensaver_err_base = 0; +#endif /* ifdef ECORE_XSS */ + int sync_base = 0; + int sync_err_base = 0; +#ifdef ECORE_XRANDR + int randr_base = 0; + int randr_err_base = 0; +#endif /* ifdef ECORE_XRANDR */ +#ifdef ECORE_XFIXES + int fixes_base = 0; + int fixes_err_base = 0; +#endif /* ifdef ECORE_XFIXES */ +#ifdef ECORE_XDAMAGE + int damage_base = 0; + int damage_err_base = 0; +#endif /* ifdef ECORE_XDAMAGE */ +#ifdef ECORE_XGESTURE + int gesture_base = 0; + int gesture_err_base = 0; +#endif /* ifdef ECORE_XGESTURE */ +#ifdef ECORE_XKB + int xkb_base = 0; +#endif /* ifdef ECORE_XKB */ + if (++_ecore_x_init_count != 1) + return _ecore_x_init_count; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); +#ifdef LOGRT + _logrt_init(); +#endif /* ifdef LOGRT */ + + eina_init(); + _ecore_xlib_log_dom = eina_log_domain_register + ("ecore_x", ECORE_XLIB_DEFAULT_LOG_COLOR); + if (_ecore_xlib_log_dom < 0) + { + EINA_LOG_ERR( + "Impossible to create a log domain for the Ecore Xlib module."); + return --_ecore_x_init_count; + } + + if (!ecore_init()) + goto shutdown_eina; + if (!ecore_event_init()) + goto shutdown_ecore; + +#ifdef EVAS_FRAME_QUEUING + XInitThreads(); +#endif /* ifdef EVAS_FRAME_QUEUING */ + _ecore_x_disp = XOpenDisplay((char *)name); + if (!_ecore_x_disp) + goto shutdown_ecore_event; + + _ecore_x_error_handler_init(); + _ecore_x_event_handlers_num = LASTEvent; + +#define ECORE_X_EVENT_HANDLERS_GROW(ext_base, ext_num_events) \ + do { \ + if (_ecore_x_event_handlers_num < (ext_base + ext_num_events)) { \ + _ecore_x_event_handlers_num = (ext_base + ext_num_events); } \ + } while (0) + + if (XShapeQueryExtension(_ecore_x_disp, &shape_base, &shape_err_base)) + _ecore_x_event_shape_id = shape_base; + + ECORE_X_EVENT_HANDLERS_GROW(shape_base, ShapeNumberEvents); + +#ifdef ECORE_XSS + if (XScreenSaverQueryExtension(_ecore_x_disp, &screensaver_base, + &screensaver_err_base)) + _ecore_x_event_screensaver_id = screensaver_base; + + ECORE_X_EVENT_HANDLERS_GROW(screensaver_base, ScreenSaverNumberEvents); +#endif /* ifdef ECORE_XSS */ + + if (XSyncQueryExtension(_ecore_x_disp, &sync_base, &sync_err_base)) + { + int major, minor; + + _ecore_x_event_sync_id = sync_base; + if (!XSyncInitialize(_ecore_x_disp, &major, &minor)) + _ecore_x_event_sync_id = 0; + } + + ECORE_X_EVENT_HANDLERS_GROW(sync_base, XSyncNumberEvents); + +#ifdef ECORE_XRANDR + if (XRRQueryExtension(_ecore_x_disp, &randr_base, &randr_err_base)) + _ecore_x_event_randr_id = randr_base; + + ECORE_X_EVENT_HANDLERS_GROW(randr_base, RRNumberEvents); +#endif /* ifdef ECORE_XRANDR */ + +#ifdef ECORE_XFIXES + if (XFixesQueryExtension(_ecore_x_disp, &fixes_base, &fixes_err_base)) + _ecore_x_event_fixes_selection_id = fixes_base; + + ECORE_X_EVENT_HANDLERS_GROW(fixes_base, XFixesNumberEvents); +#endif /* ifdef ECORE_XFIXES */ + +#ifdef ECORE_XDAMAGE + if (XDamageQueryExtension(_ecore_x_disp, &damage_base, &damage_err_base)) + _ecore_x_event_damage_id = damage_base; + + ECORE_X_EVENT_HANDLERS_GROW(damage_base, XDamageNumberEvents); +#endif /* ifdef ECORE_XDAMAGE */ + +#ifdef ECORE_XGESTURE + if (XGestureQueryExtension(_ecore_x_disp, &gesture_base, &gesture_err_base)) + _ecore_x_event_gesture_id = gesture_base; + + ECORE_X_EVENT_HANDLERS_GROW(gesture_base, GestureNumberEvents); +#endif /* ifdef ECORE_XGESTURE */ +#ifdef ECORE_XKB + { + int dummy; + + if (XkbQueryExtension(_ecore_x_disp, &dummy, &xkb_base, + &dummy, &dummy, &dummy)) + _ecore_x_event_xkb_id = xkb_base; + XkbSelectEventDetails(_ecore_x_disp, XkbUseCoreKbd, XkbStateNotify, + XkbAllStateComponentsMask, XkbGroupStateMask); + } + ECORE_X_EVENT_HANDLERS_GROW(xkb_base, XkbNumberEvents); +#endif + + _ecore_x_event_handlers = calloc(_ecore_x_event_handlers_num, sizeof(void *)); + if (!_ecore_x_event_handlers) + goto close_display; + +#ifdef ECORE_XCURSOR + _ecore_x_xcursor = XcursorSupportsARGB(_ecore_x_disp) ? EINA_TRUE : EINA_FALSE; +#endif /* ifdef ECORE_XCURSOR */ + _ecore_x_event_handlers[AnyXEvent] = _ecore_x_event_handle_any_event; + _ecore_x_event_handlers[KeyPress] = _ecore_x_event_handle_key_press; + _ecore_x_event_handlers[KeyRelease] = _ecore_x_event_handle_key_release; + _ecore_x_event_handlers[ButtonPress] = _ecore_x_event_handle_button_press; + _ecore_x_event_handlers[ButtonRelease] = + _ecore_x_event_handle_button_release; + _ecore_x_event_handlers[MotionNotify] = _ecore_x_event_handle_motion_notify; + _ecore_x_event_handlers[EnterNotify] = _ecore_x_event_handle_enter_notify; + _ecore_x_event_handlers[LeaveNotify] = _ecore_x_event_handle_leave_notify; + _ecore_x_event_handlers[FocusIn] = _ecore_x_event_handle_focus_in; + _ecore_x_event_handlers[FocusOut] = _ecore_x_event_handle_focus_out; + _ecore_x_event_handlers[KeymapNotify] = _ecore_x_event_handle_keymap_notify; + _ecore_x_event_handlers[Expose] = _ecore_x_event_handle_expose; + _ecore_x_event_handlers[GraphicsExpose] = + _ecore_x_event_handle_graphics_expose; + _ecore_x_event_handlers[VisibilityNotify] = + _ecore_x_event_handle_visibility_notify; + _ecore_x_event_handlers[CreateNotify] = _ecore_x_event_handle_create_notify; + _ecore_x_event_handlers[DestroyNotify] = + _ecore_x_event_handle_destroy_notify; + _ecore_x_event_handlers[UnmapNotify] = _ecore_x_event_handle_unmap_notify; + _ecore_x_event_handlers[MapNotify] = _ecore_x_event_handle_map_notify; + _ecore_x_event_handlers[MapRequest] = _ecore_x_event_handle_map_request; + _ecore_x_event_handlers[ReparentNotify] = + _ecore_x_event_handle_reparent_notify; + _ecore_x_event_handlers[ConfigureNotify] = + _ecore_x_event_handle_configure_notify; + _ecore_x_event_handlers[ConfigureRequest] = + _ecore_x_event_handle_configure_request; + _ecore_x_event_handlers[GravityNotify] = + _ecore_x_event_handle_gravity_notify; + _ecore_x_event_handlers[ResizeRequest] = + _ecore_x_event_handle_resize_request; + _ecore_x_event_handlers[CirculateNotify] = + _ecore_x_event_handle_circulate_notify; + _ecore_x_event_handlers[CirculateRequest] = + _ecore_x_event_handle_circulate_request; + _ecore_x_event_handlers[PropertyNotify] = + _ecore_x_event_handle_property_notify; + _ecore_x_event_handlers[SelectionClear] = + _ecore_x_event_handle_selection_clear; + _ecore_x_event_handlers[SelectionRequest] = + _ecore_x_event_handle_selection_request; + _ecore_x_event_handlers[SelectionNotify] = + _ecore_x_event_handle_selection_notify; + _ecore_x_event_handlers[ColormapNotify] = + _ecore_x_event_handle_colormap_notify; + _ecore_x_event_handlers[ClientMessage] = + _ecore_x_event_handle_client_message; + _ecore_x_event_handlers[MappingNotify] = + _ecore_x_event_handle_mapping_notify; +#ifdef GenericEvent + _ecore_x_event_handlers[GenericEvent] = _ecore_x_event_handle_generic_event; +#endif /* ifdef GenericEvent */ + + if (_ecore_x_event_shape_id) + _ecore_x_event_handlers[_ecore_x_event_shape_id] = + _ecore_x_event_handle_shape_change; + + if (_ecore_x_event_screensaver_id) + _ecore_x_event_handlers[_ecore_x_event_screensaver_id] = + _ecore_x_event_handle_screensaver_notify; + + if (_ecore_x_event_sync_id) + { + _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncCounterNotify] = + _ecore_x_event_handle_sync_counter; + _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncAlarmNotify] = + _ecore_x_event_handle_sync_alarm; + } + +#ifdef ECORE_XRANDR + if (_ecore_x_event_randr_id) + { + _ecore_x_event_handlers[_ecore_x_event_randr_id + + RRScreenChangeNotify] = + _ecore_x_event_handle_randr_change; + _ecore_x_event_handlers[_ecore_x_event_randr_id + + RRNotify] = _ecore_x_event_handle_randr_notify; + } + +#endif /* ifdef ECORE_XRANDR */ +#ifdef ECORE_XFIXES + if (_ecore_x_event_fixes_selection_id) + _ecore_x_event_handlers[_ecore_x_event_fixes_selection_id] = + _ecore_x_event_handle_fixes_selection_notify; + +#endif /* ifdef ECORE_XFIXES */ +#ifdef ECORE_XDAMAGE + if (_ecore_x_event_damage_id) + _ecore_x_event_handlers[_ecore_x_event_damage_id] = + _ecore_x_event_handle_damage_notify; + +#endif /* ifdef ECORE_XDAMAGE */ +#ifdef ECORE_XKB + // set x autorepeat detection to on. that means instead of + // press-release-press-release-press-release + // you get + // press-press-press-press-press-release + do + { + Bool works = 0; + XkbSetDetectableAutoRepeat(_ecore_x_disp, 1, &works); + } + while (0); + if (_ecore_x_event_xkb_id) + _ecore_x_event_handlers[_ecore_x_event_xkb_id] = _ecore_x_event_handle_xkb; +#endif /* ifdef ECORE_XKB */ + +#ifdef ECORE_XGESTURE + if (_ecore_x_event_gesture_id) + { + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyFlick] = + _ecore_x_event_handle_gesture_notify_flick; + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyPan] = + _ecore_x_event_handle_gesture_notify_pan; + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyPinchRotation] = + _ecore_x_event_handle_gesture_notify_pinchrotation; + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyTap] = + _ecore_x_event_handle_gesture_notify_tap; + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyTapNHold] = + _ecore_x_event_handle_gesture_notify_tapnhold; + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyHold] = + _ecore_x_event_handle_gesture_notify_hold; + _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyGroup] = + _ecore_x_event_handle_gesture_notify_group; + } + +#endif /* ifdef ECORE_XGESTURE */ + + if (!ECORE_X_EVENT_ANY) + { + ECORE_X_EVENT_ANY = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_IN = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_OUT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_FOCUS_IN = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_FOCUS_OUT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_KEYMAP = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DAMAGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CREATE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_DESTROY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_HIDE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHOW = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHOW_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_REPARENT = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CONFIGURE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_GRAVITY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STACK = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STACK_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROPERTY = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_COLORMAP = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_MAPPING = ecore_event_type_new(); + ECORE_X_EVENT_MAPPING_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_CLEAR = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_SELECTION_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_CLIENT_MESSAGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_SHAPE = ecore_event_type_new(); + ECORE_X_EVENT_SCREENSAVER_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_FLICK = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_PAN = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_TAP = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_HOLD = ecore_event_type_new(); + ECORE_X_EVENT_GESTURE_NOTIFY_GROUP = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_COUNTER = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new(); + ECORE_X_EVENT_SCREEN_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_RANDR_CRTC_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_DAMAGE_NOTIFY = ecore_event_type_new(); + + ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new(); + + ECORE_X_EVENT_DESKTOP_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_STATE_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = ecore_event_type_new(); + ECORE_X_EVENT_PING = ecore_event_type_new(); + + ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = ecore_event_type_new(); + + ECORE_X_EVENT_XKB_STATE_NOTIFY = ecore_event_type_new(); + ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = ecore_event_type_new(); + + ECORE_X_EVENT_GENERIC = ecore_event_type_new(); + + ECORE_X_RAW_BUTTON_PRESS = ecore_event_type_new(); + ECORE_X_RAW_BUTTON_RELEASE = ecore_event_type_new(); + ECORE_X_RAW_MOTION = ecore_event_type_new(); + } + + _ecore_x_modifiers_get(); + + _ecore_x_fd_handler_handle = + ecore_main_fd_handler_add(ConnectionNumber(_ecore_x_disp), + ECORE_FD_READ, + _ecore_x_fd_handler, _ecore_x_disp, + _ecore_x_fd_handler_buf, _ecore_x_disp); + if (!_ecore_x_fd_handler_handle) + goto free_event_handlers; + + _ecore_x_atoms_init(); + + /* Set up the ICCCM hints */ + ecore_x_icccm_init(); + + /* Set up the _NET_... hints */ + ecore_x_netwm_init(); + + /* old e hints init */ + ecore_x_e_init(); + + /* This is just to be anal about naming conventions */ + + _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = + ECORE_X_ATOM_WM_DELETE_WINDOW; + _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = + ECORE_X_ATOM_WM_TAKE_FOCUS; + _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = + ECORE_X_ATOM_NET_WM_PING; + _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = + ECORE_X_ATOM_NET_WM_SYNC_REQUEST; + + _ecore_x_selection_data_init(); + _ecore_x_dnd_init(); + _ecore_x_fixes_init(); + _ecore_x_damage_init(); + _ecore_x_composite_init(); + _ecore_x_dpms_init(); + _ecore_x_randr_init(); + _ecore_x_gesture_init(); + _ecore_x_input_init(); + _ecore_x_events_init(); + + _ecore_x_private_win = ecore_x_window_override_new(0, -77, -777, 123, 456); + + return _ecore_x_init_count; + +free_event_handlers: + free(_ecore_x_event_handlers); + _ecore_x_event_handlers = NULL; +close_display: + XCloseDisplay(_ecore_x_disp); + _ecore_x_fd_handler_handle = NULL; + _ecore_x_disp = NULL; +shutdown_ecore_event: + ecore_event_shutdown(); +shutdown_ecore: + ecore_shutdown(); +shutdown_eina: + eina_log_domain_unregister(_ecore_xlib_log_dom); + _ecore_xlib_log_dom = -1; + eina_shutdown(); + + return --_ecore_x_init_count; +} + +static int +_ecore_x_shutdown(int close_display) +{ + if (--_ecore_x_init_count != 0) + return _ecore_x_init_count; + + if (!_ecore_x_disp) + return _ecore_x_init_count; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + ecore_main_fd_handler_del(_ecore_x_fd_handler_handle); + if (close_display) + XCloseDisplay(_ecore_x_disp); + else + { + close(ConnectionNumber(_ecore_x_disp)); + // FIXME: may have to clean up x display internal here +// getting segv here? hmmm. odd. disable +// XFree(_ecore_x_disp); + } + + free(_ecore_x_event_handlers); + _ecore_x_fd_handler_handle = NULL; + _ecore_x_disp = NULL; + _ecore_x_event_handlers = NULL; + _ecore_x_events_shutdown(); + _ecore_x_input_shutdown(); + _ecore_x_selection_shutdown(); + _ecore_x_dnd_shutdown(); + ecore_x_netwm_shutdown(); + + ecore_event_shutdown(); + ecore_shutdown(); + + eina_log_domain_unregister(_ecore_xlib_log_dom); + _ecore_xlib_log_dom = -1; + eina_shutdown(); + + return _ecore_x_init_count; +} + +/** + * Shuts down the Ecore X library. + * + * In shutting down the library, the X display connection is terminated + * and any event handlers for it are removed. + * + * @return The number of times the library has been initialized without + * being shut down. 0 is returned if an error occurs. + * @ingroup Ecore_X_Init_Group + */ +EAPI int +ecore_x_shutdown(void) +{ + return _ecore_x_shutdown(1); +} + +/** + * Shuts down the Ecore X library. + * + * As ecore_x_shutdown, except do not close Display, only connection. + * + * @ingroup Ecore_X_Init_Group + */ +EAPI int +ecore_x_disconnect(void) +{ + return _ecore_x_shutdown(0); +} + +/** + * @defgroup Ecore_X_Display_Attr_Group X Display Attributes + * + * Functions that set and retrieve X display attributes. + */ + +/** + * Retrieves the Ecore_X_Display handle used for the current X connection. + * @return The current X display. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI Ecore_X_Display * +ecore_x_display_get(void) +{ + return (Ecore_X_Display *)_ecore_x_disp; +} + +/** + * Retrieves the X display file descriptor. + * @return The current X display file descriptor. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI int +ecore_x_fd_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ConnectionNumber(_ecore_x_disp); +} + +/** + * Retrieves the Ecore_X_Screen handle used for the current X connection. + * @return The current default screen. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI Ecore_X_Screen * +ecore_x_default_screen_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return (Ecore_X_Screen *)DefaultScreenOfDisplay(_ecore_x_disp); +} + +/** + * Retrieves the size of an Ecore_X_Screen. + * @param screen the handle to the screen to query. + * @param w where to return the width. May be NULL. Returns 0 on errors. + * @param h where to return the height. May be NULL. Returns 0 on errors. + * @ingroup Ecore_X_Display_Attr_Group + * @see ecore_x_default_screen_get() + * + * @since 1.1 + */ +EAPI void +ecore_x_screen_size_get(const Ecore_X_Screen *screen, + int *w, + int *h) +{ + Screen *s = (Screen *)screen; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (w) *w = 0; + if (h) *h = 0; + if (!s) return; + if (w) *w = s->width; + if (h) *h = s->height; +} + +/** + * Retrieves the number of screens. + * + * @return The count of the number of screens. + * @ingroup Ecore_X_Display_Attr_Group + * + * @since 1.1 + */ +EAPI int +ecore_x_screen_count_get(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + return ScreenCount(_ecore_x_disp); +} + +/** + * Retrieves the index number of the given screen. + * + * @param screen The screen for which the index will be retrieved. + * @return The index number of the screen. + * @ingroup Ecore_X_Display_Attr_Group + * + * @since 1.1 + */ +EAPI int +ecore_x_screen_index_get(const Ecore_X_Screen *screen) +{ + return XScreenNumberOfScreen((Screen *)screen); +} + +/** + * Retrieves the screen based on index number. + * + * @param idx The index that will be used to retrieve the screen. + * @return The Ecore_X_Screen at this index. + * @ingroup Ecore_X_Display_Attr_Group + * + * @since 1.1 + */ +EAPI Ecore_X_Screen * +ecore_x_screen_get(int idx) +{ + return XScreenOfDisplay(_ecore_x_disp, idx); +} + +/** + * Sets the timeout for a double and triple clicks to be flagged. + * + * This sets the time between clicks before the double_click flag is + * set in a button down event. If 3 clicks occur within double this + * time, the triple_click flag is also set. + * + * @param t The time in seconds + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI void +ecore_x_double_click_time_set(double t) +{ + if (t < 0.0) + t = 0.0; + + _ecore_x_double_click_time = t; +} + +/** + * Retrieves the double and triple click flag timeout. + * + * See @ref ecore_x_double_click_time_set for more information. + * + * @return The timeout for double clicks in seconds. + * @ingroup Ecore_X_Display_Attr_Group + */ +EAPI double +ecore_x_double_click_time_get(void) +{ + return _ecore_x_double_click_time; +} + +/** + * @defgroup Ecore_X_Flush_Group X Synchronization Functions + * + * Functions that ensure that all commands that have been issued by the + * Ecore X library have been sent to the server. + */ + +/** + * Sends all X commands in the X Display buffer. + * @ingroup Ecore_X_Flush_Group + */ +EAPI void +ecore_x_flush(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFlush(_ecore_x_disp); +} + +/** + * Flushes the command buffer and waits until all requests have been + * processed by the server. + * @ingroup Ecore_X_Flush_Group + */ +EAPI void +ecore_x_sync(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSync(_ecore_x_disp, False); +} + +/** + * Kill all clients with subwindows under a given window. + * + * You can kill all clients connected to the X server by using + * @ref ecore_x_window_root_list to get a list of root windows, and + * then passing each root window to this function. + * + * @param root The window whose children will be killed. + */ +EAPI void +ecore_x_killall(Ecore_X_Window root) +{ + unsigned int j; + Window root_r; + Window parent_r; + Window *children_r = NULL; + unsigned int num_children = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGrabServer(_ecore_x_disp); + /* Tranverse window tree starting from root, and drag each + * before the firing squad */ + while (XQueryTree(_ecore_x_disp, root, &root_r, &parent_r, + &children_r, &num_children) && (num_children > 0)) + { + for (j = 0; j < num_children; ++j) + { + XKillClient(_ecore_x_disp, children_r[j]); + } + + XFree(children_r); + } + XUngrabServer(_ecore_x_disp); + XSync(_ecore_x_disp, False); +} + +/** + * Kill a specific client + * + * You can kill a specific client owning window @p win + * + * @param win Window of the client to be killed + */ +EAPI void +ecore_x_kill(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XKillClient(_ecore_x_disp, win); +} + +/** + * Return the last event time + */ +EAPI Ecore_X_Time +ecore_x_current_time_get(void) +{ + return _ecore_x_event_last_time; +} + +/** + * Return the screen DPI + * + * This is a simplistic call to get DPI. It does not account for differing + * DPI in the x amd y axes nor does it account for multihead or xinerama and + * xrander where different parts of the screen may have different DPI etc. + * + * @return the general screen DPI (dots/pixels per inch). + */ +EAPI int +ecore_x_dpi_get(void) +{ + Screen *s; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + s = DefaultScreenOfDisplay(_ecore_x_disp); + if (s->mwidth <= 0) + return 75; + + return (((s->width * 254) / s->mwidth) + 5) / 10; +} + +/** + * Invoke the standard system beep to alert users + * + * @param percent The volume at which the bell rings. Must be in the range + * [-100,+100]. If percent >= 0, the final volume will be: + * base - [(base * percent) / 100] + percent + * Otherwise, it's calculated as: + * base + [(base * percent) / 100] + * where @c base is the bell's base volume as set by XChangeKeyboardControl(3). + * + * @returns @c EINA_TRUE on success, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_bell(int percent) +{ + int ret; + + ret = XBell(_ecore_x_disp, percent); + if (ret == BadValue) + return EINA_FALSE; + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_x_fd_handler(void *data, + Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + Display *d; + + d = data; + while (XPending(d)) + { + XEvent ev; + + XNextEvent(d, &ev); +#ifdef ENABLE_XIM + /* Filter event for XIM */ + if (XFilterEvent(&ev, ev.xkey.window)) + continue; + +#endif /* ifdef ENABLE_XIM */ + if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num)) + { + if (_ecore_x_event_handlers[AnyXEvent]) + _ecore_x_event_handlers[AnyXEvent] (&ev); + + if (_ecore_x_event_handlers[ev.type]) + _ecore_x_event_handlers[ev.type] (&ev); + } + } + return ECORE_CALLBACK_RENEW; +} + +static Eina_Bool +_ecore_x_fd_handler_buf(void *data, + Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + Display *d; + + d = data; + if (XPending(d)) + return ECORE_CALLBACK_RENEW; + + return ECORE_CALLBACK_CANCEL; +} + +static int +_ecore_x_key_mask_get(KeySym sym) +{ + XModifierKeymap *mod; + KeySym sym2; + int i, j; + const int masks[8] = + { + ShiftMask, LockMask, ControlMask, + Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask + }; + + mod = XGetModifierMapping(_ecore_x_disp); + if ((mod) && (mod->max_keypermod > 0)) + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + for (j = 0; j < 8; j++) + { + sym2 = _ecore_x_XKeycodeToKeysym(_ecore_x_disp, + mod->modifiermap[i], j); + if (sym2 != 0) + break; + } + if (sym2 == sym) + { + int mask; + + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + + XFree(mod); + return mask; + } + } + + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + + XFree(mod); + } + + return 0; +} + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/* FIXME: these funcs need categorising */ +/*****************************************************************************/ + +/** + * Get a list of all the root windows on the server. + * + * @note The returned array will need to be freed after use. + * @param num_ret Pointer to integer to put number of windows returned in. + * @return An array of all the root windows. @c NULL is returned if memory + * could not be allocated for the list, or if @p num_ret is @c NULL. + */ +EAPI Ecore_X_Window * +ecore_x_window_root_list(int *num_ret) +{ + int num, i; + Ecore_X_Window *roots; +#ifdef ECORE_XPRINT + int xp_base, xp_err_base; +#endif /* ifdef ECORE_XPRINT */ + + if (!num_ret) + return NULL; + + *num_ret = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); +#ifdef ECORE_XPRINT + num = ScreenCount(_ecore_x_disp); + if (XpQueryExtension(_ecore_x_disp, &xp_base, &xp_err_base)) + { + Screen **ps = NULL; + int psnum = 0; + + ps = XpQueryScreens(_ecore_x_disp, &psnum); + if (ps) + { + int overlap, j; + + overlap = 0; + for (i = 0; i < num; i++) + { + for (j = 0; j < psnum; j++) + { + if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j]) + overlap++; + } + } + roots = malloc(MAX((num - overlap) * sizeof(Window), 1)); + if (roots) + { + int k; + + k = 0; + for (i = 0; i < num; i++) + { + int is_print; + + is_print = 0; + for (j = 0; j < psnum; j++) + { + if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j]) + { + is_print = 1; + break; + } + } + if (!is_print) + { + roots[k] = RootWindow(_ecore_x_disp, i); + k++; + } + } + *num_ret = k; + } + + XFree(ps); + } + else + { + roots = malloc(num * sizeof(Window)); + if (!roots) + return NULL; + + *num_ret = num; + for (i = 0; i < num; i++) + roots[i] = RootWindow(_ecore_x_disp, i); + } + } + else + { + roots = malloc(num * sizeof(Window)); + if (!roots) + return NULL; + + *num_ret = num; + for (i = 0; i < num; i++) + roots[i] = RootWindow(_ecore_x_disp, i); + } + +#else /* ifdef ECORE_XPRINT */ + num = ScreenCount(_ecore_x_disp); + roots = malloc(num * sizeof(Window)); + if (!roots) + return NULL; + + *num_ret = num; + for (i = 0; i < num; i++) + roots[i] = RootWindow(_ecore_x_disp, i); +#endif /* ifdef ECORE_XPRINT */ + return roots; +} + +EAPI Ecore_X_Window +ecore_x_window_root_first_get(void) +{ + return RootWindow(_ecore_x_disp, 0); +/* + int num; + Ecore_X_Window root, *roots = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + roots = ecore_x_window_root_list(&num); + if (!(roots)) return 0; + + if (num > 0) + root = roots[0]; + else + root = 0; + + free(roots); + return root; + */ +} + +static void _ecore_x_window_manage_error(void *data); + +static int _ecore_x_window_manage_failed = 0; +static void +_ecore_x_window_manage_error(void *data EINA_UNUSED) +{ + if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) && + (ecore_x_error_code_get() == BadAccess)) + _ecore_x_window_manage_failed = 1; +} + +EAPI Eina_Bool +ecore_x_window_manage(Ecore_X_Window win) +{ + XWindowAttributes att; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True) + return EINA_FALSE; + + ecore_x_sync(); + _ecore_x_window_manage_failed = 0; + ecore_x_error_handler_set(_ecore_x_window_manage_error, NULL); + XSelectInput(_ecore_x_disp, win, + EnterWindowMask | + LeaveWindowMask | + PropertyChangeMask | + ResizeRedirectMask | + SubstructureRedirectMask | + SubstructureNotifyMask | + StructureNotifyMask | + KeyPressMask | + KeyReleaseMask | + att.your_event_mask); + ecore_x_sync(); + ecore_x_error_handler_set(NULL, NULL); + if (_ecore_x_window_manage_failed) + { + _ecore_x_window_manage_failed = 0; + return EINA_FALSE; + } + + return EINA_TRUE; +} + +EAPI void +ecore_x_window_container_manage(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSelectInput(_ecore_x_disp, win, + SubstructureRedirectMask | + SubstructureNotifyMask); +} + +EAPI void +ecore_x_window_client_manage(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSelectInput(_ecore_x_disp, win, + PropertyChangeMask | +// ResizeRedirectMask | + FocusChangeMask | + ColormapChangeMask | + VisibilityChangeMask | + StructureNotifyMask | + SubstructureNotifyMask + ); + XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); +} + +EAPI void +ecore_x_window_sniff(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSelectInput(_ecore_x_disp, win, + PropertyChangeMask | + SubstructureNotifyMask); +} + +EAPI void +ecore_x_window_client_sniff(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSelectInput(_ecore_x_disp, win, + PropertyChangeMask | + FocusChangeMask | + ColormapChangeMask | + VisibilityChangeMask | + StructureNotifyMask | + SubstructureNotifyMask); + XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); +} + +EAPI Eina_Bool +ecore_x_window_attributes_get(Ecore_X_Window win, + Ecore_X_Window_Attributes *att_ret) +{ + XWindowAttributes att; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) + return EINA_FALSE; + + memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes)); + att_ret->root = att.root; + att_ret->x = att.x; + att_ret->y = att.y; + att_ret->w = att.width; + att_ret->h = att.height; + att_ret->border = att.border_width; + att_ret->depth = att.depth; + if (att.map_state != IsUnmapped) + att_ret->visible = 1; + + if (att.map_state == IsViewable) + att_ret->viewable = 1; + + if (att.override_redirect) + att_ret->override = 1; + + if (att.class == InputOnly) + att_ret->input_only = 1; + + if (att.save_under) + att_ret->save_under = 1; + + att_ret->event_mask.mine = att.your_event_mask; + att_ret->event_mask.all = att.all_event_masks; + att_ret->event_mask.no_propagate = att.do_not_propagate_mask; + att_ret->window_gravity = att.win_gravity; + att_ret->pixel_gravity = att.bit_gravity; + att_ret->colormap = att.colormap; + att_ret->visual = att.visual; + return EINA_TRUE; +} + +EAPI void +ecore_x_window_save_set_add(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XAddToSaveSet(_ecore_x_disp, win); +} + +EAPI void +ecore_x_window_save_set_del(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XRemoveFromSaveSet(_ecore_x_disp, win); +} + +EAPI Ecore_X_Window * +ecore_x_window_children_get(Ecore_X_Window win, + int *num) +{ + Ecore_X_Window *windows = NULL; + Window root_ret = 0, parent_ret = 0, *children_ret = NULL; + unsigned int children_ret_num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XQueryTree(_ecore_x_disp, win, &root_ret, &parent_ret, &children_ret, + &children_ret_num)) + return NULL; + + if (children_ret) + { + windows = malloc(children_ret_num * sizeof(Ecore_X_Window)); + if (windows) + { + unsigned int i; + + for (i = 0; i < children_ret_num; i++) + windows[i] = children_ret[i]; + *num = children_ret_num; + } + + XFree(children_ret); + } + + return windows; +} + +EAPI Eina_Bool +ecore_x_pointer_control_set(int accel_num, + int accel_denom, + int threshold) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XChangePointerControl(_ecore_x_disp, 1, 1, + accel_num, accel_denom, threshold) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_pointer_control_get(int *accel_num, + int *accel_denom, + int *threshold) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XGetPointerControl(_ecore_x_disp, + accel_num, accel_denom, threshold) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_pointer_mapping_set(unsigned char *map, + int nmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return (XSetPointerMapping(_ecore_x_disp, map, nmap) == MappingSuccess) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_pointer_mapping_get(unsigned char *map, + int nmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XGetPointerMapping(_ecore_x_disp, map, nmap) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_pointer_grab(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XGrabPointer(_ecore_x_disp, win, False, + ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + None, None, CurrentTime) == GrabSuccess) + return EINA_TRUE; + + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_pointer_confine_grab(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XGrabPointer(_ecore_x_disp, win, False, + ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + win, None, CurrentTime) == GrabSuccess) + return EINA_TRUE; + + return EINA_FALSE; +} + +EAPI void +ecore_x_pointer_ungrab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XUngrabPointer(_ecore_x_disp, CurrentTime); +} + +EAPI Eina_Bool +ecore_x_pointer_warp(Ecore_X_Window win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_keyboard_grab(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XGrabKeyboard(_ecore_x_disp, win, False, + GrabModeAsync, GrabModeAsync, + CurrentTime) == GrabSuccess) + return EINA_TRUE; + + return EINA_FALSE; +} + +EAPI void +ecore_x_keyboard_ungrab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XUngrabKeyboard(_ecore_x_disp, CurrentTime); +} + +EAPI void +ecore_x_grab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_grab_count++; + if (_ecore_x_grab_count == 1) + XGrabServer(_ecore_x_disp); +} + +EAPI void +ecore_x_ungrab(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_grab_count--; + if (_ecore_x_grab_count < 0) + _ecore_x_grab_count = 0; + + if (_ecore_x_grab_count == 0) + XUngrabServer(_ecore_x_disp); +} + +int _ecore_window_grabs_num = 0; +Window *_ecore_window_grabs = NULL; +Eina_Bool (*_ecore_window_grab_replay_func)(void *data, + int event_type, + void *event); +void *_ecore_window_grab_replay_data; + +EAPI void +ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, + int event_type, + void *event), + void *data) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_window_grab_replay_func = func; + _ecore_window_grab_replay_data = data; +} + +EAPI void +ecore_x_window_button_grab(Ecore_X_Window win, + int button, + Ecore_X_Event_Mask event_mask, + int mod, + int any_mod) +{ + unsigned int b; + unsigned int m; + unsigned int locks[8]; + int i, ev; + Window *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + b = button; + if (b == 0) + b = AnyButton; + + m = _ecore_x_event_modifier(mod); + if (any_mod) + m = AnyModifier; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + ev = event_mask; + for (i = 0; i < 8; i++) + XGrabButton(_ecore_x_disp, b, m | locks[i], + win, False, ev, GrabModeSync, GrabModeAsync, None, None); + _ecore_window_grabs_num++; + t = realloc(_ecore_window_grabs, + _ecore_window_grabs_num * sizeof(Window)); + if (!t) return; + _ecore_window_grabs = t; + _ecore_window_grabs[_ecore_window_grabs_num - 1] = win; +} + +void +_ecore_x_sync_magic_send(int val, + Ecore_X_Window swin) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = _ecore_x_private_win; + xev.xclient.format = 32; + xev.xclient.message_type = 27777; + xev.xclient.data.l[0] = 0x7162534; + xev.xclient.data.l[1] = 0x10000000 + val; + xev.xclient.data.l[2] = swin; + XSendEvent(_ecore_x_disp, _ecore_x_private_win, False, NoEventMask, &xev); +} + +void +_ecore_x_window_grab_remove(Ecore_X_Window win) +{ + int i, shuffle = 0; + Window *t; + + if (_ecore_window_grabs_num > 0) + { + for (i = 0; i < _ecore_window_grabs_num; i++) + { + if (shuffle) + _ecore_window_grabs[i - 1] = _ecore_window_grabs[i]; + + if ((!shuffle) && (_ecore_window_grabs[i] == win)) + shuffle = 1; + } + if (shuffle) + { + _ecore_window_grabs_num--; + if (_ecore_window_grabs_num <= 0) + { + free(_ecore_window_grabs); + _ecore_window_grabs = NULL; + return; + } + t = realloc(_ecore_window_grabs, + _ecore_window_grabs_num * + sizeof(Window)); + if (!t) return; + _ecore_window_grabs = t; + } + } +} + +EAPI void +ecore_x_window_button_ungrab(Ecore_X_Window win, + int button, + int mod, + int any_mod) +{ + unsigned int b; + unsigned int m; + unsigned int locks[8]; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + b = button; + if (b == 0) + b = AnyButton; + + m = _ecore_x_event_modifier(mod); + if (any_mod) + m = AnyModifier; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + for (i = 0; i < 8; i++) + XUngrabButton(_ecore_x_disp, b, m | locks[i], win); + _ecore_x_sync_magic_send(1, win); +} + +int _ecore_key_grabs_num = 0; +Window *_ecore_key_grabs = NULL; + +EAPI void +ecore_x_window_key_grab(Ecore_X_Window win, + const char *key, + int mod, + int any_mod) +{ + KeyCode keycode = 0; + KeySym keysym; + unsigned int m; + unsigned int locks[8]; + int i; + Window *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + else + { + keysym = XStringToKeysym(key); + if (keysym == NoSymbol) + return; + + keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key)); + } + + if (keycode == 0) + return; + + m = _ecore_x_event_modifier(mod); + if (any_mod) + m = AnyModifier; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + for (i = 0; i < 8; i++) + XGrabKey(_ecore_x_disp, keycode, m | locks[i], + win, False, GrabModeSync, GrabModeAsync); + _ecore_key_grabs_num++; + t = realloc(_ecore_key_grabs, + _ecore_key_grabs_num * sizeof(Window)); + if (!t) return; + _ecore_key_grabs = t; + _ecore_key_grabs[_ecore_key_grabs_num - 1] = win; +} + +void +_ecore_x_key_grab_remove(Ecore_X_Window win) +{ + int i, shuffle = 0; + Window *t; + + if (_ecore_key_grabs_num > 0) + { + for (i = 0; i < _ecore_key_grabs_num; i++) + { + if (shuffle) + _ecore_key_grabs[i - 1] = _ecore_key_grabs[i]; + + if ((!shuffle) && (_ecore_key_grabs[i] == win)) + shuffle = 1; + } + if (shuffle) + { + _ecore_key_grabs_num--; + if (_ecore_key_grabs_num <= 0) + { + free(_ecore_key_grabs); + _ecore_key_grabs = NULL; + return; + } + t = realloc(_ecore_key_grabs, + _ecore_key_grabs_num * sizeof(Window)); + if (!t) return; + _ecore_key_grabs = t; + } + } +} + +EAPI void +ecore_x_window_key_ungrab(Ecore_X_Window win, + const char *key, + int mod, + int any_mod) +{ + KeyCode keycode = 0; + KeySym keysym; + unsigned int m; + unsigned int locks[8]; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + else + { + keysym = XStringToKeysym(key); + if (keysym == NoSymbol) + return; + + keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key)); + } + + if (keycode == 0) + return; + + m = _ecore_x_event_modifier(mod); + if (any_mod) + m = AnyModifier; + + locks[0] = 0; + locks[1] = ECORE_X_LOCK_CAPS; + locks[2] = ECORE_X_LOCK_NUM; + locks[3] = ECORE_X_LOCK_SCROLL; + locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; + locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; + locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; + for (i = 0; i < 8; i++) + XUngrabKey(_ecore_x_disp, keycode, m | locks[i], win); + _ecore_x_sync_magic_send(2, win); +} + +/** + * Send client message with given type and format 32. + * + * @param win The window the message is sent to. + * @param type The client message type. + * @param mask The mask of the message to be sent. + * @param d0 The client message data item 1 + * @param d1 The client message data item 2 + * @param d2 The client message data item 3 + * @param d3 The client message data item 4 + * @param d4 The client message data item 5 + * + * @return @c EINA_TRUE on success @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_client_message32_send(Ecore_X_Window win, + Ecore_X_Atom type, + Ecore_X_Event_Mask mask, + long d0, + long d1, + long d2, + long d3, + long d4) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.window = win; + xev.xclient.type = ClientMessage; + xev.xclient.message_type = type; + xev.xclient.format = 32; + xev.xclient.data.l[0] = d0; + xev.xclient.data.l[1] = d1; + xev.xclient.data.l[2] = d2; + xev.xclient.data.l[3] = d3; + xev.xclient.data.l[4] = d4; + + return XSendEvent(_ecore_x_disp, win, False, mask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +/** + * Send client message with given type and format 8. + * + * @param win The window the message is sent to. + * @param type The client message type. + * @param data Data to be sent. + * @param len Number of data bytes, max @c 20. + * + * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_client_message8_send(Ecore_X_Window win, + Ecore_X_Atom type, + const void *data, + int len) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.window = win; + xev.xclient.type = ClientMessage; + xev.xclient.message_type = type; + xev.xclient.format = 8; + if (len > 20) + len = 20; + + memcpy(xev.xclient.data.b, data, len); + memset(xev.xclient.data.b + len, 0, 20 - len); + + return XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_mouse_move_send(Ecore_X_Window win, + int x, + int y) +{ + XEvent xev; + XWindowAttributes att; + Window tw; + int rx, ry; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetWindowAttributes(_ecore_x_disp, win, &att); + XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); + xev.xmotion.type = MotionNotify; + xev.xmotion.window = win; + xev.xmotion.root = att.root; + xev.xmotion.subwindow = win; + xev.xmotion.time = _ecore_x_event_last_time; + xev.xmotion.x = x; + xev.xmotion.y = y; + xev.xmotion.x_root = rx; + xev.xmotion.y_root = ry; + xev.xmotion.state = 0; + xev.xmotion.is_hint = 0; + xev.xmotion.same_screen = 1; + return XSendEvent(_ecore_x_disp, win, True, PointerMotionMask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_mouse_down_send(Ecore_X_Window win, + int x, + int y, + int b) +{ + XEvent xev; + XWindowAttributes att; + Window tw; + int rx, ry; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetWindowAttributes(_ecore_x_disp, win, &att); + XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); + xev.xbutton.type = ButtonPress; + xev.xbutton.window = win; + xev.xbutton.root = att.root; + xev.xbutton.subwindow = win; + xev.xbutton.time = _ecore_x_event_last_time; + xev.xbutton.x = x; + xev.xbutton.y = y; + xev.xbutton.x_root = rx; + xev.xbutton.y_root = ry; + xev.xbutton.state = 1 << b; + xev.xbutton.button = b; + xev.xbutton.same_screen = 1; + return XSendEvent(_ecore_x_disp, win, True, ButtonPressMask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_mouse_up_send(Ecore_X_Window win, + int x, + int y, + int b) +{ + XEvent xev; + XWindowAttributes att; + Window tw; + int rx, ry; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetWindowAttributes(_ecore_x_disp, win, &att); + XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); + xev.xbutton.type = ButtonRelease; + xev.xbutton.window = win; + xev.xbutton.root = att.root; + xev.xbutton.subwindow = win; + xev.xbutton.time = _ecore_x_event_last_time; + xev.xbutton.x = x; + xev.xbutton.y = y; + xev.xbutton.x_root = rx; + xev.xbutton.y_root = ry; + xev.xbutton.state = 0; + xev.xbutton.button = b; + xev.xbutton.same_screen = 1; + return XSendEvent(_ecore_x_disp, win, True, ButtonReleaseMask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_mouse_in_send(Ecore_X_Window win, + int x, + int y) +{ + XEvent xev; + XWindowAttributes att; + Window tw; + int rx, ry; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetWindowAttributes(_ecore_x_disp, win, &att); + XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); + xev.xcrossing.type = EnterNotify; + xev.xcrossing.window = win; + xev.xcrossing.root = att.root; + xev.xcrossing.subwindow = win; + xev.xcrossing.time = _ecore_x_event_last_time; + xev.xcrossing.x = x; + xev.xcrossing.y = y; + xev.xcrossing.x_root = rx; + xev.xcrossing.y_root = ry; + xev.xcrossing.mode = NotifyNormal; + xev.xcrossing.detail = NotifyNonlinear; + xev.xcrossing.same_screen = 1; + xev.xcrossing.focus = 0; + xev.xcrossing.state = 0; + return XSendEvent(_ecore_x_disp, win, True, EnterWindowMask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_mouse_out_send(Ecore_X_Window win, + int x, + int y) +{ + XEvent xev; + XWindowAttributes att; + Window tw; + int rx, ry; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetWindowAttributes(_ecore_x_disp, win, &att); + XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); + xev.xcrossing.type = LeaveNotify; + xev.xcrossing.window = win; + xev.xcrossing.root = att.root; + xev.xcrossing.subwindow = win; + xev.xcrossing.time = _ecore_x_event_last_time; + xev.xcrossing.x = x; + xev.xcrossing.y = y; + xev.xcrossing.x_root = rx; + xev.xcrossing.y_root = ry; + xev.xcrossing.mode = NotifyNormal; + xev.xcrossing.detail = NotifyNonlinear; + xev.xcrossing.same_screen = 1; + xev.xcrossing.focus = 0; + xev.xcrossing.state = 0; + return XSendEvent(_ecore_x_disp, win, True, LeaveWindowMask, &xev) ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_focus_reset(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime); +} + +EAPI void +ecore_x_events_allow_all(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime); +} + +EAPI void +ecore_x_pointer_last_xy_get(int *x, + int *y) +{ + if (x) + *x = _ecore_x_event_last_root_x; + + if (y) + *y = _ecore_x_event_last_root_y; +} + +EAPI void +ecore_x_pointer_xy_get(Ecore_X_Window win, + int *x, + int *y) +{ + Window rwin, cwin; + int rx, ry, wx, wy, ret; + unsigned int mask; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = XQueryPointer(_ecore_x_disp, win, &rwin, &cwin, + &rx, &ry, &wx, &wy, &mask); + if (!ret) + wx = wy = -1; + + if (x) *x = wx; + if (y) *y = wy; +} + +/** + * Retrieve the Visual ID from a given Visual. + * + * @param visual The Visual to get the ID for. + * + * @return The visual id. + * @since 1.1.0 + */ +EAPI unsigned int +ecore_x_visual_id_get(Ecore_X_Visual visual) +{ + return XVisualIDFromVisual(visual); +} + +/** + * Retrieve the default Visual. + * + * @param disp The Display to get the Default Visual from + * @param screen The Screen. + * + * @return The default visual. + * @since 1.1.0 + */ +EAPI Ecore_X_Visual +ecore_x_default_visual_get(Ecore_X_Display *disp, + Ecore_X_Screen *screen) +{ + return DefaultVisual(disp, ecore_x_screen_index_get(screen)); +} + +/** + * Retrieve the default Colormap. + * + * @param disp The Display to get the Default Colormap from + * @param screen The Screen. + * + * @return The default colormap. + * @since 1.1.0 + */ +EAPI Ecore_X_Colormap +ecore_x_default_colormap_get(Ecore_X_Display *disp, + Ecore_X_Screen *screen) +{ + return DefaultColormap(disp, ecore_x_screen_index_get(screen)); +} + +/** + * Retrieve the default depth. + * + * @param disp The Display to get the Default Depth from + * @param screen The Screen. + * + * @return The default depth. + * @since 1.1.0 + */ +EAPI int +ecore_x_default_depth_get(Ecore_X_Display *disp, + Ecore_X_Screen *screen) +{ + return DefaultDepth(disp, ecore_x_screen_index_get(screen)); +} + +EAPI void +ecore_x_xkb_select_group(int group) +{ +#ifdef ECORE_XKB + XkbLockGroup(_ecore_x_disp, XkbUseCoreKbd, group); +#endif +} + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ + +static int +_ecore_x_event_modifier(unsigned int state) +{ + int xmodifiers = 0; + + if (state & ECORE_EVENT_MODIFIER_SHIFT) + xmodifiers |= ECORE_X_MODIFIER_SHIFT; + + if (state & ECORE_EVENT_MODIFIER_CTRL) + xmodifiers |= ECORE_X_MODIFIER_CTRL; + + if (state & ECORE_EVENT_MODIFIER_ALT) + xmodifiers |= ECORE_X_MODIFIER_ALT; + + if (state & ECORE_EVENT_MODIFIER_WIN) + xmodifiers |= ECORE_X_MODIFIER_WIN; + + if (state & ECORE_EVENT_MODIFIER_ALTGR) + xmodifiers |= ECORE_X_MODIFIER_ALTGR; + + if (state & ECORE_EVENT_LOCK_SCROLL) + xmodifiers |= ECORE_X_LOCK_SCROLL; + + if (state & ECORE_EVENT_LOCK_NUM) + xmodifiers |= ECORE_X_LOCK_NUM; + + if (state & ECORE_EVENT_LOCK_CAPS) + xmodifiers |= ECORE_X_LOCK_CAPS; + + if (state & ECORE_EVENT_LOCK_SHIFT) + xmodifiers |= ECORE_X_LOCK_SHIFT; + + return xmodifiers; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_atoms.c b/src/lib/ecore_x/xlib/ecore_x_atoms.c new file mode 100644 index 0000000000..2aec7ce740 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_atoms.c @@ -0,0 +1,109 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" +#include "ecore_x_atoms_decl.h" + +void +_ecore_x_atoms_init(void) +{ + Atom *atoms; + char **names; + int i, num; + + num = sizeof(atom_items) / sizeof(Atom_Item); + atoms = alloca(num * sizeof(Atom)); + names = alloca(num * sizeof(char *)); + for (i = 0; i < num; i++) + names[i] = (char *) atom_items[i].name; + XInternAtoms(_ecore_x_disp, names, num, False, atoms); + for (i = 0; i < num; i++) + *(atom_items[i].atom) = atoms[i]; +} + +/** + * Retrieves the atom value associated with the given name. + * @param name The given name. + * @return Associated atom value. + */ +EAPI Ecore_X_Atom +ecore_x_atom_get(const char *name) +{ + if (!_ecore_x_disp) + return 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XInternAtom(_ecore_x_disp, name, False); +} + +EAPI void +ecore_x_atoms_get(const char **names, + int num, + Ecore_X_Atom *atoms) +{ + Atom *atoms_int; + int i; + + if (!_ecore_x_disp) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atoms_int = alloca(num * sizeof(Atom)); + XInternAtoms(_ecore_x_disp, (char **)names, num, False, atoms_int); + for (i = 0; i < num; i++) + atoms[i] = atoms_int[i]; +} + +EAPI char * +ecore_x_atom_name_get(Ecore_X_Atom atom) +{ + char *name; + char *xname; + + if (!_ecore_x_disp) + return NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xname = XGetAtomName(_ecore_x_disp, atom); + if (!xname) + return NULL; + + name = strdup(xname); + XFree(xname); + + return name; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_composite.c b/src/lib/ecore_x/xlib/ecore_x_composite.c new file mode 100644 index 0000000000..b919db96d2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_composite.c @@ -0,0 +1,176 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" +#include "Ecore_X.h" + +static Eina_Bool _composite_available = EINA_FALSE; + +void +_ecore_x_composite_init(void) +{ + _composite_available = EINA_FALSE; + +#ifdef ECORE_XCOMPOSITE + int major, minor; + + if (XCompositeQueryVersion(_ecore_x_disp, &major, &minor)) + { +# ifdef ECORE_XRENDER + if (XRenderQueryExtension(_ecore_x_disp, &major, &minor)) + { +# ifdef ECORE_XFIXES + if (XFixesQueryVersion(_ecore_x_disp, &major, &minor)) + { + _composite_available = EINA_TRUE; + } +# endif + } +# endif + } +#endif +} + +EAPI Eina_Bool +ecore_x_composite_query(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _composite_available; +} + +EAPI void +ecore_x_composite_redirect_window(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ +#ifdef ECORE_XCOMPOSITE + int update = CompositeRedirectAutomatic; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = CompositeRedirectAutomatic; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = CompositeRedirectManual; + break; + } + XCompositeRedirectWindow(_ecore_x_disp, win, update); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + +EAPI void +ecore_x_composite_redirect_subwindows(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ +#ifdef ECORE_XCOMPOSITE + int update = CompositeRedirectAutomatic; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = CompositeRedirectAutomatic; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = CompositeRedirectManual; + break; + } + XCompositeRedirectSubwindows(_ecore_x_disp, win, update); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + +EAPI void +ecore_x_composite_unredirect_window(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ +#ifdef ECORE_XCOMPOSITE + int update = CompositeRedirectAutomatic; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = CompositeRedirectAutomatic; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = CompositeRedirectManual; + break; + } + XCompositeUnredirectWindow(_ecore_x_disp, win, update); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + +EAPI void +ecore_x_composite_unredirect_subwindows(Ecore_X_Window win, + Ecore_X_Composite_Update_Type type) +{ +#ifdef ECORE_XCOMPOSITE + int update = CompositeRedirectAutomatic; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + switch (type) + { + case ECORE_X_COMPOSITE_UPDATE_AUTOMATIC: + update = CompositeRedirectAutomatic; + break; + + case ECORE_X_COMPOSITE_UPDATE_MANUAL: + update = CompositeRedirectManual; + break; + } + XCompositeUnredirectSubwindows(_ecore_x_disp, win, update); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + +EAPI Ecore_X_Pixmap +ecore_x_composite_name_window_pixmap_get(Ecore_X_Window win) +{ + Ecore_X_Pixmap pixmap = None; +#ifdef ECORE_XCOMPOSITE + LOGFN(__FILE__, __LINE__, __FUNCTION__); + pixmap = XCompositeNameWindowPixmap(_ecore_x_disp, win); +#endif /* ifdef ECORE_XCOMPOSITE */ + return pixmap; +} + +EAPI void +ecore_x_composite_window_events_disable(Ecore_X_Window win) +{ +#ifdef ECORE_XCOMPOSITE + ecore_x_window_shape_input_rectangle_set(win, -1, -1, 1, 1); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + +EAPI void +ecore_x_composite_window_events_enable(Ecore_X_Window win) +{ +#ifdef ECORE_XCOMPOSITE + ecore_x_window_shape_input_rectangle_set(win, 0, 0, 65535, 65535); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + +EAPI Ecore_X_Window +ecore_x_composite_render_window_enable(Ecore_X_Window root) +{ + Ecore_X_Window win = 0; +#ifdef ECORE_XCOMPOSITE + win = XCompositeGetOverlayWindow(_ecore_x_disp, root); + ecore_x_composite_window_events_disable(win); +#endif /* ifdef ECORE_XCOMPOSITE */ + return win; +} + +EAPI void +ecore_x_composite_render_window_disable(Ecore_X_Window root) +{ +#ifdef ECORE_XCOMPOSITE + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XCompositeReleaseOverlayWindow(_ecore_x_disp, root); +#endif /* ifdef ECORE_XCOMPOSITE */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_cursor.c b/src/lib/ecore_x/xlib/ecore_x_cursor.c new file mode 100644 index 0000000000..a968c56af2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_cursor.c @@ -0,0 +1,246 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> + +#include "ecore_x_private.h" + +EAPI Eina_Bool +ecore_x_cursor_color_supported_get(void) +{ + return _ecore_x_xcursor; +} + +EAPI Ecore_X_Cursor +ecore_x_cursor_new(Ecore_X_Window win, + int *pixels, + int w, + int h, + int hot_x, + int hot_y) +{ +#ifdef ECORE_XCURSOR + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (_ecore_x_xcursor) + { + Cursor c; + XcursorImage *xci; + + xci = XcursorImageCreate(w, h); + if (xci) + { + int i; + + xci->xhot = hot_x; + xci->yhot = hot_y; + xci->delay = 0; + for (i = 0; i < (w * h); i++) + { +// int r, g, b, a; +// +// a = (pixels[i] >> 24) & 0xff; +// r = (((pixels[i] >> 16) & 0xff) * a) / 0xff; +// g = (((pixels[i] >> 8 ) & 0xff) * a) / 0xff; +// b = (((pixels[i] ) & 0xff) * a) / 0xff; + xci->pixels[i] = pixels[i]; +// (a << 24) | (r << 16) | (g << 8) | (b); + } + c = XcursorImageLoadCursor(_ecore_x_disp, xci); + XcursorImageDestroy(xci); + return c; + } + } + else +#endif /* ifdef ECORE_XCURSOR */ + { + XColor c1, c2; + Cursor c; + Pixmap pmap, mask; + GC gc; + XGCValues gcv; + XImage *xim; + unsigned int *pix; + int fr, fg, fb, br, bg, bb; + int brightest = 0; + int darkest = 255 * 3; + int x, y; + const int dither[2][2] = + { + {0, 2}, + {3, 1} + }; + + pmap = XCreatePixmap(_ecore_x_disp, win, w, h, 1); + mask = XCreatePixmap(_ecore_x_disp, win, w, h, 1); + xim = XCreateImage(_ecore_x_disp, + DefaultVisual(_ecore_x_disp, 0), + 1, ZPixmap, 0, NULL, w, h, 32, 0); + xim->data = malloc(xim->bytes_per_line * xim->height); + + fr = 0x00; fg = 0x00; fb = 0x00; + br = 0xff; bg = 0xff; bb = 0xff; + pix = (unsigned int *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + int r, g, b, a; + + a = (pix[0] >> 24) & 0xff; + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8) & 0xff; + b = (pix[0]) & 0xff; + if (a > 0) + { + if ((r + g + b) > brightest) + { + brightest = r + g + b; + br = r; + bg = g; + bb = b; + } + + if ((r + g + b) < darkest) + { + darkest = r + g + b; + fr = r; + fg = g; + fb = b; + } + } + + pix++; + } + } + + pix = (unsigned int *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + int v; + int r, g, b; + int d1, d2; + + r = (pix[0] >> 16) & 0xff; + g = (pix[0] >> 8) & 0xff; + b = (pix[0]) & 0xff; + d1 = + ((r - fr) * (r - fr)) + + ((g - fg) * (g - fg)) + + ((b - fb) * (b - fb)); + d2 = + ((r - br) * (r - br)) + + ((g - bg) * (g - bg)) + + ((b - bb) * (b - bb)); + if (d1 + d2) + { + v = (((d2 * 255) / (d1 + d2)) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) + v = 1; + else + v = 0; + } + else + v = 0; + + XPutPixel(xim, x, y, v); + pix++; + } + } + gc = XCreateGC(_ecore_x_disp, pmap, 0, &gcv); + XPutImage(_ecore_x_disp, pmap, gc, xim, 0, 0, 0, 0, w, h); + XFreeGC(_ecore_x_disp, gc); + + pix = (unsigned int *)pixels; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + int v; + + v = (((pix[0] >> 24) & 0xff) * 5) / 256; + if (v > dither[x & 0x1][y & 0x1]) + v = 1; + else + v = 0; + + XPutPixel(xim, x, y, v); + pix++; + } + } + gc = XCreateGC(_ecore_x_disp, mask, 0, &gcv); + XPutImage(_ecore_x_disp, mask, gc, xim, 0, 0, 0, 0, w, h); + XFreeGC(_ecore_x_disp, gc); + + free(xim->data); + xim->data = NULL; + XDestroyImage(xim); + + c1.pixel = 0; + c1.red = fr << 8 | fr; + c1.green = fg << 8 | fg; + c1.blue = fb << 8 | fb; + c1.flags = DoRed | DoGreen | DoBlue; + + c2.pixel = 0; + c2.red = br << 8 | br; + c2.green = bg << 8 | bg; + c2.blue = bb << 8 | bb; + c2.flags = DoRed | DoGreen | DoBlue; + + c = XCreatePixmapCursor(_ecore_x_disp, + pmap, mask, + &c1, &c2, + hot_x, hot_y); + XFreePixmap(_ecore_x_disp, pmap); + XFreePixmap(_ecore_x_disp, mask); + return c; + } + + return 0; +} + +EAPI void +ecore_x_cursor_free(Ecore_X_Cursor c) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFreeCursor(_ecore_x_disp, c); +} + +/* + * Returns the cursor for the given shape. + * Note that the return value must not be freed with + * ecore_x_cursor_free()! + */ +EAPI Ecore_X_Cursor +ecore_x_cursor_shape_get(int shape) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* Shapes are defined in Ecore_X_Cursor.h */ + return XCreateFontCursor(_ecore_x_disp, shape); +} + +EAPI void +ecore_x_cursor_size_set(int size) +{ +#ifdef ECORE_XCURSOR + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XcursorSetDefaultSize(_ecore_x_disp, size); +#else /* ifdef ECORE_XCURSOR */ + size = 0; +#endif /* ifdef ECORE_XCURSOR */ +} + +EAPI int +ecore_x_cursor_size_get(void) +{ +#ifdef ECORE_XCURSOR + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XcursorGetDefaultSize(_ecore_x_disp); +#else /* ifdef ECORE_XCURSOR */ + return 0; +#endif /* ifdef ECORE_XCURSOR */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_damage.c b/src/lib/ecore_x/xlib/ecore_x_damage.c new file mode 100644 index 0000000000..b094f85235 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_damage.c @@ -0,0 +1,71 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" +#include "Ecore_X.h" + +static Eina_Bool _damage_available = EINA_FALSE; +#ifdef ECORE_XDAMAGE +static int _damage_major, _damage_minor; +#endif /* ifdef ECORE_XDAMAGE */ + +void +_ecore_x_damage_init(void) +{ +#ifdef ECORE_XDAMAGE + _damage_major = 1; + _damage_minor = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XDamageQueryVersion(_ecore_x_disp, &_damage_major, &_damage_minor)) + _damage_available = EINA_TRUE; + else + _damage_available = EINA_FALSE; + +#else /* ifdef ECORE_XDAMAGE */ + _damage_available = EINA_FALSE; +#endif /* ifdef ECORE_XDAMAGE */ +} + +EAPI Eina_Bool +ecore_x_damage_query(void) +{ + return _damage_available; +} + +EAPI Ecore_X_Damage +ecore_x_damage_new(Ecore_X_Drawable d, + Ecore_X_Damage_Report_Level level) +{ +#ifdef ECORE_XDAMAGE + Ecore_X_Damage damage; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + damage = XDamageCreate(_ecore_x_disp, d, level); + return damage; +#else /* ifdef ECORE_XDAMAGE */ + return 0; +#endif /* ifdef ECORE_XDAMAGE */ +} + +EAPI void +ecore_x_damage_free(Ecore_X_Damage damage) +{ +#ifdef ECORE_XDAMAGE + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XDamageDestroy(_ecore_x_disp, damage); +#endif /* ifdef ECORE_XDAMAGE */ +} + +EAPI void +ecore_x_damage_subtract(Ecore_X_Damage damage, + Ecore_X_Region repair, + Ecore_X_Region parts) +{ +#ifdef ECORE_XDAMAGE + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XDamageSubtract(_ecore_x_disp, damage, repair, parts); +#endif /* ifdef ECORE_XDAMAGE */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_dnd.c b/src/lib/ecore_x/xlib/ecore_x_dnd.c new file mode 100644 index 0000000000..e4f74a7257 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_dnd.c @@ -0,0 +1,706 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +EAPI int ECORE_X_EVENT_XDND_ENTER = 0; +EAPI int ECORE_X_EVENT_XDND_POSITION = 0; +EAPI int ECORE_X_EVENT_XDND_STATUS = 0; +EAPI int ECORE_X_EVENT_XDND_LEAVE = 0; +EAPI int ECORE_X_EVENT_XDND_DROP = 0; +EAPI int ECORE_X_EVENT_XDND_FINISHED = 0; + +static Ecore_X_DND_Source *_source = NULL; +static Ecore_X_DND_Target *_target = NULL; +static int _ecore_x_dnd_init_count = 0; + +typedef struct _Version_Cache_Item +{ + Ecore_X_Window win; + int ver; +} Version_Cache_Item; +static Version_Cache_Item *_version_cache = NULL; +static int _version_cache_num = 0, _version_cache_alloc = 0; +static void (*_posupdatecb)(void *, + Ecore_X_Xdnd_Position *); +static void *_posupdatedata; + +void +_ecore_x_dnd_init(void) +{ + if (!_ecore_x_dnd_init_count) + { + _source = calloc(1, sizeof(Ecore_X_DND_Source)); + if (!_source) return; + _source->version = ECORE_X_DND_VERSION; + _source->win = None; + _source->dest = None; + _source->state = ECORE_X_DND_SOURCE_IDLE; + _source->prev.window = 0; + + _target = calloc(1, sizeof(Ecore_X_DND_Target)); + if (!_target) + { + free(_source); + _source = NULL; + return; + } + _target->win = None; + _target->source = None; + _target->state = ECORE_X_DND_TARGET_IDLE; + + ECORE_X_EVENT_XDND_ENTER = ecore_event_type_new(); + ECORE_X_EVENT_XDND_POSITION = ecore_event_type_new(); + ECORE_X_EVENT_XDND_STATUS = ecore_event_type_new(); + ECORE_X_EVENT_XDND_LEAVE = ecore_event_type_new(); + ECORE_X_EVENT_XDND_DROP = ecore_event_type_new(); + ECORE_X_EVENT_XDND_FINISHED = ecore_event_type_new(); + } + + _ecore_x_dnd_init_count++; +} + +void +_ecore_x_dnd_shutdown(void) +{ + _ecore_x_dnd_init_count--; + if (_ecore_x_dnd_init_count > 0) + return; + + if (_source) + free(_source); + + _source = NULL; + + if (_target) + free(_target); + + _target = NULL; + + _ecore_x_dnd_init_count = 0; +} + +static Eina_Bool +_ecore_x_dnd_converter_copy(char *target EINA_UNUSED, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *tprop EINA_UNUSED, + int *count EINA_UNUSED) +{ + XTextProperty text_prop; + char *mystr; + XICCEncodingStyle style = XTextStyle; + + if (!data || !size) + return EINA_FALSE; + + mystr = calloc(1, size + 1); + if (!mystr) + return EINA_FALSE; + + memcpy(mystr, data, size); + + if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, + &text_prop) == Success) + { + int bufsize = strlen((char *)text_prop.value) + 1; + *data_ret = malloc(bufsize); + if (!*data_ret) + { + free(mystr); + return EINA_FALSE; + } + memcpy(*data_ret, text_prop.value, bufsize); + *size_ret = bufsize; + XFree(text_prop.value); + free(mystr); + return EINA_TRUE; + } + else + { + free(mystr); + return EINA_FALSE; + } +} + +EAPI void +ecore_x_dnd_aware_set(Ecore_X_Window win, + Eina_Bool on) +{ + Ecore_X_Atom prop_data = ECORE_X_DND_VERSION; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (on) + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_AWARE, + XA_ATOM, 32, &prop_data, 1); + else + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_AWARE); +} + +EAPI int +ecore_x_dnd_version_get(Ecore_X_Window win) +{ + unsigned char *prop_data; + int num; + Version_Cache_Item *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + // this looks hacky - and it is, but we need a way of caching info about + // a window while dragging, because we literally query this every mouse + // move and going to and from x multiple times per move is EXPENSIVE + // and slows things down, puts lots of load on x etc. + if (_source->state == ECORE_X_DND_SOURCE_DRAGGING) + if (_version_cache) + { + int i; + + for (i = 0; i < _version_cache_num; i++) + { + if (_version_cache[i].win == win) + return _version_cache[i].ver; + } + } + + if (ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_AWARE, + XA_ATOM, 32, &prop_data, &num)) + { + int version = (int)*prop_data; + free(prop_data); + if (_source->state == ECORE_X_DND_SOURCE_DRAGGING) + { + _version_cache_num++; + if (_version_cache_num > _version_cache_alloc) + _version_cache_alloc += 16; + + t = realloc(_version_cache, + _version_cache_alloc * + sizeof(Version_Cache_Item)); + if (!t) return 0; + _version_cache = t; + _version_cache[_version_cache_num - 1].win = win; + _version_cache[_version_cache_num - 1].ver = version; + } + + return version; + } + + if (_source->state == ECORE_X_DND_SOURCE_DRAGGING) + { + _version_cache_num++; + if (_version_cache_num > _version_cache_alloc) + _version_cache_alloc += 16; + + t = realloc(_version_cache, _version_cache_alloc * + sizeof(Version_Cache_Item)); + if (!t) return 0; + _version_cache = t; + _version_cache[_version_cache_num - 1].win = win; + _version_cache[_version_cache_num - 1].ver = 0; + } + + return 0; +} + +EAPI Eina_Bool +ecore_x_dnd_type_isset(Ecore_X_Window win, + const char *type) +{ + int num, i, ret = EINA_FALSE; + unsigned char *data; + Ecore_X_Atom *atoms, atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, 32, &data, &num)) + return ret; + + atom = ecore_x_atom_get(type); + atoms = (Ecore_X_Atom *)data; + + for (i = 0; i < num; ++i) + { + if (atom == atoms[i]) + { + ret = EINA_TRUE; + break; + } + } + + XFree(data); + return ret; +} + +EAPI void +ecore_x_dnd_type_set(Ecore_X_Window win, + const char *type, + Eina_Bool on) +{ + Ecore_X_Atom atom; + Ecore_X_Atom *oldset = NULL, *newset = NULL; + int i, j = 0, num = 0; + unsigned char *data = NULL; + unsigned char *old_data = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = ecore_x_atom_get(type); + ecore_x_window_prop_property_get(win, ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, 32, &old_data, &num); + oldset = (Ecore_X_Atom *)old_data; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (on) + { + if (ecore_x_dnd_type_isset(win, type)) + { + XFree(old_data); + return; + } + + newset = calloc(num + 1, sizeof(Ecore_X_Atom)); + if (!newset) + return; + + data = (unsigned char *)newset; + + for (i = 0; i < num; i++) + newset[i + 1] = oldset[i]; + /* prepend the new type */ + newset[0] = atom; + + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, 32, data, num + 1); + } + else + { + if (!ecore_x_dnd_type_isset(win, type)) + { + XFree(old_data); + return; + } + + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); + if (!newset) + { + XFree(old_data); + return; + } + + data = (unsigned char *)newset; + for (i = 0; i < num; i++) + if (oldset[i] != atom) + newset[j++] = oldset[i]; + + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, 32, data, num - 1); + } + + XFree(oldset); + free(newset); +} + +EAPI void +ecore_x_dnd_types_set(Ecore_X_Window win, + const char **types, + unsigned int num_types) +{ + Ecore_X_Atom *newset = NULL; + unsigned int i; + unsigned char *data = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!num_types) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_TYPE_LIST); + else + { + newset = calloc(num_types, sizeof(Ecore_X_Atom)); + if (!newset) + return; + + data = (unsigned char *)newset; + for (i = 0; i < num_types; i++) + { + newset[i] = ecore_x_atom_get(types[i]); + ecore_x_selection_converter_atom_add(newset[i], + _ecore_x_dnd_converter_copy); + } + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, 32, data, num_types); + free(newset); + } +} + +EAPI void +ecore_x_dnd_actions_set(Ecore_X_Window win, + Ecore_X_Atom *actions, + unsigned int num_actions) +{ + unsigned int i; + unsigned char *data = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!num_actions) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_XDND_ACTION_LIST); + else + { + data = (unsigned char *)actions; + for (i = 0; i < num_actions; i++) + { + ecore_x_selection_converter_atom_add(actions[i], + _ecore_x_dnd_converter_copy); + } + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_XDND_ACTION_LIST, + XA_ATOM, 32, data, num_actions); + } +} + +/** + * The DND position update cb is called Ecore_X sends a DND position to a + * client. + * + * It essentially mirrors some of the data sent in the position message. + * Generally this cb should be set just before position update is called. + * Please note well you need to look after your own data pointer if someone + * trashes you position update cb set. + * + * It is considered good form to clear this when the dnd event finishes. + * + * @param cb Callback to updated each time ecore_x sends a position update. + * @param data User data. + */ +EAPI void +ecore_x_dnd_callback_pos_update_set( + void (*cb)(void *, + Ecore_X_Xdnd_Position *data), + const void *data) +{ + _posupdatecb = cb; + _posupdatedata = (void *)data; /* Discard the const early */ +} + +Ecore_X_DND_Source * +_ecore_x_dnd_source_get(void) +{ + return _source; +} + +Ecore_X_DND_Target * +_ecore_x_dnd_target_get(void) +{ + return _target; +} + +EAPI Eina_Bool +ecore_x_dnd_begin(Ecore_X_Window source, + unsigned char *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_dnd_version_get(source)) + return EINA_FALSE; + + /* Take ownership of XdndSelection */ + if (!ecore_x_selection_xdnd_set(source, data, size)) + return EINA_FALSE; + + if (_version_cache) + { + free(_version_cache); + _version_cache = NULL; + _version_cache_num = 0; + _version_cache_alloc = 0; + } + + ecore_x_window_shadow_tree_flush(); + + _source->win = source; + ecore_x_window_ignore_set(_source->win, 1); + _source->state = ECORE_X_DND_SOURCE_DRAGGING; + _source->time = _ecore_x_event_last_time; + _source->prev.window = 0; + + /* Default Accepted Action: move */ + _source->action = ECORE_X_ATOM_XDND_ACTION_MOVE; + _source->accepted_action = None; + _source->dest = None; + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_dnd_drop(void) +{ + XEvent xev; + int status = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (_source->dest) + { + xev.xany.type = ClientMessage; + xev.xany.display = _ecore_x_disp; + xev.xclient.format = 32; + xev.xclient.window = _source->dest; + + if (_source->will_accept) + { + xev.xclient.message_type = ECORE_X_ATOM_XDND_DROP; + xev.xclient.data.l[0] = _source->win; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = _source->time; + XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev); + _source->state = ECORE_X_DND_SOURCE_DROPPED; + status = EINA_TRUE; + } + else + { + xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE; + xev.xclient.data.l[0] = _source->win; + xev.xclient.data.l[1] = 0; + XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev); + _source->state = ECORE_X_DND_SOURCE_IDLE; + } + } + else + { + /* Dropping on nothing */ + ecore_x_selection_xdnd_clear(); + _source->state = ECORE_X_DND_SOURCE_IDLE; + } + + ecore_x_window_ignore_set(_source->win, 0); + + _source->prev.window = 0; + + return status; +} + +EAPI void +ecore_x_dnd_send_status(Eina_Bool will_accept, + Eina_Bool suppress, + Ecore_X_Rectangle rectangle, + Ecore_X_Atom action) +{ + XEvent xev; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + memset(&xev, 0, sizeof(XEvent)); + + _target->will_accept = will_accept; + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.message_type = ECORE_X_ATOM_XDND_STATUS; + xev.xclient.format = 32; + xev.xclient.window = _target->source; + + xev.xclient.data.l[0] = _target->win; + xev.xclient.data.l[1] = 0; + if (will_accept) + xev.xclient.data.l[1] |= 0x1UL; + + if (!suppress) + xev.xclient.data.l[1] |= 0x2UL; + + /* Set rectangle information */ + xev.xclient.data.l[2] = rectangle.x; + xev.xclient.data.l[2] <<= 16; + xev.xclient.data.l[2] |= rectangle.y; + xev.xclient.data.l[3] = rectangle.width; + xev.xclient.data.l[3] <<= 16; + xev.xclient.data.l[3] |= rectangle.height; + + if (will_accept) + { + xev.xclient.data.l[4] = action; + _target->accepted_action = action; + } + else + { + xev.xclient.data.l[4] = None; + _target->accepted_action = action; + } + + XSendEvent(_ecore_x_disp, _target->source, False, 0, &xev); +} + +EAPI void +ecore_x_dnd_send_finished(void) +{ + XEvent xev; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xany.type = ClientMessage; + xev.xany.display = _ecore_x_disp; + xev.xclient.message_type = ECORE_X_ATOM_XDND_FINISHED; + xev.xclient.format = 32; + xev.xclient.window = _target->source; + + xev.xclient.data.l[0] = _target->win; + xev.xclient.data.l[1] = 0; + xev.xclient.data.l[2] = 0; + if (_target->will_accept) + { + xev.xclient.data.l[1] |= 0x1UL; + xev.xclient.data.l[2] = _target->accepted_action; + } + + XSendEvent(_ecore_x_disp, _target->source, False, 0, &xev); + + _target->state = ECORE_X_DND_TARGET_IDLE; +} + +EAPI void +ecore_x_dnd_source_action_set(Ecore_X_Atom action) +{ + _source->action = action; + if (_source->prev.window) + _ecore_x_dnd_drag(_source->prev.window, _source->prev.x, _source->prev.y); +} + +EAPI Ecore_X_Atom +ecore_x_dnd_source_action_get(void) +{ + return _source->action; +} + +void +_ecore_x_dnd_drag(Ecore_X_Window root, + int x, + int y) +{ + XEvent xev; + Ecore_X_Window win; + Ecore_X_Window *skip; + Ecore_X_Xdnd_Position pos; + int num; + + if (_source->state != ECORE_X_DND_SOURCE_DRAGGING) + return; + + /* Preinitialize XEvent struct */ + memset(&xev, 0, sizeof(XEvent)); + xev.xany.type = ClientMessage; + xev.xany.display = _ecore_x_disp; + xev.xclient.format = 32; + + /* Attempt to find a DND-capable window under the cursor */ + skip = ecore_x_window_ignore_list(&num); +// WARNING - this function is HEAVY. it goes to and from x a LOT walking the +// window tree - use the SHADOW version - makes a 1-off tree copy, then uses +// that instead. +// win = ecore_x_window_at_xy_with_skip_get(x, y, skip, num); + win = ecore_x_window_shadow_tree_at_xy_with_skip_get(root, x, y, skip, num); + +// NOTE: This now uses the shadow version to find parent windows +// while ((win) && !(ecore_x_dnd_version_get(win))) +// win = ecore_x_window_parent_get(win); + while ((win) && !(ecore_x_dnd_version_get(win))) + win = ecore_x_window_shadow_parent_get(root, win); + + /* Send XdndLeave to current destination window if we have left it */ + if ((_source->dest) && (win != _source->dest)) + { + xev.xclient.window = _source->dest; + xev.xclient.message_type = ECORE_X_ATOM_XDND_LEAVE; + xev.xclient.data.l[0] = _source->win; + xev.xclient.data.l[1] = 0; + + XSendEvent(_ecore_x_disp, _source->dest, False, 0, &xev); + _source->suppress = 0; + } + + if (win) + { + int x1, x2, y1, y2; + + _source->version = MIN(ECORE_X_DND_VERSION, + ecore_x_dnd_version_get(win)); + if (win != _source->dest) + { + int i; + unsigned char *data; + Ecore_X_Atom *types; + + ecore_x_window_prop_property_get(_source->win, + ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, + 32, + &data, + &num); + types = (Ecore_X_Atom *)data; + + /* Entered new window, send XdndEnter */ + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_XDND_ENTER; + xev.xclient.data.l[0] = _source->win; + xev.xclient.data.l[1] = 0; + if (num > 3) + xev.xclient.data.l[1] |= 0x1UL; + else + xev.xclient.data.l[1] &= 0xfffffffeUL; + + xev.xclient.data.l[1] |= ((unsigned long)_source->version) << 24; + + for (i = 2; i < 5; i++) + xev.xclient.data.l[i] = 0; + for (i = 0; i < MIN(num, 3); ++i) + xev.xclient.data.l[i + 2] = types[i]; + XFree(data); + XSendEvent(_ecore_x_disp, win, False, 0, &xev); + _source->await_status = 0; + _source->will_accept = 0; + } + + /* Determine if we're still in the rectangle from the last status */ + x1 = _source->rectangle.x; + x2 = _source->rectangle.x + _source->rectangle.width; + y1 = _source->rectangle.y; + y2 = _source->rectangle.y + _source->rectangle.height; + + if ((!_source->await_status) || + (!_source->suppress) || + ((x < x1) || (x > x2) || (y < y1) || (y > y2))) + { + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_XDND_POSITION; + xev.xclient.data.l[0] = _source->win; + xev.xclient.data.l[1] = 0; /* Reserved */ + xev.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff); + xev.xclient.data.l[3] = _source->time; /* Version 1 */ + xev.xclient.data.l[4] = _source->action; /* Version 2, Needs to be pre-set */ + XSendEvent(_ecore_x_disp, win, False, 0, &xev); + + _source->await_status = 1; + } + } + + if (_posupdatecb) + { + pos.position.x = x; + pos.position.y = y; + pos.win = win; + pos.prev = _source->dest; + _posupdatecb(_posupdatedata, &pos); + } + + _source->prev.x = x; + _source->prev.y = y; + _source->prev.window = root; + _source->dest = win; +} + +/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/ diff --git a/src/lib/ecore_x/xlib/ecore_x_dpms.c b/src/lib/ecore_x/xlib/ecore_x_dpms.c new file mode 100644 index 0000000000..23349f44e6 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_dpms.c @@ -0,0 +1,247 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" + +static Eina_Bool _dpms_available = EINA_FALSE; + +void +_ecore_x_dpms_init(void) +{ +#ifdef ECORE_XDPMS + int _dpms_major, _dpms_minor; + + _dpms_major = 1; + _dpms_minor = 0; + + if (DPMSGetVersion(_ecore_x_disp, &_dpms_major, &_dpms_minor)) + _dpms_available = EINA_TRUE; + else + _dpms_available = EINA_FALSE; + +#else /* ifdef ECORE_XDPMS */ + _dpms_available = EINA_FALSE; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * @defgroup Ecore_X_DPMS_Group X DPMS Extension Functions + * + * Functions related to the X DPMS extension. + */ + +/** + * Checks if the X DPMS extension is available on the server. + * @return @c 1 if the X DPMS extension is available, @c 0 otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_query(void) +{ + return _dpms_available; +} + +/** + * Checks if the X server is capable of DPMS. + * @return @c 1 if the X server is capable of DPMS, @c 0 otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_capable_get(void) +{ +#ifdef ECORE_XDPMS + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return DPMSCapable(_ecore_x_disp) ? EINA_TRUE : EINA_FALSE; +#else /* ifdef ECORE_XDPMS */ + return EINA_FALSE; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Checks the DPMS state of the display. + * @return @c 1 if DPMS is enabled, @c 0 otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_enabled_get(void) +{ +#ifdef ECORE_XDPMS + unsigned char state; + unsigned short power_lvl; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSInfo(_ecore_x_disp, &power_lvl, &state); + return state ? EINA_TRUE : EINA_FALSE; +#else /* ifdef ECORE_XDPMS */ + return EINA_FALSE; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Sets the DPMS state of the display. + * @param enabled @c 0 to disable DPMS characteristics of the server, enable it otherwise. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_enabled_set(int enabled) +{ +#ifdef ECORE_XDPMS + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (enabled) + DPMSEnable(_ecore_x_disp); + else + DPMSDisable(_ecore_x_disp); + +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Gets the timeouts. The values are in unit of seconds. + * @param standby Amount of time of inactivity before standby mode will be invoked. + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * @param off Amount of time of inactivity before the monitor is shut off. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeouts_get(unsigned int *standby, + unsigned int *suspend, + unsigned int *off) +{ +#ifdef ECORE_XDPMS + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, (unsigned short *)standby, + (unsigned short *)suspend, (unsigned short *)off); +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Sets the timeouts. The values are in unit of seconds. + * @param standby Amount of time of inactivity before standby mode will be invoked. + * @param suspend Amount of time of inactivity before the screen is placed into suspend mode. + * @param off Amount of time of inactivity before the monitor is shut off. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI Eina_Bool +ecore_x_dpms_timeouts_set(unsigned int standby, + unsigned int suspend, + unsigned int off) +{ +#ifdef ECORE_XDPMS + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return DPMSSetTimeouts(_ecore_x_disp, standby, suspend, off) ? EINA_TRUE : EINA_FALSE; +#else /* ifdef ECORE_XDPMS */ + return EINA_FALSE; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Returns the amount of time of inactivity before standby mode is invoked. + * @return The standby timeout value. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_standby_get(void) +{ +#ifdef ECORE_XDPMS + unsigned short standby, suspend, off; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off); + return standby; +#else /* ifdef ECORE_XDPMS */ + return 0; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Returns the amount of time of inactivity before the second level of + * power saving is invoked. + * @return The suspend timeout value. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_suspend_get(void) +{ +#ifdef ECORE_XDPMS + unsigned short standby, suspend, off; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off); + return suspend; +#else /* ifdef ECORE_XDPMS */ + return 0; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Returns the amount of time of inactivity before the third and final + * level of power saving is invoked. + * @return The off timeout value. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI unsigned int +ecore_x_dpms_timeout_off_get(void) +{ +#ifdef ECORE_XDPMS + unsigned short standby, suspend, off; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off); + return off; +#else /* ifdef ECORE_XDPMS */ + return 0; +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Sets the standby timeout (in unit of seconds). + * @param new_timeout Amount of time of inactivity before standby mode will be invoked. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_standby_set(unsigned int new_timeout) +{ +#ifdef ECORE_XDPMS + unsigned short standby, suspend, off; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off); + DPMSSetTimeouts(_ecore_x_disp, new_timeout, suspend, off); +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Sets the suspend timeout (in unit of seconds). + * @param new_timeout Amount of time of inactivity before the screen is placed into suspend mode. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_suspend_set(unsigned int new_timeout) +{ +#ifdef ECORE_XDPMS + unsigned short standby, suspend, off; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off); + DPMSSetTimeouts(_ecore_x_disp, standby, new_timeout, off); +#endif /* ifdef ECORE_XDPMS */ +} + +/** + * Sets the off timeout (in unit of seconds). + * @param new_timeout Amount of time of inactivity before the monitor is shut off. + * @ingroup Ecore_X_DPMS_Group + */ +EAPI void +ecore_x_dpms_timeout_off_set(unsigned int new_timeout) +{ +#ifdef ECORE_XDPMS + unsigned short standby, suspend, off; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + DPMSGetTimeouts(_ecore_x_disp, &standby, &suspend, &off); + DPMSSetTimeouts(_ecore_x_disp, standby, suspend, new_timeout); +#endif /* ifdef ECORE_XDPMS */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_drawable.c b/src/lib/ecore_x/xlib/ecore_x_drawable.c new file mode 100644 index 0000000000..d1b41114da --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_drawable.c @@ -0,0 +1,118 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" + +/** + * @defgroup Ecore_X_Drawable_Group X Drawable Functions + * + * Functions that operate on drawables. + */ + +/** + * Retrieves the geometry of the given drawable. + * @param d The given drawable. + * @param x Pointer to an integer into which the X position is to be stored. + * @param y Pointer to an integer into which the Y position is to be stored. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI void +ecore_x_drawable_geometry_get(Ecore_X_Drawable d, + int *x, + int *y, + int *w, + int *h) +{ + Window dummy_win; + int ret_x, ret_y; + unsigned int ret_w, ret_h, dummy_border, dummy_depth; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetGeometry(_ecore_x_disp, d, &dummy_win, &ret_x, &ret_y, + &ret_w, &ret_h, &dummy_border, &dummy_depth)) + { + ret_x = 0; + ret_y = 0; + ret_w = 0; + ret_h = 0; + } + + if (x) + *x = ret_x; + + if (y) + *y = ret_y; + + if (w) + *w = (int)ret_w; + + if (h) + *h = (int)ret_h; +} + +/** + * Retrieves the width of the border of the given drawable. + * @param d The given drawable. + * @return The border width of the given drawable. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI int +ecore_x_drawable_border_width_get(Ecore_X_Drawable d) +{ + Window dummy_win; + int dummy_x, dummy_y; + unsigned int dummy_w, dummy_h, border_ret, dummy_depth; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetGeometry(_ecore_x_disp, d, &dummy_win, &dummy_x, &dummy_y, + &dummy_w, &dummy_h, &border_ret, &dummy_depth)) + border_ret = 0; + + return (int)border_ret; +} + +/** + * Retrieves the depth of the given drawable. + * @param d The given drawable. + * @return The depth of the given drawable. + * @ingroup Ecore_X_Drawable_Group + */ +EAPI int +ecore_x_drawable_depth_get(Ecore_X_Drawable d) +{ + Window dummy_win; + int dummy_x, dummy_y; + unsigned int dummy_w, dummy_h, dummy_border, depth_ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetGeometry(_ecore_x_disp, d, &dummy_win, &dummy_x, &dummy_y, + &dummy_w, &dummy_h, &dummy_border, &depth_ret)) + depth_ret = 0; + + return (int)depth_ret; +} + +/** + * Fill the specified rectangle on a drawable. + * @param d The given drawable. + * @param gc The graphic context that controls the fill rules. + * @param x The X coordinate of the top-left corner of the rectangle. + * @param y The Y coordinate of the top-left corner of the rectangle. + * @param width The width of the rectangle. + * @param height The height of the rectangle. + */ +EAPI void +ecore_x_drawable_rectangle_fill(Ecore_X_Drawable d, + Ecore_X_GC gc, + int x, + int y, + int width, + int height) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFillRectangle(_ecore_x_disp, d, gc, x, y, width, height); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_e.c b/src/lib/ecore_x/xlib/ecore_x_e.c new file mode 100644 index 0000000000..430b24b117 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_e.c @@ -0,0 +1,1670 @@ +/* + * OLD E hints + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +EAPI void +ecore_x_e_init(void) +{ +} + +EAPI void +ecore_x_e_frame_size_set(Ecore_X_Window win, + int fl, + int fr, + int ft, + int fb) +{ + unsigned int frames[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + frames[0] = fl; + frames[1] = fr; + frames[2] = ft; + frames[3] = fb; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_FRAME_SIZE, frames, 4); +} + +EAPI void +ecore_x_e_virtual_keyboard_set(Ecore_X_Window win, + unsigned int is_keyboard) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD, + &is_keyboard, 1); +} + +EAPI Eina_Bool +ecore_x_e_virtual_keyboard_get(Ecore_X_Window win) +{ + unsigned int val; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +static Ecore_X_Virtual_Keyboard_State +_ecore_x_e_vkbd_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_ON; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_IP; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_URL; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD; + + if (atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME; + + return ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_x_e_vkbd_atom_get(Ecore_X_Virtual_Keyboard_State state) +{ + switch (state) + { + case ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_ON: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_ALPHA: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ALPHA; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_NUMERIC: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_NUMERIC; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_PIN: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PIN; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_PHONE_NUMBER: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PHONE_NUMBER; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_HEX: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HEX; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_TERMINAL: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_TERMINAL; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_PASSWORD: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_PASSWORD; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_IP: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_IP; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_HOST: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_HOST; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_FILE: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_FILE; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_URL: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_URL; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_KEYPAD: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_KEYPAD; + + case ECORE_X_VIRTUAL_KEYBOARD_STATE_J2ME: + return ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_J2ME; + + default: break; + } + return 0; +} + +EAPI void +ecore_x_e_virtual_keyboard_state_set(Ecore_X_Window win, + Ecore_X_Virtual_Keyboard_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_vkbd_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE, + &atom, 1); +} + +EAPI Ecore_X_Virtual_Keyboard_State +ecore_x_e_virtual_keyboard_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE, + &atom, 1)) + return ECORE_X_VIRTUAL_KEYBOARD_STATE_UNKNOWN; + + return _ecore_x_e_vkbd_state_get(atom); +} + +EAPI void +ecore_x_e_virtual_keyboard_state_send(Ecore_X_Window win, + Ecore_X_Virtual_Keyboard_State state) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_x_e_vkbd_atom_get(state), + 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_x_e_illume_atom_get(Ecore_X_Illume_Mode mode) +{ + switch (mode) + { + case ECORE_X_ILLUME_MODE_SINGLE: + return ECORE_X_ATOM_E_ILLUME_MODE_SINGLE; + + case ECORE_X_ILLUME_MODE_DUAL_TOP: + return ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP; + + case ECORE_X_ILLUME_MODE_DUAL_LEFT: + return ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT; + + default: + break; + } + return ECORE_X_ILLUME_MODE_UNKNOWN; +} + +static Ecore_X_Illume_Mode +_ecore_x_e_illume_mode_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_MODE_SINGLE) + return ECORE_X_ILLUME_MODE_SINGLE; + + if (atom == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_TOP) + return ECORE_X_ILLUME_MODE_DUAL_TOP; + + if (atom == ECORE_X_ATOM_E_ILLUME_MODE_DUAL_LEFT) + return ECORE_X_ILLUME_MODE_DUAL_LEFT; + + return ECORE_X_ILLUME_MODE_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_zone_set(Ecore_X_Window win, + Ecore_X_Window zone) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(win, ECORE_X_ATOM_E_ILLUME_ZONE, + &zone, 1); +} + +EAPI Ecore_X_Window +ecore_x_e_illume_zone_get(Ecore_X_Window win) +{ + Ecore_X_Window zone; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_window_get(win, ECORE_X_ATOM_E_ILLUME_ZONE, + &zone, 1)) + return 0; + + return zone; +} + +EAPI void +ecore_x_e_illume_zone_list_set(Ecore_X_Window win, + Ecore_X_Window *zones, + unsigned int n_zones) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(win, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, + zones, n_zones); +} + +EAPI void +ecore_x_e_illume_conformant_set(Ecore_X_Window win, + unsigned int is_conformant) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_CONFORMANT, + &is_conformant, 1); +} + +EAPI Eina_Bool +ecore_x_e_illume_conformant_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_CONFORMANT, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_mode_set(Ecore_X_Window win, + Ecore_X_Illume_Mode mode) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_illume_atom_get(mode); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_MODE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Mode +ecore_x_e_illume_mode_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, ECORE_X_ATOM_E_ILLUME_MODE, &atom, 1)) + return ECORE_X_ILLUME_MODE_UNKNOWN; + + return _ecore_x_e_illume_mode_get(atom); +} + +EAPI void +ecore_x_e_illume_mode_send(Ecore_X_Window win, + Ecore_X_Illume_Mode mode) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_MODE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_x_e_illume_atom_get(mode), + 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_focus_back_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_BACK, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_focus_forward_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_FORWARD, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_focus_home_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_FOCUS_HOME, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_close_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_CLOSE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_home_new_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_HOME_NEW, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_home_del_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_HOME_DEL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_next_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_NEXT, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_prev_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_PREV, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_activate_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_read_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_read_next_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_read_prev_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_up_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_UP, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_access_action_down_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + win, + ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_DOWN, + 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_drag_set(Ecore_X_Window win, + unsigned int drag) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_DRAG, &drag, 1); +} + +EAPI Eina_Bool +ecore_x_e_illume_drag_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_DRAG, &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_drag_locked_set(Ecore_X_Window win, + unsigned int is_locked) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED, + &is_locked, 1); +} + +EAPI Eina_Bool +ecore_x_e_illume_drag_locked_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_drag_start_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_DRAG_START, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_drag_end_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_DRAG_END, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_indicator_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_indicator_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY, + geom, 4); + if (ret != 4) + return EINA_FALSE; + + if (x) + *x = geom[0]; + + if (y) + *y = geom[1]; + + if (w) + *w = geom[2]; + + if (h) + *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_illume_softkey_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_softkey_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY, + geom, 4); + if (ret != 4) + return EINA_FALSE; + + if (x) + *x = geom[0]; + + if (y) + *y = geom[1]; + + if (w) + *w = geom[2]; + + if (h) + *h = geom[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_e_illume_keyboard_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_keyboard_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY, + geom, 4); + if (ret != 4) + return EINA_FALSE; + + if (x) + *x = geom[0]; + + if (y) + *y = geom[1]; + + if (w) + *w = geom[2]; + + if (h) + *h = geom[3]; + + return EINA_TRUE; +} + +static Ecore_X_Atom +_ecore_x_e_quickpanel_atom_get(Ecore_X_Illume_Quickpanel_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_QUICKPANEL_STATE_ON: + return ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON; + + case ECORE_X_ILLUME_QUICKPANEL_STATE_OFF: + return ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Quickpanel_State +_ecore_x_e_quickpanel_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ON) + return ECORE_X_ILLUME_QUICKPANEL_STATE_ON; + + if (atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_OFF) + return ECORE_X_ILLUME_QUICKPANEL_STATE_OFF; + + return ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_quickpanel_set(Ecore_X_Window win, + unsigned int is_quickpanel) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL, + &is_quickpanel, 1); +} + +EAPI Eina_Bool +ecore_x_e_illume_quickpanel_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL, + &val, 1)) + return EINA_FALSE; + + return val ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_e_illume_quickpanel_state_set(Ecore_X_Window win, + Ecore_X_Illume_Quickpanel_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_quickpanel_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Quickpanel_State +ecore_x_e_illume_quickpanel_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE, + &atom, 1)) + return ECORE_X_ILLUME_QUICKPANEL_STATE_UNKNOWN; + + return _ecore_x_e_quickpanel_state_get(atom); +} + +EAPI void +ecore_x_e_illume_quickpanel_state_send(Ecore_X_Window win, + Ecore_X_Illume_Quickpanel_State state) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_x_e_quickpanel_atom_get(state), + 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_quickpanel_state_toggle(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE_TOGGLE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 0, 0, 0, 0, 0); +} + +EAPI void +ecore_x_e_illume_quickpanel_priority_major_set(Ecore_X_Window win, + unsigned int priority) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR, + &priority, 1); +} + +EAPI int +ecore_x_e_illume_quickpanel_priority_major_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR, + &val, 1)) + return 0; + + return val; +} + +EAPI void +ecore_x_e_illume_quickpanel_priority_minor_set(Ecore_X_Window win, + unsigned int priority) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR, + &priority, 1); +} + +EAPI int +ecore_x_e_illume_quickpanel_priority_minor_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR, + &val, 1)) + return 0; + + return val; +} + +EAPI void +ecore_x_e_illume_quickpanel_zone_set(Ecore_X_Window win, + unsigned int zone) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE, + &zone, 1); +} + +EAPI int +ecore_x_e_illume_quickpanel_zone_get(Ecore_X_Window win) +{ + unsigned int val = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE, + &val, 1)) + return 0; + + return val; +} + +EAPI void +ecore_x_e_illume_quickpanel_position_update_send(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_ILLUME_QUICKPANEL_POSITION_UPDATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + 1, 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_x_e_clipboard_atom_get(Ecore_X_Illume_Clipboard_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_CLIPBOARD_STATE_ON: + return ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON; + case ECORE_X_ILLUME_CLIPBOARD_STATE_OFF: + return ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF; + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Clipboard_State +_ecore_x_e_clipboard_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_ON) + return ECORE_X_ILLUME_CLIPBOARD_STATE_ON; + + if (atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_OFF) + return ECORE_X_ILLUME_CLIPBOARD_STATE_OFF; + + return ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_clipboard_state_set(Ecore_X_Window win, + Ecore_X_Illume_Clipboard_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_clipboard_atom_get(state); + + ecore_x_window_prop_atom_set(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Clipboard_State +ecore_x_e_illume_clipboard_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE, + &atom, 1)) + return ECORE_X_ILLUME_CLIPBOARD_STATE_UNKNOWN; + return _ecore_x_e_clipboard_state_get(atom); +} + +EAPI void +ecore_x_e_illume_clipboard_geometry_set(Ecore_X_Window win, + int x, int y, int w, int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY, + geom, 4); +} + +EAPI Eina_Bool +ecore_x_e_illume_clipboard_geometry_get(Ecore_X_Window win, + int *x, int *y, int *w, int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY, + geom, 4); + if (ret != 4) return EINA_FALSE; + + if (x) *x = geom[0]; + if (y) *y = geom[1]; + if (w) *w = geom[2]; + if (h) *h = geom[3]; + + return EINA_TRUE; +} + +/* for sliding window */ +EAPI void +ecore_x_e_illume_sliding_win_state_set(Ecore_X_Window win, + unsigned int is_visible) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_STATE, + &is_visible, 1); +} /* ecore_x_e_illume_sliding_win_state_set */ + +EAPI int +ecore_x_e_illume_sliding_win_state_get(Ecore_X_Window win) +{ + unsigned int is_visible = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_STATE, + &is_visible, 1)) + return 0; + + return is_visible; +} + +EAPI void +ecore_x_e_illume_sliding_win_geometry_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geom[0] = x; + geom[1] = y; + geom[2] = w; + geom[3] = h; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_GEOMETRY, + geom, 4); +} /* ecore_x_e_illume_sliding_win_geometry_set */ + +EAPI int +ecore_x_e_illume_sliding_win_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + int ret = 0; + unsigned int geom[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_E_ILLUME_SLIDING_WIN_GEOMETRY, + geom, 4); + if (ret != 4) + return 0; + + if (x) + *x = geom[0]; + + if (y) + *y = geom[1]; + + if (w) + *w = geom[2]; + + if (h) + *h = geom[3]; + + return 1; +}/* ecore_x_e_illume_sliding_win_geometry_get */ + +EAPI void +ecore_x_e_comp_sync_counter_set(Ecore_X_Window win, + Ecore_X_Sync_Counter counter) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (counter) + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER, + ECORE_X_ATOM_CARDINAL, &counter, 1); + else + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_COMP_SYNC_COUNTER); +} + +EAPI Ecore_X_Sync_Counter +ecore_x_e_comp_sync_counter_get(Ecore_X_Window win) +{ + int ret = 0; + Ecore_X_Sync_Counter counter = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_xid_get(win, + ECORE_X_ATOM_E_COMP_SYNC_COUNTER, + ECORE_X_ATOM_CARDINAL, + &counter, 1); + if (ret != 1) + return 0; + + return counter; +} + +EAPI void +ecore_x_e_comp_sync_draw_done_send(Ecore_X_Window root, + Ecore_X_Window win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 0; // version + xev.xclient.data.l[2] = 0; // later + xev.xclient.data.l[3] = 0; // later + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_comp_sync_draw_size_done_send(Ecore_X_Window root, + Ecore_X_Window win, + int w, + int h) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_DRAW_DONE; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 1; // version + xev.xclient.data.l[2] = w; // win width at draw time + xev.xclient.data.l[3] = h; // win height at draw time + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +/* + * @since 1.3 + * + */ +EAPI void +ecore_x_e_window_profile_list_set(Ecore_X_Window win, + const char **profiles, + unsigned int num_profiles) +{ + Ecore_X_Atom *atoms; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!win) + return; + + if (!num_profiles) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_PROFILE_LIST); + else + { + atoms = alloca(num_profiles * sizeof(Ecore_X_Atom)); + ecore_x_atoms_get(profiles, num_profiles, atoms); + ecore_x_window_prop_property_set(win, + ECORE_X_ATOM_E_PROFILE_LIST, + XA_ATOM, 32, (void *)atoms, + num_profiles); + } +} + +/* + * @since 1.3 + */ +EAPI Eina_Bool +ecore_x_e_window_profile_list_get(Ecore_X_Window win, + const char ***profiles, + int *ret_num) +{ + unsigned char *data; + Ecore_X_Atom *atoms; + int num, i; + + if (ret_num) + *ret_num = 0; + + if (profiles) + *profiles = NULL; + + if (!win) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_E_PROFILE_LIST, + XA_ATOM, 32, &data, &num)) + return EINA_FALSE; + + if (ret_num) + *ret_num = num; + + if (profiles) + { + (*profiles) = calloc(num, sizeof(char *)); + if (!(*profiles)) + { + if (ret_num) + *ret_num = 0; + + if (data) + free(data); + + return EINA_FALSE; + } + + atoms = (Ecore_X_Atom *)data; + for (i = 0; i < num; i++) + (*profiles)[i] = ecore_x_atom_name_get(atoms[i]); + } + + if (data) + XFree(data); + + return EINA_TRUE; +} + +/* + * @since 1.3 + */ +EAPI void +ecore_x_e_window_profile_set(Ecore_X_Window win, + const char *profile) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!win) + return; + + if (!profile) + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_E_PROFILE); + else + { + atom = ecore_x_atom_get(profile); + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_E_PROFILE, + XA_ATOM, 32, (void *)&atom, 1); + } +} + +/* + * @since 1.3 + */ +EAPI char * +ecore_x_e_window_profile_get(Ecore_X_Window win) +{ + Ecore_X_Atom *atom = NULL; + unsigned char *data; + char *profile = NULL; + int num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_E_PROFILE, + XA_ATOM, 32, &data, &num)) + return NULL; + + if (data) + atom = (Ecore_X_Atom *)data; + + if (atom) + profile = ecore_x_atom_name_get(atom[0]); + + return profile; +} + +EAPI void +ecore_x_e_comp_sync_supported_set(Ecore_X_Window root, + Eina_Bool enabled) +{ + Ecore_X_Window win; + + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (enabled) + { + win = ecore_x_window_new(root, 1, 2, 3, 4); + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + ecore_x_window_prop_xid_set(root, ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, &win, 1); + } + else + { + int ret; + + ret = + ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win, 1); + if ((ret == 1) && (win)) + { + ecore_x_window_prop_property_del( + root, + ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED); + ecore_x_window_free(win); + } + } +} + +EAPI Eina_Bool +ecore_x_e_comp_sync_supported_get(Ecore_X_Window root) +{ + Ecore_X_Window win, win2; + int ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + ret = + ecore_x_window_prop_xid_get(root, + ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win, 1); + if ((ret == 1) && (win)) + { + ret = + ecore_x_window_prop_xid_get(win, + ECORE_X_ATOM_E_COMP_SYNC_SUPPORTED, + ECORE_X_ATOM_WINDOW, + &win2, 1); + if ((ret == 1) && (win2 == win)) + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI void +ecore_x_e_comp_sync_begin_send(Ecore_X_Window win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_BEGIN; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 0; // later + xev.xclient.data.l[2] = 0; // later + xev.xclient.data.l[3] = 0; // later + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, win, False, + NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_comp_sync_end_send(Ecore_X_Window win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_END; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 0; // later + xev.xclient.data.l[2] = 0; // later + xev.xclient.data.l[3] = 0; // later + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, win, False, + NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_comp_sync_cancel_send(Ecore_X_Window win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_SYNC_CANCEL; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 0; // later + xev.xclient.data.l[2] = 0; // later + xev.xclient.data.l[3] = 0; // later + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, win, False, + NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_comp_flush_send(Ecore_X_Window win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_FLUSH; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 0; // later + xev.xclient.data.l[2] = 0; // later + xev.xclient.data.l[3] = 0; // later + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, win, False, + NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_comp_dump_send(Ecore_X_Window win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_E_COMP_DUMP; + xev.xclient.format = 32; + xev.xclient.data.l[0] = win; + xev.xclient.data.l[1] = 0; // later + xev.xclient.data.l[2] = 0; // later + xev.xclient.data.l[3] = 0; // later + xev.xclient.data.l[4] = 0; // later + + XSendEvent(_ecore_x_disp, win, False, + NoEventMask, //SubstructureRedirectMask | SubstructureNotifyMask, + &xev); +} + +EAPI void +ecore_x_e_comp_pixmap_set(Ecore_X_Window win, + Ecore_X_Pixmap pixmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (pixmap) + ecore_x_window_prop_xid_set(win, ECORE_X_ATOM_E_COMP_PIXMAP, + ECORE_X_ATOM_PIXMAP, &pixmap, 1); + else + ecore_x_window_prop_property_del(win, pixmap); +} + +EAPI Ecore_X_Pixmap +ecore_x_e_comp_pixmap_get(Ecore_X_Window win) +{ + int ret = 0; + Ecore_X_Pixmap pixmap = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = + ecore_x_window_prop_xid_get(win, + ECORE_X_ATOM_E_COMP_PIXMAP, + ECORE_X_ATOM_PIXMAP, + &pixmap, 1); + if (ret != 1) + return 0; + + return pixmap; +} + +static Ecore_X_Atom +_ecore_x_e_indicator_atom_get(Ecore_X_Illume_Indicator_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_INDICATOR_STATE_ON: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_ON; + + case ECORE_X_ILLUME_INDICATOR_STATE_OFF: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Indicator_State +_ecore_x_e_indicator_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_ON) + return ECORE_X_ILLUME_INDICATOR_STATE_ON; + + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_OFF) + return ECORE_X_ILLUME_INDICATOR_STATE_OFF; + + return ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_indicator_state_set(Ecore_X_Window win, + Ecore_X_Illume_Indicator_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_indicator_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Indicator_State +ecore_x_e_illume_indicator_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE, + &atom, 1)) + return ECORE_X_ILLUME_INDICATOR_STATE_UNKNOWN; + + return _ecore_x_e_indicator_state_get(atom); +} + +EAPI void +ecore_x_e_illume_indicator_state_send(Ecore_X_Window win, + Ecore_X_Illume_Indicator_State state) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_E_ILLUME_INDICATOR_STATE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_x_e_indicator_atom_get(state), + 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_x_e_indicator_opacity_atom_get(Ecore_X_Illume_Indicator_Opacity_Mode mode) +{ + switch (mode) + { + case ECORE_X_ILLUME_INDICATOR_OPAQUE: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE; + + case ECORE_X_ILLUME_INDICATOR_TRANSLUCENT: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT; + + case ECORE_X_ILLUME_INDICATOR_TRANSPARENT: + return ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Indicator_Opacity_Mode +_ecore_x_e_indicator_opacity_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_OPAQUE) + return ECORE_X_ILLUME_INDICATOR_OPAQUE; + + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSLUCENT) + return ECORE_X_ILLUME_INDICATOR_TRANSLUCENT; + + if (atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_TRANSPARENT) + return ECORE_X_ILLUME_INDICATOR_TRANSPARENT; + + return ECORE_X_ILLUME_INDICATOR_OPACITY_UNKNOWN; +} + +EAPI void +ecore_x_e_illume_indicator_opacity_set(Ecore_X_Window win, + Ecore_X_Illume_Indicator_Opacity_Mode mode) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_indicator_opacity_atom_get(mode); + ecore_x_window_prop_atom_set(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Indicator_Opacity_Mode +ecore_x_e_illume_indicator_opacity_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE, + &atom, 1)) + return ECORE_X_ILLUME_INDICATOR_OPACITY_UNKNOWN; + + return _ecore_x_e_indicator_opacity_get(atom); +} + +EAPI void +ecore_x_e_illume_indicator_opacity_send(Ecore_X_Window win, + Ecore_X_Illume_Indicator_Opacity_Mode mode) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, + ECORE_X_ATOM_E_ILLUME_INDICATOR_OPACITY_MODE, + ECORE_X_EVENT_MASK_WINDOW_CONFIGURE, + _ecore_x_e_indicator_opacity_atom_get(mode), + 0, 0, 0, 0); +} + +static Ecore_X_Atom +_ecore_x_e_illume_window_state_atom_get(Ecore_X_Illume_Window_State state) +{ + switch (state) + { + case ECORE_X_ILLUME_WINDOW_STATE_NORMAL: + return ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL; + + case ECORE_X_ILLUME_WINDOW_STATE_FLOATING: + return ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING; + + default: + break; + } + return 0; +} + +static Ecore_X_Illume_Window_State +_ecore_x_e_illume_window_state_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_NORMAL) + return ECORE_X_ILLUME_WINDOW_STATE_NORMAL; + + if (atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE_FLOATING) + return ECORE_X_ILLUME_WINDOW_STATE_FLOATING; + + return ECORE_X_ILLUME_WINDOW_STATE_NORMAL; +} + +EAPI void +ecore_x_e_illume_window_state_set(Ecore_X_Window win, + Ecore_X_Illume_Window_State state) +{ + Ecore_X_Atom atom = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_e_illume_window_state_atom_get(state); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_E_ILLUME_WINDOW_STATE, + &atom, 1); +} + +EAPI Ecore_X_Illume_Window_State +ecore_x_e_illume_window_state_get(Ecore_X_Window win) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_atom_get(win, + ECORE_X_ATOM_E_ILLUME_WINDOW_STATE, + &atom, 1)) + return ECORE_X_ILLUME_WINDOW_STATE_NORMAL; + + return _ecore_x_e_illume_window_state_get(atom); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_error.c b/src/lib/ecore_x/xlib/ecore_x_error.c new file mode 100644 index 0000000000..f6eb075b54 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_error.c @@ -0,0 +1,126 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +static int _ecore_x_error_handle(Display *d, + XErrorEvent *ev); +static int _ecore_x_io_error_handle(Display *d); + +static void (*_error_func)(void *data) = NULL; +static void *_error_data = NULL; +static void (*_io_error_func)(void *data) = NULL; +static void *_io_error_data = NULL; +static int _error_request_code = 0; +static int _error_code = 0; +static Ecore_X_ID _error_resource_id = 0; + +/** + * Set the error handler. + * @param func The error handler function + * @param data The data to be passed to the handler function + * + * Set the X error handler function + */ +EAPI void +ecore_x_error_handler_set(void (*func)(void *data), + const void *data) +{ + _error_func = func; + _error_data = (void *)data; +} + +/** + * Set the I/O error handler. + * @param func The I/O error handler function + * @param data The data to be passed to the handler function + * + * Set the X I/O error handler function + */ +EAPI void +ecore_x_io_error_handler_set(void (*func)(void *data), + const void *data) +{ + _io_error_func = func; + _io_error_data = (void *)data; +} + +/** + * Get the request code that caused the error. + * @return The request code causing the X error + * + * Return the X request code that caused the last X error + */ +EAPI int +ecore_x_error_request_get(void) +{ + return _error_request_code; +} + +/** + * Get the error code from the error. + * @return The error code from the X error + * + * Return the error code from the last X error + */ +//FIXME: Use Ecore_X_Error_Code type when 2.0 is released +EAPI int +ecore_x_error_code_get(void) +{ + return _error_code; +} + +/** + * Get the resource id that caused the error. + * @return The resource id causing the X error + * + * Return the X resource id that caused the last X error + */ +EAPI Ecore_X_ID +ecore_x_error_resource_id_get(void) +{ + return _error_resource_id; +} + +void +_ecore_x_error_handler_init(void) +{ + XSetErrorHandler((XErrorHandler)_ecore_x_error_handle); + XSetIOErrorHandler((XIOErrorHandler)_ecore_x_io_error_handle); +} + +static int +_ecore_x_error_handle(Display *d, + XErrorEvent *ev) +{ + if (d == _ecore_x_disp) + { + _error_request_code = ev->request_code; + _error_code = ev->error_code; + _error_resource_id = ev->resourceid; + if (_error_func) + _error_func(_error_data); + } + return 0; +} + +static int +_ecore_x_io_error_handle(Display *d) +{ + if (d == _ecore_x_disp) + { + if (_io_error_func) + _io_error_func(_io_error_data); + else + exit(-1); + } + + return 0; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_events.c b/src/lib/ecore_x/xlib/ecore_x_events.c new file mode 100644 index 0000000000..9ce7163d53 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_events.c @@ -0,0 +1,2523 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <langinfo.h> + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +/** OpenBSD does not define CODESET + * FIXME ?? + */ + +#ifndef CODESET +#define CODESET "INVALID" +#endif /* ifndef CODESET */ + +typedef struct _Ecore_X_Mouse_Down_Info +{ + EINA_INLIST; + int dev; + Window last_win; + Window last_last_win; + Window last_event_win; + Window last_last_event_win; + Time last_time; + Time last_last_time; + Eina_Bool did_double : 1; + Eina_Bool did_triple : 1; +} Ecore_X_Mouse_Down_Info; + +static int _ecore_x_last_event_mouse_move = 0; +static Ecore_Event *_ecore_x_last_event_mouse_move_event = NULL; +static Eina_Inlist *_ecore_x_mouse_down_info_list = NULL; + +static void +_ecore_x_mouse_down_info_clear(void) +{ + Eina_Inlist *l = _ecore_x_mouse_down_info_list; + Ecore_X_Mouse_Down_Info *info = NULL; + while (l) + { + info = EINA_INLIST_CONTAINER_GET(l, Ecore_X_Mouse_Down_Info); + l = eina_inlist_remove(l, l); + free(info); + } + _ecore_x_mouse_down_info_list = NULL; +} + +void +_ecore_x_events_init(void) +{ + //Actually, Nothing to do. +} + +void +_ecore_x_events_shutdown(void) +{ + _ecore_x_mouse_down_info_clear(); +} + +static Ecore_X_Mouse_Down_Info * +_ecore_x_mouse_down_info_get(int dev) +{ + Eina_Inlist *l = _ecore_x_mouse_down_info_list; + Ecore_X_Mouse_Down_Info *info = NULL; + + //Return the exist info + EINA_INLIST_FOREACH(l, info) + if (info->dev == dev) return info; + + //New Device. Add it. + info = calloc(1, sizeof(Ecore_X_Mouse_Down_Info)); + if (!info) return NULL; + + info->dev = dev; + l = eina_inlist_append(l, (Eina_Inlist *)info); + _ecore_x_mouse_down_info_list = l; + return info; +} + +static void +_ecore_x_event_free_mouse_move(void *data EINA_UNUSED, + void *ev) +{ + Ecore_Event_Mouse_Move *e; + + e = ev; + if (_ecore_x_last_event_mouse_move) + { + _ecore_x_last_event_mouse_move_event = NULL; + _ecore_x_last_event_mouse_move = 0; + } + + free(e); +} + +EAPI void +ecore_x_event_mask_set(Ecore_X_Window w, + Ecore_X_Event_Mask mask) +{ + XWindowAttributes attr; + XSetWindowAttributes s_attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!w) + w = DefaultRootWindow(_ecore_x_disp); + + memset(&attr, 0, sizeof(XWindowAttributes)); + XGetWindowAttributes(_ecore_x_disp, w, &attr); + s_attr.event_mask = mask | attr.your_event_mask; + XChangeWindowAttributes(_ecore_x_disp, w, CWEventMask, &s_attr); +} + +EAPI void +ecore_x_event_mask_unset(Ecore_X_Window w, + Ecore_X_Event_Mask mask) +{ + XWindowAttributes attr; + XSetWindowAttributes s_attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!w) + w = DefaultRootWindow(_ecore_x_disp); + + memset(&attr, 0, sizeof(XWindowAttributes)); + XGetWindowAttributes(_ecore_x_disp, w, &attr); + s_attr.event_mask = attr.your_event_mask & ~mask; + XChangeWindowAttributes(_ecore_x_disp, w, CWEventMask, &s_attr); +} + +static void +_ecore_x_event_free_xdnd_enter(void *data EINA_UNUSED, + void *ev) +{ + Ecore_X_Event_Xdnd_Enter *e; + int i; + + e = ev; + for (i = 0; i < e->num_types; i++) + XFree(e->types[i]); + free(e->types); + free(e); +} + +static void +_ecore_x_event_free_selection_notify(void *data EINA_UNUSED, + void *ev) +{ + Ecore_X_Event_Selection_Notify *e; + Ecore_X_Selection_Data *sel; + + e = ev; + sel = e->data; + if (sel->free) + sel->free(sel); + + free(e->target); + free(e); +} + +static unsigned int +_ecore_x_event_modifiers(unsigned int state) +{ + unsigned int modifiers = 0; + + if (state & ECORE_X_MODIFIER_SHIFT) + modifiers |= ECORE_EVENT_MODIFIER_SHIFT; + + if (state & ECORE_X_MODIFIER_CTRL) + modifiers |= ECORE_EVENT_MODIFIER_CTRL; + + if (state & ECORE_X_MODIFIER_ALT) + modifiers |= ECORE_EVENT_MODIFIER_ALT; + + if (state & ECORE_X_MODIFIER_WIN) + modifiers |= ECORE_EVENT_MODIFIER_WIN; + + if (state & ECORE_X_MODIFIER_ALTGR) + modifiers |= ECORE_EVENT_MODIFIER_ALTGR; + + if (state & ECORE_X_LOCK_SCROLL) + modifiers |= ECORE_EVENT_LOCK_SCROLL; + + if (state & ECORE_X_LOCK_NUM) + modifiers |= ECORE_EVENT_LOCK_NUM; + + if (state & ECORE_X_LOCK_CAPS) + modifiers |= ECORE_EVENT_LOCK_CAPS; + + if (state & ECORE_X_LOCK_SHIFT) + modifiers |= ECORE_EVENT_LOCK_SHIFT; + + return modifiers; +} + +void +_ecore_mouse_move(unsigned int timestamp, + unsigned int xmodifiers, + int x, + int y, + int x_root, + int y_root, + unsigned int event_window, + unsigned int window, + unsigned int root_win, + int same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + double mx, + double my, + double mrx, + double mry) +{ + Ecore_Event_Mouse_Move *e; + Ecore_Event *event; + + e = malloc(sizeof(Ecore_Event_Mouse_Move)); + if (!e) + return; + + e->window = window; + e->root_window = root_win; + e->timestamp = timestamp; + e->same_screen = same_screen; + e->event_window = event_window; + + e->modifiers = _ecore_x_event_modifiers(xmodifiers); + e->x = x; + e->y = y; + e->root.x = x_root; + e->root.y = y_root; + + e->multi.device = dev; + e->multi.radius = (radx + rady) / 2; + e->multi.radius_x = radx; + e->multi.radius_y = rady; + e->multi.pressure = pressure; + e->multi.angle = angle; + e->multi.x = mx; + e->multi.y = my; + e->multi.root.x = mrx; + e->multi.root.y = mry; + + event = ecore_event_add(ECORE_EVENT_MOUSE_MOVE, + e, + _ecore_x_event_free_mouse_move, + NULL); + + _ecore_x_event_last_time = timestamp; + _ecore_x_event_last_win = window; + _ecore_x_event_last_root_x = x_root; + _ecore_x_event_last_root_y = y_root; + + _ecore_x_last_event_mouse_move_event = event; +} + +static void +_ecore_key_press(int event, + XKeyEvent *xevent) +{ + Ecore_Event_Key *e; + char *compose = NULL; + char *tmp = NULL; + char *keyname; + char *key; + char keyname_buffer[256]; + char compose_buffer[256]; + KeySym sym; + XComposeStatus status; + int val; + + _ecore_x_last_event_mouse_move = 0; + keyname = XKeysymToString(_ecore_x_XKeycodeToKeysym(xevent->display, + xevent->keycode, 0)); + if (!keyname) + { + snprintf(keyname_buffer, + sizeof(keyname_buffer), + "Keycode-%i", + xevent->keycode); + keyname = keyname_buffer; + } + + sym = 0; + key = NULL; + compose = NULL; + val = XLookupString(xevent, + compose_buffer, + sizeof(compose_buffer), + &sym, + &status); + if (val > 0) + { + compose_buffer[val] = 0; + compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8", + compose_buffer); + if (!compose) + ERR("Ecore_X cannot convert input key string '%s' to UTF-8. " + "Is Eina built with iconv support?", compose_buffer); + tmp = compose; + } + + key = XKeysymToString(sym); + if (!key) + key = keyname; + + e = + malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + + (compose ? strlen(compose) : 0) + 3); + if (!e) + goto on_error; + + e->keyname = (char *)(e + 1); + e->key = e->keyname + strlen(keyname) + 1; + e->compose = (compose) ? e->key + strlen(key) + 1 : NULL; + e->string = e->compose; + + strcpy((char *)e->keyname, keyname); + strcpy((char *)e->key, key); + if (compose) + strcpy((char *)e->compose, compose); + + e->modifiers = _ecore_x_event_modifiers(xevent->state); + + e->timestamp = xevent->time; + e->window = xevent->subwindow ? xevent->subwindow : xevent->window; + e->event_window = xevent->window; + e->same_screen = xevent->same_screen; + e->root_window = xevent->root; + + ecore_event_add(event, e, NULL, NULL); + + _ecore_x_event_last_time = e->timestamp; + +on_error: + if (tmp) + free(tmp); +} + +Ecore_Event_Mouse_Button * +_ecore_mouse_button(int event, + unsigned int timestamp, + unsigned int xmodifiers, + unsigned int buttons, + int x, + int y, + int x_root, + int y_root, + unsigned int event_window, + unsigned int window, + unsigned int root_win, + int same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + double mx, + double my, + double mrx, + double mry) +{ + Ecore_Event_Mouse_Button *e; + + e = malloc(sizeof(Ecore_Event_Mouse_Button)); + if (!e) + return NULL; + + e->window = window; + e->root_window = root_win; + e->timestamp = timestamp; + e->same_screen = same_screen; + e->event_window = event_window; + + e->buttons = buttons; + e->modifiers = _ecore_x_event_modifiers(xmodifiers); + e->double_click = 0; + e->triple_click = 0; + e->x = x; + e->y = y; + e->root.x = x_root; + e->root.y = y_root; + + Ecore_X_Mouse_Down_Info *down_info = _ecore_x_mouse_down_info_get(dev); + + if (down_info) + { + if ((event == ECORE_EVENT_MOUSE_BUTTON_DOWN) && + down_info->did_triple) + { + down_info->last_win = 0; + down_info->last_last_win = 0; + down_info->last_event_win = 0; + down_info->last_last_event_win = 0; + down_info->last_time = 0; + down_info->last_last_time = 0; + } + if (event_window == window) + { + if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN) + { + //Check Double Clicked + if (((int)(timestamp - down_info->last_time) <= + (int)(1000 * _ecore_x_double_click_time)) && + (window == down_info->last_win) && + (event_window == down_info->last_event_win)) + { + e->double_click = 1; + down_info->did_double = EINA_TRUE; + } + else + { + down_info->did_double = EINA_FALSE; + down_info->did_triple = EINA_FALSE; + } + + //Check Triple Clicked + if (((int)(timestamp - down_info->last_last_time) <= + (int)(2 * 1000 * _ecore_x_double_click_time)) && + (window == down_info->last_win) && + (window == down_info->last_last_win) && + (event_window == down_info->last_event_win) && + (event_window == down_info->last_last_event_win) + ) + { + e->triple_click = 1; + down_info->did_triple = EINA_TRUE; + } + else + { + down_info->did_triple = EINA_FALSE; + } + } + else + { + if (down_info->did_double) + e->double_click = 1; + if (down_info->did_triple) + e->triple_click = 1; + } + } + } + + /* NB: Block commented out as _ecore_x_mouse_up_count appears to have + * no use. The variable is also commented out above. This code block is + * the only place that this variable is used, and appears to serve no + * purpose. - dh + if (event == ECORE_EVENT_MOUSE_BUTTON_DOWN + && !e->double_click + && !e->triple_click) + _ecore_x_mouse_up_count = 0; + */ + + e->multi.device = dev; + e->multi.radius = (radx + rady) / 2; + e->multi.radius_x = radx; + e->multi.radius_y = rady; + e->multi.pressure = pressure; + e->multi.angle = angle; + e->multi.x = mx; + e->multi.y = my; + e->multi.root.x = mrx; + e->multi.root.y = mry; + + _ecore_x_event_last_time = e->timestamp; + _ecore_x_event_last_win = e->window; + _ecore_x_event_last_root_x = x_root; + _ecore_x_event_last_root_y = y_root; + + ecore_event_add(event, e, NULL, NULL); + + if ((down_info) && + (event == ECORE_EVENT_MOUSE_BUTTON_DOWN) && + (window == event_window) && + (!down_info->did_triple)) + { + down_info->last_last_win = down_info->last_win; + down_info->last_win = window; + down_info->last_last_event_win = down_info->last_event_win; + down_info->last_event_win = event_window; + down_info->last_last_time = down_info->last_time; + down_info->last_time = timestamp; + } + + return e; +} + +void +_ecore_x_event_handle_any_event(XEvent *xevent) +{ + XEvent *ev = malloc(sizeof(XEvent)); + if (!ev) return; + memcpy(ev, xevent, sizeof(XEvent)); + ecore_event_add(ECORE_X_EVENT_ANY, ev, NULL, NULL); +} + +void +_ecore_x_event_handle_key_press(XEvent *xevent) +{ + _ecore_key_press(ECORE_EVENT_KEY_DOWN, (XKeyEvent *)xevent); +} + +void +_ecore_x_event_handle_key_release(XEvent *xevent) +{ + _ecore_key_press(ECORE_EVENT_KEY_UP, (XKeyEvent *)xevent); +} + +void +_ecore_x_event_handle_button_press(XEvent *xevent) +{ + int i; + + _ecore_x_last_event_mouse_move = 0; + if ((xevent->xbutton.button > 3) && (xevent->xbutton.button < 8)) + { + Ecore_Event_Mouse_Wheel *e; + + e = malloc(sizeof(Ecore_Event_Mouse_Wheel)); + if (!e) + return; + + e->timestamp = xevent->xbutton.time; + e->modifiers = _ecore_x_event_modifiers(xevent->xbutton.state); + switch (xevent->xbutton.button) + { + case 4: e->direction = 0; e->z = -1; break; + + case 5: e->direction = 0; e->z = 1; break; + + case 6: e->direction = 1; e->z = -1; break; + + case 7: e->direction = 1; e->z = 1; break; + + default: e->direction = 0; e->z = 0; break; + } + + e->x = xevent->xbutton.x; + e->y = xevent->xbutton.y; + e->root.x = xevent->xbutton.x_root; + e->root.y = xevent->xbutton.y_root; + + if (xevent->xbutton.subwindow) + e->window = xevent->xbutton.subwindow; + else + e->window = xevent->xbutton.window; + + e->event_window = xevent->xbutton.window; + e->same_screen = xevent->xbutton.same_screen; + e->root_window = xevent->xbutton.root; + + _ecore_x_event_last_time = e->timestamp; + _ecore_x_event_last_win = e->window; + _ecore_x_event_last_root_x = xevent->xbutton.x_root; + _ecore_x_event_last_root_y = xevent->xbutton.y_root; + ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, e, NULL, NULL); + + for (i = 0; i < _ecore_window_grabs_num; i++) + { + if ((_ecore_window_grabs[i] == xevent->xbutton.window) || + (_ecore_window_grabs[i] == xevent->xbutton.subwindow)) + { + Eina_Bool replay = EINA_FALSE; + + if (_ecore_window_grab_replay_func) + replay = _ecore_window_grab_replay_func( + _ecore_window_grab_replay_data, + ECORE_EVENT_MOUSE_WHEEL, + e); + + if (replay) + XAllowEvents(xevent->xbutton.display, + ReplayPointer, xevent->xbutton.time); + else + XAllowEvents(xevent->xbutton.display, + AsyncPointer, xevent->xbutton.time); + + break; + } + } + } + else + { + { + _ecore_mouse_move(xevent->xbutton.time, xevent->xbutton.state, + xevent->xbutton.x, xevent->xbutton.y, + xevent->xbutton.x_root, xevent->xbutton.y_root, + xevent->xbutton.window, + (xevent->xbutton.subwindow ? xevent->xbutton. + subwindow : xevent->xbutton.window), + xevent->xbutton.root, + xevent->xbutton.same_screen, + 0, 1, 1, + 1.0, // pressure + 0.0, // angle + xevent->xbutton.x, xevent->xbutton.y, + xevent->xbutton.x_root, xevent->xbutton.y_root); + } + { + Ecore_Event_Mouse_Button *e; + int event_window; + int window; + + window = + (xevent->xbutton.subwindow ? xevent->xbutton.subwindow : xevent-> + xbutton.window); + event_window = xevent->xbutton.window; + + e = _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_DOWN, + xevent->xbutton.time, + xevent->xbutton.state, + xevent->xbutton.button, + xevent->xbutton.x, + xevent->xbutton.y, + xevent->xbutton.x_root, + xevent->xbutton.y_root, + event_window, + window, + xevent->xbutton.root, + xevent->xbutton.same_screen, + 0, + 1, + 1, + 1.0, +// pressure + 0.0, +// angle + xevent->xbutton.x, + xevent->xbutton.y, + xevent->xbutton.x_root, + xevent->xbutton.y_root); + if (e) + for (i = 0; i < _ecore_window_grabs_num; i++) + { + if ((_ecore_window_grabs[i] == xevent->xbutton.window) || + (_ecore_window_grabs[i] == xevent->xbutton.subwindow)) + { + Eina_Bool replay = EINA_FALSE; + + if (_ecore_window_grab_replay_func) + replay = _ecore_window_grab_replay_func( + _ecore_window_grab_replay_data, + ECORE_EVENT_MOUSE_BUTTON_DOWN, + e); + + if (replay) + XAllowEvents(xevent->xbutton.display, + ReplayPointer, xevent->xbutton.time); + else + XAllowEvents(xevent->xbutton.display, + AsyncPointer, xevent->xbutton.time); + + break; + } + } + } + } +} + +void +_ecore_x_event_handle_button_release(XEvent *xevent) +{ + _ecore_x_last_event_mouse_move = 0; + /* filter out wheel buttons */ + if ((xevent->xbutton.button <= 3) || (xevent->xbutton.button > 7)) + { + _ecore_mouse_move(xevent->xbutton.time, xevent->xbutton.state, + xevent->xbutton.x, xevent->xbutton.y, + xevent->xbutton.x_root, xevent->xbutton.y_root, + xevent->xbutton.window, + (xevent->xbutton.subwindow ? xevent->xbutton. + subwindow : xevent->xbutton.window), + xevent->xbutton.root, + xevent->xbutton.same_screen, + 0, 1, 1, + 1.0, // pressure + 0.0, // angle + xevent->xbutton.x, xevent->xbutton.y, + xevent->xbutton.x_root, xevent->xbutton.y_root); + + _ecore_mouse_button(ECORE_EVENT_MOUSE_BUTTON_UP, + xevent->xbutton.time, xevent->xbutton.state, + xevent->xbutton.button, + xevent->xbutton.x, xevent->xbutton.y, + xevent->xbutton.x_root, xevent->xbutton.y_root, + xevent->xbutton.window, + (xevent->xbutton.subwindow ? xevent->xbutton. + subwindow : xevent->xbutton.window), + xevent->xbutton.root, + xevent->xbutton.same_screen, + 0, 1, 1, + 1.0, // pressure + 0.0, // angle + xevent->xbutton.x, xevent->xbutton.y, + xevent->xbutton.x_root, xevent->xbutton.y_root); + } +} + +void +_ecore_x_event_handle_motion_notify(XEvent *xevent) +{ +/* + if (_ecore_x_last_event_mouse_move) + { + ecore_event_del(_ecore_x_last_event_mouse_move_event); + _ecore_x_last_event_mouse_move = 0; + _ecore_x_last_event_mouse_move_event = NULL; + } + */ + _ecore_mouse_move(xevent->xmotion.time, xevent->xmotion.state, + xevent->xmotion.x, xevent->xmotion.y, + xevent->xmotion.x_root, xevent->xmotion.y_root, + xevent->xmotion.window, + (xevent->xmotion.subwindow ? xevent->xmotion.subwindow : + xevent->xmotion.window), + xevent->xmotion.root, + xevent->xmotion.same_screen, + 0, 1, 1, + 1.0, // pressure + 0.0, // angle + xevent->xmotion.x, xevent->xmotion.y, + xevent->xmotion.x_root, xevent->xmotion.y_root); + + _ecore_x_last_event_mouse_move = 1; + + /* Xdnd handling */ + _ecore_x_dnd_drag(xevent->xmotion.root, + xevent->xmotion.x_root, + xevent->xmotion.y_root); +} + +void +_ecore_x_event_handle_enter_notify(XEvent *xevent) +{ + _ecore_x_last_event_mouse_move = 0; + { + _ecore_mouse_move(xevent->xcrossing.time, xevent->xcrossing.state, + xevent->xcrossing.x, xevent->xcrossing.y, + xevent->xcrossing.x_root, xevent->xcrossing.y_root, + xevent->xcrossing.window, + (xevent->xcrossing.subwindow ? xevent->xcrossing. + subwindow : xevent->xcrossing.window), + xevent->xcrossing.root, + xevent->xcrossing.same_screen, + 0, 1, 1, + 1.0, // pressure + 0.0, // angle + xevent->xcrossing.x, xevent->xcrossing.y, + xevent->xcrossing.x_root, xevent->xcrossing.y_root); + } + { + Ecore_X_Event_Mouse_In *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_In)); + if (!e) + return; + + e->modifiers = _ecore_x_event_modifiers(xevent->xcrossing.state); + e->x = xevent->xcrossing.x; + e->y = xevent->xcrossing.y; + e->root.x = xevent->xcrossing.x_root; + e->root.y = xevent->xcrossing.y_root; + if (xevent->xcrossing.subwindow) + e->win = xevent->xcrossing.subwindow; + else + e->win = xevent->xcrossing.window; + + e->same_screen = xevent->xcrossing.same_screen; + e->root_win = xevent->xcrossing.root; + e->event_win = xevent->xcrossing.window; + + if (xevent->xcrossing.mode == NotifyNormal) + e->mode = ECORE_X_EVENT_MODE_NORMAL; + else if (xevent->xcrossing.mode == NotifyGrab) + e->mode = ECORE_X_EVENT_MODE_GRAB; + else if (xevent->xcrossing.mode == NotifyUngrab) + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + + if (xevent->xcrossing.detail == NotifyAncestor) + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + else if (xevent->xcrossing.detail == NotifyVirtual) + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + else if (xevent->xcrossing.detail == NotifyInferior) + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + else if (xevent->xcrossing.detail == NotifyNonlinear) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + else if (xevent->xcrossing.detail == NotifyNonlinearVirtual) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + + e->time = xevent->xcrossing.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_MOUSE_IN, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_leave_notify(XEvent *xevent) +{ + _ecore_x_last_event_mouse_move = 0; + { + _ecore_mouse_move(xevent->xcrossing.time, xevent->xcrossing.state, + xevent->xcrossing.x, xevent->xcrossing.y, + xevent->xcrossing.x_root, xevent->xcrossing.y_root, + xevent->xcrossing.window, + (xevent->xcrossing.subwindow ? xevent->xcrossing. + subwindow : xevent->xcrossing.window), + xevent->xcrossing.root, + xevent->xcrossing.same_screen, + 0, 1, 1, + 1.0, // pressure + 0.0, // angle + xevent->xcrossing.x, xevent->xcrossing.y, + xevent->xcrossing.x_root, xevent->xcrossing.y_root); + } + { + Ecore_X_Event_Mouse_Out *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out)); + if (!e) + return; + + e->modifiers = _ecore_x_event_modifiers(xevent->xcrossing.state); + e->x = xevent->xcrossing.x; + e->y = xevent->xcrossing.y; + e->root.x = xevent->xcrossing.x_root; + e->root.y = xevent->xcrossing.y_root; + if (xevent->xcrossing.subwindow) + e->win = xevent->xcrossing.subwindow; + else + e->win = xevent->xcrossing.window; + + e->same_screen = xevent->xcrossing.same_screen; + e->root_win = xevent->xcrossing.root; + e->event_win = xevent->xcrossing.window; + + if (xevent->xcrossing.mode == NotifyNormal) + e->mode = ECORE_X_EVENT_MODE_NORMAL; + else if (xevent->xcrossing.mode == NotifyGrab) + e->mode = ECORE_X_EVENT_MODE_GRAB; + else if (xevent->xcrossing.mode == NotifyUngrab) + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + + if (xevent->xcrossing.detail == NotifyAncestor) + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + else if (xevent->xcrossing.detail == NotifyVirtual) + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + else if (xevent->xcrossing.detail == NotifyInferior) + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + else if (xevent->xcrossing.detail == NotifyNonlinear) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + else if (xevent->xcrossing.detail == NotifyNonlinearVirtual) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + + e->time = xevent->xcrossing.time; + _ecore_x_event_last_time = e->time; + _ecore_x_event_last_win = e->win; + _ecore_x_event_last_root_x = e->root.x; + _ecore_x_event_last_root_y = e->root.y; + ecore_event_add(ECORE_X_EVENT_MOUSE_OUT, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_focus_in(XEvent *xevent) +{ + Ecore_X_Event_Window_Focus_In *e; + + _ecore_x_last_event_mouse_move = 0; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_In)); + if (!e) + return; + + e->win = xevent->xfocus.window; + + if (xevent->xfocus.mode == NotifyNormal) + e->mode = ECORE_X_EVENT_MODE_NORMAL; + else if (xevent->xfocus.mode == NotifyWhileGrabbed) + e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED; + else if (xevent->xfocus.mode == NotifyGrab) + e->mode = ECORE_X_EVENT_MODE_GRAB; + else if (xevent->xfocus.mode == NotifyUngrab) + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + + if (xevent->xfocus.detail == NotifyAncestor) + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + else if (xevent->xfocus.detail == NotifyVirtual) + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + else if (xevent->xfocus.detail == NotifyInferior) + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + else if (xevent->xfocus.detail == NotifyNonlinear) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + else if (xevent->xfocus.detail == NotifyNonlinearVirtual) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + else if (xevent->xfocus.detail == NotifyPointer) + e->detail = ECORE_X_EVENT_DETAIL_POINTER; + else if (xevent->xfocus.detail == NotifyPointerRoot) + e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT; + else if (xevent->xfocus.detail == NotifyDetailNone) + e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE; + + e->time = _ecore_x_event_last_time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, e, NULL, NULL); +} + +void +_ecore_x_event_handle_focus_out(XEvent *xevent) +{ + Ecore_X_Event_Window_Focus_Out *e; + + _ecore_x_last_event_mouse_move = 0; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Focus_Out)); + if (!e) + return; + + e->win = xevent->xfocus.window; + + if (xevent->xfocus.mode == NotifyNormal) + e->mode = ECORE_X_EVENT_MODE_NORMAL; + else if (xevent->xfocus.mode == NotifyWhileGrabbed) + e->mode = ECORE_X_EVENT_MODE_WHILE_GRABBED; + else if (xevent->xfocus.mode == NotifyGrab) + e->mode = ECORE_X_EVENT_MODE_GRAB; + else if (xevent->xfocus.mode == NotifyUngrab) + e->mode = ECORE_X_EVENT_MODE_UNGRAB; + + if (xevent->xfocus.detail == NotifyAncestor) + e->detail = ECORE_X_EVENT_DETAIL_ANCESTOR; + else if (xevent->xfocus.detail == NotifyVirtual) + e->detail = ECORE_X_EVENT_DETAIL_VIRTUAL; + else if (xevent->xfocus.detail == NotifyInferior) + e->detail = ECORE_X_EVENT_DETAIL_INFERIOR; + else if (xevent->xfocus.detail == NotifyNonlinear) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR; + else if (xevent->xfocus.detail == NotifyNonlinearVirtual) + e->detail = ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL; + else if (xevent->xfocus.detail == NotifyPointer) + e->detail = ECORE_X_EVENT_DETAIL_POINTER; + else if (xevent->xfocus.detail == NotifyPointerRoot) + e->detail = ECORE_X_EVENT_DETAIL_POINTER_ROOT; + else if (xevent->xfocus.detail == NotifyDetailNone) + e->detail = ECORE_X_EVENT_DETAIL_DETAIL_NONE; + + e->time = _ecore_x_event_last_time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, e, NULL, NULL); +} + +void +_ecore_x_event_handle_keymap_notify(XEvent *xevent EINA_UNUSED) +{ + _ecore_x_last_event_mouse_move = 0; + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_expose(XEvent *xevent) +{ + Ecore_X_Event_Window_Damage *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Damage)); + if (!e) + return; + + e->win = xevent->xexpose.window; + e->time = _ecore_x_event_last_time; + e->x = xevent->xexpose.x; + e->y = xevent->xexpose.y; + e->w = xevent->xexpose.width; + e->h = xevent->xexpose.height; + e->count = xevent->xexpose.count; + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_graphics_expose(XEvent *xevent) +{ + Ecore_X_Event_Window_Damage *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Damage)); + if (!e) + return; + + e->win = xevent->xgraphicsexpose.drawable; + e->time = _ecore_x_event_last_time; + e->x = xevent->xgraphicsexpose.x; + e->y = xevent->xgraphicsexpose.y; + e->w = xevent->xgraphicsexpose.width; + e->h = xevent->xgraphicsexpose.height; + e->count = xevent->xgraphicsexpose.count; + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_visibility_notify(XEvent *xevent) +{ + _ecore_x_last_event_mouse_move = 0; +// if (xevent->xvisibility.state != VisibilityPartiallyObscured) + { + Ecore_X_Event_Window_Visibility_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Visibility_Change)); + if (!e) + return; + + e->win = xevent->xvisibility.window; + e->time = _ecore_x_event_last_time; + if (xevent->xvisibility.state == VisibilityFullyObscured) + e->fully_obscured = 1; + else + e->fully_obscured = 0; + + ecore_event_add(ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_create_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Create *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Create)); + if (!e) + return; + + e->win = xevent->xcreatewindow.window; + e->parent = xevent->xcreatewindow.parent; + if (xevent->xcreatewindow.override_redirect) + e->override = 1; + else + e->override = 0; + + e->x = xevent->xcreatewindow.x; + e->y = xevent->xcreatewindow.y; + e->w = xevent->xcreatewindow.width; + e->h = xevent->xcreatewindow.height; + e->border = xevent->xcreatewindow.border_width; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_CREATE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_destroy_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Destroy *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy)); + if (!e) + return; + + e->win = xevent->xdestroywindow.window; + e->event_win = xevent->xdestroywindow.event; + e->time = _ecore_x_event_last_time; + if (e->win == _ecore_x_event_last_win) + _ecore_x_event_last_win = 0; + + ecore_event_add(ECORE_X_EVENT_WINDOW_DESTROY, e, NULL, NULL); +} + +void +_ecore_x_event_handle_unmap_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Hide *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Hide)); + if (!e) + return; + + e->win = xevent->xunmap.window; + e->event_win = xevent->xunmap.event; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_HIDE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_map_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Show *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Show)); + if (!e) + return; + + e->win = xevent->xmap.window; + e->event_win = xevent->xmap.event; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW, e, NULL, NULL); +} + +void +_ecore_x_event_handle_map_request(XEvent *xevent) +{ + Ecore_X_Event_Window_Show_Request *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Show_Request)); + if (!e) + return; + + e->win = xevent->xmaprequest.window; + e->time = _ecore_x_event_last_time; + e->parent = xevent->xmaprequest.parent; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHOW_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_reparent_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Reparent *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent)); + if (!e) + return; + + e->win = xevent->xreparent.window; + e->event_win = xevent->xreparent.event; + e->parent = xevent->xreparent.parent; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_REPARENT, e, NULL, NULL); +} + +void +_ecore_x_event_handle_configure_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Configure *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Configure)); + if (!e) + return; + + e->win = xevent->xconfigure.window; + e->event_win = xevent->xconfigure.event; + e->abovewin = xevent->xconfigure.above; + e->x = xevent->xconfigure.x; + e->y = xevent->xconfigure.y; + e->w = xevent->xconfigure.width; + e->h = xevent->xconfigure.height; + e->border = xevent->xconfigure.border_width; + e->override = xevent->xconfigure.override_redirect; + e->from_wm = xevent->xconfigure.send_event; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_configure_request(XEvent *xevent) +{ + Ecore_X_Event_Window_Configure_Request *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request)); + if (!e) + return; + + e->win = xevent->xconfigurerequest.window; + e->parent_win = xevent->xconfigurerequest.parent; + e->abovewin = xevent->xconfigurerequest.above; + e->x = xevent->xconfigurerequest.x; + e->y = xevent->xconfigurerequest.y; + e->w = xevent->xconfigurerequest.width; + e->h = xevent->xconfigurerequest.height; + e->border = xevent->xconfigurerequest.border_width; + e->value_mask = xevent->xconfigurerequest.value_mask; + e->time = _ecore_x_event_last_time; + + if (xevent->xconfigurerequest.detail == Above) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else if (xevent->xconfigurerequest.detail == Below) + e->detail = ECORE_X_WINDOW_STACK_BELOW; + else if (xevent->xconfigurerequest.detail == TopIf) + e->detail = ECORE_X_WINDOW_STACK_TOP_IF; + else if (xevent->xconfigurerequest.detail == BottomIf) + e->detail = ECORE_X_WINDOW_STACK_BOTTOM_IF; + else if (xevent->xconfigurerequest.detail == Opposite) + e->detail = ECORE_X_WINDOW_STACK_OPPOSITE; + + ecore_event_add(ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gravity_notify(XEvent *xevent EINA_UNUSED) +{ + _ecore_x_last_event_mouse_move = 0; + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_resize_request(XEvent *xevent) +{ + Ecore_X_Event_Window_Resize_Request *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Resize_Request)); + if (!e) + return; + + e->win = xevent->xresizerequest.window; + e->w = xevent->xresizerequest.width; + e->h = xevent->xresizerequest.height; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_circulate_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Stack *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Stack)); + if (!e) + return; + + e->win = xevent->xcirculate.window; + e->event_win = xevent->xcirculate.event; + if (xevent->xcirculate.place == PlaceOnTop) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else + e->detail = ECORE_X_WINDOW_STACK_BELOW; + + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_STACK, e, NULL, NULL); +} + +void +_ecore_x_event_handle_circulate_request(XEvent *xevent) +{ + Ecore_X_Event_Window_Stack_Request *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Stack_Request)); + if (!e) + return; + + e->win = xevent->xcirculaterequest.window; + e->parent = xevent->xcirculaterequest.parent; + if (xevent->xcirculaterequest.place == PlaceOnTop) + e->detail = ECORE_X_WINDOW_STACK_ABOVE; + else + e->detail = ECORE_X_WINDOW_STACK_BELOW; + + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_STACK_REQUEST, e, NULL, NULL); +} + +void +_ecore_x_event_handle_property_notify(XEvent *xevent) +{ + _ecore_x_last_event_mouse_move = 0; + { + Ecore_X_Event_Window_Property *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Property)); + if (!e) + return; + + e->win = xevent->xproperty.window; + e->atom = xevent->xproperty.atom; + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROPERTY, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_selection_clear(XEvent *xevent) +{ +// Ecore_X_Selection_Intern *d; + Ecore_X_Event_Selection_Clear *e; + Ecore_X_Atom sel; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_last_event_mouse_move = 0; +/* errr..... why? paranoia. + d = _ecore_x_selection_get(xevent->xselectionclear.selection); + if (d && (xevent->xselectionclear.time > d->time)) + { + _ecore_x_selection_set(None, NULL, 0, + xevent->xselectionclear.selection); + } + */ +/* Generate event for app cleanup */ + e = malloc(sizeof(Ecore_X_Event_Selection_Clear)); + e->win = xevent->xselectionclear.window; + e->time = xevent->xselectionclear.time; + e->atom = sel = xevent->xselectionclear.selection; + if (sel == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + e->selection = ECORE_X_SELECTION_OTHER; + + ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL); +} + +void +_ecore_x_event_handle_selection_request(XEvent *xevent) +{ + Ecore_X_Event_Selection_Request *e; + Ecore_X_Selection_Intern *sd; + void *data = NULL; + int len; + int typesize; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_last_event_mouse_move = 0; + /* + * Generate a selection request event. + */ + e = malloc(sizeof(Ecore_X_Event_Selection_Request)); + e->owner = xevent->xselectionrequest.owner; + e->requestor = xevent->xselectionrequest.requestor; + e->time = xevent->xselectionrequest.time; + e->selection = xevent->xselectionrequest.selection; + e->target = xevent->xselectionrequest.target; + e->property = xevent->xselectionrequest.property; + ecore_event_add(ECORE_X_EVENT_SELECTION_REQUEST, e, NULL, NULL); + + if ((sd = _ecore_x_selection_get(xevent->xselectionrequest.selection)) && + (sd->win == xevent->xselectionrequest.owner)) + { + Ecore_X_Selection_Intern *si; + + si = _ecore_x_selection_get(xevent->xselectionrequest.selection); + if (si->data) + { + Ecore_X_Atom property = None; + Ecore_X_Atom type; + + /* Set up defaults for strings first */ + type = xevent->xselectionrequest.target; + typesize = 8; + len = sd->length; + + if (!ecore_x_selection_convert(xevent->xselectionrequest.selection, + xevent->xselectionrequest.target, + &data, &len, &type, &typesize)) + /* Refuse selection, conversion to requested target failed */ + property = None; + else if (data) + { + /* FIXME: This does not properly handle large data transfers */ + ecore_x_window_prop_property_set( + xevent->xselectionrequest.requestor, + xevent->xselectionrequest. + property, + type, + typesize, + data, + len); + property = xevent->xselectionrequest.property; + free(data); + } + + ecore_x_selection_notify_send(xevent->xselectionrequest.requestor, + xevent->xselectionrequest.selection, + xevent->xselectionrequest.target, + property, + xevent->xselectionrequest.time); + } + } +} + +void +_ecore_x_event_handle_selection_notify(XEvent *xevent) +{ + Ecore_X_Event_Selection_Notify *e; + unsigned char *data = NULL; + Ecore_X_Atom selection; + int num_ret, format; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_last_event_mouse_move = 0; + selection = xevent->xselection.selection; + + if (xevent->xselection.target == ECORE_X_ATOM_SELECTION_TARGETS) + { + format = ecore_x_window_prop_property_get(xevent->xselection.requestor, + xevent->xselection.property, + XA_ATOM, 32, &data, &num_ret); + if (!format) + { + /* fallback if targets handling is not working and try get the + * selection directly */ + XConvertSelection(_ecore_x_disp, selection, + ECORE_X_ATOM_UTF8_STRING, + selection, + xevent->xselection.requestor, + CurrentTime); + return; + } + } + else + format = ecore_x_window_prop_property_get(xevent->xselection.requestor, + xevent->xselection.property, + AnyPropertyType, 8, &data, + &num_ret); + + e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify)); + if (!e) + return; + + e->win = xevent->xselection.requestor; + e->time = xevent->xselection.time; + e->atom = selection; + e->target = _ecore_x_selection_target_get(xevent->xselection.target); + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + e->selection = ECORE_X_SELECTION_XDND; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + e->selection = ECORE_X_SELECTION_OTHER; + + e->data = _ecore_x_selection_parse(e->target, data, num_ret, format); + + ecore_event_add(ECORE_X_EVENT_SELECTION_NOTIFY, e, + _ecore_x_event_free_selection_notify, NULL); +} + +void +_ecore_x_event_handle_colormap_notify(XEvent *xevent) +{ + Ecore_X_Event_Window_Colormap *e; + + _ecore_x_last_event_mouse_move = 0; + e = calloc(1, sizeof(Ecore_X_Event_Window_Colormap)); + if (!e) + return; + + e->win = xevent->xcolormap.window; + e->cmap = xevent->xcolormap.colormap; + e->time = _ecore_x_event_last_time; + if (xevent->xcolormap.state == ColormapInstalled) + e->installed = EINA_TRUE; + else + e->installed = EINA_FALSE; + + ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL); +} + +void +_ecore_x_event_handle_client_message(XEvent *xevent) +{ + _ecore_x_last_event_mouse_move = 0; + /* Special client message event handling here. need to put LOTS of if */ + /* checks here and generate synthetic events per special message known */ + /* otherwise generate generic client message event. this would handle*/ + /* netwm, ICCCM, gnomewm, old kde and mwm hint client message protocols */ + if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_PROTOCOLS) && + (xevent->xclient.format == 32) && + (xevent->xclient.data.l[0] == (long)ECORE_X_ATOM_WM_DELETE_WINDOW)) + { + Ecore_X_Event_Window_Delete_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Delete_Request)); + if (!e) + return; + + e->win = xevent->xclient.window; + e->time = _ecore_x_event_last_time; + ecore_event_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, e, NULL, NULL); + } + else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_MOVERESIZE) && + (xevent->xclient.format == 32) && +/* Ignore move and resize with keyboard */ + (xevent->xclient.data.l[2] < 9)) + { + Ecore_X_Event_Window_Move_Resize_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Move_Resize_Request)); + if (!e) + return; + + e->win = xevent->xclient.window; + e->x = xevent->xclient.data.l[0]; + e->y = xevent->xclient.data.l[1]; + e->direction = xevent->xclient.data.l[2]; + e->button = xevent->xclient.data.l[3]; + e->source = xevent->xclient.data.l[4]; + ecore_event_add(ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST, e, NULL, NULL); + } + /* Xdnd Client Message Handling Begin */ + /* Message Type: XdndEnter target */ + else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_ENTER) + { + Ecore_X_Event_Xdnd_Enter *e; + Ecore_X_DND_Target *target; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter)); + if (!e) return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + target = _ecore_x_dnd_target_get(); + target->state = ECORE_X_DND_TARGET_ENTERED; + target->source = xevent->xclient.data.l[0]; + target->win = xevent->xclient.window; + target->version = (int)(xevent->xclient.data.l[1] >> 24); + if (target->version > ECORE_X_DND_VERSION) + { + WRN("DND: Requested version %d, we only support up to %d", + target->version, ECORE_X_DND_VERSION); + free(e); + return; + } + + if (xevent->xclient.data.l[1] & 0x1UL) + { + /* source supports more than 3 types, fetch property */ + unsigned char *data; + Ecore_X_Atom *types; + int i, num_ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!(ecore_x_window_prop_property_get(target->source, + ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, + 32, &data, &num_ret))) + { + WRN( + "DND: Could not fetch data type list from source window, aborting."); + free(e); + return; + } + + types = (Ecore_X_Atom *)data; + e->types = calloc(num_ret, sizeof(char *)); + if (e->types) + { + LOGFN(__FILE__, __LINE__, __FUNCTION__); + for (i = 0; i < num_ret; i++) + e->types[i] = XGetAtomName(_ecore_x_disp, types[i]); + } + + e->num_types = num_ret; + } + else + { + int i = 0; + + e->types = calloc(3, sizeof(char *)); + if (e->types) + { + LOGFN(__FILE__, __LINE__, __FUNCTION__); + while ((i < 3) && (xevent->xclient.data.l[i + 2])) + { + e->types[i] = XGetAtomName(_ecore_x_disp, + xevent->xclient.data.l[i + 2]); + i++; + } + } + + e->num_types = i; + } + + e->win = target->win; + e->source = target->source; + ecore_event_add(ECORE_X_EVENT_XDND_ENTER, e, + _ecore_x_event_free_xdnd_enter, NULL); + } + /* Message Type: XdndPosition target */ + else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_POSITION) + { + Ecore_X_Event_Xdnd_Position *e; + Ecore_X_DND_Target *target; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + target = _ecore_x_dnd_target_get(); + if ((target->source != (Ecore_X_Window)xevent->xclient.data.l[0]) || + (target->win != xevent->xclient.window)) + return; + + target->pos.x = xevent->xclient.data.l[2] >> 16; + target->pos.y = xevent->xclient.data.l[2] & 0xFFFFUL; + target->action = xevent->xclient.data.l[4]; /* Version 2 */ + + target->time = (target->version >= 1) ? + (Time)xevent->xclient.data.l[3] : CurrentTime; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Position)); + if (!e) return; + + e->win = target->win; + e->source = target->source; + e->position.x = target->pos.x; + e->position.y = target->pos.y; + e->action = target->action; + ecore_event_add(ECORE_X_EVENT_XDND_POSITION, e, NULL, NULL); + } + /* Message Type: XdndStatus source */ + else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_STATUS) + { + Ecore_X_Event_Xdnd_Status *e; + Ecore_X_DND_Source *source; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + source = _ecore_x_dnd_source_get(); + /* Make sure source/target match */ + if ((source->win != xevent->xclient.window) || + (source->dest != (Window)xevent->xclient.data.l[0])) + return; + + source->await_status = 0; + + source->will_accept = xevent->xclient.data.l[1] & 0x1UL; + source->suppress = (xevent->xclient.data.l[1] & 0x2UL) ? 0 : 1; + + source->rectangle.x = xevent->xclient.data.l[2] >> 16; + source->rectangle.y = xevent->xclient.data.l[2] & 0xFFFFUL; + source->rectangle.width = xevent->xclient.data.l[3] >> 16; + source->rectangle.height = xevent->xclient.data.l[3] & 0xFFFFUL; + + source->accepted_action = xevent->xclient.data.l[4]; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Status)); + if (!e) return; + + e->win = source->win; + e->target = source->dest; + e->will_accept = source->will_accept; + e->rectangle.x = source->rectangle.x; + e->rectangle.y = source->rectangle.y; + e->rectangle.width = source->rectangle.width; + e->rectangle.height = source->rectangle.height; + e->action = source->accepted_action; + + ecore_event_add(ECORE_X_EVENT_XDND_STATUS, e, NULL, NULL); + } + /* Message Type: XdndLeave target */ + /* Pretend the whole thing never happened, sort of */ + else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_LEAVE) + { + Ecore_X_Event_Xdnd_Leave *e; + Ecore_X_DND_Target *target; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + target = _ecore_x_dnd_target_get(); + if ((target->source != (Ecore_X_Window)xevent->xclient.data.l[0]) || + (target->win != xevent->xclient.window)) + return; + + target->state = ECORE_X_DND_TARGET_IDLE; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Leave)); + if (!e) return; + + e->win = xevent->xclient.window; + e->source = (Window)xevent->xclient.data.l[0]; + ecore_event_add(ECORE_X_EVENT_XDND_LEAVE, e, NULL, NULL); + } + /* Message Type: XdndDrop target */ + else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_DROP) + { + Ecore_X_Event_Xdnd_Drop *e; + Ecore_X_DND_Target *target; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + target = _ecore_x_dnd_target_get(); + /* Match source/target */ + if ((target->source != (Window)xevent->xclient.data.l[0]) || + (target->win != xevent->xclient.window)) + return; + + target->time = (target->version >= 1) ? + (Time)xevent->xclient.data.l[2] : _ecore_x_event_last_time; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Drop)); + if (!e) return; + + e->win = target->win; + e->source = target->source; + e->action = target->action; + e->position.x = target->pos.x; + e->position.y = target->pos.y; + ecore_event_add(ECORE_X_EVENT_XDND_DROP, e, NULL, NULL); + } + /* Message Type: XdndFinished source */ + else if (xevent->xclient.message_type == ECORE_X_ATOM_XDND_FINISHED) + { + Ecore_X_Event_Xdnd_Finished *e; + Ecore_X_DND_Source *source; + Eina_Bool completed = EINA_TRUE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + source = _ecore_x_dnd_source_get(); + /* Match source/target */ + if ((source->win != xevent->xclient.window) || + (source->dest != (Window)xevent->xclient.data.l[0])) + return; + + if ((source->version < 5) || (xevent->xclient.data.l[1] & 0x1UL)) + { + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* Target successfully performed drop action */ + ecore_x_selection_xdnd_clear(); + source->state = ECORE_X_DND_SOURCE_IDLE; + } + else if (source->version >= 5) + { + completed = EINA_FALSE; + source->state = ECORE_X_DND_SOURCE_CONVERTING; + + /* FIXME: Probably need to add a timer to switch back to idle + * and discard the selection data */ + } + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Finished)); + if (!e) return; + + e->win = source->win; + e->target = source->dest; + e->completed = completed; + if (source->version >= 5) + { + source->accepted_action = xevent->xclient.data.l[2]; + e->action = source->accepted_action; + } + else + { + source->accepted_action = 0; + e->action = source->action; + } + + ecore_event_add(ECORE_X_EVENT_XDND_FINISHED, e, NULL, NULL); + } + else if (xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_STATE) + { + Ecore_X_Event_Window_State_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request)); + if (!e) return; + + e->win = xevent->xclient.window; + if (xevent->xclient.data.l[0] == 0) + e->action = ECORE_X_WINDOW_STATE_ACTION_REMOVE; + else if (xevent->xclient.data.l[0] == 1) + e->action = ECORE_X_WINDOW_STATE_ACTION_ADD; + else if (xevent->xclient.data.l[0] == 2) + e->action = ECORE_X_WINDOW_STATE_ACTION_TOGGLE; + else + { + free(e); + return; + } + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + e->state[0] = _ecore_x_netwm_state_get(xevent->xclient.data.l[1]); + if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN) + { +// char *name; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +// name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[1]); +// if (name) ERR("Unknown state: %s", name); +// XFree(name); + } + e->state[1] = _ecore_x_netwm_state_get(xevent->xclient.data.l[2]); + if (e->state[1] == ECORE_X_WINDOW_STATE_UNKNOWN) + { +// char *name; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + +// name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[2]); +// if (name) ERR("Unknown state: %s", name); +// XFree(name); + } + + e->source = xevent->xclient.data.l[3]; + + ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL); + } + else if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_CHANGE_STATE) + && (xevent->xclient.format == 32) + && (xevent->xclient.data.l[0] == IconicState)) + { + Ecore_X_Event_Window_State_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_State_Request)); + if (!e) + return; + + e->win = xevent->xclient.window; + e->action = ECORE_X_WINDOW_STATE_ACTION_ADD; + e->state[0] = ECORE_X_WINDOW_STATE_ICONIFIED; + + ecore_event_add(ECORE_X_EVENT_WINDOW_STATE_REQUEST, e, NULL, NULL); + } + else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_WM_DESKTOP) + && (xevent->xclient.format == 32)) + { + Ecore_X_Event_Desktop_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Desktop_Change)); + if (!e) + return; + + e->win = xevent->xclient.window; + e->desk = xevent->xclient.data.l[0]; + e->source = xevent->xclient.data.l[1]; + + ecore_event_add(ECORE_X_EVENT_DESKTOP_CHANGE, e, NULL, NULL); + } + else if ((xevent->xclient.message_type == + ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS)) + { + Ecore_X_Event_Frame_Extents_Request *e; + + e = calloc(1, sizeof(Ecore_X_Event_Frame_Extents_Request)); + if (!e) + return; + + e->win = xevent->xclient.window; + + ecore_event_add(ECORE_X_EVENT_FRAME_EXTENTS_REQUEST, e, NULL, NULL); + } + else if ((xevent->xclient.message_type == ECORE_X_ATOM_WM_PROTOCOLS) + && ((Ecore_X_Atom)xevent->xclient.data.l[0] == + ECORE_X_ATOM_NET_WM_PING) + && (xevent->xclient.format == 32)) + { + Ecore_X_Event_Ping *e; + Ecore_X_Window root = 0; + + e = calloc(1, sizeof(Ecore_X_Event_Ping)); + if (!e) + return; + + e->win = xevent->xclient.window; + e->time = xevent->xclient.data.l[1]; + e->event_win = xevent->xclient.data.l[2]; + + /* send a reply anyway - we are alive... eventloop at least */ + ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL); + if (ScreenCount(_ecore_x_disp) > 1) + { + LOGFN(__FILE__, __LINE__, __FUNCTION__); + root = ecore_x_window_root_get(e->win); + } + else + root = DefaultRootWindow(_ecore_x_disp); + + if (xevent->xclient.window != root) + { + xevent->xclient.window = root; + XSendEvent(_ecore_x_disp, root, False, + SubstructureRedirectMask | SubstructureNotifyMask, + xevent); + } + } + else if ((xevent->xclient.message_type == + ECORE_X_ATOM_NET_STARTUP_INFO_BEGIN) && + (xevent->xclient.format == 8)) + _ecore_x_netwm_startup_info_begin(xevent->xclient.window, + xevent->xclient.data.b); + else if ((xevent->xclient.message_type == ECORE_X_ATOM_NET_STARTUP_INFO) && + (xevent->xclient.format == 8)) + _ecore_x_netwm_startup_info(xevent->xclient.window, + xevent->xclient.data.b); + else if ((xevent->xclient.message_type == 27777) + && (xevent->xclient.data.l[0] == 0x7162534) + && (xevent->xclient.format == 32) + && (xevent->xclient.window == _ecore_x_private_win)) + { + /* a grab sync marker */ + if (xevent->xclient.data.l[1] == 0x10000001) + _ecore_x_window_grab_remove(xevent->xclient.data.l[2]); + else if (xevent->xclient.data.l[1] == 0x10000002) + _ecore_x_key_grab_remove(xevent->xclient.data.l[2]); + } + else + { + Ecore_X_Event_Client_Message *e; + int i; + + e = calloc(1, sizeof(Ecore_X_Event_Client_Message)); + if (!e) + return; + + e->win = xevent->xclient.window; + e->message_type = xevent->xclient.message_type; + e->format = xevent->xclient.format; + for (i = 0; i < 5; i++) + e->data.l[i] = xevent->xclient.data.l[i]; + + ecore_event_add(ECORE_X_EVENT_CLIENT_MESSAGE, e, NULL, NULL); + } +} + +void +_ecore_x_event_handle_mapping_notify(XEvent *xevent) +{ + Ecore_X_Event_Mapping_Change *e; + + _ecore_x_last_event_mouse_move = 0; + XRefreshKeyboardMapping((XMappingEvent *)xevent); + _ecore_x_modifiers_get(); + e = calloc(1, sizeof(Ecore_X_Event_Mapping_Change)); + if (!e) return; + switch (xevent->xmapping.request) + { + case MappingModifier: + e->type = ECORE_X_MAPPING_MODIFIER; + break; + + case MappingKeyboard: + e->type = ECORE_X_MAPPING_KEYBOARD; + break; + + case MappingPointer: + default: + e->type = ECORE_X_MAPPING_MOUSE; + break; + } + e->keycode = xevent->xmapping.first_keycode; + e->num = xevent->xmapping.count; + ecore_event_add(ECORE_X_EVENT_MAPPING_CHANGE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_shape_change(XEvent *xevent) +{ + XShapeEvent *shape_event; + Ecore_X_Event_Window_Shape *e; + + _ecore_x_last_event_mouse_move = 0; + shape_event = (XShapeEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Window_Shape)); + if (!e) + return; + + e->win = shape_event->window; + e->time = shape_event->time; + switch (shape_event->kind) + { + case ShapeBounding: + e->type = ECORE_X_SHAPE_BOUNDING; + break; + + case ShapeClip: + e->type = ECORE_X_SHAPE_CLIP; + break; + + case ShapeInput: + e->type = ECORE_X_SHAPE_INPUT; + break; + + default: + break; + } + e->x = shape_event->x; + e->y = shape_event->y; + e->w = shape_event->width; + e->h = shape_event->height; + e->shaped = shape_event->shaped; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_screensaver_notify(XEvent *xevent) +{ +#ifdef ECORE_XSS + XScreenSaverNotifyEvent *screensaver_event; + Ecore_X_Event_Screensaver_Notify *e; + + _ecore_x_last_event_mouse_move = 0; + screensaver_event = (XScreenSaverNotifyEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Screensaver_Notify)); + if (!e) + return; + + e->win = screensaver_event->window; + if ((screensaver_event->state == ScreenSaverOn) || + (screensaver_event->state == ScreenSaverCycle)) + e->on = EINA_TRUE; + else + e->on = EINA_FALSE; + + e->time = screensaver_event->time; + ecore_event_add(ECORE_X_EVENT_SCREENSAVER_NOTIFY, e, NULL, NULL); +#else /* ifdef ECORE_XSS */ + xevent = NULL; +#endif /* ifdef ECORE_XSS */ +} + +void +_ecore_x_event_handle_sync_counter(XEvent *xevent) +{ + XSyncCounterNotifyEvent *sync_counter_event; + Ecore_X_Event_Sync_Counter *e; + + _ecore_x_last_event_mouse_move = 0; + sync_counter_event = (XSyncCounterNotifyEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Sync_Counter)); + if (!e) + return; + + e->time = sync_counter_event->time; + ecore_event_add(ECORE_X_EVENT_SYNC_COUNTER, e, NULL, NULL); +} + +void +_ecore_x_event_handle_sync_alarm(XEvent *xevent) +{ + XSyncAlarmNotifyEvent *sync_alarm_event; + Ecore_X_Event_Sync_Alarm *e; + + _ecore_x_last_event_mouse_move = 0; + sync_alarm_event = (XSyncAlarmNotifyEvent *)xevent; + + e = calloc(1, sizeof(Ecore_X_Event_Sync_Alarm)); + if (!e) + return; + + e->time = sync_alarm_event->time; + e->alarm = sync_alarm_event->alarm; + ecore_event_add(ECORE_X_EVENT_SYNC_ALARM, e, NULL, NULL); +} + +#ifdef ECORE_XRANDR +void +_ecore_x_event_handle_randr_change(XEvent *xevent) +{ + XRRScreenChangeNotifyEvent *randr_event; + Ecore_X_Event_Screen_Change *e; + + _ecore_x_last_event_mouse_move = 0; + randr_event = (XRRScreenChangeNotifyEvent *)xevent; + if (!XRRUpdateConfiguration(xevent)) + ERR("Can't update RR config!"); + + e = calloc(1, sizeof(Ecore_X_Event_Screen_Change)); + if (!e) + return; + + e->win = randr_event->window; + e->root = randr_event->root; + 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->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); +} + +static void +_ecore_x_event_handle_randr_notify_crtc_change(const XRRNotifyEvent *xevent) +{ + const XRRCrtcChangeNotifyEvent *randr_event; + Ecore_X_Event_Randr_Crtc_Change *e; + + randr_event = (const XRRCrtcChangeNotifyEvent *)xevent; + + e = calloc(1, sizeof(Ecore_X_Event_Randr_Crtc_Change)); + if (!e) + return; + + e->win = randr_event->window; + e->crtc = randr_event->crtc; + e->mode = randr_event->mode; + 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); +} + +static void +_ecore_x_event_handle_randr_notify_output_change(const XRRNotifyEvent *xevent) +{ + const XRROutputChangeNotifyEvent *randr_event; + Ecore_X_Event_Randr_Output_Change *e; + + randr_event = (const XRROutputChangeNotifyEvent *)xevent; + + e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Change)); + if (!e) + return; + + e->win = randr_event->window; + e->output = randr_event->output; + e->crtc = randr_event->crtc; + e->mode = randr_event->mode; + 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); +} + +static void +_ecore_x_event_handle_randr_notify_output_property(const XRRNotifyEvent *xevent) +{ + const XRROutputPropertyNotifyEvent *randr_event; + Ecore_X_Event_Randr_Output_Property_Notify *e; + + randr_event = (const XRROutputPropertyNotifyEvent *)xevent; + + e = calloc(1, sizeof(Ecore_X_Event_Randr_Output_Property_Notify)); + if (!e) + return; + + e->win = randr_event->window; + e->output = randr_event->output; + e->property = randr_event->property; + e->time = randr_event->timestamp; + if (randr_event->state == PropertyNewValue) + e->state = ECORE_X_RANDR_PROPERTY_CHANGE_ADD; + else + e->state = ECORE_X_RANDR_PROPERTY_CHANGE_DEL; + ecore_event_add(ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, e, NULL, NULL); +} + +void +_ecore_x_event_handle_randr_notify(XEvent *xevent) +{ + const XRRNotifyEvent *randr_event; + + _ecore_x_last_event_mouse_move = 0; + randr_event = (const XRRNotifyEvent *)xevent; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + switch (randr_event->subtype) + { + case RRNotify_CrtcChange: + _ecore_x_event_handle_randr_notify_crtc_change(randr_event); + break; + + case RRNotify_OutputChange: + _ecore_x_event_handle_randr_notify_output_change(randr_event); + break; + + case RRNotify_OutputProperty: + _ecore_x_event_handle_randr_notify_output_property(randr_event); + break; + + default: + ERR("Unknown XRandR RRNotify subtype: %d.", + randr_event->subtype); + break; + } +} + +#endif /* ifdef ECORE_XRANDR */ + +#ifdef ECORE_XFIXES +void +_ecore_x_event_handle_fixes_selection_notify(XEvent *event) +{ + XFixesSelectionNotifyEvent *notify_event = + (XFixesSelectionNotifyEvent *)event; + Ecore_X_Event_Fixes_Selection_Notify *e; + Ecore_X_Atom sel; + + _ecore_x_last_event_mouse_move = 0; + /* Nothing here yet */ + + e = calloc(1, sizeof(*e)); + if (!e) + return; + + e->win = notify_event->window; + e->owner = notify_event->owner; + e->time = notify_event->timestamp; + e->selection_time = notify_event->selection_timestamp; + e->atom = sel = notify_event->selection; + if (sel == ECORE_X_ATOM_SELECTION_PRIMARY) + e->selection = ECORE_X_SELECTION_PRIMARY; + else if (sel == ECORE_X_ATOM_SELECTION_SECONDARY) + e->selection = ECORE_X_SELECTION_SECONDARY; + else if (sel == ECORE_X_ATOM_SELECTION_CLIPBOARD) + e->selection = ECORE_X_SELECTION_CLIPBOARD; + else + e->selection = ECORE_X_SELECTION_OTHER; + e->reason = notify_event->subtype; + + ecore_event_add(ECORE_X_EVENT_FIXES_SELECTION_NOTIFY, e, NULL, NULL); +} + +#endif /* ifdef ECORE_XFIXES */ + +#ifdef ECORE_XDAMAGE +void +_ecore_x_event_handle_damage_notify(XEvent *event) +{ + XDamageNotifyEvent *damage_event; + Ecore_X_Event_Damage *e; + + _ecore_x_last_event_mouse_move = 0; + damage_event = (XDamageNotifyEvent *)event; + + e = calloc(1, sizeof(Ecore_X_Event_Damage)); + if (!e) + return; + + e->level = damage_event->level; + e->drawable = damage_event->drawable; + e->damage = damage_event->damage; + e->more = damage_event->more; + e->time = damage_event->timestamp; + e->area.x = damage_event->area.x; + e->area.y = damage_event->area.y; + e->area.width = damage_event->area.width; + e->area.height = damage_event->area.height; + e->geometry.x = damage_event->geometry.x; + e->geometry.y = damage_event->geometry.y; + e->geometry.width = damage_event->geometry.width; + e->geometry.height = damage_event->geometry.height; + + ecore_event_add(ECORE_X_EVENT_DAMAGE_NOTIFY, e, NULL, NULL); +} + +#endif /* ifdef ECORE_XDAMAGE */ + +static void +_ecore_x_event_free_generic_event(void *data, + void *ev) +{ +#ifdef ECORE_XI2 + Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic *)ev; + + if (data) + { + if (e->data) + XFreeEventData(_ecore_x_disp, (XGenericEventCookie *)data); + free(data); + } + free(e); +#else + return; + data = NULL; ev = NULL; +#endif /* ifdef ECORE_XI2 */ +} + +void +_ecore_x_event_handle_generic_event(XEvent *event) +{ +#ifdef ECORE_XI2 + XGenericEvent *generic_event; + Ecore_X_Event_Generic *e; + XGenericEventCookie *data; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + generic_event = (XGenericEvent *)event; + + e = calloc(1, sizeof(Ecore_X_Event_Generic)); + if (!e) + return; + + if (XGetEventData(_ecore_x_disp, &(event->xcookie))) + { + e->cookie = event->xcookie.cookie; + e->data = event->xcookie.data; + } + else + { + e->cookie = 0; + e->data = NULL; + } + + e->extension = generic_event->extension; + e->evtype = generic_event->evtype; + + if (e->extension == _ecore_x_xi2_opcode) + _ecore_x_input_handler(event); + + data = malloc(sizeof(XGenericEventCookie)); + if (data) memcpy(data, &(event->xcookie), sizeof(XGenericEventCookie)); + ecore_event_add(ECORE_X_EVENT_GENERIC, + e, + _ecore_x_event_free_generic_event, + data); +#else + return; + event = NULL; +#endif /* ifdef ECORE_XI2 */ +} + +#ifdef ECORE_XGESTURE +void +_ecore_x_event_handle_gesture_notify_flick(XEvent *xevent) +{ + XGestureNotifyFlickEvent *xfe; + Ecore_X_Event_Gesture_Notify_Flick *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xfe = (XGestureNotifyFlickEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Flick)); + if (!e) + return; + + e->win = xfe->window; + e->time = xfe->time; + e->subtype = xfe->kind; + e->num_fingers = xfe->num_finger; + e->distance = xfe->distance; + e->duration = xfe->duration; + e->direction = xfe->direction; + e->angle = XFixedToDouble(xfe->angle); + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_FLICK, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gesture_notify_pan(XEvent *xevent) +{ + XGestureNotifyPanEvent *xpe; + Ecore_X_Event_Gesture_Notify_Pan *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xpe = (XGestureNotifyPanEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Pan)); + if (!e) + return; + + e->win = xpe->window; + e->time = xpe->time; + e->subtype = xpe->kind; + e->num_fingers = xpe->num_finger; + e->dx = xpe->dx; + e->dy = xpe->dy; + e->distance = xpe->distance; + e->duration = xpe->duration; + e->direction = xpe->direction; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_PAN, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gesture_notify_pinchrotation(XEvent *xevent) +{ + XGestureNotifyPinchRotationEvent *xpre; + Ecore_X_Event_Gesture_Notify_PinchRotation *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xpre = (XGestureNotifyPinchRotationEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_PinchRotation)); + if (!e) + return; + + e->win = xpre->window; + e->time = xpre->time; + e->subtype = xpre->kind; + e->num_fingers = xpre->num_finger; + e->distance = xpre->distance; + e->cx = xpre->cx; + e->cy = xpre->cy; + e->zoom = XFixedToDouble(xpre->zoom); + e->angle = XFixedToDouble(xpre->angle); + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gesture_notify_tap(XEvent *xevent) +{ + XGestureNotifyTapEvent *xte; + Ecore_X_Event_Gesture_Notify_Tap *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xte = (XGestureNotifyTapEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Tap)); + if (!e) + return; + + e->win = xte->window; + e->time = xte->time; + e->subtype = xte->kind; + e->num_fingers = xte->num_finger; + e->cx = xte->cx; + e->cy = xte->cy; + e->tap_repeat = xte->tap_repeat; + e->interval = xte->interval; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_TAP, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gesture_notify_tapnhold(XEvent *xevent) +{ + XGestureNotifyTapNHoldEvent *xthe; + Ecore_X_Event_Gesture_Notify_TapNHold *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xthe = (XGestureNotifyTapNHoldEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_TapNHold)); + if (!e) + return; + + e->win = xthe->window; + e->time = xthe->time; + e->subtype = xthe->kind; + e->num_fingers = xthe->num_finger; + e->cx = xthe->cx; + e->cy = xthe->cy; + e->interval = xthe->interval; + e->hold_time = xthe->holdtime; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gesture_notify_hold(XEvent *xevent) +{ + XGestureNotifyHoldEvent *xhe; + Ecore_X_Event_Gesture_Notify_Hold *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xhe = (XGestureNotifyHoldEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Hold)); + if (!e) + return; + + e->win = xhe->window; + e->time = xhe->time; + e->subtype = xhe->kind; + e->num_fingers = xhe->num_finger; + e->cx = xhe->cx; + e->cy = xhe->cy; + e->hold_time = xhe->holdtime; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_HOLD, e, NULL, NULL); +} + +void +_ecore_x_event_handle_gesture_notify_group(XEvent *xevent) +{ + XGestureNotifyGroupEvent *xge; + Ecore_X_Event_Gesture_Notify_Group *e; + + _ecore_x_last_event_mouse_move = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xge = (XGestureNotifyGroupEvent *)xevent; + e = calloc(1, sizeof(Ecore_X_Event_Gesture_Notify_Group)); + if (!e) + return; + + e->win = xge->window; + e->time = xge->time; + e->subtype = xge->kind; + e->num_groups = xge->num_group; + e->group_id = xge->groupid; + + ecore_event_add(ECORE_X_EVENT_GESTURE_NOTIFY_GROUP, e, NULL, NULL); +} + +#endif /* ifdef ECORE_XGESTURE */ +#ifdef ECORE_XKB +void +_ecore_x_event_handle_xkb(XEvent *xevent) +{ + XkbEvent *xkbev; + Ecore_X_Event_Xkb *e; + + xkbev = (XkbEvent *) xevent; + e = calloc(1, sizeof(Ecore_X_Event_Xkb)); + if (!e) + return; + e->group = xkbev->state.group; + if (xkbev->any.xkb_type == XkbStateNotify) + ecore_event_add(ECORE_X_EVENT_XKB_STATE_NOTIFY, e, NULL, NULL); + else if ((xkbev->any.xkb_type == XkbNewKeyboardNotify) || + (xkbev->any.xkb_type == XkbMapNotify)) + { + if (xkbev->any.xkb_type == XkbMapNotify) + { + XkbMapNotifyEvent *xkbmapping; + + xkbmapping = (XkbMapNotifyEvent *)xkbev; + XkbRefreshKeyboardMapping(xkbmapping); + } + ecore_event_add(ECORE_X_EVENT_XKB_NEWKBD_NOTIFY, e, NULL, NULL); + } +} +#endif /* ifdef ECORE_XKB */ diff --git a/src/lib/ecore_x/xlib/ecore_x_fixes.c b/src/lib/ecore_x/xlib/ecore_x_fixes.c new file mode 100644 index 0000000000..da0a6c3ac9 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_fixes.c @@ -0,0 +1,365 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> + +#include "ecore_x_private.h" +#include "Ecore_X.h" + +static int _fixes_available; +#ifdef ECORE_XFIXES +static int _fixes_major, _fixes_minor; +#endif /* ifdef ECORE_XFIXES */ + +void +_ecore_x_fixes_init(void) +{ +#ifdef ECORE_XFIXES + _fixes_major = 3; + _fixes_minor = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XFixesQueryVersion(_ecore_x_disp, &_fixes_major, &_fixes_minor)) + { + _fixes_available = 1; + + ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = ecore_event_type_new(); + } + else + _fixes_available = 0; + +#else /* ifdef ECORE_XFIXES */ + _fixes_available = 0; +#endif /* ifdef ECORE_XFIXES */ +} + +#ifdef ECORE_XFIXES +/* I don't know what to call this function. */ +static XRectangle * +_ecore_x_rectangle_ecore_to_x(Ecore_X_Rectangle *rects, + int num) +{ + XRectangle *xrect; + int i; + + if (num == 0) + return NULL; + + xrect = malloc(sizeof(XRectangle) * num); + if (!xrect) + return NULL; + + for (i = 0; i < num; i++) + { + xrect[i].x = rects[i].x; + xrect[i].y = rects[i].y; + xrect[i].width = rects[i].width; + xrect[i].height = rects[i].height; + } + return xrect; +} + +static Ecore_X_Rectangle * +_ecore_x_rectangle_x_to_ecore(XRectangle *xrect, + int num) +{ + Ecore_X_Rectangle *rects; + int i; + + if (num == 0) + return NULL; + + rects = malloc(sizeof(Ecore_X_Rectangle) * num); + if (!rects) + return NULL; + + for (i = 0; i < num; i++) + { + rects[i].x = xrect[i].x; + rects[i].y = xrect[i].y; + rects[i].width = xrect[i].width; + rects[i].height = xrect[i].height; + } + return rects; +} + +#endif /* ifdef ECORE_XFIXES */ + +EAPI Eina_Bool +ecore_x_fixes_selection_notification_request(Ecore_X_Atom selection) +{ +#ifdef ECORE_XFIXES + if (_fixes_available) + { + XFixesSelectSelectionInput (_ecore_x_disp, + DefaultRootWindow(_ecore_x_disp), + selection, + XFixesSetSelectionOwnerNotifyMask | + XFixesSelectionWindowDestroyNotifyMask | + XFixesSelectionClientCloseNotifyMask); + return EINA_TRUE; + } +#endif + return EINA_FALSE; +} + +EAPI Ecore_X_Region +ecore_x_region_new(Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XFIXES + Ecore_X_Region region; + XRectangle *xrect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xrect = _ecore_x_rectangle_ecore_to_x(rects, num); + region = XFixesCreateRegion(_ecore_x_disp, xrect, num); + free(xrect); + return region; +#else /* ifdef ECORE_XFIXES */ + return 0; +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI Ecore_X_Region +ecore_x_region_new_from_bitmap(Ecore_X_Pixmap bitmap) +{ +#ifdef ECORE_XFIXES + Ecore_X_Region region; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + region = XFixesCreateRegionFromBitmap(_ecore_x_disp, bitmap); + return region; +#else /* ifdef ECORE_XFIXES */ + return 0; +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI Ecore_X_Region +ecore_x_region_new_from_window(Ecore_X_Window win, + Ecore_X_Region_Type type) +{ +#ifdef ECORE_XFIXES + Ecore_X_Region region; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + region = XFixesCreateRegionFromWindow(_ecore_x_disp, win, type); + return region; +#else /* ifdef ECORE_XFIXES */ + return 0; +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI Ecore_X_Region +ecore_x_region_new_from_gc(Ecore_X_GC gc) +{ +#ifdef ECORE_XFIXES + Ecore_X_Region region; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + region = XFixesCreateRegionFromGC(_ecore_x_disp, gc); + return region; +#else /* ifdef ECORE_XFIXES */ + return 0; +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI Ecore_X_Region +ecore_x_region_new_from_picture(Ecore_X_Picture picture) +{ +#ifdef ECORE_XFIXES + Ecore_X_Region region; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + region = XFixesCreateRegionFromPicture(_ecore_x_disp, picture); + return region; +#else /* ifdef ECORE_XFIXES */ + return 0; +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_free(Ecore_X_Region region) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesDestroyRegion(_ecore_x_disp, region); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_set(Ecore_X_Region region, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ECORE_XFIXES + XRectangle *xrect = _ecore_x_rectangle_ecore_to_x(rects, num); + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesSetRegion(_ecore_x_disp, region, xrect, num); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_copy(Ecore_X_Region dest, + Ecore_X_Region source) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesCopyRegion(_ecore_x_disp, dest, source); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_combine(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesUnionRegion(_ecore_x_disp, dest, source1, source2); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_intersect(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesIntersectRegion(_ecore_x_disp, dest, source1, source2); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_subtract(Ecore_X_Region dest, + Ecore_X_Region source1, + Ecore_X_Region source2) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesSubtractRegion(_ecore_x_disp, dest, source1, source2); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_invert(Ecore_X_Region dest, + Ecore_X_Rectangle *bounds, + Ecore_X_Region source) +{ +#ifdef ECORE_XFIXES + XRectangle *xbound; + int num = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + while (bounds + num) + num++; + xbound = _ecore_x_rectangle_ecore_to_x(bounds, num); + + XFixesInvertRegion(_ecore_x_disp, dest, xbound, source); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_translate(Ecore_X_Region region, + int dx, + int dy) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesTranslateRegion(_ecore_x_disp, region, dx, dy); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_extents(Ecore_X_Region dest, + Ecore_X_Region source) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesRegionExtents(_ecore_x_disp, dest, source); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI Ecore_X_Rectangle * +ecore_x_region_fetch(Ecore_X_Region region, + int *num, + Ecore_X_Rectangle *bounds){ +#ifdef ECORE_XFIXES + Ecore_X_Rectangle *rects; + XRectangle *xrect, xbound; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xrect = XFixesFetchRegionAndBounds(_ecore_x_disp, region, num, &xbound); + rects = _ecore_x_rectangle_x_to_ecore(xrect, *num); + (*bounds).x = xbound.x; + (*bounds).y = xbound.y; + (*bounds).width = xbound.width; + (*bounds).height = xbound.height; + return rects; +#else /* ifdef ECORE_XFIXES */ + return NULL; +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_expand(Ecore_X_Region dest, + Ecore_X_Region source, + unsigned int left, + unsigned int right, + unsigned int top, + unsigned int bottom) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesExpandRegion(_ecore_x_disp, dest, source, left, right, top, bottom); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_gc_clip_set(Ecore_X_Region region, + Ecore_X_GC gc, + int x_origin, + int y_origin) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesSetGCClipRegion(_ecore_x_disp, gc, x_origin, y_origin, region); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_window_shape_set(Ecore_X_Region region, + Ecore_X_Window win, + Ecore_X_Shape_Type type, + int x_offset, + int y_offset) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesSetWindowShapeRegion(_ecore_x_disp, + win, + type, + x_offset, + y_offset, + region); +#endif /* ifdef ECORE_XFIXES */ +} + +EAPI void +ecore_x_region_picture_clip_set(Ecore_X_Region region, + Ecore_X_Picture picture, + int x_origin, + int y_origin) +{ +#ifdef ECORE_XFIXES + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFixesSetPictureClipRegion(_ecore_x_disp, + picture, + x_origin, + y_origin, + region); +#endif /* ifdef ECORE_XFIXES */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_gc.c b/src/lib/ecore_x/xlib/ecore_x_gc.c new file mode 100644 index 0000000000..539636648f --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_gc.c @@ -0,0 +1,171 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +/** + * Creates a new default graphics context associated with the given + * drawable. + * @param draw Drawable to create graphics context with. If @c 0 is + * given instead, the default root window is used. + * @param value_mask Bitmask values. + * @param value_list List of values. The order of values must be the + * same than the corresponding bitmaks. + * @return The new default graphics context. + */ +EAPI Ecore_X_GC +ecore_x_gc_new(Ecore_X_Drawable draw, + Ecore_X_GC_Value_Mask value_mask, + const unsigned int *value_list) +{ + XGCValues gcv; + int mask; + int idx; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!draw) + draw = DefaultRootWindow(_ecore_x_disp); + + memset(&gcv, 0, sizeof (gcv)); + + for (i = 0, idx = 0, mask = 1; i <= 22; i++, mask <<= 1) + { + switch (mask & value_mask) + { + case ECORE_X_GC_VALUE_MASK_FUNCTION: + gcv.function = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_PLANE_MASK: + gcv.plane_mask = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_FOREGROUND: + gcv.foreground = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_BACKGROUND: + gcv.background = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_LINE_WIDTH: + gcv.line_width = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_LINE_STYLE: + gcv.line_style = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_CAP_STYLE: + gcv.cap_style = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_JOIN_STYLE: + gcv.join_style = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_FILL_STYLE: + gcv.fill_style = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_FILL_RULE: + gcv.fill_rule = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_TILE: + gcv.tile = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_STIPPLE: + gcv.stipple = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_X: + gcv.ts_x_origin = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_TILE_STIPPLE_ORIGIN_Y: + gcv.ts_y_origin = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_FONT: + gcv.font = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_SUBWINDOW_MODE: + gcv.subwindow_mode = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_GRAPHICS_EXPOSURES: + gcv.graphics_exposures = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_X: + gcv.clip_x_origin = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_CLIP_ORIGIN_Y: + gcv.clip_y_origin = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_CLIP_MASK: + gcv.clip_mask = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_DASH_OFFSET: + gcv.dash_offset = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_DASH_LIST: + gcv.dashes = value_list[idx]; + idx++; + break; + + case ECORE_X_GC_VALUE_MASK_ARC_MODE: + gcv.arc_mode = value_list[idx]; + idx++; + break; + } + } + + return XCreateGC(_ecore_x_disp, draw, value_mask, &gcv); +} + +/** + * Deletes and frees the given graphics context. + * @param gc The given graphics context. + */ +EAPI void +ecore_x_gc_free(Ecore_X_GC gc) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFreeGC(_ecore_x_disp, gc); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_gesture.c b/src/lib/ecore_x/xlib/ecore_x_gesture.c new file mode 100644 index 0000000000..dbde8b0db2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_gesture.c @@ -0,0 +1,137 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" + +static Eina_Bool _gesture_available = EINA_FALSE; + +#ifdef ECORE_XGESTURE +static int _gesture_major, _gesture_minor, _gesture_patch; +int _gesture_version; +#endif /* ifdef ECORE_XGESTURE */ + +void +_ecore_x_gesture_init(void) +{ +#ifdef ECORE_XGESTURE + _gesture_major = 0; + _gesture_minor = 0; + _gesture_patch = 0; + _gesture_version = 0; + + if (XGestureQueryVersion(_ecore_x_disp, &_gesture_major, &_gesture_minor, &_gesture_patch)) + { + _gesture_version = (_gesture_major << 16) | _gesture_minor; + _gesture_available = EINA_TRUE; + } + else + _gesture_available = EINA_FALSE; +#else /* ifdef ECORE_XGESTURE */ + _gesture_available = EINA_FALSE; +#endif /* ifdef ECORE_XGESTURE */ +} + +/* + * @brief Query whether gesture is available or not. + * + * @return @c EINA_TRUE, if extension is available, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_gesture_supported(void) +{ + return _gesture_available; +} + +EAPI Eina_Bool +ecore_x_gesture_events_select(Ecore_X_Window win, + Ecore_X_Gesture_Event_Mask mask) +{ +#ifdef ECORE_XGESTURE + if (!_gesture_available) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGestureSelectEvents(_ecore_x_disp, win, mask); + + return EINA_TRUE; +#else /* ifdef ECORE_XGESTURE */ + (void) win; + (void) mask; + return EINA_FALSE; +#endif /* ifdef ECORE_XGESTURE */ +} + +EAPI Ecore_X_Gesture_Event_Mask +ecore_x_gesture_events_selected_get(Ecore_X_Window win) +{ +#ifdef ECORE_XGESTURE + Ecore_X_Gesture_Event_Mask mask; + + if (!_gesture_available) + return ECORE_X_GESTURE_EVENT_MASK_NONE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (GestureSuccess != XGestureGetSelectedEvents(_ecore_x_disp, win, &mask)) + { + mask = ECORE_X_GESTURE_EVENT_MASK_NONE; + return mask; + } + + return mask; +#else /* ifdef ECORE_XGESTURE */ + (void) win; + return ECORE_X_GESTURE_EVENT_MASK_NONE; +#endif /* ifdef ECORE_XGESTURE */ +} + +EAPI Eina_Bool +ecore_x_gesture_event_grab(Ecore_X_Window win, + Ecore_X_Gesture_Event_Type type, + int num_fingers) +{ +#ifdef ECORE_XGESTURE + if (!_gesture_available) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (GestureGrabSuccess != XGestureGrabEvent(_ecore_x_disp, win, type, num_fingers, CurrentTime)) + { + return EINA_FALSE; + } + + return EINA_TRUE; +#else /* ifdef ECORE_XGESTURE */ + (void) win; + (void) type; + (void) num_fingers; + return EINA_FALSE; +#endif /* ifdef ECORE_XGESTURE */ +} + +EAPI Eina_Bool +ecore_x_gesture_event_ungrab(Ecore_X_Window win, + Ecore_X_Gesture_Event_Type type, + int num_fingers) +{ +#ifdef ECORE_XGESTURE + Ecore_X_Gesture_Event_Mask mask; + + if (!_gesture_available) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (GestureUngrabSuccess != XGestureUngrabEvent(_ecore_x_disp, win, type, num_fingers, CurrentTime)) + { + return EINA_FALSE; + } + + return EINA_TRUE; +#else /* ifdef ECORE_XGESTURE */ + (void) win; + (void) type; + (void) num_fingers; + return EINA_FALSE; +#endif /* ifdef ECORE_XGESTURE */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_icccm.c b/src/lib/ecore_x/xlib/ecore_x_icccm.c new file mode 100644 index 0000000000..8d6ea1f50e --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_icccm.c @@ -0,0 +1,1214 @@ +/* + * Various ICCCM related functions. + * + * This is ALL the code involving anything ICCCM related. for both WM and + * client. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +EAPI void +ecore_x_icccm_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +} + +EAPI void +ecore_x_icccm_state_set(Ecore_X_Window win, + Ecore_X_Window_State_Hint state) +{ + unsigned long c[2]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + c[0] = WithdrawnState; + else if (state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + c[0] = NormalState; + else if (state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + c[0] = IconicState; + + c[1] = None; + XChangeProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE, + ECORE_X_ATOM_WM_STATE, 32, PropModeReplace, + (unsigned char *)c, 2); +} + +EAPI Ecore_X_Window_State_Hint +ecore_x_icccm_state_get(Ecore_X_Window win) +{ + unsigned char *prop_ret = NULL; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + Ecore_X_Window_State_Hint hint; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + hint = ECORE_X_WINDOW_STATE_HINT_NONE; + XGetWindowProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_STATE, + 0, 0x7fffffff, False, ECORE_X_ATOM_WM_STATE, + &type_ret, &format_ret, &num_ret, &bytes_after, + &prop_ret); + if ((prop_ret) && (num_ret == 2)) + { + if (prop_ret[0] == WithdrawnState) + hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else if (prop_ret[0] == NormalState) + hint = ECORE_X_WINDOW_STATE_HINT_NORMAL; + else if (prop_ret[0] == IconicState) + hint = ECORE_X_WINDOW_STATE_HINT_ICONIC; + } + + if (prop_ret) + XFree(prop_ret); + + return hint; +} + +EAPI void +ecore_x_icccm_delete_window_send(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_DELETE_WINDOW, + t, 0, 0, 0); +} + +EAPI void +ecore_x_icccm_take_focus_send(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_TAKE_FOCUS, + t, 0, 0, 0); +} + +EAPI void +ecore_x_icccm_save_yourself_send(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_client_message32_send(win, ECORE_X_ATOM_WM_PROTOCOLS, + ECORE_X_EVENT_MASK_NONE, + ECORE_X_ATOM_WM_SAVE_YOURSELF, + t, 0, 0, 0); +} + +EAPI void +ecore_x_icccm_move_resize_send(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + XEvent ev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ev.type = ConfigureNotify; + ev.xconfigure.display = _ecore_x_disp; + ev.xconfigure.event = win; + ev.xconfigure.window = win; + ev.xconfigure.x = x; + ev.xconfigure.y = y; + ev.xconfigure.width = w; + ev.xconfigure.height = h; + ev.xconfigure.border_width = 0; + ev.xconfigure.above = None; + ev.xconfigure.override_redirect = False; + XSendEvent(_ecore_x_disp, win, False, StructureNotifyMask, &ev); +} + +EAPI void +ecore_x_icccm_hints_set(Ecore_X_Window win, + Eina_Bool accepts_focus, + Ecore_X_Window_State_Hint initial_state, + Ecore_X_Pixmap icon_pixmap, + Ecore_X_Pixmap icon_mask, + Ecore_X_Window icon_window, + Ecore_X_Window window_group, + Eina_Bool is_urgent) +{ + XWMHints *hints; + + hints = XAllocWMHints(); + if (!hints) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + hints->flags = InputHint | StateHint; + hints->input = accepts_focus; + if (initial_state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN) + hints->initial_state = WithdrawnState; + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_NORMAL) + hints->initial_state = NormalState; + else if (initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC) + hints->initial_state = IconicState; + + if (icon_pixmap != 0) + { + hints->icon_pixmap = icon_pixmap; + hints->flags |= IconPixmapHint; + } + + if (icon_mask != 0) + { + hints->icon_mask = icon_mask; + hints->flags |= IconMaskHint; + } + + if (icon_window != 0) + { + hints->icon_window = icon_window; + hints->flags |= IconWindowHint; + } + + if (window_group != 0) + { + hints->window_group = window_group; + hints->flags |= WindowGroupHint; + } + + if (is_urgent) + hints->flags |= XUrgencyHint; + + XSetWMHints(_ecore_x_disp, win, hints); + XFree(hints); +} + +EAPI Eina_Bool +ecore_x_icccm_hints_get(Ecore_X_Window win, + Eina_Bool *accepts_focus, + Ecore_X_Window_State_Hint *initial_state, + Ecore_X_Pixmap *icon_pixmap, + Ecore_X_Pixmap *icon_mask, + Ecore_X_Window *icon_window, + Ecore_X_Window *window_group, + Eina_Bool *is_urgent) +{ + XWMHints *hints; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (accepts_focus) + *accepts_focus = EINA_TRUE; + + if (initial_state) + *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + + if (icon_pixmap) + *icon_pixmap = 0; + + if (icon_mask) + *icon_mask = 0; + + if (icon_window) + *icon_window = 0; + + if (window_group) + *window_group = 0; + + if (is_urgent) + *is_urgent = EINA_FALSE; + + hints = XGetWMHints(_ecore_x_disp, win); + if (hints) + { + if ((hints->flags & InputHint) && (accepts_focus)) + { + if (hints->input) + *accepts_focus = EINA_TRUE; + else + *accepts_focus = EINA_FALSE; + } + + if ((hints->flags & StateHint) && (initial_state)) + { + if (hints->initial_state == WithdrawnState) + *initial_state = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else if (hints->initial_state == NormalState) + *initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL; + else if (hints->initial_state == IconicState) + *initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC; + } + + if ((hints->flags & IconPixmapHint) && (icon_pixmap)) + *icon_pixmap = hints->icon_pixmap; + + if ((hints->flags & IconMaskHint) && (icon_mask)) + *icon_mask = hints->icon_mask; + + if ((hints->flags & IconWindowHint) && (icon_window)) + *icon_window = hints->icon_window; + + if ((hints->flags & WindowGroupHint) && (window_group)) + *window_group = hints->window_group; + + if ((hints->flags & XUrgencyHint) && (is_urgent)) + *is_urgent = EINA_TRUE; + + XFree(hints); + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI void +ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win, + Eina_Bool request_pos, + Ecore_X_Gravity gravity, + int min_w, + int min_h, + int max_w, + int max_h, + int base_w, + int base_h, + int step_x, + int step_y, + double min_aspect, + double max_aspect) +{ + XSizeHints hint; + long mask; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask)) + memset(&hint, 0, sizeof(XSizeHints)); + + hint.flags = 0; + if (request_pos) + hint.flags |= USPosition; + + if (gravity != ECORE_X_GRAVITY_NW) + { + hint.flags |= PWinGravity; + hint.win_gravity = gravity; + } + + if ((min_w > 0) || (min_h > 0)) + { + hint.flags |= PMinSize; + hint.min_width = min_w; + hint.min_height = min_h; + } + + if ((max_w > 0) || (max_h > 0)) + { + hint.flags |= PMaxSize; + hint.max_width = max_w; + hint.max_height = max_h; + } + + if ((base_w > 0) || (base_h > 0)) + { + hint.flags |= PBaseSize; + hint.base_width = base_w; + hint.base_height = base_h; + } + + if ((step_x > 1) || (step_y > 1)) + { + hint.flags |= PResizeInc; + hint.width_inc = step_x; + hint.height_inc = step_y; + } + + if ((min_aspect > 0.0) || (max_aspect > 0.0)) + { + hint.flags |= PAspect; + hint.min_aspect.x = min_aspect * 10000; + hint.min_aspect.y = 10000; + hint.max_aspect.x = max_aspect * 10000; + hint.max_aspect.y = 10000; + } + + XSetWMNormalHints(_ecore_x_disp, win, &hint); +} + +EAPI Eina_Bool +ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win, + Eina_Bool *request_pos, + Ecore_X_Gravity *gravity, + int *min_w, + int *min_h, + int *max_w, + int *max_h, + int *base_w, + int *base_h, + int *step_x, + int *step_y, + double *min_aspect, + double *max_aspect) +{ + XSizeHints hint; + long mask; + + int minw = 0, minh = 0; + int maxw = 32767, maxh = 32767; + int basew = -1, baseh = -1; + int stepx = -1, stepy = -1; + double mina = 0.0, maxa = 0.0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask)) + return EINA_FALSE; + + if ((hint.flags & USPosition) || ((hint.flags & PPosition))) + { + if (request_pos) + *request_pos = EINA_TRUE; + } + else if (request_pos) + *request_pos = EINA_FALSE; + + if (hint.flags & PWinGravity) + { + if (gravity) + *gravity = hint.win_gravity; + } + else if (gravity) + *gravity = ECORE_X_GRAVITY_NW; + + if (hint.flags & PMinSize) + { + minw = hint.min_width; + minh = hint.min_height; + } + + if (hint.flags & PMaxSize) + { + maxw = hint.max_width; + maxh = hint.max_height; + if (maxw < minw) + maxw = minw; + + if (maxh < minh) + maxh = minh; + } + + if (hint.flags & PBaseSize) + { + basew = hint.base_width; + baseh = hint.base_height; + if (basew > minw) + minw = basew; + + if (baseh > minh) + minh = baseh; + } + + if (hint.flags & PResizeInc) + { + stepx = hint.width_inc; + stepy = hint.height_inc; + if (stepx < 1) + stepx = 1; + + if (stepy < 1) + stepy = 1; + } + + if (hint.flags & PAspect) + { + if (hint.min_aspect.y > 0) + mina = ((double)hint.min_aspect.x) / ((double)hint.min_aspect.y); + + if (hint.max_aspect.y > 0) + maxa = ((double)hint.max_aspect.x) / ((double)hint.max_aspect.y); + } + + if (min_w) + *min_w = minw; + + if (min_h) + *min_h = minh; + + if (max_w) + *max_w = maxw; + + if (max_h) + *max_h = maxh; + + if (base_w) + *base_w = basew; + + if (base_h) + *base_h = baseh; + + if (step_x) + *step_x = stepx; + + if (step_y) + *step_y = stepy; + + if (min_aspect) + *min_aspect = mina; + + if (max_aspect) + *max_aspect = maxa; + + return EINA_TRUE; +} + +EAPI void +ecore_x_icccm_title_set(Ecore_X_Window win, + const char *t) +{ + char *list[1]; + XTextProperty xprop; + int ret; + + if (!t) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xprop.value = NULL; +#ifdef X_HAVE_UTF8_STRING + list[0] = strdup(t); + ret = + Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, XUTF8StringStyle, + &xprop); +#else /* ifdef X_HAVE_UTF8_STRING */ + list[0] = strdup(t); + ret = + XmbTextListToTextProperty(_ecore_x_disp, list, 1, XStdICCTextStyle, + &xprop); +#endif /* ifdef X_HAVE_UTF8_STRING */ + if (ret >= Success) + { + XSetWMName(_ecore_x_disp, win, &xprop); + if (xprop.value) + XFree(xprop.value); + } + else if (XStringListToTextProperty(list, 1, &xprop) >= Success) + { + XSetWMName(_ecore_x_disp, win, &xprop); + if (xprop.value) + XFree(xprop.value); + } + + free(list[0]); +} + +EAPI char * +ecore_x_icccm_title_get(Ecore_X_Window win) +{ + XTextProperty xprop; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xprop.value = NULL; + if (XGetWMName(_ecore_x_disp, win, &xprop) >= Success) + { + if (xprop.value) + { + char **list = NULL; + char *t = NULL; + int num = 0; + int ret; + + if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING) + t = strdup((char *)xprop.value); + else + { + /* convert to utf8 */ +#ifdef X_HAVE_UTF8_STRING + ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop, + &list, &num); +#else /* ifdef X_HAVE_UTF8_STRING */ + ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop, + &list, &num); +#endif /* ifdef X_HAVE_UTF8_STRING */ + + if ((ret == XLocaleNotSupported) || + (ret == XNoMemory) || (ret == XConverterNotFound)) + t = strdup((char *)xprop.value); + else if ((ret >= Success) && (num > 0)) + t = strdup(list[0]); + + if (list) + XFreeStringList(list); + } + + if (xprop.value) + XFree(xprop.value); + + return t; + } + } + + return NULL; +} + +/** + * Set protocol atoms explicitly + * @param win The Window + * @param protos An array of protocol atoms + * @param num the number of members of the array + */ +EAPI void +ecore_x_icccm_protocol_atoms_set(Ecore_X_Window win, + Ecore_X_Atom *protos, + int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num > 0) + XSetWMProtocols(_ecore_x_disp, win, (Atom *)(protos), num); + else + XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_PROTOCOLS); +} + +/** + * Set or unset a wm protocol property. + * @param win The Window + * @param protocol The protocol to enable/disable + * @param on On/Off + */ +EAPI void +ecore_x_icccm_protocol_set(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol, + Eina_Bool on) +{ + Atom *protos = NULL; + Atom proto; + int protos_count = 0; + int already_set = 0; + int i; + + /* Check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + proto = _ecore_x_atoms_wm_protocols[protocol]; + + if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count)) + { + protos = NULL; + protos_count = 0; + } + + for (i = 0; i < protos_count; i++) + { + if (protos[i] == proto) + { + already_set = 1; + break; + } + } + + if (on) + { + Atom *new_protos = NULL; + + if (already_set) + goto leave; + + new_protos = malloc((protos_count + 1) * sizeof(Atom)); + if (!new_protos) + goto leave; + + for (i = 0; i < protos_count; i++) + new_protos[i] = protos[i]; + new_protos[protos_count] = proto; + XSetWMProtocols(_ecore_x_disp, win, new_protos, protos_count + 1); + free(new_protos); + } + else + { + if (!already_set) + goto leave; + + for (i = 0; i < protos_count; i++) + { + if (protos[i] == proto) + { + int j; + + for (j = i + 1; j < protos_count; j++) + protos[j - 1] = protos[j]; + if (protos_count > 1) + XSetWMProtocols(_ecore_x_disp, win, protos, + protos_count - 1); + else + XDeleteProperty(_ecore_x_disp, win, + ECORE_X_ATOM_WM_PROTOCOLS); + + goto leave; + } + } + } + +leave: + if (protos) + XFree(protos); +} + +/** + * Determines whether a protocol is set for a window. + * @param win The Window + * @param protocol The protocol to query + * @return 1 if the protocol is set, else 0. + */ +EAPI Eina_Bool +ecore_x_icccm_protocol_isset(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol) +{ + Atom proto, *protos = NULL; + int i, protos_count = 0; + Eina_Bool ret = EINA_FALSE; + + /* check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + proto = _ecore_x_atoms_wm_protocols[protocol]; + + if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count)) + return EINA_FALSE; + + for (i = 0; i < protos_count; i++) + if (protos[i] == proto) + { + ret = EINA_TRUE; + break; + } + + if (protos) + XFree(protos); + + return ret; +} + +/** + * Set a window name & class. + * @param win The window + * @param n The name string + * @param c The class string + * + * Set a window name * class + */ +EAPI void +ecore_x_icccm_name_class_set(Ecore_X_Window win, + const char *n, + const char *c) +{ + XClassHint *xch; + + xch = XAllocClassHint(); + if (!xch) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xch->res_name = (char *)n; + xch->res_class = (char *)c; + XSetClassHint(_ecore_x_disp, win, xch); + XFree(xch); +} + +/** + * Get a window name & class. + * @param win The window + * @param n The name string + * @param c The class string + * + * Get a window name * class + */ +EAPI void +ecore_x_icccm_name_class_get(Ecore_X_Window win, + char **n, + char **c) +{ + XClassHint xch; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (n) + *n = NULL; + + if (c) + *c = NULL; + + xch.res_name = NULL; + xch.res_class = NULL; + if (XGetClassHint(_ecore_x_disp, win, &xch)) + { + if (n) + if (xch.res_name) + *n = strdup(xch.res_name); + + if (c) + if (xch.res_class) + *c = strdup(xch.res_class); + + XFree(xch.res_name); + XFree(xch.res_class); + } +} + +/** + * Get a window client machine string. + * @param win The window + * @return The windows client machine string + * + * Return the client machine of a window. String must be free'd when done with. + */ +EAPI char * +ecore_x_icccm_client_machine_get(Ecore_X_Window win) +{ + char *name; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + name = ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_CLIENT_MACHINE); + return name; +} + +/** + * Sets the WM_COMMAND property for @a win. + * + * @param win The window. + * @param argc Number of arguments. + * @param argv Arguments. + */ +EAPI void +ecore_x_icccm_command_set(Ecore_X_Window win, + int argc, + char **argv) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSetCommand(_ecore_x_disp, win, argv, argc); +} + +/** + * Get the WM_COMMAND property for @a win. + * + * Return the command of a window. String must be free'd when done with. + * + * @param win The window. + * @param argc Number of arguments. + * @param argv Arguments. + */ +EAPI void +ecore_x_icccm_command_get(Ecore_X_Window win, + int *argc, + char ***argv) +{ + int i, c; + char **v; + + if (argc) + *argc = 0; + + if (argv) + *argv = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetCommand(_ecore_x_disp, win, &v, &c)) + return; + + if (c < 1) + { + if (v) + XFreeStringList(v); + + return; + } + + if (argc) + *argc = c; + + if (argv) + { + (*argv) = malloc(c * sizeof(char *)); + if (!*argv) + { + XFreeStringList(v); + if (argc) + *argc = 0; + + return; + } + + for (i = 0; i < c; i++) + { + if (v[i]) + (*argv)[i] = strdup(v[i]); + else + (*argv)[i] = strdup(""); + } + } + + XFreeStringList(v); +} + +/** + * Set a window icon name. + * @param win The window + * @param t The icon name string + * + * Set a window icon name + */ +EAPI void +ecore_x_icccm_icon_name_set(Ecore_X_Window win, + const char *t) +{ + char *list[1]; + XTextProperty xprop; + int ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xprop.value = NULL; +#ifdef X_HAVE_UTF8_STRING + list[0] = strdup(t); + ret = Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, + XUTF8StringStyle, &xprop); +#else /* ifdef X_HAVE_UTF8_STRING */ + list[0] = strdup(t); + ret = XmbTextListToTextProperty(_ecore_x_disp, list, 1, + XStdICCTextStyle, &xprop); +#endif /* ifdef X_HAVE_UTF8_STRING */ + if (ret >= Success) + { + XSetWMIconName(_ecore_x_disp, win, &xprop); + if (xprop.value) + XFree(xprop.value); + } + else if (XStringListToTextProperty(list, 1, &xprop) >= Success) + { + XSetWMIconName(_ecore_x_disp, win, &xprop); + if (xprop.value) + XFree(xprop.value); + } + + free(list[0]); +} + +/** + * Get a window icon name. + * @param win The window + * @return The windows icon name string + * + * Return the icon name of a window. String must be free'd when done with. + */ +EAPI char * +ecore_x_icccm_icon_name_get(Ecore_X_Window win) +{ + XTextProperty xprop; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xprop.value = NULL; + if (XGetWMIconName(_ecore_x_disp, win, &xprop) >= Success) + { + if (xprop.value) + { + char **list = NULL; + char *t = NULL; + int num = 0; + int ret; + + if (xprop.encoding == ECORE_X_ATOM_UTF8_STRING) + t = strdup((char *)xprop.value); + else + { + /* convert to utf8 */ +#ifdef X_HAVE_UTF8_STRING + ret = Xutf8TextPropertyToTextList(_ecore_x_disp, &xprop, + &list, &num); +#else /* ifdef X_HAVE_UTF8_STRING */ + ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop, + &list, &num); +#endif /* ifdef X_HAVE_UTF8_STRING */ + + if ((ret == XLocaleNotSupported) || + (ret == XNoMemory) || (ret == XConverterNotFound)) + t = strdup((char *)xprop.value); + else if (ret >= Success) + { + if ((num >= 1) && (list)) + t = strdup(list[0]); + + if (list) + XFreeStringList(list); + } + } + + if (xprop.value) + XFree(xprop.value); + + return t; + } + } + + return NULL; +} + +/** + * Add a subwindow to the list of windows that need a different colormap installed. + * @param win The toplevel window + * @param subwin The subwindow to be added to the colormap windows list + */ +EAPI void +ecore_x_icccm_colormap_window_set(Ecore_X_Window win, + Ecore_X_Window subwin) +{ + int num = 0, i; + unsigned char *old_data = NULL; + unsigned char *data = NULL; + Window *oldset = NULL; + Window *newset = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + XA_WINDOW, 32, &old_data, &num)) + { + newset = calloc(1, sizeof(Window)); + if (!newset) + return; + + newset[0] = subwin; + num = 1; + data = (unsigned char *)newset; + } + else + { + newset = calloc(num + 1, sizeof(Window)); + oldset = (Window *)old_data; + if (!newset) + return; + + for (i = 0; i < num; ++i) + { + if (oldset[i] == subwin) + { + if (old_data) + XFree(old_data); + + old_data = NULL; + free(newset); + return; + } + + newset[i] = oldset[i]; + } + + newset[num++] = subwin; + if (old_data) + XFree(old_data); + + data = (unsigned char *)newset; + } + + ecore_x_window_prop_property_set(win, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + XA_WINDOW, 32, data, num); + free(newset); +} + +/** + * Remove a window from the list of colormap windows. + * @param win The toplevel window + * @param subwin The window to be removed from the colormap window list. + */ +EAPI void +ecore_x_icccm_colormap_window_unset(Ecore_X_Window win, + Ecore_X_Window subwin) +{ + int num = 0, i, j, k = 0; + unsigned char *old_data = NULL; + unsigned char *data = NULL; + Window *oldset = NULL; + Window *newset = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + XA_WINDOW, 32, &old_data, &num)) + return; + + oldset = (Window *)old_data; + for (i = 0; i < num; i++) + { + if (oldset[i] == subwin) + { + if (num == 1) + { + XDeleteProperty(_ecore_x_disp, + win, ECORE_X_ATOM_WM_COLORMAP_WINDOWS); + if (old_data) + XFree(old_data); + + old_data = NULL; + return; + } + else + { + newset = calloc(num - 1, sizeof(Window)); + data = (unsigned char *)newset; + for (j = 0; j < num; ++j) + if (oldset[j] != subwin) + newset[k++] = oldset[j]; + + ecore_x_window_prop_property_set( + win, + ECORE_X_ATOM_WM_COLORMAP_WINDOWS, + XA_WINDOW, + 32, + data, + k); + if (old_data) + XFree(old_data); + + old_data = NULL; + free(newset); + return; + } + } + } + + if (old_data) + XFree(old_data); +} + +/** + * Specify that a window is transient for another top-level window and should be handled accordingly. + * @param win the transient window + * @param forwin the toplevel window + */ +EAPI void +ecore_x_icccm_transient_for_set(Ecore_X_Window win, + Ecore_X_Window forwin) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSetTransientForHint(_ecore_x_disp, win, forwin); +} + +/** + * Remove the transient_for setting from a window. + * @param win The window + */ +EAPI void +ecore_x_icccm_transient_for_unset(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XDeleteProperty(_ecore_x_disp, win, ECORE_X_ATOM_WM_TRANSIENT_FOR); +} + +/** + * Get the window this window is transient for, if any. + * @param win The window to check + * @return The window ID of the top-level window, or 0 if the property does not exist. + */ +EAPI Ecore_X_Window +ecore_x_icccm_transient_for_get(Ecore_X_Window win) +{ + Window forwin; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XGetTransientForHint(_ecore_x_disp, win, &forwin)) + return (Ecore_X_Window)forwin; + else + return 0; +} + +/** + * Set the window role hint. + * @param win The window + * @param role The role string + */ +EAPI void +ecore_x_icccm_window_role_set(Ecore_X_Window win, + const char *role) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_WINDOW_ROLE, + (char *)role); +} + +/** + * Get the window role. + * @param win The window + * @return The window's role string. + */ +EAPI char * +ecore_x_icccm_window_role_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_window_prop_string_get(win, ECORE_X_ATOM_WM_WINDOW_ROLE); +} + +/** + * Set the window's client leader. + * @param win The window + * @param l The client leader window + * + * All non-transient top-level windows created by an app other than + * the main window must have this property set to the app's main window. + */ +EAPI void +ecore_x_icccm_client_leader_set(Ecore_X_Window win, + Ecore_X_Window l) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(win, ECORE_X_ATOM_WM_CLIENT_LEADER, + &l, 1); +} + +/** + * Get the window's client leader. + * @param win The window + * @return The window's client leader window, or 0 if unset */ +EAPI Ecore_X_Window +ecore_x_icccm_client_leader_get(Ecore_X_Window win) +{ + Ecore_X_Window l; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (ecore_x_window_prop_window_get(win, ECORE_X_ATOM_WM_CLIENT_LEADER, + &l, 1) > 0) + return l; + + return 0; +} + +EAPI void +ecore_x_icccm_iconic_request_send(Ecore_X_Window win, + Ecore_X_Window root) +{ + XEvent xev; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.format = 32; + xev.xclient.message_type = ECORE_X_ATOM_WM_CHANGE_STATE; + xev.xclient.data.l[0] = IconicState; + + XSendEvent(_ecore_x_disp, root, False, + SubstructureNotifyMask | SubstructureRedirectMask, &xev); +} + +/* FIXME: there are older E hints, gnome hints and mwm hints and new netwm */ +/* hints. each should go in their own file/section so we know which */ +/* is which. also older kde hints too. we should try support as much */ +/* as makese sense to support */ diff --git a/src/lib/ecore_x/xlib/ecore_x_image.c b/src/lib/ecore_x/xlib/ecore_x_image.c new file mode 100644 index 0000000000..def81104a2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_image.c @@ -0,0 +1,626 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include <stdlib.h> +#include <string.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#include "ecore_x_private.h" +#include "Ecore_X.h" + +#include <X11/extensions/XShm.h> +#include <X11/Xutil.h> + +static int _ecore_x_image_shm_can = -1; +static int _ecore_x_image_err = 0; + +static int +_ecore_x_image_error_handler(Display *d EINA_UNUSED, + XErrorEvent *ev EINA_UNUSED) +{ + _ecore_x_image_err = 1; + return 0; +} + +static void +_ecore_x_image_shm_check(void) +{ + XErrorHandler ph; + XShmSegmentInfo shminfo; + XImage *xim; + + if (_ecore_x_image_shm_can != -1) + return; + + XSync(_ecore_x_disp, False); + _ecore_x_image_err = 0; + + xim = XShmCreateImage(_ecore_x_disp, + DefaultVisual(_ecore_x_disp, + DefaultScreen(_ecore_x_disp)), + DefaultDepth(_ecore_x_disp, + DefaultScreen(_ecore_x_disp)), + ZPixmap, NULL, + &shminfo, 1, 1); + if (!xim) + { + _ecore_x_image_shm_can = 0; + return; + } + + shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, + IPC_CREAT | 0666); + if (shminfo.shmid == -1) + { + XDestroyImage(xim); + _ecore_x_image_shm_can = 0; + return; + } + + shminfo.readOnly = False; + shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); + xim->data = shminfo.shmaddr; + + if (xim->data == (char *)-1) + { + XDestroyImage(xim); + _ecore_x_image_shm_can = 0; + return; + } + + ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler); + XShmAttach(_ecore_x_disp, &shminfo); + XShmGetImage(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp), + xim, 0, 0, 0xffffffff); + XSync(_ecore_x_disp, False); + XSetErrorHandler((XErrorHandler)ph); + if (_ecore_x_image_err) + { + XShmDetach(_ecore_x_disp, &shminfo); + XDestroyImage(xim); + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); + _ecore_x_image_shm_can = 0; + return; + } + + XShmDetach(_ecore_x_disp, &shminfo); + XDestroyImage(xim); + shmdt(shminfo.shmaddr); + shmctl(shminfo.shmid, IPC_RMID, 0); + + _ecore_x_image_shm_can = 1; +} + +struct _Ecore_X_Image +{ + XShmSegmentInfo shminfo; + Ecore_X_Visual vis; + XImage *xim; + int depth; + int w, h; + int bpl, bpp, rows; + unsigned char *data; + Eina_Bool shm : 1; +}; + +EAPI Ecore_X_Image * +ecore_x_image_new(int w, + int h, + Ecore_X_Visual vis, + int depth) +{ + Ecore_X_Image *im; + + im = calloc(1, sizeof(Ecore_X_Image)); + if (!im) + return NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + im->w = w; + im->h = h; + im->vis = vis; + im->depth = depth; + _ecore_x_image_shm_check(); + im->shm = _ecore_x_image_shm_can; + return im; +} + +EAPI void +ecore_x_image_free(Ecore_X_Image *im) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (im->shm) + { + if (im->xim) + { + XShmDetach(_ecore_x_disp, &(im->shminfo)); + XDestroyImage(im->xim); + shmdt(im->shminfo.shmaddr); + shmctl(im->shminfo.shmid, IPC_RMID, 0); + } + } + else if (im->xim) + { + free(im->xim->data); + im->xim->data = NULL; + XDestroyImage(im->xim); + } + + free(im); +} + +static void +_ecore_x_image_shm_create(Ecore_X_Image *im) +{ + im->xim = XShmCreateImage(_ecore_x_disp, im->vis, im->depth, + ZPixmap, NULL, &(im->shminfo), + im->w, im->h); + if (!im->xim) + return; + + im->shminfo.shmid = shmget(IPC_PRIVATE, + im->xim->bytes_per_line * im->xim->height, + IPC_CREAT | 0666); + if (im->shminfo.shmid == -1) + { + XDestroyImage(im->xim); + return; + } + + im->shminfo.readOnly = False; + im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0); + im->xim->data = im->shminfo.shmaddr; + if ((im->xim->data == (char *)-1) || + (!im->xim->data)) + { + shmdt(im->shminfo.shmaddr); + shmctl(im->shminfo.shmid, IPC_RMID, 0); + XDestroyImage(im->xim); + return; + } + + XShmAttach(_ecore_x_disp, &im->shminfo); + + im->data = (unsigned char *)im->xim->data; + + im->bpl = im->xim->bytes_per_line; + im->rows = im->xim->height; + if (im->xim->bits_per_pixel <= 8) + im->bpp = 1; + else if (im->xim->bits_per_pixel <= 16) + im->bpp = 2; + else + im->bpp = 4; +} + +EAPI Eina_Bool +ecore_x_image_get(Ecore_X_Image *im, + Ecore_X_Drawable draw, + int x, + int y, + int sx, + int sy, + int w, + int h) +{ + Eina_Bool ret = EINA_TRUE; + XErrorHandler ph; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (im->shm) + { + if (!im->xim) + _ecore_x_image_shm_create(im); + + if (!im->xim) + return 0; + + _ecore_x_image_err = 0; + // optimised path + ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler); + if ((sx == 0) && (w == im->w)) + { + im->xim->data = (char *) + im->data + (im->xim->bytes_per_line * sy) + (sx * im->bpp); + im->xim->width = w; + im->xim->height = h; + XGrabServer(_ecore_x_disp); + if (!XShmGetImage(_ecore_x_disp, draw, im->xim, x, y, 0xffffffff)) + ret = EINA_FALSE; + XUngrabServer(_ecore_x_disp); + ecore_x_sync(); + } + // unavoidable thanks to mit-shm get api - tmp shm buf + copy into it + else + { + Ecore_X_Image *tim; + unsigned char *spixels, *sp, *pixels, *p; + int bpp, bpl, rows, sbpp, sbpl, srows; + int r; + + tim = ecore_x_image_new(w, h, im->vis, im->depth); + if (tim) + { + ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h); + if (ret) + { + spixels = ecore_x_image_data_get(tim, + &sbpl, + &srows, + &sbpp); + pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp); + if ((pixels) && (spixels)) + { + p = pixels + (sy * bpl) + (sx * bpp); + sp = spixels; + for (r = srows; r > 0; r--) + { + memcpy(p, sp, sbpl); + p += bpl; + sp += sbpl; + } + } + } + + ecore_x_image_free(tim); + } + } + + XSetErrorHandler((XErrorHandler)ph); + if (_ecore_x_image_err) + ret = EINA_FALSE; + } + else + { + printf("currently unimplemented ecore_x_image_get without shm\n"); + ret = EINA_FALSE; + } + + return ret; +} + +EAPI void +ecore_x_image_put(Ecore_X_Image *im, + Ecore_X_Drawable draw, + Ecore_X_GC gc, + int x, + int y, + int sx, + int sy, + int w, + int h) +{ + Ecore_X_GC tgc = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!gc) + { + XGCValues gcv; + memset(&gcv, 0, sizeof(gcv)); + gcv.subwindow_mode = IncludeInferiors; + tgc = XCreateGC(_ecore_x_disp, draw, GCSubwindowMode, &gcv); + gc = tgc; + } + if (!im->xim) _ecore_x_image_shm_create(im); + if (im->xim) + XShmPutImage(_ecore_x_disp, draw, gc, im->xim, sx, sy, x, y, w, h, False); + if (tgc) ecore_x_gc_free(tgc); +} + +EAPI void * +ecore_x_image_data_get(Ecore_X_Image *im, + int *bpl, + int *rows, + int *bpp) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!im->xim) _ecore_x_image_shm_create(im); + if (!im->xim) return NULL; + if (bpl) *bpl = im->bpl; + if (rows) *rows = im->rows; + if (bpp) *bpp = im->bpp; + return im->data; +} + +EAPI Eina_Bool +ecore_x_image_is_argb32_get(Ecore_X_Image *im) +{ + Visual *vis = im->vis; + if (!im->xim) _ecore_x_image_shm_create(im); + if (((vis->class == TrueColor) || + (vis->class == DirectColor)) && + (im->depth >= 24) && + (vis->red_mask == 0xff0000) && + (vis->green_mask == 0x00ff00) && + (vis->blue_mask == 0x0000ff)) + { +#ifdef WORDS_BIGENDIAN + if (im->xim->bitmap_bit_order == MSBFirst) return EINA_TRUE; +#else + if (im->xim->bitmap_bit_order == LSBFirst) return EINA_TRUE; +#endif + } + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_image_to_argb_convert(void *src, + int sbpp, + int sbpl, + Ecore_X_Colormap c, + Ecore_X_Visual v, + int x, + int y, + int w, + int h, + unsigned int *dst, + int dbpl, + int dx, + int dy) +{ + Visual *vis = v; + XColor *cols = NULL; + int n = 0, nret = 0, i, row; + unsigned int pal[256], r, g, b; + enum + { + rgbnone = 0, + rgb565, + bgr565, + rgbx555, + argbx888, + abgrx888, + rgba888x, + bgra888x, + argbx666 + }; + int mode = 0; + + sbpp *= 8; + + n = vis->map_entries; + if ((n <= 256) && + ((vis->class == PseudoColor) || + (vis->class == StaticColor) || + (vis->class == GrayScale) || + (vis->class == StaticGray))) + { + if (!c) + c = DefaultColormap(_ecore_x_disp, + DefaultScreen(_ecore_x_disp)); + cols = alloca(n * sizeof(XColor)); + for (i = 0; i < n; i++) + { + cols[i].pixel = i; + cols[i].flags = DoRed | DoGreen | DoBlue; + cols[i].red = 0; + cols[i].green = 0; + cols[i].blue = 0; + } + XQueryColors(_ecore_x_disp, c, cols, n); + for (i = 0; i < n; i++) + { + pal[i] = 0xff000000 | + ((cols[i].red >> 8) << 16) | + ((cols[i].green >> 8) << 8) | + ((cols[i].blue >> 8)); + } + nret = n; + } + else if ((vis->class == TrueColor) || + (vis->class == DirectColor)) + { + if ((vis->red_mask == 0x00ff0000) && + (vis->green_mask == 0x0000ff00) && + (vis->blue_mask == 0x000000ff)) + mode = argbx888; + else if ((vis->red_mask == 0x000000ff) && + (vis->green_mask == 0x0000ff00) && + (vis->blue_mask == 0x00ff0000)) + mode = abgrx888; + else if ((vis->red_mask == 0xff000000) && + (vis->green_mask == 0x00ff0000) && + (vis->blue_mask == 0x0000ff00)) + mode = rgba888x; + else if ((vis->red_mask == 0x0000ff00) && + (vis->green_mask == 0x00ff0000) && + (vis->blue_mask == 0xff000000)) + mode = bgra888x; + else if ((vis->red_mask == 0x0003f000) && + (vis->green_mask == 0x00000fc0) && + (vis->blue_mask == 0x0000003f)) + mode = argbx666; + else if ((vis->red_mask == 0x0000f800) && + (vis->green_mask == 0x000007e0) && + (vis->blue_mask == 0x0000001f)) + mode = rgb565; + else if ((vis->red_mask == 0x0000001f) && + (vis->green_mask == 0x000007e0) && + (vis->blue_mask == 0x0000f800)) + mode = bgr565; + else if ((vis->red_mask == 0x00007c00) && + (vis->green_mask == 0x000003e0) && + (vis->blue_mask == 0x0000001f)) + mode = rgbx555; + else + return EINA_FALSE; + } + for (row = 0; row < h; row++) + { + unsigned char *s8; + unsigned short *s16; + unsigned int *s32; + unsigned int *dp, *de; + + dp = ((unsigned int *)(((unsigned char *)dst) + + ((dy + row) * dbpl))) + dx; + de = dp + w; + switch (sbpp) + { + case 8: + s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + x; + if (nret > 0) + { + while (dp < de) + { + *dp = pal[*s8]; + s8++; dp++; + } + } + else + return EINA_FALSE; + break; + + case 16: + s16 = ((unsigned short *)(((unsigned char *)src) + ((y + row) * sbpl))) + x; + switch (mode) + { + case rgb565: + while (dp < de) + { + r = (*s16 & 0xf800) << 8; + g = (*s16 & 0x07e0) << 5; + b = (*s16 & 0x001f) << 3; + r |= (r >> 5) & 0xff0000; + g |= (g >> 6) & 0x00ff00; + b |= (b >> 5); + *dp = 0xff000000 | r | g | b; + s16++; dp++; + } + break; + + case bgr565: + while (dp < de) + { + r = (*s16 & 0x001f) << 19; + g = (*s16 & 0x07e0) << 5; + b = (*s16 & 0xf800) >> 8; + r |= (r >> 5) & 0xff0000; + g |= (g >> 6) & 0x00ff00; + b |= (b >> 5); + *dp = 0xff000000 | r | g | b; + s16++; dp++; + } + break; + + case rgbx555: + while (dp < de) + { + r = (*s16 & 0x7c00) << 9; + g = (*s16 & 0x03e0) << 6; + b = (*s16 & 0x001f) << 3; + r |= (r >> 5) & 0xff0000; + g |= (g >> 5) & 0x00ff00; + b |= (b >> 5); + *dp = 0xff000000 | r | g | b; + s16++; dp++; + } + break; + + default: + return EINA_FALSE; + break; + } + break; + + case 24: + case 32: + s32 = ((unsigned int *)(((unsigned char *)src) + ((y + row) * sbpl))) + x; + switch (mode) + { + case argbx888: + while (dp < de) + { + *dp = 0xff000000 | *s32; + s32++; dp++; + } + break; + + case abgrx888: + while (dp < de) + { + r = *s32 & 0x000000ff; + g = *s32 & 0x0000ff00; + b = *s32 & 0x00ff0000; + *dp = 0xff000000 | (r << 16) | (g) | (b >> 16); + s32++; dp++; + } + break; + + case rgba888x: + while (dp < de) + { + *dp = 0xff000000 | (*s32 >> 8); + s32++; dp++; + } + break; + + case bgra888x: + while (dp < de) + { + r = *s32 & 0x0000ff00; + g = *s32 & 0x00ff0000; + b = *s32 & 0xff000000; + *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24); + s32++; dp++; + } + break; + + case argbx666: + while (dp < de) + { + r = (*s32 & 0x3f000) << 6; + g = (*s32 & 0x00fc0) << 4; + b = (*s32 & 0x0003f) << 2; + r |= (r >> 6) & 0xff0000; + g |= (g >> 6) & 0x00ff00; + b |= (b >> 6); + *dp = 0xff000000 | r | g | b; + s32++; dp++; + } + break; + + default: + return EINA_FALSE; + break; + } + break; + break; + + default: + return EINA_FALSE; + break; + } + } + return EINA_TRUE; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_mwm.c b/src/lib/ecore_x/xlib/ecore_x_mwm.c new file mode 100644 index 0000000000..7812cc23ae --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_mwm.c @@ -0,0 +1,106 @@ +/* + * Various MWM related functions. + * + * This is ALL the code involving anything MWM related. for both WM and + * client. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +#define ECORE_X_MWM_HINTS_FUNCTIONS (1 << 0) +#define ECORE_X_MWM_HINTS_DECORATIONS (1 << 1) +#define ECORE_X_MWM_HINTS_INPUT_MODE (1 << 2) +#define ECORE_X_MWM_HINTS_STATUS (1 << 3) + +typedef struct _mwmhints +{ + CARD32 flags; + CARD32 functions; + CARD32 decorations; + INT32 inputmode; + CARD32 status; +} +MWMHints; + +EAPI Eina_Bool +ecore_x_mwm_hints_get(Ecore_X_Window win, + Ecore_X_MWM_Hint_Func *fhint, + Ecore_X_MWM_Hint_Decor *dhint, + Ecore_X_MWM_Hint_Input *ihint) +{ + unsigned char *p = NULL; + MWMHints *mwmhints = NULL; + int num; + Eina_Bool ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = EINA_FALSE; + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_MOTIF_WM_HINTS, + ECORE_X_ATOM_MOTIF_WM_HINTS, + 32, &p, &num)) + return EINA_FALSE; + + mwmhints = (MWMHints *)p; + if (mwmhints) + { + if (num >= 4) + { + if (dhint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_DECORATIONS) + *dhint = mwmhints->decorations; + else + *dhint = ECORE_X_MWM_HINT_DECOR_ALL; + } + + if (fhint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_FUNCTIONS) + *fhint = mwmhints->functions; + else + *fhint = ECORE_X_MWM_HINT_FUNC_ALL; + } + + if (ihint) + { + if (mwmhints->flags & ECORE_X_MWM_HINTS_INPUT_MODE) + *ihint = mwmhints->inputmode; + else + *ihint = ECORE_X_MWM_HINT_INPUT_MODELESS; + } + + ret = EINA_TRUE; + } + + free(mwmhints); + } + + return ret; +} + +EAPI void +ecore_x_mwm_borderless_set(Ecore_X_Window win, + Eina_Bool borderless) +{ + unsigned int data[5] = {0, 0, 0, 0, 0}; + + data[0] = 2; /* just set the decorations hint! */ + data[2] = !borderless; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_property_set(win, + ECORE_X_ATOM_MOTIF_WM_HINTS, + ECORE_X_ATOM_MOTIF_WM_HINTS, + 32, (void *)data, 5); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_netwm.c b/src/lib/ecore_x/xlib/ecore_x_netwm.c new file mode 100644 index 0000000000..3f08af8b9c --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_netwm.c @@ -0,0 +1,2083 @@ +/* + * _NET_WM... aka Extended Window Manager Hint (EWMH) functions. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +typedef struct _Ecore_X_Startup_Info Ecore_X_Startup_Info; + +struct _Ecore_X_Startup_Info +{ + Ecore_X_Window win; + + int init; + + int buffer_size; + char *buffer; + + int length; + + /* These are the sequence info fields */ + char *id; + char *name; + int screen; + char *bin; + char *icon; + int desktop; + int timestamp; + char *description; + char *wmclass; + int silent; +}; + +static void _ecore_x_window_prop_string_utf8_set(Ecore_X_Window win, + Ecore_X_Atom atom, + const char *str); +static char *_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win, + Ecore_X_Atom atom); +#if 0 /* Unused */ +static int _ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info); +static int _ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, + char *data); +#endif /* if 0 */ +static void _ecore_x_netwm_startup_info_free(void *data); + +/* + * Convenience macros + */ +#define _ATOM_SET_UTF8_STRING_LIST(win, atom, string, cnt) \ + XChangeProperty(_ecore_x_disp, \ + win, \ + atom, \ + ECORE_X_ATOM_UTF8_STRING, \ + 8, \ + PropModeReplace, \ + (unsigned char *)string, \ + cnt) + +/* + * Local variables + */ + +static Eina_Hash *startup_info = NULL; + +EAPI void +ecore_x_netwm_init(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + startup_info = eina_hash_string_superfast_new( + _ecore_x_netwm_startup_info_free); +} + +EAPI void +ecore_x_netwm_shutdown(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (startup_info) + eina_hash_free(startup_info); + + startup_info = NULL; +} + +/* + * WM identification + */ +EAPI void +ecore_x_netwm_wm_identify(Ecore_X_Window root, + Ecore_X_Window check, + const char *wm_name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(check, + ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, + &check, + 1); + _ecore_x_window_prop_string_utf8_set(check, + ECORE_X_ATOM_NET_WM_NAME, + wm_name); + /* This one isn't mandatory */ + _ecore_x_window_prop_string_utf8_set(root, + ECORE_X_ATOM_NET_WM_NAME, + wm_name); + ecore_x_window_prop_window_set(root, + ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, + &check, + 1); +} + +/* + * Set supported atoms + */ +EAPI void +ecore_x_netwm_supported_set(Ecore_X_Window root, + Ecore_X_Atom *supported, + int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_atom_set(root, + ECORE_X_ATOM_NET_SUPPORTED, + supported, + num); +} + +EAPI Eina_Bool +ecore_x_netwm_supported_get(Ecore_X_Window root, + Ecore_X_Atom **supported, + int *num) +{ + int num_ret; + + if (num) + *num = 0; + + if (supported) + *supported = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + num_ret = ecore_x_window_prop_atom_list_get(root, ECORE_X_ATOM_NET_SUPPORTED, + supported); + if (num_ret <= 0) + return EINA_FALSE; + + if (num) + *num = num_ret; + + return EINA_TRUE; +} + +/* + * Desktop configuration and status + */ +EAPI void +ecore_x_netwm_desk_count_set(Ecore_X_Window root, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS, + &n_desks, 1); +} + +EAPI void +ecore_x_netwm_desk_roots_set(Ecore_X_Window root, + Ecore_X_Window *vroots, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(root, + ECORE_X_ATOM_NET_VIRTUAL_ROOTS, + vroots, + n_desks); +} + +EAPI void +ecore_x_netwm_desk_names_set(Ecore_X_Window root, + const char **names, + unsigned int n_desks) +{ + char ss[32], *buf, *t; + const char *s; + unsigned int i; + int l, len; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + buf = NULL; + len = 0; + + for (i = 0; i < n_desks; i++) + { + s = (names) ? names[i] : NULL; + if (!s) + { + /* Default to "Desk-<number>" */ + sprintf(ss, "Desk-%d", i); + s = ss; + } + + l = strlen(s) + 1; + t = realloc(buf, len + l); + if (t) + { + buf = t; + memcpy(buf + len, s, l); + } + len += l; + } + + _ATOM_SET_UTF8_STRING_LIST(root, ECORE_X_ATOM_NET_DESKTOP_NAMES, buf, len); + + free(buf); +} + +EAPI void +ecore_x_netwm_desk_size_set(Ecore_X_Window root, + unsigned int width, + unsigned int height) +{ + unsigned int size[2]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + size[0] = width; + size[1] = height; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size, + 2); +} + +EAPI void +ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, + unsigned int *origins, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT, + origins, 2 * n_desks); +} + +EAPI void +ecore_x_netwm_desk_layout_set(Ecore_X_Window root, + int orientation, + int columns, + int rows, + int starting_corner) +{ + unsigned int layout[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + layout[0] = orientation; + layout[1] = columns; + layout[2] = rows; + layout[3] = starting_corner; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_LAYOUT, + layout, 4); +} + +EAPI void +ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, + unsigned int *areas, + unsigned int n_desks) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas, + 4 * n_desks); +} + +EAPI unsigned int * +ecore_x_netwm_desk_workareas_get(Ecore_X_Window root, unsigned int *n_desks) +{ + int ret; + unsigned int *areas = NULL; + + if (!root) root = DefaultRootWindow(_ecore_x_disp); + + ret = ecore_x_window_prop_card32_list_get(root, ECORE_X_ATOM_NET_WORKAREA, + &areas); + if (!areas) + { + if (n_desks) *n_desks = 0; + return 0; + } + if (n_desks) *n_desks = ret / 4; + return areas; +} + +EAPI void +ecore_x_netwm_desk_current_set(Ecore_X_Window root, + unsigned int desk) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk, + 1); +} + +EAPI void +ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, + Eina_Bool on) +{ + unsigned int val; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + val = (on) ? 1 : 0; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val, + 1); +} + +/* + * Client status + */ + +/* Mapping order */ +EAPI void +ecore_x_netwm_client_list_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST, + p_clients, n_clients); +} + +/* Stacking order */ +EAPI void +ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING, + p_clients, n_clients); +} + +EAPI void +ecore_x_netwm_client_active_set(Ecore_X_Window root, + Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_window_set(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW, + &win, 1); +} + +EAPI void +ecore_x_netwm_client_active_request(Ecore_X_Window root, + Ecore_X_Window win, + int type, + Ecore_X_Window current_win) +{ + XEvent xev; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_NET_ACTIVE_WINDOW; + xev.xclient.format = 32; + xev.xclient.data.l[0] = type; + xev.xclient.data.l[1] = CurrentTime; + xev.xclient.data.l[2] = current_win; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(_ecore_x_disp, root, False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +EAPI void +ecore_x_netwm_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name); +} + +EAPI int +ecore_x_netwm_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (name) + *name = _ecore_x_window_prop_string_utf8_get(win, + ECORE_X_ATOM_NET_WM_NAME); + + return 1; +} + +EAPI void +ecore_x_netwm_startup_id_set(Ecore_X_Window win, + const char *id) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_STARTUP_ID, id); +} + +EAPI int +ecore_x_netwm_startup_id_get(Ecore_X_Window win, + char **id) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (id) + *id = _ecore_x_window_prop_string_utf8_get(win, + ECORE_X_ATOM_NET_STARTUP_ID); + + return 1; +} + +EAPI void +ecore_x_netwm_visible_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME, + name); +} + +EAPI int +ecore_x_netwm_visible_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (name) + *name = _ecore_x_window_prop_string_utf8_get( + win, + ECORE_X_ATOM_NET_WM_VISIBLE_NAME); + + return 1; +} + +EAPI void +ecore_x_netwm_icon_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME, + name); +} + +EAPI int +ecore_x_netwm_icon_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (name) + *name = _ecore_x_window_prop_string_utf8_get( + win, + ECORE_X_ATOM_NET_WM_ICON_NAME); + + return 1; +} + +EAPI void +ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, + const char *name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_window_prop_string_utf8_set(win, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, + name); +} + +EAPI int +ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, + char **name) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (name) + *name = _ecore_x_window_prop_string_utf8_get( + win, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME); + + return 1; +} + +EAPI void +ecore_x_netwm_desktop_set(Ecore_X_Window win, + unsigned int desk) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_desktop_get(Ecore_X_Window win, + unsigned int *desk) +{ + int ret; + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP, + &tmp, 1); + + if (desk) + *desk = tmp; + + return ret == 1 ? EINA_TRUE : EINA_FALSE; +} + +/* + * _NET_WM_STRUT is deprecated + */ +EAPI void +ecore_x_netwm_strut_set(Ecore_X_Window win, + int left, + int right, + int top, + int bottom) +{ + unsigned int strut[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + strut[0] = left; + strut[1] = right; + strut[2] = top; + strut[3] = bottom; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4); +} + +/* + * _NET_WM_STRUT is deprecated + */ +EAPI Eina_Bool +ecore_x_netwm_strut_get(Ecore_X_Window win, + int *left, + int *right, + int *top, + int *bottom) +{ + int ret = 0; + unsigned int strut[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_NET_WM_STRUT, + strut, + 4); + if (ret != 4) + return EINA_FALSE; + + if (left) + *left = strut[0]; + + if (right) + *right = strut[1]; + + if (top) + *top = strut[2]; + + if (bottom) + *bottom = strut[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_strut_partial_set(Ecore_X_Window win, + int left, + int right, + int top, + int bottom, + int left_start_y, + int left_end_y, + int right_start_y, + int right_end_y, + int top_start_x, + int top_end_x, + int bottom_start_x, + int bottom_end_x) +{ + unsigned int strut[12]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + strut[0] = left; + strut[1] = right; + strut[2] = top; + strut[3] = bottom; + strut[4] = left_start_y; + strut[5] = left_end_y; + strut[6] = right_start_y; + strut[7] = right_end_y; + strut[8] = top_start_x; + strut[9] = top_end_x; + strut[10] = bottom_start_x; + strut[11] = bottom_end_x; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, + strut, + 12); +} + +EAPI Eina_Bool +ecore_x_netwm_strut_partial_get(Ecore_X_Window win, + int *left, + int *right, + int *top, + int *bottom, + int *left_start_y, + int *left_end_y, + int *right_start_y, + int *right_end_y, + int *top_start_x, + int *top_end_x, + int *bottom_start_x, + int *bottom_end_x) +{ + int ret = 0; + unsigned int strut[12]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, + strut, + 12); + if (ret != 12) + return EINA_FALSE; + + if (left) + *left = strut[0]; + + if (right) + *right = strut[1]; + + if (top) + *top = strut[2]; + + if (bottom) + *bottom = strut[3]; + + if (left_start_y) + *left_start_y = strut[4]; + + if (left_end_y) + *left_end_y = strut[5]; + + if (right_start_y) + *right_start_y = strut[6]; + + if (right_end_y) + *right_end_y = strut[7]; + + if (top_start_x) + *top_start_x = strut[8]; + + if (top_end_x) + *top_end_x = strut[9]; + + if (bottom_start_x) + *bottom_start_x = strut[10]; + + if (bottom_end_x) + *bottom_end_x = strut[11]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_icons_set(Ecore_X_Window win, + Ecore_X_Icon *icon, + int num) +{ + unsigned int *data, *p, *p2; + unsigned int i, size, x, y; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + size = 0; + for (i = 0; i < (unsigned int)num; i++) + { + size += 2 + (icon[i].width * icon[i].height); + } + data = malloc(size * sizeof(unsigned int)); + if (!data) return; + p = data; + for (i = 0; i < (unsigned int)num; i++) + { + p[0] = icon[i].width; + p[1] = icon[i].height; + p += 2; + p2 = icon[i].data; + for (y = 0; y < icon[i].height; y++) + { + for (x = 0; x < icon[i].width; x++) + { + unsigned int r, g, b, a; + + a = (*p2 >> 24) & 0xff; + r = (*p2 >> 16) & 0xff; + g = (*p2 >> 8 ) & 0xff; + b = (*p2 ) & 0xff; + if ((a > 0) && (a < 255)) + { + // unpremul + r = (r * 255) / a; + g = (g * 255) / a; + b = (b * 255) / a; + } + *p = (a << 24) | (r << 16) | (g << 8) | b; + p++; + p2++; + } + } + } + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_ICON, + data, size); + free(data); +} + +EAPI Eina_Bool +ecore_x_netwm_icons_get(Ecore_X_Window win, + Ecore_X_Icon **icon, + int *num) +{ + unsigned int *data, *p; + unsigned int *src; + unsigned int len, icons, i; + int num_ret; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num) + *num = 0; + + if (icon) + *icon = NULL; + + num_ret = ecore_x_window_prop_card32_list_get(win, ECORE_X_ATOM_NET_WM_ICON, + &data); + if (num_ret <= 0) + return EINA_FALSE; + + if (!data) + return EINA_FALSE; + + if (num_ret < 2) + { + free(data); + return EINA_FALSE; + } + + /* Check how many icons there are */ + icons = 0; + p = data; + while (p) + { + len = p[0] * p[1]; + p += (len + 2); + if ((p - data) > num_ret) + { + free(data); + return EINA_FALSE; + } + + icons++; + + if ((p - data) == num_ret) + p = NULL; + } + if (num) + *num = icons; + + /* If the user doesn't want the icons, return */ + if (!icon) + { + free(data); + return EINA_TRUE; + } + + /* Allocate memory */ + *icon = malloc(icons * sizeof(Ecore_X_Icon)); + if (!(*icon)) + { + free(data); + return EINA_FALSE; + } + + /* Fetch the icons */ + p = data; + for (i = 0; i < icons; i++) + { + unsigned int *ps, *pd, *pe; + + len = p[0] * p[1]; + ((*icon)[i]).width = p[0]; + ((*icon)[i]).height = p[1]; + src = &(p[2]); + ((*icon)[i]).data = malloc(len * sizeof(unsigned int)); + if (!((*icon)[i]).data) + { + while (i) + free(((*icon)[--i]).data); + free(*icon); + free(data); + return EINA_FALSE; + } + + pd = ((*icon)[i]).data; + ps = src; + pe = ps + len; + for (; ps < pe; ps++) + { + unsigned int r, g, b, a; + + a = (*ps >> 24) & 0xff; + r = (((*ps >> 16) & 0xff) * a) / 255; + g = (((*ps >> 8) & 0xff) * a) / 255; + b = (((*ps) & 0xff) * a) / 255; + *pd = (a << 24) | (r << 16) | (g << 8) | (b); + pd++; + } + p += (len + 2); + } + + free(data); + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, + int x, + int y, + int width, + int height) +{ + unsigned int geometry[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + geometry[0] = x; + geometry[1] = y; + geometry[2] = width; + geometry[3] = height; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, + geometry, + 4); +} + +EAPI Eina_Bool +ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *width, + int *height) +{ + int ret; + unsigned int geometry[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, + geometry, + 4); + if (ret != 4) + return EINA_FALSE; + + if (x) + *x = geometry[0]; + + if (y) + *y = geometry[1]; + + if (width) + *width = geometry[2]; + + if (height) + *height = geometry[3]; + + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_pid_set(Ecore_X_Window win, + int pid) +{ + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + tmp = pid; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID, + &tmp, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_pid_get(Ecore_X_Window win, + int *pid) +{ + int ret; + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID, + &tmp, 1); + if (pid) + *pid = tmp; + + return ret == 1 ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_netwm_handled_icons_set(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); +} + +EAPI Eina_Bool +ecore_x_netwm_handled_icons_get(Ecore_X_Window win) +{ + int ret = 0; + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); + return ret == 0 ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_netwm_user_time_set(Ecore_X_Window win, + unsigned int tim) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME, + &tim, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_user_time_get(Ecore_X_Window win, + unsigned int *tim) +{ + int ret; + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME, + &tmp, 1); + if (tim) + *tim = tmp; + + return ret == 1 ? EINA_TRUE : EINA_FALSE; +} + +Ecore_X_Window_State +_ecore_x_netwm_state_get(Ecore_X_Atom a) +{ + if (a == ECORE_X_ATOM_NET_WM_STATE_MODAL) + return ECORE_X_WINDOW_STATE_MODAL; + else if (a == ECORE_X_ATOM_NET_WM_STATE_STICKY) + return ECORE_X_WINDOW_STATE_STICKY; + else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT) + return ECORE_X_WINDOW_STATE_MAXIMIZED_VERT; + else if (a == ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ) + return ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ; + else if (a == ECORE_X_ATOM_NET_WM_STATE_SHADED) + return ECORE_X_WINDOW_STATE_SHADED; + else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR) + return ECORE_X_WINDOW_STATE_SKIP_TASKBAR; + else if (a == ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER) + return ECORE_X_WINDOW_STATE_SKIP_PAGER; + else if (a == ECORE_X_ATOM_NET_WM_STATE_HIDDEN) + return ECORE_X_WINDOW_STATE_HIDDEN; + else if (a == ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN) + return ECORE_X_WINDOW_STATE_FULLSCREEN; + else if (a == ECORE_X_ATOM_NET_WM_STATE_ABOVE) + return ECORE_X_WINDOW_STATE_ABOVE; + else if (a == ECORE_X_ATOM_NET_WM_STATE_BELOW) + return ECORE_X_WINDOW_STATE_BELOW; + else if (a == ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION) + return ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION; + else + return ECORE_X_WINDOW_STATE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_x_netwm_state_atom_get(Ecore_X_Window_State s) +{ + switch (s) + { + case ECORE_X_WINDOW_STATE_MODAL: + return ECORE_X_ATOM_NET_WM_STATE_MODAL; + + case ECORE_X_WINDOW_STATE_STICKY: + return ECORE_X_ATOM_NET_WM_STATE_STICKY; + + case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT: + return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT; + + case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ: + return ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ; + + case ECORE_X_WINDOW_STATE_SHADED: + return ECORE_X_ATOM_NET_WM_STATE_SHADED; + + case ECORE_X_WINDOW_STATE_SKIP_TASKBAR: + return ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR; + + case ECORE_X_WINDOW_STATE_SKIP_PAGER: + return ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER; + + case ECORE_X_WINDOW_STATE_HIDDEN: + return ECORE_X_ATOM_NET_WM_STATE_HIDDEN; + + case ECORE_X_WINDOW_STATE_FULLSCREEN: + return ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN; + + case ECORE_X_WINDOW_STATE_ABOVE: + return ECORE_X_ATOM_NET_WM_STATE_ABOVE; + + case ECORE_X_WINDOW_STATE_BELOW: + return ECORE_X_ATOM_NET_WM_STATE_BELOW; + + case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION: + return ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION; + + default: + return 0; + } +} + +EAPI void +ecore_x_netwm_window_state_set(Ecore_X_Window win, + Ecore_X_Window_State *state, + unsigned int num) +{ + Ecore_X_Atom *set; + unsigned int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!num) + { + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE); + return; + } + + set = malloc(num * sizeof(Ecore_X_Atom)); + if (!set) + return; + + for (i = 0; i < num; i++) + set[i] = _ecore_x_netwm_state_atom_get(state[i]); + + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_STATE, set, num); + + free(set); +} + +EAPI Eina_Bool +ecore_x_netwm_window_state_get(Ecore_X_Window win, + Ecore_X_Window_State **state, + unsigned int *num) +{ + int num_ret, i; + Ecore_X_Atom *atoms; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num) + *num = 0; + + if (state) + *state = NULL; + + num_ret = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_STATE, + &atoms); + if (num_ret <= 0) + return EINA_FALSE; + + if (state) + { + *state = malloc(num_ret * sizeof(Ecore_X_Window_State)); + if (*state) + for (i = 0; i < num_ret; ++i) + (*state)[i] = _ecore_x_netwm_state_get(atoms[i]); + + if (num) + *num = num_ret; + } + + free(atoms); + return EINA_TRUE; +} + +static Ecore_X_Window_Type +_ecore_x_netwm_window_type_type_get(Ecore_X_Atom atom) +{ + if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP) + return ECORE_X_WINDOW_TYPE_DESKTOP; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK) + return ECORE_X_WINDOW_TYPE_DOCK; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR) + return ECORE_X_WINDOW_TYPE_TOOLBAR; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU) + return ECORE_X_WINDOW_TYPE_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY) + return ECORE_X_WINDOW_TYPE_UTILITY; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH) + return ECORE_X_WINDOW_TYPE_SPLASH; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG) + return ECORE_X_WINDOW_TYPE_DIALOG; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL) + return ECORE_X_WINDOW_TYPE_NORMAL; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU) + return ECORE_X_WINDOW_TYPE_DROPDOWN_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU) + return ECORE_X_WINDOW_TYPE_POPUP_MENU; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP) + return ECORE_X_WINDOW_TYPE_TOOLTIP; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION) + return ECORE_X_WINDOW_TYPE_NOTIFICATION; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO) + return ECORE_X_WINDOW_TYPE_COMBO; + else if (atom == ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND) + return ECORE_X_WINDOW_TYPE_DND; + else + return ECORE_X_WINDOW_TYPE_UNKNOWN; +} + +static Ecore_X_Atom +_ecore_x_netwm_window_type_atom_get(Ecore_X_Window_Type type) +{ + switch (type) + { + case ECORE_X_WINDOW_TYPE_DESKTOP: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP; + + case ECORE_X_WINDOW_TYPE_DOCK: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK; + + case ECORE_X_WINDOW_TYPE_TOOLBAR: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; + + case ECORE_X_WINDOW_TYPE_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU; + + case ECORE_X_WINDOW_TYPE_UTILITY: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY; + + case ECORE_X_WINDOW_TYPE_SPLASH: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH; + + case ECORE_X_WINDOW_TYPE_DIALOG: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG; + + case ECORE_X_WINDOW_TYPE_NORMAL: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL; + + case ECORE_X_WINDOW_TYPE_DROPDOWN_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DROPDOWN_MENU; + + case ECORE_X_WINDOW_TYPE_POPUP_MENU: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_POPUP_MENU; + + case ECORE_X_WINDOW_TYPE_TOOLTIP: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLTIP; + + case ECORE_X_WINDOW_TYPE_NOTIFICATION: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NOTIFICATION; + + case ECORE_X_WINDOW_TYPE_COMBO: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_COMBO; + + case ECORE_X_WINDOW_TYPE_DND: + return ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DND; + + default: + return 0; + } +} + +/* + * FIXME: We should set WM_TRANSIENT_FOR if type is ECORE_X_WINDOW_TYPE_TOOLBAR + * , ECORE_X_WINDOW_TYPE_MENU or ECORE_X_WINDOW_TYPE_DIALOG + */ +EAPI void +ecore_x_netwm_window_type_set(Ecore_X_Window win, + Ecore_X_Window_Type type) +{ + Ecore_X_Atom atom; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + atom = _ecore_x_netwm_window_type_atom_get(type); + ecore_x_window_prop_atom_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atom, 1); +} + +/* FIXME: Maybe return 0 on some conditions? */ +EAPI Eina_Bool +ecore_x_netwm_window_type_get(Ecore_X_Window win, + Ecore_X_Window_Type *type) +{ + int num; + Ecore_X_Atom *atoms = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (type) + *type = ECORE_X_WINDOW_TYPE_NORMAL; + + num = ecore_x_window_prop_atom_list_get(win, + ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atoms); + if ((type) && (num >= 1) && (atoms)) + *type = _ecore_x_netwm_window_type_type_get(atoms[0]); + + free(atoms); + if (num >= 1) + return EINA_TRUE; + + return EINA_FALSE; +} + +EAPI int +ecore_x_netwm_window_types_get(Ecore_X_Window win, + Ecore_X_Window_Type **types) +{ + int num, i; + Ecore_X_Atom *atoms = NULL; + Ecore_X_Window_Type *atoms2 = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (types) + *types = NULL; + + num = ecore_x_window_prop_atom_list_get(win, + ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atoms); + if ((num <= 0) || (!atoms)) + { + if (atoms) + free(atoms); + + return 0; + } + + atoms2 = malloc(num * sizeof(Ecore_X_Window_Type)); + if (!atoms2) + return 0; + + for (i = 0; i < num; i++) + atoms2[i] = _ecore_x_netwm_window_type_type_get(atoms[i]); + free(atoms); + if (types) + *types = atoms2; + else + free(atoms2); + + return num; +} + +static Ecore_X_Atom +_ecore_x_netwm_action_atom_get(Ecore_X_Action action) +{ + switch (action) + { + case ECORE_X_ACTION_MOVE: + return ECORE_X_ATOM_NET_WM_ACTION_MOVE; + + case ECORE_X_ACTION_RESIZE: + return ECORE_X_ATOM_NET_WM_ACTION_RESIZE; + + case ECORE_X_ACTION_MINIMIZE: + return ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; + + case ECORE_X_ACTION_SHADE: + return ECORE_X_ATOM_NET_WM_ACTION_SHADE; + + case ECORE_X_ACTION_STICK: + return ECORE_X_ATOM_NET_WM_ACTION_STICK; + + case ECORE_X_ACTION_MAXIMIZE_HORZ: + return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; + + case ECORE_X_ACTION_MAXIMIZE_VERT: + return ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; + + case ECORE_X_ACTION_FULLSCREEN: + return ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; + + case ECORE_X_ACTION_CHANGE_DESKTOP: + return ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; + + case ECORE_X_ACTION_CLOSE: + return ECORE_X_ATOM_NET_WM_ACTION_CLOSE; + + case ECORE_X_ACTION_ABOVE: + return ECORE_X_ATOM_NET_WM_ACTION_ABOVE; + + case ECORE_X_ACTION_BELOW: + return ECORE_X_ATOM_NET_WM_ACTION_BELOW; + + default: + return 0; + } +} + +/* FIXME: Get complete list */ +EAPI Eina_Bool +ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, + Ecore_X_Action action) +{ + int num, i; + Ecore_X_Atom *atoms, atom; + Eina_Bool ret = EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + num = ecore_x_window_prop_atom_list_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + &atoms); + if (num <= 0) + return ret; + + atom = _ecore_x_netwm_action_atom_get(action); + + for (i = 0; i < num; ++i) + { + if (atom == atoms[i]) + { + ret = 1; + break; + } + } + + free(atoms); + return ret; +} + +/* FIXME: Set complete list */ +EAPI void +ecore_x_netwm_allowed_action_set(Ecore_X_Window win, + Ecore_X_Action *action, + unsigned int num) +{ + Ecore_X_Atom *set; + unsigned int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!num) + { + ecore_x_window_prop_property_del(win, + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS); + return; + } + + set = malloc(num * sizeof(Ecore_X_Atom)); + if (!set) + return; + + for (i = 0; i < num; i++) + set[i] = _ecore_x_netwm_action_atom_get(action[i]); + + ecore_x_window_prop_atom_set(win, + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + set, + num); + + free(set); +} + +EAPI Eina_Bool +ecore_x_netwm_allowed_action_get(Ecore_X_Window win, + Ecore_X_Action **action, + unsigned int *num) +{ + int num_ret, i; + Ecore_X_Atom *atoms; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num) + *num = 0; + + if (action) + *action = NULL; + + num_ret = ecore_x_window_prop_atom_list_get( + win, + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + &atoms); + if (num_ret <= 0) + return EINA_FALSE; + + if (action) + { + *action = malloc(num_ret * sizeof(Ecore_X_Action)); + if (*action) + for (i = 0; i < num_ret; ++i) + (*action)[i] = _ecore_x_netwm_action_atom_get(atoms[i]); + + if (num) + *num = num_ret; + } + + free(atoms); + return EINA_TRUE; +} + +EAPI void +ecore_x_netwm_opacity_set(Ecore_X_Window win, + unsigned int opacity) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &opacity, 1); +} + +EAPI Eina_Bool +ecore_x_netwm_opacity_get(Ecore_X_Window win, + unsigned int *opacity) +{ + int ret; + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &tmp, 1); + if (opacity) + *opacity = tmp; + + return ret == 1 ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_netwm_frame_size_set(Ecore_X_Window win, + int fl, + int fr, + int ft, + int fb) +{ + unsigned int frames[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + frames[0] = fl; + frames[1] = fr; + frames[2] = ft; + frames[3] = fb; + ecore_x_window_prop_card32_set(win, + ECORE_X_ATOM_NET_FRAME_EXTENTS, + frames, + 4); +} + +EAPI Eina_Bool +ecore_x_netwm_frame_size_get(Ecore_X_Window win, + int *fl, + int *fr, + int *ft, + int *fb) +{ + int ret = 0; + unsigned int frames[4]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get(win, + ECORE_X_ATOM_NET_FRAME_EXTENTS, + frames, + 4); + if (ret != 4) + return EINA_FALSE; + + if (fl) + *fl = frames[0]; + + if (fr) + *fr = frames[1]; + + if (ft) + *ft = frames[2]; + + if (fb) + *fb = frames[3]; + + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_netwm_sync_counter_get(Ecore_X_Window win, + Ecore_X_Sync_Counter *counter) +{ + int ret; + unsigned int tmp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ret = ecore_x_window_prop_card32_get( + win, + ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER, + &tmp, + 1); + + if (counter) + *counter = tmp; + + return ret == 1 ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_netwm_ping_send(Ecore_X_Window win) +{ + XEvent xev; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS; + xev.xclient.format = 32; + xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_PING; + xev.xclient.data.l[1] = _ecore_x_event_last_time; + xev.xclient.data.l[2] = win; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + + XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev); +} + +EAPI void +ecore_x_netwm_sync_request_send(Ecore_X_Window win, + unsigned int serial) +{ + XSyncValue value; + XEvent xev; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncIntToValue(&value, (int)serial); + + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS; + xev.xclient.format = 32; + xev.xclient.data.l[0] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST; + xev.xclient.data.l[1] = _ecore_x_event_last_time; + xev.xclient.data.l[2] = XSyncValueLow32(value); + xev.xclient.data.l[3] = XSyncValueHigh32(value); + xev.xclient.data.l[4] = 0; + + XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev); +} + +EAPI void +ecore_x_netwm_state_request_send(Ecore_X_Window win, + Ecore_X_Window root, + Ecore_X_Window_State s1, + Ecore_X_Window_State s2, + Eina_Bool set) +{ + XEvent xev; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.format = 32; + xev.xclient.message_type = ECORE_X_ATOM_NET_WM_STATE; + xev.xclient.data.l[0] = !!set; + xev.xclient.data.l[1] = _ecore_x_netwm_state_atom_get(s1); + xev.xclient.data.l[2] = _ecore_x_netwm_state_atom_get(s2); + /* 1 == normal client, if someone wants to use this + * function in a pager, this should be 2 */ + xev.xclient.data.l[3] = 1; + xev.xclient.data.l[4] = 0; + + XSendEvent(_ecore_x_disp, root, False, + SubstructureNotifyMask | SubstructureRedirectMask, &xev); +} + +EAPI void +ecore_x_netwm_desktop_request_send(Ecore_X_Window win, + Ecore_X_Window root, + unsigned int desktop) +{ + XEvent xev; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!root) + root = DefaultRootWindow(_ecore_x_disp); + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.format = 32; + xev.xclient.message_type = ECORE_X_ATOM_NET_WM_DESKTOP; + xev.xclient.data.l[0] = desktop; + + XSendEvent(_ecore_x_disp, root, False, + SubstructureNotifyMask | SubstructureRedirectMask, &xev); +} + +EAPI void +ecore_x_netwm_moveresize_request_send(Ecore_X_Window win, + int x, + int y, + Ecore_X_Netwm_Direction direction, + unsigned int button) +{ + XEvent xev; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.window = win; + xev.xclient.type = ClientMessage; + xev.xclient.message_type = ECORE_X_ATOM_NET_WM_MOVERESIZE; + xev.xclient.format = 32; + xev.xclient.data.l[0] = x; + xev.xclient.data.l[1] = y; + xev.xclient.data.l[2] = direction; + xev.xclient.data.l[3] = button; + xev.xclient.data.l[4] = 1; + + XSendEvent(_ecore_x_disp, win, False, + SubstructureNotifyMask | SubstructureRedirectMask, &xev); +} + +int +_ecore_x_netwm_startup_info_begin(Ecore_X_Window win EINA_UNUSED, + char *data EINA_UNUSED) +{ +#if 0 + Ecore_X_Startup_Info *info; + unsigned char *exists = 0; + + if (!startup_info) + return 0; + + info = eina_hash_find(startup_info, (void *)win); + if (info) + { + exists = 1; + WRN("Already got info for win: 0x%x", win); + _ecore_x_netwm_startup_info_free(info); + } + + info = calloc(1, sizeof(Ecore_X_Startup_Info)); + if (!info) + return 0; + + info->win = win; + info->length = 0; + info->buffer_size = 161; + info->buffer = calloc(info->buffer_size, sizeof(char)); + if (!info->buffer) + { + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + memcpy(info->buffer, data, 20); + info->length += 20; + info->buffer[info->length] = 0; + if (exists) + eina_hash_modify(startup_info, (void *)info->win, info); + else + eina_hash_add(startup_info, (void *)info->win, info); + + if (strlen(info->buffer) != 20) + /* We have a '\0' in there, the message is done */ + _ecore_x_netwm_startup_info_process(info); + +#endif /* if 0 */ + return 1; +} + +int +_ecore_x_netwm_startup_info(Ecore_X_Window win EINA_UNUSED, + char *data EINA_UNUSED) +{ +#if 0 + Ecore_X_Startup_Info *info; + char *p; + + if (!startup_info) + return 0; + + info = eina_hash_find(startup_info, (void *)win); + if (!info) + return 0; + + if ((info->length + 20) > info->buffer_size) + { + info->buffer_size += 160; + info->buffer = realloc(info->buffer, info->buffer_size * sizeof(char)); + if (!info->buffer) + { + eina_hash_del(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + } + + memcpy(info->buffer + info->length, data, 20); + p = info->buffer + info->length; + info->length += 20; + info->buffer[info->length] = 0; + if (strlen(p) != 20) + /* We have a '\0' in there, the message is done */ + _ecore_x_netwm_startup_info_process(info); + +#endif /* if 0 */ + return 1; +} + +/* + * Set UTF-8 string property + */ +static void +_ecore_x_window_prop_string_utf8_set(Ecore_X_Window win, + Ecore_X_Atom atom, + const char *str) +{ + XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8, + PropModeReplace, (unsigned char *)str, strlen(str)); +} + +/* + * Get UTF-8 string property + */ +static char * +_ecore_x_window_prop_string_utf8_get(Ecore_X_Window win, + Ecore_X_Atom atom) +{ + char *str; + unsigned char *prop_ret; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + + str = NULL; + prop_ret = NULL; + XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False, + ECORE_X_ATOM_UTF8_STRING, &type_ret, + &format_ret, &num_ret, &bytes_after, &prop_ret); + if (prop_ret && num_ret > 0 && format_ret == 8) + { + str = malloc(num_ret + 1); + if (str) + { + memcpy(str, prop_ret, num_ret); + str[num_ret] = '\0'; + } + } + + if (prop_ret) + XFree(prop_ret); + + return str; +} + +#if 0 /* Unused */ +/* + * Process startup info + */ +static int +_ecore_x_netwm_startup_info_process(Ecore_X_Startup_Info *info) +{ + Ecore_X_Event_Startup_Sequence *e; + int event; + char *p; + + p = strchr(info->buffer, ':'); + if (!p) + { + eina_hash_del(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + *p = 0; + if (!strcmp(info->buffer, "new")) + { + if (info->init) + event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE; + else + event = ECORE_X_EVENT_STARTUP_SEQUENCE_NEW; + + info->init = 1; + } + else if (!strcmp(info->buffer, "change")) + event = ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE; + else if (!strcmp(info->buffer, "remove")) + event = ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE; + else + { + eina_hash_del(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + p++; + + if (!_ecore_x_netwm_startup_info_parse(info, p)) + { + eina_hash_del(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + if (info->init) + { + e = calloc(1, sizeof(Ecore_X_Event_Startup_Sequence)); + if (!e) + { + eina_hash_del(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + return 0; + } + + e->win = info->win; + ecore_event_add(event, e, NULL, NULL); + } + + if (event == ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE) + { + eina_hash_del(startup_info, (void *)info->win); + _ecore_x_netwm_startup_info_free(info); + } + else + { + /* Discard buffer */ + info->length = 0; + info->buffer[0] = 0; + } + + return 1; +} + +/* + * Parse startup info + */ +static int +_ecore_x_netwm_startup_info_parse(Ecore_X_Startup_Info *info, + char *data) +{ + while (*data) + { + int in_quot_sing, in_quot_dbl, escaped; + char *p, *pp; + char *key; + char value[1024]; + + /* Skip space */ + while (*data == ' ') + data++; + /* Get key */ + key = data; + data = strchr(key, '='); + if (!data) + return 0; + + *data = 0; + data++; + + /* Get value */ + p = data; + pp = value; + in_quot_dbl = 0; + in_quot_sing = 0; + escaped = 0; + while (*p) + { + if ((pp - value) >= 1024) + return 0; + + if (escaped) + { + *pp = *p; + pp++; + escaped = 0; + } + else if (in_quot_sing) + { + if (*p == '\\') + escaped = 1; + else if (*p == '\'') + in_quot_sing = 0; + else + { + *pp = *p; + pp++; + } + } + else if (in_quot_dbl) + { + if (*p == '\\') + escaped = 1; + else if (*p == '\"') + in_quot_dbl = 0; + else + { + *pp = *p; + pp++; + } + } + else + { + if (*p == '\\') + escaped = 1; + else if (*p == '\'') + in_quot_sing = 1; + else if (*p == '\"') + in_quot_dbl = 1; + else if (*p == ' ') + break; + else + { + *pp = *p; + pp++; + } + } + + p++; + } + if ((in_quot_dbl) || (in_quot_sing)) + return 0; + + data = p; + *pp = 0; + + /* Parse info */ + if (!strcmp(key, "ID")) + { + if ((info->id) && (strcmp(info->id, value))) + return 0; + + info->id = strdup(value); + p = strstr(value, "_TIME"); + if (p) + info->timestamp = atoi(p + 5); + } + else if (!strcmp(key, "NAME")) + { + if (info->name) + free(info->name); + + info->name = strdup(value); + } + else if (!strcmp(key, "SCREEN")) + info->screen = atoi(value); + else if (!strcmp(key, "BIN")) + { + if (info->bin) + free(info->bin); + + info->bin = strdup(value); + } + else if (!strcmp(key, "ICON")) + { + if (info->icon) + free(info->icon); + + info->icon = strdup(value); + } + else if (!strcmp(key, "DESKTOP")) + info->desktop = atoi(value); + else if (!strcmp(key, "TIMESTAMP")) + { + if (!info->timestamp) + info->timestamp = atoi(value); + } + else if (!strcmp(key, "DESCRIPTION")) + { + if (info->description) + free(info->description); + + info->description = strdup(value); + } + else if (!strcmp(key, "WMCLASS")) + { + if (info->wmclass) + free(info->wmclass); + + info->wmclass = strdup(value); + } + else if (!strcmp(key, "SILENT")) + info->silent = atoi(value); + else + ERR("Ecore X Sequence, Unknown: %s=%s", key, value); + } + if (!info->id) + return 0; + + return 1; +} + +#endif /* if 0 */ + +/* + * Free startup info struct + */ +static void +_ecore_x_netwm_startup_info_free(void *data) +{ + Ecore_X_Startup_Info *info; + + info = data; + if (!info) + return; + + if (info->buffer) + free(info->buffer); + + if (info->id) + free(info->id); + + if (info->name) + free(info->name); + + if (info->bin) + free(info->bin); + + if (info->icon) + free(info->icon); + + if (info->description) + free(info->description); + + if (info->wmclass) + free(info->wmclass); + + free(info); +} + +/* + * Is screen composited? + */ +EAPI Eina_Bool +ecore_x_screen_is_composited(int screen) +{ + Ecore_X_Window win; + static Ecore_X_Atom atom = None; + char buf[32]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen); + if (atom == None) + atom = XInternAtom(_ecore_x_disp, buf, False); + + if (atom == None) + return EINA_FALSE; + + win = XGetSelectionOwner(_ecore_x_disp, atom); + + return (win != None) ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_screen_is_composited_set(int screen, + Ecore_X_Window win) +{ + static Ecore_X_Atom atom = None; + char buf[32]; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + snprintf(buf, sizeof(buf), "_NET_WM_CM_S%i", screen); + if (atom == None) + atom = XInternAtom(_ecore_x_disp, buf, False); + + if (atom == None) + return; + + XSetSelectionOwner(_ecore_x_disp, atom, win, _ecore_x_event_last_time); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_pixmap.c b/src/lib/ecore_x/xlib/ecore_x_pixmap.c new file mode 100644 index 0000000000..7b13615675 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_pixmap.c @@ -0,0 +1,121 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +/** + * @defgroup Ecore_X_Pixmap_Group X Pixmap Functions + * + * Functions that operate on pixmaps. + */ + +/** + * Creates a new pixmap. + * @param win Window used to determine which screen of the display the + * pixmap should be created on. If 0, the default root window + * is used. + * @param w Width of the new pixmap. + * @param h Height of the new pixmap. + * @param dep Depth of the pixmap. If 0, the default depth of the default + * screen is used. + * @return New pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI Ecore_X_Pixmap +ecore_x_pixmap_new(Ecore_X_Window win, + int w, + int h, + int dep) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); + + if (dep == 0) + dep = DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)); + + return XCreatePixmap(_ecore_x_disp, win, w, h, dep); +} + +/** + * Deletes the reference to the given pixmap. + * + * If no other clients have a reference to the given pixmap, the server + * will destroy it. + * + * @param pmap The given pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_free(Ecore_X_Pixmap pmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XFreePixmap(_ecore_x_disp, pmap); +} + +/** + * Pastes a rectangular area of the given pixmap onto the given drawable. + * @param pmap The given pixmap. + * @param dest The given drawable. + * @param gc The graphics context which governs which operation will + * be used to paste the area onto the drawable. + * @param sx The X position of the area on the pixmap. + * @param sy The Y position of the area on the pixmap. + * @param w The width of the area. + * @param h The height of the area. + * @param dx The X position at which to paste the area on @p dest. + * @param dy The Y position at which to paste the area on @p dest. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_paste(Ecore_X_Pixmap pmap, + Ecore_X_Drawable dest, + Ecore_X_GC gc, + int sx, + int sy, + int w, + int h, + int dx, + int dy) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XCopyArea(_ecore_x_disp, pmap, dest, gc, sx, sy, w, h, dx, dy); +} + +/** + * Retrieves the size of the given pixmap. + * @param pmap The given pixmap. + * @param x Pointer to an integer in which to store the X position. + * @param y Pointer to an integer in which to store the Y position. + * @param w Pointer to an integer in which to store the width. + * @param h Pointer to an integer in which to store the height. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI void +ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, + int *x, + int *y, + int *w, + int *h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (pmap) + ecore_x_drawable_geometry_get(pmap, x, y, w, h); +} + +/** + * Retrieves the depth of the given pixmap. + * @param pmap The given pixmap. + * @return The depth of the pixmap. + * @ingroup Ecore_X_Pixmap_Group + */ +EAPI int +ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_drawable_depth_get(pmap); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_private.h b/src/lib/ecore_x/xlib/ecore_x_private.h new file mode 100644 index 0000000000..f962ffb4b2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_private.h @@ -0,0 +1,379 @@ +#ifndef _ECORE_X_PRIVATE_H +#define _ECORE_X_PRIVATE_H + +#include <sys/param.h> +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif /* ifndef MAXHOSTNAMELEN */ + +#include <X11/Xlib.h> +#include <X11/Xproto.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Xresource.h> +#include <X11/keysymdef.h> +#include <X11/extensions/XShm.h> +#include <X11/extensions/shape.h> +#include <X11/extensions/sync.h> +#include <X11/extensions/dpms.h> +#ifdef ECORE_XCURSOR +#include <X11/Xcursor/Xcursor.h> +#endif /* ifdef ECORE_XCURSOR */ +#ifdef ECORE_XPRINT +#include <X11/extensions/Print.h> +#endif /* ifdef ECORE_XPRINT */ +#ifdef ECORE_XINERAMA +#include <X11/extensions/Xinerama.h> +#endif /* ifdef ECORE_XINERAMA */ +#ifdef ECORE_XRANDR +#include <X11/extensions/Xrandr.h> +#endif /* ifdef ECORE_XRANDR */ +#ifdef ECORE_XSS +#include <X11/extensions/scrnsaver.h> +#endif /* ifdef ECORE_XSS */ +#ifdef ECORE_XRENDER +#include <X11/extensions/Xrender.h> +#endif /* ifdef ECORE_XRENDER */ +#ifdef ECORE_XFIXES +#include <X11/extensions/Xfixes.h> +#endif /* ifdef ECORE_XFIXES */ +#ifdef ECORE_XCOMPOSITE +#include <X11/extensions/Xcomposite.h> +#endif /* ifdef ECORE_XCOMPOSITE */ +#ifdef ECORE_XDAMAGE +#include <X11/extensions/Xdamage.h> +#endif /* ifdef ECORE_XDAMAGE */ +#ifdef ECORE_XGESTURE +#include <X11/extensions/gesture.h> +#include <X11/extensions/gestureproto.h> +#endif /* ifdef ECORE_XGESTURE */ +#ifdef ECORE_XDPMS +#include <X11/extensions/dpms.h> +#endif /* ifdef ECORE_XDPMS */ +#ifdef ECORE_XKB +#include <X11/XKBlib.h> +#endif /* ifdef ECORE_XKB */ +#ifdef ECORE_XI2 +#include <X11/extensions/XInput2.h> +#endif /* ifdef ECORE_XI2 */ + +#ifndef XK_MISCELLANY +# define XK_MISCELLANY 1 +#endif + +#include "Ecore.h" +#include "ecore_private.h" +#include "Ecore_X.h" +#include "Ecore_Input.h" + +extern int _ecore_xlib_log_dom; +#ifdef ECORE_XLIB_DEFAULT_LOG_COLOR +# undef ECORE_XLIB_DEFAULT_LOG_COLOR +#endif /* ifdef ECORE_XLIB_DEFAULT_LOG_COLOR */ +#define ECORE_XLIB_DEFAULT_LOG_COLOR EINA_COLOR_BLUE + +#ifdef ERR +# undef ERR +#endif /* ifdef ERR */ +#define ERR(...) EINA_LOG_DOM_ERR(_ecore_xlib_log_dom, __VA_ARGS__) + +#ifdef DBG +# undef DBG +#endif /* ifdef DBG */ +#define DBG(...) EINA_LOG_DOM_DBG(_ecore_xlib_log_dom, __VA_ARGS__) + +#ifdef INF +# undef INF +#endif /* ifdef INF */ +#define INF(...) EINA_LOG_DOM_INFO(_ecore_xlib_log_dom, __VA_ARGS__) + +#ifdef WRN +# undef WRN +#endif /* ifdef WRN */ +#define WRN(...) EINA_LOG_DOM_WARN(_ecore_xlib_log_dom, __VA_ARGS__) + +#ifdef CRIT +# undef CRIT +#endif /* ifdef CRIT */ +#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_xlib_log_dom, __VA_ARGS__) + +typedef struct _Ecore_X_Selection_Intern Ecore_X_Selection_Intern; + +struct _Ecore_X_Selection_Intern +{ + Ecore_X_Window win; + Ecore_X_Atom selection; + unsigned char *data; + int length; + Time time; +}; + +typedef struct _Ecore_X_Selection_Converter Ecore_X_Selection_Converter; + +struct _Ecore_X_Selection_Converter +{ + Ecore_X_Atom target; + Eina_Bool (*convert)(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *type, int *typeseize); + Ecore_X_Selection_Converter *next; +}; + +typedef struct _Ecore_X_Selection_Parser Ecore_X_Selection_Parser; + +struct _Ecore_X_Selection_Parser +{ + char *target; + void *(*parse)(const char *target, void *data, int size, int format); + Ecore_X_Selection_Parser *next; +}; + +typedef struct _Ecore_X_DND_Source +{ + int version; + Ecore_X_Window win, dest; + + enum { + ECORE_X_DND_SOURCE_IDLE, + ECORE_X_DND_SOURCE_DRAGGING, + ECORE_X_DND_SOURCE_DROPPED, + ECORE_X_DND_SOURCE_CONVERTING + } state; + + struct + { + short x, y; + unsigned short width, height; + } rectangle; + + struct + { + Ecore_X_Window window; + int x, y; + } prev; + + Time time; + + Ecore_X_Atom action, accepted_action; + + int will_accept; + int suppress; + + int await_status; +} Ecore_X_DND_Source; + +typedef struct _Ecore_X_DND_Target +{ + int version; + Ecore_X_Window win, source; + + enum { + ECORE_X_DND_TARGET_IDLE, + ECORE_X_DND_TARGET_ENTERED + } state; + + struct + { + int x, y; + } pos; + + Time time; + + Ecore_X_Atom action, accepted_action; + + int will_accept; +} Ecore_X_DND_Target; + +extern Display *_ecore_x_disp; +extern double _ecore_x_double_click_time; +extern Time _ecore_x_event_last_time; +extern Window _ecore_x_event_last_win; +extern int _ecore_x_event_last_root_x; +extern int _ecore_x_event_last_root_y; +extern Eina_Bool _ecore_x_xcursor; + +extern Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; + +extern int _ecore_window_grabs_num; +extern Window *_ecore_window_grabs; +extern Eina_Bool (*_ecore_window_grab_replay_func)(void *data, + int event_type, + void *event); +extern void *_ecore_window_grab_replay_data; + +extern Ecore_X_Window _ecore_x_private_win; + +void _ecore_x_error_handler_init(void); +void _ecore_x_event_handle_any_event(XEvent *xevent); +void _ecore_x_event_handle_key_press(XEvent *xevent); +void _ecore_x_event_handle_key_release(XEvent *xevent); +void _ecore_x_event_handle_button_press(XEvent *xevent); +void _ecore_x_event_handle_button_release(XEvent *xevent); +void _ecore_x_event_handle_motion_notify(XEvent *xevent); +void _ecore_x_event_handle_enter_notify(XEvent *xevent); +void _ecore_x_event_handle_leave_notify(XEvent *xevent); +void _ecore_x_event_handle_focus_in(XEvent *xevent); +void _ecore_x_event_handle_focus_out(XEvent *xevent); +void _ecore_x_event_handle_keymap_notify(XEvent *xevent); +void _ecore_x_event_handle_expose(XEvent *xevent); +void _ecore_x_event_handle_graphics_expose(XEvent *xevent); +void _ecore_x_event_handle_visibility_notify(XEvent *xevent); +void _ecore_x_event_handle_create_notify(XEvent *xevent); +void _ecore_x_event_handle_destroy_notify(XEvent *xevent); +void _ecore_x_event_handle_unmap_notify(XEvent *xevent); +void _ecore_x_event_handle_map_notify(XEvent *xevent); +void _ecore_x_event_handle_map_request(XEvent *xevent); +void _ecore_x_event_handle_reparent_notify(XEvent *xevent); +void _ecore_x_event_handle_configure_notify(XEvent *xevent); +void _ecore_x_event_handle_configure_request(XEvent *xevent); +void _ecore_x_event_handle_gravity_notify(XEvent *xevent); +void _ecore_x_event_handle_resize_request(XEvent *xevent); +void _ecore_x_event_handle_circulate_notify(XEvent *xevent); +void _ecore_x_event_handle_circulate_request(XEvent *xevent); +void _ecore_x_event_handle_property_notify(XEvent *xevent); +void _ecore_x_event_handle_selection_clear(XEvent *xevent); +void _ecore_x_event_handle_selection_request(XEvent *xevent); +void _ecore_x_event_handle_selection_notify(XEvent *xevent); +void _ecore_x_event_handle_colormap_notify(XEvent *xevent); +void _ecore_x_event_handle_client_message(XEvent *xevent); +void _ecore_x_event_handle_mapping_notify(XEvent *xevent); +void _ecore_x_event_handle_shape_change(XEvent *xevent); +void _ecore_x_event_handle_screensaver_notify(XEvent *xevent); +#ifdef ECORE_XGESTURE +void _ecore_x_event_handle_gesture_notify_flick(XEvent *xevent); +void _ecore_x_event_handle_gesture_notify_pan(XEvent *xevent); +void _ecore_x_event_handle_gesture_notify_pinchrotation(XEvent *xevent); +void _ecore_x_event_handle_gesture_notify_tap(XEvent *xevent); +void _ecore_x_event_handle_gesture_notify_tapnhold(XEvent *xevent); +void _ecore_x_event_handle_gesture_notify_hold(XEvent *xevent); +void _ecore_x_event_handle_gesture_notify_group(XEvent *xevent); +#endif /* ifdef ECORE_XGESTURE */ +void _ecore_x_event_handle_sync_counter(XEvent *xevent); +void _ecore_x_event_handle_sync_alarm(XEvent *xevent); +#ifdef ECORE_XRANDR +void _ecore_x_event_handle_randr_change(XEvent *xevent); +void _ecore_x_event_handle_randr_notify(XEvent *xevent); +#endif /* ifdef ECORE_XRANDR */ +#ifdef ECORE_XFIXES +void _ecore_x_event_handle_fixes_selection_notify(XEvent *xevent); +#endif /* ifdef ECORE_XFIXES */ +#ifdef ECORE_XDAMAGE +void _ecore_x_event_handle_damage_notify(XEvent *xevent); +#endif /* ifdef ECORE_XDAMAGE */ +#ifdef ECORE_XKB +void _ecore_x_event_handle_xkb(XEvent *xevent); +#endif /* ifdef ECORE_XKB */ +void _ecore_x_event_handle_generic_event(XEvent *xevent); + +void _ecore_x_selection_data_init(void); +void _ecore_x_selection_shutdown(void); +Ecore_X_Atom _ecore_x_selection_target_atom_get(const char *target); +char *_ecore_x_selection_target_get(Ecore_X_Atom target); +Ecore_X_Selection_Intern *_ecore_x_selection_get(Ecore_X_Atom selection); +Eina_Bool _ecore_x_selection_set(Window w, + const void *data, + int len, + Ecore_X_Atom selection); +int _ecore_x_selection_convert(Ecore_X_Atom selection, + Ecore_X_Atom target, + void **data_ret, + Ecore_X_Atom *targettype, + int *targetsize); +void *_ecore_x_selection_parse(const char *target, + void *data, + int size, + int format); + +void _ecore_x_sync_magic_send(int val, + Ecore_X_Window swin); +void _ecore_x_window_grab_remove(Ecore_X_Window win); +void _ecore_x_key_grab_remove(Ecore_X_Window win); + +/* from dnd */ +void _ecore_x_dnd_init(void); +Ecore_X_DND_Source *_ecore_x_dnd_source_get(void); +Ecore_X_DND_Target *_ecore_x_dnd_target_get(void); +void _ecore_x_dnd_drag(Ecore_X_Window root, + int x, + int y); +void _ecore_x_dnd_shutdown(void); + +/* from netwm */ +Ecore_X_Window_State _ecore_x_netwm_state_get(Ecore_X_Atom a); +int _ecore_x_netwm_startup_info_begin(Ecore_X_Window win, + char *data); +int _ecore_x_netwm_startup_info(Ecore_X_Window win, + char *data); + +/* Fixes * Damage * Composite * DPMS */ +void _ecore_x_fixes_init(void); +void _ecore_x_damage_init(void); +void _ecore_x_composite_init(void); +void _ecore_x_dpms_init(void); +void _ecore_x_randr_init(void); +void _ecore_x_gesture_init(void); + +void _ecore_x_atoms_init(void); + +extern int _ecore_x_xi2_opcode; + +void _ecore_x_events_init(void); +void _ecore_x_events_shutdown(void); + +void _ecore_x_input_init(void); +void _ecore_x_input_shutdown(void); +void _ecore_x_input_handler(XEvent *xevent); +/* from sync */ + +void _ecore_mouse_move(unsigned int timestamp, + unsigned int xmodifiers, + int x, + int y, + int x_root, + int y_root, + unsigned int event_window, + unsigned int window, + unsigned int root_win, + int same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + double mx, + double my, + double mrx, + double mry); +Ecore_Event_Mouse_Button *_ecore_mouse_button(int event, + unsigned int timestamp, + unsigned int xmodifiers, + unsigned int buttons, + int x, + int y, + int x_root, + int y_root, + unsigned int event_window, + unsigned int window, + unsigned int root_win, + int same_screen, + int dev, + double radx, + double rady, + double pressure, + double angle, + double mx, + double my, + double mrx, + double mry); + +void _ecore_x_modifiers_get(void); +KeySym _ecore_x_XKeycodeToKeysym(Display *display, KeyCode keycode, int index); + +//#define LOGFNS 1 + +#ifdef LOGFNS +#include <stdio.h> +#define LOGFN(fl, ln, fn) printf("-ECORE-X: %25s: %5i - %s\n", fl, ln, fn); +#else /* ifdef LOGFNS */ +#define LOGFN(fl, ln, fn) +#endif /* ifdef LOGFNS */ + +#endif /* ifndef _ECORE_X_PRIVATE_H */ diff --git a/src/lib/ecore_x/xlib/ecore_x_randr.c b/src/lib/ecore_x/xlib/ecore_x_randr.c new file mode 100644 index 0000000000..58a28305ac --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr.c @@ -0,0 +1,103 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" +#include "ecore_x_randr.h" + +static Eina_Bool _randr_available = EINA_FALSE; +#ifdef ECORE_XRANDR +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 +_ecore_x_randr_init(void) +{ +#ifdef ECORE_XRANDR + _randr_major = 1; + _randr_minor = 3; + _randr_version = 0; + + _ecore_x_randr_get_screen_resources = NULL; + if (XRRQueryVersion(_ecore_x_disp, &_randr_major, &_randr_minor)) + { + _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 = EINA_FALSE; + +#else + _randr_available = EINA_FALSE; +#endif +} + +/* + * @brief Query whether randr is available or not. + * + * @return @c EINA_TRUE, if extension is available, @c EINA_FALSE otherwise. + */ +EAPI Eina_Bool +ecore_x_randr_query(void) +{ + return _randr_available; +} + +/* + * @return version of the RandR extension supported by the server or, in case + * RandR extension is not available, Ecore_X_Randr_Unset (=-1). + * bit version information: 31 MAJOR 16 | 15 MINOR 0 + */ +EAPI int +ecore_x_randr_version_get(void) +{ +#ifdef ECORE_XRANDR + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (_randr_available) + { + return _randr_version; + } + else + { + return Ecore_X_Randr_Unset; + } +#else + return -1; +#endif +} + +Eina_Bool +_ecore_x_randr_root_validate(Ecore_X_Window root) +{ +#ifdef ECORE_XRANDR + 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/src/lib/ecore_x/xlib/ecore_x_randr.h b/src/lib/ecore_x/xlib/ecore_x_randr.h new file mode 100644 index 0000000000..eca3c0c32c --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr.h @@ -0,0 +1,7 @@ +#ifndef ECORE_X_INLINE_X +#define ECORE_X_INLINE_X +Eina_Bool _ecore_x_randr_root_validate(Ecore_X_Window root); +Eina_Bool _ecore_x_randr_output_validate(Ecore_X_Window root, + Ecore_X_Randr_Output + output); +#endif diff --git a/src/lib/ecore_x/xlib/ecore_x_randr_11.c b/src/lib/ecore_x/xlib/ecore_x_randr_11.c new file mode 100644 index 0000000000..7d2b3b34b5 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr_11.c @@ -0,0 +1,334 @@ +/* + * vim:ts=8:sw=3:sts=8:expandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" +#include "ecore_x_randr.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#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 */ +} + +/* + * @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 */ +} + +/* + * @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 @c 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 */ +} + +/* + * @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); + if ((!sizes) || (n <= 0)) return NULL; + 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 */ +} + +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 idx; + Rotation orientation; + int n; + + if (!(sc = XRRGetScreenInfo(_ecore_x_disp, root))) + { + ERR("Couldn't get screen information for %d", root); + return; + } + + idx = XRRConfigCurrentConfiguration(sc, &orientation); + + sizes = + XRRSizes(_ecore_x_disp, XRRRootToScreen(_ecore_x_disp, + root), &n); + if ((idx < n) && (idx >= 0)) + { + if (w) + *w = sizes[idx].width; + + if (h) + *h = sizes[idx].height; + + if (w_mm) + *w_mm = sizes[idx].mwidth; + + if (h_mm) + *h_mm = sizes[idx].mheight; + + if (size_index) + *size_index = idx; + } + + XRRFreeScreenConfigInfo(sc); +#endif /* ifdef ECORE_XRANDR */ +} + +/* + * @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 @c EINA_TRUE on success, @c 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; + Eina_Bool ret = EINA_FALSE; + int nsizes = 0; + + if (size_index >= 0 && _ecore_x_randr_root_validate(root)) + { + 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 */ +} + +/* + * @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 */ +} + +/* + * @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 */ +} + +//>= 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 @c EINA_TRUE on success, @c EINA_FALSE otherwise. + */ +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 */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_randr_12.c b/src/lib/ecore_x/xlib/ecore_x_randr_12.c new file mode 100644 index 0000000000..9e937d7bf7 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr_12.c @@ -0,0 +1,2438 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include "ecore_x_private.h" +#include "ecore_x_randr.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#define Ecore_X_Randr_None (Ecore_X_Randr_Crtc)0 +#define Ecore_X_Randr_Unset (Ecore_X_Randr_Crtc) - 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 RandR >= 1.2. + * + * @param win Select this window's properties for RandR 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, @c EINA_TRUE will be returned, @c EINA_FALSE + * otherwise. + */ +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 +} + +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. + * @c 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 @c 0, current + * aspect is assumed. + * @param h_mm Height in mm the screen should be set to. If @c 0, current + * aspect is assumed. + * @return @c EINA_TRUE if request was successfully sent or screen is already + * in requested size, @c 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 + 1)))) + strncpy(ret[i]->name, res->modes[i].name, + (res->modes[i].nameLength + 1)); + 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 Add a mode to a display. + * + * @param root Window to which's screen's ressources are added. + * @param mode_info + * @return Ecore_X_Randr_Mode of the added mode. Ecore_X_Randr_None if mode + * adding failed. + * @since 1.2.0 + */ +EAPI Ecore_X_Randr_Mode +ecore_x_randr_mode_info_add(Ecore_X_Window root, + Ecore_X_Randr_Mode_Info *mode_info) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + Ecore_X_Randr_Mode mode = Ecore_X_Randr_None; + + if (_ecore_x_randr_root_validate(root) && mode_info) + mode = XRRCreateMode(_ecore_x_disp, root, (XRRModeInfo*)mode_info); + + return mode; +#else + return Ecore_X_Randr_None; +#endif +} + +/* + * @brief Delete a mode from the display. + * + * @param mode_info + * @since 1.2.0 + */ +EAPI void +ecore_x_randr_mode_del(Ecore_X_Randr_Mode mode) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(); + + XRRDestroyMode(_ecore_x_disp, mode); +#else + return; +#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; + ret->name = NULL; + ret->nameLength = 0; + if (res->modes[i].nameLength > 0) + { + ret->nameLength = res->modes[i].nameLength; + ret->name = malloc(res->modes[i].nameLength + 1); + if (ret->name) + memcpy(ret->name, res->modes[i].name, + res->modes[i].nameLength + 1); + } + 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 + * @c 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 (root && + (res = _ecore_x_randr_get_screen_resources (_ecore_x_disp, root))) + { + if ((ret = malloc(sizeof(Ecore_X_Randr_Crtc) * res->ncrtc))) + { + int i = 0; + + if (num) *num = res->ncrtc; + + for (i = 0; i < res->ncrtc; i++) + ret[i] = res->crtcs[i]; + } + + XRRFreeScreenResources(res); + } + + return ret; +#else + return NULL; +#endif +} + +/* + * @deprecated bad naming. Use ecore_x_randr_window_crtcs_get instead. + * @brief get the CRTCs, which display a certain window + * @param window window the displaying crtcs shall be found for + * @param num the number of crtcs displaying the window + * @return Array of crtcs that display a certain window. @c NULL if no crtcs + * was found that displays the specified window. + */ +EAPI Ecore_X_Randr_Crtc * +ecore_x_randr_current_crtc_get(Ecore_X_Window window, + int *num) +{ + return ecore_x_randr_window_crtcs_get(window, num); +} + +/* + * @brief get the CRTCs, which display a certain window + * @param window window the displaying crtcs shall be found for + * @param num the number of crtcs displaying the window + * @return Array of crtcs that display a certain window. @c NULL if no crtcs + * was found that displays the specified window. + * @since 1.2.0 + */ +EAPI Ecore_X_Randr_Crtc * +ecore_x_randr_window_crtcs_get(Ecore_X_Window window, + int *num) +{ +#ifdef ECORE_XRANDR + Ecore_X_Window root; + Eina_Rectangle w_geo, c_geo; + Ecore_X_Randr_Crtc *crtcs; + Ecore_X_Randr_Mode mode; + Ecore_X_Randr_Output *ret = NULL; + Window tw; + int ncrtcs, i, nret = 0, rx = 0, ry = 0; + + if (_randr_version < RANDR_1_2) goto _ecore_x_randr_window_crtcs_get_fail; + + ecore_x_window_geometry_get(window, + &w_geo.x, &w_geo.y, + &w_geo.w, &w_geo.h); + + root = ecore_x_window_root_get(window); + crtcs = ecore_x_randr_crtcs_get(root, &ncrtcs); + if (!crtcs) goto _ecore_x_randr_window_crtcs_get_fail; + + /* now get window RELATIVE to root window - thats what matters. */ + XTranslateCoordinates(_ecore_x_disp, window, root, 0, 0, &rx, &ry, &tw); + w_geo.x = rx; + w_geo.y = ry; + + ret = calloc(1, ncrtcs * sizeof(Ecore_X_Randr_Crtc)); + if (!ret) + { + free(crtcs); + goto _ecore_x_randr_window_crtcs_get_fail; + } + for (i = 0, nret = 0; i < ncrtcs; i++) + { + /* if crtc is not enabled, don't bother about it any further */ + mode = ecore_x_randr_crtc_mode_get(root, crtcs[i]); + if (mode == Ecore_X_Randr_None) continue; + + ecore_x_randr_crtc_geometry_get(root, crtcs[i], + &c_geo.x, &c_geo.y, + &c_geo.w, &c_geo.h); + if (eina_rectangles_intersect(&w_geo, &c_geo)) + { + ret[nret] = crtcs[i]; + nret++; + } + } + free(crtcs); + + if (num) *num = nret; + return ret; + +_ecore_x_randr_window_crtcs_get_fail: +#endif + if (num) *num = 0; + return NULL; +} + +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 (root && + (res = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root))) + { + if ((ret = malloc(sizeof(Ecore_X_Randr_Output) * res->noutput))) + { + int i = 0; + + if (num) *num = res->noutput; + + for (i = 0; i < res->noutput; i++) + ret[i] = res->outputs[i]; + } + + 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))) + { + int i = 0; + + if (num) *num = crtc_info->noutput; + + for (i = 0; i < crtc_info->noutput; i++) + ret[i] = crtc_info->outputs[i]; + } + + 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))) + { + int i = 0; + + if (num) *num = crtc_info->npossible; + + for (i = 0; i < crtc_info->npossible; i++) + ret[i] = crtc_info->possible[i]; + } + + 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 @c EINA_TRUE if position could 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 @c NULL, CRTC will be disabled. + * @param noutputs Number of outputs in array to be used. Use + * Ecore_X_Randr_Unset (or @c -1) to use currently used outputs. + * @param mode XID of the mode to be set. If set to @c 0 the CRTC will be + * disabled. If set to @c -1 the call will fail. + * @return @c EINA_TRUE if mode setting was successful, @c EINA_FALSE + * otherwise. + */ +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 clon) +{ +#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, + clon) && + (res = + _ecore_x_randr_get_screen_resources (_ecore_x_disp, + root)) && + (clone_crtc_info = XRRGetCrtcInfo(_ecore_x_disp, res, clon))) + { + 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, + clon, + 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 @c EINA_TRUE if the configuration alteration was successful, + * @c EINA_FALSE otherwise. + */ +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 == (int)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. + * + * @param root The root window which's default display will be set. + * @param crtc_r1 The CRTC to be positioned. + * @param crtc_r2 The CRTC the position should be relative to. + * @param policy The relation between the crtcs. + * @param alignment In case CRTCs size differ, aligns CRTC1 accordingly at + * CRTC2's borders. + * @return @c EINA_TRUE if crtc could be successfully positioned, @c 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; + */ + case ECORE_X_RANDR_OUTPUT_POLICY_NONE: + break; + default: + return EINA_FALSE; + } + 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 +} + +/* + * @brief Add given mode to given output. + * + * @param output The output the mode is added to. + * @param mode The mode added to the output. + * @return @c EINA_FALSE if output or mode equal Ecore_X_Randr_None, else + * @c EINA_TRUE. + * Additionally, if xcb backend is used, the success of the addition is + * reported back directly. + * @since 1.2.0 + */ +EAPI Eina_Bool +ecore_x_randr_output_mode_add(Ecore_X_Randr_Output output, + Ecore_X_Randr_Mode mode) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + + if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None)) + return EINA_FALSE; + + XRRAddOutputMode(_ecore_x_disp, output, mode); + return EINA_TRUE; +#else + return EINA_FALSE; +#endif +} + +/* + * @brief delete given mode from given output + * @param output the output the mode is removed from + * @param mode the mode removed from the output + * @since 1.2.0 + */ +EAPI void +ecore_x_randr_output_mode_del(Ecore_X_Randr_Output output, + Ecore_X_Randr_Mode mode) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(); + + if ((output == Ecore_X_Randr_None) || (mode == Ecore_X_Randr_None)) + return; + + XRRDeleteOutputMode(_ecore_x_disp, output, mode); +#else + return; +#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))) + { + int i = 0; + + if (num) *num = output_info->nmode; + if (npreferred) *npreferred = output_info->npreferred; + + for (i = 0; i < output_info->nmode; i++) + modes[i] = output_info->modes[i]; + } + } + + 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. + * @param root window that this information should be queried for. + * @param output the output which's clones we concern + * @param 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 + * @param output The output for which the name will be reported. + * @param 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 below command is correct, but due to a bug in libXrandr + * it doesn't work. Therefore we stick with strlen(). + * Replace the line below with the following once this bug is + * fixed within libXrandr. + * + * *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 + * @param w width of given mode in px + * @param 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 + * @param output the XID of the output + * @param 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) + || !_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 necessary 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 @c 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 = NULL; + Eina_Bool ret = EINA_TRUE; + int i, cw, ch, w_max, h_max, nw, nh; + + crtc_info = alloca(sizeof(XRRCrtcInfo *) * ncrtc); + memset(crtc_info, 0, sizeof(XRRCrtcInfo *) * ncrtc); + 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) || + ((int)(crtc_info[i]->x + crtc_info[i]->width + dx) > w_max) + || ((crtc_info[i]->y + dy) < 0) || + ((int)(crtc_info[i]->y + crtc_info[i]->height + dy) > h_max) + ) + goto _ecore_x_randr_move_crtcs_fail_free_crtc_info; + + nw = MAX((int)(crtc_info[i]->x + crtc_info[i]->width + dx), nw); + nh = MAX((int)(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) && crtc_info[i]; i++) + { + if ((crtc_info[i]) && + (!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) + { + if (crtc_info[i]) + 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++) + { + if (crtc_info[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 ((int)(crtc_info->x + crtc_info->width) > w_n) + w_n = (crtc_info->x + crtc_info->width); + + if ((int)(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); + } + 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 +} + +/** + * @brief Set up the backlight level to the given level. + * + * @param root The window's screen which will be set. + * @param level Of the backlight between @c 0 and @c 1. + */ + +EAPI void +ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root, + double level) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(); + Atom _backlight; + XRRScreenResources *resources = NULL; + Ecore_X_Randr_Output output; + int o; + + if ((level < 0) || (level > 1)) + { + ERR("Wrong value for the backlight level. It should be between 0 and 1."); + return; + } + + /* + * To make sure that the _backlight atomic property still exists. + */ + _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True); + if (_backlight == None) + { + WRN("Backlight setting is not supported on this server or driver"); + return; + } + + /* get the ressources */ + resources = _ecore_x_randr_get_screen_resources(_ecore_x_disp, root); + if (!resources) return; + + for (o = 0; o < resources->noutput; o++) + { + output = resources->outputs[o]; + if (ecore_x_randr_output_backlight_level_get(root, output) >= 0) + { + ecore_x_randr_output_backlight_level_set(root, output, level); + } + } + XRRFreeScreenResources(resources); +#endif +} + +/* + * @brief Check if a backlight is available. + * @return Whether a backlight is available. + */ + +EAPI Eina_Bool +ecore_x_randr_output_backlight_available(void) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(-1); + Atom _backlight; + + _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True); + + return (_backlight == None) ? EINA_FALSE : EINA_TRUE; + +#endif + return EINA_FALSE; +} + +/* + * @brief Get the backlight level of the given output. + * + * @param root Window which's screen should be queried. + * @param output From which the backlight level should be retrieved. + * @return The backlight level. + */ + +EAPI double +ecore_x_randr_output_backlight_level_get(Ecore_X_Window root, + Ecore_X_Randr_Output output) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(-1); + Atom actual_type; + Atom _backlight; + XRRPropertyInfo *info = NULL; + double dvalue; + int actual_format; + long value, max, min; + unsigned long nitems; + unsigned long bytes_after; + unsigned char *prop = NULL; + + /* set backlight variable if not already done */ + + _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True); + if (_backlight == None) + { + ERR("Backlight property is not suppported on this server or driver"); + return -1; + } + + if (!_ecore_x_randr_output_validate(root, output)) + { + ERR("Invalid output"); + return -1; + } + + if (XRRGetOutputProperty(_ecore_x_disp, output, _backlight, + 0, 4, False, False, None, + &actual_type, &actual_format, + &nitems, &bytes_after, &prop) != Success) + { + WRN("Backlight not supported on this output"); + return -1; + } + + if ((actual_type != XA_INTEGER) || (nitems != 1) || (actual_format != 32)) return -1; + + value = *((long *)prop); + free (prop); + + /* I have the current value of the backlight */ + /* Now retrieve the min and max intensities of the output */ + info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight); + if (info) + { + dvalue = -1; + if ((info->range) && (info->num_values == 2)) + { + /* finally convert the current value in the interval [0..1] */ + min = info->values[0]; + max = info->values[1]; + dvalue = ((double)(value - min)) / ((double)(max - min)); + } + free(info); + return dvalue; + } +#endif + return -1; +} + +/* + * @brief Set the backlight level of a given output. + * + * @param root Window which's screen should be queried. + * @param output That should be set. + * @param level For which the backlight should be set. + * @return @c EINA_TRUE in case of success. + */ + +EAPI Eina_Bool +ecore_x_randr_output_backlight_level_set(Ecore_X_Window root, + Ecore_X_Randr_Output output, + double level) +{ +#ifdef ECORE_XRANDR + RANDR_CHECK_1_2_RET(EINA_FALSE); + Atom _backlight; + XRRPropertyInfo *info = NULL; + double min, max, tmp; + long new; + + if ((level < 0) || (level > 1)) + { + ERR("Backlight level should be between 0 and 1"); + return EINA_FALSE; + } + + if (!_ecore_x_randr_output_validate(root, output)) + { + ERR("Wrong output value"); + return EINA_FALSE; + } + + _backlight = XInternAtom(_ecore_x_disp, RANDR_PROPERTY_BACKLIGHT, True); + if (_backlight == None) + { + WRN("Backlight property is not suppported on this server or driver"); + return EINA_FALSE; + } + + info = XRRQueryOutputProperty(_ecore_x_disp, output, _backlight); + if (info) + { + if ((info->range) && (info->num_values == 2)) + { + min = info->values[0]; + max = info->values[1]; + tmp = (level * (max - min)) + min; + new = tmp; + if (new > max) new = max; + if (new < min) new = min; + XRRChangeOutputProperty(_ecore_x_disp, output, _backlight, XA_INTEGER, 32, + PropModeReplace, (unsigned char *)&new, 1); + XFlush(_ecore_x_disp); + } + free(info); + return EINA_TRUE; + } +#endif + return EINA_FALSE; +} + +/* + * @brief Get the outputs, which display a certain window. + * + * @param window Window the displaying outputs shall be found for + * @param num The number of outputs displaying the window + * @return Array of outputs that display a certain window. @c NULL if no + * outputs was found that displays the specified window. + */ + +EAPI Ecore_X_Randr_Output * +ecore_x_randr_window_outputs_get(Ecore_X_Window window, + int *num) +{ +#ifdef ECORE_XRANDR + Ecore_X_Window root; + Ecore_X_Randr_Crtc *crtcs; + Ecore_X_Randr_Output *outputs, *ret = NULL, *tret; + int ncrtcs, noutputs, i, nret = 0; + + if (_randr_version < RANDR_1_2) goto _ecore_x_randr_current_output_get_fail; + + root = ecore_x_window_root_get(window); + if (!(crtcs = ecore_x_randr_window_crtcs_get(window, &ncrtcs))) + goto _ecore_x_randr_current_output_get_fail; + + for (i = 0, nret = 0; i < ncrtcs; i++) + { + + outputs = ecore_x_randr_crtc_outputs_get(root, crtcs[i], + &noutputs); + if (!outputs) + goto _ecore_x_randr_current_output_get_fail_free; + tret = realloc(ret, ((nret + noutputs) * sizeof(Ecore_X_Randr_Output))); + if (!tret) goto _ecore_x_randr_current_output_get_fail_free; + ret = tret; + memcpy(&ret[nret], outputs, (noutputs * sizeof(Ecore_X_Randr_Output))); + nret += noutputs; + free(outputs); + outputs = NULL; + } + free(crtcs); + + if (num) + *num = nret; + + return ret; + +_ecore_x_randr_current_output_get_fail_free: + free(outputs); + free(crtcs); + free(ret); +_ecore_x_randr_current_output_get_fail: +#endif + if (num) *num = 0; + return NULL; +} + +/* + * @deprecated bad naming. Use ecore_x_randr_window_outputs_get instead. + * @brief Get the outputs, which display a certain window. + * + * @param window Window the displaying outputs shall be found for. + * @param num The number of outputs displaying the window. + * @return Array of outputs that display a certain window. @c NULL if no + * outputs was found that displays the specified window. + */ + +EAPI Ecore_X_Randr_Output * +ecore_x_randr_current_output_get(Ecore_X_Window window, + int *num) +{ + return ecore_x_randr_window_outputs_get(window, num); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c b/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c new file mode 100644 index 0000000000..5bda332a06 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c @@ -0,0 +1,463 @@ +/* + * Copyright 2006-2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Original Author: Adam Jackson <ajax@nwnk.net> */ +/* Heavily modified by: Leif Middelschulte <leif.middelschulte@gmail.com> */ + +#include "Ecore_X.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +/* TODO: + * - see other TODO's within this file. + */ + +#define ECORE_X_RANDR_EDID_VERSION_10 ((1 << 8) | 0) +#define ECORE_X_RANDR_EDID_VERSION_11 ((1 << 8) | 1) +#define ECORE_X_RANDR_EDID_VERSION_12 ((1 << 8) | 2) +#define ECORE_X_RANDR_EDID_VERSION_13 ((1 << 8) | 3) +#define ECORE_X_RANDR_EDID_VERSION_14 ((1 << 8) | 4) + +#define _ECORE_X_RANDR_EDID_OFFSET_MANUFACTURER 0x08 +#define _ECORE_X_RANDR_EDID_OFFSET_TYPE 0x14 +#define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR 0x12 +#define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR 0x13 +#define _ECORE_X_RANDR_EDID_OFFSET_DPMS 0x18 +#define _ECORE_X_RANDR_EDID_OFFSET_COLORSPACE 0x18 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK 0x36 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE 3 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT 5 +#define _ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO_PREFERRED 15 +#define _ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO 14 + +#define _ECORE_X_RANDR_EDID_MASK_DIGITAL 0x80 +#define _ECORE_X_RANDR_EDID_MASK_DIGITAL_INTERFACE 0x0f +#define _ECORE_X_RANDR_EDID_MASK_DIGITAL_TMDS_DFP_10 0x01 +#define _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_ANALOGOUS 0x18 +#define _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_444 0x10 +#define _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_422 0x08 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_PREFERRED 0xe0 +#define _ECORE_X_RANDR_EDID_MASK_DPMS 0xE0 +#define _ECORE_X_RANDR_EDID_MASK_DPMS_STANDBY 0x80 +#define _ECORE_X_RANDR_EDID_MASK_DPMS_SUSPEND 0x40 +#define _ECORE_X_RANDR_EDID_MASK_DPMS_OFF 0x20 +#define _ECORE_X_RANDR_EDID_MASK_INTERFACE_TYPE 0x0f +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_4_3 0x80 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_9 0x40 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_10 0x20 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_5_4 0x10 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_15_9 0x08 + +#define _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX 13 + +typedef enum _Ecore_X_Randr_Edid_Aspect_Ratio_Preferred { + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_4_3 = 0x00, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_9 = 0x01, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_10 = 0x02, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_5_4 = 0x03, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_15_9 = 0x04 +} Ecore_X_Randr_Edid_Aspect_Ratio_Preferred; + +/* Some convenience loops */ +#define _ECORE_X_RANDR_EDID_FOR_EACH_EXTENSION_BLOCK(edid, edid_length, extension_block_iter) \ + for (extension_block_iter = edid; extension_block_iter < (edid + edid_length); extension_block_iter += 128) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_CEA_BLOCK(edid, edid_length, cea_block_iter) \ + _ECORE_X_RANDR_EDID_FOR_EACH_EXTENSION_BLOCK(edid, edid_length, cea_block_iter) \ + if (cea_block_iter[0] == 0x02) + +/* The following macro is to be used with caution as it inherits another loop. + * Therefore using a 'break;' statement will lead to continuation in the + * inherent 'Extension block'-loop. + */ +#define _ECORE_X_RANDR_EDID_FOR_EACH_CEA_DETAILED_BLOCK(edid, edid_length, cea_block_iter, detailed_block_iter) \ + _ECORE_X_RANDR_EDID_FOR_EACH_CEA_BLOCK(edid, edid_length, cea_block_iter) \ + for (detailed_block_iter = cea_block_iter + cea_block_iter[2]; detailed_block_iter + 18 < cea_block_iter + 127; detailed_block_iter += 18) \ + if (detailed_block_iter[0]) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \ + for (block = edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK; block <= (edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK + (3 * 18)); block += 18) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) \ + _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \ + if ((block[0] == 0) && (block[1] == 0)) + +EAPI Eina_Bool +ecore_x_randr_edid_has_valid_header(unsigned char *edid, + unsigned long edid_length) +{ + const unsigned char header[] = + { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; + if (!edid) return EINA_FALSE; + if (edid_length < 8) return EINA_FALSE; + if (!memcmp(edid, header, 8)) return EINA_TRUE; + return EINA_FALSE; +} + +EAPI int +ecore_x_randr_edid_version_get(unsigned char *edid, + unsigned long edid_length) +{ + if ((edid_length > _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR) && + (ecore_x_randr_edid_has_valid_header(edid, edid_length))) + return (edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR] << 8) | + edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR]; + return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; +} + +EAPI int +ecore_x_randr_edid_manufacturer_model_get(unsigned char *edid, + unsigned long edid_length) +{ + if ((edid_length > 0x0b) && + (ecore_x_randr_edid_has_valid_header(edid, edid_length))) + return (int)(edid[0x0a] + (edid[0x0b] << 8)); + return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; +} + +EAPI int +ecore_x_randr_edid_manufacturer_serial_number_get(unsigned char *edid, + unsigned long edid_length) +{ + if ((edid_length > 0x0f) && + (ecore_x_randr_edid_has_valid_header(edid, edid_length))) + return (int)(edid[0x0c] + (edid[0x0d] << 8) + + (edid[0x0e] << 16) + (edid[0x0f] << 24)); + return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; +} + +EAPI char * +ecore_x_randr_edid_manufacturer_name_get(unsigned char *edid, + unsigned long edid_length) +{ + if ((edid_length > (_ECORE_X_RANDR_EDID_OFFSET_MANUFACTURER + 1)) && + (ecore_x_randr_edid_has_valid_header(edid, edid_length))) + { + unsigned char *x; + char *name; + + x = (edid + _ECORE_X_RANDR_EDID_OFFSET_MANUFACTURER); + name = malloc(sizeof(char) * 4); + if (!name) return NULL; + name[0] = ((x[0] & 0x7c) >> 2) + '@'; + name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xe0) >> 5) + '@'; + name[2] = (x[1] & 0x1f) + '@'; + name[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] = 0; + return name; + } + return NULL; +} + +EAPI char * +ecore_x_randr_edid_display_name_get(unsigned char *edid, + unsigned long edid_length) +{ + unsigned char *block = NULL; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL; + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfc) + { + char *name, *p; + const char *edid_name; + + edid_name = (const char *)block + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + name = malloc(sizeof(char) * _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + if (!name) return NULL; + strncpy(name, edid_name, (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + name[_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX] = 0; + for (p = name; *p; p++) + { + if ((*p < ' ') || (*p > '~')) *p = 0; + } + return name; + } + } + return NULL; +} + +EAPI Ecore_X_Randr_Edid_Aspect_Ratio +ecore_x_randr_edid_display_aspect_ratio_preferred_get(unsigned char *edid, + unsigned long edid_length) +{ + unsigned char *block = NULL; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if ((block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfd) && + (block[10] == 0x04)) + { + Ecore_X_Randr_Edid_Aspect_Ratio_Preferred preferred_ratio = + (Ecore_X_Randr_Edid_Aspect_Ratio_Preferred) + ((block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO_PREFERRED] & + _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_PREFERRED) >> 5); + switch (preferred_ratio) + { + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_4_3: + return ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3; + + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_9: + return ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9; + + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_10: + return ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10; + + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_5_4: + return ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4; + + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_15_9: + return ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9; + + default: + return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + } + } + } + return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; +} + +EAPI Ecore_X_Randr_Edid_Aspect_Ratio +ecore_x_randr_edid_display_aspect_ratios_get(unsigned char *edid, + unsigned long edid_length) +{ + Ecore_X_Randr_Edid_Aspect_Ratio ret = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + unsigned char *block = NULL; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if ((block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfd) && + (block[10] == 0x04)) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_4_3) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_9) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_10) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_5_4) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_15_9) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9; + } + } + return ret; +} + +EAPI char * +ecore_x_randr_edid_display_ascii_get(unsigned char *edid, + unsigned long edid_length) +{ + unsigned char *block = NULL; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL; + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xfe) + { + char *ascii, *p; + const char *edid_ascii = (const char *)block + + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + /* + * TODO: Two of these in a row, in the third and fourth slots, + * seems to be specified by SPWG: http://www.spwg.org/ + */ + ascii = malloc(sizeof(char) * _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + if (!ascii) return NULL; + strncpy(ascii, edid_ascii, (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + ascii[_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX] = 0; + for (p = ascii; *p; p++) + { + if ((*p < ' ') || (*p > '~')) *p = 0; + } + return ascii; + } + } + return NULL; +} + +EAPI char * +ecore_x_randr_edid_display_serial_get(unsigned char *edid, + unsigned long edid_length) +{ + unsigned char *block = NULL; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL; + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xff) + { + char *serial, *p; + const char *edid_serial = (const char *)block + + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + /* + * TODO: Two of these in a row, in the third and fourth slots, + * seems to be specified by SPWG: http://www.spwg.org/ + */ + serial = malloc(sizeof(char) * _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + if (!serial) return NULL; + strncpy(serial, edid_serial, (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + serial[_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX] = 0; + for (p = serial; *p; p++) + { + if ((*p < ' ') || (*p > '~')) *p = 0; + } + return serial; + } + } + return NULL; +} + +EAPI Eina_Bool +ecore_x_randr_edid_info_has_valid_checksum(unsigned char *edid, + unsigned long edid_length) +{ + unsigned char *cea_block_iter = NULL; + char sum = 0; + int i; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + if (edid_length < 128) return EINA_FALSE; + + /* Check the EDID block itself */ + for (i = 0; i < 128; i++) + sum += edid[i]; + if (sum) return EINA_FALSE; + + /* Check the cea extension blocks */ + _ECORE_X_RANDR_EDID_FOR_EACH_CEA_BLOCK(edid, edid_length, cea_block_iter) + { + for (i = 0, sum = 0; i < 128; i++) + sum += cea_block_iter[i]; + } + if (sum) return EINA_FALSE; + return EINA_TRUE; +} + +EAPI Eina_Bool +ecore_x_randr_edid_dpms_available_get(unsigned char *edid, + unsigned long edid_length) +{ + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + return !!(edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & + _ECORE_X_RANDR_EDID_MASK_DPMS); +} + +EAPI Eina_Bool +ecore_x_randr_edid_dpms_standby_available_get(unsigned char *edid, + unsigned long edid_length) +{ + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS) + return !!(edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & + _ECORE_X_RANDR_EDID_MASK_DPMS_STANDBY); + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_randr_edid_dpms_suspend_available_get(unsigned char *edid, + unsigned long edid_length) +{ + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS) + return !!(edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & + _ECORE_X_RANDR_EDID_MASK_DPMS_SUSPEND); + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_randr_edid_dpms_off_available_get(unsigned char *edid, + unsigned long edid_length) +{ + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS) + return !!(edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & + _ECORE_X_RANDR_EDID_MASK_DPMS_OFF); + return EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_randr_edid_display_type_digital_get(unsigned char *edid, + unsigned long edid_length) +{ + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + return !!(edid[_ECORE_X_RANDR_EDID_OFFSET_TYPE] & + _ECORE_X_RANDR_EDID_MASK_DIGITAL); +} + +EAPI Ecore_X_Randr_Edid_Display_Colorscheme +ecore_x_randr_edid_display_colorscheme_get(unsigned char *edid, + unsigned long edid_length) +{ + Ecore_X_Randr_Edid_Display_Colorscheme colorscheme = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return colorscheme; + if (ecore_x_randr_edid_display_type_digital_get(edid, edid_length)) + { + colorscheme = ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_4_4_4; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_COLORSPACE] & + _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_444) + colorscheme |= ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_4_4; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_COLORSPACE] & + _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_422) + colorscheme |= ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_2_2; + } + else + colorscheme = edid[_ECORE_X_RANDR_EDID_OFFSET_COLORSPACE] & _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_ANALOGOUS; + return colorscheme; +} + +EAPI Ecore_X_Randr_Edid_Display_Interface_Type +ecore_x_randr_edid_display_interface_type_get(unsigned char *edid, + unsigned long edid_length) +{ + Ecore_X_Randr_Edid_Display_Interface_Type type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + int version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return type; + type = edid[_ECORE_X_RANDR_EDID_OFFSET_TYPE] & + _ECORE_X_RANDR_EDID_MASK_INTERFACE_TYPE; + if (type > ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT) + type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + return type; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_randr_13.c b/src/lib/ecore_x/xlib/ecore_x_randr_13.c new file mode 100644 index 0000000000..5d1c8e96db --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_randr_13.c @@ -0,0 +1,68 @@ +/* + * vim:ts=8:sw=3:sts=8:expandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "ecore_x_private.h" +#include "ecore_x_randr.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#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 +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_region.c b/src/lib/ecore_x/xlib/ecore_x_region.c new file mode 100644 index 0000000000..81d7eea49c --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_region.c @@ -0,0 +1,158 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "ecore_x_private.h" + +/* + * [x] XCreateRegion + * [ ] XPolygonRegion + * [x] XSetRegion + * [x] XDestroyRegion + * + * [x] XOffsetRegion + * [ ] XShrinkRegion + * + * [ ] XClipBox + * [x] XIntersectRegion + * [x] XUnionRegion + * [x] XUnionRectWithRegion + * [x] XSubtractRegion + * [ ] XXorRegion + * + * [x] XEmptyRegion + * [x] XEqualRegion + * + * [x] XPointInRegion + * [x] XRectInRegion + */ + +EAPI Ecore_X_XRegion * +ecore_x_xregion_new() +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return (Ecore_X_XRegion *)XCreateRegion(); +} + +EAPI void +ecore_x_xregion_free(Ecore_X_XRegion *region) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!region) + return; + + XDestroyRegion((Region)region); +} + +EAPI Eina_Bool +ecore_x_xregion_set(Ecore_X_XRegion *region, + Ecore_X_GC gc) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XSetRegion(_ecore_x_disp, gc, (Region)region) ? EINA_TRUE : EINA_FALSE; +} + +EAPI void +ecore_x_xregion_translate(Ecore_X_XRegion *region, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!region) + return; + + /* return value not used */ + XOffsetRegion((Region)region, x, y); +} + +EAPI Eina_Bool +ecore_x_xregion_intersect(Ecore_X_XRegion *dst, + Ecore_X_XRegion *r1, + Ecore_X_XRegion *r2) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XIntersectRegion((Region)r1, (Region)r2, (Region)dst) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_union(Ecore_X_XRegion *dst, + Ecore_X_XRegion *r1, + Ecore_X_XRegion *r2) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XUnionRegion((Region)r1, (Region)r2, (Region)dst) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_union_rect(Ecore_X_XRegion *dst, + Ecore_X_XRegion *src, + Ecore_X_Rectangle *rect) +{ + XRectangle xr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xr.x = rect->x; + xr.y = rect->y; + xr.width = rect->width; + xr.height = rect->height; + + return XUnionRectWithRegion(&xr, (Region)src, (Region)dst) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_subtract(Ecore_X_XRegion *dst, + Ecore_X_XRegion *rm, + Ecore_X_XRegion *rs) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XSubtractRegion((Region)rm, (Region)rs, (Region)dst) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_is_empty(Ecore_X_XRegion *region) +{ + if (!region) + return EINA_TRUE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XEmptyRegion((Region)region) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_is_equal(Ecore_X_XRegion *r1, + Ecore_X_XRegion *r2) +{ + if (!r1 || !r2) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XEqualRegion((Region)r1, (Region)r1) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_point_contain(Ecore_X_XRegion *region, + int x, + int y) +{ + if (!region) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XPointInRegion((Region)region, x, y) ? EINA_TRUE : EINA_FALSE; +} + +EAPI Eina_Bool +ecore_x_xregion_rect_contain(Ecore_X_XRegion *region, + Ecore_X_Rectangle *rect) +{ + if (!region || !rect) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XRectInRegion((Region)region, + rect->x, + rect->y, + rect->width, + rect->height) ? EINA_TRUE : EINA_FALSE; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_screensaver.c b/src/lib/ecore_x/xlib/ecore_x_screensaver.c new file mode 100644 index 0000000000..3688a44c56 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_screensaver.c @@ -0,0 +1,204 @@ +/* + * Screensaver code + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +static int _screensaver_available = -1; + +EAPI Eina_Bool +ecore_x_screensaver_event_available_get(void) +{ + if (_screensaver_available >= 0) + return _screensaver_available; + +#ifdef ECORE_XSS + int _screensaver_major, _screensaver_minor; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _screensaver_major = 1; + _screensaver_minor = 0; + + if (XScreenSaverQueryVersion(_ecore_x_disp, &_screensaver_major, + &_screensaver_minor)) + _screensaver_available = 1; + else + _screensaver_available = 0; + +#else /* ifdef ECORE_XSS */ + _screensaver_available = 0; +#endif /* ifdef ECORE_XSS */ + return _screensaver_available; +} + +EAPI int +ecore_x_screensaver_idle_time_get(void) +{ +#ifdef ECORE_XSS + XScreenSaverInfo *xss; + int idle; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xss = XScreenSaverAllocInfo(); + XScreenSaverQueryInfo(_ecore_x_disp, + RootWindow(_ecore_x_disp, DefaultScreen( + _ecore_x_disp)), xss); + idle = xss->idle / 1000; + XFree(xss); + + return idle; +#else + return 0; +#endif /* ifdef ECORE_XSS */ +} + +EAPI void +ecore_x_screensaver_set(int timeout, + int interval, + int prefer_blanking, + int allow_exposures) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSetScreenSaver(_ecore_x_disp, + timeout, + interval, + prefer_blanking, + allow_exposures); +} + +EAPI void +ecore_x_screensaver_timeout_set(int timeout) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + XSetScreenSaver(_ecore_x_disp, timeout, pint, pblank, pexpo); +} + +EAPI int +ecore_x_screensaver_timeout_get(void) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + return pto; +} + +EAPI void +ecore_x_screensaver_blank_set(int blank) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + XSetScreenSaver(_ecore_x_disp, pto, pint, blank, pexpo); +} + +EAPI int +ecore_x_screensaver_blank_get(void) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + return pblank; +} + +EAPI void +ecore_x_screensaver_expose_set(int expose) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + XSetScreenSaver(_ecore_x_disp, pto, pint, pblank, expose); +} + +EAPI int +ecore_x_screensaver_expose_get(void) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + return pexpo; +} + +EAPI void +ecore_x_screensaver_interval_set(int interval) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + XSetScreenSaver(_ecore_x_disp, pto, interval, pblank, pexpo); +} + +EAPI int +ecore_x_screensaver_interval_get(void) +{ + int pto, pint, pblank, pexpo; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XGetScreenSaver(_ecore_x_disp, &pto, &pint, &pblank, &pexpo); + return pint; +} + +EAPI void +ecore_x_screensaver_event_listen_set(Eina_Bool on) +{ +#ifdef ECORE_XSS + Ecore_X_Window root; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + root = DefaultRootWindow(_ecore_x_disp); + if (on) + XScreenSaverSelectInput(_ecore_x_disp, root, + ScreenSaverNotifyMask | ScreenSaverCycle); + else + XScreenSaverSelectInput(_ecore_x_disp, root, 0); +#else + return; + on = EINA_FALSE; +#endif /* ifdef ECORE_XSS */ +} + + +EAPI Eina_Bool +ecore_x_screensaver_custom_blanking_enable(void) +{ +#ifdef ECORE_XSS + XSetWindowAttributes attr; + + XScreenSaverSetAttributes(_ecore_x_disp, + DefaultRootWindow(_ecore_x_disp), + -9999, -9999, 1, 1, 0, + CopyFromParent, InputOnly, CopyFromParent, + 0, &attr); + return EINA_TRUE; +#else + return EINA_FALSE; +#endif /* ifdef ECORE_XSS */ +} + +EAPI Eina_Bool +ecore_x_screensaver_custom_blanking_disable(void) +{ +#ifdef ECORE_XSS + XScreenSaverUnsetAttributes(_ecore_x_disp, + DefaultRootWindow(_ecore_x_disp)); + return EINA_TRUE; +#else + return EINA_FALSE; +#endif /* ifdef ECORE_XSS */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_selection.c b/src/lib/ecore_x/xlib/ecore_x_selection.c new file mode 100644 index 0000000000..3e1d2d34a2 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_selection.c @@ -0,0 +1,1021 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#elif !defined alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# elif defined _AIX +# define alloca __alloca +# elif defined _MSC_VER +# include <malloc.h> +# define alloca _alloca +# elif !defined HAVE_ALLOCA +# ifdef __cplusplus +extern "C" +# endif +void *alloca (size_t); +# endif +#endif + +#include <stdlib.h> +#include <string.h> + +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +static Ecore_X_Selection_Intern selections[4]; +static Ecore_X_Selection_Converter *converters = NULL; +static Ecore_X_Selection_Parser *parsers = NULL; + +static int _ecore_x_selection_data_default_free(void *data); +static void *_ecore_x_selection_parser_files(const char *target, + void *data, + int size, + int format); +static int _ecore_x_selection_data_files_free(void *data); +static void *_ecore_x_selection_parser_text(const char *target, + void *data, + int size, + int format); +static int _ecore_x_selection_data_text_free(void *data); +static void *_ecore_x_selection_parser_targets(const char *target, + void *data, + int size, + int format); +static int _ecore_x_selection_data_targets_free(void *data); + +#define ECORE_X_SELECTION_DATA(x) ((Ecore_X_Selection_Data *)(x)) + +void +_ecore_x_selection_data_init(void) +{ + /* Initialize global data */ + memset(selections, 0, sizeof(selections)); + + /* Initialize converters */ + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_TEXT, + ecore_x_selection_converter_text); +#ifdef X_HAVE_UTF8_STRING + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_UTF8_STRING, + ecore_x_selection_converter_text); +#endif /* ifdef X_HAVE_UTF8_STRING */ + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_COMPOUND_TEXT, + ecore_x_selection_converter_text); + ecore_x_selection_converter_atom_add(ECORE_X_ATOM_STRING, + ecore_x_selection_converter_text); + + /* Initialize parsers */ + ecore_x_selection_parser_add("text/plain", + _ecore_x_selection_parser_text); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_UTF8_STRING, + _ecore_x_selection_parser_text); + ecore_x_selection_parser_add("text/uri-list", + _ecore_x_selection_parser_files); + ecore_x_selection_parser_add("_NETSCAPE_URL", + _ecore_x_selection_parser_files); + ecore_x_selection_parser_add(ECORE_X_SELECTION_TARGET_TARGETS, + _ecore_x_selection_parser_targets); +} + +void +_ecore_x_selection_shutdown(void) +{ + Ecore_X_Selection_Converter *cnv; + Ecore_X_Selection_Parser *prs; + + /* free the selection converters */ + cnv = converters; + while (cnv) + { + Ecore_X_Selection_Converter *tmp; + + tmp = cnv->next; + free(cnv); + cnv = tmp; + } + converters = NULL; + + /* free the selection parsers */ + prs = parsers; + while (prs) + { + Ecore_X_Selection_Parser *tmp; + + tmp = prs; + prs = prs->next; + free(tmp->target); + free(tmp); + } + parsers = NULL; +} + +Ecore_X_Selection_Intern * +_ecore_x_selection_get(Ecore_X_Atom selection) +{ + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + return &selections[0]; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + return &selections[1]; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + return &selections[2]; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + return &selections[3]; + else + return NULL; +} + +Eina_Bool +_ecore_x_selection_set(Window w, + const void *data, + int size, + Ecore_X_Atom selection) +{ + int in; + unsigned char *buf = NULL; + + XSetSelectionOwner(_ecore_x_disp, selection, w, _ecore_x_event_last_time); + if (XGetSelectionOwner(_ecore_x_disp, selection) != w) + return EINA_FALSE; + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + in = 0; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + in = 1; + else if (selection == ECORE_X_ATOM_SELECTION_XDND) + in = 2; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + in = 3; + else + return EINA_FALSE; + + if (data) + { + selections[in].win = w; + selections[in].selection = selection; + selections[in].length = size; + selections[in].time = _ecore_x_event_last_time; + + buf = malloc(size); + if (!buf) return EINA_FALSE; + memcpy(buf, data, size); + selections[in].data = buf; + } + else if (selections[in].data) + { + free(selections[in].data); + memset(&selections[in], 0, sizeof(Ecore_X_Selection_Data)); + } + + return EINA_TRUE; +} + +/** + * Claim ownership of the PRIMARY selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_primary_set(Ecore_X_Window w, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_PRIMARY); +} + +/** + * Release ownership of the primary selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + */ +EAPI Eina_Bool +ecore_x_selection_primary_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_PRIMARY); +} + +/** + * Claim ownership of the SECONDARY selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_secondary_set(Ecore_X_Window w, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(w, + data, + size, + ECORE_X_ATOM_SELECTION_SECONDARY); +} + +/** + * Release ownership of the secondary selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + */ +EAPI Eina_Bool +ecore_x_selection_secondary_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(None, + NULL, + 0, + ECORE_X_ATOM_SELECTION_SECONDARY); +} + +/** + * Claim ownership of the XDND selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + */ +EAPI Eina_Bool +ecore_x_selection_xdnd_set(Ecore_X_Window w, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(w, data, size, ECORE_X_ATOM_SELECTION_XDND); +} + +/** + * Release ownership of the XDND selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + */ +EAPI Eina_Bool +ecore_x_selection_xdnd_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(None, NULL, 0, ECORE_X_ATOM_SELECTION_XDND); +} + +/** + * Claim ownership of the CLIPBOARD selection and set its data. + * @param w The window to which this selection belongs + * @param data The data associated with the selection + * @param size The size of the data buffer in bytes + * @return Returns 1 if the ownership of the selection was successfully + * claimed, or 0 if unsuccessful. + * + * Get the converted data from a previous CLIPBOARD selection + * request. The buffer must be freed when done with. + */ +EAPI Eina_Bool +ecore_x_selection_clipboard_set(Ecore_X_Window w, + const void *data, + int size) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(w, + data, + size, + ECORE_X_ATOM_SELECTION_CLIPBOARD); +} + +/** + * Release ownership of the clipboard selection + * @return Returns 1 if the selection was successfully cleared, + * or 0 if unsuccessful. + * + */ +EAPI Eina_Bool +ecore_x_selection_clipboard_clear(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_selection_set(None, + NULL, + 0, + ECORE_X_ATOM_SELECTION_CLIPBOARD); +} + +Ecore_X_Atom +_ecore_x_selection_target_atom_get(const char *target) +{ + Ecore_X_Atom x_target; + + if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) + x_target = ECORE_X_ATOM_TEXT; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) + x_target = ECORE_X_ATOM_COMPOUND_TEXT; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) + x_target = ECORE_X_ATOM_STRING; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) + x_target = ECORE_X_ATOM_UTF8_STRING; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_FILENAME)) + x_target = ECORE_X_ATOM_FILE_NAME; + else + x_target = ecore_x_atom_get(target); + + return x_target; +} + +char * +_ecore_x_selection_target_get(Ecore_X_Atom target) +{ + /* FIXME: Should not return mem allocated with strdup or X mixed, + * one should use free to free, the other XFree */ + if (target == ECORE_X_ATOM_FILE_NAME) + return strdup(ECORE_X_SELECTION_TARGET_FILENAME); + else if (target == ECORE_X_ATOM_STRING) + return strdup(ECORE_X_SELECTION_TARGET_STRING); + else if (target == ECORE_X_ATOM_UTF8_STRING) + return strdup(ECORE_X_SELECTION_TARGET_UTF8_STRING); + else if (target == ECORE_X_ATOM_TEXT) + return strdup(ECORE_X_SELECTION_TARGET_TEXT); + else + return XGetAtomName(_ecore_x_disp, target); +} + +static void +_ecore_x_selection_request(Ecore_X_Window w, + Ecore_X_Atom selection, + const char *target_str) +{ + Ecore_X_Atom target, prop; + + target = _ecore_x_selection_target_atom_get(target_str); + + if (selection == ECORE_X_ATOM_SELECTION_PRIMARY) + prop = ECORE_X_ATOM_SELECTION_PROP_PRIMARY; + else if (selection == ECORE_X_ATOM_SELECTION_SECONDARY) + prop = ECORE_X_ATOM_SELECTION_PROP_SECONDARY; + else if (selection == ECORE_X_ATOM_SELECTION_CLIPBOARD) + prop = ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD; + else + return; + + XConvertSelection(_ecore_x_disp, selection, target, prop, + w, CurrentTime); +} + +EAPI void +ecore_x_selection_primary_request(Ecore_X_Window w, + const char *target) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target); +} + +EAPI void +ecore_x_selection_secondary_request(Ecore_X_Window w, + const char *target) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target); +} + +EAPI void +ecore_x_selection_xdnd_request(Ecore_X_Window w, + const char *target) +{ + Ecore_X_Atom atom; + Ecore_X_DND_Target *_target; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _target = _ecore_x_dnd_target_get(); + atom = _ecore_x_selection_target_atom_get(target); + XConvertSelection(_ecore_x_disp, ECORE_X_ATOM_SELECTION_XDND, atom, + ECORE_X_ATOM_SELECTION_PROP_XDND, w, + _target->time); +} + +EAPI void +ecore_x_selection_clipboard_request(Ecore_X_Window w, + const char *target) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target); +} + +EAPI void +ecore_x_selection_converter_atom_add(Ecore_X_Atom target, + Eina_Bool (*func)(char *target, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *ttype, + int *tsize)) +{ + Ecore_X_Selection_Converter *cnv; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + cnv = converters; + if (converters) + { + while (1) + { + if (cnv->target == target) + { + cnv->convert = func; + return; + } + + if (cnv->next) + cnv = cnv->next; + else + break; + } + + cnv->next = calloc(1, sizeof(Ecore_X_Selection_Converter)); + if (!cnv->next) return; + cnv = cnv->next; + } + else + { + converters = calloc(1, sizeof(Ecore_X_Selection_Converter)); + if (!converters) return; + cnv = converters; + } + + cnv->target = target; + cnv->convert = func; +} + +EAPI void +ecore_x_selection_converter_add(char *target, + Eina_Bool (*func)(char *target, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *, + int *)) +{ + Ecore_X_Atom x_target; + + if (!func || !target) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + x_target = _ecore_x_selection_target_atom_get(target); + + ecore_x_selection_converter_atom_add(x_target, func); +} + +EAPI void +ecore_x_selection_converter_atom_del(Ecore_X_Atom target) +{ + Ecore_X_Selection_Converter *cnv, *prev_cnv; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + prev_cnv = NULL; + cnv = converters; + + while (cnv) + { + if (cnv->target == target) + { + if (prev_cnv) + prev_cnv->next = cnv->next; + else + { + converters = cnv->next; /* This was the first converter */ + } + + free(cnv); + + return; + } + + prev_cnv = cnv; + cnv = cnv->next; + } +} + +EAPI void +ecore_x_selection_converter_del(char *target) +{ + Ecore_X_Atom x_target; + + if (!target) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + x_target = _ecore_x_selection_target_atom_get(target); + ecore_x_selection_converter_atom_del(x_target); +} + +EAPI Eina_Bool +ecore_x_selection_notify_send(Ecore_X_Window requestor, + Ecore_X_Atom selection, + Ecore_X_Atom target, + Ecore_X_Atom property, + Ecore_X_Time tim) +{ + XEvent xev; + XSelectionEvent xnotify; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xnotify.type = SelectionNotify; + xnotify.display = _ecore_x_disp; + xnotify.requestor = requestor; + xnotify.selection = selection; + xnotify.target = target; + xnotify.property = property; + xnotify.time = tim; + xnotify.send_event = True; + xnotify.serial = 0; + + xev.xselection = xnotify; + return (XSendEvent(_ecore_x_disp, requestor, False, 0, &xev) > 0) ? EINA_TRUE : EINA_FALSE; +} + +/* Locate and run conversion callback for specified selection target */ +EAPI Eina_Bool +ecore_x_selection_convert(Ecore_X_Atom selection, + Ecore_X_Atom target, + void **data_ret, + int *size, + Ecore_X_Atom *targtype, + int *typesize) +{ + Ecore_X_Selection_Intern *sel; + Ecore_X_Selection_Converter *cnv; + void *data; + char *tgt_str; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + sel = _ecore_x_selection_get(selection); + tgt_str = _ecore_x_selection_target_get(target); + + for (cnv = converters; cnv; cnv = cnv->next) + { + if (cnv->target == target) + { + int r; + r = cnv->convert(tgt_str, sel->data, sel->length, &data, size, + targtype, typesize); + free(tgt_str); + if (r) + { + *data_ret = data; + return r; + } + else + return EINA_FALSE; + } + } + + /* ICCCM says "If the selection cannot be converted into a form based on the target (and parameters, if any), the owner should refuse the SelectionRequest as previously described." */ + return EINA_FALSE; + + /* Default, just return the data + * data_ret = malloc(sel->length); + memcpy(*data_ret, sel->data, sel->length); + free(tgt_str); + return 1; + */ +} + +/* TODO: We need to work out a mechanism for automatic conversion to any requested + * locale using Ecore_Txt functions */ +/* Converter for standard non-utf8 text targets */ +EAPI Eina_Bool +ecore_x_selection_converter_text(char *target, + void *data, + int size, + void **data_ret, + int *size_ret, + Ecore_X_Atom *targprop EINA_UNUSED, + int *s EINA_UNUSED) +{ + XTextProperty text_prop; + char *mystr; + XICCEncodingStyle style; + + if (!data || !size) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!strcmp(target, ECORE_X_SELECTION_TARGET_TEXT)) + style = XTextStyle; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_COMPOUND_TEXT)) + style = XCompoundTextStyle; + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_STRING)) + style = XStringStyle; + +#ifdef X_HAVE_UTF8_STRING + else if (!strcmp(target, ECORE_X_SELECTION_TARGET_UTF8_STRING)) + style = XUTF8StringStyle; +#endif /* ifdef X_HAVE_UTF8_STRING */ + else + return EINA_FALSE; + + mystr = alloca(size + 1); + memcpy(mystr, data, size); + mystr[size] = '\0'; + +#ifdef X_HAVE_UTF8_STRING + if (Xutf8TextListToTextProperty(_ecore_x_disp, &mystr, 1, style, + &text_prop) == Success) + { + int bufsize = strlen((char *)text_prop.value) + 1; + *data_ret = malloc(bufsize); + if (!*data_ret) + { + return EINA_FALSE; + } + memcpy(*data_ret, text_prop.value, bufsize); + *size_ret = bufsize; + XFree(text_prop.value); + return EINA_TRUE; + } + +#else /* ifdef X_HAVE_UTF8_STRING */ + if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, + &text_prop) == Success) + { + int bufsize = strlen(text_prop.value) + 1; + *data_ret = malloc(bufsize); + if (!*data_ret) return EINA_FALSE; + memcpy(*data_ret, text_prop.value, bufsize); + *size_ret = bufsize; + XFree(text_prop.value); + return EINA_TRUE; + } + +#endif /* ifdef X_HAVE_UTF8_STRING */ + else + { + return EINA_TRUE; + } +} + +EAPI void +ecore_x_selection_parser_add(const char *target, + void *(*func)(const char *target, void *data, + int size, + int format)) +{ + Ecore_X_Selection_Parser *prs; + + if (!target) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + prs = parsers; + if (parsers) + { + while (prs->next) + { + if (!strcmp(prs->target, target)) + { + prs->parse = func; + return; + } + + prs = prs->next; + } + + prs->next = calloc(1, sizeof(Ecore_X_Selection_Parser)); + if (!prs->next) return; + prs = prs->next; + } + else + { + parsers = calloc(1, sizeof(Ecore_X_Selection_Parser)); + if (!parsers) return; + prs = parsers; + } + + prs->target = strdup(target); + prs->parse = func; +} + +EAPI void +ecore_x_selection_parser_del(const char *target) +{ + Ecore_X_Selection_Parser *prs, *prev_prs; + + if (!target) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + prev_prs = NULL; + prs = parsers; + + while (prs) + { + if (!strcmp(prs->target, target)) + { + if (prev_prs) + prev_prs->next = prs->next; + else + { + parsers = prs->next; /* This was the first parser */ + } + + free(prs->target); + free(prs); + + return; + } + + prev_prs = prs; + prs = prs->next; + } +} + +/** + * Change the owner and last-change time for the specified selection. + * @param win The owner of the specified atom. + * @param atom The selection atom + * @param tim Specifies the time + * @since 1.1.0 + */ +EAPI void +ecore_x_selection_owner_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Time tim) +{ + XSetSelectionOwner(_ecore_x_disp, atom, win, tim); +} + +/** + * Return the window that currently owns the specified selection. + * + * @param atom The specified selection atom. + * + * @return The window that currently owns the specified selection. + * @since 1.1.0 + */ +EAPI Ecore_X_Window +ecore_x_selection_owner_get(Ecore_X_Atom atom) +{ + return XGetSelectionOwner(_ecore_x_disp, atom); +} + +/* Locate and run conversion callback for specified selection target */ +void * +_ecore_x_selection_parse(const char *target, + void *data, + int size, + int format) +{ + Ecore_X_Selection_Parser *prs; + Ecore_X_Selection_Data *sel; + + for (prs = parsers; prs; prs = prs->next) + { + if (!strcmp(prs->target, target)) + { + sel = prs->parse(target, data, size, format); + if (sel) return sel; + } + } + + /* Default, just return the data */ + sel = calloc(1, sizeof(Ecore_X_Selection_Data)); + if (!sel) return NULL; + sel->free = _ecore_x_selection_data_default_free; + sel->length = size; + sel->format = format; + sel->data = data; + return sel; +} + +static int +_ecore_x_selection_data_default_free(void *data) +{ + Ecore_X_Selection_Data *sel; + + sel = data; + free(sel->data); + free(sel); + return 1; +} + +static void * +_ecore_x_selection_parser_files(const char *target, + void *_data, + int size, + int format EINA_UNUSED) +{ + Ecore_X_Selection_Data_Files *sel; + char *t, *data = _data; + int i, is; + char *tmp; + char **t2; + + if (strcmp(target, "text/uri-list") && + strcmp(target, "_NETSCAPE_URL")) + return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files)); + if (!sel) return NULL; + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free; + + if (data && data[size - 1]) + { + /* Isn't nul terminated */ + size++; + t = realloc(data, size); + if (!t) + { + free(sel); + return NULL; + } + data = t; + data[size - 1] = 0; + } + + tmp = malloc(size); + if (!tmp) + { + free(sel); + return NULL; + } + i = 0; + is = 0; + while ((is < size) && (data[is])) + { + if ((i == 0) && (data[is] == '#')) + for (; ((data[is]) && (data[is] != '\n')); is++) ; + else + { + if ((data[is] != '\r') && + (data[is] != '\n')) + tmp[i++] = data[is++]; + else + { + while ((data[is] == '\r') || (data[is] == '\n')) + is++; + tmp[i] = 0; + sel->num_files++; + t2 = realloc(sel->files, sel->num_files * sizeof(char *)); + if (t2) + { + sel->files = t2; + sel->files[sel->num_files - 1] = strdup(tmp); + } + tmp[0] = 0; + i = 0; + } + } + } + if (i > 0) + { + tmp[i] = 0; + sel->num_files++; + t2 = realloc(sel->files, sel->num_files * sizeof(char *)); + if (t2) + { + sel->files = t2; + sel->files[sel->num_files - 1] = strdup(tmp); + } + } + + free(tmp); + free(data); + + ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_FILES; + ECORE_X_SELECTION_DATA(sel)->length = sel->num_files; + + return ECORE_X_SELECTION_DATA(sel); +} + +static int +_ecore_x_selection_data_files_free(void *data) +{ + Ecore_X_Selection_Data_Files *sel; + int i; + + sel = data; + if (sel->files) + { + for (i = 0; i < sel->num_files; i++) + free(sel->files[i]); + free(sel->files); + } + + free(sel); + return 0; +} + +static void * +_ecore_x_selection_parser_text(const char *target EINA_UNUSED, + void *_data, + int size, + int format EINA_UNUSED) +{ + Ecore_X_Selection_Data_Text *sel; + unsigned char *data = _data; + void *t; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text)); + if (!sel) return NULL; + if (data && data[size - 1]) + { + /* Isn't nul terminated */ + size++; + t = realloc(data, size); + if (!t) + { + free(sel); + return NULL; + } + data = t; + data[size - 1] = 0; + } + + sel->text = (char *)data; + ECORE_X_SELECTION_DATA(sel)->length = size; + ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TEXT; + ECORE_X_SELECTION_DATA(sel)->data = data; + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_text_free; + return sel; +} + +static int +_ecore_x_selection_data_text_free(void *data) +{ + Ecore_X_Selection_Data_Text *sel; + + sel = data; + free(sel->text); + free(sel); + return 1; +} + +static void * +_ecore_x_selection_parser_targets(const char *target EINA_UNUSED, + void *data, + int size, + int format EINA_UNUSED) +{ + Ecore_X_Selection_Data_Targets *sel; + unsigned long *targets; + int i; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets)); + if (!sel) return NULL; + targets = (unsigned long *)data; + + sel->num_targets = size - 2; + sel->targets = malloc((size - 2) * sizeof(char *)); + if (!sel->targets) + { + free(sel); + return NULL; + } + for (i = 2; i < size; i++) + sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]); + + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free; + ECORE_X_SELECTION_DATA(sel)->content = ECORE_X_SELECTION_CONTENT_TARGETS; + ECORE_X_SELECTION_DATA(sel)->length = size; + ECORE_X_SELECTION_DATA(sel)->data = data; + return sel; +} + +static int +_ecore_x_selection_data_targets_free(void *data) +{ + Ecore_X_Selection_Data_Targets *sel; + int i; + + sel = data; + + if (sel->targets) + { + for (i = 0; i < sel->num_targets; i++) + XFree(sel->targets[i]); + free(sel->targets); + } + + free(ECORE_X_SELECTION_DATA(sel)->data); + free(sel); + return 1; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_sync.c b/src/lib/ecore_x/xlib/ecore_x_sync.c new file mode 100644 index 0000000000..0c7f546f1a --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_sync.c @@ -0,0 +1,159 @@ +/* + * XSync code + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +EAPI Ecore_X_Sync_Alarm +ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter) +{ + Ecore_X_Sync_Alarm alarm; + XSyncAlarmAttributes values; + XSyncValue init; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncIntToValue(&init, 0); + XSyncSetCounter(_ecore_x_disp, counter, init); + + values.trigger.counter = counter; + values.trigger.value_type = XSyncAbsolute; + XSyncIntToValue(&values.trigger.wait_value, 1); + values.trigger.test_type = XSyncPositiveComparison; + + XSyncIntToValue(&values.delta, 1); + + values.events = True; + + alarm = XSyncCreateAlarm(_ecore_x_disp, + XSyncCACounter | + XSyncCAValueType | + XSyncCAValue | + XSyncCATestType | + XSyncCADelta | + XSyncCAEvents, + &values); + + ecore_x_sync(); + return alarm; +} + +EAPI Eina_Bool +ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XSyncDestroyAlarm(_ecore_x_disp, alarm); +} + +EAPI Eina_Bool +ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, + unsigned int *val) +{ + XSyncValue value; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XSyncQueryCounter(_ecore_x_disp, counter, &value)) + { + *val = (unsigned int)XSyncValueLow32(value); + return EINA_TRUE; + } + + return EINA_FALSE; +} + +EAPI Ecore_X_Sync_Counter +ecore_x_sync_counter_new(int val) +{ + XSyncCounter counter; + XSyncValue v; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncIntToValue(&v, val); + counter = XSyncCreateCounter(_ecore_x_disp, v); + return counter; +} + +EAPI void +ecore_x_sync_counter_free(Ecore_X_Sync_Counter counter) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncDestroyCounter(_ecore_x_disp, counter); +} + +EAPI void +ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, + int by) +{ + XSyncValue v; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncIntToValue(&v, by); + XSyncChangeCounter(_ecore_x_disp, counter, v); +} + +EAPI void +ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, + int val) +{ + XSyncWaitCondition cond; + XSyncValue v, v2; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncQueryCounter(_ecore_x_disp, counter, &v); + XSyncIntToValue(&v, val); + XSyncIntToValue(&v2, val + 1); + cond.trigger.counter = counter; + cond.trigger.value_type = XSyncAbsolute; + cond.trigger.wait_value = v; + cond.trigger.test_type = XSyncPositiveComparison; + cond.event_threshold = v2; + XSyncAwait(_ecore_x_disp, &cond, 1); +// XSync(_ecore_x_disp, False); // dont need this +} + +EAPI void +ecore_x_sync_counter_set(Ecore_X_Sync_Counter counter, + int val) +{ + XSyncValue v; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncIntToValue(&v, val); + XSyncSetCounter(_ecore_x_disp, counter, v); +} + +EAPI void +ecore_x_sync_counter_2_set(Ecore_X_Sync_Counter counter, + int val_hi, + unsigned int val_lo) +{ + XSyncValue v; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSyncIntsToValue(&v, val_lo, val_hi); + XSyncSetCounter(_ecore_x_disp, counter, v); +} + +EAPI Eina_Bool +ecore_x_sync_counter_2_query(Ecore_X_Sync_Counter counter, + int *val_hi, + unsigned int *val_lo) +{ + XSyncValue value; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (XSyncQueryCounter(_ecore_x_disp, counter, &value)) + { + *val_lo = (unsigned int)XSyncValueLow32(value); + *val_hi = (int)XSyncValueHigh32(value); + return EINA_TRUE; + } + return EINA_FALSE; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_test.c b/src/lib/ecore_x/xlib/ecore_x_test.c new file mode 100644 index 0000000000..4eec6b74b3 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_test.c @@ -0,0 +1,167 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> + +#ifdef ECORE_XTEST +# include <X11/extensions/XTest.h> +#endif /* ifdef ECORE_XTEST */ + +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include <string.h> + +EAPI Eina_Bool +#ifdef ECORE_XTEST +ecore_x_test_fake_key_down(const char *key) +#else +ecore_x_test_fake_key_down(const char *key EINA_UNUSED) +#endif +{ +#ifdef ECORE_XTEST + KeyCode keycode = 0; + KeySym keysym; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + else + { + keysym = XStringToKeysym(key); + if (keysym == NoSymbol) + return EINA_FALSE; + + keycode = XKeysymToKeycode(_ecore_x_disp, keysym); + } + + if (keycode == 0) + return EINA_FALSE; + + return XTestFakeKeyEvent(_ecore_x_disp, keycode, 1, 0) ? EINA_TRUE : EINA_FALSE; +#else /* ifdef ECORE_XTEST */ + return EINA_FALSE; +#endif /* ifdef ECORE_XTEST */ +} + +EAPI Eina_Bool +#ifdef ECORE_XTEST +ecore_x_test_fake_key_up(const char *key) +#else +ecore_x_test_fake_key_up(const char *key EINA_UNUSED) +#endif +{ +#ifdef ECORE_XTEST + KeyCode keycode = 0; + KeySym keysym; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + else + { + keysym = XStringToKeysym(key); + if (keysym == NoSymbol) + return EINA_FALSE; + + keycode = XKeysymToKeycode(_ecore_x_disp, keysym); + } + + if (keycode == 0) + return EINA_FALSE; + + return XTestFakeKeyEvent(_ecore_x_disp, keycode, 0, 0) ? EINA_TRUE : EINA_FALSE; +#else /* ifdef ECORE_XTEST */ + return EINA_FALSE; +#endif /* ifdef ECORE_XTEST */ +} + +EAPI Eina_Bool +#ifdef ECORE_XTEST +ecore_x_test_fake_key_press(const char *key) +#else +ecore_x_test_fake_key_press(const char *key EINA_UNUSED) +#endif +{ +#ifdef ECORE_XTEST + KeyCode keycode = 0; + KeySym keysym = 0; + int shift = 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!strncmp(key, "Keycode-", 8)) + keycode = atoi(key + 8); + else + { + keysym = XStringToKeysym(key); + if (keysym == NoSymbol) + return EINA_FALSE; + + keycode = XKeysymToKeycode(_ecore_x_disp, keysym); + if (_ecore_x_XKeycodeToKeysym(_ecore_x_disp, keycode, 0) != keysym) + { + if (_ecore_x_XKeycodeToKeysym(_ecore_x_disp, keycode, 1) == keysym) + shift = 1; + else + keycode = 0; + } + else + shift = 0; + } + + if (keycode == 0) + { + static int mod = 0; + KeySym *keysyms; + int keycode_min, keycode_max, keycode_num; + int i; + + XDisplayKeycodes(_ecore_x_disp, &keycode_min, &keycode_max); + keysyms = XGetKeyboardMapping(_ecore_x_disp, keycode_min, + keycode_max - keycode_min + 1, + &keycode_num); + mod = (mod + 1) & 0x7; + i = (keycode_max - keycode_min - mod - 1) * keycode_num; + + keysyms[i] = keysym; + XChangeKeyboardMapping(_ecore_x_disp, keycode_min, keycode_num, + keysyms, (keycode_max - keycode_min)); + XFree(keysyms); + XSync(_ecore_x_disp, False); + keycode = keycode_max - mod - 1; + } + + if (shift) + XTestFakeKeyEvent(_ecore_x_disp, + XKeysymToKeycode(_ecore_x_disp, XK_Shift_L), 1, 0); + + XTestFakeKeyEvent(_ecore_x_disp, keycode, 1, 0); + XTestFakeKeyEvent(_ecore_x_disp, keycode, 0, 0); + if (shift) + XTestFakeKeyEvent(_ecore_x_disp, + XKeysymToKeycode(_ecore_x_disp, XK_Shift_L), 0, 0); + + return EINA_TRUE; +#else /* ifdef ECORE_XTEST */ + return EINA_FALSE; +#endif /* ifdef ECORE_XTEST */ +} + +EAPI const char * +ecore_x_keysym_string_get(int keysym) +{ + return XKeysymToString(keysym); +} + +EAPI int +ecore_x_keysym_keycode_get(const char *keyname) +{ + int keycode = 0; + + if (!strncmp(keyname, "Keycode-", 8)) + keycode = atoi(keyname + 8); + else + keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(keyname)); + + return keycode; +} diff --git a/src/lib/ecore_x/xlib/ecore_x_vsync.c b/src/lib/ecore_x/xlib/ecore_x_vsync.c new file mode 100644 index 0000000000..a316a33c45 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_vsync.c @@ -0,0 +1,351 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +#include <string.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define ECORE_X_VSYNC_DRI2 1 + +#ifdef ECORE_X_VSYNC_DRI2 +// relevant header bits of dri/drm inlined here to avoid needing external +// headers to build +/// drm +typedef unsigned int drm_magic_t; + +typedef enum +{ + DRM_VBLANK_ABSOLUTE = 0x00000000, + DRM_VBLANK_RELATIVE = 0x00000001, + DRM_VBLANK_EVENT = 0x04000000, + DRM_VBLANK_FLIP = 0x08000000, + DRM_VBLANK_NEXTONMISS = 0x10000000, + DRM_VBLANK_SECONDARY = 0x20000000, + DRM_VBLANK_SIGNAL = 0x40000000 +} +drmVBlankSeqType; + +typedef struct _drmVBlankReq +{ + drmVBlankSeqType type; + unsigned int sequence; + unsigned long signal; +} drmVBlankReq; + +typedef struct _drmVBlankReply +{ + drmVBlankSeqType type; + unsigned int sequence; + long tval_sec; + long tval_usec; +} drmVBlankReply; + +typedef union _drmVBlank +{ + drmVBlankReq request; + drmVBlankReply reply; +} drmVBlank; + +#define DRM_EVENT_CONTEXT_VERSION 2 + +typedef struct _drmEventContext +{ + int version; + void (*vblank_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); + void (*page_flip_handler)(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); +} drmEventContext; + +static int (*sym_drmClose)(int fd) = NULL; +static int (*sym_drmGetMagic)(int fd, + drm_magic_t *magic) = NULL; +static int (*sym_drmWaitVBlank)(int fd, + drmVBlank *vbl) = NULL; +static int (*sym_drmHandleEvent)(int fd, + drmEventContext *evctx) = NULL; + +//// dri + +static Bool (*sym_DRI2QueryExtension)(Display *display, + int *eventBase, + int *errorBase) = NULL; +static Bool (*sym_DRI2QueryVersion)(Display *display, + int *major, + int *minor) = NULL; +static Bool (*sym_DRI2Connect)(Display *display, + XID window, + char **driverName, + char **deviceName) = NULL; +static Bool (*sym_DRI2Authenticate)(Display *display, + XID window, + drm_magic_t magic) = NULL; + +//// dri/drm data needed +static int dri2_event = 0; +static int dri2_error = 0; +static int dri2_major = 0; +static int dri2_minor = 0; +static char *device_name = 0; +static char *driver_name = 0; +static drm_magic_t drm_magic; + +static int drm_fd = -1; +static int drm_event_is_busy = 0; +static int drm_animators_interval = 1; +static drmEventContext drm_evctx; +static Ecore_Fd_Handler *dri_drm_fdh = NULL; + +static void *dri_lib = NULL; +static void *drm_lib = NULL; + +static Window dri_drm_vsync_root = 0; + +static void +_dri_drm_tick_schedule(void) +{ + drmVBlank vbl; + + vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; + vbl.request.sequence = drm_animators_interval; + vbl.request.signal = 0; + sym_drmWaitVBlank(drm_fd, &vbl); +} + +static void +_dri_drm_tick_begin(void *data EINA_UNUSED) +{ + drm_event_is_busy = 1; + _dri_drm_tick_schedule(); +} + +static void +_dri_drm_tick_end(void *data EINA_UNUSED) +{ + drm_event_is_busy = 0; +} + +static void +_dri_drm_vblank_handler(int fd EINA_UNUSED, + unsigned int frame EINA_UNUSED, + unsigned int sec EINA_UNUSED, + unsigned int usec EINA_UNUSED, + void *data EINA_UNUSED) +{ + ecore_animator_custom_tick(); + if (drm_event_is_busy) _dri_drm_tick_schedule(); +} + +static Eina_Bool +_dri_drm_cb(void *data EINA_UNUSED, + Ecore_Fd_Handler *fd_handler EINA_UNUSED) +{ + sym_drmHandleEvent(drm_fd, &drm_evctx); + return ECORE_CALLBACK_RENEW; +} + +// yes. most evil. we dlopen libdrm and libGL etc. to manually find smbols +// so we can be as compatible as possible given the whole mess of the +// gl/dri/drm etc. world. and handle graceful failure at runtime not +// compile time +static int +_dri_drm_link(void) +{ + const char *drm_libs[] = + { + "libdrm.so.2", + "libdrm.so.1", + "libdrm.so.0", + "libdrm.so", + NULL, + }; + const char *dri_libs[] = + { + "libdri2.so.2", + "libdri2.so.1", + "libdri2.so.0", + "libdri2.so", + "libGL.so.4", + "libGL.so.3", + "libGL.so.2", + "libGL.so.1", + "libGL.so.0", + "libGL.so", + NULL, + }; + int i, fail; +#define SYM(lib, xx) \ + do { \ + sym_ ## xx = dlsym(lib, #xx); \ + if (!(sym_ ## xx)) { \ + fprintf(stderr, "%s\n", dlerror()); \ + fail = 1; \ + } \ + } while (0) + + if (dri_lib) return 1; + for (i = 0; drm_libs[i]; i++) + { + drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY); + if (drm_lib) + { + fail = 0; + SYM(drm_lib, drmClose); + SYM(drm_lib, drmWaitVBlank); + SYM(drm_lib, drmHandleEvent); + if (fail) + { + dlclose(drm_lib); + drm_lib = NULL; + } + else break; + } + } + if (!drm_lib) return 0; + for (i = 0; dri_libs[i]; i++) + { + dri_lib = dlopen(dri_libs[i], RTLD_LOCAL | RTLD_LAZY); + if (dri_lib) + { + fail = 0; + SYM(dri_lib, DRI2QueryExtension); + SYM(dri_lib, DRI2QueryVersion); + SYM(dri_lib, DRI2Connect); + SYM(dri_lib, DRI2Authenticate); + if (fail) + { + dlclose(dri_lib); + dri_lib = NULL; + } + else break; + } + } + if (!dri_lib) + { + dlclose(drm_lib); + drm_lib = NULL; + return 0; + } + return 1; +} + +static int +_dri_drm_init(void) +{ + if (!sym_DRI2QueryExtension(_ecore_x_disp, &dri2_event, &dri2_error)) + return 0; + if (!sym_DRI2QueryVersion(_ecore_x_disp, &dri2_major, &dri2_minor)) + return 0; + if (dri2_major < 2) + return 0; + if (!sym_DRI2Connect(_ecore_x_disp, dri_drm_vsync_root, &driver_name, &device_name)) + return 0; + drm_fd = open(device_name, O_RDWR); + if (drm_fd < 0) + return 0; + sym_drmGetMagic(drm_fd, &drm_magic); + if (!sym_DRI2Authenticate(_ecore_x_disp, dri_drm_vsync_root, drm_magic)) + { + close(drm_fd); + drm_fd = -1; + return 0; + } + memset(&drm_evctx, 0, sizeof(drm_evctx)); + drm_evctx.version = DRM_EVENT_CONTEXT_VERSION; + drm_evctx.vblank_handler = _dri_drm_vblank_handler; + drm_evctx.page_flip_handler = NULL; + + dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ, + _dri_drm_cb, NULL, NULL, NULL); + if (!dri_drm_fdh) + { + close(drm_fd); + drm_fd = -1; + return 0; + } + return 1; +} + +static void +_dri_drm_shutdown(void) +{ + if (drm_fd >= 0) + { + close(drm_fd); + drm_fd = -1; + } + if (dri_drm_fdh) + { + ecore_main_fd_handler_del(dri_drm_fdh); + dri_drm_fdh = NULL; + } +} + +#endif + +EAPI Eina_Bool +ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win) +{ +#ifdef ECORE_X_VSYNC_DRI2 + Ecore_X_Window root; + + root = ecore_x_window_root_get(win); + if (root != dri_drm_vsync_root) + { + dri_drm_vsync_root = root; + if (dri_drm_vsync_root) + { + if (!_dri_drm_link()) + { + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + return EINA_FALSE; + } + _dri_drm_shutdown(); + if (!_dri_drm_init()) + { + dri_drm_vsync_root = 0; + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + return EINA_FALSE; + } + ecore_animator_custom_source_tick_begin_callback_set + (_dri_drm_tick_begin, NULL); + ecore_animator_custom_source_tick_end_callback_set + (_dri_drm_tick_end, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); + } + else + { + if (drm_fd >= 0) + { + _dri_drm_shutdown(); + ecore_animator_custom_source_tick_begin_callback_set + (NULL, NULL); + ecore_animator_custom_source_tick_end_callback_set + (NULL, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + } + } + } + return EINA_TRUE; +#else + return EINA_FALSE; + win = 0; +#endif +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_window.c b/src/lib/ecore_x/xlib/ecore_x_window.c new file mode 100644 index 0000000000..36fc5cc53a --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_window.c @@ -0,0 +1,1727 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <sys/types.h> +#include <unistd.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +static int ignore_num = 0; +static Ecore_X_Window *ignore_list = NULL; + +/** + * @defgroup Ecore_X_Window_Create_Group X Window Creation Functions + * + * Functions that can be used to create an X window. + */ + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Window win; + XSetWindowAttributes attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (parent == 0) + parent = DefaultRootWindow(_ecore_x_disp); + + attr.backing_store = NotUseful; + attr.override_redirect = False; + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.bit_gravity = NorthWestGravity; + attr.win_gravity = NorthWestGravity; + attr.save_under = False; + attr.do_not_propagate_mask = NoEventMask; + attr.event_mask = KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + ExposureMask | + VisibilityChangeMask | + StructureNotifyMask | + FocusChangeMask | + PropertyChangeMask | + ColormapChangeMask; + win = XCreateWindow(_ecore_x_disp, parent, + x, y, w, h, 0, + CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/ + InputOutput, + CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/ + CWBackingStore | + CWOverrideRedirect | +/* CWColormap | */ + CWBorderPixel | + CWBackPixmap | + CWSaveUnder | + CWDontPropagate | + CWEventMask | + CWBitGravity | + CWWinGravity, + &attr); + + if (parent == DefaultRootWindow(_ecore_x_disp)) + ecore_x_window_defaults_set(win); + + return win; +} + +/** + * Creates a window with the override redirect attribute set to @c True. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_override_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Window win; + XSetWindowAttributes attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (parent == 0) + parent = DefaultRootWindow(_ecore_x_disp); + + attr.backing_store = NotUseful; + attr.override_redirect = True; + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.bit_gravity = NorthWestGravity; + attr.win_gravity = NorthWestGravity; + attr.save_under = False; + attr.do_not_propagate_mask = NoEventMask; + attr.event_mask = KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + ExposureMask | + VisibilityChangeMask | + StructureNotifyMask | + FocusChangeMask | + PropertyChangeMask | + ColormapChangeMask; + win = XCreateWindow(_ecore_x_disp, parent, + x, y, w, h, 0, + CopyFromParent, /*DefaultDepth(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/ + InputOutput, + CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/ + CWBackingStore | + CWOverrideRedirect | +/* CWColormap | */ + CWBorderPixel | + CWBackPixmap | + CWSaveUnder | + CWDontPropagate | + CWEventMask | + CWBitGravity | + CWWinGravity, + &attr); + return win; +} + +/** + * Creates a new input window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_input_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ + Window win; + XSetWindowAttributes attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (parent == 0) + parent = DefaultRootWindow(_ecore_x_disp); + + attr.override_redirect = True; + attr.do_not_propagate_mask = NoEventMask; + attr.event_mask = KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + ExposureMask | + VisibilityChangeMask | + StructureNotifyMask | + FocusChangeMask | + PropertyChangeMask | + ColormapChangeMask; + win = XCreateWindow(_ecore_x_disp, parent, + x, y, w, h, 0, + CopyFromParent, + InputOnly, + CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/ + CWOverrideRedirect | + CWDontPropagate | + CWEventMask, + &attr); + + if (parent == DefaultRootWindow(_ecore_x_disp)) + { + } + + return win; +} + +/** + * @defgroup Ecore_X_Window_Properties_Group X Window Property Functions + * + * Functions that set window properties. + */ + +/** + * Sets the default properties for the given window. + * + * The default properties set for the window are @c WM_CLIENT_MACHINE and + * @c _NET_WM_PID. + * + * @param win The given window. + * @ingroup Ecore_X_Window_Properties_Group + */ +EAPI void +ecore_x_window_defaults_set(Ecore_X_Window win) +{ + long pid; + char buf[MAXHOSTNAMELEN]; + char *hostname[1]; + int argc; + char **argv; + XTextProperty xprop; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* + * Set WM_CLIENT_MACHINE. + */ + gethostname(buf, MAXHOSTNAMELEN); + buf[MAXHOSTNAMELEN - 1] = '\0'; + hostname[0] = buf; + /* The ecore function uses UTF8 which Xlib may not like (especially + * with older clients) */ + /* ecore_x_window_prop_string_set(win, ECORE_X_ATOM_WM_CLIENT_MACHINE, + (char *)buf); */ + if (XStringListToTextProperty(hostname, 1, &xprop)) + { + XSetWMClientMachine(_ecore_x_disp, win, &xprop); + XFree(xprop.value); + } + + /* + * Set _NET_WM_PID + */ + pid = getpid(); + ecore_x_netwm_pid_set(win, pid); + + ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL); + + ecore_app_args_get(&argc, &argv); + ecore_x_icccm_command_set(win, argc, argv); +} + +EAPI void +ecore_x_window_configure(Ecore_X_Window win, + Ecore_X_Window_Configure_Mask mask, + int x, + int y, + int w, + int h, + int border_width, + Ecore_X_Window sibling, + int stack_mode) +{ + XWindowChanges xwc; + + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + + xwc.x = x; + xwc.y = y; + xwc.width = w; + xwc.height = h; + xwc.border_width = border_width; + xwc.sibling = sibling; + xwc.stack_mode = stack_mode; + + XConfigureWindow(_ecore_x_disp, win, mask, &xwc); +} + +/** + * @defgroup Ecore_X_Window_Destroy_Group X Window Destroy Functions + * + * Functions to destroy X windows. + */ + +/** + * Deletes the given window. + * @param win The given window. + * @ingroup Ecore_X_Window_Destroy_Group + */ +EAPI void +ecore_x_window_free(Ecore_X_Window win) +{ + /* sorry sir, deleting the root window doesn't sound like + * a smart idea. + */ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win) + XDestroyWindow(_ecore_x_disp, win); +} + +/** + * Set if a window should be ignored. + * @param win The given window. + * @param ignore if to ignore + */ +EAPI void +ecore_x_window_ignore_set(Ecore_X_Window win, + int ignore) +{ + int i, j, cnt; + Ecore_X_Window *t; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (ignore) + { + if (ignore_list) + { + for (i = 0; i < ignore_num; i++) + { + if (win == ignore_list[i]) + return; + } + t = realloc(ignore_list, (ignore_num + 1) * sizeof(Ecore_X_Window)); + if (!t) return; + ignore_list = t; + ignore_list[ignore_num++] = win; + } + else + { + ignore_num = 0; + ignore_list = malloc(sizeof(Ecore_X_Window)); + if (ignore_list) + ignore_list[ignore_num++] = win; + } + } + else + { + if (!ignore_list) + return; + + for (cnt = ignore_num, i = 0, j = 0; i < cnt; i++) + { + if (win != ignore_list[i]) + ignore_list[j++] = ignore_list[i]; + else + ignore_num--; + } + + if (ignore_num <= 0) + { + free(ignore_list); + ignore_list = NULL; + return; + } + t = realloc(ignore_list, ignore_num * sizeof(Ecore_X_Window)); + if (t) ignore_list = t; + } +} + +/** + * Get the ignore list + * @param num number of windows in the list + * @return list of windows to ignore + */ +EAPI Ecore_X_Window * +ecore_x_window_ignore_list(int *num) +{ + if (num) + *num = ignore_num; + + return ignore_list; +} + +/** + * Sends a delete request to the given window. + * @param win The given window. + * @ingroup Ecore_X_Window_Destroy_Group + */ +EAPI void +ecore_x_window_delete_request_send(Ecore_X_Window win) +{ + XEvent xev; + + /* sorry sir, deleting the root window doesn't sound like + * a smart idea. + */ + if (!win) + return; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + xev.xclient.type = ClientMessage; + xev.xclient.display = _ecore_x_disp; + xev.xclient.window = win; + xev.xclient.message_type = ECORE_X_ATOM_WM_PROTOCOLS; + xev.xclient.format = 32; + xev.xclient.data.l[0] = ECORE_X_ATOM_WM_DELETE_WINDOW; + xev.xclient.data.l[1] = CurrentTime; + + XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev); +} + +/** + * @defgroup Ecore_X_Window_Visibility_Group X Window Visibility Functions + * + * Functions to access and change the visibility of X windows. + */ + +/** + * Shows a window. + * + * Synonymous to "mapping" a window in X Window System terminology. + * + * @param win The window to show. + * @ingroup Ecore_X_Window_Visibility + */ +EAPI void +ecore_x_window_show(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XMapWindow(_ecore_x_disp, win); +} + +/** + * Hides a window. + * + * Synonymous to "unmapping" a window in X Window System terminology. + * + * @param win The window to hide. + * @ingroup Ecore_X_Window_Visibility + */ +EAPI void +ecore_x_window_hide(Ecore_X_Window win) +{ + XEvent xev; + Window root; + int idum; + unsigned int uidum; + + /* ICCCM: SEND unmap event... */ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + root = win; + if (ScreenCount(_ecore_x_disp) == 1) + root = DefaultRootWindow(_ecore_x_disp); + else + XGetGeometry(_ecore_x_disp, + win, + &root, + &idum, + &idum, + &uidum, + &uidum, + &uidum, + &uidum); + + XUnmapWindow(_ecore_x_disp, win); + xev.xunmap.type = UnmapNotify; + xev.xunmap.serial = 0; + xev.xunmap.send_event = True; + xev.xunmap.display = _ecore_x_disp; + xev.xunmap.event = root; + xev.xunmap.window = win; + xev.xunmap.from_configure = False; + XSendEvent(_ecore_x_disp, xev.xunmap.event, False, + SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +/** + * @defgroup Ecore_X_Window_Geometry_Group X Window Geometry Functions + * + * Functions that change or retrieve the geometry of X windows. + */ + +/** + * Moves a window to the position @p x, @p y. + * + * The position is relative to the upper left hand corner of the + * parent window. + * + * @param win The window to move. + * @param x X position. + * @param y Y position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_move(Ecore_X_Window win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XMoveWindow(_ecore_x_disp, win, x, y); +} + +/** + * Resizes a window. + * @param win The window to resize. + * @param w New width of the window. + * @param h New height of the window. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_resize(Ecore_X_Window win, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (w < 1) + w = 1; + + if (h < 1) + h = 1; + + XResizeWindow(_ecore_x_disp, win, w, h); +} + +/** + * Moves and resizes a window. + * @param win The window to move and resize. + * @param x New X position of the window. + * @param y New Y position of the window. + * @param w New width of the window. + * @param h New height of the window. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_move_resize(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (w < 1) + w = 1; + + if (h < 1) + h = 1; + + XMoveResizeWindow(_ecore_x_disp, win, x, y, w, h); +} + +/** + * @defgroup Ecore_X_Window_Focus_Functions X Window Focus Functions + * + * Functions that give the focus to an X Window. + */ + +/** + * Sets the focus to the window @p win. + * @param win The window to focus. + * @ingroup Ecore_X_Window_Focus_Functions + */ +EAPI void +ecore_x_window_focus(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); // XSetInputFocus(_ecore_x_disp, win, RevertToNone, CurrentTime); + +// XSetInputFocus(_ecore_x_disp, win, RevertToPointerRoot, CurrentTime); + XSetInputFocus(_ecore_x_disp, win, RevertToParent, CurrentTime); +} + +/** + * Sets the focus to the given window at a specific time. + * @param win The window to focus. + * @param t When to set the focus to the window. + * @ingroup Ecore_X_Window_Focus_Functions + */ +EAPI void +ecore_x_window_focus_at_time(Ecore_X_Window win, + Ecore_X_Time t) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); // XSetInputFocus(_ecore_x_disp, win, RevertToNone, t); + +// XSetInputFocus(_ecore_x_disp, win, PointerRoot, t); + XSetInputFocus(_ecore_x_disp, win, RevertToParent, t); +} + +/** + * gets the window that has focus. + * @return The window that has focus. + * @ingroup Ecore_X_Window_Focus_Functions + */ +EAPI Ecore_X_Window +ecore_x_window_focus_get(void) +{ + Window win; + int revert_mode; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + win = 0; + XGetInputFocus(_ecore_x_disp, &win, &revert_mode); + return win; +} + +/** + * @defgroup Ecore_X_Window_Z_Order_Group X Window Z Order Functions + * + * Functions that change the Z order of X windows. + */ + +/** + * Raises the given window. + * @param win The window to raise. + * @ingroup Ecore_X_Window_Z_Order_Group + */ +EAPI void +ecore_x_window_raise(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XRaiseWindow(_ecore_x_disp, win); +} + +/** + * Lowers the given window. + * @param win The window to lower. + * @ingroup Ecore_X_Window_Z_Order_Group + */ +EAPI void +ecore_x_window_lower(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XLowerWindow(_ecore_x_disp, win); +} + +/** + * @defgroup Ecore_X_Window_Parent_Group X Window Parent Functions + * + * Functions that retrieve or changes the parent window of a window. + */ + +/** + * Moves a window to within another window at a given position. + * @param win The window to reparent. + * @param new_parent The new parent window. + * @param x X position within new parent window. + * @param y Y position within new parent window. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI void +ecore_x_window_reparent(Ecore_X_Window win, + Ecore_X_Window new_parent, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (new_parent == 0) + new_parent = DefaultRootWindow(_ecore_x_disp); + + XReparentWindow(_ecore_x_disp, win, new_parent, x, y); +} + +/** + * Retrieves the size of the given window. + * @param win The given window. + * @param w Pointer to an integer into which the width is to be stored. + * @param h Pointer to an integer into which the height is to be stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_size_get(Ecore_X_Window win, + int *w, + int *h) +{ + int dummy_x, dummy_y; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); + + ecore_x_drawable_geometry_get(win, &dummy_x, &dummy_y, w, h); +} + +/** + * Retrieves the geometry of the given window. + * + * Note that the x & y coordinates are relative to your parent. In + * particular for reparenting window managers - relative to you window border. + * If you want screen coordinates either walk the window tree to the root, + * else for ecore_evas applications see ecore_evas_geometry_get(). Elementary + * applications can use elm_win_screen_position_get(). + * + * @param win The given window. + * @param x Pointer to an integer in which the X position is to be stored. + * @param y Pointer to an integer in which the Y position is to be stored. + * @param w Pointer to an integer in which the width is to be stored. + * @param h Pointer to an integer in which the height is to be stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_geometry_get(Ecore_X_Window win, + int *x, + int *y, + int *w, + int *h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!win) + win = DefaultRootWindow(_ecore_x_disp); + + ecore_x_drawable_geometry_get(win, x, y, w, h); +} + +/** + * Retrieves the width of the border of the given window. + * @param win The given window. + * @return Width of the border of @p win. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI int +ecore_x_window_border_width_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* doesn't make sense to call this on a root window */ + if (!win) + return 0; + + return ecore_x_drawable_border_width_get(win); +} + +/** + * Sets the width of the border of the given window. + * @param win The given window. + * @param width The new border width. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_border_width_set(Ecore_X_Window win, + int width) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* doesn't make sense to call this on a root window */ + if (!win) + return; + + XSetWindowBorderWidth (_ecore_x_disp, win, width); +} + +/** + * Retrieves the depth of the given window. + * @param win The given window. + * @return Depth of the window. + */ +EAPI int +ecore_x_window_depth_get(Ecore_X_Window win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_drawable_depth_get(win); +} + +/** + * @brief Show the cursor on a window of type Ecore_X_Window. + * @param win The window for which the cursor will be showed. + * @param show Enables the show of the cursor on the window if equals EINA_TRUE, disables if equals EINA_FALSE. + */ +EAPI void +ecore_x_window_cursor_show(Ecore_X_Window win, + Eina_Bool show) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); + + if (!show) + { + Cursor c; + XColor cl; + Pixmap p, m; + GC gc; + XGCValues gcv; + + p = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1); + m = XCreatePixmap(_ecore_x_disp, win, 1, 1, 1); + gc = XCreateGC(_ecore_x_disp, m, 0, &gcv); + XSetForeground(_ecore_x_disp, gc, 0); + XDrawPoint(_ecore_x_disp, m, gc, 0, 0); + XFreeGC(_ecore_x_disp, gc); + c = XCreatePixmapCursor(_ecore_x_disp, p, m, &cl, &cl, 0, 0); + XDefineCursor(_ecore_x_disp, win, c); + XFreeCursor(_ecore_x_disp, c); + XFreePixmap(_ecore_x_disp, p); + XFreePixmap(_ecore_x_disp, m); + } + else + XDefineCursor(_ecore_x_disp, win, 0); +} + +EAPI void +ecore_x_window_cursor_set(Ecore_X_Window win, + Ecore_X_Cursor c) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (c == 0) + XUndefineCursor(_ecore_x_disp, win); + else + XDefineCursor(_ecore_x_disp, win, c); +} + +/** + * Finds out whether the given window is currently visible. + * @param win The given window. + * @return 1 if the window is visible, otherwise 0. + * @ingroup Ecore_X_Window_Visibility_Group + */ +EAPI int +ecore_x_window_visible_get(Ecore_X_Window win) +{ + XWindowAttributes attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return XGetWindowAttributes(_ecore_x_disp, win, &attr) && + (attr.map_state == IsViewable); +} + +typedef struct _Shadow Shadow; +struct _Shadow +{ + Shadow *parent; + Shadow **children; + Window win; + int children_num; + short x, y; + unsigned short w, h; +}; + +static Shadow **shadow_base = NULL; +static int shadow_num = 0; + +static Shadow * +_ecore_x_window_tree_walk(Window win) +{ + Window *list = NULL; + Window parent_win = 0, root_win = 0; + unsigned int num; + Shadow *s, **sl; + XWindowAttributes att; + + if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) + return NULL; // if (att.class == InputOnly) return NULL; + + if (att.map_state != IsViewable) + return NULL; + + s = calloc(1, sizeof(Shadow)); + if (!s) + return NULL; + + s->win = win; + s->x = att.x; + s->y = att.y; + s->w = att.width; + s->h = att.height; + if (XQueryTree(_ecore_x_disp, s->win, &root_win, &parent_win, + &list, &num)) + { + s->children = calloc(1, sizeof(Shadow *) * num); + if (s->children) + { + size_t i, j; + s->children_num = num; + for (i = 0; i < num; i++) + { + s->children[i] = _ecore_x_window_tree_walk(list[i]); + if (s->children[i]) + s->children[i]->parent = s; + } + /* compress list down */ + j = 0; + for (i = 0; i < num; i++) + { + if (s->children[i]) + { + s->children[j] = s->children[i]; + j++; + } + } + if (j == 0) + { + free(s->children); + s->children = NULL; + s->children_num = 0; + } + else + { + s->children_num = j; + sl = realloc(s->children, sizeof(Shadow *) * j); + if (sl) + s->children = sl; + } + } + } + + if (list) + XFree(list); + + return s; +} + +static void +_ecore_x_window_tree_shadow_free1(Shadow *s) +{ + int i; + + if (!s) + return; + + if (s->children) + { + for (i = 0; i < s->children_num; i++) + { + if (s->children[i]) + _ecore_x_window_tree_shadow_free1(s->children[i]); + } + free(s->children); + } + + free(s); +} + +static void +_ecore_x_window_tree_shadow_free(void) +{ + int i; + + if (!shadow_base) + return; + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) + continue; + + _ecore_x_window_tree_shadow_free1(shadow_base[i]); + } + free(shadow_base); + shadow_base = NULL; + shadow_num = 0; +} + +static void +_ecore_x_window_tree_shadow_populate(void) +{ + Ecore_X_Window *roots; + int i, num; + + roots = ecore_x_window_root_list(&num); + if (roots) + { + shadow_base = calloc(1, sizeof(Shadow *) * num); + if (shadow_base) + { + shadow_num = num; + for (i = 0; i < num; i++) + shadow_base[i] = _ecore_x_window_tree_walk(roots[i]); + } + + free(roots); + } +} + +/* + static int shadow_count = 0; + + static void + _ecore_x_window_tree_shadow_start(void) + { + shadow_count++; + if (shadow_count > 1) return; + _ecore_x_window_tree_shadow_populate(); + } + + static void + _ecore_x_window_tree_shadow_stop(void) + { + shadow_count--; + if (shadow_count != 0) return; + _ecore_x_window_tree_shadow_free(); + } + */ + +static Shadow * +_ecore_x_window_shadow_tree_find_shadow(Shadow *s, + Window win) +{ + Shadow *ss; + int i; + + if (s->win == win) + return s; + + if (s->children) + for (i = 0; i < s->children_num; i++) + { + if (!s->children[i]) + continue; + + if ((ss = + _ecore_x_window_shadow_tree_find_shadow(s->children[i], win))) + return ss; + } + + return NULL; +} + +static Shadow * +_ecore_x_window_shadow_tree_find(Window base) +{ + Shadow *s; + int i; + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) + continue; + + if ((s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], base))) + return s; + } + return NULL; +} + +static int +_inside_rects(Shadow *s, + int x, + int y, + int bx, + int by, + Ecore_X_Rectangle *rects, + int num) +{ + int i, inside; + + if (!rects) return 0; + inside = 0; + for (i = 0; i < num; i++) + { + if ((x >= s->x + bx + rects[i].x) && + (y >= s->y + by + rects[i].y) && + (x < (int)(s->x + bx + rects[i].x + rects[i].width)) && + (y < (int)(s->y + by + rects[i].y + rects[i].height))) + { + inside = 1; + break; + } + } + free(rects); + return inside; +} + +static Window +_ecore_x_window_shadow_tree_at_xy_get_shadow(Shadow *s, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Window child; + int i, j; + int wx, wy; + + wx = s->x + bx; + wy = s->y + by; + if (!((x >= wx) && (y >= wy) && (x < (wx + s->w)) && (y < (wy + s->h)))) + return 0; + + /* FIXME: get shape */ + { + int num; + Ecore_X_Rectangle *rects; + + num = 0; + rects = ecore_x_window_shape_rectangles_get(s->win, &num); + if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; + num = 0; + rects = ecore_x_window_shape_input_rectangles_get(s->win, &num); + if (!_inside_rects(s, x, y, bx, by, rects, num)) return 0; + } + + if (s->children) + { + int skipit = 0; + + for (i = s->children_num - 1; i >= 0; --i) + { + if (!s->children[i]) + continue; + + skipit = 0; + if (skip) + for (j = 0; j < skip_num; j++) + { + if (s->children[i]->win == skip[j]) + { + skipit = 1; + goto onward; + } + } + +onward: + if (!skipit) + if ((child = + _ecore_x_window_shadow_tree_at_xy_get_shadow(s-> + children[i + ], wx, wy, + x, y, skip, + skip_num))) + return child; + } + } + + return s->win; +} + +static Window +_ecore_x_window_shadow_tree_at_xy_get(Window base, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Shadow *s; + + if (!shadow_base) + { + _ecore_x_window_tree_shadow_populate(); + if (!shadow_base) + return 0; + } + + s = _ecore_x_window_shadow_tree_find(base); + if (!s) + return 0; + + return _ecore_x_window_shadow_tree_at_xy_get_shadow(s, + bx, + by, + x, + y, + skip, + skip_num); +} + +/** + * Retrieves the top, visible window at the given location, + * but skips the windows in the list. This uses a shadow tree built from the + * window tree that is only updated the first time + * ecore_x_window_shadow_tree_at_xy_with_skip_get() is called, or the next time + * it is called after a ecore_x_window_shadow_tree_flush() + * @param base The base window to start searching from (normally root). + * @param x The given X position. + * @param y The given Y position. + * @param skip The list of windows to be skipped. + * @param skip_num The number of windows to be skipped. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_shadow_tree_at_xy_with_skip_get(Ecore_X_Window base, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_window_shadow_tree_at_xy_get(base, + 0, + 0, + x, + y, + skip, + skip_num); +} + +/** + * Retrieves the parent window a given window has. This uses the shadow window + * tree. + * @param root The root window of @p win - if 0, this will be automatically determined with extra processing overhead + * @param win The window to get the parent window of + * @return The parent window of @p win + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_shadow_parent_get(Ecore_X_Window root EINA_UNUSED, + Ecore_X_Window win) +{ + Shadow *s; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!shadow_base) + { + _ecore_x_window_tree_shadow_populate(); + if (!shadow_base) + return 0; + } + + for (i = 0; i < shadow_num; i++) + { + if (!shadow_base[i]) + continue; + + s = _ecore_x_window_shadow_tree_find_shadow(shadow_base[i], win); + if (s) + { + if (!s->parent) + return 0; + + return s->parent->win; + } + } + return 0; +} + +/** + * Flushes the window shadow tree so nothing is stored. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI void +ecore_x_window_shadow_tree_flush(void) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + _ecore_x_window_tree_shadow_free(); +} + +/** + * Retrieves the root window a given window is on. + * @param win The window to get the root window of + * @return The root window of @p win + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_root_get(Ecore_X_Window win) +{ + XWindowAttributes att; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) + return 0; + + return att.root; +} + +static Window +_ecore_x_window_at_xy_get(Window base, + int bx, + int by, + int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Window *list = NULL; + Window parent_win = 0, child = 0, root_win = 0; + int i, j, wx, wy, ww, wh; + unsigned int num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!ecore_x_window_visible_get(base)) + return 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_geometry_get(base, &wx, &wy, &ww, &wh); + wx += bx; + wy += by; + + if (!((x >= wx) && (y >= wy) && (x < (wx + ww)) && (y < (wy + wh)))) + return 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num)) + return base; + + if (list) + { + int skipit = 0; + + for (i = num - 1; i >= 0; --i) + { + skipit = 0; + + if (skip) + for (j = 0; j < skip_num; j++) + { + if (list[i] == skip[j]) + { + skipit = 1; + goto onward; + } + } + +onward: + if (!skipit) + if ((child = + _ecore_x_window_at_xy_get(list[i], wx, wy, x, y, skip, + skip_num))) + { + XFree(list); + return child; + } + } + XFree(list); + } + + return base; +} + +/** + * Retrieves the top, visible window at the given location. + * @param x The given X position. + * @param y The given Y position. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_get(int x, + int y) +{ + Ecore_X_Window win, root; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* FIXME: Proper function to determine current root/virtual root + * window missing here */ + root = DefaultRootWindow(_ecore_x_disp); + + ecore_x_grab(); + win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, NULL, 0); + ecore_x_ungrab(); + + return win ? win : root; +} + +/** + * Retrieves the top, visible window at the given location, + * but skips the windows in the list. + * @param x The given X position. + * @param y The given Y position. + * @param skip The list of windows to be skipped. + * @param skip_num The number of windows to be skipped. + * @return The window at that position. + * @ingroup Ecore_X_Window_Geometry_Group + */ +EAPI Ecore_X_Window +ecore_x_window_at_xy_with_skip_get(int x, + int y, + Ecore_X_Window *skip, + int skip_num) +{ + Ecore_X_Window win, root; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + /* FIXME: Proper function to determine current root/virtual root + * window missing here */ + root = DefaultRootWindow(_ecore_x_disp); + + ecore_x_grab(); + win = _ecore_x_window_at_xy_get(root, 0, 0, x, y, skip, skip_num); + ecore_x_ungrab(); + + return win ? win : root; +} + +EAPI Ecore_X_Window +ecore_x_window_at_xy_begin_get(Ecore_X_Window begin, + int x, + int y) +{ + Ecore_X_Window win; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_grab(); + win = _ecore_x_window_at_xy_get(begin, 0, 0, x, y, NULL, 0); + ecore_x_ungrab(); + + return win ? win : begin; +} + +/** + * Retrieves the parent window of the given window. + * @param win The given window. + * @return The parent window of @p win. + * @ingroup Ecore_X_Window_Parent_Group + */ +EAPI Ecore_X_Window +ecore_x_window_parent_get(Ecore_X_Window win) +{ + Window root, parent, *children = NULL; + unsigned int num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XQueryTree(_ecore_x_disp, win, &root, &parent, &children, &num)) + return 0; + + if (children) + XFree(children); + + return parent; +} + +/** + * Sets the background color of the given window. + * @param win The given window + * @param r red value (0...65536, 16 bits) + * @param g green value (0...65536, 16 bits) + * @param b blue value (0...65536, 16 bits) + */ +EAPI void +ecore_x_window_background_color_set(Ecore_X_Window win, + unsigned short r, + unsigned short g, + unsigned short b) +{ + XSetWindowAttributes attr; + Colormap map; + XColor col; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + col.red = r; + col.green = g; + col.blue = b; + + map = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp)); + XAllocColor(_ecore_x_disp, map, &col); + + attr.background_pixel = col.pixel; + XChangeWindowAttributes(_ecore_x_disp, win, CWBackPixel, &attr); +} + +EAPI void +ecore_x_window_gravity_set(Ecore_X_Window win, + Ecore_X_Gravity grav) +{ + XSetWindowAttributes att; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + att.win_gravity = grav; + XChangeWindowAttributes(_ecore_x_disp, win, CWWinGravity, &att); +} + +EAPI void +ecore_x_window_pixel_gravity_set(Ecore_X_Window win, + Ecore_X_Gravity grav) +{ + XSetWindowAttributes att; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + att.bit_gravity = grav; + XChangeWindowAttributes(_ecore_x_disp, win, CWBitGravity, &att); +} + +EAPI void +ecore_x_window_pixmap_set(Ecore_X_Window win, + Ecore_X_Pixmap pmap) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XSetWindowBackgroundPixmap(_ecore_x_disp, win, pmap); +} + +EAPI void +ecore_x_window_area_clear(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XClearArea(_ecore_x_disp, win, x, y, w, h, False); +} + +EAPI void +ecore_x_window_area_expose(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XClearArea(_ecore_x_disp, win, x, y, w, h, True); +} + +EAPI void +ecore_x_window_override_set(Ecore_X_Window win, + Eina_Bool override) +{ + XSetWindowAttributes att; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + att.override_redirect = override; + XChangeWindowAttributes(_ecore_x_disp, win, CWOverrideRedirect, &att); +} + +#ifdef ECORE_XRENDER +static Ecore_X_Window +_ecore_x_window_argb_internal_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h, + Eina_Bool override, + Eina_Bool saveunder) +{ + Window win; + XSetWindowAttributes attr; + XWindowAttributes att; + XVisualInfo *xvi; + XVisualInfo vi_in; + int nvi, i, scr = 0; + XRenderPictFormat *fmt; + Visual *vis; + + if (parent == 0) + { + parent = DefaultRootWindow(_ecore_x_disp); + scr = DefaultScreen(_ecore_x_disp); + } + else + { + /* ewww - round trip */ + XGetWindowAttributes(_ecore_x_disp, parent, &att); + for (i = 0; i < ScreenCount(_ecore_x_disp); i++) + { + if (att.screen == ScreenOfDisplay(_ecore_x_disp, i)) + { + scr = i; + break; + } + } + } + + vi_in.screen = scr; + vi_in.depth = 32; + vi_in.class = TrueColor; + xvi = XGetVisualInfo(_ecore_x_disp, + VisualScreenMask | + VisualDepthMask | + VisualClassMask, + &vi_in, + &nvi); + if (!xvi) + return 0; + + vis = NULL; + for (i = 0; i < nvi; i++) + { + fmt = XRenderFindVisualFormat(_ecore_x_disp, xvi[i].visual); + if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask)) + { + vis = xvi[i].visual; + break; + } + } + XFree (xvi); + + attr.backing_store = NotUseful; + attr.override_redirect = override; + attr.colormap = XCreateColormap(_ecore_x_disp, parent, + vis, AllocNone); + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.bit_gravity = NorthWestGravity; + attr.win_gravity = NorthWestGravity; + attr.save_under = saveunder; + attr.do_not_propagate_mask = NoEventMask; + attr.event_mask = KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + ExposureMask | + VisibilityChangeMask | + StructureNotifyMask | + FocusChangeMask | + PropertyChangeMask | + ColormapChangeMask; + win = XCreateWindow(_ecore_x_disp, parent, + x, y, w, h, 0, + 32, + InputOutput, + vis, + CWBackingStore | + CWOverrideRedirect | + CWColormap | + CWBorderPixel | + CWBackPixmap | + CWSaveUnder | + CWDontPropagate | + CWEventMask | + CWBitGravity | + CWWinGravity, + &attr); + XFreeColormap(_ecore_x_disp, attr.colormap); + + if (parent == DefaultRootWindow(_ecore_x_disp)) + ecore_x_window_defaults_set(win); + + return win; +} + +#endif /* ifdef ECORE_XRENDER */ + +EAPI int +ecore_x_window_argb_get(Ecore_X_Window win) +{ +#ifdef ECORE_XRENDER + XWindowAttributes att; + XRenderPictFormat *fmt; + + att.visual = 0; + if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) + return 0; + + fmt = XRenderFindVisualFormat(_ecore_x_disp, att.visual); + if (!fmt) + return 0; + + if ((fmt->type == PictTypeDirect) && (fmt->direct.alphaMask)) + return 1; + + return 0; +#else /* ifdef ECORE_XRENDER */ + return 0; +#endif /* ifdef ECORE_XRENDER */ +} + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_manager_argb_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XRENDER + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0); +#else /* ifdef ECORE_XRENDER */ + return 0; +#endif /* ifdef ECORE_XRENDER */ +} + +/** + * Creates a new window. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_argb_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XRENDER + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 0, 0); +#else /* ifdef ECORE_XRENDER */ + return 0; +#endif /* ifdef ECORE_XRENDER */ +} + +/** + * Creates a window with the override redirect attribute set to @c True. + * @param parent The parent window to use. If @p parent is @c 0, the root + * window of the default display is used. + * @param x X position. + * @param y Y position. + * @param w Width. + * @param h Height. + * @return The new window handle. + * @ingroup Ecore_X_Window_Create_Group + */ +EAPI Ecore_X_Window +ecore_x_window_override_argb_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h) +{ +#ifdef ECORE_XRENDER + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return _ecore_x_window_argb_internal_new(parent, x, y, w, h, 1, 0); +#else /* ifdef ECORE_XRENDER */ + return 0; +#endif /* ifdef ECORE_XRENDER */ +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_window_prop.c b/src/lib/ecore_x/xlib/ecore_x_window_prop.c new file mode 100644 index 0000000000..535c521941 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_window_prop.c @@ -0,0 +1,760 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" +#include <inttypes.h> +#include <limits.h> + +#define _ATOM_SET_CARD32(win, atom, p_val, cnt) \ + XChangeProperty(_ecore_x_disp, win, atom, XA_CARDINAL, 32, PropModeReplace, \ + (unsigned char *)p_val, cnt) + +/* + * Set CARD32 (array) property + */ +EAPI void +ecore_x_window_prop_card32_set(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int *val, + unsigned int num) +{ +#if SIZEOF_INT == SIZEOF_LONG + _ATOM_SET_CARD32(win, atom, val, num); +#else /* if SIZEOF_INT == SIZEOF_LONG */ + long *v2; + unsigned int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + v2 = malloc(num * sizeof(long)); + if (!v2) + return; + + for (i = 0; i < num; i++) + v2[i] = val[i]; + _ATOM_SET_CARD32(win, atom, v2, num); + free(v2); +#endif /* if SIZEOF_INT == SIZEOF_LONG */ +} + +/* + * Get CARD32 (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_card32_get(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int *val, + unsigned int len) +{ + unsigned char *prop_ret; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + unsigned int i; + int num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + prop_ret = NULL; + if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False, + XA_CARDINAL, &type_ret, &format_ret, &num_ret, + &bytes_after, &prop_ret) != Success) + return -1; + + if (type_ret != XA_CARDINAL || format_ret != 32) + num = -1; + else if (num_ret == 0 || !prop_ret) + num = 0; + else + { + if (num_ret < len) + len = num_ret; + + for (i = 0; i < len; i++) + val[i] = ((unsigned long *)prop_ret)[i]; + num = len; + } + + if (prop_ret) + XFree(prop_ret); + + return num; +} + +/* + * Get CARD32 (array) property of any length + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_card32_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + unsigned int **plst) +{ + unsigned char *prop_ret; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + unsigned int i, *val; + int num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + *plst = NULL; + prop_ret = NULL; + if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False, + XA_CARDINAL, &type_ret, &format_ret, &num_ret, + &bytes_after, &prop_ret) != Success) + return -1; + + if ((type_ret != XA_CARDINAL) || (format_ret != 32)) + num = -1; + else if ((num_ret == 0) || (!prop_ret)) + num = 0; + else + { + val = malloc(num_ret * sizeof(unsigned int)); + if (!val) + { + if (prop_ret) XFree(prop_ret); + return -1; + } + for (i = 0; i < num_ret; i++) + val[i] = ((unsigned long *)prop_ret)[i]; + num = num_ret; + *plst = val; + } + + if (prop_ret) + XFree(prop_ret); + + return num; +} + +/* + * Set X ID (array) property + */ +EAPI void +ecore_x_window_prop_xid_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID *lst, + unsigned int num) +{ +#if SIZEOF_INT == SIZEOF_LONG + XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace, + (unsigned char *)lst, num); +#else /* if SIZEOF_INT == SIZEOF_LONG */ + unsigned long *pl; + unsigned int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + pl = malloc(num * sizeof(long)); + if (!pl) + return; + + for (i = 0; i < num; i++) + pl[i] = lst[i]; + XChangeProperty(_ecore_x_disp, win, atom, type, 32, PropModeReplace, + (unsigned char *)pl, num); + free(pl); +#endif /* if SIZEOF_INT == SIZEOF_LONG */ +} + +/* + * Get X ID (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_xid_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID *lst, + unsigned int len) +{ + unsigned char *prop_ret; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + int num; + unsigned i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + prop_ret = NULL; + if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False, + type, &type_ret, &format_ret, &num_ret, + &bytes_after, &prop_ret) != Success) + return -1; + + if (type_ret != type || format_ret != 32) + num = -1; + else if (num_ret == 0 || !prop_ret) + num = 0; + else + { + if (num_ret < len) + len = num_ret; + + for (i = 0; i < len; i++) + lst[i] = ((unsigned long *)prop_ret)[i]; + num = len; + } + + if (prop_ret) + XFree(prop_ret); + + return num; +} + +/* + * Get X ID (array) property + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * The returned array must be freed with free(). + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_xid_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID **val) +{ + unsigned char *prop_ret; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + Ecore_X_Atom *alst; + int num; + unsigned i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + *val = NULL; + prop_ret = NULL; + if (XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False, + type, &type_ret, &format_ret, &num_ret, + &bytes_after, &prop_ret) != Success) + return -1; + + if (type_ret != type || format_ret != 32) + num = -1; + else if (num_ret == 0 || !prop_ret) + num = 0; + else + { + alst = malloc(num_ret * sizeof(Ecore_X_ID)); + for (i = 0; i < num_ret; i++) + alst[i] = ((unsigned long *)prop_ret)[i]; + num = num_ret; + *val = alst; + } + + if (prop_ret) + XFree(prop_ret); + + return num; +} + +/* + * Remove/add/toggle X ID list item. + */ +EAPI void +ecore_x_window_prop_xid_list_change(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom type, + Ecore_X_ID item, + int op) +{ + Ecore_X_ID *lst; + int i, num; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + num = ecore_x_window_prop_xid_list_get(win, atom, type, &lst); + if (num < 0) + { + return; /* Error - assuming invalid window */ + } + + /* Is it there? */ + for (i = 0; i < num; i++) + { + if (lst[i] == item) + break; + } + + if (i < num) + { + /* Was in list */ + if (op == ECORE_X_PROP_LIST_ADD) + goto done; /* Remove it */ + + num--; + for (; i < num; i++) + lst[i] = lst[i + 1]; + } + else + { + /* Was not in list */ + if (op == ECORE_X_PROP_LIST_REMOVE) + goto done; /* Add it */ + + num++; + lst = realloc(lst, num * sizeof(Ecore_X_ID)); + lst[i] = item; + } + + ecore_x_window_prop_xid_set(win, atom, type, lst, num); + +done: + if (lst) + free(lst); +} + +/* + * Set Atom (array) property + */ +EAPI void +ecore_x_window_prop_atom_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom *lst, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_xid_set(win, atom, XA_ATOM, lst, num); +} + +/* + * Get Atom (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_atom_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom *lst, + unsigned int len) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_window_prop_xid_get(win, atom, XA_ATOM, lst, len); +} + +/* + * Get Atom (array) property + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * The returned array must be freed with free(). + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_atom_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom **plst) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_window_prop_xid_list_get(win, atom, XA_ATOM, plst); +} + +/* + * Remove/add/toggle atom list item. + */ +EAPI void +ecore_x_window_prop_atom_list_change(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Atom item, + int op) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_xid_list_change(win, atom, XA_ATOM, item, op); +} + +/* + * Set Window (array) property + */ +EAPI void +ecore_x_window_prop_window_set(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window *lst, + unsigned int num) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + ecore_x_window_prop_xid_set(win, atom, XA_WINDOW, lst, num); +} + +/* + * Get Window (array) property + * + * At most len items are returned in val. + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_window_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window *lst, + unsigned int len) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_window_prop_xid_get(win, atom, XA_WINDOW, lst, len); +} + +/* + * Get Window (array) property + * + * If the property was successfully fetched the number of items stored in + * val is returned, otherwise -1 is returned. + * The returned array must be freed with free(). + * Note: Return value 0 means that the property exists but has no elements. + */ +EAPI int +ecore_x_window_prop_window_list_get(Ecore_X_Window win, + Ecore_X_Atom atom, + Ecore_X_Window **plst) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + return ecore_x_window_prop_xid_list_get(win, atom, XA_WINDOW, plst); +} + +EAPI Ecore_X_Atom +ecore_x_window_prop_any_type(void) +{ + return AnyPropertyType; +} + +/** + * @brief Set a property of Ecore_X_Window. + * @param win The window for which the property will be set. + * @param property The property of the window to be set. + * @param type The type of the property that will be set. + * @param size The size of the property that will be set. + * @param data The data of the property that will be set. + * @param number The size of data. + */ +EAPI void +ecore_x_window_prop_property_set(Ecore_X_Window win, + Ecore_X_Atom property, + Ecore_X_Atom type, + int size, + void *data, + int number) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); + + if (size != 32) + XChangeProperty(_ecore_x_disp, + win, + property, + type, + size, + PropModeReplace, + (unsigned char *)data, + number); + else + { + unsigned long *dat; + int i, *ptr; + + dat = malloc(sizeof(unsigned long) * number); + if (dat) + { + for (ptr = (int *)data, i = 0; i < number; i++) + dat[i] = ptr[i]; + XChangeProperty(_ecore_x_disp, win, property, type, size, + PropModeReplace, (unsigned char *)dat, number); + free(dat); + } + } +} + +/** + * @brief Get a property of Ecore_X_Window. + * @note If there aren't any data to be got the function return NULL. + * If the function can't allocate the memory then 0 is returned. + * @param win The window for which the property will be got. + * @param property The property of the window that will be gotten. + * @param type The type of the property that will be gotten. + * @param size This parameter isn't in use. + * @param data The data of the property that will be gotten. + * @param num The size of property. + * @return size_ret The size of array that contains the property. + */ +EAPI int +ecore_x_window_prop_property_get(Ecore_X_Window win, + Ecore_X_Atom property, + Ecore_X_Atom type, + int size EINA_UNUSED, + unsigned char **data, + int *num) +{ + Atom type_ret = 0; + int ret, size_ret = 0; + unsigned long num_ret = 0, bytes = 0, i; + unsigned char *prop_ret = NULL; + + /* make sure these are initialized */ + if (num) + *num = 0; + + if (data) + *data = NULL; + else /* we can't store the retrieved data, so just return */ + return 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!win) + win = DefaultRootWindow(_ecore_x_disp); + + ret = XGetWindowProperty(_ecore_x_disp, win, property, 0, LONG_MAX, + False, type, &type_ret, &size_ret, + &num_ret, &bytes, &prop_ret); + + if (ret != Success) + return 0; + + if (!num_ret) + { + XFree(prop_ret); + return 0; + } + + if (!(*data = malloc(num_ret * size_ret / 8))) + { + XFree(prop_ret); + return 0; + } + + switch (size_ret) { + case 8: + for (i = 0; i < num_ret; i++) + (*data)[i] = prop_ret[i]; + break; + + case 16: + for (i = 0; i < num_ret; i++) + ((unsigned short *)*data)[i] = ((unsigned short *)prop_ret)[i]; + break; + + case 32: + for (i = 0; i < num_ret; i++) + ((unsigned int *)*data)[i] = ((unsigned long *)prop_ret)[i]; + break; + } + + XFree(prop_ret); + + if (num) + *num = num_ret; + + return size_ret; +} + +EAPI void +ecore_x_window_prop_property_del(Ecore_X_Window win, + Ecore_X_Atom property) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XDeleteProperty(_ecore_x_disp, win, property); +} + +EAPI Ecore_X_Atom * +ecore_x_window_prop_list(Ecore_X_Window win, + int *num_ret) +{ + Ecore_X_Atom *atoms; + Atom *atom_ret; + int num = 0, i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num_ret) + *num_ret = 0; + + atom_ret = XListProperties(_ecore_x_disp, win, &num); + if (!atom_ret) + return NULL; + + atoms = malloc(num * sizeof(Ecore_X_Atom)); + if (atoms) + { + for (i = 0; i < num; i++) + atoms[i] = atom_ret[i]; + if (num_ret) + *num_ret = num; + } + + XFree(atom_ret); + return atoms; +} + +/** + * Set a window string property. + * @param win The window + * @param type The property + * @param str The string + * + * Set a window string property + */ +EAPI void +ecore_x_window_prop_string_set(Ecore_X_Window win, + Ecore_X_Atom type, + const char *str) +{ + XTextProperty xtp; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); + + xtp.value = (unsigned char *)str; + xtp.format = 8; + xtp.encoding = ECORE_X_ATOM_UTF8_STRING; + xtp.nitems = strlen(str); + XSetTextProperty(_ecore_x_disp, win, &xtp, type); +} + +/** + * Get a window string property. + * @param win The window + * @param type The property + * @return Window string property of a window. String must be free'd when done. + */ +EAPI char * +ecore_x_window_prop_string_get(Ecore_X_Window win, + Ecore_X_Atom type) +{ + XTextProperty xtp; + char *str = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (win == 0) + win = DefaultRootWindow(_ecore_x_disp); + + if (XGetTextProperty(_ecore_x_disp, win, &xtp, type)) + { + int items; + char **list = NULL; + Status s; + + if (xtp.encoding == ECORE_X_ATOM_UTF8_STRING) + str = strdup((char *)xtp.value); + else + { +#ifdef X_HAVE_UTF8_STRING + s = Xutf8TextPropertyToTextList(_ecore_x_disp, &xtp, + &list, &items); +#else /* ifdef X_HAVE_UTF8_STRING */ + s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp, + &list, &items); +#endif /* ifdef X_HAVE_UTF8_STRING */ + if ((s == XLocaleNotSupported) || + (s == XNoMemory) || (s == XConverterNotFound)) + str = strdup((char *)xtp.value); + else if ((s >= Success) && (items > 0)) + str = strdup(list[0]); + + if (list) + XFreeStringList(list); + } + + XFree(xtp.value); + } + + return str; +} + +EAPI Eina_Bool +ecore_x_window_prop_protocol_isset(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol) +{ + Atom proto, *protos = NULL; + int i, protos_count = 0; + Eina_Bool ret = EINA_FALSE; + + /* check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + proto = _ecore_x_atoms_wm_protocols[protocol]; + + if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count)) + return ret; + + for (i = 0; i < protos_count; i++) + if (protos[i] == proto) + { + ret = EINA_TRUE; + break; + } + + XFree(protos); + + return ret; +} + +/** + * @brief Get a array containing the protocols of @a win + * @note If there aren't any properties to be counted or any protocols to get + * then the function returns NULL. + * @param win The window for which protocol list will be got. + * @param num_ret Contains the number of elements of the array to be returned. + * @return The array that contains the protocols. + */ +EAPI Ecore_X_WM_Protocol * +ecore_x_window_prop_protocol_list_get(Ecore_X_Window win, + int *num_ret) +{ + Atom *protos = NULL; + int i, protos_count = 0; + Ecore_X_WM_Protocol *prot_ret = NULL; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count)) + return NULL; + + if ((!protos) || (protos_count <= 0)) + return NULL; + + prot_ret = calloc(1, protos_count * sizeof(Ecore_X_WM_Protocol)); + if (!prot_ret) + { + XFree(protos); + return NULL; + } + + for (i = 0; i < protos_count; i++) + { + Ecore_X_WM_Protocol j; + + prot_ret[i] = -1; + for (j = 0; j < ECORE_X_WM_PROTOCOL_NUM; j++) + { + if (_ecore_x_atoms_wm_protocols[j] == protos[i]) + prot_ret[i] = j; + } + } + XFree(protos); + *num_ret = protos_count; + return prot_ret; +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_window_shape.c b/src/lib/ecore_x/xlib/ecore_x_window_shape.c new file mode 100644 index 0000000000..71718cfa3a --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_window_shape.c @@ -0,0 +1,658 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <stdlib.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +/** + * @defgroup Ecore_X_Window_Shape X Window Shape Functions + * + * These functions use the shape extension of the X server to change + * shape of given windows. + */ + +/** + * Sets the shape of the given window to that given by the pixmap @p mask. + * @param win The given window. + * @param mask A 2-bit depth pixmap that provides the new shape of the + * window. + * @ingroup Ecore_X_Window_Shape + */ +EAPI void +ecore_x_window_shape_mask_set(Ecore_X_Window win, + Ecore_X_Pixmap mask) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineMask(_ecore_x_disp, win, ShapeBounding, 0, 0, mask, ShapeSet); +} + +/** + * Sets the input shape of the given window to that given by the pixmap @p mask. + * @param win The given window. + * @param mask A 1-bit depth pixmap that provides the new input shape of the + * window. + * @ingroup Ecore_X_Window_Shape + */ +EAPI void +ecore_x_window_shape_input_mask_set(Ecore_X_Window win, + Ecore_X_Pixmap mask) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +#ifdef ShapeInput + XShapeCombineMask(_ecore_x_disp, win, ShapeInput, 0, 0, mask, ShapeSet); +#else /* ifdef ShapeInput */ + return; + win = mask = 0; +#endif /* ifdef ShapeInput */ +} + +EAPI void +ecore_x_window_shape_window_set(Ecore_X_Window win, + Ecore_X_Window shape_win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + shape_win, + ShapeBounding, + ShapeSet); +} + +EAPI void +ecore_x_window_shape_input_window_set(Ecore_X_Window win, + Ecore_X_Window shape_win) +{ +#ifdef ShapeInput + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + shape_win, + ShapeInput, + ShapeSet); +#else + return; + win = shape_win = 0; +#endif +} + +EAPI void +ecore_x_window_shape_window_set_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeBounding, + x, + y, + shape_win, + ShapeBounding, + ShapeSet); +} + +EAPI void +ecore_x_window_shape_input_window_set_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ +#ifdef ShapeInput + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeInput, + x, + y, + shape_win, + ShapeInput, + ShapeSet); +#else + return; + win = shape_win = x = y = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + &rect, + 1, + ShapeSet, + Unsorted); +} + +EAPI void +ecore_x_window_shape_input_rectangle_set(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ShapeInput + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + &rect, + 1, + ShapeSet, + Unsorted); +#else + return; + win = x = y = w = h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangles_set(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ShapeInput + XRectangle *rect = NULL; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!rects) return; + if (num > 0) + { + rect = malloc(sizeof(XRectangle) * num); + if (!rect) return; + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + rect, + num, + ShapeSet, + Unsorted); + if (rect) free(rect); +#else + return; + win = rects = num = 0; +#endif +} + +EAPI void +ecore_x_window_shape_input_rectangles_set(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ShapeInput + XRectangle *rect = NULL; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (!rects) return; + if (num > 0) + { + rect = malloc(sizeof(XRectangle) * num); + if (!rect) return; + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + rect, + num, + ShapeSet, + Unsorted); + if (rect) free(rect); +#else + return; + win = rects = num = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_subtract(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + &rect, + 1, + ShapeSubtract, + Unsorted); +} + +EAPI void +ecore_x_window_shape_input_rectangle_subtract(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ShapeInput + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + &rect, + 1, + ShapeSubtract, + Unsorted); +#else + return; + win = x = y = w = h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_window_add(Ecore_X_Window win, + Ecore_X_Window shape_win) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + shape_win, + ShapeBounding, + ShapeUnion); +} + +EAPI void +ecore_x_window_shape_window_add_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeBounding, + x, + y, + shape_win, + ShapeBounding, + ShapeUnion); +} + +EAPI void +ecore_x_window_shape_input_window_add_xy(Ecore_X_Window win, + Ecore_X_Window shape_win, + int x, + int y) +{ +#ifdef ShapeInput + LOGFN(__FILE__, __LINE__, __FUNCTION__); + XShapeCombineShape(_ecore_x_disp, + win, + ShapeInput, + x, + y, + shape_win, + ShapeInput, + ShapeUnion); +#else + return; + win = shape_win = x = y = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_add(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + &rect, + 1, + ShapeUnion, + Unsorted); +} + +EAPI void +ecore_x_window_shape_input_rectangle_add(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ShapeInput + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + &rect, + 1, + ShapeUnion, + Unsorted); +#else + return; + win = x = y = w = h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + &rect, + 1, + ShapeIntersect, + Unsorted); +} + +EAPI void +ecore_x_window_shape_input_rectangle_clip(Ecore_X_Window win, + int x, + int y, + int w, + int h) +{ +#ifdef ShapeInput + XRectangle rect; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + &rect, + 1, + ShapeIntersect, + Unsorted); +#else + return; + win = x = y = w = h = 0; +#endif +} + +EAPI void +ecore_x_window_shape_rectangles_add(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ + XRectangle *rect = NULL; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num > 0) + { + rect = malloc(sizeof(XRectangle) * num); + if (!rect) return; + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeBounding, + 0, + 0, + rect, + num, + ShapeUnion, + Unsorted); + if (rect) free(rect); +} + +EAPI void +ecore_x_window_shape_input_rectangles_add(Ecore_X_Window win, + Ecore_X_Rectangle *rects, + int num) +{ +#ifdef ShapeInput + XRectangle *rect = NULL; + int i; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (num > 0) + { + rect = malloc(sizeof(XRectangle) * num); + if (!rect) return; + for (i = 0; i < num; i++) + { + rect[i].x = rects[i].x; + rect[i].y = rects[i].y; + rect[i].width = rects[i].width; + rect[i].height = rects[i].height; + } + } + + XShapeCombineRectangles(_ecore_x_disp, + win, + ShapeInput, + 0, + 0, + rect, + num, + ShapeUnion, + Unsorted); + if (rect) free(rect); +#else + return; + win = rects = num = 0; +#endif +} + +EAPI Ecore_X_Rectangle * +ecore_x_window_shape_rectangles_get(Ecore_X_Window win, + int *num_ret) +{ + XRectangle *rect; + Ecore_X_Rectangle *rects = NULL; + int i, num = 0, ord; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect = XShapeGetRectangles(_ecore_x_disp, win, ShapeBounding, &num, &ord); + if (rect) + { + if (num < 1) + { + XFree(rect); + if (num_ret) *num_ret = 0; + return NULL; + } + rects = malloc(sizeof(Ecore_X_Rectangle) * num); + if (!rects) + { + XFree(rect); + if (num_ret) *num_ret = 0; + return NULL; + } + for (i = 0; i < num; i++) + { + rects[i].x = rect[i].x; + rects[i].y = rect[i].y; + rects[i].width = rect[i].width; + rects[i].height = rect[i].height; + } + XFree(rect); + } + if (num_ret) *num_ret = num; + return rects; +} + +EAPI Ecore_X_Rectangle * +ecore_x_window_shape_input_rectangles_get(Ecore_X_Window win, + int *num_ret) +{ + Ecore_X_Rectangle *rects = NULL; +#ifdef ShapeInput + XRectangle *rect; + int i, num = 0, ord; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + rect = XShapeGetRectangles(_ecore_x_disp, win, ShapeInput, &num, &ord); + if (rect) + { + if (num < 1) + { + XFree(rect); + if (num_ret) *num_ret = 0; + return NULL; + } + rects = malloc(sizeof(Ecore_X_Rectangle) * num); + if (!rects) + { + XFree(rect); + if (num_ret) *num_ret = 0; + return NULL; + } + for (i = 0; i < num; i++) + { + rects[i].x = rect[i].x; + rects[i].y = rect[i].y; + rects[i].width = rect[i].width; + rects[i].height = rect[i].height; + } + XFree(rect); + } + if (num_ret) *num_ret = num; + return rects; +#else + // have to return fake shape input rect of size of window + Window dw; + unsigned int di; + + if (num_ret) *num_ret = 0; + rects = malloc(sizeof(Ecore_X_Rectangle)); + if (!rects) return NULL; + if (!XGetGeometry(_ecore_x_disp, win, &dw, + &(rects[0].x), &(rects[0].y), + &(rects[0].width), &(rects[0].height), + &di, &di)) + { + free(rects); + return NULL; + } + if (num_ret) *num_ret = 1; + return rects; +#endif +} + +EAPI void +ecore_x_window_shape_events_select(Ecore_X_Window win, + Eina_Bool on) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (on) + XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); + else + XShapeSelectInput(_ecore_x_disp, win, 0); +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_xi2.c b/src/lib/ecore_x/xlib/ecore_x_xi2.c new file mode 100644 index 0000000000..04d1023ec7 --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_xi2.c @@ -0,0 +1,336 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include <string.h> + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +#ifdef ECORE_XI2 +#include "Ecore_Input.h" +#endif /* ifdef ECORE_XI2 */ + +int _ecore_x_xi2_opcode = -1; + +#ifndef XIPointerEmulated +#define XIPointerEmulated (1 << 16) +#endif + +#ifdef ECORE_XI2 +static XIDeviceInfo *_ecore_x_xi2_devs = NULL; +static int _ecore_x_xi2_num = 0; +#endif /* ifdef ECORE_XI2 */ + +void +_ecore_x_input_init(void) +{ +#ifdef ECORE_XI2 + int event, error; + int major = 2, minor = 0; + + if (!XQueryExtension(_ecore_x_disp, "XInputExtension", + &_ecore_x_xi2_opcode, &event, &error)) + { + _ecore_x_xi2_opcode = -1; + return; + } + + if (XIQueryVersion(_ecore_x_disp, &major, &minor) == BadRequest) + { + _ecore_x_xi2_opcode = -1; + return; + } + + _ecore_x_xi2_devs = XIQueryDevice(_ecore_x_disp, XIAllDevices, + &_ecore_x_xi2_num); +#endif /* ifdef ECORE_XI2 */ +} + +void +_ecore_x_input_shutdown(void) +{ +#ifdef ECORE_XI2 + if (_ecore_x_xi2_devs) + { + XIFreeDeviceInfo(_ecore_x_xi2_devs); + _ecore_x_xi2_devs = NULL; + } + + _ecore_x_xi2_num = 0; + _ecore_x_xi2_opcode = -1; +#endif /* ifdef ECORE_XI2 */ +} + +void +_ecore_x_input_handler(XEvent *xevent) +{ +#ifdef ECORE_XI2 + XIDeviceEvent *evd = (XIDeviceEvent *)(xevent->xcookie.data); + /* XIRawEvent *evr = (XIRawEvent *)(xevent->xcookie.data); */ + int devid = evd->deviceid; + int i; + + /* No filter for this events */ + switch (xevent->xcookie.evtype) + { +#ifdef XI_RawButtonPress + case XI_RawButtonPress: + ecore_event_add(ECORE_X_RAW_BUTTON_PRESS, NULL, NULL, NULL); + break; +#endif +#ifdef XI_RawButtonRelease + case XI_RawButtonRelease: + ecore_event_add(ECORE_X_RAW_BUTTON_RELEASE, NULL, NULL, NULL); + break; +#endif +#ifdef XI_RawMotion + case XI_RawMotion: + ecore_event_add(ECORE_X_RAW_MOTION, NULL, NULL, NULL); + break; +#endif + } + + if (_ecore_x_xi2_devs) + { + for (i = 0; i < _ecore_x_xi2_num; i++) + { + XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]); + + if (devid == dev->deviceid) + { + if (dev->use == XIMasterPointer) return; + if ((dev->use == XISlavePointer) && + (evd->flags & XIPointerEmulated)) return; + } + } + } + switch (xevent->xcookie.evtype) + { + case XI_Motion: + _ecore_mouse_move + (evd->time, + 0, // state + evd->event_x, evd->event_y, + evd->root_x, evd->root_y, + evd->event, + (evd->child ? evd->child : evd->event), + evd->root, + 1, // same_screen + devid, 1, 1, + 1.0, // pressure + 0.0, // angle + evd->event_x, evd->event_y, + evd->root_x, evd->root_y); + break; + + case XI_ButtonPress: + _ecore_mouse_button + (ECORE_EVENT_MOUSE_BUTTON_DOWN, + evd->time, + 0, // state + 0, // button + evd->event_x, evd->event_y, + evd->root_x, evd->root_y, + evd->event, + (evd->child ? evd->child : evd->event), + evd->root, + 1, // same_screen + devid, 1, 1, + 1.0, // pressure + 0.0, // angle + evd->event_x, evd->event_y, + evd->root_x, evd->root_y); + break; + + case XI_ButtonRelease: + _ecore_mouse_button + (ECORE_EVENT_MOUSE_BUTTON_UP, + evd->time, + 0, // state + 0, // button + evd->event_x, evd->event_y, + evd->root_x, evd->root_y, + evd->event, + (evd->child ? evd->child : evd->event), + evd->root, + 1, // same_screen + devid, 1, 1, + 1.0, // pressure + 0.0, // angle + evd->event_x, evd->event_y, + evd->root_x, evd->root_y); + break; + +#ifdef XI_TouchUpdate + case XI_TouchUpdate: + _ecore_mouse_move + (evd->time, + 0, // state + evd->event_x, evd->event_y, + evd->root_x, evd->root_y, + evd->event, + (evd->child ? evd->child : evd->event), + evd->root, + 1, // same_screen + devid, 1, 1, + 1.0, // pressure + 0.0, // angle + evd->event_x, evd->event_y, + evd->root_x, evd->root_y); + break; + +#endif +#ifdef XI_TouchBegin + case XI_TouchBegin: + _ecore_mouse_button + (ECORE_EVENT_MOUSE_BUTTON_DOWN, + evd->time, + 0, // state + 0, // button + evd->event_x, evd->event_y, + evd->root_x, evd->root_y, + evd->event, + (evd->child ? evd->child : evd->event), + evd->root, + 1, // same_screen + devid, 1, 1, + 1.0, // pressure + 0.0, // angle + evd->event_x, evd->event_y, + evd->root_x, evd->root_y); + break; + +#endif +#ifdef XI_TouchEnd + case XI_TouchEnd: + _ecore_mouse_button + (ECORE_EVENT_MOUSE_BUTTON_UP, + evd->time, + 0, // state + 0, // button + evd->event_x, evd->event_y, + evd->root_x, evd->root_y, + evd->event, + (evd->child ? evd->child : evd->event), + evd->root, + 1, // same_screen + devid, 1, 1, + 1.0, // pressure + 0.0, // angle + evd->event_x, evd->event_y, + evd->root_x, evd->root_y); + break; + +#endif + default: + break; + } +#endif /* ifdef ECORE_XI2 */ +} + +EAPI Eina_Bool +ecore_x_input_multi_select(Ecore_X_Window win) +{ +#ifdef ECORE_XI2 + int i; + Eina_Bool find = EINA_FALSE; + + if (!_ecore_x_xi2_devs) + return 0; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + for (i = 0; i < _ecore_x_xi2_num; i++) + { + XIDeviceInfo *dev = &(_ecore_x_xi2_devs[i]); + + if (dev->use == XIFloatingSlave) + { + XIEventMask eventmask; + unsigned char mask[4] = { 0 }; + + eventmask.deviceid = dev->deviceid; + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); + XISelectEvents(_ecore_x_disp, win, &eventmask, 1); + find = EINA_TRUE; + } + else if (dev->use == XISlavePointer) + { + XIDeviceInfo *atdev = NULL; + int j; + + for (j = 0; j < _ecore_x_xi2_num; j++) + { + if (_ecore_x_xi2_devs[j].deviceid == dev->attachment) + atdev = &(_ecore_x_xi2_devs[j]); + } + if (((atdev) && (atdev->use != XIMasterPointer)) || + (!atdev)) + { + XIEventMask eventmask; + unsigned char mask[4] = { 0 }; + + eventmask.deviceid = dev->deviceid; + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); +# ifdef XI_TouchUpdate + XISetMask(mask, XI_TouchUpdate); +# endif +# ifdef XI_TouchBegin + XISetMask(mask, XI_TouchBegin); +# endif +# ifdef XI_TouchEnd + XISetMask(mask, XI_TouchEnd); +# endif + XISelectEvents(_ecore_x_disp, win, &eventmask, 1); + find = EINA_TRUE; + } + } + } + + return find; +#else /* ifdef ECORE_XI2 */ + return EINA_FALSE; +#endif /* ifdef ECORE_XI2 */ +} + +EAPI Eina_Bool +ecore_x_input_raw_select(Ecore_X_Window win) +{ +#ifdef ECORE_XI2 + XIEventMask emask; + unsigned char mask[4] = { 0 }; + + if (!_ecore_x_xi2_devs) + return EINA_FALSE; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + emask.deviceid = XIAllMasterDevices; + emask.mask_len = sizeof(mask); + emask.mask = mask; +#ifdef XI_RawButtonPress + XISetMask(emask.mask, XI_RawButtonPress); +#endif +#ifdef XI_RawButtonRelease + XISetMask(emask.mask, XI_RawButtonRelease); +#endif +#ifdef XI_RawMotion + XISetMask(emask.mask, XI_RawMotion); +#endif + + XISelectEvents(_ecore_x_disp, win, &emask, 1); + + return EINA_TRUE; +#else + return EINA_FALSE; +#endif +} + diff --git a/src/lib/ecore_x/xlib/ecore_x_xinerama.c b/src/lib/ecore_x/xlib/ecore_x_xinerama.c new file mode 100644 index 0000000000..f49a4d348f --- /dev/null +++ b/src/lib/ecore_x/xlib/ecore_x_xinerama.c @@ -0,0 +1,91 @@ +/* + * Xinerama code + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* ifdef HAVE_CONFIG_H */ + +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +#ifdef ECORE_XINERAMA +static XineramaScreenInfo *_xin_info = NULL; +static int _xin_scr_num = 0; +#endif /* ifdef ECORE_XINERAMA */ + +EAPI int +ecore_x_xinerama_screen_count_get(void) +{ +#ifdef ECORE_XINERAMA + int event_base, error_base; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (_xin_info) + XFree(_xin_info); + + _xin_info = NULL; + if (XineramaQueryExtension(_ecore_x_disp, &event_base, &error_base)) + { + _xin_info = XineramaQueryScreens(_ecore_x_disp, &_xin_scr_num); + if (_xin_info) + return _xin_scr_num; + } + +#endif /* ifdef ECORE_XINERAMA */ + return 0; +} + +EAPI Eina_Bool +ecore_x_xinerama_screen_geometry_get(int screen, + int *x, + int *y, + int *w, + int *h) +{ + LOGFN(__FILE__, __LINE__, __FUNCTION__); +#ifdef ECORE_XINERAMA + if (_xin_info) + { + int i; + + for (i = 0; i < _xin_scr_num; i++) + { + if (_xin_info[i].screen_number == screen) + { + if (x) + *x = _xin_info[i].x_org; + + if (y) + *y = _xin_info[i].y_org; + + if (w) + *w = _xin_info[i].width; + + if (h) + *h = _xin_info[i].height; + + return EINA_TRUE; + } + } + } + +#endif /* ifdef ECORE_XINERAMA */ + if (x) + *x = 0; + + if (y) + *y = 0; + + if (w) + *w = DisplayWidth(_ecore_x_disp, 0); + + if (h) + *h = DisplayHeight(_ecore_x_disp, 0); + + return EINA_FALSE; + screen = 0; +} + |