diff options
author | puppetmaster <puppetmaster> | 2005-07-25 17:06:37 +0000 |
---|---|---|
committer | puppetmaster <puppetmaster> | 2005-07-25 17:06:37 +0000 |
commit | f7314c870669f105d21814729b9fe2dd1160437d (patch) | |
tree | c5696f507133bb90ea3fef39fc4849c68f77fe2b /ecore/src | |
parent | fix for struct usage ... -> and not "." (diff) | |
download | elock-f7314c870669f105d21814729b9fe2dd1160437d.tar.xz |
adding last snapshot of ecore for ecore_x_screensaver
Diffstat (limited to 'ecore/src')
190 files changed, 46799 insertions, 0 deletions
diff --git a/ecore/src/.cvsignore b/ecore/src/.cvsignore new file mode 100644 index 0000000..282522d --- /dev/null +++ b/ecore/src/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/ecore/src/CVS/Entries b/ecore/src/CVS/Entries new file mode 100644 index 0000000..8b75dcf --- /dev/null +++ b/ecore/src/CVS/Entries @@ -0,0 +1,12 @@ +/.cvsignore/1.3/Thu Nov 13 12:30:47 2003//THEAD +/Ecore.h/1.49/Tue Sep 23 08:09:28 2003//THEAD +/Makefile.am/1.10/Thu Mar 10 15:19:35 2005//THEAD +/e_ev_filter.c/1.8/Tue Sep 23 08:09:28 2003//THEAD +/e_ev_signal.c/1.7/Tue Sep 23 08:09:28 2003//THEAD +/e_ev_x.c/1.30/Tue Sep 23 08:09:28 2003//THEAD +/e_events.c/1.16/Tue Sep 23 08:09:28 2003//THEAD +/e_ipc.c/1.5/Tue Sep 23 08:09:28 2003//THEAD +/e_util.c/1.7/Tue Sep 23 08:09:28 2003//THEAD +/e_x.c/1.56/Tue Sep 23 08:09:28 2003//THEAD +D/bin//// +D/lib//// diff --git a/ecore/src/CVS/Repository b/ecore/src/CVS/Repository new file mode 100644 index 0000000..0014dc3 --- /dev/null +++ b/ecore/src/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src diff --git a/ecore/src/CVS/Root b/ecore/src/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/CVS/Tag b/ecore/src/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/Ecore.h b/ecore/src/Ecore.h new file mode 100644 index 0000000..9bdd679 --- /dev/null +++ b/ecore/src/Ecore.h @@ -0,0 +1,916 @@ +#ifndef E_CORE_H +#define E_CORE_H 1 + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <signal.h> + +#define XK_MISCELLANY 1 + +#include <X11/Xlib.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> +#ifdef WITH_DMALLOC +#include <dmalloc.h> +#endif + +#define XEV_NONE NoEventMask +#define XEV_KEY KeyPressMask | KeyReleaseMask +#define XEV_BUTTON ButtonPressMask | ButtonReleaseMask +#define XEV_KEY_PRESS KeyPressMask +#define XEV_KEY_RELEASE KeyReleaseMask +#define XEV_BUTTON_PRESS ButtonPressMask +#define XEV_BUTTON_RELEASE ButtonReleaseMask +#define XEV_IN_OUT EnterWindowMask | LeaveWindowMask +#define XEV_MOUSE_MOVE PointerMotionMask | ButtonMotionMask +#define XEV_EXPOSE ExposureMask +#define XEV_VISIBILITY VisibilityChangeMask +#define XEV_CONFIGURE StructureNotifyMask +#define XEV_CHILD_CHANGE SubstructureNotifyMask +#define XEV_CHILD_REDIRECT SubstructureRedirectMask | ResizeRedirectMask +#define XEV_FOCUS FocusChangeMask +#define XEV_PROPERTY PropertyChangeMask +#define XEV_COLORMAP ColormapChangeMask + + +#define ECORE_ATOM(atom, name) \ + if (!atom) (atom) = ecore_atom_get(name); +#define MEMCPY(src, dst, type, num) \ + memcpy(dst, src, sizeof(type) * (num)) +#define NEW(type, num) \ + malloc(sizeof(type) * (num)) +#define ZERO(ptr, type, num) \ + memset((ptr), 0, sizeof(type) * (num)) +#define NEW_PTR(num) \ + malloc(sizeof(void *) * (num)) +#define FREE(ptr) \ + { \ + free(ptr); \ + (ptr) = NULL; \ + } +#define IF_FREE(ptr) \ + {if (ptr) FREE(ptr);} +#define REALLOC(ptr, type, num) \ + { \ + if ((ptr) && (num == 0)) {free(ptr); ptr = NULL;} \ + else if (ptr) ptr = realloc((ptr), sizeof(type) * (num)); \ + else ptr = malloc(sizeof(type) * (num)); \ + } +#define REALLOC_PTR(ptr, num) \ + { \ + if ((ptr) && (num == 0)) {free(ptr); ptr = NULL;} \ + else if (ptr) ptr = realloc(ptr, sizeof(void *) * (num)); \ + else ptr = malloc(sizeof(void *) * (num)); \ + } + +#define START_LIST_DEL(type, base, cmp) \ + type *_p, *_pp; _pp = NULL; \ + _p = (base); \ + while(_p) \ + { \ + if (cmp) \ + { \ + if (_pp) _pp->next = _p->next; \ + else (base) = _p->next; +#define END_LIST_DEL \ + return; \ + } \ + _pp = _p; \ + _p = _p->next; \ + } + +#define DND_TYPE_URI_LIST 0 +#define DND_TYPE_PLAIN_TEXT 1 +#define DND_TYPE_MOZ_URL 2 +#define DND_TYPE_NETSCAPE_URL 3 + +#ifdef __cplusplus +extern "C" +{ +#endif + + extern XContext xid_context; + + typedef void (*Ecore_Error_Function) (Display * d, XErrorEvent * ev); + + typedef struct _ecore_keygrab Ecore_KeyGrab; + + typedef enum _ecore_ev_modifiers + { + ECORE_EVENT_KEY_MODIFIER_NONE = 0, + ECORE_EVENT_KEY_MODIFIER_SHIFT = (1 << 0), + ECORE_EVENT_KEY_MODIFIER_CTRL = (1 << 1), + ECORE_EVENT_KEY_MODIFIER_ALT = (1 << 2), + ECORE_EVENT_KEY_MODIFIER_WIN = (1 << 3) + } Ecore_Event_Key_Modifiers; + + typedef enum _ecore_event_stack_detail + { + ECORE_EVENT_STACK_ABOVE = Above, + ECORE_EVENT_STACK_BELOW = Below, + ECORE_EVENT_STACK_TOP_IF = TopIf, + ECORE_EVENT_STACK_BOTTOM_IF = BottomIf, + ECORE_EVENT_STACK_OPPOSITE = Opposite + } Ecore_Event_Stack_Detail; + + typedef enum _ecore_event_value_mask + { + ECORE_EVENT_VALUE_X = CWX, + ECORE_EVENT_VALUE_Y = CWY, + ECORE_EVENT_VALUE_W = CWWidth, + ECORE_EVENT_VALUE_H = CWHeight, + ECORE_EVENT_VALUE_BORDER = CWBorderWidth, + ECORE_EVENT_VALUE_SIBLING = CWSibling, + ECORE_EVENT_VALUE_STACKING = CWStackMode + } Ecore_Event_Value_Mask; + + typedef enum _ecore_event_type + { + ECORE_EVENT_MOUSE_MOVE, + ECORE_EVENT_MOUSE_DOWN, + ECORE_EVENT_MOUSE_UP, + ECORE_EVENT_MOUSE_IN, + ECORE_EVENT_MOUSE_OUT, + ECORE_EVENT_MOUSE_WHEEL, + ECORE_EVENT_KEY_DOWN, + ECORE_EVENT_KEY_UP, + ECORE_EVENT_WINDOW_MAP, + ECORE_EVENT_WINDOW_UNMAP, + ECORE_EVENT_WINDOW_CREATE, + ECORE_EVENT_WINDOW_DESTROY, + ECORE_EVENT_WINDOW_CONFIGURE, + ECORE_EVENT_WINDOW_CONFIGURE_REQUEST, + ECORE_EVENT_WINDOW_MAP_REQUEST, + ECORE_EVENT_WINDOW_PROPERTY, + ECORE_EVENT_WINDOW_CIRCULATE, + ECORE_EVENT_WINDOW_CIRCULATE_REQUEST, + ECORE_EVENT_WINDOW_REPARENT, + ECORE_EVENT_WINDOW_EXPOSE, + ECORE_EVENT_WINDOW_VISIBILITY, + ECORE_EVENT_WINDOW_SHAPE, + ECORE_EVENT_WINDOW_FOCUS_IN, + ECORE_EVENT_WINDOW_FOCUS_OUT, + ECORE_EVENT_MESSAGE, + ECORE_EVENT_WINDOW_DELETE, + ECORE_EVENT_COLORMAP, + + ECORE_EVENT_DND_DROP_REQUEST, + ECORE_EVENT_DND_DROP_END, + ECORE_EVENT_DND_DROP_POSITION, + ECORE_EVENT_DND_DROP, + ECORE_EVENT_DND_DROP_STATUS, + ECORE_EVENT_DND_DATA_REQUEST, + ECORE_EVENT_PASTE_REQUEST, + ECORE_EVENT_CLEAR_SELECTION, + + ECORE_EVENT_CHILD, + ECORE_EVENT_USER, + + ECORE_EVENT_MAX + } Ecore_Event_Type; + + typedef struct _ecore_event + { + Ecore_Event_Type type; + char ignore; + void *event; + void (*ev_free) (void *evnt); + struct _ecore_event *next; + } Ecore_Event; + + typedef struct _ecore_event_fd_handler + { + int fd; + void (*func) (int fd); + struct _ecore_event_fd_handler *next; + } Ecore_Event_Fd_Handler; + + typedef struct _ecore_event_pid_handler + { + pid_t pid; + void (*func) (pid_t pid); + struct _ecore_event_pid_handler *next; + } Ecore_Event_Pid_Handler; + + typedef struct _ecore_event_ipc_handler + { + int ipc; + void (*func) (int ipc); + struct _ecore_event_ipc_handler *next; + } Ecore_Event_Ipc_Handler; + + typedef struct _ecore_event_timer + { + char *name; + void (*func) (int val, void *data); + int val; + void *data; + double in; + char just_added; + struct _ecore_event_timer *next; + } Ecore_Event_Timer; + + typedef struct _ecore_event_key_down + { + Window win, root; + Ecore_Event_Key_Modifiers mods; + char *key; + char *compose; + Time time; + } Ecore_Event_Key_Down; + + typedef struct _ecore_event_key_up + { + Window win, root; + Ecore_Event_Key_Modifiers mods; + char *key; + char *compose; + Time time; + } Ecore_Event_Key_Up; + + typedef struct _ecore_event_mouse_down + { + Window win, root; + Ecore_Event_Key_Modifiers mods; + int button; + int x, y; + int rx, ry; + int double_click, triple_click; + Time time; + } Ecore_Event_Mouse_Down; + + typedef struct _ecore_event_mouse_up + { + Window win, root; + Ecore_Event_Key_Modifiers mods; + int button; + int x, y; + int rx, ry; + Time time; + } Ecore_Event_Mouse_Up; + + typedef struct _ecore_event_wheel + { + Window win, root; + Ecore_Event_Key_Modifiers mods; + int x, y, z; + int rx, ry; + Time time; + } Ecore_Event_Wheel; + + typedef struct _ecore_event_mouse_move + { + Window win, root; + Ecore_Event_Key_Modifiers mods; + int x, y; + int rx, ry; + Time time; + } Ecore_Event_Mouse_Move; + + typedef struct _ecore_event_window_enter + { + Window win, root; + int x, y; + int rx, ry; + Ecore_Event_Key_Modifiers mods; + Time time; + } Ecore_Event_Window_Enter; + + typedef struct _ecore_event_window_leave + { + Window win, root; + int x, y; + int rx, ry; + Ecore_Event_Key_Modifiers mods; + Time time; + } Ecore_Event_Window_Leave; + + typedef struct _ecore_event_window_focus_in + { + Window win, root; + int key_grab; + Time time; + } Ecore_Event_Window_Focus_In; + + typedef struct _ecore_event_window_focus_out + { + Window win, root; + int key_grab; + Time time; + } Ecore_Event_Window_Focus_Out; + + typedef struct _ecore_event_window_expose + { + Window win, root; + int x, y, w, h; + } Ecore_Event_Window_Expose; + + typedef struct _ecore_event_window_visibility + { + Window win, root; + int fully_obscured; + } Ecore_Event_Window_Visibility; + + typedef struct _ecore_event_window_create + { + Window win, root; + int override; + } Ecore_Event_Window_Create; + + typedef struct _ecore_event_window_destroy + { + Window win, root; + } Ecore_Event_Window_Destroy; + + typedef struct _ecore_event_window_map + { + Window win, root; + } Ecore_Event_Window_Map; + + typedef struct _ecore_event_window_unmap + { + Window win, root; + } Ecore_Event_Window_Unmap; + + typedef struct _ecore_event_window_map_request + { + Window win, root; + } Ecore_Event_Window_Map_Request; + + typedef struct _ecore_event_window_reparent + { + Window win, root; + Window parent_from, parent; + } Ecore_Event_Window_Reparent; + + typedef struct _ecore_event_window_configure + { + Window win, root; + int x, y, w, h; + int wm_generated; + } Ecore_Event_Window_Configure; + + typedef struct _ecore_event_window_configure_request + { + Window win, root; + int x, y, w, h; + int border; + Window stack_win; + Ecore_Event_Stack_Detail detail; + Ecore_Event_Value_Mask mask; + } Ecore_Event_Window_Configure_Request; + + typedef struct _ecore_event_window_circulate + { + Window win, root; + int lower; + } Ecore_Event_Window_Circulate; + + typedef struct _ecore_event_window_circulate_request + { + Window win, root; + int lower; + } Ecore_Event_Window_Circulate_Request; + + typedef struct _ecore_event_window_property + { + Window win, root; + Atom atom; + Time time; + } Ecore_Event_Window_Property; + + typedef struct _ecore_event_window_shape + { + Window win, root; + Time time; + } Ecore_Event_Window_Shape; + + typedef struct _ecore_event_message + { + Window win; + int format; + Atom atom; + union + { + char b[20]; + short s[10]; + long l[5]; + } + data; + } Ecore_Event_Message; + + typedef struct _ecore_event_colormap + { + Window win, root; + Colormap cmap; + int installed; + } Ecore_Event_Colormap; + + typedef struct _ecore_event_window_delete + { + Window win, root; + } Ecore_Event_Window_Delete; + + typedef struct _ecore_event_paste_request + { + Window win, root, source_win; + char *string; + } Ecore_Event_Paste_Request; + + typedef struct _ecore_event_clear_selection + { + Window win, root; + Atom selection; + } Ecore_Event_Clear_Selection; + + typedef struct _ecore_event_dnd_drop_request + { + Window win, root, source_win; + int num_files; + char **files; + int copy, link, move; + } Ecore_Event_Dnd_Drop_Request; + + typedef struct _ecore_event_dnd_drop_end + { + Window win, root, source_win; + } Ecore_Event_Dnd_Drop_End; + + typedef struct _ecore_event_dnd_drop_position + { + Window win, root, source_win; + int x, y; + } Ecore_Event_Dnd_Drop_Position; + + typedef struct _ecore_event_dnd_drop + { + Window win, root, source_win; + } Ecore_Event_Dnd_Drop; + + typedef struct _ecore_event_dnd_drop_status + { + Window win, root, source_win; + int x, y, w, h; + int copy, link, move, e_private; + int all_position_msgs; + int ok; + } Ecore_Event_Dnd_Drop_Status; + + typedef struct _ecore_event_dnd_data_request + { + Window win, root, source_win; + Atom destination_atom; + int plain_text; + int uri_list; + int moz_url; + int netscape_url; + } Ecore_Event_Dnd_Data_Request; + + typedef struct _ecore_event_child + { + pid_t pid; + int exit_code; + } Ecore_Event_Child; + + typedef struct _ecore_event_user + { + int num; + int hup; + } Ecore_Event_User; + + typedef struct _ecore_event_ipc_service + { + int service; + void (*func) (int fd); + struct _ecore_event_ipc_service *next; + } Ecore_Event_Ipc_Service; + + + typedef struct _ecore_xid + { + Window win; + Window parent; + Window root; + int children_num; + Window *children; + int x, y, w, h; + int mapped; + int mouse_in; + int depth; + int gravity; + int coords_invalid; + int bw; + int (*grab_button_auto_replay) (Ecore_Event_Mouse_Down *ev); + } Ecore_XID; + + + /* ---------------- API CALLS BELOW --------------------*/ + + /* ---------------- X WRAPPER CALLS */ + + int ecore_x_get_fd(void); + void ecore_set_error_handler(Ecore_Error_Function func); + void ecore_reset_error_handler(void); + + /** + * ecore_display_init - Establishes a connection to the X server + * @display: The name of the display to connect to + * + * This function creates a connection to the X server. If + * @display is NULL, the name is taken from the $DISPLAY + * environment variable. + */ + int ecore_display_init(char *display); + + int ecore_events_pending(void); + void ecore_get_next_event(XEvent * event); + int ecore_event_shape_get_id(void); + void ecore_sync(void); + void ecore_flush(void); + + /* ---------------- WINDOW CHILD HANDLING */ + + void ecore_del_child(Window win, Window child); + void ecore_add_child(Window win, Window child); + void ecore_raise_child(Window win, Window child); + void ecore_lower_child(Window win, Window child); + Ecore_XID *ecore_add_xid(Window win, int x, int y, int w, int h, + int depth, Window parent); + Ecore_XID *ecore_validate_xid(Window win); + void ecore_unvalidate_xid(Window win); + + /* ---------------- WINDOWS-RELATED CALLS */ + + Window ecore_window_new(Window parent, int x, int y, int w, + int h); + Window ecore_window_override_new(Window parent, int x, int y, + int w, int h); + Window ecore_window_input_new(Window parent, int x, int y, int w, + int h); + void ecore_window_set_events_propagate(Window win, + int propagate); + void ecore_window_show(Window win); + void ecore_window_hide(Window win); + void ecore_window_set_background_pixmap(Window win, + Pixmap pmap); + void ecore_window_set_shape_mask(Window win, Pixmap mask); + void ecore_window_add_shape_mask(Window win, Pixmap mask); + void ecore_window_set_shape_window(Window win, Window src, + int x, int y); + void ecore_window_add_shape_window(Window win, Window src, + int x, int y); + void ecore_window_set_shape_rectangle(Window win, int x, int y, + int w, int h); + void ecore_window_add_shape_rectangle(Window win, int x, int y, + int w, int h); + void ecore_window_set_shape_rectangles(Window win, + XRectangle * rect, + int num); + void ecore_window_add_shape_rectangles(Window win, + XRectangle * rect, + int num); + void ecore_window_clip_shape_by_rectangle(Window win, int x, + int y, int w, int h); + XRectangle *ecore_window_get_shape_rectangles(Window win, int *num); + void ecore_window_select_shape_events(Window win); + void ecore_window_unselect_shape_events(Window win); + void ecore_window_clear(Window win); + void ecore_window_clear_area(Window win, int x, int y, int w, + int h); + void ecore_window_set_events(Window win, long mask); + void ecore_window_remove_events(Window win, long mask); + void ecore_window_add_events(Window win, long mask); + void ecore_window_move(Window win, int x, int y); + void ecore_window_resize(Window win, int w, int h); + void ecore_window_move_resize(Window win, int x, int y, int w, + int h); + void ecore_window_destroy(Window win); + void ecore_window_reparent(Window win, Window parent, int x, + int y); + void ecore_window_raise(Window win); + void ecore_window_lower(Window win); + void ecore_window_get_geometry(Window win, int *x, int *y, + int *w, int *h); + int ecore_window_get_depth(Window win); + int ecore_window_exists(Window win); + Window ecore_window_get_parent(Window win); + Window *ecore_window_get_children(Window win, int *num); + int ecore_window_mouse_in(Window win); + void ecore_window_mouse_set_in(Window win, int in); + Window ecore_window_get_root(Window win); + void ecore_window_set_delete_inform(Window win); + void ecore_window_property_set(Window win, Atom type, + Atom format, int size, + void *data, int number); + void *ecore_window_property_get(Window win, Atom type, + Atom format, int *size); + void ecore_window_dnd_advertise(Window win); + void ecore_window_ignore(Window win); + void ecore_window_no_ignore(Window win); + int ecore_window_is_ignored(Window win); + Window ecore_window_get_at_xy(int x, int y); + + int ecore_window_dnd_capable(Window win); + void ecore_window_dnd_handle_motion(Window source_win, int x, + int y, int dragging); + void ecore_window_dnd_ok(int ok); + void ecore_window_dnd_finished(void); + void ecore_window_dnd_send_status_ok(Window source_win, + Window win, int x, int y, + int w, int h); + void ecore_window_dnd_send_finished(Window source_win, + Window win); + void ecore_window_set_title(Window win, char *title); + void ecore_window_set_name_class(Window win, char *name, + char *); + void ecore_window_get_name_class(Window win, char **name, + char **name_class); + char *ecore_window_get_machine(Window win); + char *ecore_window_get_command(Window win); + char *ecore_window_get_icon_name(Window win); + void ecore_window_get_hints(Window win, int *accepts_focus, + int *initial_state, + Pixmap * icon_pixmap, + Pixmap * icon_mask, + Window * icon_window, + Window * window_group); + void ecore_window_set_min_size(Window win, int w, int h); + void ecore_window_set_max_size(Window win, int w, int h); + void ecore_window_set_xy_hints(Window win, int x, int y); + void ecore_window_get_frame_size(Window win, int *l, int *r, + int *t, int *b); + int ecore_window_save_under(Window win); + void ecore_window_hint_set_layer(Window win, int layer); + void ecore_window_hint_set_sticky(Window win, int sticky); + void ecore_window_hint_set_borderless(Window win); + int ecore_window_get_gravity(Window win); + void ecore_window_gravity_reset(Window win); + void ecore_window_gravity_set(Window win, int gravity); + void ecore_window_bit_gravity_set(Window win, int gravity); + void ecore_window_get_root_relative_location(Window win, + int *x, int *y); + void ecore_window_send_event_move_resize(Window win, int x, + int y, int w, int h); + void ecore_window_send_client_message(Window win, Atom type, + int format, void *data); + void ecore_window_add_to_save_set(Window win); + void ecore_window_del_from_save_set(Window win); + void ecore_window_kill_client(Window win); + void ecore_window_set_border_width(Window win, int bw); + int ecore_window_get_border_width(Window win); + int ecore_window_get_wm_size_hints(Window win, + XSizeHints * hints, + int *mask); + int ecore_window_is_visible(Window win); + int ecore_window_is_normal(Window win); + + /** + * ecore_window_is_manageable - Returns 1 if a window can be managed by the wm. + * @win: the window for which to query. + * + * This function returns 0 if the window is unmapped, should be ignored + * by the window manager or is of the InputOnly class, 1 otherwise. + */ + int ecore_window_is_manageable(Window win); + + void ecore_windows_restack(Window * wins, int num); + void ecore_window_stack_above(Window win, Window above); + void ecore_window_stack_below(Window win, Window below); + char *ecore_window_get_title(Window win); + void ecore_window_button_grab_auto_replay_set(Window win, + int (*func) (Ecore_Event_Mouse_Down *ev)); + void *ecore_window_button_grab_auto_replay_get(Window win); + Window ecore_window_root(void); + void ecore_window_get_virtual_area(Window win, int *area_x, + int *area_y); + + /* ---------------- PIXMAP CALLS */ + + Pixmap ecore_pixmap_new(Window win, int w, int h, int dep); + void ecore_pixmap_free(Pixmap pmap); + + /* ---------------- POINTER CALLS */ + + void ecore_pointer_xy(Window win, int *x, int *y); + void ecore_pointer_xy_set(int x, int y); + void ecore_pointer_xy_get(int *x, int *y); + void ecore_pointer_warp_by(int dx, int dy); + void ecore_pointer_warp_to(int x, int y); + void ecore_pointer_replay(Time t); + void ecore_pointer_grab(Window win, Time t); + void ecore_pointer_ungrab(Time t); + + /* ---------------- KEYBOARD-RELATED CALLS */ + + KeySym ecore_key_get_keysym_from_keycode(KeyCode keycode); + char *ecore_key_get_string_from_keycode(KeyCode keycode); + void ecore_key_grab(char *key, Ecore_Event_Key_Modifiers mods, + int anymod, int sync); + void ecore_key_ungrab(char *key, + Ecore_Event_Key_Modifiers mods, + int anymod); + KeyCode ecore_key_get_keycode(char *key); + char *ecore_keypress_translate_into_typeable(Ecore_Event_Key_Down * e); + + void ecore_event_allow(int mode, Time t); + + /* ---------------- LOCKS AND MODIFIER CALLS */ + + int ecore_lock_mask_scroll_get(void); + int ecore_lock_mask_num_get(void); + int ecore_lock_mask_caps_get(void); + void ecore_lock_scroll_set(int onoff); + int ecore_lock_scroll_get(void); + void ecore_lock_num_set(int onoff); + int ecore_lock_num_get(void); + void ecore_lock_caps_set(int onoff); + int ecore_lock_caps_get(void); + + int ecore_mod_mask_shift_get(void); + int ecore_mod_mask_ctrl_get(void); + int ecore_mod_mask_alt_get(void); + int ecore_mod_mask_win_get(void); + void ecore_mod_shift_set(int onoff); + int ecore_mod_shift_get(void); + void ecore_mod_ctrl_set(int onoff); + int ecore_mod_ctrl_get(void); + void ecore_mod_alt_set(int onoff); + int ecore_mod_alt_get(void); + void ecore_mod_win_set(int onoff); + int ecore_mod_win_get(void); + + int ecore_lock_mask_get(void); + int ecore_modifier_mask_get(void); + Window ecore_get_key_grab_win(void); + Display *ecore_display_get(void); + void ecore_focus_window_set(Window win); + Window ecore_focus_window_get(void); + void ecore_focus_to_window(Window win); + void ecore_focus_mode_reset(void); + Atom ecore_atom_get(char *name); + + + /* ---------------- GRABBING/UNGRABBING CALLS */ + + /** + * ecore_grab - Grabs the X server connection + * + * This function wraps XGrabServer, which prevents all other + * clients from receiving events. Calls are reference-counted. + */ + void ecore_grab(void); + + /** + * ecore_ungrab - Ungrabs the X server connection + * + * This function releases the server, provided that ecore_grab() + * has been called the same number of times as ecore_ungrab(). + */ + void ecore_ungrab(void); + + void ecore_grab_mouse(Window win, int confine, Cursor cursor); + void ecore_ungrab_mouse(void); + Window ecore_grab_window_get(void); + + void ecore_button_grab(Window win, int button, int events, + Ecore_Event_Key_Modifiers mod, + int any_mod); + void ecore_button_ungrab(Window win, int button, + Ecore_Event_Key_Modifiers mod, + int any_mod); + void ecore_keyboard_grab(Window win); + void ecore_keyboard_ungrab(void); + Window ecore_keyboard_grab_window_get(void); + + + /* ----------------- GRAPHICS CONTEXT AND DRAWING CALLS */ + + GC ecore_gc_new(Drawable d); + void ecore_gc_free(GC gc); + void ecore_gc_set_fg(GC gc, int val); + void ecore_gc_set_include_inferiors(GC gc); + void ecore_fill_rectangle(Drawable d, GC gc, int x, int y, + int w, int h); + void ecore_draw_rectangle(Drawable d, GC gc, int x, int y, + int w, int h); + void ecore_draw_line(Drawable d, GC gc, int x1, int y1, int x2, + int y2); + void ecore_draw_point(Drawable d, GC gc, int x, int y); + void ecore_area_copy(Drawable src, Drawable dest, GC gc, + int sx, int sy, int sw, int sh, int dx, + int dy); + + + /* ---------------- DRAG AND DROP CALLS */ + + + int ecore_dnd_selection_convert(Window win, Window req, + Atom type); + void *ecore_dnd_selection_get(Window win, Window req, Atom type, + int *size); + void ecore_dnd_set_data(Window win); + void ecore_dnd_set_action(Window win); + + void ecore_dnd_send_data(Window win, Window source_win, + void *data, int size, Atom dest_atom, + int type); + void ecore_dnd_set_mode_copy(void); + void ecore_dnd_set_mode_link(void); + void ecore_dnd_set_mode_move(void); + void ecore_dnd_set_mode_ask(void); + void ecore_dnd_own_selection(Window win); + void ecore_dnd_send_drop(Window win, Window source_win); + void ecore_get_virtual_area(int *area_x, int *area_y); + void ecore_clear_target_status(void); + + + /* ---------------- IPC CALLS */ + + void ecore_event_ipc_init(char *path); + void ecore_event_ipc_cleanup(void); + void ecore_add_ipc_service(int service, void (*func) (int fd)); + void ecore_del_ipc_service(int service); + + /* ---------------- SELECTION CALLS */ + + char *ecore_selection_get_data(Window win, Atom prop); + Window ecore_selection_request(void); + Window ecore_selection_set(char *string); + + /* ---------------- CURSOR LOOK CALLS */ + + void ecore_set_blank_pointer(Window w); + Cursor ecore_cursor_new(Pixmap pmap, Pixmap mask, int x, int y, + int fr, int fg, int fb, int br, int bg, + int bb); + void ecore_cursor_free(Cursor c); + void ecore_cursor_set(Window win, Cursor c); + + /* ---------------- EVENT-HANDLING CALLS */ + + void ecore_add_event(Ecore_Event_Type type, void *event, + void (*ev_free) (void *event)); + void ecore_del_event(void *event); + void ecore_del_all_events(void); + Ecore_Event *ecore_get_last_event(void); + void ecore_add_event_fd(int fd, void (*func) (int fd)); + void ecore_del_event_fd(int fd); + void ecore_add_event_pid(pid_t pid, void (*func) (pid_t pid)); + void ecore_del_event_pid(pid_t pid); + void ecore_add_event_ipc(int ipc, void (*func) (int ipc)); + void ecore_del_event_ipc(int ipc); + void ecore_event_loop(void); + void ecore_event_loop_quit(void); + void ecore_add_event_timer(char *name, double in, + void (*func) (int val, void *data), + int val, void *data); + void *ecore_del_event_timer(char *name); + void ecore_event_filter(Ecore_Event * ev); + void ecore_event_filter_events_handle(Ecore_Event * ev); + void ecore_event_filter_idle_handle(void); + + /** + * ecore_event_filter_init - Setup event handlers + * + * This function initializes all ECORE_EVENT_MAX + * event handler to be empty. + */ + void ecore_event_filter_init(void); + + void ecore_event_filter_handler_add(Ecore_Event_Type type, + void (*func) (Ecore_Event *ev)); + void ecore_event_filter_idle_handler_add(void (*func) (void *data), void *data); + + /** + * ecore_event_signal_init - Setup for default signal handlers + * + * This function initializes signal handlers for various + * signals via sigaction(). + */ + void ecore_event_signal_init(void); + + int ecore_event_signal_events_pending(void); + + /** + * ecore_event_x_init - Ecore X initialization + * + * This function initializes Ecore's X event handling + * callbacks. + */ + void ecore_event_x_init(void); + + /* ---------------- MISCELLANEOUS CALLS */ + + double ecore_get_time(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/Makefile.am b/ecore/src/Makefile.am new file mode 100644 index 0000000..f8d2f8c --- /dev/null +++ b/ecore/src/Makefile.am @@ -0,0 +1,12 @@ +MAINTAINERCLEANFILES = Makefile.in + +SUBDIRS = lib bin + +EXTRA_DIST = \ + e_ev_filter.c \ + e_ev_signal.c \ + e_ev_x.c \ + e_events.c \ + e_ipc.c \ + e_util.c \ + e_x.c diff --git a/ecore/src/bin/.cvsignore b/ecore/src/bin/.cvsignore new file mode 100644 index 0000000..67aa34d --- /dev/null +++ b/ecore/src/bin/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +ecore_evas_test +ecore_test diff --git a/ecore/src/bin/CVS/Entries b/ecore/src/bin/CVS/Entries new file mode 100644 index 0000000..c8c44fb --- /dev/null +++ b/ecore/src/bin/CVS/Entries @@ -0,0 +1,10 @@ +/.cvsignore/1.1/Thu Nov 13 12:30:47 2003//THEAD +/Makefile.am/1.16/Thu Jun 23 03:33:43 2005//THEAD +/ecore_config.c/1.1/Thu Jun 23 03:33:43 2005//THEAD +/ecore_evas_test.c/1.2/Tue Sep 23 08:09:28 2003//THEAD +/ecore_evas_test.h/1.3/Wed Feb 23 20:55:18 2005//THEAD +/ecore_evas_test_app.c/1.7/Sun May 22 03:01:59 2005//THEAD +/ecore_evas_test_bg.c/1.5/Thu Jul 7 03:31:34 2005//THEAD +/ecore_evas_test_calibrate.c/1.5/Sat Jan 8 18:40:31 2005//THEAD +/ecore_test.c/1.18/Mon Jun 20 09:18:01 2005//THEAD +D diff --git a/ecore/src/bin/CVS/Repository b/ecore/src/bin/CVS/Repository new file mode 100644 index 0000000..5c94258 --- /dev/null +++ b/ecore/src/bin/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/bin diff --git a/ecore/src/bin/CVS/Root b/ecore/src/bin/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/bin/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/bin/CVS/Tag b/ecore/src/bin/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/bin/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/bin/Makefile.am b/ecore/src/bin/Makefile.am new file mode 100644 index 0000000..67e6a17 --- /dev/null +++ b/ecore/src/bin/Makefile.am @@ -0,0 +1,148 @@ +MAINTAINERCLEANFILES = Makefile.in + +if BUILD_ECORE_EVAS +ECORE_EVAS_LIB = $(top_builddir)/src/lib/ecore_evas/libecore_evas.la +else +ECORE_EVAS_LIB = +endif + +if BUILD_ECORE_X +ECORE_X_LIB = $(top_builddir)/src/lib/ecore_x/libecore_x.la +else +ECORE_X_LIB = +endif + +if BUILD_ECORE_FB +ECORE_FB_LIB = $(top_builddir)/src/lib/ecore_fb/libecore_fb.la +else +ECORE_FB_LIB = +endif + +if BUILD_ECORE_JOB +ECORE_JOB_LIB = $(top_builddir)/src/lib/ecore_job/libecore_job.la +else +ECORE_JOB_LIB = +endif + +if BUILD_ECORE_CON +ECORE_CON_LIB = $(top_builddir)/src/lib/ecore_con/libecore_con.la +else +ECORE_CON_LIB = +endif + +if BUILD_ECORE_IPC +ECORE_IPC_LIB = $(top_builddir)/src/lib/ecore_ipc/libecore_ipc.la +else +ECORE_IPC_LIB = +endif + +if BUILD_ECORE_TXT +ECORE_TXT_LIB = $(top_builddir)/src/lib/ecore_txt/libecore_txt.la +else +ECORE_TXT_LIB = +endif + +if BUILD_ECORE_CONFIG +ECORE_CONFIG_LIB = $(top_builddir)/src/lib/ecore_config/libecore_config.la +else +ECORE_CONFIG_LIB = +endif + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_evas \ +-I$(top_srcdir)/src/lib/ecore_x \ +-I$(top_srcdir)/src/lib/ecore_fb \ +-I$(top_srcdir)/src/lib/ecore_job \ +-I$(top_srcdir)/src/lib/ecore_con \ +-I$(top_srcdir)/src/lib/ecore_ipc \ +-I$(top_srcdir)/src/lib/ecore_txt @iconv_cflags@ \ +-I$(top_srcdir)/src/lib/ecore_config \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_evas \ +-I$(top_builddir)/src/lib/ecore_x \ +-I$(top_builddir)/src/lib/ecore_fb \ +-I$(top_builddir)/src/lib/ecore_job \ +-I$(top_builddir)/src/lib/ecore_con \ +-I$(top_builddir)/src/lib/ecore_ipc \ +-I$(top_builddir)/src/lib/ecore_txt @iconv_cflags@ \ +-I$(top_builddir)/src/lib/ecore_config \ +@evas_cflags@ \ +@x_cflags@ \ +@eet_cflags@ + +bin_PROGRAMS = \ +ecore_test \ +ecore_evas_test \ +ecore_config + +ecore_test_SOURCES = \ +ecore_test.c + +ecore_test_LDADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(ECORE_X_LIB) \ +$(ECORE_TXT_LIB) \ +$(ECORE_JOB_LIB) \ +$(ECORE_FB_LIB) \ +$(ECORE_EVAS_LIB) \ +$(ECORE_CON_LIB) \ +$(ECORE_IPC_LIB) \ +-lm @iconv_libs@ + +ecore_test_CFLAGS = \ +$(CFLAGS) \ +$(INCLUDES) + +ecore_test_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(ECORE_X_LIB) \ +$(ECORE_TXT_LIB) \ +$(ECORE_JOB_LIB) \ +$(ECORE_FB_LIB) \ +$(ECORE_EVAS_LIB) \ +$(ECORE_CON_LIB) \ +$(ECORE_IPC_LIB) + +ecore_evas_test_SOURCES = \ +ecore_evas_test.c \ +ecore_evas_test_app.c \ +ecore_evas_test_bg.c \ +ecore_evas_test_calibrate.c \ +ecore_evas_test.h + +ecore_evas_test_LDADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(ECORE_X_LIB) \ +$(ECORE_TXT_LIB) \ +$(ECORE_JOB_LIB) \ +$(ECORE_FB_LIB) \ +$(ECORE_EVAS_LIB) \ +$(ECORE_CON_LIB) \ +$(ECORE_IPC_LIB) \ +-lm @iconv_libs@ + +ecore_evas_test_CFLAGS = \ +$(CFLAGS) \ +$(INCLUDES) + +ecore_evas_test_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(ECORE_JOB_LIB) \ +$(ECORE_FB_LIB) \ +$(ECORE_X_LIB) \ +$(ECORE_EVAS_LIB) \ +$(ECORE_CON_LIB) \ +$(ECORE_IPC_LIB) \ +$(ECORE_TXT_LIB) + +ecore_config_SOURCES = \ +ecore_config.c + +ecore_config_LDADD = \ +$(ECORE_CONFIG_LIB) + +ecore_config_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(ECORE_CONFIG_LIB) + diff --git a/ecore/src/bin/ecore_config.c b/ecore/src/bin/ecore_config.c new file mode 100644 index 0000000..690d9fd --- /dev/null +++ b/ecore/src/bin/ecore_config.c @@ -0,0 +1,229 @@ +#include "config.h" +#include "Ecore.h" + +#ifdef BUILD_ECORE_CONFIG +#include "Ecore_Config.h" + +int +set(const char *key, int ec_type, const char *value) +{ + int i; + float f; + + switch (ec_type) { + case PT_INT: + case PT_BLN: + i = atoi(value); + if (ecore_config_typed_set(key, &i, ec_type) != ECORE_CONFIG_ERR_SUCC) return -1; + break; + case PT_FLT: + f = atof(value); + if (ecore_config_typed_set(key, &f, ec_type) != ECORE_CONFIG_ERR_SUCC) return -1; + break; + case PT_STR: + case PT_RGB: + case PT_THM: + case PT_NIL: + if (ecore_config_typed_set(key, value, ec_type) != ECORE_CONFIG_ERR_SUCC) return -1; + break; + } + return 0; +} + +int +get(const char *key) +{ + Ecore_Config_Prop *e; + + if (!(e = ecore_config_get(key))) { + fprintf(stderr, "No such property\n"); + return -1; + } + + switch (e->type) { + case PT_NIL: + printf("\n"); + break; + case PT_INT: + printf("%ld\n", ecore_config_int_get(key)); + break; + case PT_BLN: + printf("%d\n", ecore_config_boolean_get(key)); + break; + case PT_FLT: + printf("%lf\n", ecore_config_float_get(key)); + break; + case PT_STR: + printf("%s\n", ecore_config_string_get(key)); + break; + case PT_RGB: + printf("%s\n", ecore_config_argbstr_get(key)); + break; + case PT_THM: + printf("%s\n", ecore_config_theme_get(key)); + break; + default: + fprintf(stderr, "Property has unrecognised type"); + return -1; + } + return 0; +} + +int +list(const char *file) +{ + fprintf(stderr, "Command not yet supported\n"); + return -1; +} + +int +get_type(const char *key) +{ + Ecore_Config_Prop *e; + if (!(e = ecore_config_get(key))) { + fprintf(stderr, "No such property\n"); + return -1; + } + + switch (e->type) { + case PT_NIL: + printf("nil\n"); + break; + case PT_INT: + printf("int\n"); + break; + case PT_BLN: + printf("bool\n"); + break; + case PT_FLT: + printf("float\n"); + break; + case PT_STR: + printf("string\n"); + break; + case PT_RGB: + printf("rgb\n"); + break; + case PT_THM: + printf("theme\n"); + break; + default: + fprintf(stderr, "Property has unrecognised type"); + return -1; + } + return 0; +} + +int +parse_type(const char *type) +{ + if (!strcmp("nil", type)) { + return PT_NIL; + } else if (!strcmp("int", type)) { + return PT_INT; + } else if (!strcmp("float", type)) { + return PT_FLT; + } else if (!strcmp("bool", type)) { + return PT_BLN; + } else if (!strcmp("str", type)) { + return PT_STR; + } else if (!strcmp("rgb", type)) { + return PT_RGB; + } else if (!strcmp("theme", type)) { + return PT_THM; + } + return -1; +} + +void +usage_and_exit(const char *prog, int ret, const char *msg) +{ + if (msg) fprintf(stderr, msg); + fprintf(stderr, "Usage: %s <config-file> {get|set|type|list} [args...]\n", prog); + fprintf(stderr, "LIST: %s <config-file> list\n", prog); + fprintf(stderr, "GET: %s <config-file> get <key>\n", prog); + fprintf(stderr, "GET TYPE: %s <config-file> type <key>\n", prog); + fprintf(stderr, "SET: %s <config-file> set <key> {nil|int|float|bool|str|rgb|theme} <value>\n", prog); + exit(ret); +} + +int +main(int argc, const char **argv) +{ + const char *prog, *file, *cmd, *key, *type, *value; + int ec_type = -1; + int ret = 0; + prog = file = cmd = key = type = value = NULL; + + prog = argv[0]; + if (argc < 3) usage_and_exit(prog, 2, "Not enough arguments\n"); + + file = argv[1]; + cmd = argv[2]; + + // Check for valid command + if (strcmp("get", cmd) && + strcmp("type", cmd) && + strcmp("set", cmd) && + strcmp("list", cmd)) + { + usage_and_exit(prog, 2, "Unrecognised command\n"); + } + + // Check for enough arguments + if ((*cmd == 's') || (*cmd == 'g') || (*cmd == 't')) { + if (argc < 3) usage_and_exit(prog, 2, "Not enough arguments\n"); + key = argv[3]; + } + + if (*cmd == 's') { + if (argc < 5) usage_and_exit(prog, 2, "No type and value specified\n"); + type = argv[4]; + + if ((ec_type = parse_type(type)) < 0) + usage_and_exit(prog, 3, "Unsupported type\n"); + + if (strcmp(type, "nil")) { + if (argc < 6) + usage_and_exit(prog, 2, "No value specified\n"); + value = argv[5]; + } + } + + // Load configuration from file + ecore_config_init("econfig"); + ecore_config_file_load(file); + + // Execute command + switch (*cmd) { + case 's': + if (set(key, ec_type, value)) { + fprintf(stderr, "Set failed\n"); + ret = 4; + } else { + ecore_config_file_save(file); + } + break; + case 'g': + if (get(key)) ret = 4; + break; + case 't': + if (get_type(key)) ret = 4; + break; + case 'l': + if (list(file)) ret = 4; + break; + } + + ecore_config_shutdown(); + + return ret; +} +#else +int +main(int argc, const char **argv) +{ + printf("Ecore_config module not compiled. This program is empty.\n"); + return -1; +} +#endif diff --git a/ecore/src/bin/ecore_evas_test.c b/ecore/src/bin/ecore_evas_test.c new file mode 100644 index 0000000..91536e5 --- /dev/null +++ b/ecore/src/bin/ecore_evas_test.c @@ -0,0 +1,27 @@ +#include "ecore_evas_test.h" + +#ifdef BUILD_ECORE_EVAS + +int +main(int argc, const char **argv) +{ + if (app_start(argc, argv) < 1) return -1; + + bg_start(); + + calibrate_start(); + + ecore_main_loop_begin(); + + app_finish(); + + return 0; +} +#else +int +main(int argc, const char **argv) +{ + printf("Ecore_evas module not compiled. This program is empty.\n"); + return -1; +} +#endif diff --git a/ecore/src/bin/ecore_evas_test.h b/ecore/src/bin/ecore_evas_test.h new file mode 100644 index 0000000..f0b9962 --- /dev/null +++ b/ecore/src/bin/ecore_evas_test.h @@ -0,0 +1,36 @@ +#ifndef _ECORE_EVAS_TEST_H +#define _ECORE_EVAS_TEST_H + +#include "config.h" +#include "Ecore.h" +#include <math.h> + +#ifdef BUILD_ECORE_EVAS +#include "Ecore_Evas.h" +#include "Ecore_Fb.h" + +#define IM PACKAGE_DATA_DIR"/images/" +#define PT PACKAGE_DATA_DIR"/pointers/" +#define FN PACKAGE_DATA_DIR"/fonts/" + +extern double start_time; +extern Ecore_Evas *ee; +extern Evas *evas; + + + +void calibrate_pos_set(int pos); +int calibrate_pos_get(void); +void calibrate_finish(void); +void calibrate_start(void); + +void bg_resize(double w, double h); +void bg_start(void); +void bg_go(void); + +int app_start(int argc, const char **argv); +void app_finish(void); + +#endif + +#endif diff --git a/ecore/src/bin/ecore_evas_test_app.c b/ecore/src/bin/ecore_evas_test_app.c new file mode 100644 index 0000000..e1d58d2 --- /dev/null +++ b/ecore/src/bin/ecore_evas_test_app.c @@ -0,0 +1,174 @@ +#include "ecore_evas_test.h" + +#ifdef BUILD_ECORE_EVAS + +double start_time = 0.0; +Ecore_Evas *ee = NULL; +Evas *evas = NULL; + +Ecore_Idle_Enterer *getpix_handler = NULL; + +static void app_resize(Ecore_Evas *ee); +static int app_signal_exit(void *data, int ev_type, void *ev); +static void app_delete_request(Ecore_Evas *ee); + +static int +getpix_cb(void *data) +{ + const int *pix; + int p; + int w, h; + FILE *f; + int x, y; + static int count = 0; + char buf[256]; + unsigned char *line; + + pix = ecore_evas_buffer_pixels_get(ee); + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + snprintf(buf, sizeof(buf), "out%04i.ppm", count); + count++; + f = fopen(buf, "wb"); + if (f) + { + line = malloc(w * 4); + fprintf(f, "P6\n%i %i\n255\n", w, h); + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + p = pix[(y * w) + x]; + line[(x * 3) + 0] = ((p >> 16) & 0xff); + line[(x * 3) + 1] = ((p >> 8 ) & 0xff); + line[(x * 3) + 2] = ((p ) & 0xff); +/* line[(x * 3) + 3] = ((p >> 24) & 0xff);*/ + } + fwrite(line, w * 3, 1, f); + } + free(line); + fclose(f); + } + return 1; +} + +int +app_start(int argc, const char **argv) +{ + /* init the app */ + start_time = ecore_time_get(); + ecore_init(); + ecore_app_args_set(argc, argv); + ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, app_signal_exit, NULL); + + /* create an evas */ + if (!ecore_evas_init()) return -1; + if ((argc > 1) && (!strcmp(argv[1], "-fb"))) + { + ee = ecore_evas_fb_new(NULL, 0, 240, 320); + evas = ecore_evas_get(ee); + } + else if ((argc > 1) && (!strcmp(argv[1], "-x"))) + { + ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 240, 320); + evas = ecore_evas_get(ee); + } +#if HAVE_ECORE_EVAS_GL + else if ((argc > 1) && (!strcmp(argv[1], "-gl"))) + { + ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, 240, 320); + evas = ecore_evas_get(ee); + } +#endif + else if ((argc > 1) && (!strcmp(argv[1], "-buf"))) + { + ee = ecore_evas_buffer_new(240, 320); + evas = ecore_evas_get(ee); + getpix_handler = ecore_idle_enterer_add(getpix_cb, NULL); + } + else if ((argc > 1) && (!strcmp(argv[1], "-buf2"))) + { + Evas_Object *o; + + ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 240, 320); + + o = evas_object_rectangle_add(ecore_evas_get(ee)); + evas_object_move(o, 0, 0); + evas_object_resize(o, 240, 320); + evas_object_color_set(o, 150, 200, 250, 255); + evas_object_show(o); + + o = ecore_evas_object_image_new(ee); + evas = ecore_evas_get(evas_object_data_get(o, "Ecore_Evas")); + evas_object_move(o, 50, 50); + evas_object_resize(o, 120, 160); + evas_object_image_fill_set(o, 0, 0, 120, 160); + evas_object_image_size_set(o, 240, 320); + ecore_evas_resize(evas_object_data_get(o, "Ecore_Evas"), 240, 320); + evas_object_color_set(o, 255, 255, 255, 200); + evas_object_show(o); + } + else if ((argc > 1) && (!strcmp(argv[1], "-h"))) + { + printf("%s -x Test ecore_evas in X (default)\n" + "%s -gl Test ecore_evas in X GL\n" + "%s -fb Test ecore_evas in the Framebuffer\n" + "%s -buf Test ecore_evas in the Buffer\n" + "%s -buf2 Test ecore_evas in the Image Buffer\n" + "%s -h Display this help\n", + argv[0], argv[0], argv[0], argv[0], argv[0], argv[0]); + ecore_evas_shutdown(); + ecore_shutdown(); + return 0; + } + else { +#ifdef BUILD_ECORE_X + ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 240, 320); +#else +#ifdef BUILD_ECORE_FB + ee = ecore_evas_fb_new(NULL, 270, 240, 320); +#endif +#endif + evas = ecore_evas_get(ee); + } + if (!ee) return -1; + ecore_evas_callback_delete_request_set(ee, app_delete_request); + ecore_evas_callback_resize_set(ee, app_resize); + ecore_evas_title_set(ee, "Ecore Evas Test"); + ecore_evas_name_class_set(ee, "ecore_test", "test_evas"); + ecore_evas_show(ee); + evas_image_cache_set(evas, 8192 * 1024); + evas_font_cache_set(evas, 512 * 1024); + evas_font_path_append(evas, FN); + return 1; +} + +void +app_finish(void) +{ + ecore_evas_shutdown(); + ecore_shutdown(); +} + +static void +app_resize(Ecore_Evas *ee) +{ + Evas_Coord w, h; + + evas_output_viewport_get(evas, NULL, NULL, &w, &h); + bg_resize(w, h); +} + +static int +app_signal_exit(void *data, int ev_type, void *ev) +{ + ecore_main_loop_quit(); + return 1; +} + +static void +app_delete_request(Ecore_Evas *ee) +{ + ecore_main_loop_quit(); +} + +#endif diff --git a/ecore/src/bin/ecore_evas_test_bg.c b/ecore/src/bin/ecore_evas_test_bg.c new file mode 100644 index 0000000..397e5f5 --- /dev/null +++ b/ecore/src/bin/ecore_evas_test_bg.c @@ -0,0 +1,412 @@ +#include "ecore_evas_test.h" + +#ifdef BUILD_ECORE_EVAS + +Evas_Object *o_bg_rect = NULL; +Evas_Object *o_logo = NULL; +Ecore_Timer *anim_timer = NULL; + +#define NUM 32 +#define SIZE 32 +#define SLIDE 80 + +Evas_Object *o_ball[NUM]; +Evas_Object *o_shad[NUM]; + +Evas_Object *o_clip = NULL; +Evas_Object *o_bar[2]; +Evas_Object *o_bar_shad_1[3]; +Evas_Object *o_bar_shad_2[2]; +Evas_Object *o_bg = NULL; + +static int bg_animate_obj_timer(void *data); +static void bg_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info); + +void +bg_resize(double w, double h) +{ + evas_object_resize(o_bg_rect, w, h); + evas_object_move(o_logo, (w - 240) / 2, (h - 280) / 2); + bg_animate_obj_timer(NULL); +} + +void +bg_start(void) +{ + Evas_Object *o; + + /* set up a big white rectangle on the bg */ + o = evas_object_rectangle_add(evas); + evas_object_color_set(o, 255, 255, 255, 255); + evas_object_move(o, 0, 0); + evas_object_resize(o, 240, 320); + evas_object_layer_set(o, -1000000); + evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN, bg_cb_key_down, ee); + evas_object_focus_set(o, 1); + evas_object_show(o); + o_bg_rect = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"e_logo.png", NULL); + evas_object_resize(o, 240, 280); + evas_object_image_fill_set(o, 0, 0, 240, 280); + evas_object_move(o, (240 - 240) / 2, (320 - 280) / 2); + evas_object_layer_set(o, -999); + evas_object_pass_events_set(o, 1); + evas_object_show(o); + o_logo = o; + + o = evas_object_rectangle_add(evas); + evas_object_color_set(o, 255, 255, 255, 255); + evas_object_resize(o, 240, 0); + evas_object_pass_events_set(o, 1); + evas_object_show(o); + o_clip = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bg.png", NULL); + evas_object_resize(o, 240, 320); + evas_object_image_fill_set(o, 0, 0, 240, 320); + evas_object_layer_set(o, -9999); + evas_object_move(o, 0, 0); + evas_object_clip_set(o, o_clip); + evas_object_pass_events_set(o, 1); + evas_object_show(o); + o_bg = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar.png", NULL); + evas_object_image_border_set(o, 5, 5, 5, 5); + evas_object_resize(o, 240, 32); + evas_object_image_fill_set(o, 0, 0, 240, 32); + evas_object_layer_set(o, 100); + evas_object_pass_events_set(o, 1); + o_bar[0] = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar.png", NULL); + evas_object_image_border_set(o, 5, 5, 5, 5); + evas_object_resize(o, 240, 32); + evas_object_image_fill_set(o, 0, 0, 240, 32); + evas_object_layer_set(o, 100); + evas_object_pass_events_set(o, 1); + o_bar[1] = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar_shad_above.png", NULL); + evas_object_resize(o, 240, 8); + evas_object_image_fill_set(o, 0, 0, 240, 8); + evas_object_image_smooth_scale_set(o, 0); + evas_object_layer_set(o, 100); + evas_object_pass_events_set(o, 1); + o_bar_shad_1[0] = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar_shad_below.png", NULL); + evas_object_resize(o, 240, 32); + evas_object_image_fill_set(o, 0, 0, 240, 32); + evas_object_image_smooth_scale_set(o, 0); + evas_object_layer_set(o, -100); + evas_object_pass_events_set(o, 1); + evas_object_clip_set(o, o_clip); + o_bar_shad_1[1] = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar_shad_below.png", NULL); + evas_object_resize(o, 240, 16); + evas_object_image_fill_set(o, 0, 0, 240, 16); + evas_object_image_smooth_scale_set(o, 0); + evas_object_layer_set(o, 100); + evas_object_pass_events_set(o, 1); + evas_object_clip_set(o, o_clip); + o_bar_shad_1[2] = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar_shad_above.png", NULL); + evas_object_resize(o, 240, 8); + evas_object_image_fill_set(o, 0, 0, 240, 8); + evas_object_image_smooth_scale_set(o, 0); + evas_object_layer_set(o, 100); + evas_object_pass_events_set(o, 1); + evas_object_clip_set(o, o_clip); + o_bar_shad_2[0] = o; + + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"bar_shad_below.png", NULL); + evas_object_resize(o, 240, 8); + evas_object_image_fill_set(o, 0, 0, 240, 8); + evas_object_image_smooth_scale_set(o, 0); + evas_object_layer_set(o, 100); + evas_object_pass_events_set(o, 1); + o_bar_shad_2[1] = o; + + { + int i; + + for (i = 0; i < NUM; i++) + { + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"ball.png", NULL); + evas_object_resize(o, SIZE, SIZE); + evas_object_image_fill_set(o, 0, 0, SIZE, SIZE); + evas_object_move(o, 0, 0); + evas_object_pass_events_set(o, 1); + evas_object_clip_set(o, o_clip); + o_ball[i] = o; + o = evas_object_image_add(evas); + evas_object_image_file_set(o, IM"shadow.png", NULL); + evas_object_resize(o, SIZE, SIZE); + evas_object_image_fill_set(o, 0, 0, SIZE, SIZE); + evas_object_move(o, 0, 0); + evas_object_pass_events_set(o, 1); + evas_object_clip_set(o, o_clip); + evas_object_lower(o); + o_shad[i] = o; + } + } +} + +void +bg_go(void) +{ + /* add a timer to animate them */ + anim_timer = ecore_timer_add(0.01, bg_animate_obj_timer, NULL); +} + +static int +bg_animate_obj_timer(void *data) +{ + Evas_Object *o; + Evas_Coord x, y, sx, sy; + Evas_Coord w, h; + double v; + int ow, oh; + double t; + int l, m, n; + int i; + static double t_first = 0; + static int done = 0; + + t = ecore_time_get() - start_time; + if (t_first == 0) t_first = t; + if (t - t_first > 2.0) done = 1; + evas_output_viewport_get(evas_object_evas_get(o_clip), NULL, NULL, &w, &h); + if (!done) + { + v = ((cos(((t - t_first) / 2) * 3.14159) - 1.0) / -2); + l = (SLIDE) * v; + } + else + { + l = SLIDE; + } + evas_object_move(o_bar[0], 0, (h / 2) - 32 - l); + evas_object_move(o_bar[1], 0, (h / 2) + l); + evas_object_move(o_bar_shad_1[0], 0, (h / 2) - 32 - l - 8); + evas_object_move(o_bar_shad_1[1], 0, (h / 2) - l); + evas_object_move(o_bar_shad_1[2], 0, (h / 2) - l); + evas_object_move(o_bar_shad_2[0], 0, (h / 2) + l - 8); + evas_object_move(o_bar_shad_2[1], 0, (h / 2) + 32 + l); + + evas_object_resize(o_bar[0], w, 32); + evas_object_image_fill_set(o_bar[0], 0, 0, w, 32); + + evas_object_resize(o_bar[1], w, 32); + evas_object_image_fill_set(o_bar[1], 0, 0, w, 32); + + evas_object_resize(o_bar_shad_1[0], w, 8); + evas_object_image_fill_set(o_bar_shad_1[0], 0, 0, w, 8); + + evas_object_resize(o_bar_shad_1[1], w, 32); + evas_object_image_fill_set(o_bar_shad_1[1], 0, 0, w, 32); + + evas_object_resize(o_bar_shad_1[2], w, 16); + evas_object_image_fill_set(o_bar_shad_1[2], 0, 0, w, 16); + + evas_object_resize(o_bar_shad_2[0], w, 8); + evas_object_image_fill_set(o_bar_shad_2[0], 0, 0, w, 8); + + evas_object_resize(o_bar_shad_2[1], w, 8); + evas_object_image_fill_set(o_bar_shad_2[1], 0, 0, w, 8); + + evas_object_move(o_clip, 0, (h / 2) - l); + evas_object_resize(o_clip, w, l * 2); + + evas_object_resize(o_bg, w, h); + evas_object_image_fill_set(o_bg, 0, 0, w, h); + + evas_object_show(o_bar[0]); + evas_object_show(o_bar[1]); + evas_object_show(o_bar_shad_1[0]); + evas_object_show(o_bar_shad_1[1]); + evas_object_show(o_bar_shad_1[2]); + evas_object_show(o_bar_shad_2[0]); + evas_object_show(o_bar_shad_2[1]); + for (i = 0; i < NUM; i++) + { + o = o_ball[i]; + evas_output_viewport_get(evas_object_evas_get(o), NULL, NULL, &w, &h); + l = ((int)o / 179) & 0x0f; + v = (sin(t * (double)l / 12) + 1.0) / 2; + v = 0.25 + (0.75 * v); + m = 1 + (((int)o / 36) & 0x0f); + n = 1 + (((int)o / 763) & 0x0f); + ow = SIZE * v; + oh = SIZE * v; + evas_object_resize(o, ow, oh); + evas_object_image_fill_set(o, 0, 0, ow, oh); + x = sin(t * (double)m / 12) * ((w - ow) / 2); + y = sin(t * (double)n / 12) * ((h - oh) / 2); + evas_object_move(o, (w / 2) - (ow / 2) + x, (h / 2) - (oh / 2) + y); + evas_object_show(o); + o = o_shad[i]; + evas_object_resize(o, ow, oh); + evas_object_image_fill_set(o, 0, 0, ow, oh); + sx = v * (((w - ow) / 2) + x) / 8; + sy = v * (((h - oh) / 2) + y) / 8; + evas_object_move(o, + (w / 2) - (ow / 2) + x + sx, + (h / 2) - (oh / 2) + y + sy); + evas_object_show(o); + } + return 1; +} + +/* NB: on ipaq + * + * "F1" "F2" "F3" "F4" + * "Up" + * "Left" "Return" "Right" + * "Down" + * + */ +static void +bg_cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Key_Down *ev; + + ev = event_info; + if (!strcmp(ev->keyname, "Escape")) ecore_main_loop_quit(); + if (!strcmp(ev->keyname, "q")) ecore_main_loop_quit(); + if (!strcmp(ev->keyname, "Q")) ecore_main_loop_quit(); + if ((!strcmp(ev->keyname, "f")) || + (!strcmp(ev->keyname, "F1"))) + { + if (!ecore_evas_fullscreen_get(ee)) + ecore_evas_fullscreen_set(ee, 1); + else + ecore_evas_fullscreen_set(ee, 0); + } + if (!strcmp(ev->keyname, "o")) + { + if (!ecore_evas_override_get(ee)) + ecore_evas_override_set(ee, 1); + else + ecore_evas_override_set(ee, 0); + } + if ((!strcmp(ev->keyname, "r")) || + (!strcmp(ev->keyname, "F4"))) + { + int r; + + r = ecore_evas_rotation_get(ee); + if (r == 0) r = 90; + else if (r == 90) r = 270; + else if (r == 270) r = 0; + ecore_evas_rotation_set(ee, r); + } + if (!strcmp(ev->keyname, "b")) + { + if (!ecore_evas_borderless_get(ee)) + ecore_evas_borderless_set(ee, 1); + else + ecore_evas_borderless_set(ee, 0); + } + if (!strcmp(ev->keyname, "d")) + { + if (!ecore_evas_avoid_damage_get(ee)) + ecore_evas_avoid_damage_set(ee, 1); + else + ecore_evas_avoid_damage_set(ee, 0); + } + if (!strcmp(ev->keyname, "s")) + { + if (!ecore_evas_shaped_get(ee)) + { + evas_object_hide(o_bg_rect); +// evas_object_hide(o_bg); + ecore_evas_shaped_set(ee, 1); + } + else + { + evas_object_show(o_bg_rect); +// evas_object_show(o_bg); + ecore_evas_shaped_set(ee, 0); + } + } + if (!strcmp(ev->keyname, "Up")) + { +#ifdef BUILD_ECORE_FB + double br; + + br = ecore_fb_backlight_brightness_get(); + ecore_fb_backlight_brightness_set(br + 0.1); +#endif + } + if (!strcmp(ev->keyname, "Down")) + { +#ifdef BUILD_ECORE_FB + double br; + + br = ecore_fb_backlight_brightness_get(); + ecore_fb_backlight_brightness_set(br - 0.1); +#endif + } + if (!strcmp(ev->keyname, "F2")) + { +#ifdef BUILD_ECORE_FB + if (ecore_fb_backlight_get()) + ecore_fb_backlight_set(0); + else + ecore_fb_backlight_set(1); +#endif + } + if (!strcmp(ev->keyname, "F3")) + { +#ifdef BUILD_ECORE_FB + static int v = 0; + + if (v) ecore_fb_led_set(0); + else ecore_fb_led_set(1); + if (!v) v = 1; + else v = 0; +#endif + } + if (!strcmp(ev->keyname, "Left")) + { +#ifdef BUILD_ECORE_FB + ecore_fb_led_blink_set(0.1); +#endif + } + if (!strcmp(ev->keyname, "Right")) + { +#ifdef BUILD_ECORE_FB + ecore_fb_led_blink_set(0.5); +#endif + } + if ((!strcmp(ev->keyname, "p")) || + (!strcmp(ev->keyname, "Return"))) + { + char *fl; + + ecore_evas_cursor_get(ee, &fl, NULL, NULL, NULL); + if (!fl) + ecore_evas_cursor_set(ee, PT"mouse_pointer.png", 1000000, 2, 2); + else + ecore_evas_cursor_set(ee, NULL, 0, 0, 0); +#ifdef BUILD_ECORE_FB + printf("%3.3f\n", ecore_fb_light_sensor_get()); +#endif + } +} +#endif diff --git a/ecore/src/bin/ecore_evas_test_calibrate.c b/ecore/src/bin/ecore_evas_test_calibrate.c new file mode 100644 index 0000000..22b2424 --- /dev/null +++ b/ecore/src/bin/ecore_evas_test_calibrate.c @@ -0,0 +1,285 @@ +#include "ecore_evas_test.h" + +#ifdef BUILD_ECORE_EVAS + +static Evas_Object *o_events = NULL; +static Evas_Object *o_crosshair = NULL; +static Evas_Object *o_text = NULL; +static int cal_pos = 0; +static int down = 0; + +static int cal_coords[] = {15, 15, -15, 15, 15, -15, -15, -15}; +static char *cal_lines[] = +{ + "Please click on the crosshair", + "Again please", + "And again", + "Last one, then calibration is complete" +}; +static int cal_input[8]; + +static int tmp_input_count = 0; +static int tmp_input[16]; + +static void calibrate_cb_down(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void calibrate_cb_up(void *data, Evas *e, Evas_Object *obj, void *event_info); +static void calibrate_cb_move(void *data, Evas *e, Evas_Object *obj, void *event_info); + +void +calibrate_pos_set(int pos) +{ + Evas_Coord w, h, ow, oh; + int x, y; + + cal_pos = pos; + evas_object_geometry_get(o_crosshair, NULL, NULL, &w, &h); + x = cal_coords[(cal_pos * 2) + 0]; + y = cal_coords[(cal_pos * 2) + 1]; + evas_output_viewport_get(evas, NULL, NULL, &ow, &oh); + if (x < 0) x = ow + x - 1; + if (y < 0) y = oh + y - 1; + cal_coords[(cal_pos * 2) + 0] = x; + cal_coords[(cal_pos * 2) + 1] = y; + evas_object_move(o_crosshair, x - (((int)w - 1) / 2), y - (((int)h - 1) / 2)); + evas_object_text_text_set(o_text, cal_lines[cal_pos]); + evas_object_geometry_get(o_text, NULL, NULL, &w, &h); + evas_object_move(o_text, (ow - w) / 2, (oh - h) / 2); +} + +int +calibrate_pos_get(void) +{ + return cal_pos; +} + +void +calibrate_finish(void) +{ + int m0, m1; + int y0, y1; + int x[4], y[4], xi[4], yi[4]; + int i, rot; + + int xscale, xtrans, yscale, ytrans, xyswap; + + rot = ecore_evas_rotation_get(ee); + for (i = 0; i < 4; i++) + { + x[i] = cal_coords[(i * 2) + 0]; + y[i] = cal_coords[(i * 2) + 1]; + xi[i] = cal_input[(i * 2) + 0]; + yi[i] = cal_input[(i * 2) + 1]; + } + xyswap = 0; + + m0 = ((x[1] - x[0]) * 256) / (xi[1] - xi[0]); + y0 = ((x[1] - ((xi[1] * m0) / 256)) + (x[0] - ((xi[0] * m0) >> 8)) ) / 2; + + m1 = ((x[3] - x[2]) * 256) / (xi[3] - xi[2]); + y1 = ((x[3] - ((xi[3] * m1) / 256)) + (x[2] - ((xi[2] * m1) >> 8)) ) / 2; + + xscale = (m0 + m1) / 2; + xtrans = (y0 + y1) / 2; + + m0 = ((y[2] - y[0]) * 256) / (yi[2] - yi[0]); + y0 = ((y[2] - ((yi[2] * m0) / 256)) + (y[0] - ((yi[0] * m0) >> 8)) ) / 2; + + m1 = ((y[3] - y[1]) * 256) / (yi[3] - yi[1]); + y1 = ((y[3] - ((yi[3] * m1) / 256)) + (y[1] - ((yi[1] * m1) >> 8)) ) / 2; + + yscale = (m0 + m1) / 2; + ytrans = (y0 + y1) / 2; + + if (rot == 0) + { +#ifdef BUILD_ECORE_FB + ecore_fb_touch_screen_calibrate_set(xscale, xtrans, yscale, ytrans, xyswap); +#endif + } + else if (rot == 270) + { + int ow, oh; + + evas_output_size_get(evas, &ow, &oh); + ytrans = oh - (ytrans + ((oh * yscale) / 256)); +#ifdef BUILD_ECORE_FB + ecore_fb_touch_screen_calibrate_set(yscale, ytrans, xscale, xtrans, xyswap); +#endif + } + + evas_object_del(o_crosshair); + evas_object_del(o_events); + evas_object_del(o_text); + o_crosshair = NULL; + o_events = NULL; + o_text = NULL; + cal_pos = 0; + bg_go(); +} + +void +calibrate_start(void) +{ + Evas_Object *o; + +#ifdef BUILD_ECORE_FB + ecore_fb_touch_screen_calibrate_set(256, 0, 256, 0, 0); +#endif + + o = evas_object_rectangle_add(evas); + evas_object_layer_set(o, 1000000); + evas_object_color_set(o, 255, 255, 255, 120); + evas_object_move(o, -12000, -16000); + evas_object_resize(o, 24000, 32000); + evas_object_show(o); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, calibrate_cb_down, ee); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, calibrate_cb_up, ee); + evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, calibrate_cb_move, ee); + o_events = o; + + o = evas_object_image_add(evas); + evas_object_layer_set(o, 1000001); + evas_object_image_file_set(o, IM"crosshair.png", NULL); + evas_object_resize(o, 31, 31); + evas_object_image_fill_set(o, 0, 0, 31, 31); + evas_object_pass_events_set(o, 1); + evas_object_show(o); + o_crosshair = o; + + o = evas_object_text_add(evas); + evas_object_layer_set(o, 1000002); + evas_object_color_set(o, 0, 0, 0, 255); + evas_object_text_font_set(o, "Vera", 10); + evas_object_pass_events_set(o, 1); + evas_object_show(o); + o_text = o; + + calibrate_pos_set(0); +} + + +static void +calibrate_cb_down(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Mouse_Down *ev; + + ev = event_info; + + evas_object_move(o_crosshair, ev->output.x - 15, ev->output.y - 15); + tmp_input_count = 0; + tmp_input[((tmp_input_count & 0x7) * 2) + 0] = ev->output.x; + tmp_input[((tmp_input_count & 0x7) * 2) + 1] = ev->output.y; + tmp_input_count++; + down = 1; +} + +static void +calibrate_cb_up(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Mouse_Up *ev; + int n, i, avx, avy, c, mx, my; + int dists[8]; + int indexes[8]; + int sorted; + + ev = event_info; + down = 0; + tmp_input[((tmp_input_count & 0x7) * 2) + 0] = ev->output.x; + tmp_input[((tmp_input_count & 0x7) * 2) + 1] = ev->output.y; + tmp_input_count++; + n = 8; + if (tmp_input_count < 8) n = tmp_input_count; + avx = 0; avy = 0; c = 0; + for (i = 0; i < n; i++) + { + dists[i] = tmp_input[(i * 2) + 0]; + indexes[i] = i; + } + sorted = 0; + while (!sorted) + { + sorted = 1; + for (i = 0; i < n - 1; i++) + { + if (dists[i + 1] < dists[i]) + { + int tmp; + + sorted = 0; + tmp = dists[i]; + dists[i] = dists[i + 1]; + dists[i + 1] = tmp; + tmp = indexes[i]; + indexes[i] = indexes[i + 1]; + indexes[i + 1] = tmp; + } + } + } + mx = dists[(n + 1) / 2]; + for (i = 0; i < n; i++) + { + dists[i] = tmp_input[(i * 2) + 1]; + indexes[i] = i; + } + sorted = 0; + while (!sorted) + { + sorted = 1; + for (i = 0; i < n - 1; i++) + { + if (dists[i + 1] < dists[i]) + { + int tmp; + + sorted = 0; + tmp = dists[i]; + dists[i] = dists[i + 1]; + dists[i + 1] = tmp; + tmp = indexes[i]; + indexes[i] = indexes[i + 1]; + indexes[i + 1] = tmp; + } + } + } + my = dists[(n + 1) / 2]; + + for (i = 0; i < n; i++) + { + int x, y, dx, dy; + + x = tmp_input[(i * 2) + 0]; + y = tmp_input[(i * 2) + 1]; + dx = x - mx; + dy = y - my; + if (dx < 0) dx = -dx; + if (dy < 0) dy = -dy; + if ((dx <= 8) && (dy <= 8)) + { + avx += tmp_input[(i * 2) + 0]; + avy += tmp_input[(i * 2) + 1]; + c++; + } + } + cal_input[(cal_pos * 2) + 0] = avx / c; + cal_input[(cal_pos * 2) + 1] = avy / c; + n = calibrate_pos_get(); + if (n < 3) + { + calibrate_pos_set(n + 1); + return; + } + calibrate_finish(); +} + +static void +calibrate_cb_move(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Mouse_Move *ev; + + ev = event_info; + if (!down) return; + tmp_input[((tmp_input_count & 0x7) * 2) + 0] = ev->cur.output.x; + tmp_input[((tmp_input_count & 0x7) * 2) + 1] = ev->cur.output.y; + tmp_input_count++; +} +#endif diff --git a/ecore/src/bin/ecore_test.c b/ecore/src/bin/ecore_test.c new file mode 100644 index 0000000..c32aef8 --- /dev/null +++ b/ecore/src/bin/ecore_test.c @@ -0,0 +1,899 @@ +#include "config.h" +#include "Ecore.h" +#ifdef BUILD_ECORE_JOB +#include "Ecore_Job.h" +#endif +#ifdef BUILD_ECORE_X +#include "Ecore_X.h" +#endif +#ifdef BUILD_ECORE_FB +#include "Ecore_Fb.h" +#endif +#ifdef BUILD_ECORE_EVAS +#include "Ecore_Evas.h" +#endif +#ifdef BUILD_ECORE_CON +#include "Ecore_Con.h" +#endif +#ifdef BUILD_ECORE_IPC +#include "Ecore_Ipc.h" +#endif + +#include <math.h> + +/* APP GLOBALS */ +double start_time = 0; + +int +handler_signal_exit(void *data, int ev_type, void *ev) +{ + Ecore_Event_Signal_Exit *e; + + e = ev; + if (e->interrupt) printf("exit: interrupt\n"); + if (e->quit) printf("exit: quit\n"); + if (e->terminate) printf("exit: terminate\n"); + ecore_main_loop_quit(); + return 1; +} + + + + + + +int +handler_ipc_client_add(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_IPC + Ecore_Ipc_Event_Client_Add *e; + + e = event; + printf("!!! client %p connected to server!\n", e->client); + return 1; +#endif +} + +int +handler_ipc_client_del(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_IPC + Ecore_Ipc_Event_Client_Del *e; + + e = event; + printf("!!! client %p disconnected from server!\n", e->client); + return 1; +#endif +} + + +int +handler_ipc_client_data(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_IPC + Ecore_Ipc_Event_Client_Data *e; + + e = event; + printf("!!! client sent: [%i] [%i] (%i) \"%s\"\n", e->major, e->minor, e->size, (char*)e->data); + ecore_ipc_client_send(e->client, 1, 2, 0, 0, 0, "ABC", 4); + /* we can disconnect a client like this: */ + /* ecore_ipc_client_del(e->client); */ + /* or we can end a server by: */ + /* ecore_ipc_server_del(ecore_ipc_client_server_get(e->client)); */ + return 1; +#endif +} + + +int +handler_ipc_server_add(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_IPC + Ecore_Ipc_Event_Server_Add *e; + + e = event; + printf("!!! client made successful connect to server %p!\n", e->server); + return 1; +#endif +} + +int +handler_ipc_server_del(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_IPC + Ecore_Ipc_Event_Server_Del *e; + + e = event; + printf("!!! server went away!\n"); + /* clean up our server connection since it went away */ + ecore_ipc_server_del(e->server); + return 1; +#endif +} + +int +handler_ipc_server_data(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_IPC + Ecore_Ipc_Event_Server_Data *e; + static int count = 0; + + e = event; + printf("!!! server sent: [%i] [%i] (%i) \"%s\"\n", e->major, e->minor, e->size, (char*)e->data); + ecore_ipc_server_send(e->server, 3, 4, 0, 0, 0, "EFG", 4); + count++; + if (count > 4) + { + printf("!!! go & disconnect from server!\n"); + ecore_ipc_server_del(e->server); + } + return 1; +#endif +} + +/**** ECORE_CON TEST CODE */ +int +handler_client_add(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_CON + Ecore_Con_Event_Client_Add *e; + + e = event; + printf("!!! client %p connected to server!\n", e->client); + return 1; +#endif +} + +int +handler_client_del(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_CON + Ecore_Con_Event_Client_Del *e; + + e = event; + printf("!!! client %p disconnected from server!\n", e->client); + return 1; +#endif +} + + +int +handler_client_data(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_CON + Ecore_Con_Event_Client_Data *e; + + e = event; + printf("!!! client sent: \"%s\"\n", (char*)e->data); + ecore_con_client_send(e->client, "ABC", 4); + /* we can disconnect a client like this: */ + /* ecore_con_client_del(e->client); */ + /* or we can end a server by: */ + /* ecore_con_server_del(ecore_con_client_server_get(e->client)); */ + return 1; +#endif +} + + +int +handler_server_add(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_CON + Ecore_Con_Event_Server_Add *e; + + e = event; + printf("!!! client made successful connect to server %p!\n", e->server); + return 1; +#endif +} + +int +handler_server_del(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_CON + Ecore_Con_Event_Server_Del *e; + + e = event; + printf("!!! server went away!\n"); + /* clean up our server connection since it went away */ + ecore_con_server_del(e->server); + return 1; +#endif +} + +int +handler_server_data(void *data, int type, void *event) +{ +#ifdef BUILD_ECORE_CON + Ecore_Con_Event_Server_Data *e; + static int count = 0; + + e = event; + printf("!!! server sent: \"%s\"\n", (char*)e->data); + ecore_con_server_send(e->server, "EFG", 4); + count++; + if (count > 4) + { + printf("!!! go & disconnect from server!\n"); + ecore_con_server_del(e->server); + } + return 1; +#endif +} + + +/* NB: also tests ECORE_JOB */ +#ifdef BUILD_ECORE_JOB +void +job_call(void *data) +{ + printf("!! Job done \"%s\"!\n", (char *)data); +} +#endif + +int +idle_enterer(void *data) +{ + printf("-------> Entering idle %3.3f\n", ecore_time_get() - start_time); + return 1; +} + +int +idler(void *data) +{ + printf("oo Idler %3.3f\n", ecore_time_get() - start_time); + return 1; +} + +int +timer(void *data) +{ + printf("Q- Timer tick %3.8f\n", ecore_time_get() - start_time); + /* test ecore_job */ +#ifdef BUILD_ECORE_JOB + ecore_job_add(job_call, "1"); + ecore_job_add(job_call, "2"); + ecore_job_add(job_call, "3"); +#endif + return 1; +} + +void +setup_ecore_test(void) +{ + ecore_idle_enterer_add(idle_enterer, NULL); +/* ecore_idler_add(idler, NULL); */ + ecore_timer_add(2.0, timer, NULL); +} + +#ifdef BUILD_ECORE_X +/**** ECORE_X TEST CODE */ + +Ecore_X_Window win = 0; + +int +handler_x_key_down(void *data, int type, void *event) +{ + Ecore_X_Event_Key_Down *e; + + e = event; + printf("Key down %s\n", e->keyname); + return 1; +} + +int +handler_x_key_up(void *data, int type, void *event) +{ + Ecore_X_Event_Key_Up *e; + + e = event; + printf("Key up %s\n", e->keyname); + return 1; +} + +int +handler_x_mouse_button_down(void *data, int type, void *event) +{ + Ecore_X_Event_Mouse_Button_Down *e; + + e = event; + printf("Mouse down %i [%i][%i]\n", e->button, e->double_click, e->triple_click); + return 1; +} + +int +handler_x_mouse_button_up(void *data, int type, void *event) +{ + Ecore_X_Event_Mouse_Button_Up *e; + + e = event; + printf("Mouse up %i\n", e->button); + return 1; +} + +int +handler_x_mouse_move(void *data, int type, void *event) +{ + Ecore_X_Event_Mouse_Move *e; + + e = event; + printf("Mouse move to %i %i\n", e->x, e->y); + return 1; +} + +int +handler_x_mouse_in(void *data, int type, void *event) +{ + Ecore_X_Event_Mouse_In *e; + + e = event; + printf("Mouse in\n"); + return 1; +} + +int +handler_x_mouse_out(void *data, int type, void *event) +{ + Ecore_X_Event_Mouse_Out *e; + + e = event; + printf("Mouse out\n"); + return 1; +} + +int +handler_x_window_focus_in(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Focus_In *e; + + e = event; + printf("Focus in\n"); + return 1; +} + +int +handler_x_window_focus_out(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Focus_Out *e; + + e = event; + printf("Focus out\n"); + return 1; +} + +int +handler_x_window_damage(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Damage *e; + + e = event; + printf("Damage %i %i, %ix%i\n", e->x, e->y, e->w, e->h); + return 1; +} + +int +handler_x_window_destroy(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Destroy *e; + + e = event; + printf("Destroy\n"); + ecore_main_loop_quit(); + return 1; +} + +int +handler_x_window_configure(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Configure *e; + const int desktop = 0; + + e = event; + printf("Configure %i %i, %ix%i\n", e->x, e->y, e->w, e->h); + printf("Switching desktops to %d\n", desktop); + ecore_x_netwm_desktop_request_send(e->win, 0, desktop); + return 1; +} + +int +handler_x_window_delete_request(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Delete_Request *e; + + e = event; + printf("Delete Request\n"); + ecore_main_loop_quit(); + return 1; +} + +int +handler_x_window_prop_title_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Title_Change *e; + + e = event; + if (e->title) + printf("Title change to \"%s\"\n", e->title); + else + printf("Title deleted\n"); + return 1; +} + +int +handler_x_window_prop_visible_title_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Visible_Title_Change *e; + + e = event; + if (e->title) + printf("Visible title change to \"%s\"\n", e->title); + else + printf("Visible title deleted\n"); + return 1; +} + +int +handler_x_window_prop_icon_name_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Icon_Name_Change *e; + + e = event; + if (e->name) + printf("Icon name change to \"%s\"\n", e->name); + else + printf("Icon name deleted\n"); + return 1; +} + +int +handler_x_window_prop_visible_icon_name_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e; + + e = event; + if (e->name) + printf("Visible icon name change to \"%s\"\n", e->name); + else + printf("Visible icon name deleted\n"); + return 1; +} + +int +handler_x_window_prop_client_machine_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Client_Machine_Change *e; + + e = event; + if (e->name) + printf("Client machine change to \"%s\"\n", e->name); + else + printf("Client machine deleted\n"); + return 1; +} + +int +handler_x_window_prop_pid_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Pid_Change *e; + + e = event; + if (e->pid) + { + printf("Pid change to \"%d\" ", e->pid); + if (e->pid == getpid()) + printf("correct.\n"); + else + printf("INCORRECT!\n"); + } + else + printf("Pid deleted\n"); + return 1; +} + +int +handler_x_window_prop_name_class_change(void *data, int type, void *event) +{ + Ecore_X_Event_Window_Prop_Name_Class_Change *e; + + e = event; + if ((e->name) && (e->clas)) + printf("Name & Class change to \"%s\".\"%s\"\n", e->name, e->clas); + else + printf("Name & Class deleted\n"); + return 1; +} + +void +setup_ecore_x_test(void) +{ + char *tmp; + int pid; + unsigned int desktop; + + win = ecore_x_window_new(0, 0, 0, 120, 60); + ecore_x_netwm_name_set(win, "Ecore Test Program"); + ecore_x_icccm_title_set(win, "Ecore Test Program"); + //printf("Title currently: %s\n", tmp); + free(tmp); +#if 0 + /* Visibile title should be set by the wm */ + tmp = ecore_x_netwm_visible_name_get(win); + if (!tmp) + { + printf("No visible title, setting it to Ecore ... Program\n"); + ecore_x_window_prop_visible_title_set(win, "Ecore ... Program"); + tmp = ecore_x_window_prop_visible_title_get(win); + } + printf("Visible title: %s\n", tmp); + free(tmp); +#endif + ecore_x_netwm_icon_name_get(win, &tmp); + if (!tmp) + { + printf("No icon name, setting it to Ecore_Test\n"); + ecore_x_netwm_icon_name_set(win, "Ecore_Test"); + ecore_x_netwm_icon_name_get(win, &tmp); + } + printf("Icon Name: %s\n", tmp); + free(tmp); +#if 0 + /* Visibile icon should be set by the wm */ + tmp = ecore_x_window_prop_visible_icon_name_get(win); + if (!tmp) + { + printf("No visible icon name, setting it to Ecore\n"); + ecore_x_window_prop_visible_icon_name_set(win, "Ecore"); + tmp = ecore_x_window_prop_visible_icon_name_get(win); + } + printf("Visible icon Name: %s\n", tmp); + free(tmp); +#endif + tmp = ecore_x_icccm_client_machine_get(win); + if (tmp) + { + printf("Client machine: %s\n", tmp); + free(tmp); + } + ecore_x_netwm_pid_get(win, &pid); + printf("Pid: %d\n", pid); + ecore_x_icccm_name_class_set(win, "ecore_test", "main"); + ecore_x_netwm_desktop_set(win, 1); + ecore_x_netwm_desktop_get(win, &desktop); + printf("Window on desktop %u\n", desktop); + ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_DIALOG); + ecore_x_icccm_protocol_set(win, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 1); + ecore_x_window_show(win); + ecore_x_flush(); + + ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN, handler_x_key_down, NULL); + ecore_event_handler_add(ECORE_X_EVENT_KEY_UP, handler_x_key_up, NULL); + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_DOWN, handler_x_mouse_button_down, NULL); + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_UP, handler_x_mouse_button_up, NULL); + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_MOVE, handler_x_mouse_move, NULL); + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, handler_x_mouse_in, NULL); + ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, handler_x_mouse_out, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, handler_x_window_focus_in, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, handler_x_window_focus_out, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, handler_x_window_damage, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, handler_x_window_destroy, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, handler_x_window_configure, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, handler_x_window_delete_request, NULL); + /* + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE, handler_x_window_prop_title_change, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE, handler_x_window_prop_visible_title_change, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE, handler_x_window_prop_icon_name_change, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE, handler_x_window_prop_visible_icon_name_change, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE, handler_x_window_prop_name_class_change, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE, handler_x_window_prop_client_machine_change, NULL); + ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, handler_x_window_prop_pid_change, NULL); + */ + +} +#endif + +#ifdef BUILD_ECORE_EVAS +/* choose: TEST_X, TEST_FB */ +#define TEST_X + +/**** ECORE_EVAS TEST CODE */ + +Ecore_Timer *anim_timer = NULL; +Ecore_Evas *ee = NULL; +Evas *evas = NULL; +Evas_Object *objects[64]; + +int +obj_timer(void *data) +{ + Evas_Object *o; + Evas_Coord x, y; + Evas_Coord w, h; + Evas_Coord ow, oh; + double t; + int m, n; + int i; + + t = ecore_time_get() - start_time; + for (i = 0; i < (sizeof(objects) / sizeof(Evas_Object *)); i++) + { + o = objects[i]; + evas_output_viewport_get(evas_object_evas_get(o), NULL, NULL, &w, &h); + evas_object_geometry_get(o, NULL, NULL, &ow, &oh); + m = ((int)o / 36) & 0x3f; + n = ((int)o / 763) & 0x3f; + x = sin(t * (double)m / 12) * ((w - ow) / 2); + y = sin(t * (double)n / 12) * ((h - oh) / 2); + evas_object_move(o, (w / 2) - (ow / 2) + x, (h / 2) - (oh / 2) + y); + } + return 1; +} + +void +del_req(Ecore_Evas *ee) +{ + int i; + + printf("request to go away... nice exit\n"); + for (i = 0; i < (sizeof(objects) / sizeof(Evas_Object *)); i++) + objects[i] = NULL; + ecore_timer_del(anim_timer); + anim_timer = NULL; + ecore_main_loop_quit(); +} + +static void +cb_key_down(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Evas_Event_Key_Down *ev; + + ev = event_info; + if (!strcmp(ev->keyname, "Escape")) ecore_main_loop_quit(); + if (!strcmp(ev->keyname, "q")) ecore_main_loop_quit(); + if (!strcmp(ev->keyname, "Q")) ecore_main_loop_quit(); + if (!strcmp(ev->keyname, "f")) + { + if (!ecore_evas_fullscreen_get(ee)) + ecore_evas_fullscreen_set(ee, 1); + else + ecore_evas_fullscreen_set(ee, 0); + } + if (!strcmp(ev->keyname, "o")) + { + if (!ecore_evas_override_get(ee)) + ecore_evas_override_set(ee, 1); + else + ecore_evas_override_set(ee, 0); + } + if (!strcmp(ev->keyname, "r")) + { + int r; + + r = ecore_evas_rotation_get(ee); + if (r == 0) r = 90; + else if (r == 90) r = 270; + else if (r == 270) r = 0; + ecore_evas_rotation_set(ee, r); + } + if (!strcmp(ev->keyname, "b")) + { + if (!ecore_evas_borderless_get(ee)) + ecore_evas_borderless_set(ee, 1); + else + ecore_evas_borderless_set(ee, 0); + } + if (!strcmp(ev->keyname, "d")) + { + if (!ecore_evas_avoid_damage_get(ee)) + ecore_evas_avoid_damage_set(ee, 1); + else + ecore_evas_avoid_damage_set(ee, 0); + } + if (!strcmp(ev->keyname, "s")) + { + if (!ecore_evas_shaped_get(ee)) + ecore_evas_shaped_set(ee, 1); + else + ecore_evas_shaped_set(ee, 0); + } +#if 1 /* no data files shipped yet to test this */ + if (!strcmp(ev->keyname, "p")) + { + char *fl; + + ecore_evas_cursor_get(ee, &fl, NULL, NULL, NULL); + if (!fl) + ecore_evas_cursor_set(ee, "data/pointers/mouse_pointer.png", 1000000, 2, 2); + else + ecore_evas_cursor_set(ee, NULL, 0, 0, 0); + } +#endif +} + +int +setup_ecore_evas_test(void) +{ + Evas_Object *o; + int i; + + /* create a new ecore wrapped evas canvas in X */ +#ifdef TEST_X + ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 240, 320); +#endif +#ifdef TEST_FB + ee = ecore_evas_fb_new(NULL, 270, 240, 320); +#endif + if (!ee) return 0; + ecore_evas_title_set(ee, "Ecore Evas Test"); + ecore_evas_name_class_set(ee, "ecore_test", "test_evas"); + /* callback if clsoe button is pressed and win is asked to be deleted */ + ecore_evas_callback_delete_request_set(ee, del_req); + + /* get the actual evas ecore created for us */ + evas = ecore_evas_get(ee); + + /* image cache set (in bytes) */ + evas_image_cache_set(evas, 0 * 1024); + /* font cache set (in bytes) */ + evas_font_cache_set(evas, 0 * 1024); + /* add a directory to look in for fonts */ + evas_font_path_append(evas, "./"); + + /* set up a big white rectangle on the bg */ + o = evas_object_rectangle_add(evas); + evas_object_color_set(o, 255, 255, 255, 255); + evas_object_move(o, 0, 0); + evas_object_resize(o, 100000, 100000); + evas_object_layer_set(o, -1000000); + evas_object_event_callback_add(o, EVAS_CALLBACK_KEY_DOWN, cb_key_down, ee); + evas_object_focus_set(o, 1); + evas_object_show(o); + + /* make a bunch of rectangles */ + for (i = 0; i < (sizeof(objects) / sizeof(Evas_Object *)); i++) + { + o = evas_object_rectangle_add(evas); + evas_object_move(o, 10, 10); + evas_object_pass_events_set(o, 1); + evas_object_color_set(o, + ((int)o) & 0xff, + ((int)o / 30) & 0xff, + ((int)o / 65) & 0xff, + ((int)o / 156) & 0xff); + evas_object_resize(o, 4 + (((int)o) % 100), 4 + (((int)o / 50) % 100)); + evas_object_show(o); + objects[i] = o; + } + /* add a timer to animate them */ + anim_timer = ecore_timer_add(0.01, obj_timer, NULL); + + ecore_evas_show(ee); + return 1; +} +#endif + +/**** MAIN */ +int +main(int argc, const char **argv) +{ + /* get the time the program started at */ + start_time = ecore_time_get(); + + /* init ecore */ + ecore_init(); + /* tell ecore what our arguments are */ + ecore_app_args_set(argc, argv); + +#if 1 + /* setup to test ecore module basics */ + setup_ecore_test(); +#endif + +#ifdef BUILD_ECORE_CON +#if 0 + /* init ecore_con */ + ecore_con_init(); + { + Ecore_Con_Server *server; + +/* server = ecore_con_server_add(ECORE_CON_LOCAL_USER, "ecore_test", 0, NULL);*/ + server = ecore_con_server_add(ECORE_CON_LOCAL_SYSTEM, "ecore_test", 0, NULL); +/* server = ecore_con_server_add(ECORE_CON_REMOTE_SYSTEM, "localhost", 7654, NULL); */ + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, handler_client_add, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, handler_client_del, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, handler_client_data, NULL); + printf("create server %p\n", server); + } + { + Ecore_Con_Server *server; + +/* server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, "ecore_test", 0, NULL);*/ + server = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM, "ecore_test", 0, NULL); +/* server = ecore_con_server_connect(ECORE_CON_REMOTE_SYSTEM, "localhost", 7654, NULL); */ +/* server = ecore_con_server_connect(ECORE_CON_REMOTE_SYSTEM, "www.rasterman.com", 80, NULL); */ + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, handler_server_add, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, handler_server_del, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, handler_server_data, NULL); + printf("connect to server: %p\n", server); + if (server) + { + char data[160 * 1024]; + + strcpy(data, "BLAHPANTS!"); + ecore_con_server_send(server, data, 160 * 1024); + } + } +#endif +#endif + +#ifdef BUILD_ECORE_IPC +#if 1 + /* init ecore_ipc */ + ecore_ipc_init(); + { + Ecore_Ipc_Server *server; + + server = ecore_ipc_server_add(ECORE_IPC_LOCAL_SYSTEM, "ecore_ipc_test", 0, NULL); +/* server = ecore_ipc_server_add(ECORE_IPC_REMOTE_SYSTEM, "localhost", 4567, NULL); */ + ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD, handler_ipc_client_add, NULL); + ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL, handler_ipc_client_del, NULL); + ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA, handler_ipc_client_data, NULL); + printf("create ipc server %p\n", server); + } + { + Ecore_Ipc_Server *server; + + server = ecore_ipc_server_connect(ECORE_IPC_LOCAL_SYSTEM, "ecore_ipc_test", 0, NULL); +/* server = ecore_ipc_server_connect(ECORE_IPC_REMOTE_SYSTEM, "localhost", 4567, NULL); */ + ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_ADD, handler_ipc_server_add, NULL); + ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DEL, handler_ipc_server_del, NULL); + ecore_event_handler_add(ECORE_IPC_EVENT_SERVER_DATA, handler_ipc_server_data, NULL); + printf("connect to ipc server: %p\n", server); + if (server) + { + char data[160 * 1024]; + + strcpy(data, "BLAHPANTS!"); + ecore_ipc_server_send(server, 5, 6, 0, 0, 0, data, 160 * 1024); + } + } +#endif +#endif + +#ifdef BUILD_ECORE_EVAS + /* init ecore_evas */ +/* if (!ecore_evas_init()) return -1; */ +#endif + + /* setup a callback to handle a systsme signal to quit */ + ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, handler_signal_exit, NULL); + +#ifdef BUILD_ECORE_X + /* setup to test ecore_x module things */ + if (!ecore_x_init(NULL)) return -1; + setup_ecore_x_test(); +#endif + +#ifdef BUILD_ECORE_EVAS + /* setup to test ecore_evas module */ +/* if (!setup_ecore_evas_test()) return -1; */ +#endif + + /* run the main loop */ + ecore_main_loop_begin(); + +#ifdef BUILD_ECORE_EVAS + /* shut down ecore_evas */ + ecore_evas_shutdown(); +#endif +#ifdef BUILD_ECORE_IPC + /* shut down ecore_ipc */ + ecore_ipc_shutdown(); +#endif +#ifdef BUILD_ECORE_CON + /* shut down ecore_con */ + ecore_con_shutdown(); +#endif + /* shut down ecore */ + ecore_shutdown(); + return 0; +} diff --git a/ecore/src/e_ev_filter.c b/ecore/src/e_ev_filter.c new file mode 100644 index 0000000..58c7e0f --- /dev/null +++ b/ecore/src/e_ev_filter.c @@ -0,0 +1,132 @@ +#include "Ecore.h" + +typedef struct _ecore_event_handler Ecore_Event_Handler; +typedef struct _ecore_event_idle_handler Ecore_Event_Idle_Handler; + +struct _ecore_event_handler +{ + void (*func) (Ecore_Event * ev); + Ecore_Event_Handler *next; +}; + +struct _ecore_event_idle_handler +{ + void (*func) (void *data); + void *data; + Ecore_Event_Idle_Handler *next; +}; + +static Ecore_Event_Handler *handler[ECORE_EVENT_MAX]; +static Ecore_Event_Idle_Handler *idle_handlers = NULL; + +void +ecore_event_filter(Ecore_Event * ev) +{ + Ecore_Event *evp; + int motion_events = 0; + int dnd_pos_events = 0; + int dnd_status_events = 0; + + /* count events to only use last events of some types */ + for (evp = ev; evp; evp = evp->next) + { + if (evp->type == ECORE_EVENT_MOUSE_MOVE) + motion_events++; + if (evp->type == ECORE_EVENT_DND_DROP_POSITION) + dnd_pos_events++; + if (evp->type == ECORE_EVENT_DND_DROP_STATUS) + dnd_status_events++; + } + for (evp = ev; evp; evp = evp->next) + { + if (evp->type == ECORE_EVENT_MOUSE_MOVE) + { + if (motion_events > 1) + { + evp->ignore = 1; + motion_events--; + } + } + else if (evp->type == ECORE_EVENT_DND_DROP_POSITION) + { + if (dnd_pos_events > 1) + { + evp->ignore = 1; + dnd_pos_events--; + } + } + else if (evp->type == ECORE_EVENT_DND_DROP_STATUS) + { + if (dnd_status_events > 1) + { + evp->ignore = 1; + dnd_status_events--; + } + } + } +} + +void +ecore_event_filter_events_handle(Ecore_Event * ev) +{ + Ecore_Event *evp; + + for (evp = ev; evp; evp = evp->next) + { + Ecore_Event_Handler *h; + + if (!evp->ignore) + { + for (h = handler[evp->type]; h; h = h->next) + { + if (h->func) + h->func(evp); + } + } + } +} + +void +ecore_event_filter_idle_handle(void) +{ + Ecore_Event_Idle_Handler *h; + + for (h = idle_handlers; h; h = h->next) + h->func(h->data); +} + +extern int __quit_ev_loop; + +void +ecore_event_filter_init(void) +{ + int i; + + __quit_ev_loop = 0; + for (i = 0; i < ECORE_EVENT_MAX; i++) + handler[i] = NULL; +} + +void +ecore_event_filter_handler_add(Ecore_Event_Type type, + void (*func) (Ecore_Event * ev)) +{ + Ecore_Event_Handler *h; + + h = NEW(Ecore_Event_Handler, 1); + h->func = func; + h->next = handler[type]; + handler[type] = h; +} + +void +ecore_event_filter_idle_handler_add(void (*func) (void *data), void *data) +{ + Ecore_Event_Idle_Handler *h; + + h = NEW(Ecore_Event_Idle_Handler, 1); + h->func = func; + h->data = data; + h->next = idle_handlers; + idle_handlers = h; +} diff --git a/ecore/src/e_ev_signal.c b/ecore/src/e_ev_signal.c new file mode 100644 index 0000000..b0e34cb --- /dev/null +++ b/ecore/src/e_ev_signal.c @@ -0,0 +1,320 @@ +#include "Ecore.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <errno.h> + +static void ecore_event_signal_free(void *event); +static void ecore_event_signal_handle_sigchld(int num); +static void ecore_event_signal_handle_sigusr1(int num); +static void ecore_event_signal_handle_sigusr2(int num); +static void ecore_event_signal_handle_sighup(int num); +static void ecore_event_signal_handle_sigpipe(int num); +static void ecore_event_signal_handle_sigsegv(int num); +static void ecore_event_signal_handle_sigfpe(int num); +static void ecore_event_signal_handle_sigill(int num); +static void ecore_event_signal_handle_sigbus(int num); + +#ifdef HAVE_SIGSTKFLT +static void ecore_event_signal_handle_sigstkflt(int num); +#endif +#ifdef HAVE_SIGPWR +static void ecore_event_signal_handle_sigpwr(int num); +#endif +static void ecore_event_signal_handle_sigchld(int num); +static void ecore_event_signal_handle_all(pid_t pid); + +static int signal_chld_count = 0; +static int signal_usr1_count = 0; +static int signal_usr2_count = 0; +static int signal_hup_count = 0; + +/* freeing stuff */ +static void +ecore_event_signal_free(void *event) +{ + FREE(event); +} + +/* signal handlers we can return from and add to signal recieved counts */ +static void +ecore_event_signal_handle_sigchld(int num) +{ + signal_chld_count++; + return; + num = 0; +} + +static void +ecore_event_signal_handle_sigusr1(int num) +{ + signal_usr1_count++; + return; + num = 0; +} + +static void +ecore_event_signal_handle_sigusr2(int num) +{ + signal_usr2_count++; + return; + num = 0; +} + +static void +ecore_event_signal_handle_sighup(int num) +{ + signal_hup_count++; + return; + num = 0; +} + +/* signals to ignore */ +static void +ecore_event_signal_handle_sigpipe(int num) +{ + return; + num = 0; +} + +/* signal handlers we cant return from - so handle here */ +static void +ecore_event_signal_handle_sigsegv(int num) +{ + for (;;) + { + fprintf(stderr, "EEEEEEEEK SEGV - waiting 10 seconds\n"); + sleep(10); + } + /* EEK - can't return - bad */ + abort(); + num = 0; +} + +static void +ecore_event_signal_handle_sigfpe(int num) +{ + /* EEK - can't return - bad */ + abort(); + num = 0; +} + +static void +ecore_event_signal_handle_sigill(int num) +{ + /* EEK - can't return - bad */ + abort(); + num = 0; +} + +static void +ecore_event_signal_handle_sigbus(int num) +{ + /* EEK - can't return - bad */ + abort(); + num = 0; +} + +#ifdef HAVE_SIGSTKFLT +static void +ecore_event_signal_handle_sigstkflt(int num) +{ + /* EEK - can't return - bad */ + abort(); + return; + num = 0; +} +#endif + +static void +ecore_event_signal_handle_sigint(int num) +{ + exit(0); + return; + num = 0; +} + +static void +ecore_event_signal_handle_sigquit(int num) +{ + exit(0); + return; + num = 0; +} + +static void +ecore_event_signal_handle_sigabrt(int num) +{ + abort(); + return; + num = 0; +} + +static void +ecore_event_signal_handle_sigalrm(int num) +{ + return; + num = 0; +} + +static void +ecore_event_signal_handle_sigterm(int num) +{ + exit(0); + return; + num = 0; +} + +#ifdef HAVE_SIGPWR +static void +ecore_event_signal_handle_sigpwr(int num) +{ + exit(0); + return; + num = 0; +} +#endif + +static void +ecore_event_signal_handle_all(pid_t pid_pass) +{ + int status; + pid_t pid; + + if (signal_chld_count > 0) + { + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) + { + if (WIFEXITED(status)) + { + Ecore_Event_Child *e; + int code; + + code = WEXITSTATUS(status); + e = NEW(Ecore_Event_Child, 1); + e->pid = pid; + e->exit_code = code; + ecore_add_event(ECORE_EVENT_CHILD, e, ecore_event_signal_free); + } + } + signal_chld_count = 0; + } + while (signal_usr1_count > 0) + { + Ecore_Event_User *e; + + e = NEW(Ecore_Event_User, 1); + e->num = 0; + e->hup = 0; + ecore_add_event(ECORE_EVENT_USER, e, ecore_event_signal_free); + signal_usr1_count--; + } + while (signal_hup_count > 0) + { + Ecore_Event_User *e; + + e = NEW(Ecore_Event_User, 1); + e->num = 0; + e->hup = 1; + ecore_add_event(ECORE_EVENT_USER, e, ecore_event_signal_free); + signal_hup_count--; + } + return; + pid_pass = 0; +} + +int +ecore_event_signal_events_pending(void) +{ + return (signal_chld_count + signal_usr1_count + signal_hup_count); +} + +void +ecore_event_signal_init(void) +{ + struct sigaction sa; + + ecore_add_event_pid(0, ecore_event_signal_handle_all); + + sa.sa_handler = ecore_event_signal_handle_sigchld; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGCHLD, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigusr1; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGUSR1, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigusr2; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGUSR2, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sighup; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGHUP, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigpipe; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGPIPE, &sa, (struct sigaction *)0); +/* + sa.sa_handler = ecore_event_signal_handle_sigsegv; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGSEGV, &sa, (struct sigaction *)0); +*/ + sa.sa_handler = ecore_event_signal_handle_sigfpe; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGFPE, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigill; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGILL, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigbus; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGBUS, &sa, (struct sigaction *)0); +#ifdef HAVE_SIGSTKFLT + sa.sa_handler = ecore_event_signal_handle_sigstkflt; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGSTKFLT, &sa, (struct sigaction *)0); +#endif + sa.sa_handler = ecore_event_signal_handle_sigint; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigquit; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGQUIT, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigabrt; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGABRT, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigalrm; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGALRM, &sa, (struct sigaction *)0); + + sa.sa_handler = ecore_event_signal_handle_sigterm; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGTERM, &sa, (struct sigaction *)0); +#ifdef HAVE_SIGPWR + sa.sa_handler = ecore_event_signal_handle_sigpwr; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGPWR, &sa, (struct sigaction *)0); +#endif +} diff --git a/ecore/src/e_ev_x.c b/ecore/src/e_ev_x.c new file mode 100644 index 0000000..a3ea7bd --- /dev/null +++ b/ecore/src/e_ev_x.c @@ -0,0 +1,1234 @@ +#include "Ecore.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* private funtion prototypes */ +static void ecore_event_x_handle_events(int fd); +static void ecore_event_x_translate_events(XEvent * events, + int num_events); + +static void ecore_event_key_down_free(void *event); +static void ecore_event_key_up_free(void *event); +static void ecore_event_generic_free(void *event); +static void ecore_event_dnd_drop_request_free(void *event); +static void ecore_event_paste_request_free(void *event); + +static void ecore_event_x_handle_keypress(XEvent * xevent); +static void ecore_event_x_handle_keyrelease(XEvent * xevent); +static void ecore_event_x_handle_button_press(XEvent * xevent); +static void ecore_event_x_handle_button_release(XEvent * xevent); +static void ecore_event_x_handle_motion_notify(XEvent * xevent); +static void ecore_event_x_handle_enter_notify(XEvent * xevent); +static void ecore_event_x_handle_leave_notify(XEvent * xevent); +static void ecore_event_x_handle_focus_in(XEvent * xevent); +static void ecore_event_x_handle_focus_out(XEvent * xevent); +static void ecore_event_x_handle_expose(XEvent * xevent); +static void ecore_event_x_handle_visibility_notify(XEvent * xevent); +static void ecore_event_x_handle_create_notify(XEvent * xevent); +static void ecore_event_x_handle_destroy_notify(XEvent * xevent); +static void ecore_event_x_handle_unmap_notify(XEvent * xevent); +static void ecore_event_x_handle_map_notify(XEvent * xevent); +static void ecore_event_x_handle_map_request(XEvent * xevent); +static void ecore_event_x_handle_reparent_notify(XEvent * xevent); +static void ecore_event_x_handle_configure_notify(XEvent * xevent); +static void ecore_event_x_handle_configure_request(XEvent * xevent); +static void ecore_event_x_handle_circulate_notify(XEvent * xevent); +static void ecore_event_x_handle_circulate_request(XEvent * xevent); +static void ecore_event_x_handle_property_notify(XEvent * xevent); +static void ecore_event_x_handle_colormap_notify(XEvent * xevent); +static void ecore_event_x_handle_selection_notify(XEvent * xevent); +static void ecore_event_x_handle_selection_clear(XEvent * xevent); +static void ecore_event_x_handle_selection_request(XEvent * xevent); +static void ecore_event_x_handle_client_message(XEvent * xevent); +static void ecore_event_x_handle_shape_change(XEvent * xevent); + +static int max_event_id = 0; +static void (**event_translator) (XEvent * event) = NULL; + +static int lock_mask_scroll = 0, lock_mask_num = 0, lock_mask_caps = 0; +static int mod_mask_shift = 0, mod_mask_ctrl = 0, mod_mask_alt = + 0, mod_mask_win = 0; + +/* convenience macros */ +#define GETSET_MODS(state, mods) \ +(mods) = ECORE_EVENT_KEY_MODIFIER_NONE;\ +if ((state) & mod_mask_shift) { ecore_mod_shift_set(1); (mods) |= ECORE_EVENT_KEY_MODIFIER_SHIFT; }\ +else ecore_mod_shift_set(0);\ +if ((state) & mod_mask_ctrl) { ecore_mod_ctrl_set(1); (mods) |= ECORE_EVENT_KEY_MODIFIER_CTRL; }\ +else ecore_mod_ctrl_set(0);\ +if ((state) & mod_mask_alt) { ecore_mod_alt_set(1); (mods) |= ECORE_EVENT_KEY_MODIFIER_ALT; }\ +else ecore_mod_alt_set(0);\ +if ((state) & mod_mask_win) { ecore_mod_win_set(1); (mods) |= ECORE_EVENT_KEY_MODIFIER_WIN; }\ +else ecore_mod_win_set(0); + +/* public functions */ + +/* initialise event handling for the fd X is on */ +void +ecore_event_x_init(void) +{ + int i, shape_event_id, current_lock; + + shape_event_id = max_event_id = ecore_event_shape_get_id(); + if (shape_event_id < LASTEvent) + { + max_event_id = LASTEvent; + fprintf(stderr, "ERROR: No shape extension! This is BAD!\n"); + } + event_translator = NEW_PTR(max_event_id + 1); + for (i = 0; i < max_event_id + 1; i++) + event_translator[i] = NULL; + event_translator[KeyPress] = ecore_event_x_handle_keypress; + event_translator[KeyRelease] = ecore_event_x_handle_keyrelease; + event_translator[ButtonPress] = ecore_event_x_handle_button_press; + event_translator[ButtonRelease] = ecore_event_x_handle_button_release; + event_translator[MotionNotify] = ecore_event_x_handle_motion_notify; + event_translator[EnterNotify] = ecore_event_x_handle_enter_notify; + event_translator[LeaveNotify] = ecore_event_x_handle_leave_notify; + event_translator[FocusIn] = ecore_event_x_handle_focus_in; + event_translator[FocusOut] = ecore_event_x_handle_focus_out; + event_translator[Expose] = ecore_event_x_handle_expose; + event_translator[VisibilityNotify] = ecore_event_x_handle_visibility_notify; + event_translator[CreateNotify] = ecore_event_x_handle_create_notify; + event_translator[DestroyNotify] = ecore_event_x_handle_destroy_notify; + event_translator[UnmapNotify] = ecore_event_x_handle_unmap_notify; + event_translator[MapNotify] = ecore_event_x_handle_map_notify; + event_translator[MapRequest] = ecore_event_x_handle_map_request; + event_translator[ReparentNotify] = ecore_event_x_handle_reparent_notify; + event_translator[ConfigureNotify] = ecore_event_x_handle_configure_notify; + event_translator[ConfigureRequest] = ecore_event_x_handle_configure_request; + event_translator[CirculateNotify] = ecore_event_x_handle_circulate_notify; + event_translator[CirculateRequest] = ecore_event_x_handle_circulate_request; + event_translator[PropertyNotify] = ecore_event_x_handle_property_notify; + event_translator[ColormapNotify] = ecore_event_x_handle_colormap_notify; + event_translator[ClientMessage] = ecore_event_x_handle_client_message; + event_translator[SelectionNotify] = ecore_event_x_handle_selection_notify; + event_translator[SelectionClear] = ecore_event_x_handle_selection_clear; + event_translator[SelectionRequest] = ecore_event_x_handle_selection_request; + if (shape_event_id > SelectionRequest) + event_translator[shape_event_id] = ecore_event_x_handle_shape_change; + + lock_mask_scroll = ecore_lock_mask_scroll_get(); + lock_mask_num = ecore_lock_mask_num_get(); + lock_mask_caps = ecore_lock_mask_caps_get(); + + mod_mask_shift = ecore_mod_mask_shift_get(); + mod_mask_ctrl = ecore_mod_mask_ctrl_get(); + mod_mask_alt = ecore_mod_mask_alt_get(); + mod_mask_win = ecore_mod_mask_win_get(); + +/* HRRRMMM lets not do this + ecorecore_keygrab("Num_Lock", ECORE_EVENT_KEY_MODIFIER_NONE, 1, 1); + ecorecore_keygrab("Scroll_Lock", ECORE_EVENT_KEY_MODIFIER_NONE, 1, 1); + ecorecore_keygrab("Caps_Lock", ECORE_EVENT_KEY_MODIFIER_NONE, 1, 1); + */ + current_lock = ecore_modifier_mask_get(); + if (current_lock & lock_mask_scroll) + ecore_lock_scroll_set(1); + if (current_lock & lock_mask_num) + ecore_lock_num_set(1); + if (current_lock & lock_mask_caps) + ecore_lock_caps_set(1); + if (current_lock & mod_mask_shift) + ecore_mod_shift_set(1); + if (current_lock & mod_mask_ctrl) + ecore_mod_ctrl_set(1); + if (current_lock & mod_mask_alt) + ecore_mod_alt_set(1); + if (current_lock & mod_mask_win) + ecore_mod_win_set(1); + ecore_add_event_fd(ecore_x_get_fd(), ecore_event_x_handle_events); +} + +/* private functions */ +/* get all events onthe event queue and translate them */ +static void +ecore_event_x_handle_events(int fd) +{ + int num_events = 0, size_events = 0; + XEvent *events = NULL; + + /* while there are events in the queue */ + while (ecore_events_pending()) + { + /* incriment our event count */ + num_events++; + /* if the numebr fo events is > than our buffer size then */ + if (num_events > size_events) + { + /* increase the buffer size by 64 events */ + size_events += 64; + if (events) + { + REALLOC(events, XEvent, size_events)} + else + events = NEW(XEvent, size_events); + } + /* get the next event into the event buffer */ + ecore_get_next_event(&(events[num_events - 1])); + } + /* call the XEvent -> Eevent translator */ + if (events) + { + ecore_event_x_translate_events(events, num_events); + /* if theres an event buffer - free it */ + FREE(events); + } + return; + fd = 0; +} + +/* take an array of events and translate them into E events */ +static void +ecore_event_x_translate_events(XEvent * events, int num_events) +{ + int i; + + for (i = 0; i < num_events; i++) + { + if ((events[i].type <= max_event_id) && + (event_translator[events[i].type])) + (*(event_translator[events[i].type])) (&(events[i])); + } +} + +static void +ecore_event_key_down_free(void *event) +{ + Ecore_Event_Key_Down *e; + + e = (Ecore_Event_Key_Down *) event; + IF_FREE(e->key); + IF_FREE(e->compose); + FREE(e); +} + +static void +ecore_event_key_up_free(void *event) +{ + Ecore_Event_Key_Up *e; + + e = (Ecore_Event_Key_Up *) event; + IF_FREE(e->key); + IF_FREE(e->compose); + FREE(e); +} + +static void +ecore_event_generic_free(void *event) +{ + FREE(event); +} + +static void +ecore_event_dnd_drop_request_free(void *event) +{ + Ecore_Event_Dnd_Drop_Request *e; + + e = (Ecore_Event_Dnd_Drop_Request *) event; + if (e->files) + { + int i; + + for (i = 0; i < e->num_files; i++) + FREE(e->files[i]); + } + FREE(event); +} + +static void +ecore_event_paste_request_free(void *event) +{ + Ecore_Event_Paste_Request *e; + + e = (Ecore_Event_Paste_Request *) event; + IF_FREE(e->string); + FREE(event); +} + +static void +ecore_event_x_handle_keypress(XEvent * xevent) +{ + Ecore_Event_Key_Down *e; + static KeyCode previous_code = 0; + static Time previous_time = 0; + + /* avoid doubling events up from passive grabs */ + if ((xevent->xkey.keycode == previous_code) && + xevent->xkey.time == previous_time) + return; + previous_code = xevent->xkey.keycode; + previous_time = xevent->xkey.time; +/* + if (ecore_keyget_keysym_from_keycode(xevent->xkey.keycode) == XK_Scroll_Lock) + { + if (ecore_lock_scroll_get()) + ecore_lock_scroll_set(0); + else + ecore_lock_scroll_set(1); + e_event_allow(ReplayKeyboard, xevent->xkey.time); + ecore_flush(); + } + else if (ecore_keyget_keysym_from_keycode(xevent->xkey.keycode) == XK_Num_Lock) + { + if (ecore_lock_num_get()) + ecore_lock_num_set(0); + else + ecore_lock_num_set(1); + e_event_allow(ReplayKeyboard, xevent->xkey.time); + ecore_flush(); + } + else if (ecore_keyget_keysym_from_keycode(xevent->xkey.keycode) == XK_Caps_Lock) + { + if (ecore_lock_caps_get()) + ecore_lock_caps_set(0); + else + ecore_lock_caps_set(1); + e_event_allow(ReplayKeyboard, xevent->xkey.time); + ecore_flush(); + } + */ + e = NEW(Ecore_Event_Key_Down, 1); + e->win = xevent->xkey.window; + e->root = xevent->xkey.root; + GETSET_MODS(xevent->xkey.state, e->mods); + e->time = xevent->xkey.time; + e->key = ecore_key_get_string_from_keycode(xevent->xkey.keycode); + { + int val; + char buf[256]; + KeySym sym; + XComposeStatus stat; + + val = XLookupString((XKeyEvent *) xevent, buf, sizeof(buf), &sym, &stat); + if (val > 0) + { + buf[val] = 0; + e->compose = strdup(buf); + } + else + e->compose = NULL; + } + ecore_add_event(ECORE_EVENT_KEY_DOWN, e, ecore_event_key_down_free); +} + +static void +ecore_event_x_handle_keyrelease(XEvent * xevent) +{ + Ecore_Event_Key_Up *e; + static KeyCode previous_code = 0; + static Time previous_time = 0; + + /* avoid doubling events up from passive grabs */ + if ((xevent->xkey.keycode == previous_code) && + xevent->xkey.time == previous_time) + return; + previous_code = xevent->xkey.keycode; + previous_time = xevent->xkey.time; + + e = NEW(Ecore_Event_Key_Up, 1); + e->win = xevent->xkey.window; + e->root = xevent->xkey.root; + GETSET_MODS(xevent->xkey.state, e->mods); + e->time = xevent->xkey.time; + e->key = ecore_key_get_string_from_keycode(xevent->xkey.keycode); + { + int val; + char buf[256]; + KeySym sym; + XComposeStatus stat; + + val = XLookupString((XKeyEvent *) xevent, buf, sizeof(buf), &sym, &stat); + if (val > 0) + { + buf[val] = 0; + e->compose = strdup(buf); + } + else + e->compose = NULL; + } + ecore_add_event(ECORE_EVENT_KEY_UP, e, ecore_event_key_up_free); +} + +static void +ecore_event_x_handle_button_press(XEvent * xevent) +{ + static Time last_time = 0, last_last_time = 0; + static int last_button = 0, last_last_button = 0; + static Window last_window = 0, last_last_window = 0; + + ecore_pointer_xy_set(xevent->xbutton.x_root, xevent->xbutton.y_root); + if ((xevent->xbutton.button == 4) || (xevent->xbutton.button == 5)) + { + Ecore_Event_Wheel *e; + + e = NEW(Ecore_Event_Wheel, 1); + e->win = xevent->xbutton.window; + e->root = xevent->xbutton.root; + e->x = xevent->xbutton.x; + e->y = xevent->xbutton.y; + e->rx = xevent->xbutton.x_root; + e->ry = xevent->xbutton.y_root; + e->time = xevent->xbutton.time; + if (xevent->xbutton.button == 5) + e->z = 1; + else + e->z = -1; + if (xevent->xbutton.time - last_time < 15) + e->z *= 16; + else if (xevent->xbutton.time - last_time < 30) + e->z *= 4; + GETSET_MODS(xevent->xbutton.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_WHEEL, e, ecore_event_generic_free); + } + else + { + Ecore_Event_Mouse_Down *e; + + e = NEW(Ecore_Event_Mouse_Down, 1); + e->win = xevent->xbutton.window; + e->root = xevent->xbutton.root; + e->button = xevent->xbutton.button; + e->x = xevent->xbutton.x; + e->y = xevent->xbutton.y; + e->rx = xevent->xbutton.x_root; + e->ry = xevent->xbutton.y_root; + e->time = xevent->xbutton.time; + e->double_click = 0; + e->triple_click = 0; + GETSET_MODS(xevent->xbutton.state, e->mods); + if (xevent->xbutton.time - last_last_time < 500) + { + if ((xevent->xbutton.window == (unsigned int)last_window) && + (last_window == last_last_window) && + (xevent->xbutton.button == (unsigned int)last_button) && + (last_button == last_button)) + e->triple_click = 1; + } + else if (xevent->xbutton.time - last_time < 250) + { + if ((xevent->xbutton.window == (unsigned int)last_window) && + (xevent->xbutton.button == (unsigned int)last_button)) + e->double_click = 1; + } + ecore_add_event(ECORE_EVENT_MOUSE_DOWN, e, ecore_event_generic_free); + { + Ecore_XID *xid = NULL; + + if (XFindContext(xevent->xbutton.display, e->win, + xid_context, (XPointer *) & xid) != XCNOENT) + { + if ((xid->grab_button_auto_replay) && + (xid->grab_button_auto_replay(e))) + { + ecore_pointer_replay(e->time); + } + } + } + } + last_last_window = last_window; + last_window = xevent->xbutton.window; + last_last_button = last_button; + last_button = xevent->xbutton.button; + last_last_time = last_time; + last_time = xevent->xbutton.time; +} + +static void +ecore_event_x_handle_button_release(XEvent * xevent) +{ + Ecore_Event_Mouse_Up *e; + + if (xevent->xbutton.button > 3) + return; + + e = NEW(Ecore_Event_Mouse_Up, 1); + e->win = xevent->xbutton.window; + e->root = xevent->xbutton.root; + e->button = xevent->xbutton.button; + e->x = xevent->xbutton.x; + e->y = xevent->xbutton.y; + e->rx = xevent->xbutton.x_root; + e->ry = xevent->xbutton.y_root; + e->time = xevent->xbutton.time; + GETSET_MODS(xevent->xbutton.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_UP, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_motion_notify(XEvent * xevent) +{ + Ecore_Event_Mouse_Move *e; + + ecore_pointer_xy_set(xevent->xmotion.x_root, xevent->xmotion.y_root); + e = NEW(Ecore_Event_Mouse_Move, 1); + e->win = xevent->xmotion.window; + e->root = xevent->xmotion.root; + e->x = xevent->xmotion.x; + e->y = xevent->xmotion.y; + e->rx = xevent->xmotion.x_root; + e->ry = xevent->xmotion.y_root; + e->time = xevent->xmotion.time; + GETSET_MODS(xevent->xmotion.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_MOVE, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_enter_notify(XEvent * xevent) +{ + Ecore_Event_Window_Enter *e; + +/* if ((xevent->xcrossing.mode == NotifyGrab) || (xevent->xcrossing.mode == NotifyUngrab)) return;*/ + ecore_pointer_xy_set(xevent->xcrossing.x_root, xevent->xcrossing.y_root); + e = NEW(Ecore_Event_Window_Enter, 1); + e->win = xevent->xcrossing.window; + e->root = xevent->xcrossing.root; + e->x = xevent->xcrossing.x; + e->y = xevent->xcrossing.y; + e->rx = xevent->xcrossing.x_root; + e->ry = xevent->xcrossing.y_root; + e->time = xevent->xcrossing.time; + GETSET_MODS(xevent->xcrossing.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_IN, e, ecore_event_generic_free); + ecore_window_mouse_set_in(e->win, 1); + { + Ecore_Event_Mouse_Move *e; + + e = NEW(Ecore_Event_Mouse_Move, 1); + e->win = xevent->xcrossing.window; + e->root = xevent->xcrossing.root; + e->x = xevent->xcrossing.x; + e->y = xevent->xcrossing.y; + e->rx = xevent->xcrossing.x_root; + e->ry = xevent->xcrossing.y_root; + e->time = xevent->xcrossing.time; + GETSET_MODS(xevent->xcrossing.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_MOVE, e, ecore_event_generic_free); + } +} + +static void +ecore_event_x_handle_leave_notify(XEvent * xevent) +{ + Ecore_Event_Window_Leave *e; + +/* if ((xevent->xcrossing.mode == NotifyGrab) || (xevent->xcrossing.mode == NotifyUngrab)) return;*/ + ecore_pointer_xy_set(xevent->xcrossing.x_root, xevent->xcrossing.y_root); + { + Ecore_Event_Mouse_Move *e; + + e = NEW(Ecore_Event_Mouse_Move, 1); + e->win = xevent->xcrossing.window; + e->root = xevent->xcrossing.root; + e->x = xevent->xcrossing.x; + e->y = xevent->xcrossing.y; + e->rx = xevent->xcrossing.x_root; + e->ry = xevent->xcrossing.y_root; + e->time = xevent->xcrossing.time; + GETSET_MODS(xevent->xcrossing.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_MOVE, e, ecore_event_generic_free); + } + e = NEW(Ecore_Event_Window_Leave, 1); + e->win = xevent->xcrossing.window; + e->root = xevent->xcrossing.root; + e->x = xevent->xcrossing.x; + e->y = xevent->xcrossing.y; + e->rx = xevent->xcrossing.x_root; + e->ry = xevent->xcrossing.y_root; + e->time = xevent->xcrossing.time; + GETSET_MODS(xevent->xcrossing.state, e->mods); + ecore_add_event(ECORE_EVENT_MOUSE_OUT, e, ecore_event_generic_free); + ecore_window_mouse_set_in(e->win, 0); +} + +static void +ecore_event_x_handle_focus_in(XEvent * xevent) +{ + Ecore_Event_Window_Focus_In *e; + + e = NEW(Ecore_Event_Window_Focus_In, 1); + e->win = xevent->xfocus.window; + e->root = ecore_window_get_root(e->win); + if (xevent->xfocus.mode != NotifyNormal) + e->key_grab = 1; + else + e->key_grab = 0; + ecore_add_event(ECORE_EVENT_WINDOW_FOCUS_IN, e, ecore_event_generic_free); + ecore_focus_window_set(e->win); +} + +static void +ecore_event_x_handle_focus_out(XEvent * xevent) +{ + Ecore_Event_Window_Focus_Out *e; + + e = NEW(Ecore_Event_Window_Focus_Out, 1); + e->win = xevent->xfocus.window; + e->root = ecore_window_get_root(e->win); + if (xevent->xfocus.mode != NotifyNormal) + e->key_grab = 1; + else + e->key_grab = 0; + ecore_add_event(ECORE_EVENT_WINDOW_FOCUS_OUT, e, ecore_event_generic_free); + ecore_focus_window_set(0); +} + +static void +ecore_event_x_handle_expose(XEvent * xevent) +{ + Ecore_Event_Window_Expose *e; + + e = NEW(Ecore_Event_Window_Expose, 1); + e->win = xevent->xexpose.window; + e->root = ecore_window_get_root(e->win); + e->x = xevent->xexpose.x; + e->y = xevent->xexpose.y; + e->w = xevent->xexpose.width; + e->h = xevent->xexpose.height; + ecore_add_event(ECORE_EVENT_WINDOW_EXPOSE, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_visibility_notify(XEvent * xevent) +{ + if (xevent->xvisibility.state != VisibilityPartiallyObscured) + { + Ecore_Event_Window_Visibility *e; + + e = NEW(Ecore_Event_Window_Visibility, 1); + e->win = xevent->xvisibility.window; + e->root = ecore_window_get_root(e->win); + if (xevent->xvisibility.state == VisibilityFullyObscured) + e->fully_obscured = 1; + else + e->fully_obscured = 0; + ecore_add_event(ECORE_EVENT_WINDOW_VISIBILITY, e, + ecore_event_generic_free); + } +} + +static void +ecore_event_x_handle_create_notify(XEvent * xevent) +{ + Ecore_Event_Window_Create *e; + + e = NEW(Ecore_Event_Window_Create, 1); + e->win = xevent->xcreatewindow.window; + ecore_validate_xid(e->win); + e->root = ecore_window_get_root(e->win); + if (xevent->xcreatewindow.override_redirect) + e->override = 1; + else + e->override = 0; + ecore_add_event(ECORE_EVENT_WINDOW_CREATE, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_destroy_notify(XEvent * xevent) +{ + Ecore_Event_Window_Destroy *e; + + e = NEW(Ecore_Event_Window_Destroy, 1); + e->win = xevent->xdestroywindow.window; + e->root = ecore_window_get_root(e->win); + ecore_add_event(ECORE_EVENT_WINDOW_DESTROY, e, ecore_event_generic_free); + ecore_unvalidate_xid(e->win); +} + +static void +ecore_event_x_handle_unmap_notify(XEvent * xevent) +{ + Ecore_Event_Window_Unmap *e; + Ecore_XID *xid = NULL; + + e = NEW(Ecore_Event_Window_Unmap, 1); + e->win = xevent->xunmap.window; + e->root = ecore_window_get_root(e->win); + ecore_add_event(ECORE_EVENT_WINDOW_UNMAP, e, ecore_event_generic_free); + xid = ecore_validate_xid(e->win); + if (xid) + xid->mapped = 0; +} + +static void +ecore_event_x_handle_map_notify(XEvent * xevent) +{ + Ecore_Event_Window_Map *e; + Ecore_XID *xid = NULL; + + e = NEW(Ecore_Event_Window_Map, 1); + e->win = xevent->xmap.window; + e->root = ecore_window_get_root(e->win); + ecore_add_event(ECORE_EVENT_WINDOW_MAP, e, ecore_event_generic_free); + xid = ecore_validate_xid(e->win); + if (xid) + xid->mapped = 1; +} + +static void +ecore_event_x_handle_map_request(XEvent * xevent) +{ + Ecore_Event_Window_Map_Request *e; + + e = NEW(Ecore_Event_Window_Map_Request, 1); + e->win = xevent->xmaprequest.window; + e->root = ecore_window_get_root(e->win); + ecore_add_event(ECORE_EVENT_WINDOW_MAP_REQUEST, e, ecore_event_generic_free); + ecore_validate_xid(e->win); +} + +static void +ecore_event_x_handle_reparent_notify(XEvent * xevent) +{ + Ecore_Event_Window_Reparent *e; + Window parent; + Ecore_XID *xid = NULL; + + e = NEW(Ecore_Event_Window_Reparent, 1); + e->win = xevent->xreparent.window; + xid = ecore_validate_xid(e->win); + e->root = ecore_window_get_root(e->win); + parent = ecore_window_get_parent(e->win); + e->parent_from = parent; + e->parent = xevent->xreparent.parent; + ecore_validate_xid(e->parent); + ecore_del_child(parent, e->win); + ecore_add_child(xevent->xreparent.parent, xevent->xreparent.window); + if (xid) + xid->parent = e->parent; + ecore_add_event(ECORE_EVENT_WINDOW_REPARENT, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_configure_notify(XEvent * xevent) +{ + Ecore_Event_Window_Configure *e; + Ecore_XID *xid; + + e = NEW(Ecore_Event_Window_Configure, 1); + e->win = xevent->xconfigure.window; + e->root = ecore_window_get_root(e->win); + e->x = xevent->xconfigure.x; + e->y = xevent->xconfigure.y; + e->w = xevent->xconfigure.width; + e->h = xevent->xconfigure.height; + if (!xevent->xconfigure.send_event) + { + xid = ecore_validate_xid(e->win); + if (xid) + { + xid->x = e->x; + xid->y = e->y; + xid->w = e->w; + xid->h = e->h; + } + e->wm_generated = 0; + /* FIXME: don't handle redoing stack for xevent->xconfigure.above */ + /* member (the window is stacked immediately in stack above this) */ + } + else + e->wm_generated = 1; + ecore_add_event(ECORE_EVENT_WINDOW_CONFIGURE, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_configure_request(XEvent * xevent) +{ + Ecore_Event_Window_Configure_Request *e; + + e = NEW(Ecore_Event_Window_Configure_Request, 1); + e->win = xevent->xconfigurerequest.window; + e->root = ecore_window_get_root(e->win); + e->x = xevent->xconfigurerequest.x; + e->y = xevent->xconfigurerequest.y; + e->w = xevent->xconfigurerequest.width; + e->h = xevent->xconfigurerequest.height; + e->stack_win = xevent->xconfigurerequest.above; + e->detail = xevent->xconfigurerequest.detail; + e->mask = xevent->xconfigurerequest.value_mask; + ecore_add_event(ECORE_EVENT_WINDOW_CONFIGURE_REQUEST, e, + ecore_event_generic_free); +} + +static void +ecore_event_x_handle_circulate_notify(XEvent * xevent) +{ + Ecore_Event_Window_Circulate *e; + + e = NEW(Ecore_Event_Window_Circulate, 1); + e->win = xevent->xcirculate.window; + e->root = ecore_window_get_root(e->win); + if (xevent->xcirculate.place == PlaceOnBottom) + e->lower = 1; + else + e->lower = 0; + ecore_add_event(ECORE_EVENT_WINDOW_CIRCULATE, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_circulate_request(XEvent * xevent) +{ + Ecore_Event_Window_Circulate_Request *e; + + e = NEW(Ecore_Event_Window_Circulate_Request, 1); + e->win = xevent->xcirculaterequest.window; + e->root = ecore_window_get_root(e->win); + if (xevent->xcirculaterequest.place == PlaceOnBottom) + e->lower = 1; + else + e->lower = 0; + ecore_add_event(ECORE_EVENT_WINDOW_CIRCULATE_REQUEST, e, + ecore_event_generic_free); +} + +static void +ecore_event_x_handle_property_notify(XEvent * xevent) +{ + Ecore_Event_Window_Property *e; + + e = NEW(Ecore_Event_Window_Property, 1); + e->win = xevent->xproperty.window; + e->root = ecore_window_get_root(e->win); + e->atom = xevent->xproperty.atom; + e->time = xevent->xproperty.time; + ecore_add_event(ECORE_EVENT_WINDOW_PROPERTY, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_colormap_notify(XEvent * xevent) +{ + Ecore_Event_Colormap *e; + + e = NEW(Ecore_Event_Colormap, 1); + e->win = xevent->xcolormap.window; + e->root = ecore_window_get_root(e->win); + e->cmap = xevent->xcolormap.colormap; + if (xevent->xcolormap.state == ColormapInstalled) + e->installed = 1; + else + e->installed = 0; + ecore_add_event(ECORE_EVENT_COLORMAP, e, ecore_event_generic_free); +} + +Ecore_Event_Dnd_Drop_Request *ev_drop_request_pending = NULL; + +static void +ecore_event_x_handle_selection_notify(XEvent * xevent) +{ + Ecore_Event_Dnd_Drop_Request *e; + char *data; + int size; + static Atom atom_xdndactioncopy = 0; + static Atom atom_xdndactionmove = 0; + static Atom atom_xdndactionlink = 0; + static Atom atom_xdndactionask = 0; + static Atom atom_xdndactionlist = 0; + + e = ev_drop_request_pending; + if (!e) + { + Ecore_Event_Paste_Request *e2; + + e2 = NEW(Ecore_Event_Paste_Request, 1); + e2->string = ecore_selection_get_data(xevent->xselection.requestor, + xevent->xselection.property); + if (e2->string) + { + e2->win = xevent->xselection.requestor; + e2->root = ecore_window_get_root(e2->win); + e2->source_win = xevent->xselection.requestor; + ecore_add_event(ECORE_EVENT_PASTE_REQUEST, e2, + ecore_event_paste_request_free); + } + else + { + FREE(e2); + } + return; + } + + ECORE_ATOM(atom_xdndactioncopy, "XdndActionCopy"); + ECORE_ATOM(atom_xdndactionmove, "XdndActionMove"); + ECORE_ATOM(atom_xdndactionlink, "XdndActionLink"); + ECORE_ATOM(atom_xdndactionask, "XdndActionAsk"); + ECORE_ATOM(atom_xdndactionlist, "XdndActionList"); + data = ecore_dnd_selection_get(xevent->xany.window, e->source_win, + xevent->xselection.property, &size); + if (data) + { + char *s, *buf; + int i, is; + Atom *method = NULL; + + method = ecore_window_property_get(e->source_win, + atom_xdndactionlist, XA_ATOM, &is); + if (method) + { + e->copy = 0; + e->link = 0; + e->move = 0; + if (*method == atom_xdndactioncopy) + e->copy = 1; + else if (*method == atom_xdndactionmove) + e->move = 1; + else if (*method == atom_xdndactionlink) + e->link = 1; + FREE(method); + } + else + { + e->copy = 0; + e->link = 0; + e->move = 0; + } + s = data; + buf = NEW(char, size); + + i = 0; + is = 0; + e->files = NULL; + while ((s[is]) && (is < size)) + { + if ((i == 0) && (s[is] == '#')) + { + for (; ((s[is] != 0) && (s[is] != '\n')); is++); + } + else + { + if (s[is] != '\r') + { + buf[i++] = s[is]; + } + else + { + buf[i] = 0; + e->num_files++; + REALLOC_PTR(e->files, e->num_files); + e->files[e->num_files - 1] = strdup(buf); + buf[0] = 0; + i = 0; + is++; + } + is++; + } + } + if (i > 0) + { + buf[i] = 0; + e->num_files++; + REALLOC_PTR(e->files, e->num_files); + e->files[e->num_files - 1] = strdup(buf); + } + FREE(buf); + FREE(data); + } + ecore_add_event(ECORE_EVENT_DND_DROP_REQUEST, e, + ecore_event_dnd_drop_request_free); + ev_drop_request_pending = NULL; +} + +static void +ecore_event_x_handle_selection_clear(XEvent * xevent) +{ + Ecore_Event_Clear_Selection *e; + + e = NEW(Ecore_Event_Clear_Selection, 1); + e->win = xevent->xselectionclear.window; + e->root = ecore_window_get_root(e->win); + e->selection = xevent->xselectionclear.selection; + ecore_add_event(ECORE_EVENT_CLEAR_SELECTION, e, ecore_event_generic_free); +} + +static void +ecore_event_x_handle_selection_request(XEvent * xevent) +{ + static Atom atom_xdndselection = 0; + static Atom atom_text_plain = 0; + static Atom atom_text_uri_list = 0; + static Atom atom_text_moz_url = 0; + static Atom atom_netscape_url = 0; + static Atom atom_text_selection = 0; + Ecore_Event_Dnd_Data_Request *e; + + ECORE_ATOM(atom_xdndselection, "XdndSelection"); + ECORE_ATOM(atom_text_plain, "text/plain"); + ECORE_ATOM(atom_text_uri_list, "text/uri-list"); + ECORE_ATOM(atom_text_moz_url, "text/x-moz-url"); + ECORE_ATOM(atom_netscape_url, "_NETSCAPE_URL"); + ECORE_ATOM(atom_text_selection, "TEXT_SELECTION"); + if (xevent->xselectionrequest.selection == atom_xdndselection) + { + e = NEW(Ecore_Event_Dnd_Data_Request, 1); + e->win = xevent->xselectionrequest.owner; + e->root = ecore_window_get_root(e->win); + e->source_win = xevent->xselectionrequest.requestor; + e->plain_text =0; + e->uri_list = 0; + e->moz_url = 0; + e->netscape_url = 0; + + if (xevent->xselectionrequest.target == atom_text_plain) e->plain_text = 1; + if (xevent->xselectionrequest.target == atom_text_uri_list) e->uri_list = 1; + if (xevent->xselectionrequest.target == atom_text_moz_url) e->moz_url = 1; + if (xevent->xselectionrequest.target == atom_netscape_url) e->netscape_url = 1; + e->destination_atom = xevent->xselectionrequest.property; + ecore_add_event(ECORE_EVENT_DND_DATA_REQUEST, e, + ecore_event_generic_free); + } + else + { + XEvent ev; + Atom target_list[2]; + static Atom xa_targets = None; + + if (xa_targets == None) + xa_targets = XInternAtom(xevent->xselectionrequest.display, + "TARGETS", False); + ev.xselection.type = SelectionNotify; + ev.xselection.property = None; + ev.xselection.display = xevent->xselectionrequest.display; + ev.xselection.requestor = xevent->xselectionrequest.requestor; + ev.xselection.selection = xevent->xselectionrequest.selection; + ev.xselection.target = xevent->xselectionrequest.target; + ev.xselection.time = xevent->xselectionrequest.time; + if (xevent->xselectionrequest.target == xa_targets) + { + target_list[0] = (Atom) xa_targets; + target_list[1] = (Atom) XA_STRING; + XChangeProperty(xevent->xselectionrequest.display, + xevent->xselectionrequest.requestor, + xevent->xselectionrequest.property, + xevent->xselectionrequest.target, + (8 * sizeof(target_list[0])), + PropModeReplace, + (unsigned char *)target_list, + (sizeof(target_list) / sizeof(target_list[0]))); + ev.xselection.property = xevent->xselectionrequest.property; + } + else if (xevent->xselectionrequest.target == XA_STRING) + { + void *data; + int size; + + data = ecore_window_property_get(xevent->xselectionrequest.owner, + atom_text_selection, XA_STRING, + &size); + if (data) + { + XChangeProperty(xevent->xselectionrequest.display, + xevent->xselectionrequest.requestor, + xevent->xselectionrequest.property, + xevent->xselectionrequest.target, + 8, PropModeReplace, data, size); + FREE(data); + } + ev.xselection.property = xevent->xselectionrequest.property; + } + XSendEvent(xevent->xselectionrequest.display, + xevent->xselectionrequest.requestor, False, 0, &ev); + } +} + +static void +ecore_event_x_handle_client_message(XEvent * xevent) +{ + static Atom atom_wm_delete_window = 0; + static Atom atom_wm_protocols = 0; + static Atom atom_xdndstatus = 0; + static Atom atom_xdndenter = 0; + static Atom atom_xdndleave = 0; + static Atom atom_xdndfinished = 0; + static Atom atom_xdndposition = 0; + static Atom atom_xdnddrop = 0; + static Atom atom_text_uri_list = 0; + static Atom atom_xdndactioncopy = 0; + static Atom atom_xdndactionlink = 0; + static Atom atom_xdndactionmove = 0; + static Atom atom_xdndactionprivate = 0; + + /* setup some known atoms to translate this message into a sensible event */ + ECORE_ATOM(atom_wm_delete_window, "WM_DELETE_WINDOW"); + ECORE_ATOM(atom_wm_protocols, "WM_PROTOCOLS"); + ECORE_ATOM(atom_xdndstatus, "XdndStatus"); + ECORE_ATOM(atom_xdndfinished, "XdndFinished"); + ECORE_ATOM(atom_xdndenter, "XdndEnter"); + ECORE_ATOM(atom_xdndleave, "XdndLeave"); + ECORE_ATOM(atom_xdnddrop, "XdndDrop"); + ECORE_ATOM(atom_xdndposition, "XdndPosition"); + ECORE_ATOM(atom_xdndactioncopy, "XdndActionCopy"); + ECORE_ATOM(atom_xdndactionlink, "XdndActionLink"); + ECORE_ATOM(atom_xdndactionmove, "XdndActionMove"); + ECORE_ATOM(atom_xdndactionprivate, "XdndActionPrivate"); + ECORE_ATOM(atom_text_uri_list, "text/uri-list"); + + /* first type = delete event sent to client */ + if ((xevent->xclient.message_type == atom_wm_protocols) && + (xevent->xclient.format == 32) && + (xevent->xclient.data.l[0] == (long)atom_wm_delete_window)) + { + Ecore_Event_Window_Delete *e; + + e = NEW(Ecore_Event_Window_Delete, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + ecore_add_event(ECORE_EVENT_WINDOW_DELETE, e, ecore_event_generic_free); + } + else if ((xevent->xclient.message_type == atom_xdndenter) && + (xevent->xclient.format == 32)) + { +/* if ((xevent->xclient.data.l[2] == (long)atom_text_uri_list) || + * (xevent->xclient.data.l[3] == (long)atom_text_uri_list) || + * (xevent->xclient.data.l[4] == (long)atom_text_uri_list)) + */ { + Ecore_Event_Dnd_Drop_Request *e; + + + if (ev_drop_request_pending) + { + ecore_event_dnd_drop_request_free(ev_drop_request_pending); + ev_drop_request_pending = NULL; + } + e = NEW(Ecore_Event_Dnd_Drop_Request, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + e->source_win = (Window) xevent->xclient.data.l[0]; + if (!ecore_dnd_selection_convert + (e->source_win, e->win, atom_text_uri_list)) + { + FREE(e); + return; + } + e->files = NULL; + e->num_files = 0; + ev_drop_request_pending = e; + } + } + else if ((xevent->xclient.message_type == atom_xdndleave) && + (xevent->xclient.format == 32)) + { + Ecore_Event_Dnd_Drop_End *e; + + e = NEW(Ecore_Event_Dnd_Drop_End, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + e->source_win = (Window) xevent->xclient.data.l[0]; + ecore_add_event(ECORE_EVENT_DND_DROP_END, e, ecore_event_generic_free); + } + else if ((xevent->xclient.message_type == atom_xdndposition) && + (xevent->xclient.format == 32)) + { + Ecore_Event_Dnd_Drop_Position *e; + + e = NEW(Ecore_Event_Dnd_Drop_Position, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + e->source_win = (Window) xevent->xclient.data.l[0]; + e->x = (xevent->xclient.data.l[2] >> 16) & 0xffff; + e->y = xevent->xclient.data.l[2] & 0xffff; + ecore_add_event(ECORE_EVENT_DND_DROP_POSITION, e, + ecore_event_generic_free); + } + else if ((xevent->xclient.message_type == atom_xdndstatus) && + (xevent->xclient.format == 32)) + { + Ecore_Event_Dnd_Drop_Status *e; + + ecore_clear_target_status(); + e = NEW(Ecore_Event_Dnd_Drop_Status, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + e->source_win = (Window) xevent->xclient.data.l[0]; + e->x = (xevent->xclient.data.l[2] >> 16) & 0xffff; + e->y = xevent->xclient.data.l[2] & 0xffff; + e->w = (xevent->xclient.data.l[3] >> 16) & 0xffff; + e->h = xevent->xclient.data.l[3] & 0xffff; + + e->copy = e->link = e->move = e->e_private = 0; + if( xevent->xclient.data.l[4] == atom_xdndactioncopy ) + e->copy = 1; + else if( xevent->xclient.data.l[4] == atom_xdndactionlink ) + e->link = 1; + else if( xevent->xclient.data.l[4] == atom_xdndactionmove ) + e->move = 1; + else if( xevent->xclient.data.l[4] == atom_xdndactionprivate ) + e->e_private = 1; + + if (xevent->xclient.data.l[1] & 0x1) + e->ok = 1; + else + e->ok = 0; + if (xevent->xclient.data.l[1] & 0x2) + e->all_position_msgs = 1; + else + e->all_position_msgs = 0; + ecore_add_event(ECORE_EVENT_DND_DROP_STATUS, e, ecore_event_generic_free); + } + else if ((xevent->xclient.message_type == atom_xdndfinished) && + (xevent->xclient.format == 32)) + { + Ecore_Event_Dnd_Drop_End *e; + + e = NEW(Ecore_Event_Dnd_Drop_End, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + e->source_win = (Window) xevent->xclient.data.l[0]; + ecore_add_event(ECORE_EVENT_DND_DROP_END, e, ecore_event_generic_free); + } + else if ((xevent->xclient.message_type == atom_xdnddrop) && + (xevent->xclient.format == 32)) + { + Ecore_Event_Dnd_Drop *e; + + e = NEW(Ecore_Event_Dnd_Drop, 1); + e->win = xevent->xclient.window; + e->root = ecore_window_get_root(e->win); + e->source_win = (Window) xevent->xclient.data.l[0]; + ecore_add_event(ECORE_EVENT_DND_DROP, e, ecore_event_generic_free); + } + else + { + Ecore_Event_Message *e; + + e = NEW(Ecore_Event_Message, 1); + e->win = xevent->xclient.window; + e->format = xevent->xclient.format; + e->atom = xevent->xclient.message_type; + MEMCPY(xevent->xclient.data.b, e->data.b, char, 20); + + ecore_add_event(ECORE_EVENT_MESSAGE, e, ecore_event_generic_free); + } +} + +static void +ecore_event_x_handle_shape_change(XEvent * xevent) +{ + Ecore_Event_Window_Shape *e; + XShapeEvent *shape_event; + + shape_event = (XShapeEvent *) xevent; + e = NEW(Ecore_Event_Window_Shape, 1); + e->win = shape_event->window; + e->root = ecore_window_get_root(e->win); + e->time = shape_event->time; + ecore_add_event(ECORE_EVENT_WINDOW_SHAPE, e, ecore_event_generic_free); +} + +char * +ecore_keypress_translate_into_typeable(Ecore_Event_Key_Down * e) +{ + /* exceptions */ + if ((!strcmp(e->key, "Delete")) || + (!strcmp(e->key, "BackSpace")) || + (!strcmp(e->key, "Tab")) || + (!strcmp(e->key, "Escape")) || + (!strcmp(e->key, "Return")) || + (!strcmp(e->key, "KP_Enter")) || + (!strcmp(e->key, "Enter")) || + (!strcmp(e->key, "KP_Divide")) || + (!strcmp(e->key, "KP_Multiply")) || + (!strcmp(e->key, "KP_Subtract")) || + (!strcmp(e->key, "KP_Add")) || (!strcmp(e->key, "Enter"))) + return NULL; + return e->compose; +} diff --git a/ecore/src/e_events.c b/ecore/src/e_events.c new file mode 100644 index 0000000..0a8f442 --- /dev/null +++ b/ecore/src/e_events.c @@ -0,0 +1,430 @@ +#include "Ecore.h" +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* glocal (yes global/local) variabels for events */ +Ecore_Event_Fd_Handler *fd_handlers = NULL; +Ecore_Event_Ipc_Handler *ipc_handlers = NULL; +Ecore_Event_Pid_Handler *pid_handlers = NULL; +Ecore_Event_Timer *timers = NULL; + +Ecore_Event *events = NULL; +Ecore_Event *last_event = NULL; + +int __quit_ev_loop = 0; + +/* local functions for event handling */ +static void ecore_handle_event_timer(void); +static void ecore_handle_zero_event_timer(void); + +/* public functions */ + +/* add an event to the end of the event queue */ +void +ecore_add_event(Ecore_Event_Type type, void *event, + void (*ev_free) (void *event)) +{ + Ecore_Event *ev; + + ev = NEW(Ecore_Event, 1); + ev->type = type; + ev->ignore = 0; + ev->event = event; + ev->next = NULL; + ev->ev_free = ev_free; + if (!events) + events = ev; + else + last_event->next = ev; + last_event = ev; +} + +/* delete an event from the event queue */ +void +ecore_del_event(void *event) +{ + Ecore_Event *ev, *pev; + + pev = NULL; + ev = events; + while (ev) + { + if (ev->event == event) + { + if (pev) + pev->next = ev->next; + else + events = ev->next; + if (!ev->next) + last_event = pev; + if ((ev->event) && (ev->ev_free)) + (*ev->ev_free) (ev->event); + FREE(ev); + return; + } + pev = ev; + ev = ev->next; + } +} + +void +ecore_del_all_events(void) +{ + Ecore_Event *ev, *pev; + + ev = events; + while (ev) + { + pev = ev; + ev = ev->next; + if ((pev->event) && (pev->ev_free)) + pev->ev_free(pev->event); + FREE(pev); + } + events = NULL; + last_event = NULL; +} + +Ecore_Event * +ecore_get_last_event(void) +{ + return last_event; +} + +/* add a callback handler if fd is active for reading */ +void +ecore_add_event_fd(int fd, void (*func) (int fd)) +{ + Ecore_Event_Fd_Handler *fd_h; + + /* new handler struct */ + fd_h = NEW(Ecore_Event_Fd_Handler, 1); + fd_h->next = fd_handlers; + fd_h->fd = fd; + fd_h->func = func; + fd_handlers = fd_h; +} + +/* delete handler for fd */ +void +ecore_del_event_fd(int fd) +{ + START_LIST_DEL(Ecore_Event_Fd_Handler, fd_handlers, (_p->fd == fd)); + FREE(_p); + END_LIST_DEL; +} + +void +ecore_add_event_pid(pid_t pid, void (*func) (pid_t pid)) +{ + Ecore_Event_Pid_Handler *pid_h; + + /* delete the old handler */ + ecore_del_event_pid(pid); + /* new handler struct */ + pid_h = NEW(Ecore_Event_Pid_Handler, 1); + pid_h->next = pid_handlers; + pid_h->pid = pid; + pid_h->func = func; + pid_handlers = pid_h; +} + +void +ecore_del_event_pid(pid_t pid) +{ + START_LIST_DEL(Ecore_Event_Pid_Handler, pid_handlers, (_p->pid == pid)); + FREE(_p); + END_LIST_DEL; +} + +void +ecore_add_event_ipc(int ipc, void (*func) (int ipc)) +{ + Ecore_Event_Ipc_Handler *ipc_h; + + /* delete the old handler */ + ecore_del_event_ipc(ipc); + /* new handler struct */ + ipc_h = NEW(Ecore_Event_Ipc_Handler, 1); + ipc_h->next = ipc_handlers; + ipc_h->ipc = ipc; + ipc_h->func = func; + ipc_handlers = ipc_h; +} + +void +ecore_del_event_ipc(int ipc) +{ + START_LIST_DEL(Ecore_Event_Ipc_Handler, ipc_handlers, (_p->ipc == ipc)); + FREE(_p); + END_LIST_DEL; +} + +/* sit in this loop forever and process events */ +void +ecore_event_loop(void) +{ + int fdcount, fdsize, ipccount, ipcsize; + int timed_out, were_events; + double time1, time2, prev_time = 0.0; + struct timeval tval; + fd_set fdset, ipcset; + Ecore_Event_Fd_Handler *fd_h; + Ecore_Event_Pid_Handler *pid_h; + Ecore_Event_Ipc_Handler *ipc_h; + + /* init some of the time variables */ + time1 = ecore_get_time(); + time2 = time1 - prev_time; + prev_time = time1; + while (__quit_ev_loop == 0) + { + /* state setup */ + timed_out = 0; + were_events = 0; + + /* setup fd array from list of listening fd's */ + fdsize = 0; + FD_ZERO(&fdset); + /* for ever fd handler add the fd to the array and incriment fdsize */ + for (fd_h = fd_handlers; fd_h; fd_h = fd_h->next) + { + FD_SET(fd_h->fd, &fdset); + if (fd_h->fd > fdsize) + fdsize = fd_h->fd; + } + fdcount = 1; + ipcsize = 0; + FD_ZERO(&ipcset); + /* for ever fd handler add the fd to the array and incriment fdsize */ + for (ipc_h = ipc_handlers; ipc_h; ipc_h = ipc_h->next) + { + FD_SET(ipc_h->ipc, &ipcset); + if (ipc_h->ipc > ipcsize) + ipcsize = ipc_h->ipc; + } + ipccount = 1; + /* if there are timers setup adjust timeout value and select */ + if (timers) + { + if (timers->just_added) + { + timers->just_added = 0; + time1 = timers->in; + } + else + { + time1 = timers->in - time2; + if (time1 < 0.0) + time1 = 0.0; + timers->in = time1; + } + tval.tv_sec = (long)time1; + tval.tv_usec = (long)((time1 - ((double)tval.tv_sec)) * 1000000); + if (tval.tv_sec < 0) + tval.tv_sec = 0; + if (tval.tv_usec <= 1000) + tval.tv_usec = 1000; + ecore_handle_zero_event_timer(); + if ((!ecore_events_pending()) && (!ecore_event_signal_events_pending())) + fdcount = select(fdsize + 1, &fdset, NULL, NULL, &tval); + } + /* no timers - just sit and block */ + else + { + if ((!ecore_events_pending()) && (!ecore_event_signal_events_pending())) + fdcount = select(fdsize + 1, &fdset, NULL, NULL, NULL); + } + for (pid_h = pid_handlers; pid_h; pid_h = pid_h->next) + pid_h->func(pid_h->pid); + + /* see if we have any new ipc connections */ + tval.tv_sec = 0; + tval.tv_usec = 0; + ipccount += select(ipcsize + 1, &ipcset, NULL, NULL, &tval); + + /* return < 0 - error or signal interrupt */ + if (fdcount < 0) + { + /* error */ + if ((errno == ENOMEM) || (errno == EINVAL) || (errno == EBADF)) + { + fprintf(stderr, "Lost connection to X display.\n"); + exit(1); + } + } + /* timers are available and its a timeout */ + if ((timers) && (fdcount == 0)) + { + ecore_handle_event_timer(); + timed_out = 1; + } + if (fdcount < 0) + fdcount = 0; + if (ecore_events_pending()) + { + fdcount++; + FD_SET(ecore_x_get_fd(), &fdset); + } + /* fd's are active */ + if (fdcount > 0) + { + /* for every fd handler - if its fd is set - call the func */ + for (fd_h = fd_handlers; fd_h;) + { + Ecore_Event_Fd_Handler *fdh; + + fdh = fd_h; + fd_h = fd_h->next; + if (FD_ISSET(fdh->fd, &fdset)) + fdh->func(fdh->fd); + } + } + + /* ipc clients are active */ + if (ipccount > 0) + { + for (ipc_h = ipc_handlers; ipc_h;) + { + Ecore_Event_Ipc_Handler *ipch; + + ipch = ipc_h; + ipc_h = ipc_h->next; + if (FD_ISSET(ipch->ipc, &ipcset)) + ipch->func(ipch->ipc); + } + } + if (events) + ecore_event_filter(events); + if (events) + { + ecore_event_filter_events_handle(events); + were_events = 1; + } + ecore_del_all_events(); + if ((timed_out) || (were_events)) + ecore_event_filter_idle_handle(); + ecore_flush(); + time1 = ecore_get_time(); + time2 = time1 - prev_time; + prev_time = time1; + } + __quit_ev_loop = 0; +} + +/* set a flag to 0 so that we can quit the event loop and shutdown + * properly */ +void +ecore_event_loop_quit(void) +{ + __quit_ev_loop = 1; +} + +/* add a timeout funcitont o be called in "in" seconds with name name */ +void +ecore_add_event_timer(char *name, double in, void (*func) (int val, void *data), + int val, void *data) +{ + Ecore_Event_Timer *timer, *ptr, *pptr; + double tally; + + if (name) + ecore_del_event_timer(name); + timer = NEW(Ecore_Event_Timer, 1); + timer->next = NULL; + timer->func = func; + timer->data = data; + timer->val = val; + timer->just_added = 1; + timer->in = in; + timer->name = strdup(name); + if (!timers) + timers = timer; + else + { + pptr = NULL; + ptr = timers; + tally = 0.0; + while (ptr) + { + tally += ptr->in; + if (tally > in) + { + tally -= ptr->in; + timer->next = ptr; + if (pptr) + pptr->next = timer; + else + timers = timer; + timer->in -= tally; + if (timer->next) + timer->next->in -= timer->in; + return; + } + pptr = ptr; + ptr = ptr->next; + } + if (pptr) + pptr->next = timer; + else + timers = timer; + timer->in -= tally; + } +} + +/* delete a timer timeout entry named "name" */ +void * +ecore_del_event_timer(char *name) +{ + Ecore_Event_Timer *timer, *ptr, *pptr; + + pptr = NULL; + ptr = timers; + while (ptr) + { + timer = ptr; + if (!strcmp(timer->name, name)) + { + void *data; + + if (pptr) + pptr->next = timer->next; + else + timers = timer->next; + if (timer->next) + timer->next->in += timer->in; + IF_FREE(timer->name); + data = timer->data; + FREE(timer); + return data; + } + pptr = ptr; + ptr = ptr->next; + } + return NULL; +} + +/* private functions */ +static void +ecore_handle_event_timer(void) +{ + Ecore_Event_Timer *timer; + + if (!timers) + return; + timer = timers; + timers = timer->next; + (*(timer->func)) (timer->val, timer->data); + IF_FREE(timer->name); + FREE(timer); +} + +static void +ecore_handle_zero_event_timer(void) +{ + while ((timers) && (timers->in == 0.0)) + ecore_handle_event_timer(); +} diff --git a/ecore/src/e_ipc.c b/ecore/src/e_ipc.c new file mode 100644 index 0000000..2a6de2b --- /dev/null +++ b/ecore/src/e_ipc.c @@ -0,0 +1,187 @@ +#include "Ecore.h" +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +void ecore_ipc_init(char *path); +void ecore_ipc_cleanup(void); +static void ecore_ipc_connect_handler(int fd); +static void ecore_ipc_client_handler(int fd); +void ecore_ipc_get_data(int fd, void *buf); +void ecore_ipc_send_data(int fd, void *buf, int size); +void ecore_add_ipc_service(int service, void (*func) (int fd)); +void ecore_del_ipc_service(int service); + +Ecore_Event_Ipc_Service *ipc_services = NULL; + +void +ecore_ev_ipc_init(char *path) +{ + int fd, len; + struct sockaddr_un saun; + + if (path == NULL) + return; + + /* a UNIX domain, stream socket */ + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + { + printf("Cannot create ipc socket... disabling ipc.\n"); + return; + } + + /* create the address we will be binding to */ + saun.sun_family = AF_UNIX; + strcpy(saun.sun_path, path); + + /* unlink the address so the bind won't fail */ + unlink(path); + len = sizeof(saun.sun_family) + strlen(saun.sun_path); + + if (bind(fd, (struct sockaddr *)&saun, len) < 0) + { + printf("Cannot bind ipc socket... disabling ipc.\n"); + return; + } + + /* listen on the socket */ + if (listen(fd, 5) < 0) + { + printf("Cannot listen on ipc socket... disabling ipc.\n"); + return; + } + + /* add ipc listener */ + ecore_add_event_ipc(fd, ecore_ipc_connect_handler); +} + +void +ecore_ev_ipc_cleanup(void) +{ + Ecore_Event_Ipc_Service *ipc_s; + + /* cleanup services list */ + for (ipc_s = ipc_services; ipc_s; ipc_s = ipc_s->next) + { + ecore_del_ipc_service(ipc_s->service); + } +} + +static void +ecore_ipc_connect_handler(int fd) +{ + struct sockaddr_un fsaun; + int fromlen, nfd; + + /* accept ipc connection */ + fromlen = sizeof(fsaun); + + if ((nfd = accept(fd, (struct sockaddr *)&fsaun, &fromlen)) < 0) + { + printf("Cannot accept ipc connection... ignoring connection attempt.\n"); + return; + } + + /* add ipc client */ + ecore_add_event_ipc(nfd, ecore_ipc_client_handler); +} + +static void +ecore_ipc_client_handler(int fd) +{ + int nread, service; + Ecore_Event_Ipc_Service *ipc_s; + + if ((nread = read(fd, &service, sizeof(service))) == 0) + { + close(fd); + ecore_del_event_ipc(fd); + } + else if (nread > 0) + { + /* call the service function */ + for (ipc_s = ipc_services; ipc_s; ipc_s = ipc_s->next) + { + if (ipc_s->service == service) + { + ipc_s->func(fd); + break; + } + } + } + else + { + printf("ipc error in read service.\n"); + fflush(stdout); + } +} + +void +ecore_ipc_get_data(int fd, void *buf) +{ + int readn, nread; + + /* read number of bytes being sent */ + if ((nread = read(fd, &readn, sizeof(readn))) == -1) + { + printf("ipc error in get data.\n"); + fflush(stdout); + return; + } + + /* get data structure */ + if ((nread = read(fd, buf, readn)) == -1) + { + printf("ipc error in get data.\n"); + fflush(stdout); + return; + } +} + +void +ecore_ipc_send_data(int fd, void *buf, int size) +{ + int n; + + /* send length of data being sent */ + if ((n = write(fd, &size, sizeof(size))) == -1) + { + printf("ipc error in send data length.\n"); + fflush(stdout); + return; + } + + /* send data */ + if ((n = write(fd, buf, size)) == -1) + { + printf("ipc error in send data.\n"); + fflush(stdout); + return; + } +} + +void +ecore_add_ipc_service(int service, void (*func) (int fd)) +{ + Ecore_Event_Ipc_Service *ipc_s; + + /* delete the old service */ + ecore_del_ipc_service(service); + /* new service struct */ + ipc_s = NEW(Ecore_Event_Ipc_Service, 1); + ipc_s->next = ipc_services; + ipc_s->service = service; + ipc_s->func = func; + ipc_services = ipc_s; +} + +void +ecore_del_ipc_service(int service) +{ + START_LIST_DEL(Ecore_Event_Ipc_Service, ipc_services, + (_p->service == service)); + FREE(_p); + END_LIST_DEL; +} diff --git a/ecore/src/e_util.c b/ecore/src/e_util.c new file mode 100644 index 0000000..fc4a2ae --- /dev/null +++ b/ecore/src/e_util.c @@ -0,0 +1,10 @@ +#include "Ecore.h" + +double +ecore_get_time(void) +{ + struct timeval timev; + + gettimeofday(&timev, NULL); + return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000); +} diff --git a/ecore/src/e_x.c b/ecore/src/e_x.c new file mode 100644 index 0000000..b3d8069 --- /dev/null +++ b/ecore/src/e_x.c @@ -0,0 +1,3610 @@ +#include "Ecore.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifdef XA_CLIPBOARD +#define X_CLIPBOARD_SELECTION XA_CLIPBOARD(disp) +#define X_CLIPBOARD_PROP XA_CLIPBOARD(disp) +#else +#define X_CLIPBOARD_SELECTION XA_PRIMARY +#define X_CLIPBOARD_PROP XA_CUT_BUFFER0 +#endif + +typedef struct _window_list Window_List; + +struct _window_list +{ + Window win; + Window_List *next; +}; + +XContext xid_context = 0; + +static Display *disp; +static Visual *default_vis; +static Colormap default_cm; +static int default_depth; +static Window default_win; +static Window default_root; + +static int lock_scroll = 0; +static int lock_num = 0; +static int lock_caps = 0; + +static Window focused_win = 0; + +static int mod_shift = 0; +static int mod_ctrl = 0; +static int mod_alt = 0; +static int mod_win = 0; + +static Window grabkey_win = 0; + +static int mouse_x = 0, mouse_y = 0; + +static Window current_dnd_win = 0; +static int current_dnd_target_ok = 0; +static int dnd_await_target_status = 0; + +static int x_grabs = 0; + +static Window_List *ignore_wins = NULL; + +static Window grab_pointer_win = 0; + +static Window keyboard_grab_win = 0; + +static int dnd_copy = 0; +static int dnd_link = 0; +static int dnd_move = 1; + +static void ecore_handle_x_error(Display * d, XErrorEvent * ev); +static void ecore_handle_x_io_error(Display * d); +static Window ecore_window_at_xy_0(Window base, int bx, int by, int x, + int y); + +static void +ecore_handle_x_error(Display * d, XErrorEvent * ev) +{ +/* + char err[16384]; + + XGetErrorText(d, ev->error_code, err, 16000); + printf("X Error:\n" + "Error: %s\nrequest: %i\nminor: %i\n", err, ev->request_code, ev->minor_code); + */ + /* ignore all X errors */ + return; + d = NULL; + ev = NULL; +} + +static void +ecore_handle_x_io_error(Display * d) +{ + /* FIXME: call clean exit handler */ + exit(1); + d = NULL; +} + +void +ecore_del_child(Window win, Window child) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + if (XFindContext(disp, win, xid_context, (XPointer *) & xid) == XCNOENT) + return; + if (xid) + { + int i; + + for (i = 0; i < xid->children_num; i++) + { + if (xid->children[i] == child) + { + int j; + + for (j = i; j < xid->children_num - 1; j++) + xid->children[j] = xid->children[j + 1]; + xid->children_num--; + REALLOC(xid->children, Window, xid->children_num); + return; + } + } + } +} + +void +ecore_add_child(Window win, Window child) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + if (XFindContext(disp, win, xid_context, (XPointer *) & xid) == XCNOENT) + return; + if (xid) + { + int i; + + for (i = 0; i < xid->children_num; i++) + { + if (xid->children[i] == child) + return; + } + xid->children_num++; + REALLOC(xid->children, Window, xid->children_num); + xid->children[xid->children_num - 1] = child; + } + xid = ecore_validate_xid(child); +} + +void +ecore_raise_child(Window win, Window child) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + if (XFindContext(disp, win, xid_context, (XPointer *) & xid) == XCNOENT) + return; + if (xid) + { + int i; + + for (i = 0; i < xid->children_num; i++) + { + if (xid->children[i] == child) + { + int j; + + for (j = i; j < xid->children_num - 1; j++) + xid->children[j] = xid->children[j + 1]; + xid->children[xid->children_num - 1] = child; + return; + } + } + } +} + +void +ecore_lower_child(Window win, Window child) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + if (XFindContext(disp, win, xid_context, (XPointer *) & xid) == XCNOENT) + return; + if (xid) + { + int i; + + for (i = 0; i < xid->children_num; i++) + { + if (xid->children[i] == child) + { + int j; + + for (j = i; j > 0; j--) + xid->children[j] = xid->children[j - 1]; + xid->children[0] = child; + return; + } + } + } +} + +Ecore_XID * +ecore_add_xid(Window win, int x, int y, int w, int h, int depth, Window parent) +{ + Ecore_XID *xid = NULL; + + ecore_window_add_events(win, XEV_IN_OUT | XEV_CONFIGURE | XEV_VISIBILITY); + xid = NEW(Ecore_XID, 1); + xid->win = win; + xid->x = x; + xid->y = y; + xid->w = w; + xid->h = h; + xid->mapped = 0; + xid->depth = depth; + xid->mouse_in = 0; + xid->parent = parent; + xid->root = ecore_window_get_root(parent); + xid->children_num = 0; + xid->children = NULL; + xid->gravity = ecore_window_get_gravity(win); + xid->coords_invalid = 0; + xid->bw = 0; + xid->grab_button_auto_replay = NULL; + XSaveContext(disp, xid->win, xid_context, (XPointer) xid); + ecore_add_child(parent, win); + return xid; +} + +Ecore_XID * +ecore_validate_xid(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return NULL; + if (XFindContext(disp, win, xid_context, (XPointer *) & xid) == XCNOENT) + { + XWindowAttributes att; + Window root_ret = 0, parent_ret = 0, *children_ret = NULL; + unsigned int children_ret_num = 0; + + ecore_window_add_events(win, XEV_IN_OUT | XEV_CONFIGURE | + XEV_VISIBILITY | XEV_CHILD_CHANGE); + xid = NEW(Ecore_XID, 1); + xid->win = win; + if (!XGetWindowAttributes(disp, win, &att)) + { + FREE(xid); + return NULL; + } + if (!XQueryTree(disp, win, &root_ret, &parent_ret, &children_ret, + &children_ret_num)) + { + FREE(xid); + return NULL; + } + xid->parent = parent_ret; + if (xid->parent) + ecore_validate_xid(xid->parent); + if (children_ret) + { + xid->children_num = children_ret_num; + xid->children = NEW(Window, children_ret_num); + MEMCPY(children_ret, xid->children, Window, children_ret_num); + XFree(children_ret); + } + else + { + xid->children_num = 0; + xid->children = NULL; + } + xid->root = root_ret; + xid->x = att.x; + xid->y = att.y; + xid->w = att.width; + xid->h = att.height; + if (att.map_state == IsUnmapped) + xid->mapped = 0; + else + xid->mapped = 1; + xid->depth = att.depth; + xid->mouse_in = 0; + xid->gravity = att.win_gravity; + xid->bw = att.border_width; + xid->coords_invalid = 0; + xid->grab_button_auto_replay = NULL; + XSaveContext(disp, xid->win, xid_context, (XPointer) xid); + ecore_add_child(xid->parent, win); + } + return xid; +} + +void +ecore_unvalidate_xid(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + if (XFindContext(disp, win, xid_context, (XPointer *) & xid) == XCNOENT) + return; + if (xid) + { + int i; + + for (i = 0; i < xid->children_num; i++) + ecore_unvalidate_xid(xid->children[i]); + ecore_del_child(xid->parent, win); + IF_FREE(xid->children); + FREE(xid); + XDeleteContext(disp, win, xid_context); + } +} + +void +ecore_sync(void) +{ + if (!disp) + return; + + XSync(disp, False); +} + +void +ecore_flush(void) +{ + if (!disp) + return; + XFlush(disp); +} + +Window +ecore_window_new(Window parent, int x, int y, int w, int h) +{ + Window win; + XSetWindowAttributes attr; + + if (!disp) + return 0; + if (!parent) + parent = default_root; + attr.backing_store = NotUseful; + attr.override_redirect = False; + attr.colormap = default_cm; + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.save_under = False; + attr.do_not_propagate_mask = True; + win = XCreateWindow(disp, parent, + x, y, w, h, 0, + default_depth, InputOutput, default_vis, + CWOverrideRedirect | CWSaveUnder | CWBackingStore | + CWColormap | CWBackPixmap | CWBorderPixel | + CWDontPropagate, &attr); + ecore_add_xid(win, x, y, w, h, default_depth, parent); + ecore_add_child(parent, win); + ecore_validate_xid(parent); + return win; +} + +Window +ecore_window_override_new(Window parent, int x, int y, int w, int h) +{ + Window win; + XSetWindowAttributes attr; + + if (!disp) + return 0; + if (!parent) + parent = default_root; + attr.backing_store = NotUseful; + attr.override_redirect = True; + attr.colormap = default_cm; + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.save_under = False; + attr.do_not_propagate_mask = True; + win = XCreateWindow(disp, parent, + x, y, w, h, 0, + default_depth, InputOutput, default_vis, + CWOverrideRedirect | CWSaveUnder | CWBackingStore | + CWColormap | CWBackPixmap | CWBorderPixel | + CWDontPropagate, &attr); + ecore_add_xid(win, x, y, w, h, default_depth, parent); + ecore_add_child(parent, win); + ecore_validate_xid(parent); + return win; +} + +Window +ecore_window_input_new(Window parent, int x, int y, int w, int h) +{ + Window win; + XSetWindowAttributes attr; + + if (!disp) + return 0; + if (!parent) + parent = default_root; + attr.override_redirect = True; + attr.do_not_propagate_mask = True; + win = XCreateWindow(disp, parent, + x, y, w, h, 0, + 0, InputOnly, default_vis, + CWOverrideRedirect | CWDontPropagate, &attr); + ecore_add_xid(win, x, y, w, h, 0, parent); + ecore_add_child(parent, win); + ecore_validate_xid(parent); + return win; +} + +void +ecore_window_set_events_propagate(Window win, int propagate) +{ + XSetWindowAttributes attr; + + if (!disp) + return; + if (!win) + win = default_root; + if (!propagate) + attr.do_not_propagate_mask = True; + else + attr.do_not_propagate_mask = False; + XChangeWindowAttributes(disp, win, CWDontPropagate, &attr); +} + +void +ecore_window_show(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + xid = ecore_validate_xid(win); + if (xid) + { + if (xid->mapped) + return; + xid->mapped = 1; + XMapWindow(disp, win); + } +} + +void +ecore_window_hide(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) + return; + xid = ecore_validate_xid(win); + if (xid) + { + if (!xid->mapped) + return; + xid->mapped = 0; + XUnmapWindow(disp, win); + } +} + +Pixmap +ecore_pixmap_new(Window win, int w, int h, int dep) +{ + if (!disp) + return 0; + if (!win) + win = default_win; + if (dep == 0) + dep = default_depth; + return XCreatePixmap(disp, win, w, h, dep); +} + +void +ecore_pixmap_free(Pixmap pmap) +{ + if (!disp) + return; + if (!pmap) + return; + XFreePixmap(disp, pmap); +} + +void +ecore_window_set_background_pixmap(Window win, Pixmap pmap) +{ + if (!disp) + return; + if (win == 0) + win = default_root; + XSetWindowBackgroundPixmap(disp, win, pmap); +} + +void +ecore_window_set_shape_mask(Window win, Pixmap mask) +{ + if (!disp) + return; + XShapeCombineMask(disp, win, ShapeBounding, 0, 0, mask, ShapeSet); +} + +void +ecore_window_add_shape_mask(Window win, Pixmap mask) +{ + if (!disp) + return; + XShapeCombineMask(disp, win, ShapeBounding, 0, 0, mask, ShapeUnion); +} + +void +ecore_window_set_shape_window(Window win, Window src, int x, int y) +{ + if (!disp) + return; + XShapeCombineShape(disp, win, ShapeBounding, x, y, src, ShapeBounding, + ShapeSet); +} + +void +ecore_window_add_shape_window(Window win, Window src, int x, int y) +{ + if (!disp) + return; + XShapeCombineShape(disp, win, ShapeBounding, x, y, src, ShapeBounding, + ShapeUnion); +} + +void +ecore_window_set_shape_rectangle(Window win, int x, int y, int w, int h) +{ + XRectangle rect; + + if (!disp) + return; + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, + Unsorted); +} + +void +ecore_window_add_shape_rectangle(Window win, int x, int y, int w, int h) +{ + XRectangle rect; + + if (!disp) + return; + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, + Unsorted); +} + +void +ecore_window_set_shape_rectangles(Window win, XRectangle * rect, int num) +{ + if (!disp) + return; + XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rect, num, ShapeSet, + Unsorted); +} + +void +ecore_window_add_shape_rectangles(Window win, XRectangle * rect, int num) +{ + if (!disp) + return; + XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rect, num, ShapeUnion, + Unsorted); +} + +void +ecore_window_clip_shape_by_rectangle(Window win, int x, int y, int w, int h) +{ + XRectangle rect; + + if (!disp) + return; + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, &rect, 1, + ShapeIntersect, Unsorted); +} + +XRectangle * +ecore_window_get_shape_rectangles(Window win, int *num) +{ + int ord; + + if (!disp) + return NULL; + return XShapeGetRectangles(disp, win, ShapeBounding, num, &ord); +} + +void +ecore_window_select_shape_events(Window win) +{ + if (!disp) + return; + + XShapeSelectInput(disp, win, ShapeNotifyMask); +} + +void +ecore_window_unselect_shape_events(Window win) +{ + if (!disp) + return; + + XShapeSelectInput(disp, win, 0); +} + +void +ecore_window_clear(Window win) +{ + if (!disp) + return; + if (win == 0) + win = default_root; + XClearWindow(disp, win); +} + +void +ecore_window_clear_area(Window win, int x, int y, int w, int h) +{ + if (!disp) + return; + if (win == 0) + win = default_root; + XClearArea(disp, win, x, y, w, h, False); +} + +void +ecore_pointer_xy(Window win, int *x, int *y) +{ + Window dw; + unsigned int dm; + int wx, wy; + + if (!disp) + return; + + if (win == 0) + win = default_root; + + XQueryPointer(disp, win, &dw, &dw, &mouse_x, &mouse_y, &wx, &wy, &dm); + + if (x) + *x = wx; + if (y) + *y = wy; +} + +void +ecore_pointer_xy_set(int x, int y) +{ + if (!disp) return; + mouse_x = x; + mouse_y = y; +} + +void +ecore_pointer_xy_get(int *x, int *y) +{ + if (!disp) return; + if (x) + *x = mouse_x; + if (y) + *y = mouse_y; +} + +void +ecore_window_set_events(Window win, long mask) +{ + if (!disp) return; + if (win == 0) + win = default_root; + XSelectInput(disp, win, mask); +} + +void +ecore_window_remove_events(Window win, long mask) +{ + XWindowAttributes att; + + if (!disp) return; + if (win == 0) + win = default_root; + if (XGetWindowAttributes(disp, win, &att) == True) + { + mask = att.your_event_mask & (~mask); + ecore_window_set_events(win, mask); + } +} + +void +ecore_window_add_events(Window win, long mask) +{ + XWindowAttributes att; + + if (!disp) return; + if (win == 0) + win = default_root; + if (XGetWindowAttributes(disp, win, &att) == True) + { + mask = att.your_event_mask | mask; + ecore_window_set_events(win, mask); + } +} + +void +ecore_window_move(Window win, int x, int y) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + if (!xid->coords_invalid) + { + if ((xid->x == x) && (xid->y == y)) + return; + } + xid->x = x; + xid->y = y; + xid->coords_invalid = 0; + XMoveWindow(disp, win, x, y); + } +} + +#define REGRAVITATE \ +if (xid->children) \ +{ \ + int j; \ +\ + for (j = 0; j < xid->children_num; j++) \ + { \ + Ecore_XID *xid2; \ +\ + xid2 = ecore_validate_xid(xid->children[j]); \ + if (xid2) \ + { \ + xid2->coords_invalid = 1; \ + } \ + } \ +} + +#if 0 +switch (xid2->gravity) + { + case UnmapGravity: + xid2->mapped = 0; + break; + case NorthWestGravity: + break; + case NorthGravity: + xid2->x += (w - xid->w) / 2; + break; + case NorthEastGravity: + xid2->x += (w - xid->w); + break; + case WestGravity: + xid2->h += (h - xid->h) / 2; + break; + case CenterGravity: + xid2->x += (w - xid->w) / 2; + xid2->h += (h - xid->h) / 2; + break; + case EastGravity: + xid2->x += (w - xid->w); + break; + case SouthWestGravity: + xid2->y += (h - xid->h); + break; + case SouthGravity: + xid2->x += (w - xid->w) / 2; + xid2->y += (h - xid->h); + break; + case SouthEastGravity: + xid2->x += (w - xid->w); + xid2->y += (h - xid->h); + break; + case StaticGravity: + xid2->coords_invalid = 1; + break; + default: + break; + } +} +} +} +#endif + +void +ecore_window_resize(Window win, int w, int h) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + if (!xid->coords_invalid) + { + if ((xid->w == w) && (xid->h == h)) + return; + } + REGRAVITATE; + xid->w = w; + xid->h = h; + xid->coords_invalid = 0; + XResizeWindow(disp, win, w, h); + } +} + +void +ecore_window_move_resize(Window win, int x, int y, int w, int h) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + if (!xid->coords_invalid) + { + if ((xid->x == x) && (xid->y == y) && (xid->w == w) && (xid->h == h)) + return; + } + REGRAVITATE; + xid->x = x; + xid->y = y; + xid->w = w; + xid->h = h; + xid->coords_invalid = 0; + XMoveResizeWindow(disp, win, x, y, w, h); + } +} + +int +ecore_x_get_fd(void) +{ + if (!disp) return 0; + return ConnectionNumber(disp); +} + +void +ecore_set_error_handler(Ecore_Error_Function func) +{ + if (!disp) return; + XSetErrorHandler((XErrorHandler) func); +} + +void +ecore_reset_error_handler(void) +{ + if (!disp) return; + XSetErrorHandler((XErrorHandler) ecore_handle_x_error); +} + +int +ecore_display_init(char *display) +{ + int revert; + + xid_context = XUniqueContext(); + disp = XOpenDisplay(display); + if (!disp) + { + char *d; + + d = getenv("DISPLAY"); +/* no need for this anymore + if (d) + fprintf(stderr, + "Fatal Error:\n" + "Cannot connect to the display nominated by your DISPLAY variable:\n" + "%s\n" + "Try changing your DISPLAY variable like:\n" + "DISPLAY=host:0 application_name\n", d); + else + fprintf(stderr, + "Fatal Error:\n" + "No DISPLAY variable set so cannot determine display to connect to.\n" + "Try setting your DISPLAY variable like:\n" + "DISPLAY=host:0 appication_name\n"); +*/ + return 0; + } + XSetErrorHandler((XErrorHandler) ecore_handle_x_error); + XSetIOErrorHandler((XIOErrorHandler) ecore_handle_x_io_error); + default_vis = DefaultVisual(disp, DefaultScreen(disp)); + default_depth = DefaultDepth(disp, DefaultScreen(disp)); + default_cm = DefaultColormap(disp, DefaultScreen(disp)); + default_win = DefaultRootWindow(disp); + default_root = DefaultRootWindow(disp); + mod_shift = ecore_mod_mask_shift_get(); + mod_ctrl = ecore_mod_mask_ctrl_get(); + mod_alt = ecore_mod_mask_alt_get(); + mod_win = ecore_mod_mask_win_get(); + XGetInputFocus(disp, &focused_win, &revert); + ecore_window_set_events(default_root, XEV_KEY | XEV_IN_OUT | XEV_MOUSE_MOVE | + XEV_CONFIGURE | XEV_CHILD_CHANGE | XEV_PROPERTY | + XEV_COLORMAP | XEV_VISIBILITY); + ecore_pointer_xy(0, NULL, NULL); + return 1; +} + +int +ecore_events_pending(void) +{ + if (!disp) return 0; + return XPending(disp); +} + +void +ecore_get_next_event(XEvent * event) +{ + if (!disp) return; + XNextEvent(disp, event); +} + +int +ecore_event_shape_get_id(void) +{ + int base = -1, err_base; + + if (!disp) return 0; + XShapeQueryExtension(disp, &base, &err_base); + base += ShapeNotify; + return base; +} + +KeySym +ecore_key_get_keysym_from_keycode(KeyCode keycode) +{ + if (!disp) return 0; + return XKeycodeToKeysym(disp, keycode, 0); +} + +char * +ecore_key_get_string_from_keycode(KeyCode keycode) +{ + char *str; + + if (!disp) return strdup(""); + str = XKeysymToString(ecore_key_get_keysym_from_keycode(keycode)); + if (!str) + return strdup(""); + return strdup(str); +} + +void +ecore_event_allow(int mode, Time t) +{ + if (!disp) return; + XAllowEvents(disp, mode, t); +} + +int +ecore_lock_mask_scroll_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Scroll_Lock); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_lock_mask_num_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Num_Lock); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_lock_mask_caps_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Caps_Lock); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_mod_mask_shift_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Shift_L); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_mod_mask_ctrl_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Control_L); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_mod_mask_alt_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Alt_L); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_mod_mask_win_get(void) +{ + static int have_mask = 0; + static int mask = 0; + XModifierKeymap *mod; + KeyCode nl; + int i; + int masks[8] = { + ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, + Mod4Mask, Mod5Mask + }; + + if (!disp) return 0; + if (have_mask) + return mask; + mod = XGetModifierMapping(disp); + nl = XKeysymToKeycode(disp, XK_Meta_L); + if ((mod) && (mod->max_keypermod > 0)) + { + for (i = 0; i < (8 * mod->max_keypermod); i++) + { + if ((nl) && (mod->modifiermap[i] == nl)) + { + mask = masks[i / mod->max_keypermod]; + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + if (mask == ecore_mod_mask_alt_get()) + mask = 0; + if (mask == ecore_mod_mask_ctrl_get()) + mask = 0; + have_mask = 1; + return mask; + } + } + } + if (mod) + { + if (mod->modifiermap) + XFree(mod->modifiermap); + XFree(mod); + } + return 0; +} + +int +ecore_lock_mask_get(void) +{ + static int mask = 0; + Window root_ret, child_ret; + int root_x_ret, root_y_ret, win_x_ret, win_y_ret; + unsigned int mask_ret; + + if (!disp) return 0; + if (!mask) + mask = ecore_lock_mask_scroll_get() | ecore_lock_mask_num_get() | + ecore_lock_mask_caps_get(); + XQueryPointer(disp, default_root, &root_ret, &child_ret, &root_x_ret, + &root_y_ret, &win_x_ret, &win_y_ret, &mask_ret); + return (mask_ret & mask); +} + +int +ecore_modifier_mask_get(void) +{ + Window root_ret, child_ret; + int root_x_ret, root_y_ret, win_x_ret, win_y_ret; + unsigned int mask_ret; + + if (!disp) return 0; + XQueryPointer(disp, default_root, &root_ret, &child_ret, &root_x_ret, + &root_y_ret, &win_x_ret, &win_y_ret, &mask_ret); + return (mask_ret); +} + +Window +ecore_get_key_grab_win(void) +{ + if (!disp) return 0; + return grabkey_win; +} + +void +ecore_key_grab(char *key, Ecore_Event_Key_Modifiers mods, int anymod, int sync) +{ + KeyCode keycode; + int i, mod, mask_scroll, mask_num, mask_caps, masks[8], mode; + + if (!disp) return; + keycode = ecore_key_get_keycode(key); + mod = 0; + mode = GrabModeAsync; + if (sync) + mode = GrabModeSync; + if (!grabkey_win) + grabkey_win = default_root; + if (mods & ECORE_EVENT_KEY_MODIFIER_SHIFT) + mod |= ecore_mod_mask_shift_get(); + if (mods & ECORE_EVENT_KEY_MODIFIER_CTRL) + mod |= ecore_mod_mask_ctrl_get(); + if (mods & ECORE_EVENT_KEY_MODIFIER_ALT) + mod |= ecore_mod_mask_alt_get(); + if (mods & ECORE_EVENT_KEY_MODIFIER_WIN) + mod |= ecore_mod_mask_win_get(); + mask_scroll = ecore_lock_mask_scroll_get(); + mask_num = ecore_lock_mask_num_get(); + mask_caps = ecore_lock_mask_caps_get(); + masks[0] = 0; + masks[1] = mask_scroll; + masks[2] = mask_num; + masks[3] = mask_caps; + masks[4] = mask_scroll | mask_num; + masks[5] = mask_scroll | mask_caps; + masks[6] = mask_num | mask_caps; + masks[7] = mask_scroll | mask_num | mask_caps; + if (anymod) + XGrabKey(disp, keycode, AnyModifier, grabkey_win, False, mode, mode); + else + { + for (i = 0; i < 8; i++) + XGrabKey(disp, keycode, masks[i] | mod, grabkey_win, False, mode, mode); + } +} + +void +ecore_key_ungrab(char *key, Ecore_Event_Key_Modifiers mods, int anymod) +{ + KeyCode keycode; + + if (!disp) return; + keycode = ecore_key_get_keycode(key); + if (anymod) + XUngrabKey(disp, keycode, AnyModifier, default_root); + else + { + int i, mod, mask_scroll, mask_num, mask_caps, masks[8]; + + mod = 0; + if (mods & ECORE_EVENT_KEY_MODIFIER_SHIFT) + mod |= ecore_mod_mask_shift_get(); + if (mods & ECORE_EVENT_KEY_MODIFIER_CTRL) + mod |= ecore_mod_mask_ctrl_get(); + if (mods & ECORE_EVENT_KEY_MODIFIER_ALT) + mod |= ecore_mod_mask_alt_get(); + if (mods & ECORE_EVENT_KEY_MODIFIER_WIN) + mod |= ecore_mod_mask_win_get(); + mask_scroll = ecore_lock_mask_scroll_get(); + mask_num = ecore_lock_mask_num_get(); + mask_caps = ecore_lock_mask_caps_get(); + masks[0] = 0; + masks[1] = mask_scroll; + masks[2] = mask_num; + masks[3] = mask_caps; + masks[4] = mask_scroll | mask_num; + masks[5] = mask_scroll | mask_caps; + masks[6] = mask_num | mask_caps; + masks[7] = mask_scroll | mask_num | mask_caps; + for (i = 0; i < 8; i++) + XUngrabKey(disp, keycode, masks[i] | mod, grabkey_win); + } +} + +KeyCode +ecore_key_get_keycode(char *key) +{ + if (!disp) return 0; + return XKeysymToKeycode(disp, XStringToKeysym(key)); +} + +void +ecore_window_destroy(Window win) +{ + if (!disp) return; + ecore_unvalidate_xid(win); + XDestroyWindow(disp, win); +} + +void +ecore_window_reparent(Window win, Window parent, int x, int y) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + if (parent == 0) + parent = default_root; + XReparentWindow(disp, win, parent, x, y); + ecore_del_child(xid->parent, win); + ecore_add_child(parent, win); + xid->parent = parent; + xid->x = x; + xid->y = y; + } +} + +void +ecore_window_raise(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + XRaiseWindow(disp, win); + ecore_raise_child(xid->parent, win); + } +} + +void +ecore_window_lower(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + XLowerWindow(disp, win); + ecore_lower_child(xid->parent, win); + } +} + +void +ecore_window_get_geometry(Window win, int *x, int *y, int *w, int *h) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + if (win == 0) + win = default_root; + xid = ecore_validate_xid(win); + if ((xid) && (xid->coords_invalid)) + { + Window dw; + int rx, ry; + unsigned int rw, rh, di; + + XGetGeometry(disp, win, &dw, &rx, &ry, &rw, &rh, &di, &di); + xid->x = rx; + xid->y = ry; + xid->w = (int)rw; + xid->h = (int)rh; + xid->coords_invalid = 0; + } + if (xid) + { + if (x) + *x = xid->x; + if (y) + *y = xid->y; + if (w) + *w = xid->w; + if (h) + *h = xid->h; + } + else + { + if (x) + *x = 0; + if (y) + *y = 0; + if (w) + *w = 0; + if (h) + *h = 0; + } +} + +int +ecore_window_get_depth(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return 0; + if (win == 0) + win = default_root; + xid = ecore_validate_xid(win); + if (xid) + return xid->depth; + return -1; +} + +int +ecore_window_exists(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return 0; + xid = ecore_validate_xid(win); + if (xid) + return 1; + return 0; +} + +Window +ecore_window_get_parent(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return 0; + xid = ecore_validate_xid(win); + if (xid) + return xid->parent; + return 0; +} + +Window * +ecore_window_get_children(Window win, int *num) +{ + Ecore_XID *xid = NULL; + + if (!disp) return NULL; + if (win == 0) + win = default_root; + xid = ecore_validate_xid(win); + if (xid) + { + Window *wlist = NULL; + + *num = xid->children_num; + if (xid->children) + { + wlist = NEW(Window, xid->children_num); + MEMCPY(xid->children, wlist, Window, xid->children_num); + } + return wlist; + } + *num = 0; + return NULL; +} + +int +ecore_window_mouse_in(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return 0; + if (win == 0) + win = default_root; + xid = ecore_validate_xid(win); + if (xid) + return xid->mouse_in; + return 0; +} + +void +ecore_window_mouse_set_in(Window win, int in) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + if (win == 0) + win = default_root; + xid = ecore_validate_xid(win); + if (xid) + xid->mouse_in = in; +} + +Display * +ecore_display_get(void) +{ + return disp; +} + +Window +ecore_window_get_root(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return 0; + xid = ecore_validate_xid(win); + if (xid) + return xid->root; + return 0; +} + +void +ecore_lock_scroll_set(int onoff) +{ + lock_scroll = onoff; +} + +int +ecore_lock_scroll_get(void) +{ + return lock_scroll; +} + +void +ecore_lock_num_set(int onoff) +{ + lock_num = onoff; +} + +int +ecore_lock_num_get(void) +{ + return lock_num; +} + +void +ecore_lock_caps_set(int onoff) +{ + lock_caps = onoff; +} + +int +ecore_lock_caps_get(void) +{ + return lock_caps; +} + +void +ecore_mod_shift_set(int onoff) +{ + mod_shift = onoff; +} + +int +ecore_mod_shift_get(void) +{ + return mod_shift; +} + +void +ecore_mod_ctrl_set(int onoff) +{ + mod_ctrl = onoff; +} + +int +ecore_mod_ctrl_get(void) +{ + return mod_ctrl; +} + +void +ecore_mod_alt_set(int onoff) +{ + mod_alt = onoff; +} + +int +ecore_mod_alt_get(void) +{ + return mod_alt; +} + +void +ecore_mod_win_set(int onoff) +{ + mod_win = onoff; +} + +int +ecore_mod_win_get(void) +{ + return mod_win; +} + +void +ecore_focus_window_set(Window win) +{ + focused_win = win; +} + +Window +ecore_focus_window_get(void) +{ + return focused_win; +} + +void +ecore_focus_to_window(Window win) +{ + if (!disp) return; + if (win == 0) + win = default_root; + XSetInputFocus(disp, win, RevertToNone, CurrentTime); +} + +void +ecore_focus_mode_reset(void) +{ + if (!disp) return; + XSetInputFocus(disp, default_root, RevertToPointerRoot, CurrentTime); +} + +Atom +ecore_atom_get(char *name) +{ + if (!disp) return 0; + return XInternAtom(disp, name, False); +} + +void +ecore_window_set_delete_inform(Window win) +{ + static Atom protocols[1] = { 0 }; + + if (!disp) return; + ECORE_ATOM(protocols[0], "WM_DELETE_WINDOW"); + XSetWMProtocols(disp, win, protocols, 1); +} + +void +ecore_window_property_set(Window win, Atom type, Atom format, int size, + void *data, int number) +{ + if (!disp) return; + if (win == 0) + win = default_root; + if (size != 32) + XChangeProperty(disp, win, type, format, size, PropModeReplace, + (unsigned char *)data, number); + else + { + long *dat; + int i, *ptr; + + dat = NEW(long, number); + + for (ptr = (int *)data, i = 0; i < number; i++) + dat[i] = ptr[i]; + XChangeProperty(disp, win, type, format, size, PropModeReplace, + (unsigned char *)dat, number); + FREE(dat); + } +} + +void * +ecore_window_property_get(Window win, Atom type, Atom format, int *size) +{ + unsigned char *retval; + Atom type_ret; + unsigned long bytes_after, num_ret; + int format_ret; + void *data = NULL; + + if (!disp) + return NULL; + + retval = NULL; + if (win == 0) + win = default_root; + XGetWindowProperty(disp, win, type, 0, 0x7fffffffL, False, format, + &type_ret, &format_ret, &num_ret, &bytes_after, &retval); + if (retval) + { + if (format_ret == 32) + { + int i; + + *size = num_ret * sizeof(unsigned int); + + data = NEW(unsigned int, num_ret); + + for (i = 0; i < (int)num_ret; i++) + ((unsigned int *)data)[i] = ((unsigned long *)retval)[i]; + } + else if (format_ret == 16) + { + int i; + + *size = num_ret * sizeof(unsigned short); + + data = NEW(unsigned short, *size); + + for (i = 0; i < (int)num_ret; i++) + ((unsigned short *)data)[i] = ((unsigned short *)retval)[i]; + } + else if (format_ret == 8) + { + /* format_ret == 8 */ + *size = num_ret; + data = NEW(char, num_ret); + + if (data) + memcpy(data, retval, num_ret); + } + XFree(retval); + return data; + } + *size = 0; + return NULL; +} + +void +ecore_window_dnd_advertise(Window win) +{ + static Atom atom_xdndaware = 0; + int dnd_version = 3; + + if (!disp) return; + ECORE_ATOM(atom_xdndaware, "XdndAware"); + ecore_window_property_set(win, atom_xdndaware, XA_ATOM, 32, &dnd_version, 1); +} + +void +ecore_grab(void) +{ + if (!disp) + return; + + x_grabs++; + + if (x_grabs == 1) + XGrabServer(disp); +} + +void +ecore_ungrab(void) +{ + if (!disp) + return; + + x_grabs--; + + if (x_grabs == 0) + { + XUngrabServer(disp); + ecore_sync(); + } +} + +void +ecore_window_ignore(Window win) +{ + Window_List *w; + + if (!disp) return; + if (win == 0) + win = default_root; + w = NEW(Window_List, 1); + w->win = win; + w->next = ignore_wins; + ignore_wins = w; +} + +void +ecore_window_no_ignore(Window win) +{ + Window_List *w, *pw; + + if (!disp) return; + if (win == 0) + win = default_root; + for (pw = NULL, w = ignore_wins; w; pw = w, w = w->next) + { + if (w->win == win) + { + if (pw) + pw->next = w->next; + else + ignore_wins = w->next; + FREE(w); + return; + } + } +} + +int +ecore_window_is_ignored(Window win) +{ + Window_List *w; + + if (!disp) return 0; + if (win == 0) + win = default_root; + for (w = ignore_wins; w; w = w->next) + { + if (w->win == win) + return 1; + } + return 0; +} + +static Window +ecore_window_at_xy_0(Window base, int bx, int by, int x, int y) +{ + Window *list = NULL; + XWindowAttributes att; + Window child = 0, parent_win = 0, root_win = 0; + int i; + unsigned int ww, wh, num; + int wx, wy; + + if (!disp) return 0; + if ((!XGetWindowAttributes(disp, base, &att)) || + (att.map_state != IsViewable)) + return 0; + + wx = att.x; + wy = att.y; + ww = att.width; + wh = att.height; + + wx += bx; + wy += by; + + if (!((x >= wx) && (y >= wy) && (x < (int)(wx + ww)) && (y < (int)(wy + wh)))) + return 0; + + if (!XQueryTree(disp, base, &root_win, &parent_win, &list, &num)) + return base; + if (list) + { + for (i = num - 1;; i--) + { + if (!ecore_window_is_ignored(list[i])) + { + if ((child = ecore_window_at_xy_0(list[i], wx, wy, x, y)) != 0) + { + XFree(list); + return child; + } + } + if (!i) + break; + } + XFree(list); + } + return base; +} + +Window +ecore_window_get_at_xy(int x, int y) +{ + Window child; + + if (!disp) return 0; + ecore_grab(); + child = ecore_window_at_xy_0(default_root, 0, 0, x, y); + if (child) + { + ecore_ungrab(); + return child; + } + ecore_ungrab(); + return default_root; +} + +int +ecore_window_dnd_capable(Window win) +{ + static Atom atom_xdndaware = 0; + int dnd_version = 3; + int *atom_ret; + int size = 0; + + if (!disp) return 0; + ECORE_ATOM(atom_xdndaware, "XdndAware"); + atom_ret = ecore_window_property_get(win, atom_xdndaware, XA_ATOM, &size); + if ((atom_ret) && (size >= (int)sizeof(int))) + { + if (atom_ret[0] == dnd_version) + { + FREE(atom_ret); + return 1; + } + FREE(atom_ret); + } + return 0; +} + +void +ecore_window_dnd_handle_motion(Window source_win, int x, int y, int dragging) +{ + static Atom atom_xdndenter = 0; + static Atom atom_xdndleave = 0; + static Atom atom_xdnddrop = 0; + static Atom atom_xdndposition = 0; + static Atom atom_xdndactioncopy = 0; + static Atom atom_xdndactionmove = 0; + static Atom atom_xdndactionlink = 0; + static Atom atom_xdndactionask = 0; + static Atom atom_text_uri_list = 0; + static Atom atom_text_plain = 0; + static Atom atom_text_moz_url = 0; + static Atom atom_netscape_url = 0; + Window win; + XEvent xevent; + + if (!disp) return; + win = ecore_window_get_at_xy(x, y); + while ((win) && (!ecore_window_dnd_capable(win))) + win = ecore_window_get_parent(win); + ECORE_ATOM(atom_xdndenter, "XdndEnter"); + ECORE_ATOM(atom_xdndleave, "XdndLeave"); + ECORE_ATOM(atom_xdnddrop, "XdndDrop"); + ECORE_ATOM(atom_xdndposition, "XdndPosition"); + ECORE_ATOM(atom_xdndactioncopy, "XdndActionCopy"); + ECORE_ATOM(atom_xdndactionmove, "XdndActionMove"); + ECORE_ATOM(atom_xdndactionlink, "XdndActionLink"); + ECORE_ATOM(atom_xdndactionask, "XdndActionAsk"); + ECORE_ATOM(atom_text_uri_list, "text/uri-list"); + ECORE_ATOM(atom_text_plain, "text/plain"); + ECORE_ATOM(atom_text_moz_url, "text/x-moz-url"); + ECORE_ATOM(atom_netscape_url, "_NETSCAPE_URL"); + if ((win != current_dnd_win) && (current_dnd_win)) + { + /* send leave to old dnd win */ + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.format = 32; + xevent.xclient.window = current_dnd_win; + xevent.xclient.message_type = atom_xdndleave; + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + XSendEvent(disp, current_dnd_win, False, 0, &xevent); + } + if (win) + { + if (win != current_dnd_win) + { + /* send enter on new win */ + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdndenter; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = (3 << 24); + xevent.xclient.data.l[2] = atom_text_uri_list; + xevent.xclient.data.l[3] = atom_text_plain; + xevent.xclient.data.l[4] = atom_text_moz_url; + XSendEvent(disp, win, False, 0, &xevent); + ecore_clear_target_status(); + } + /* kjb cep */ + if(!dnd_await_target_status) + { + /* send position information */ + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdndposition; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = (3 << 24); + xevent.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff); + xevent.xclient.data.l[3] = CurrentTime; + if (dnd_copy) + xevent.xclient.data.l[4] = atom_xdndactioncopy; + else if (dnd_link) + xevent.xclient.data.l[4] = atom_xdndactionlink; + else if (dnd_move) + xevent.xclient.data.l[4] = atom_xdndactionmove; + else + xevent.xclient.data.l[4] = atom_xdndactionask; + XSendEvent(disp, win, False, 0, &xevent); + dnd_await_target_status = 1; + } + } + if (!dragging) + { + if (win) + { + if (current_dnd_target_ok) + { + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdnddrop; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = CurrentTime; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + XSendEvent(disp, win, False, 0, &xevent); + } + else + { + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdndleave; + xevent.xclient.format = 32; + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + XSendEvent(disp, win, False, 0, &xevent); + } + } + current_dnd_target_ok = 0; + } + current_dnd_win = win; +} + + +void +ecore_clear_target_status(void) +{ + dnd_await_target_status = 0; +} + + +int +ecore_dnd_selection_convert(Window win, Window req, Atom type) +{ + static Atom atom_xdndselection = 0; + static Atom atom_jxselectionwindowproperty = 0; + + if (!disp) return 0; + ECORE_ATOM(atom_xdndselection, "XdndSelection"); + ECORE_ATOM(atom_jxselectionwindowproperty, "JXSelectionWindowProperty"); + if (win == XGetSelectionOwner(disp, atom_xdndselection)) + { + XConvertSelection(disp, atom_xdndselection, type, + atom_jxselectionwindowproperty, req, CurrentTime); + return 1; + } + return 0; +} + +void * +ecore_dnd_selection_get(Window win, Window req, Atom type, int *size) +{ + unsigned char *data = NULL; + long bytes_read; + unsigned long remaining = 1; + + if (!disp) return NULL; + *size = 0; + bytes_read = 0; + while (remaining) + { + unsigned char *s; + Atom actual; + int format; + unsigned long count; + + s = NULL; + if (XGetWindowProperty(disp, win, type, bytes_read / 4, 0x10000, 1, + AnyPropertyType, &actual, &format, &count, + &remaining, &s) != Success) + { + /* error occured */ + XFree(s); + IF_FREE(data); + *size = 0; + return NULL; + } + if (s) + { + /* got some mroe data - append it */ + bytes_read += count; + if (!data) + data = NEW(char, bytes_read); + + else + REALLOC(data, char, bytes_read); + MEMCPY(s, data + (bytes_read - count), char, count); + + XFree(s); + } + } + *size = bytes_read; + return data; + req = 0; +} + +void +ecore_dnd_set_data(Window win) +{ + static Atom atom_xdndselection = 0; + + if (!disp) return; + ECORE_ATOM(atom_xdndselection, "XdndSelection"); + ecore_dnd_set_action(win); + XSetSelectionOwner(disp, atom_xdndselection, win, CurrentTime); +} + +void +ecore_dnd_set_action(Window win) +{ + static int atom_xdndactioncopy = 0; + static int atom_xdndactionmove = 0; + static int atom_xdndactionlink = 0; + static int atom_xdndactionask = 0; + static Atom atom_xdndactionlist = 0; + + if (!disp) return; + ECORE_ATOM(atom_xdndactioncopy, "XdndActionCopy"); + ECORE_ATOM(atom_xdndactionmove, "XdndActionMove"); + ECORE_ATOM(atom_xdndactionlink, "XdndActionLink"); + ECORE_ATOM(atom_xdndactionask, "XdndActionAsk"); + ECORE_ATOM(atom_xdndactionlist, "XdndActionList"); + if (dnd_copy) + ecore_window_property_set(win, atom_xdndactionlist, XA_ATOM, 32, + &atom_xdndactioncopy, 1); + else if (dnd_link) + ecore_window_property_set(win, atom_xdndactionlist, XA_ATOM, 32, + &atom_xdndactionlink, 1); + else if (dnd_move) + ecore_window_property_set(win, atom_xdndactionlist, XA_ATOM, 32, + &atom_xdndactionmove, 1); + else + ecore_window_property_set(win, atom_xdndactionlist, XA_ATOM, 32, + &atom_xdndactionask, 1); +} + +void +ecore_dnd_send_data(Window win, Window source_win, void *data, int size, + Atom dest_atom, int type) +{ + XEvent xevent; + static Atom atom_text_plain = 0; + static Atom atom_text_uri_list = 0; + static Atom atom_text_moz_url = 0; + static Atom atom_netscape_url = 0; + static Atom atom_xdndselection = 0; + Atom target; + + if (!disp) return; + ECORE_ATOM(atom_xdndselection, "XdndSelection"); + ECORE_ATOM(atom_text_uri_list, "text/uri-list"); + ECORE_ATOM(atom_text_plain, "text/plain"); + ECORE_ATOM(atom_text_moz_url, "text/x-moz-url"); + ECORE_ATOM(atom_text_moz_url, "_NETSCAPE_URL"); + ECORE_ATOM(atom_text_plain, "text/plain"); + if (type == DND_TYPE_URI_LIST) target = atom_text_uri_list; + else if (type == DND_TYPE_PLAIN_TEXT) target = atom_text_plain; + else if (type == DND_TYPE_MOZ_URL) target = atom_text_moz_url; + else if (type == DND_TYPE_NETSCAPE_URL) target = atom_netscape_url; + else target = 0; + ecore_window_property_set(win, dest_atom, target, 8, data, size); + xevent.xselection.type = SelectionNotify; + xevent.xselection.property = dest_atom; + xevent.xselection.display = disp; + xevent.xselection.requestor = win; + xevent.xselection.selection = atom_xdndselection; + xevent.xselection.target = target; + xevent.xselection.time = CurrentTime; + XSendEvent(disp, win, False, 0, &xevent); + return; + source_win = 0; +} + +void +ecore_dnd_set_mode_copy(void) +{ + dnd_copy = 1; + dnd_link = 0; + dnd_move = 0; +} + +void +ecore_dnd_set_mode_link(void) +{ + dnd_copy = 0; + dnd_link = 1; + dnd_move = 0; +} + +void +ecore_dnd_set_mode_move(void) +{ + dnd_copy = 0; + dnd_link = 0; + dnd_move = 1; +} + +void +ecore_dnd_set_mode_ask(void) +{ + dnd_copy = 0; + dnd_link = 0; + dnd_move = 0; +} + +void +ecore_dnd_own_selection(Window win) +{ + static Atom atom_xdndselection = 0; + static Atom atom_jxselectionwindowproperty = 0; + + if (!disp) return; + ECORE_ATOM(atom_xdndselection, "XdndSelection"); + ECORE_ATOM(atom_jxselectionwindowproperty, "JXSelectionWindowProperty"); + + if (!XSetSelectionOwner(disp, atom_xdndselection, win, CurrentTime)) + return; +} + +void +ecore_dnd_send_drop(Window win, Window source_win) +{ + static Atom atom_xdnddrop = 0; + XEvent xevent; + + if (!disp) return; + ECORE_ATOM(atom_xdnddrop, "XdndDrop"); + + ecore_dnd_own_selection(source_win); + + memset(&xevent, 0, sizeof(xevent)); + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdnddrop; + xevent.xclient.format = 32; + + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = CurrentTime; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + XSendEvent(disp, win, False, 0, &xevent); +} + +void +ecore_window_dnd_send_status_ok(Window source_win, Window win, int x, int y, + int w, int h) +{ + static Atom atom_xdndstatus = 0; + static Atom atom_xdndactioncopy = 0; + static Atom atom_xdndactionmove = 0; + static Atom atom_xdndactionlink = 0; + static Atom atom_xdndactionask = 0; + XEvent xevent; + + if (!disp) return; + ECORE_ATOM(atom_xdndstatus, "XdndStatus"); + ECORE_ATOM(atom_xdndactioncopy, "XdndActionCopy"); + ECORE_ATOM(atom_xdndactionmove, "XdndActionMove"); + ECORE_ATOM(atom_xdndactionlink, "XdndActionLink"); + ECORE_ATOM(atom_xdndactionask, "XdndActionAsk"); + memset(&xevent, 0, sizeof(xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdndstatus; + xevent.xclient.format = 32; + + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = 3; + xevent.xclient.data.l[2] = ((x << 16) & 0xffff0000) | (y & 0xffff); + xevent.xclient.data.l[3] = ((h << 16) & 0xffff0000) | (w & 0xffff); + if (dnd_copy) + xevent.xclient.data.l[4] = atom_xdndactioncopy; + else if (dnd_link) + xevent.xclient.data.l[4] = atom_xdndactionlink; + else if (dnd_move) + xevent.xclient.data.l[4] = atom_xdndactionmove; + else + xevent.xclient.data.l[4] = atom_xdndactionask; + XSendEvent(disp, win, False, 0, &xevent); +} + +void +ecore_window_dnd_send_finished(Window source_win, Window win) +{ + static Atom atom_xdndfinished = 0; + XEvent xevent; + + if (!disp) return; + ECORE_ATOM(atom_xdndfinished, "XdndFinished"); + memset(&xevent, 0, sizeof(xevent)); + + xevent.xany.type = ClientMessage; + xevent.xany.display = disp; + xevent.xclient.window = win; + xevent.xclient.message_type = atom_xdndfinished; + xevent.xclient.format = 32; + + xevent.xclient.data.l[0] = source_win; + xevent.xclient.data.l[1] = 0; + xevent.xclient.data.l[2] = 0; + xevent.xclient.data.l[3] = 0; + xevent.xclient.data.l[4] = 0; + XSendEvent(disp, win, False, 0, &xevent); +} + +void +ecore_window_dnd_ok(int ok) +{ + current_dnd_target_ok = ok; +} + +void +ecore_window_dnd_finished(void) +{ + current_dnd_win = 0; +} + +void +ecore_window_set_title(Window win, char *title) +{ + if (!disp) return; + XStoreName(disp, win, title); +} + +void +ecore_window_set_name_class(Window win, char *name, char *class) +{ + XClassHint hint; + + if (!disp) return; + hint.res_name = name; + hint.res_class = class; + XSetClassHint(disp, win, &hint); +} + +void +ecore_window_get_name_class(Window win, char **name, char **class) +{ + XClassHint xch; + + if (!disp) return; + if (name) + *name = NULL; + if (class) + *class = NULL; + if (XGetClassHint(disp, win, &xch)) + { + if (name) + { + if (xch.res_name) + *name = strdup(xch.res_name); + } + if (class) + { + if (xch.res_class) + *class = strdup(xch.res_class); + } + XFree(xch.res_name); + XFree(xch.res_class); + } +} + +void +ecore_window_get_hints(Window win, int *accepts_focus, int *initial_state, + Pixmap * icon_pixmap, Pixmap * icon_mask, + Window * icon_window, Window * window_group) +{ + XWMHints *hints; + + if (!disp) return; + hints = XGetWMHints(disp, win); + if (hints) + { + if ((hints->flags & InputHint) && (accepts_focus)) + { + if (hints->input) + *accepts_focus = 1; + else + *accepts_focus = 0; + } + if ((hints->flags & StateHint) && (initial_state)) + { + *initial_state = hints->initial_state; + } + if ((hints->flags & IconPixmapHint) && (icon_pixmap)) + { + *icon_pixmap = hints->icon_pixmap; + } + if ((hints->flags & IconMaskHint) && (icon_mask)) + { + *icon_mask = hints->icon_pixmap; + } + if ((hints->flags & IconWindowHint) && (icon_window)) + { + *icon_window = hints->icon_window; + } + if ((hints->flags & WindowGroupHint) && (window_group)) + { + *window_group = hints->window_group; + } + XFree(hints); + } +} + +char * +ecore_window_get_machine(Window win) +{ + XTextProperty xtp; + + if (!disp) return NULL; + if (XGetWMClientMachine(disp, win, &xtp)) + { + char *s; + + if (!xtp.value) + return NULL; + s = strdup(xtp.value); + XFree(xtp.value); + return s; + } + return NULL; +} + +char * +ecore_window_get_command(Window win) +{ + int cargc; + char **cargv; + + if (!disp) return NULL; + if (XGetCommand(disp, win, &cargv, &cargc)) + { + if (cargc > 0) + { + char *s; + int size, i; + + size = 0; + for (i = 0; i < cargc; i++) + size += strlen(cargv[i]); + size += cargc - 1; + s = NEW(char, size + 1); + s[0] = 0; + + strcpy(s, cargv[0]); + for (i = 1; i < cargc; i++) + { + strcat(s, " "); + strcat(s, cargv[i]); + } + XFreeStringList(cargv); + return s; + } + else + return NULL; + } + return NULL; +} + +char * +ecore_window_get_icon_name(Window win) +{ + XTextProperty xtp; + + if (!disp) return NULL; + if (XGetWMIconName(disp, win, &xtp)) + { + char *s; + + if (!xtp.value) + return NULL; + s = strdup(xtp.value); + XFree(xtp.value); + return s; + } + return NULL; +} + +void +ecore_window_set_min_size(Window win, int w, int h) +{ + XSizeHints hints; + long ret; + + if (!disp) return; + memset(&hints, 0, sizeof(XSizeHints)); + XGetWMNormalHints(disp, win, &hints, &ret); + hints.flags |= PMinSize | PSize | USSize; + hints.min_width = w; + hints.min_height = h; + XSetWMNormalHints(disp, win, &hints); +} + +void +ecore_window_set_max_size(Window win, int w, int h) +{ + XSizeHints hints; + long ret; + + if (!disp) return; + memset(&hints, 0, sizeof(XSizeHints)); + XGetWMNormalHints(disp, win, &hints, &ret); + hints.flags |= PMaxSize | PSize | USSize; + hints.max_width = w; + hints.max_height = h; + XSetWMNormalHints(disp, win, &hints); +} + +void +ecore_window_set_xy_hints(Window win, int x, int y) +{ + XSizeHints hints; + long ret; + + if (!disp) return; + memset(&hints, 0, sizeof(XSizeHints)); + XGetWMNormalHints(disp, win, &hints, &ret); + hints.flags |= PPosition | USPosition | PSize | USSize; + hints.x = x; + hints.y = y; + XSetWMNormalHints(disp, win, &hints); +} + +void +ecore_window_get_frame_size(Window win, int *l, int *r, int *t, int *b) +{ + static Atom atom_e_frame_size = 0; + int *data, size; + + if (!disp) return; + ECORE_ATOM(atom_e_frame_size, "_E_FRAME_SIZE"); + data = ecore_window_property_get(win, atom_e_frame_size, XA_CARDINAL, &size); + if (data) + { + if (size == (4 * sizeof(int))) + { + if (l) + *l = data[0]; + if (r) + *r = data[1]; + if (t) + *t = data[2]; + if (b) + *b = data[3]; + } + else + { + if (l) + *l = 0; + if (r) + *r = 0; + if (t) + *t = 0; + if (b) + *b = 0; + } + FREE(data); + } + else + { + if (l) + *l = 0; + if (r) + *r = 0; + if (t) + *t = 0; + if (b) + *b = 0; + } +} + +int +ecore_window_save_under(Window win) +{ + XSetWindowAttributes att; + XWindowAttributes gatt; + + if (!disp) return 0; + att.save_under = True; + XChangeWindowAttributes(disp, win, CWSaveUnder, &att); + XGetWindowAttributes(disp, win, &gatt); + return (gatt.save_under == True) ? 1 : 0; +} + +GC +ecore_gc_new(Drawable d) +{ + XGCValues gcv; + + if (!disp) return 0; + if (d == 0) + d = default_root; + return XCreateGC(disp, d, 0, &gcv); +} + +void +ecore_gc_free(GC gc) +{ + if (!disp) return; + XFreeGC(disp, gc); +} + +void +ecore_gc_set_fg(GC gc, int val) +{ + if (!disp) return; + XSetForeground(disp, gc, val); +} + +void +ecore_fill_rectangle(Drawable d, GC gc, int x, int y, int w, int h) +{ + if (!disp) return; + XFillRectangle(disp, d, gc, x, y, w, h); +} + +void +ecore_draw_rectangle(Drawable d, GC gc, int x, int y, int w, int h) +{ + if (!disp) return; + XDrawRectangle(disp, d, gc, x, y, w - 1, h - 1); +} + +void +ecore_draw_line(Drawable d, GC gc, int x1, int y1, int x2, int y2) +{ + if (!disp) return; + XDrawLine(disp, d, gc, x1, y1, x2, y2); +} + +void +ecore_draw_point(Drawable d, GC gc, int x, int y) +{ + if (!disp) return; + XDrawPoint(disp, d, gc, x, y); +} + +void +ecore_window_hint_set_layer(Window win, int layer) +{ + static Atom atom_win_layer = 0; + + if (!disp) return; + ECORE_ATOM(atom_win_layer, "_WIN_LAYER"); + ecore_window_property_set(win, atom_win_layer, XA_CARDINAL, 32, &layer, 1); +} + +void +ecore_window_hint_set_sticky(Window win, int sticky) +{ + static Atom atom_win_state = 0; + static Atom atom_win_hints = 0; + int data; + + if (!disp) return; + ECORE_ATOM(atom_win_state, "_WIN_STATE"); + ECORE_ATOM(atom_win_hints, "_WIN_HINTS"); + if (sticky) + { + data = ((1 << 0) | (1 << 8) | (1 << 9)); + ecore_window_property_set(win, atom_win_state, XA_CARDINAL, 32, &data, 1); + data = ((1 << 0) | (1 << 1) | (1 << 2)); + ecore_window_property_set(win, atom_win_hints, XA_CARDINAL, 32, &data, 1); + } + else + { + data = 0; + ecore_window_property_set(win, atom_win_state, XA_CARDINAL, 32, &data, 1); + ecore_window_property_set(win, atom_win_hints, XA_CARDINAL, 32, &data, 1); + } +} + +void +ecore_window_hint_set_borderless(Window win) +{ + static Atom atom_motif_wm_hints = 0; + int data[5]; + + if (!disp) return; + ECORE_ATOM(atom_motif_wm_hints, "_MOTIF_WM_HINTS"); + data[0] = 0x3; + data[1] = 0x0; + data[2] = 0x0; + data[3] = 0x2ada27b0; + data[4] = 0x2aabd6b0; + ecore_window_property_set(win, atom_motif_wm_hints, atom_motif_wm_hints, 32, + data, 5); +} + +void +ecore_grab_mouse(Window win, int confine, Cursor cursor) +{ + int ret; + + if (!disp) + return; + if (confine) + ret = XGrabPointer(disp, win, False, + XEV_BUTTON | XEV_MOUSE_MOVE | XEV_IN_OUT, + GrabModeAsync, GrabModeAsync, win, cursor, CurrentTime); + else + ret = XGrabPointer(disp, win, False, + XEV_BUTTON | XEV_MOUSE_MOVE | XEV_IN_OUT, + GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime); + if (ret == GrabSuccess) + grab_pointer_win = win; +} + +void +ecore_ungrab_mouse(void) +{ + if (!disp) return; + XUngrabPointer(disp, CurrentTime); + grab_pointer_win = 0; +} + +Window +ecore_grab_window_get(void) +{ + return grab_pointer_win; +} + +int +ecore_window_get_gravity(Window win) +{ + XWindowAttributes att; + + if (!disp) + return 0; + + XGetWindowAttributes(disp, win, &att); + return att.win_gravity; +} + +void +ecore_window_gravity_reset(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + XSetWindowAttributes att; + +/* if (xid->gravity != NorthWestGravity)*/ + { + att.win_gravity = NorthWestGravity; + XChangeWindowAttributes(disp, win, CWWinGravity, &att); + xid->gravity = NorthWestGravity; + xid->coords_invalid = 1; + } + } +} + +void +ecore_window_gravity_set(Window win, int gravity) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { +/* if (xid->gravity != gravity)*/ + { + XSetWindowAttributes att; + + att.win_gravity = gravity; + XChangeWindowAttributes(disp, win, CWWinGravity, &att); + xid->gravity = gravity; + xid->coords_invalid = 1; + } + } +} + +void +ecore_window_bit_gravity_set(Window win, int gravity) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + XSetWindowAttributes att; + + att.bit_gravity = gravity; + XChangeWindowAttributes(disp, win, CWBitGravity, &att); + } +} + +void +ecore_pointer_warp_by(int dx, int dy) +{ + if (!disp) return; + XWarpPointer(disp, None, None, 0, 0, 0, 0, dx, dy); +} + +void +ecore_pointer_warp_to(int x, int y) +{ + if (!disp) return; + XWarpPointer(disp, None, default_root, 0, 0, 0, 0, x, y); +} + +void +ecore_gc_set_include_inferiors(GC gc) +{ + XGCValues gcv; + + if (!disp) return; + gcv.subwindow_mode = IncludeInferiors; + XChangeGC(disp, gc, GCSubwindowMode, &gcv); +} + +void +ecore_area_copy(Drawable src, Drawable dest, GC gc, + int sx, int sy, int sw, int sh, int dx, int dy) +{ + if (!disp) return; + if (src == 0) + src = default_root; + if (dest == 0) + dest = default_root; + XCopyArea(disp, src, dest, gc, sx, sy, sw, sh, dx, dy); +} + +Window +ecore_window_root(void) +{ + return default_root; +} + +void +ecore_window_get_virtual_area(Window win, int *area_x, int *area_y) +{ + static Atom atom_win_area = 0; + int *data, size; + + if (!disp) return; + ECORE_ATOM(atom_win_area, "_WIN_AREA"); + data = ecore_window_property_get(win, atom_win_area, XA_CARDINAL, &size); + if (data) + { + if (size == (sizeof(int) * 2)) + { + if (area_x) + *area_x = data[0]; + if (area_y) + *area_y = data[1]; + } + FREE(data); + } +} + +void +ecore_get_virtual_area(int *area_x, int *area_y) +{ + static Atom atom_win_area = 0; + int *data, size; + + if (!disp) return; + ECORE_ATOM(atom_win_area, "_WIN_AREA"); + data = ecore_window_property_get(default_root, atom_win_area, XA_CARDINAL, &size); + if (data) + { + if (size == (sizeof(int) * 2)) + { + if (area_x) + *area_x = data[0]; + if (area_y) + *area_y = data[1]; + } + FREE(data); + } +} + +void +ecore_window_get_root_relative_location(Window win, int *x, int *y) +{ + int dx, dy; + Window parent; + Ecore_XID *xid = NULL; + + if (!disp) return; + if (win == 0) + win = default_root; + if (win == default_root) + { + if (x) + *x = 0; + if (y) + *y = 0; + return; + } + xid = ecore_validate_xid(win); + if (!xid) + { + if (x) + *x = 0; + if (y) + *y = 0; + return; + } + dx = 0; + dy = 0; + do + { + parent = xid->parent; + dx += xid->x; + dy += xid->y; + if (parent != default_root) + { + xid = ecore_validate_xid(parent); + if (!xid) + { + if (x) + *x = dx; + if (y) + *y = dy; + return; + } + } + } + while (parent != default_root); + if (x) + *x = dx; + if (y) + *y = dy; +} + +void +ecore_window_button_grab_auto_replay_set(Window win, int (*func) (Ecore_Event_Mouse_Down *ev)) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (!xid) return; + xid->grab_button_auto_replay = func; +} + +void * +ecore_window_button_grab_auto_replay_get(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return NULL; + xid = ecore_validate_xid(win); + if (!xid) return NULL; + return xid->grab_button_auto_replay; +} + +void +ecore_button_grab(Window win, int button, int events, + Ecore_Event_Key_Modifiers mod, int any_mod) +{ + unsigned int b; + unsigned int m; + unsigned int locks[8]; + int i; + + if (!disp) return; + b = button; + if (b == 0) + b = AnyButton; + m = 0; + if (any_mod) + m = AnyModifier; + else + { + if (mod & ECORE_EVENT_KEY_MODIFIER_SHIFT) + m |= ecore_mod_mask_shift_get(); + if (mod & ECORE_EVENT_KEY_MODIFIER_CTRL) + m |= ecore_mod_mask_ctrl_get(); + if (mod & ECORE_EVENT_KEY_MODIFIER_ALT) + m |= ecore_mod_mask_alt_get(); + if (mod & ECORE_EVENT_KEY_MODIFIER_WIN) + m |= ecore_mod_mask_win_get(); + } + locks[0] = 0; + locks[1] = ecore_lock_mask_caps_get(); + locks[2] = ecore_lock_mask_num_get(); + locks[3] = ecore_lock_mask_scroll_get(); + locks[4] = ecore_lock_mask_caps_get() | ecore_lock_mask_num_get(); + locks[5] = ecore_lock_mask_caps_get() | ecore_lock_mask_scroll_get(); + locks[6] = ecore_lock_mask_num_get() | ecore_lock_mask_scroll_get(); + locks[7] = + ecore_lock_mask_caps_get() | ecore_lock_mask_num_get() | + ecore_lock_mask_scroll_get(); + for (i = 0; i < 8; i++) + XGrabButton(disp, b, m | locks[i], + win, False, events, GrabModeSync, GrabModeAsync, None, None); +} + +void +ecore_button_ungrab(Window win, int button, Ecore_Event_Key_Modifiers mod, + int any_mod) +{ + unsigned int b; + unsigned int m; + unsigned int locks[8]; + int i; + + if (!disp) return; + b = button; + if (b == 0) + b = AnyButton; + m = 0; + if (any_mod) + m = AnyModifier; + else + { + if (mod & ECORE_EVENT_KEY_MODIFIER_SHIFT) + m |= ecore_mod_mask_shift_get(); + if (mod & ECORE_EVENT_KEY_MODIFIER_CTRL) + m |= ecore_mod_mask_ctrl_get(); + if (mod & ECORE_EVENT_KEY_MODIFIER_ALT) + m |= ecore_mod_mask_alt_get(); + if (mod & ECORE_EVENT_KEY_MODIFIER_WIN) + m |= ecore_mod_mask_win_get(); + } + locks[0] = 0; + locks[1] = ecore_lock_mask_caps_get(); + locks[2] = ecore_lock_mask_num_get(); + locks[3] = ecore_lock_mask_scroll_get(); + locks[4] = ecore_lock_mask_caps_get() | ecore_lock_mask_num_get(); + locks[5] = ecore_lock_mask_caps_get() | ecore_lock_mask_scroll_get(); + locks[6] = ecore_lock_mask_num_get() | ecore_lock_mask_scroll_get(); + locks[7] = + ecore_lock_mask_caps_get() | ecore_lock_mask_num_get() | + ecore_lock_mask_scroll_get(); + for (i = 0; i < 8; i++) + XUngrabButton(disp, b, m | locks[i], win); +} + +void +ecore_pointer_replay(Time t) +{ + if (!disp) return; + XSync(disp, False); + XAllowEvents(disp, ReplayPointer, t); + XSync(disp, False); +} + +void +ecore_pointer_grab(Window win, Time t) +{ + if (!disp) return; + XGrabPointer(disp, win, False, XEV_BUTTON | XEV_MOUSE_MOVE | XEV_IN_OUT, + GrabModeAsync, GrabModeAsync, None, None, t); +} + +void +ecore_pointer_ungrab(Time t) +{ + if (!disp) return; + XUngrabPointer(disp, t); +} + +void +ecore_window_send_event_move_resize(Window win, int x, int y, int w, int h) +{ + XEvent ev; + + if (!disp) return; + ev.type = ConfigureNotify; + ev.xconfigure.display = 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 = win; + ev.xconfigure.override_redirect = False; + XSendEvent(disp, win, False, StructureNotifyMask, &ev); +} + +void +ecore_window_send_client_message(Window win, Atom type, int format, void *data) +{ + XClientMessageEvent ev; + int i; + + if (!disp) return; + ev.type = ClientMessage; + ev.window = win; + ev.message_type = type; + ev.format = format; + if (format == 32) + { + for (i = 0; i < 5; i++) + ev.data.l[i] = ((unsigned int *)data)[i]; + } + else if (format == 16) + { + for (i = 0; i < 10; i++) + ev.data.s[i] = ((unsigned short *)data)[i]; + } + else if (format == 8) + { + for (i = 0; i < 20; i++) + ev.data.b[i] = ((unsigned char *)data)[i]; + } + XSendEvent(disp, win, False, 0, (XEvent *) & ev); +} + +void +ecore_window_add_to_save_set(Window win) +{ + if (!disp) return; + XAddToSaveSet(disp, win); +} + +void +ecore_window_del_from_save_set(Window win) +{ + if (!disp) return; + XRemoveFromSaveSet(disp, win); +} + +void +ecore_window_kill_client(Window win) +{ + if (!disp) return; + XKillClient(disp, (XID) win); +} + +void +ecore_window_set_border_width(Window win, int bw) +{ + Ecore_XID *xid = NULL; + + if (!disp) return; + xid = ecore_validate_xid(win); + if (xid) + { + xid->bw = bw; + } + XSetWindowBorderWidth(disp, win, bw); +} + +int +ecore_window_get_border_width(Window win) +{ + Ecore_XID *xid = NULL; + + if (!disp) return 0; + + xid = ecore_validate_xid(win); + if (xid) + { + return xid->bw; + } + + return 0; +} + +int +ecore_window_get_wm_size_hints(Window win, XSizeHints * hints, int *mask) +{ + long sup_ret; + Status ok; + + if (!disp) return 0; + + ok = XGetWMNormalHints(disp, win, hints, &sup_ret); + *mask = (int)sup_ret; + return ok; +} + +int +ecore_window_is_visible(Window win) +{ + XWindowAttributes att; + + if (!disp) return 0; + if (win == 0) + win = default_root; + if (XGetWindowAttributes(disp, win, &att) == True) + { + if (att.map_state == IsUnmapped) + return 0; + return 1; + } + return 0; +} + +int +ecore_window_is_normal(Window win) +{ + XWindowAttributes att; + + if (!disp) return 0; + if (win == 0) + win = default_root; + if (XGetWindowAttributes(disp, win, &att) == True) + { + if ((att.override_redirect) || (att.class == InputOnly)) + return 0; + return 1; + } + return 0; +} + +int +ecore_window_is_manageable(Window win) +{ + XWindowAttributes att; + + if (!disp) return 0; + if (win == 0) + win = default_root; + if (XGetWindowAttributes(disp, win, &att) == True) + { + if ((att.map_state == IsUnmapped) || (att.override_redirect) + || (att.class == InputOnly)) + return 0; + return 1; + } + return 0; +} + +void +ecore_windows_restack(Window * wins, int num) +{ + if (!disp) return; + XRestackWindows(disp, wins, num); +} + +void +ecore_window_stack_above(Window win, Window above) +{ + XWindowChanges xwc; + + if (!disp) return; + if (win == 0) + win = default_root; + xwc.sibling = above; + xwc.stack_mode = Above; + XConfigureWindow(disp, win, CWSibling | CWStackMode, &xwc); +} + +void +ecore_window_stack_below(Window win, Window below) +{ + XWindowChanges xwc; + + if (!disp) return; + + if (win == 0) + win = default_root; + xwc.sibling = below; + xwc.stack_mode = Below; + XConfigureWindow(disp, win, CWSibling | CWStackMode, &xwc); +} + +char * +ecore_window_get_title(Window win) +{ + XTextProperty xtp; + + if (!disp) return 0; + + if (win == 0) + win = default_root; + if (XGetWMName(disp, win, &xtp)) + { + int items; + char **list; + Status s; + char *title = NULL; + + if (xtp.format == 8) + { + s = XmbTextPropertyToTextList(disp, &xtp, &list, &items); + if ((s == Success) && (items > 0)) + { + title = strdup(*list); + XFreeStringList(list); + } + else + title = strdup((char *)xtp.value); + } + else + title = strdup((char *)xtp.value); + XFree(xtp.value); + return title; + } + return NULL; +} + +void +ecore_keyboard_grab(Window win) +{ + int status; + + if (!disp) return; + if (keyboard_grab_win) + return; + if (win == 0) + win = default_root; + keyboard_grab_win = win; + status = + XGrabKeyboard(disp, win, False, GrabModeAsync, GrabModeAsync, CurrentTime); + if ((status == AlreadyGrabbed) || (status == GrabNotViewable) + || (status == GrabFrozen) || (status == GrabInvalidTime)) + keyboard_grab_win = 0; +} + +void +ecore_keyboard_ungrab(void) +{ + if (!disp) return; + if (!keyboard_grab_win) + return; + keyboard_grab_win = 0; + XUngrabKeyboard(disp, CurrentTime); +} + +Window +ecore_keyboard_grab_window_get(void) +{ + if (!disp) return 0; + return keyboard_grab_win; +} + +Window +ecore_selection_set(char *string) +{ + Window target = 0; + static Atom dest = 0; + Atom selection; + + if (!disp) return 0; + selection = X_CLIPBOARD_SELECTION; + ECORE_ATOM(dest, "TEXT_SELECTION"); + target = ecore_window_new(0, 0, 0, 77, 7); + ecore_window_add_events(target, XEV_CONFIGURE | XEV_PROPERTY); + XSetSelectionOwner(disp, selection, target, CurrentTime); + if (XGetSelectionOwner(disp, XA_PRIMARY) != target) + { + ecore_window_destroy(target); + return 0; + } + XChangeProperty(disp, target, dest, + XA_STRING, 8, PropModeReplace, string, strlen(string)); + return target; +} + +Window +ecore_selection_request(void) +{ + static Atom dest = 0; + Atom selection; + Window target = 0; + + if (!disp) return 0; + selection = X_CLIPBOARD_SELECTION; + ECORE_ATOM(dest, "TEXT_SELECTION"); + target = ecore_window_new(0, 0, 0, 7, 77); + ecore_window_add_events(target, XEV_CONFIGURE | XEV_PROPERTY); + XConvertSelection(disp, XA_PRIMARY, XA_STRING, dest, target, CurrentTime); + return target; +} + +char * +ecore_selection_get_data(Window win, Atom prop) +{ + char *string = NULL; + long nread; + unsigned long bytes_after, nitems; + unsigned char *data; + Atom actual_type; + int actual_fmt; + + if (!disp) return NULL; + if (prop == None) + return NULL; + for (nread = 0, bytes_after = 1; bytes_after > 0;) + { + if ((XGetWindowProperty(disp, win, prop, nread / 4, + 0x10000, True, AnyPropertyType, + &actual_type, &actual_fmt, &nitems, + &bytes_after, &data) != Success)) + { + IF_FREE(string); + if (data) + { + XFree(data); + } + return NULL; + } + nread += nitems; + + if (actual_type == XA_STRING) + { + if (string) + string = realloc(string, strlen(string) + nitems + 1); + else + { + string = malloc(nitems + 1); + string[0] = 0; + } + string[strlen(string) + nitems] = 0; + strncat(string, data, nitems); + } + else + { + int size, i; + XTextProperty xtextp; + char **cl = NULL; + + xtextp.value = data; + xtextp.encoding = actual_type; + xtextp.format = actual_fmt; + xtextp.nitems = nitems; + XmbTextPropertyToTextList(disp, &xtextp, &cl, &size); + + if (cl) + { + for (i = 0; i < size; i++) + { + if (cl[i]) + { + if (string) + string = + realloc(string, strlen(string) + strlen(cl[i]) + 1); + else + { + string = malloc(strlen(cl[i]) + 1); + string[0] = 0; + } + string[strlen(string) + strlen(cl[i])] = 0; + strcat(string, cl[i]); + } + } + XFreeStringList(cl); + } + } + if (data) + { + XFree(data); + } + } + return string; +} + +void +ecore_set_blank_pointer(Window w) +{ + Cursor c; + XColor cl; + Pixmap p, m; + GC gc; + XGCValues gcv; + + if (!disp) return; + if (w == 0) + w = default_root; + p = XCreatePixmap(disp, w, 1, 1, 1); + m = XCreatePixmap(disp, w, 1, 1, 1); + gc = XCreateGC(disp, m, 0, &gcv); + XSetForeground(disp, gc, 0); + XDrawPoint(disp, m, gc, 0, 0); + XFreeGC(disp, gc); + c = XCreatePixmapCursor(disp, p, m, &cl, &cl, 0, 0); + XDefineCursor(disp, w, c); + XFreeCursor(disp, c); + XFreePixmap(disp, p); + XFreePixmap(disp, m); +} + +Cursor +ecore_cursor_new(Pixmap pmap, Pixmap mask, int x, int y, int fr, int fg, int fb, + int br, int bg, int bb) +{ + XColor cl1, cl2; + + if (!disp) return 0; + cl1.pixel = 0; + cl1.red = fr << 8 | fr; + cl1.green = fg << 8 | fg; + cl1.blue = fb << 8 | fb; + cl1.flags = DoRed | DoGreen | DoBlue; + cl2.pixel = 0; + cl2.red = br << 8 | br; + cl2.green = bg << 8 | bg; + cl2.blue = bb << 8 | bb; + cl2.flags = DoRed | DoGreen | DoBlue; + return XCreatePixmapCursor(disp, pmap, mask, &cl1, &cl2, x, y); +} + +void +ecore_cursor_free(Cursor c) +{ + if (!disp) return; + XFreeCursor(disp, c); +} + +void +ecore_cursor_set(Window win, Cursor c) +{ + if (!disp) return; + if (win == 0) + win = default_root; + XDefineCursor(disp, win, c); +} diff --git a/ecore/src/lib/.cvsignore b/ecore/src/lib/.cvsignore new file mode 100644 index 0000000..282522d --- /dev/null +++ b/ecore/src/lib/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/ecore/src/lib/CVS/Entries b/ecore/src/lib/CVS/Entries new file mode 100644 index 0000000..78afff1 --- /dev/null +++ b/ecore/src/lib/CVS/Entries @@ -0,0 +1,13 @@ +/.cvsignore/1.1/Thu Nov 13 12:30:47 2003//THEAD +/Makefile.am/1.8/Fri Apr 29 05:29:13 2005//THEAD +D/ecore//// +D/ecore_con//// +D/ecore_config//// +D/ecore_dbus//// +D/ecore_evas//// +D/ecore_fb//// +D/ecore_file//// +D/ecore_ipc//// +D/ecore_job//// +D/ecore_txt//// +D/ecore_x//// diff --git a/ecore/src/lib/CVS/Repository b/ecore/src/lib/CVS/Repository new file mode 100644 index 0000000..9ce7be3 --- /dev/null +++ b/ecore/src/lib/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib diff --git a/ecore/src/lib/CVS/Root b/ecore/src/lib/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/CVS/Tag b/ecore/src/lib/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/Makefile.am b/ecore/src/lib/Makefile.am new file mode 100644 index 0000000..8bfccd9 --- /dev/null +++ b/ecore/src/lib/Makefile.am @@ -0,0 +1,13 @@ +## Process this file with automake to produce Makefile.in +SUBDIRS = \ +ecore \ +ecore_job \ +ecore_txt \ +ecore_fb \ +ecore_con \ +ecore_x \ +ecore_ipc \ +ecore_evas \ +ecore_config \ +ecore_file \ +ecore_dbus diff --git a/ecore/src/lib/ecore/.cvsignore b/ecore/src/lib/ecore/.cvsignore new file mode 100644 index 0000000..78de274 --- /dev/null +++ b/ecore/src/lib/ecore/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +libecore.la diff --git a/ecore/src/lib/ecore/CVS/Entries b/ecore/src/lib/ecore/CVS/Entries new file mode 100644 index 0000000..0d13af0 --- /dev/null +++ b/ecore/src/lib/ecore/CVS/Entries @@ -0,0 +1,26 @@ +/.cvsignore/1.2/Mon Mar 29 21:11:30 2004//THEAD +/Ecore.h/1.23/Fri Apr 15 01:22:45 2005//THEAD +/Ecore_Data.h/1.14/Sat Apr 2 15:59:55 2005//THEAD +/Makefile.am/1.9/Thu Mar 10 15:19:36 2005//THEAD +/ecore.c/1.11/Mon Apr 11 15:43:44 2005//THEAD +/ecore_anim.c/1.3/Wed Mar 2 07:06:32 2005//THEAD +/ecore_app.c/1.5/Thu Nov 25 04:07:54 2004//THEAD +/ecore_events.c/1.18/Mon Jun 13 02:30:37 2005//THEAD +/ecore_exe.c/1.8/Thu Jul 7 03:31:34 2005//THEAD +/ecore_hash.c/1.11/Wed Mar 2 07:06:32 2005//THEAD +/ecore_idle_enterer.c/1.5/Sat May 8 04:44:03 2004//THEAD +/ecore_idle_exiter.c/1.3/Sat May 8 04:44:03 2004//THEAD +/ecore_idler.c/1.5/Sat May 8 04:44:03 2004//THEAD +/ecore_main.c/1.18/Mon Mar 28 09:00:08 2005//THEAD +/ecore_path.c/1.6/Tue Jan 4 22:45:05 2005//THEAD +/ecore_plugin.c/1.4/Wed Oct 20 17:51:27 2004//THEAD +/ecore_private.h/1.14/Sat May 28 03:57:17 2005//THEAD +/ecore_sheap.c/1.5/Sat Jan 29 02:13:12 2005//THEAD +/ecore_signal.c/1.16/Wed Mar 2 07:06:33 2005//THEAD +/ecore_time.c/1.5/Wed Oct 20 17:51:28 2004//THEAD +/ecore_timer.c/1.12/Mon Apr 4 16:01:39 2005//THEAD +/ecore_tree.c/1.4/Tue Jan 4 22:45:06 2005//THEAD +/ecore_value.c/1.5/Wed Mar 2 07:06:33 2005//THEAD +/ecore_list.c/1.16/Sat Jul 23 17:35:06 2005//THEAD +/ecore_strings.c/1.7/Sat Jul 23 17:35:06 2005//THEAD +D diff --git a/ecore/src/lib/ecore/CVS/Repository b/ecore/src/lib/ecore/CVS/Repository new file mode 100644 index 0000000..69e64ae --- /dev/null +++ b/ecore/src/lib/ecore/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore diff --git a/ecore/src/lib/ecore/CVS/Root b/ecore/src/lib/ecore/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore/CVS/Tag b/ecore/src/lib/ecore/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore/Ecore.h b/ecore/src/lib/ecore/Ecore.h new file mode 100644 index 0000000..308262d --- /dev/null +++ b/ecore/src/lib/ecore/Ecore.h @@ -0,0 +1,254 @@ +#ifndef _ECORE_H +#define _ECORE_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file Ecore.h + * @brief The file that provides the program utility, main loop and timer + * functions. + * + * This header provides the Ecore event handling loop. For more + * details, see @ref Ecore_Main_Loop_Group. + * + * For the main loop to be of any use, you need to be able to add events + * and event handlers. Events for file descriptor events are covered in + * @ref Ecore_FD_Handler_Group. + * + * Time functions are covered in @ref Ecore_Time_Group. + * + * There is also provision for callbacks for when the loop enters or + * exits an idle state. See @ref Idle_Group for more information. + * + * Functions are also provided for spawning child processes using fork. + * See @ref Ecore_Exe_Basic_Group and @ref Ecore_Exe_Signal_Group for + * more details. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <limits.h> +#include <signal.h> + +#include <Ecore_Data.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +#ifndef MIN +#define MIN(x, y) (((x) > (y)) ? (y) : (x)) +#endif + +#ifndef MAX +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif + +#ifndef ABS +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#endif + +#ifndef CLAMP +#define CLAMP(x, min, max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x))) +#endif + +#define ECORE_EVENT_NONE 0 +#define ECORE_EVENT_EXE_EXIT 1 /**< Spawned Exe has exit event */ +#define ECORE_EVENT_SIGNAL_USER 2 /**< User signal event */ +#define ECORE_EVENT_SIGNAL_HUP 3 /**< Hup signal event */ +#define ECORE_EVENT_SIGNAL_EXIT 4 /**< Exit signal event */ +#define ECORE_EVENT_SIGNAL_POWER 5 /**< Power signal event */ +#define ECORE_EVENT_SIGNAL_REALTIME 6 /**< Realtime signal event */ +#define ECORE_EVENT_COUNT 7 + +#ifndef _ECORE_PRIVATE_H + enum _Ecore_Fd_Handler_Flags + { + ECORE_FD_READ = 1, /**< Fd Read mask */ + ECORE_FD_WRITE = 2, /**< Fd Write mask */ + ECORE_FD_ERROR = 4 /**< Fd Error mask */ + }; + typedef enum _Ecore_Fd_Handler_Flags Ecore_Fd_Handler_Flags; + +#ifndef WIN32 + typedef void Ecore_Exe; /**< A handle for spawned processes */ +#endif + typedef void Ecore_Timer; /**< A handle for timers */ + typedef void Ecore_Idler; /**< A handle for idlers */ + typedef void Ecore_Idle_Enterer; /**< A handle for idle enterers */ + typedef void Ecore_Idle_Exiter; /**< A handle for idle exiters */ + typedef void Ecore_Fd_Handler; /**< A handle for Fd hanlders */ + typedef void Ecore_Event_Handler; /**< A handle for an event handler */ + typedef void Ecore_Event_Filter; /**< A handle for an event filter */ + typedef void Ecore_Event; /**< A handle for an event */ + typedef void Ecore_Animator; /**< A handle for animators */ +#endif + typedef struct _Ecore_Event_Exe_Exit Ecore_Event_Exe_Exit; /**< Spawned Exe exit event */ + typedef struct _Ecore_Event_Signal_User Ecore_Event_Signal_User; /**< User signal event */ + typedef struct _Ecore_Event_Signal_Hup Ecore_Event_Signal_Hup; /**< Hup signal event */ + typedef struct _Ecore_Event_Signal_Exit Ecore_Event_Signal_Exit; /**< Exit signal event */ + typedef struct _Ecore_Event_Signal_Power Ecore_Event_Signal_Power; /**< Power signal event */ + typedef struct _Ecore_Event_Signal_Realtime Ecore_Event_Signal_Realtime; /**< Realtime signal event */ + +#ifndef WIN32 + struct _Ecore_Event_Exe_Exit /** Process exit event */ + { + pid_t pid; /**< The process ID of the process that exited */ + int exit_code; /**< The exit code of the process */ + Ecore_Exe *exe; /**< The handle to the exited process, or NULL if not found */ + int exit_signal; /** < The signal that caused the process to exit */ + char exited : 1; /** < set to 1 if the process exited of its own accord */ + char signalled : 1; /** < set to 1 id the process exited due to uncaught signal */ + void *ext_data; /**< Extension data - not used */ + siginfo_t data; /**< Signal info */ + }; +#endif + + struct _Ecore_Event_Signal_User /** User signal event */ + { + int number; /**< The signal number. Either 1 or 2 */ + void *ext_data; /**< Extension data - not used */ + +#ifndef WIN32 + siginfo_t data; /**< Signal info */ +#endif + }; + + struct _Ecore_Event_Signal_Hup /** Hup signal event */ + { + void *ext_data; /**< Extension data - not used */ + +#ifndef WIN32 + siginfo_t data; /**< Signal info */ +#endif + }; + + struct _Ecore_Event_Signal_Exit /** Exit request event */ + { + int interrupt : 1; /**< Set if the exit request was an interrupt signal*/ + int quit : 1; /**< set if the exit request was a quit signal */ + int terminate : 1; /**< Set if the exit request was a terminate singal */ + void *ext_data; /**< Extension data - not used */ + +#ifndef WIN32 + siginfo_t data; /**< Signal info */ +#endif + }; + + struct _Ecore_Event_Signal_Power /** Power event */ + { + void *ext_data; /**< Extension data - not used */ + +#ifndef WIN32 + siginfo_t data; /**< Signal info */ +#endif + }; + + struct _Ecore_Event_Signal_Realtime /** Realtime event */ + { + int num; /**< The realtime signal's number */ + +#ifndef WIN32 + siginfo_t data; /**< Signal info */ +#endif + }; + + EAPI int ecore_init(void); + EAPI int ecore_shutdown(void); + + EAPI void ecore_app_args_set(int argc, const char **argv); + EAPI void ecore_app_args_get(int *argc, char ***argv); + EAPI void ecore_app_restart(void); + + EAPI Ecore_Event_Handler *ecore_event_handler_add(int type, int (*func) (void *data, int type, void *event), const void *data); + EAPI void *ecore_event_handler_del(Ecore_Event_Handler *event_handler); + EAPI Ecore_Event *ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data); + EAPI void *ecore_event_del(Ecore_Event *event); + EAPI int ecore_event_type_new(void); + EAPI Ecore_Event_Filter *ecore_event_filter_add(void * (*func_start) (void *data), int (*func_filter) (void *data, void *loop_data, int type, void *event), void (*func_end) (void *data, void *loop_data), const void *data); + EAPI void *ecore_event_filter_del(Ecore_Event_Filter *ef); + EAPI int ecore_event_current_type_get(void); + EAPI void *ecore_event_current_event_get(void); + + +#ifndef WIN32 + EAPI Ecore_Exe *ecore_exe_run(const char *exe_cmd, const void *data); + EAPI void *ecore_exe_free(Ecore_Exe *exe); + EAPI pid_t ecore_exe_pid_get(Ecore_Exe *exe); + EAPI void *ecore_exe_data_get(Ecore_Exe *exe); + EAPI void ecore_exe_pause(Ecore_Exe *exe); + EAPI void ecore_exe_continue(Ecore_Exe *exe); + EAPI void ecore_exe_terminate(Ecore_Exe *exe); + EAPI void ecore_exe_kill(Ecore_Exe *exe); + EAPI void ecore_exe_signal(Ecore_Exe *exe, int num); + EAPI void ecore_exe_hup(Ecore_Exe *exe); +#endif + + EAPI Ecore_Idler *ecore_idler_add(int (*func) (void *data), const void *data); + EAPI void *ecore_idler_del(Ecore_Idler *idler); + + EAPI Ecore_Idle_Enterer *ecore_idle_enterer_add(int (*func) (void *data), const void *data); + EAPI void *ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer); + + EAPI Ecore_Idle_Exiter *ecore_idle_exiter_add(int (*func) (void *data), const void *data); + EAPI void *ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter); + + EAPI void ecore_main_loop_iterate(void); + EAPI void ecore_main_loop_begin(void); + EAPI void ecore_main_loop_quit(void); + EAPI Ecore_Fd_Handler *ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), const void *buf_data); + EAPI void ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data); + EAPI void *ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler); + EAPI int ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler); + EAPI int ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags); + EAPI void ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags); + + EAPI double ecore_time_get(void); + + EAPI Ecore_Timer *ecore_timer_add(double in, int (*func) (void *data), const void *data); + EAPI void *ecore_timer_del(Ecore_Timer *timer); + EAPI void ecore_timer_interval_set(Ecore_Timer *timer, double in); + + EAPI Ecore_Animator *ecore_animator_add(int (*func) (void *data), const void *data); + EAPI void *ecore_animator_del(Ecore_Animator *animator); + EAPI void ecore_animator_frametime_set(double frametime); + EAPI double ecore_animator_frametime_get(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ecore/src/lib/ecore/Ecore_Data.h b/ecore/src/lib/ecore/Ecore_Data.h new file mode 100644 index 0000000..117f96c --- /dev/null +++ b/ecore/src/lib/ecore/Ecore_Data.h @@ -0,0 +1,591 @@ +#ifndef _ECORE_DATA_H +# define _ECORE_DATA_H + +/** + * @file Ecore_Data.h + * @brief Contains threading, list, hash, debugging and tree functions. + */ + +# ifdef __cplusplus +extern "C" { +# endif + +#ifdef __sgi +#define __FUNCTION__ "unknown" +#ifndef __cplusplus +#define inline +#endif +#endif + +# define PRIME_TABLE_MAX 21 +# define PRIME_MIN 17 +# define PRIME_MAX 16777213 + + extern const unsigned int ecore_prime_table[]; + + typedef void (*Ecore_For_Each) (void *value, void *user_data); +# define ECORE_FOR_EACH(function) ((Ecore_For_Each)function) + + typedef void (*Ecore_Free_Cb) (void *data); +# define ECORE_FREE_CB(func) ((Ecore_Free_Cb)func) + + typedef unsigned int (*Ecore_Hash_Cb) (void *key); +# define ECORE_HASH_CB(function) ((Ecore_Hash_Cb)function) + + typedef int (*Ecore_Compare_Cb) (void *data1, void *data2); +# define ECORE_COMPARE_CB(function) ((Ecore_Compare_Cb)function) + + int ecore_direct_compare(void *key1, void *key2); + int ecore_str_compare(void *key1, void *key2); + + unsigned int ecore_direct_hash(void *key); + unsigned int ecore_str_hash(void *key); + + +# ifdef HAVE_PTHREADS /* pthreads are installed */ + +# include <pthread.h> + +# define ECORE_DECLARE_LOCKS \ + struct { \ + int readers; \ + pthread_mutex_t readers_mutex; \ + pthread_mutex_t writers_mutex; \ + pthread_cond_t readers_cond; \ + } locks + +# define ECORE_INIT_LOCKS(structure) \ + if (structure) { \ + structure->readers = 0; \ + pthread_mutex_init(&structure->locks.readers_mutex, NULL); \ + pthread_mutex_init(&structure->locks.writers_mutex, NULL); \ + pthread_cond_init(&structure->locks.readers_cond, NULL); \ + } + +# define ECORE_DESTROY_LOCKS(structure) \ + if (structure) { \ + pthread_mutex_destroy(&structure->locks.readers_mutex); \ + pthread_mutex_destroy(&structure->locks.writers_mutex); \ + pthread_cond_destroy(&structure->readers_cond); \ + } + +# define ECORE_READ_LOCK(structure) \ + if (structure) { \ + pthread_mutex_lock(&structure->locks.readers_mutex); \ + structure->locks.readers++; \ + pthread_mutex_unlock(&structure->locks.readers_mutex); \ + } + +# define ECORE_READ_UNLOCK(structure) \ + if (structure) { \ + pthread_mutex_lock(&structure->locks.readers_mutex); \ + if (--structure->locks.readers == 0) \ + pthread_cond_broadcast(&structure->locks.readers_cond); \ + pthread_mutex_unlock(&structure->locks.readers_mutex); \ + } + +# define ECORE_WRITE_LOCK(structure) \ + if (structure) { \ + pthread_mutex_lock(&structure->locks.readers_mutex); \ + pthread_mutex_lock(&structure->locks.writers_mutex); \ + while (structure->locks.readers > 0) \ + pthread_cond_wait(&structure->locks.readers_cond, \ + &structure->locks.readers_mutex); \ + pthread_mutex_unlock(&structure->locks.readers_mutex); \ + } + +# define ECORE_WRITE_UNLOCK(structure) \ + if (structure) \ + pthread_mutex_unlock(&structure->locks.writers_mutex); \ + +# define ECORE_THREAD_CREATE(function, arg) \ + if (function) { \ + pthread_t thread; \ + pthread_create(&thread, NULL, function, arg); \ + pthread_detach(thread); \ + } + +# define ECORE_NO_THREADS(function, arg) + +# else /* No pthreads available */ + +# define ECORE_DECLARE_LOCKS +# define ECORE_INIT_LOCKS(structure) +# define ECORE_READ_LOCK(structure) +# define ECORE_READ_UNLOCK(structure) +# define ECORE_WRITE_LOCK(structure) +# define ECORE_WRITE_UNLOCK(structure) +# define ECORE_THREAD_CREATE(function, args) +# define ECORE_DESTROY_LOCKS(structure) + +# define ECORE_NO_THREADS(function, arg) if (function) function(arg); + +# endif /* HAVE_PTHREADS */ + + typedef struct _ecore_list Ecore_List; +# define ECORE_LIST(list) ((Ecore_List *)list) + + typedef struct _ecore_list_node Ecore_List_Node; +# define ECORE_LIST_NODE(node) ((Ecore_List_Node *)node) + + struct _ecore_list_node { + void *data; + struct _ecore_list_node *next; + + ECORE_DECLARE_LOCKS; + }; + + struct _ecore_list { + Ecore_List_Node *first; /* The first node in the list */ + Ecore_List_Node *last; /* The last node in the list */ + Ecore_List_Node *current; /* The current node in the list */ + + Ecore_Free_Cb free_func; /* The callback to free data in nodes */ + + int nodes; /* The number of nodes in the list */ + int index; /* The position from the front of the + list of current node */ + ECORE_DECLARE_LOCKS; + }; + + + /* Creating and initializing new list structures */ + Ecore_List *ecore_list_new(void); + int ecore_list_init(Ecore_List *list); + + /* Adding items to the list */ + inline int ecore_list_append(Ecore_List * list, void *_data); + inline int ecore_list_prepend(Ecore_List * list, void *_data); + inline int ecore_list_insert(Ecore_List * list, void *_data); + + /* Removing items from the list */ + inline int ecore_list_remove_destroy(Ecore_List *list); + inline void *ecore_list_remove(Ecore_List * list); + inline void *ecore_list_remove_first(Ecore_List * list); + inline void *ecore_list_remove_last(Ecore_List * list); + + /* Retrieve the current position in the list */ + inline void *ecore_list_current(Ecore_List * list); + int ecore_list_index(Ecore_List * list); + int ecore_list_nodes(Ecore_List * list); + + /* Traversing the list */ + int ecore_list_for_each(Ecore_List *list, Ecore_For_Each function, + void *user_data); + inline void *ecore_list_goto_first(Ecore_List * list); + inline void *ecore_list_goto_last(Ecore_List * list); + inline void *ecore_list_goto_index(Ecore_List * list, int index); + inline void *ecore_list_goto(Ecore_List * list, void *_data); + + /* Traversing the list and returning data */ + inline void *ecore_list_next(Ecore_List * list); + + /* Check to see if there is any data in the list */ + int ecore_list_is_empty(Ecore_List * list); + + /* Remove every node in the list without freeing the list itself */ + int ecore_list_clear(Ecore_List * list); + /* Free the list and it's contents */ + void ecore_list_destroy(Ecore_List *list); + + /* Creating and initializing list nodes */ + Ecore_List_Node *ecore_list_node_new(void); + int ecore_list_node_init(Ecore_List_Node *newNode); + + /* Destroying nodes */ + int ecore_list_node_destroy(Ecore_List_Node * _e_node, Ecore_Free_Cb free_func); + + int ecore_list_set_free_cb(Ecore_List * list, Ecore_Free_Cb free_func); + + typedef Ecore_List Ecore_DList; +# define ECORE_DLIST(dlist) ((Ecore_DList *)dlist) + + typedef struct _ecore_dlist_node Ecore_DList_Node; +# define ECORE_DLIST_NODE(dlist) ((Ecore_DList_Node *)dlist) + + struct _ecore_dlist_node { + Ecore_List_Node single; + Ecore_DList_Node *previous; + }; + + /* Creating and initializing new list structures */ + Ecore_DList *ecore_dlist_new(void); + int ecore_dlist_init(Ecore_DList *list); + void ecore_dlist_destroy(Ecore_DList *list); + + /* Adding items to the list */ + int ecore_dlist_append(Ecore_DList * _e_dlist, void *_data); + int ecore_dlist_prepend(Ecore_DList * _e_dlist, void *_data); + int ecore_dlist_insert(Ecore_DList * _e_dlist, void *_data); + + /* Info about list's state */ + void *ecore_dlist_current(Ecore_DList *list); + int ecore_dlist_index(Ecore_DList *list); +# define ecore_dlist_nodes(list) ecore_list_nodes(ECORE_LIST(list)) + + /* Removing items from the list */ + void *ecore_dlist_remove(Ecore_DList * _e_dlist); + void *ecore_dlist_remove_first(Ecore_DList * _e_dlist); + int ecore_dlist_remove_destroy(Ecore_DList *list); + void *ecore_dlist_remove_last(Ecore_DList * _e_dlist); + + /* Traversing the list */ +# define ecore_dlist_for_each(list, function, user_data) \ + ecore_list_for_each(ECORE_LIST(list), function, user_data) + inline void *ecore_dlist_goto_first(Ecore_DList * _e_dlist); + inline void *ecore_dlist_goto_last(Ecore_DList * _e_dlist); + inline void *ecore_dlist_goto_index(Ecore_DList * _e_dlist, int index); + inline void *ecore_dlist_goto(Ecore_DList * _e_dlist, void *_data); + + /* Traversing the list and returning data */ + inline void *ecore_dlist_next(Ecore_DList * list); + inline void *ecore_dlist_previous(Ecore_DList * list); + + /* Check to see if there is any data in the list */ + int ecore_dlist_is_empty(Ecore_DList * _e_dlist); + + /* Remove every node in the list without free'ing it */ + int ecore_dlist_clear(Ecore_DList * _e_dlist); + + /* Creating and initializing list nodes */ + int ecore_dlist_node_init(Ecore_DList_Node * node); + Ecore_DList_Node *ecore_dlist_node_new(void); + + /* Destroying nodes */ + int ecore_dlist_node_destroy(Ecore_DList_Node * node, Ecore_Free_Cb free_func); + + int ecore_dlist_set_free_cb(Ecore_DList * dlist, Ecore_Free_Cb free_func); + + + + /* + * Hash Table Implementation: + * + * Traditional hash table implementation. I had tried a list of tables + * approach to save on the realloc's but it ended up being much slower than + * the traditional approach. + */ + + typedef struct _ecore_hash_node Ecore_Hash_Node; +# define ECORE_HASH_NODE(hash) ((Ecore_Hash_Node *)hash) + + struct _ecore_hash_node { + void *key; /* The key for the data node */ + void *value; /* The value associated with this node */ + + ECORE_DECLARE_LOCKS; + }; + + typedef struct _ecore_hash Ecore_Hash; +# define ECORE_HASH(hash) ((Ecore_Hash *)hash) + + struct _ecore_hash { + Ecore_List **buckets; + int size; /* An index into the table of primes to + determine size */ + int nodes; /* The number of nodes currently in the hash */ + + int index; /* The current index into the bucket table */ + + Ecore_Compare_Cb compare; /* The function used to compare node values */ + Ecore_Hash_Cb hash_func; /* The function used to compare node values */ + + Ecore_Free_Cb free_key; /* The callback function to free key */ + Ecore_Free_Cb free_value; /* The callback function to determine hash */ + + ECORE_DECLARE_LOCKS; + }; + + /* Create and initialize a hash */ + Ecore_Hash *ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare); + int ecore_hash_init(Ecore_Hash *hash, Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare); + + /* Functions related to freeing the data in the hash table */ + int ecore_hash_set_free_key(Ecore_Hash *hash, Ecore_Free_Cb function); + int ecore_hash_set_free_value(Ecore_Hash *hash, Ecore_Free_Cb function); + void ecore_hash_destroy(Ecore_Hash *hash); + + int ecore_hash_for_each_node(Ecore_Hash *hash, Ecore_For_Each for_each_func, + void *user_data); + Ecore_List *ecore_hash_keys(Ecore_Hash *hash); + + /* Retrieve and store data into the hash */ + void *ecore_hash_get(Ecore_Hash *hash, void *key); + int ecore_hash_set(Ecore_Hash *hash, void *key, void *value); + void *ecore_hash_remove(Ecore_Hash *hash, void *key); + void ecore_hash_dump_graph(Ecore_Hash *hash); + + + inline void ecore_print_warning(const char *function, const char *sparam); + + /* Wrappers around free() that helps debug free() bugs such as freeing NULL + * or accessing a pointer that has already been freed */ +# ifndef IF_FREE +# define IF_FREE(ptr) if (ptr) free(ptr); ptr = NULL; +# endif + +# ifndef FREE +# define FREE(ptr) free(ptr); ptr = NULL; +# endif + + /* Debugging printf, basically a wrapper to fprintf that checks the level + * of the message and checks that it is to be printed at the current debugging + * level */ +# ifndef DPRINTF +# ifdef __sgi +# define DPRINTF(debug, format, args) \ + if (debug >= DEBUG_LEVEL) \ + fprintf(stderr, format, args); +# else +# define DPRINTF(debug, format, args...) \ + if (debug >= DEBUG_LEVEL) \ + fprintf(stderr, format, args); +# endif +# endif + + + /* convenience macros for checking pointer parameters for non-NULL */ +# ifndef CHECK_PARAM_POINTER_RETURN +# define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \ + if (!(param)) \ + { \ + ecore_print_warning(__FUNCTION__, sparam); \ + return ret; \ + } +# endif + +# ifndef CHECK_PARAM_POINTER +# define CHECK_PARAM_POINTER(sparam, param) \ + if (!(param)) \ + { \ + ecore_print_warning(__FUNCTION__, sparam); \ + return; \ + } +# endif + + /* Use the larger of a and b */ +# ifndef MAX +# define MAX(a, b) (((a) > (b)) ? (a) : (b)) +# endif + + /* Use the smaller of a and b */ +# ifndef MIN +# define MIN(a, b) (((a) < (b)) ? (a) : (b)) +# endif + + + typedef struct _ecore_path_group Ecore_Path_Group; + struct _ecore_path_group + { + int id; + char *name; + Ecore_List *paths; + }; + + /* + * Create a new path group + */ + int ecore_path_group_new(char *group_name); + + /* + * Destroy a previous path group + */ + void ecore_path_group_del(int group_id); + + /* + * Add a directory to be searched for files + */ + void ecore_path_group_add(int group_id, char *path); + + /* + * Remove a directory to be searched for files + */ + void ecore_path_group_remove(int group_id, char *path); + + /* + * Find the absolute path if it exists in the group of paths + */ + char * ecore_path_group_find(int group_id, char *name); + + /* + * Get a list of all the available files in a path set + */ + Ecore_List * ecore_path_group_available(int group_id); + + + typedef struct _ecore_plugin Ecore_Plugin; + struct _ecore_plugin + { + int group; + char *name; + void *handle; + }; + + /* + * Load the specified plugin + */ + Ecore_Plugin *ecore_plugin_load(int group_id, char *plugin); + + /* + * Unload the specified plugin + */ + void ecore_plugin_unload(Ecore_Plugin * plugin); + + /* + * Lookup the specified symbol for the plugin + */ + void *ecore_plugin_call(Ecore_Plugin * plugin, char *symbol_name); + + Ecore_List *ecore_plugin_get_available(int group_id); + + +# define ECORE_SHEAP_MIN 0 +# define ECORE_SHEAP_MAX 1 + +# define HEAP_INCREMENT 4096 + +# define PARENT(i) (i / 2) +# define LEFT(i) (2 * i) +# define RIGHT(i) (2 * i + 1) + + typedef struct _ecore_heap Ecore_Sheap; +# define ECORE_HEAP(heap) ((Ecore_Sheap *)heap) + + struct _ecore_heap { + void **data; + int size; + int space; + + char order, sorted; + + /* Callback for comparing node values, default is direct comparison */ + Ecore_Compare_Cb compare; + + /* Callback for freeing node data, default is NULL */ + Ecore_Free_Cb free_func; + }; + + Ecore_Sheap *ecore_sheap_new(Ecore_Compare_Cb compare, int size); + void ecore_sheap_destroy(Ecore_Sheap *heap); + int ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size); + int ecore_sheap_set_free_cb(Ecore_Sheap *heap, Ecore_Free_Cb free_func); + int ecore_sheap_insert(Ecore_Sheap *heap, void *data); + void *ecore_sheap_extract(Ecore_Sheap *heap); + void *ecore_sheap_extreme(Ecore_Sheap *heap); + int ecore_sheap_change(Ecore_Sheap *heap, void *item, void *newval); + int ecore_sheap_set_compare(Ecore_Sheap *heap, Ecore_Compare_Cb compare); + void ecore_sheap_set_order(Ecore_Sheap *heap, char order); + void ecore_sheap_sort(Ecore_Sheap *heap); + + inline void *ecore_sheap_item(Ecore_Sheap *heap, int i); + + + typedef struct _ecore_string Ecore_String; + struct _ecore_string { + char *string; + int references; + }; + + char *ecore_string_instance(char *string); + void ecore_string_release(char *string); + + + typedef struct _Ecore_Tree_Node Ecore_Tree_Node; +# define ECORE_TREE_NODE(object) ((Ecore_Tree_Node *)object) + struct _Ecore_Tree_Node { + + /* The actual data for each node */ + void *key; + void *value; + + /* Pointers to surrounding nodes */ + Ecore_Tree_Node *parent; + Ecore_Tree_Node *left_child; + Ecore_Tree_Node *right_child; + + /* Book keeping information for quicker balancing of the tree */ + int max_right; + int max_left; + + ECORE_DECLARE_LOCKS; + }; + + typedef struct _Ecore_Tree Ecore_Tree; +# define ECORE_TREE(object) ((Ecore_Tree *)object) + struct _Ecore_Tree { + /* Nodes of the tree */ + Ecore_Tree_Node *tree; + + /* Callback for comparing node values, default is direct comparison */ + Ecore_Compare_Cb compare_func; + + /* Callback for freeing node data, default is NULL */ + Ecore_Free_Cb free_func; + + ECORE_DECLARE_LOCKS; + }; + + /* Some basic tree functions */ + /* Allocate and initialize a new tree */ + Ecore_Tree *ecore_tree_new(Ecore_Compare_Cb compare_func); + /* Initialize a new tree */ + int ecore_tree_init(Ecore_Tree * tree, Ecore_Compare_Cb compare_func); + + /* Free the tree */ + int ecore_tree_destroy(Ecore_Tree * tree); + /* Check to see if the tree has any nodes in it */ + int ecore_tree_is_empty(Ecore_Tree * tree); + + /* Retrieve the value associated with key */ + void *ecore_tree_get(Ecore_Tree * tree, void *key); + Ecore_Tree_Node *ecore_tree_get_node(Ecore_Tree * tree, void *key); + /* Retrieve the value of node with key greater than or equal to key */ + void *ecore_tree_get_closest_larger(Ecore_Tree * tree, void *key); + /* Retrieve the value of node with key less than or equal to key */ + void *ecore_tree_get_closest_smaller(Ecore_Tree * tree, void *key); + + /* Set the value associated with key to value */ + int ecore_tree_set(Ecore_Tree * tree, void *key, void *value); + /* Remove the key from the tree */ + int ecore_tree_remove(Ecore_Tree * tree, void *key); + + /* Add a node to the tree */ + int ecore_tree_add_node(Ecore_Tree * tree, Ecore_Tree_Node * node); + /* Remove a node from the tree */ + int ecore_tree_remove_node(Ecore_Tree * tree, Ecore_Tree_Node * node); + + /* For each node in the tree perform the for_each_func function */ + /* For this one pass in the node */ + int ecore_tree_for_each_node(Ecore_Tree * tree, Ecore_For_Each for_each_func, + void *user_data); + /* And here pass in the node's value */ + int ecore_tree_for_each_node_value(Ecore_Tree * tree, + Ecore_For_Each for_each_func, + void *user_data); + + /* Some basic node functions */ + /* Initialize a node */ + int ecore_tree_node_init(Ecore_Tree_Node * new_node); + /* Allocate and initialize a new node */ + Ecore_Tree_Node *ecore_tree_node_new(void); + /* Free the desired node */ + int ecore_tree_node_destroy(Ecore_Tree_Node * node, Ecore_Free_Cb free_data); + + /* Set the node's key to key */ + int ecore_tree_node_key_set(Ecore_Tree_Node * node, void *key); + /* Retrieve the key in node */ + void *ecore_tree_node_key_get(Ecore_Tree_Node * node); + + /* Set the node's value to value */ + int ecore_tree_node_value_set(Ecore_Tree_Node * node, void *value); + /* Retrieve the value in node */ + void *ecore_tree_node_value_get(Ecore_Tree_Node * node); + + /* Add a function to free the data stored in nodes */ + int ecore_tree_set_free_cb(Ecore_Tree * tree, Ecore_Free_Cb free_func); + +#ifdef __cplusplus +} +#endif +#endif /* _ECORE_DATA_H */ + diff --git a/ecore/src/lib/ecore/Makefile.am b/ecore/src/lib/ecore/Makefile.am new file mode 100644 index 0000000..c0bdd3a --- /dev/null +++ b/ecore/src/lib/ecore/Makefile.am @@ -0,0 +1,34 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = + +lib_LTLIBRARIES = libecore.la +include_HEADERS = \ +Ecore.h \ +Ecore_Data.h + +libecore_la_SOURCES = \ +ecore.c \ +ecore_app.c \ +ecore_anim.c \ +ecore_events.c \ +ecore_exe.c \ +ecore_hash.c \ +ecore_idle_enterer.c \ +ecore_idle_exiter.c \ +ecore_idler.c \ +ecore_list.c \ +ecore_main.c \ +ecore_path.c \ +ecore_plugin.c \ +ecore_sheap.c \ +ecore_signal.c \ +ecore_strings.c \ +ecore_time.c \ +ecore_timer.c \ +ecore_tree.c \ +ecore_value.c \ +ecore_private.h + +libecore_la_LIBADD = -lm @dlopen_libs@ @winsock_libs@ +libecore_la_LDFLAGS = -version-info 1:0:0 diff --git a/ecore/src/lib/ecore/ecore.c b/ecore/src/lib/ecore/ecore.c new file mode 100644 index 0000000..3e6b2a8 --- /dev/null +++ b/ecore/src/lib/ecore/ecore.c @@ -0,0 +1,236 @@ +#include "ecore_private.h" +#include "Ecore.h" +#include <locale.h> +#include <langinfo.h> + +static const char *_ecore_magic_string_get(Ecore_Magic m); +static int _ecore_init_count = 0; + +#ifndef WIN32 +int _ecore_fps_debug = 0; +#endif + +/** OpenBSD does not define CODESET + * FIXME ?? + */ + +#ifndef CODESET +#define CODESET "INVALID" +#endif + +/** + * Set up connections, signal handlers, sockets etc. + * @return 1 or greater on success, 0 otherwise + * + * This function sets up all singal handlers and the basic event loop. If it + * succeeds, 1 will be returned, otherwise 0 will be returned. + * + * @code + * #include <Ecore.h> + * + * int main(int argc, char **argv) + * { + * if (!ecore_init()) + * { + * printf("ERROR: Cannot init Ecore!\n"); + * return -1; + * } + * ecore_main_loop_begin(); + * ecore_shutdown(); + * } + * @endcode + */ +int +ecore_init(void) +{ + if (++_ecore_init_count == 1) + { + setlocale(LC_CTYPE, ""); + if (strcmp(nl_langinfo(CODESET), "UTF-8")) + { +// printf("WARNING: not a utf8 locale!\n"); + } +#ifndef WIN32 + if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1; + if (_ecore_fps_debug) _ecore_fps_debug_init(); + _ecore_signal_init(); +#endif + } + + return _ecore_init_count; +} + +/** + * Shut down connections, signal handlers sockets etc. + * + * This function shuts down all things set up in ecore_init() and cleans up all + * event queues, handlers, filters, timers, idlers, idle enterers/exiters + * etc. set up after ecore_init() was called. + * + * Do not call this function from any callback that may be called from the main + * loop, as the main loop will then fall over and not function properly. + */ +int +ecore_shutdown(void) +{ + if (--_ecore_init_count) + return _ecore_init_count; + +#ifndef WIN32 + if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); +#endif + _ecore_animator_shutdown(); +#ifndef WIN32 + _ecore_exe_shutdown(); +#endif + _ecore_idle_enterer_shutdown(); + _ecore_idle_exiter_shutdown(); + _ecore_idler_shutdown(); + _ecore_timer_shutdown(); + _ecore_event_shutdown(); + _ecore_main_shutdown(); +#ifndef WIN32 + _ecore_signal_shutdown(); +#endif + + return _ecore_init_count; +} + +void +_ecore_magic_fail(void *d, Ecore_Magic m, Ecore_Magic req_m, const char *fname) +{ + fprintf(stderr, + "\n" + "*** ECORE ERROR: Ecore Magic Check Failed!!!\n" + "*** IN FUNCTION: %s()\n", fname); + if (!d) + fprintf(stderr, " Input handle pointer is NULL!\n"); + else if (m == ECORE_MAGIC_NONE) + fprintf(stderr, " Input handle has already been freed!\n"); + else if (m != req_m) + fprintf(stderr, " Input handle is wrong type\n" + " Expected: %08x - %s\n" + " Supplied: %08x - %s\n", + (unsigned int)req_m, _ecore_magic_string_get(req_m), + (unsigned int)m, _ecore_magic_string_get(m)); + fprintf(stderr, + "*** NAUGHTY PROGRAMMER!!!\n" + "*** SPANK SPANK SPANK!!!\n" + "*** Now go fix your code. Tut tut tut!\n" + "\n"); + if (getenv("ECORE_ERROR_ABORT")) abort(); +} + +static const char * +_ecore_magic_string_get(Ecore_Magic m) +{ + switch (m) + { + case ECORE_MAGIC_NONE: + return "None (Freed Object)"; + break; + case ECORE_MAGIC_EXE: + return "Ecore_Exe (Executable)"; + break; + case ECORE_MAGIC_TIMER: + return "Ecore_Timer (Timer)"; + break; + case ECORE_MAGIC_IDLER: + return "Ecore_Idler (Idler)"; + break; + case ECORE_MAGIC_IDLE_ENTERER: + return "Ecore_Idle_Enterer (Idler Enterer)"; + break; + case ECORE_MAGIC_IDLE_EXITER: + return "Ecore_Idle_Exiter (Idler Exiter)"; + break; + case ECORE_MAGIC_FD_HANDLER: + return "Ecore_Fd_Handler (Fd Handler)"; + break; + case ECORE_MAGIC_EVENT_HANDLER: + return "Ecore_Event_Handler (Event Handler)"; + break; + case ECORE_MAGIC_EVENT: + return "Ecore_Event (Event)"; + break; + default: + return "<UNKNOWN>"; + }; + return "<UNKNOWN>"; +} + +#ifndef WIN32 +/* fps debug calls - for debugging how much time your app actually spends */ +/* "running" (and the inverse being time spent running)... this does not */ +/* account for other apps and multitasking... */ + +static int _ecore_fps_debug_init_count = 0; +static int _ecore_fps_debug_fd = -1; +unsigned int *_ecore_fps_runtime_mmap = NULL; + +void +_ecore_fps_debug_init(void) +{ + char buf[4096]; + + _ecore_fps_debug_init_count++; + if (_ecore_fps_debug_init_count > 1) return; + snprintf(buf, sizeof(buf), "/tmp/.ecore_fps_debug-%i", (int)getpid()); + _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR); + if (_ecore_fps_debug_fd < 0) + { + unlink(buf); + _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR); + } + if (_ecore_fps_debug_fd >= 0) + { + unsigned int zero = 0; + + write(_ecore_fps_debug_fd, &zero, sizeof(unsigned int)); + _ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int), + PROT_READ | PROT_WRITE, + MAP_SHARED, + _ecore_fps_debug_fd, 0); + } +} + +void +_ecore_fps_debug_shutdown(void) +{ + _ecore_fps_debug_init_count--; + if (_ecore_fps_debug_init_count > 0) return; + if (_ecore_fps_debug_fd >= 0) + { + char buf[4096]; + + snprintf(buf, sizeof(buf), "/tmp/.ecore_fps_debug-%i", (int)getpid()); + unlink(buf); + if (_ecore_fps_runtime_mmap) + { + munmap(_ecore_fps_runtime_mmap, sizeof(int)); + _ecore_fps_runtime_mmap = NULL; + } + close(_ecore_fps_debug_fd); + _ecore_fps_debug_fd = -1; + } +} + +void +_ecore_fps_debug_runtime_add(double t) +{ + if ((_ecore_fps_debug_fd >= 0) && + (_ecore_fps_runtime_mmap)) + { + unsigned int tm; + + tm = (unsigned int)(t * 1000000.0); + /* i know its not 100% theoretically guaranteed, but i'd say a write */ + /* of an int could be considered atomic for all practical purposes */ + /* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */ + /* this can run for about 4294 seconds becore looping. if you are */ + /* doing performance testing in one run for over an hour... well */ + /* time to restart or handle a loop condition :) */ + *(_ecore_fps_runtime_mmap) += tm; + } +} +#endif diff --git a/ecore/src/lib/ecore/ecore_anim.c b/ecore/src/lib/ecore/ecore_anim.c new file mode 100644 index 0000000..476fa20 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_anim.c @@ -0,0 +1,169 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static int _ecore_animator(void *data); + +static Ecore_Timer *timer = NULL; +static int animators_delete_me = 0; +static Ecore_Animator *animators = NULL; +static double animators_frametime = 1.0 / 30.0; + +/** + * Add a animator to tick off at every animaton tick during main loop execution. + * @param func The function to call when it ticks off + * @param data The data to pass to the function + * @return A handle to the new animator + * @ingroup Ecore_Animator_Group + * + * This function adds a animator and returns its handle on success and NULL on + * failure. The function @p func will be called every N seconds where N is the + * frametime interval set by ecore_animator_frametime_set(). The function will + * be passed the @p data pointer as its parameter. + * + * When the animator @p func is called, it must return a value of either 1 or 0. + * If it returns 1, it will be called again at the next tick, or if it returns + * 0 it will be deleted automatically making any references/handles for it + * invalid. + */ +Ecore_Animator * +ecore_animator_add(int (*func) (void *data), const void *data) +{ + Ecore_Animator *animator; + + if (!func) return NULL; + animator = calloc(1, sizeof(Ecore_Animator)); + if (!animator) return NULL; + ECORE_MAGIC_SET(animator, ECORE_MAGIC_ANIMATOR); + animator->func = func; + animator->data = (void *)data; + animators = _ecore_list_append(animators, animator); + if (!timer) + timer = ecore_timer_add(animators_frametime, _ecore_animator, NULL); + return animator; +} + +/** + * Delete the specified animator from the animator list. + * @param animator The animator to delete + * @return The data pointer set for the animator + * @ingroup Ecore_Animator_Group + * + * Delete the specified @p aqnimator from the set of animators that are executed + * during main loop execution. This function returns the data parameter that + * was being passed to the callback on success, or NULL on failure. After this + * call returns the specified animator object @p animator is invalid and should not + * be used again. It will not get called again after deletion. + */ +void * +ecore_animator_del(Ecore_Animator *animator) +{ + if (!ECORE_MAGIC_CHECK(animator, ECORE_MAGIC_ANIMATOR)) + { + ECORE_MAGIC_FAIL(animator, ECORE_MAGIC_ANIMATOR, + "ecore_animator_del"); + return NULL; + } + if (animator->delete_me) return animator->data; + animator->delete_me = 1; + animators_delete_me++; + return animator->data; +} + +/** + * Set the animator call interval in seconds. + * @param frametime The time in seconds in between animator ticks. + * + * This function sets the time interval (in seconds) inbetween animator ticks. + */ +void +ecore_animator_frametime_set(double frametime) +{ + if (frametime < 0.0) frametime = 0.0; + if (animators_frametime == frametime) return; + animators_frametime = frametime; + if (timer) + { + ecore_timer_del(timer); + timer = NULL; + } + if (animators) + timer = ecore_timer_add(animators_frametime, _ecore_animator, NULL); +} + +/** + * Get the animator call interval in seconds. + * @return The time in second in between animator ticks. + * + * this function retrieves the time inbetween animator ticks, in seconds. + */ +double +ecore_animator_frametime_get(void) +{ + return animators_frametime; +} + +void +_ecore_animator_shutdown(void) +{ + if (timer) + { + ecore_timer_del(timer); + timer = NULL; + } + while (animators) + { + Ecore_Animator *animator; + + animator = animators; + animators = _ecore_list_remove(animators, animator); + ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE); + free(animator); + } +} + +static int +_ecore_animator(void *data __UNUSED__) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)animators; l;) + { + Ecore_Animator *animator; + + animator = (Ecore_Animator *)l; + l = l->next; + if (!animator->delete_me) + { + if (!animator->func(animator->data)) + { + animator->delete_me = 1; + animators_delete_me = 1; + } + } + } + if (animators_delete_me) + { + + for (l = (Ecore_Oldlist *)animators; l;) + { + Ecore_Animator *animator; + + animator = (Ecore_Animator *)l; + l = l->next; + if (animator->delete_me) + { + animators = _ecore_list_remove(animators, animator); + ECORE_MAGIC_SET(animator, ECORE_MAGIC_NONE); + free(animator); + animators_delete_me--; + if (animators_delete_me == 0) break; + } + } + } + if (!animators) + { + timer = NULL; + return 0; + } + return 1; +} diff --git a/ecore/src/lib/ecore/ecore_app.c b/ecore/src/lib/ecore/ecore_app.c new file mode 100644 index 0000000..ecf36bf --- /dev/null +++ b/ecore/src/lib/ecore/ecore_app.c @@ -0,0 +1,64 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static int app_argc = 0; +static char **app_argv = NULL; + +/** + * Set up the programs command-line arguments. + * @param argc The same as passed as argc to the programs main() function + * @param argv The same as passed as argv to the programs main() function + * + * A call to this function will store the programs command-line arguments + * for later use by ecore_app_restart() or ecore_app_args_get(). + */ +void +ecore_app_args_set(int argc, const char **argv) +{ + if ((argc < 1) || + (!argv)) return; + app_argc = argc; + app_argv = (char **)argv; +} + +/** + * Return the programs stored command-line arguments. + * @param argc A pointer to the return value to hold argc + * @param argv A pointer to the return value to hold argv + * + * When called, this funciton returns the arguments for the program stored by + * ecore_app_args_set(). The integer pointed to by @p argc will be filled, if + * the pointer is not NULL, and the string array pointer @p argv will be filled + * also if the pointer is not NULL. The values they are filled with will be the + * same set by ecore_app_args_set(). + */ +void +ecore_app_args_get(int *argc, char ***argv) +{ + if (argc) *argc = app_argc; + if (argv) *argv = app_argv; +} + +/** + * Restart the program executable with the command-line arguments stored. + * + * This function will restart & re-execute this program in place of itself + * using the command-line arguments stored by ecore_app_args_set(). This is + * an easy way for a program to restart itself for cleanup purposes, + * configuration reasons or in the event of a crash. + * + * FIXME: Currently not implimented. + */ +void +ecore_app_restart(void) +{ + char **args; + int i; + + if ((app_argc < 1) || (!app_argv)) return; + args = malloc((app_argc + 1) * sizeof(char *)); + if (!args) return; + for (i = 0; i < app_argc; i++) args[i] = app_argv[i]; + args[i] = NULL; + execvp(app_argv[0], args); +} diff --git a/ecore/src/lib/ecore/ecore_events.c b/ecore/src/lib/ecore/ecore_events.c new file mode 100644 index 0000000..45e2ac9 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_events.c @@ -0,0 +1,519 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static int events_num = 0; +static Ecore_Event *events = NULL; + +static Ecore_Event_Handler **event_handlers = NULL; +static int event_handlers_num = 0; +static int event_handlers_alloc_num = 0; +static Ecore_Oldlist_Data *event_handlers_delete_list = NULL; + +static Ecore_Event_Filter *event_filters = NULL; +static int event_filters_delete_me = 0; + +static int event_id_max = ECORE_EVENT_COUNT; + +static int ecore_raw_event_type = ECORE_EVENT_NONE; +static void *ecore_raw_event_event = NULL; + + +/** + * Add an event handler. + * @param type The type of the event this handler will get called for + * @param func The function to call when the event is found in the queue + * @param data A data pointer to pass to the called function @p func + * @return A new Event handler, or NULL on failure + * + * Add an event handler to the list of handlers. This will, on success, return + * a handle to the event handler object that was created, that can be used + * later to remove the handler using ecore_event_handler_del(). The @p type + * parameter is the iteger of the event type that will trigger this callback + * to be called. The callback @p func is called when this event is processed + * and will be passed the event type, a pointer to the private event + * structure that is specific to that event type, and a data pointer that is + * provided in this call as the @p data parameter. + * + * When the callback @p func is called, it must return 1 or 0. If it returns + * 1, It will keep being called as per normal, for each handler set up for that + * event type. If it returns 0, it will cease processing handlers for that + * particular event, so all handler set to handle that event type that have not + * already been called, will not be. + */ +Ecore_Event_Handler * +ecore_event_handler_add(int type, int (*func) (void *data, int type, void *event), const void *data) +{ + Ecore_Event_Handler *eh; + + if (!func) return NULL; + if ((type <= ECORE_EVENT_NONE) || (type >= event_id_max)) return NULL; + eh = calloc(1, sizeof(Ecore_Event_Handler)); + if (!eh) return NULL; + ECORE_MAGIC_SET(eh, ECORE_MAGIC_EVENT_HANDLER); + eh->type = type; + eh->func = func; + eh->data = (void *)data; + if (type >= (event_handlers_num - 1)) + { + int p_alloc_num; + + p_alloc_num = event_handlers_alloc_num; + event_handlers_num = type + 1; + if (event_handlers_num > event_handlers_alloc_num) + { + Ecore_Event_Handler **new_handlers; + int i; + + event_handlers_alloc_num = ((event_handlers_num + 16) / 16) * 16; + new_handlers = realloc(event_handlers, event_handlers_alloc_num * sizeof(Ecore_Event_Handler *)); + if (!new_handlers) + { + free(eh); + return NULL; + } + event_handlers = new_handlers; + for (i = p_alloc_num; i < event_handlers_alloc_num; i++) + event_handlers[i] = NULL; + } + } + event_handlers[type] = _ecore_list_append(event_handlers[type], eh); + return eh; +} + +/** + * Delete an event handler. + * @param event_handler Event handler handle to delete + * @return Data passed to handler + * + * Delete a specified event handler from the handler list. On success this will + * delete the event handler and return the pointer passed as @p data when the + * handler was added by ecore_event_handler_add(). On failure NULL will be + * returned. Once a handler is deleted it will no longer be called. + */ +void * +ecore_event_handler_del(Ecore_Event_Handler *event_handler) +{ + Ecore_Oldlist_Data *node; + + if (!ECORE_MAGIC_CHECK(event_handler, ECORE_MAGIC_EVENT_HANDLER)) + { + ECORE_MAGIC_FAIL(event_handler, ECORE_MAGIC_EVENT_HANDLER, + "ecore_event_handler_del"); + return NULL; + } + event_handler->delete_me = 1; + node = calloc(1, sizeof(Ecore_Oldlist_Data)); + node->data = event_handler; + event_handlers_delete_list = _ecore_list_append(event_handlers_delete_list, node); + return event_handler->data; +} + +static void _ecore_event_generic_free (void *data __UNUSED__, void *event) +{ + free (event); +} + +/** + * Add an event to the event queue. + * @param type The event type to add to the end of the event queue + * @param ev The private data structure for this event type + * @param func_free The function to be called to free this private structure + * @param data The data pointer to be passed to the free function + * @return A Handle for that event + * + * On success this function returns a handle to an event on the event queue, or + * NULL if it fails. If it succeeds, an event of type @p type will be added + * to the queue for processing by event handlers added by + * ecore_event_handler_add(). The @p ev parameter will be a pointer to the event + * private data that is specific to that event type. When the event is no + * longer needed, @p func_free will be called and passed the private sructure + * pointer for cleaning up. If @p func_free is NULL, free() will be called + * with the private structure pointer. + * func_free is passed @p data as its data parameter. + */ +Ecore_Event * +ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data) +{ + if (!ev) return NULL; + if (type <= ECORE_EVENT_NONE) return NULL; + if (type >= event_id_max) return NULL; + if (!func_free) func_free = _ecore_event_generic_free; + return _ecore_event_add(type, ev, func_free, data); +} + +/** + * Delete an event from the queue. + * @param event The event handle to delete + * @return The data pointer originally set for the event free function + * + * This deletes the event @p event from the event queue, and returns the + * @p data parameer originally set when adding it with ecore_event_add(). This + * does not immediately call the free function, and it may be called later on + * cleanup, and so if the free function depends on the data pointer to work, + * you should defer cleaning of this till the free function is called later. + */ +void * +ecore_event_del(Ecore_Event *event) +{ + if (!ECORE_MAGIC_CHECK(event, ECORE_MAGIC_EVENT)) + { + ECORE_MAGIC_FAIL(event, ECORE_MAGIC_EVENT, + "ecore_event_del"); + return NULL; + } + event->delete_me = 1; + return event->data; +} + +/** + * Allocate a new event type id sensibly and return the new id. + * @return A new event type id. + * + * This function allocates a new event type id and returns it. Once an event + * type has been allocated it can never be de-allocated during the life of + * the program. There is no guarantee of the contents of this event ID, or how + * it is calculated, except that the ID will be unique to the current instance + * of the process. + */ +int +ecore_event_type_new(void) +{ + event_id_max++; + return event_id_max - 1; +} + +/** + * Add a filter the current event queue. + * @param func_start Function to call just before filtering and return data + * @param func_filter Function to call on each event + * @param func_end Function to call after the queu has been filtered + * @param data Data to pass to the filter functions + * @return A filter handle + * + * This adds a filter to call callbacks to loop through the event queue and + * filter events out of the queue. On failure NULL is returned. On success a + * Filter handle is returned. Filters are called on the queue just before + * Event handler processing to try and remove redundant events. Just as + * processing starts @p func_start is called and passed the @p data pointer. + * This function returns a pointer that is used as loop_data that is now passed to + * @p func_filter as loop_data. @p func_filter is also passed @p data and the + * event type and private event structure. If this callback returns 0, the + * event is removed from the queue. If it returns 1, the event is kept. When + * processing is finished @p func_end is called and is passed the loop_data + * and @p data pointer to clean up. + */ +Ecore_Event_Filter * +ecore_event_filter_add(void * (*func_start) (void *data), int (*func_filter) (void *data, void *loop_data, int type, void *event), void (*func_end) (void *data, void *loop_data), const void *data) +{ + Ecore_Event_Filter *ef; + + if (!func_filter) return NULL; + ef = calloc(1, sizeof(Ecore_Event_Filter)); + if (!ef) return NULL; + ECORE_MAGIC_SET(ef, ECORE_MAGIC_EVENT_FILTER); + ef->func_start = func_start; + ef->func_filter = func_filter; + ef->func_end = func_end; + ef->data = (void *)data; + event_filters = _ecore_list_append(event_filters, ef); + return ef; +} + +/** + * Delete an event filter. + * @param ef The event filter handle + * @return The data set for the filter + * + * Delete a filter that has been added by its @p ef handle. On success this + * will return the data pointer set when this filter was added. On failure + * NULL is returned. + */ +void * +ecore_event_filter_del(Ecore_Event_Filter *ef) +{ + if (!ECORE_MAGIC_CHECK(ef, ECORE_MAGIC_EVENT_FILTER)) + { + ECORE_MAGIC_FAIL(ef, ECORE_MAGIC_EVENT_FILTER, + "ecore_event_filter_del"); + return NULL; + } + ef->delete_me = 1; + event_filters_delete_me = 1; + return ef->data; +} + +/** + * Return the current event type being handled. + * @return The current event type being handled if inside a handler callback + * + * If the program is currently inside an Ecore event handler callback this + * will return the type of the current event being processed. If Ecore is + * not inside an event handler, ECORE_EVENT_NONE is returned. + * + * This is useful when certain Ecore modules such as Ecore_Evas "swallow" + * events and not all the original information is passed on. In special cases + * this extra information may be useful or needed and using this call can let + * the program know if the event type being handled is one it wants to get more + * information about. + */ +int +ecore_event_current_type_get(void) +{ + return ecore_raw_event_type; +} + +/** + * Return the current event type pointer handled. + * @return The current event pointer being handled if inside a handler callback + * + * If the program is currently inside an Ecore event handler callback this + * will return the pointer of the current event being processed. If Ecore is + * not inside an event handler, NULL will be returned. + * + * This is useful when certain Ecore modules such as Ecore_Evas "swallow" + * events and not all the original information is passed on. In special cases + * this extra information may be useful or needed and using this call can let + * the program access the event data if the type of the event is handled by + * the program. + */ +void * +ecore_event_current_event_get(void) +{ + return ecore_raw_event_event; +} + +void +_ecore_event_shutdown(void) +{ + int i; + + while (events) _ecore_event_del(events); + for (i = 0; i < event_handlers_num; i++) + { + while (event_handlers[i]) + { + Ecore_Event_Handler *eh; + + eh = event_handlers[i]; + event_handlers[i] = _ecore_list_remove(event_handlers[i], eh); + ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE); + free(eh); + } + } + while (event_handlers_delete_list) + { + Ecore_Oldlist_Data *ehd; + + ehd = event_handlers_delete_list; + event_handlers_delete_list = _ecore_list_remove(event_handlers_delete_list, ehd); + free(ehd); + } + if (event_handlers) free(event_handlers); + event_handlers = NULL; + event_handlers_num = 0; + event_handlers_alloc_num = 0; + while (event_filters) + { + Ecore_Event_Filter *ef; + + ef = event_filters; + event_filters = _ecore_list_remove(event_filters, ef); + ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE); + free(ef); + } + event_filters_delete_me = 0; +} + +int +_ecore_event_exist(void) +{ + if (events) return 1; + return 0; +} + +Ecore_Event * +_ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data) +{ + Ecore_Event *e; + + e = calloc(1, sizeof(Ecore_Event)); + if (!e) return NULL; + ECORE_MAGIC_SET(e, ECORE_MAGIC_EVENT); + e->type = type; + e->event = ev; + e->func_free = func_free; + e->data = data; + events = _ecore_list_append(events, e); + events_num++; + return e; +} + +void * +_ecore_event_del(Ecore_Event *event) +{ + void *data; + + data = event->data; + event->func_free(event->data, event->event); + events = _ecore_list_remove(events, event); + ECORE_MAGIC_SET(event, ECORE_MAGIC_NONE); + free(event); + events_num--; + return data; +} + +void +_ecore_event_call(void) +{ + Ecore_Oldlist *l, *ll; + Ecore_Event *e; + Ecore_Event_Filter *ef; + Ecore_Event_Handler *eh; + Ecore_Oldlist_Data *ehd; + int handle_count; + + for (l = (Ecore_Oldlist *)event_filters; l; l = l->next) + { + ef = (Ecore_Event_Filter *)l; + if (!ef->delete_me) + { + if (ef->func_start) + ef->loop_data = ef->func_start(ef->data); + for (ll = (Ecore_Oldlist *)events; ll; ll = ll->next) + { + Ecore_Event *e; + + e = (Ecore_Event *)ll; + if (!ef->func_filter(ef->loop_data, ef->data, + e->type, e->event)) + { +// printf("FILTER SAID TO DEL ev %p\n", e->event); + ecore_event_del(e); + } + } + if (ef->func_end) + ef->func_end(ef->data, ef->loop_data); + } + } + if (event_filters_delete_me) + { + for (l = (Ecore_Oldlist *)event_filters; l;) + { + ef = (Ecore_Event_Filter *)l; + l = l->next; + if (ef->delete_me) + { + event_filters = _ecore_list_remove(event_filters, ef); + ECORE_MAGIC_SET(ef, ECORE_MAGIC_NONE); + free(ef); + } + } + event_filters_delete_me = 0; + } +// printf("EVENT BATCH...\n"); + for (l = (Ecore_Oldlist *)events; l; l = l->next) + { + e = (Ecore_Event *)l; + if (!e->delete_me) + { + handle_count = 0; + ecore_raw_event_type = e->type; + ecore_raw_event_event = e->event; +// printf("HANDLE ev type %i, %p\n", e->type, e->event); + if ((e->type >= 0) && (e->type < event_handlers_num)) + { + for (ll = (Ecore_Oldlist *)event_handlers[e->type]; ll; ll = ll->next) + { + eh = (Ecore_Event_Handler *)ll; + if (!eh->delete_me) + { + handle_count++; + if (!eh->func(eh->data, e->type, e->event)) + break; /* 0 == "call no further handlers" */ + } + } + } + /* if no handlers were set for EXIT signal - then default is */ + /* to quit the main loop */ + if ((e->type == ECORE_EVENT_SIGNAL_EXIT) && (handle_count == 0)) + ecore_main_loop_quit(); + } + } + ecore_raw_event_type = ECORE_EVENT_NONE; + ecore_raw_event_event = NULL; + + while (events) _ecore_event_del(events); + while (event_handlers_delete_list) + { + ehd = event_handlers_delete_list; + eh = ehd->data; + event_handlers[eh->type] = _ecore_list_remove(event_handlers[eh->type], eh); + event_handlers_delete_list = _ecore_list_remove(event_handlers_delete_list, ehd); + ECORE_MAGIC_SET(eh, ECORE_MAGIC_NONE); + free(eh); + free(ehd); + } +} + +#ifndef WIN32 +void * +_ecore_event_exe_exit_new(void) +{ + Ecore_Event_Exe_Exit *e; + + e = calloc(1, sizeof(Ecore_Event_Exe_Exit)); + return e; +} + +void +_ecore_event_exe_exit_free(void *data __UNUSED__, void *ev) +{ + Ecore_Event_Exe_Exit *e; + + e = ev; + if (e->exe) _ecore_exe_free(e->exe); + free(e); +} +#endif + +void * +_ecore_event_signal_user_new(void) +{ + Ecore_Event_Signal_User *e; + + e = calloc(1, sizeof(Ecore_Event_Signal_User)); + return e; +} + +void * +_ecore_event_signal_hup_new(void) +{ + Ecore_Event_Signal_Hup *e; + + e = calloc(1, sizeof(Ecore_Event_Signal_Hup)); + return e; +} + +void * +_ecore_event_signal_exit_new(void) +{ + Ecore_Event_Signal_Exit *e; + + e = calloc(1, sizeof(Ecore_Event_Signal_Exit)); + return e; +} + +void * +_ecore_event_signal_power_new(void) +{ + Ecore_Event_Signal_Power *e; + + e = calloc(1, sizeof(Ecore_Event_Signal_Power)); + return e; +} + +void * +_ecore_event_signal_realtime_new(void) +{ + return calloc(1, sizeof(Ecore_Event_Signal_Realtime)); +} diff --git a/ecore/src/lib/ecore/ecore_exe.c b/ecore/src/lib/ecore/ecore_exe.c new file mode 100644 index 0000000..a91b35b --- /dev/null +++ b/ecore/src/lib/ecore/ecore_exe.c @@ -0,0 +1,263 @@ +#include "ecore_private.h" +#include "Ecore.h" + +#include <sys/types.h> +#include <signal.h> +#include <unistd.h> + +#ifndef WIN32 +static Ecore_Exe *exes = NULL; + +/** + * @defgroup Ecore_Exe_Basic_Group Process Spawning Functions + * + * Functions that deal with spawned processes. + */ + +/** + * Spawns a child process. + * + * This function forks and runs the given command using @c /bin/sh. + * + * Note that the process handle is only valid until a child process + * terminated event is received. After all handlers for the child process + * terminated event have been called, the handle will be freed by Ecore. + * + * @param exe_cmd The command to run with @c /bin/sh. + * @param data Data to attach to the returned process handle. + * @return A process handle to the spawned process. + * @ingroup Ecore_Exe_Basic_Group + */ +Ecore_Exe * +ecore_exe_run(const char *exe_cmd, const void *data) +{ + Ecore_Exe *exe; + pid_t pid; + + if (!exe_cmd) return NULL; + pid = fork(); + if (pid) + { + exe = calloc(1, sizeof(Ecore_Exe)); + if (!exe) + { + kill(pid, SIGKILL); + return NULL; + } + ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE); + exe->pid = pid; + exe->data = (void *)data; + exes = _ecore_list_append(exes, exe); + return exe; + } + setsid(); + execl("/bin/sh", "/bin/sh", "-c", exe_cmd, (char *)NULL); + exit(127); + return NULL; +} + +/** + * Frees the given process handle. + * + * Note that the process that the handle represents is unaffected by this + * function. + * + * @param exe The given process handle. + * @return The data attached to the handle when @ref ecore_exe_run was + * called. + * @ingroup Ecore_Exe_Basic_Group + */ +void * +ecore_exe_free(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_free"); + return NULL; + } + return _ecore_exe_free(exe); +} + +/** + * Retrieves the process ID of the given spawned process. + * @param exe Handle to the given spawned process. + * @return The process ID on success. @c -1 otherwise. + * @ingroup Ecore_Exe_Basic_Group + */ +pid_t +ecore_exe_pid_get(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_pid_get"); + return -1; + } + return exe->pid; +} + +/** + * Retrieves the data attached to the given process handle. + * @param exe The given process handle. + * @return The data pointer attached to @p exe. + * @ingroup Ecore_Exe_Basic_Group + */ +void * +ecore_exe_data_get(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_data_get"); + return NULL; + } + return exe->data; +} + +/** + * @defgroup Ecore_Exe_Signal_Group Spawned Process Signal Functions + * + * Functions that send signals to spawned processes. + */ + +/** + * Pauses the given process by sending it a @c SIGSTOP signal. + * @param exe Process handle to the given process. + * @ingroup Ecore_Exe_Signal_Group + */ +void +ecore_exe_pause(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_pause"); + return; + } + kill(exe->pid, SIGSTOP); +} + +/** + * Continues the given paused process by sending it a @c SIGCONT signal. + * @param exe Process handle to the given process. + * @ingroup Ecore_Exe_Signal_Group + */ +void +ecore_exe_continue(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_continue"); + return; + } + kill(exe->pid, SIGCONT); +} + +/** + * Sends the given spawned process a terminate (@c SIGTERM) signal. + * @param exe Process handle to the given process. + * @ingroup Ecore_Exe_Signal_Group + */ +void +ecore_exe_terminate(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_terminate"); + return; + } + kill(exe->pid, SIGTERM); +} + +/** + * Kills the given spawned process by sending it a @c SIGKILL signal. + * @param exe Process handle to the given process. + * @ingroup Ecore_Exe_Signal_Group + */ +void +ecore_exe_kill(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_kill"); + return; + } + kill(exe->pid, SIGKILL); +} + +/** + * Sends a @c SIGUSR signal to the given spawned process. + * @param exe Process handle to the given process. + * @param num The number user signal to send. Must be either 1 or 2, or + * the signal will be ignored. + * @ingroup Ecore_Exe_Signal_Group + */ +void +ecore_exe_signal(Ecore_Exe *exe, int num) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_signal"); + return; + } + if (num == 1) + kill(exe->pid, SIGUSR1); + else if (num == 2) + kill(exe->pid, SIGUSR2); +} + +/** + * Sends a @c SIGHUP signal to the given spawned process. + * @param exe Process handle to the given process. + * @ingroup Ecore_Exe_Signal_Group + */ +void +ecore_exe_hup(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, + "ecore_exe_hup"); + return; + } + kill(exe->pid, SIGHUP); +} + +void +_ecore_exe_shutdown(void) +{ + while (exes) _ecore_exe_free(exes); +} + +Ecore_Exe * +_ecore_exe_find(pid_t pid) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)exes; l; l = l->next) + { + Ecore_Exe *exe; + + exe = (Ecore_Exe *)l; + if (exe->pid == pid) return exe; + } + return NULL; +} + +void * +_ecore_exe_free(Ecore_Exe *exe) +{ + void *data; + + data = exe->data; + exes = _ecore_list_remove(exes, exe); + ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE); + free(exe); + return data; +} +#endif diff --git a/ecore/src/lib/ecore/ecore_hash.c b/ecore/src/lib/ecore/ecore_hash.c new file mode 100644 index 0000000..0fde533 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_hash.c @@ -0,0 +1,713 @@ +#include <Ecore.h> + +#define ECORE_HASH_CHAIN_MAX 3 + +#define ECORE_COMPUTE_HASH(hash, key) hash->hash_func(key) % \ + ecore_prime_table[hash->size]; + +#define ECORE_HASH_INCREASE(hash) ((hash && hash->size < PRIME_MAX) ? \ + (hash->nodes / ecore_prime_table[hash->size]) > \ + ECORE_HASH_CHAIN_MAX : FALSE) +#define ECORE_HASH_REDUCE(hash) ((hash && hash->size > PRIME_MIN) ? \ + (double)hash->nodes / (double)ecore_prime_table[hash->size-1] \ + < ((double)ECORE_HASH_CHAIN_MAX * 0.375) : FALSE) + + +/* Private hash manipulation functions */ +static int _ecore_hash_add_node(Ecore_Hash *hash, Ecore_Hash_Node *node); +static Ecore_Hash_Node * _ecore_hash_get_node(Ecore_Hash *hash, void *key); +static int _ecore_hash_increase(Ecore_Hash *hash); +static int _ecore_hash_decrease(Ecore_Hash *hash); +inline int _ecore_hash_rehash(Ecore_Hash *hash, Ecore_List **old_table, int old_size); +static int _ecore_hash_bucket_destroy(Ecore_List *list, Ecore_Free_Cb keyd, + Ecore_Free_Cb valued); +inline Ecore_Hash_Node * _ecore_hash_get_bucket(Ecore_Hash *hash, Ecore_List *bucket, + void *key); + +static Ecore_Hash_Node *_ecore_hash_node_new(void *key, void *value); +static int _ecore_hash_node_init(Ecore_Hash_Node *node, void *key, void *value); +static int _ecore_hash_node_destroy(Ecore_Hash_Node *node, Ecore_Free_Cb keyd, + Ecore_Free_Cb valued); + +/** + * @defgroup Ecore_Data_Hash_ADT_Creation_Group Hash Creation Functions + * + * Functions that create hash tables. + */ + +/** + * Creates and initializes a new hash + * @param hash_func The function for determining hash position. + * @param compare The function for comparing node keys. + * @return @c NULL on error, a new hash on success. + * @ingroup Ecore_Data_Hash_ADT_Creation_Group + */ +Ecore_Hash *ecore_hash_new(Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare) +{ + Ecore_Hash *new_hash = (Ecore_Hash *)malloc(sizeof(Ecore_Hash)); + if (!new_hash) + return NULL; + + if (!ecore_hash_init(new_hash, hash_func, compare)) { + FREE(new_hash); + return NULL; + } + + return new_hash; +} + +/** + * Initializes the given hash. + * @param hash The given hash. + * @param hash_func The function used for hashing node keys. + * @param compare The function used for comparing node keys. + * @return @c TRUE on success, @c FALSE on an error. + * @ingroup Ecore_Data_Hash_ADT_Creation_Group + */ +int ecore_hash_init(Ecore_Hash *hash, Ecore_Hash_Cb hash_func, Ecore_Compare_Cb compare) +{ + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + memset(hash, 0, sizeof(Ecore_Hash)); + + hash->hash_func = hash_func; + hash->compare = compare; + + hash->buckets = (Ecore_List **)malloc(ecore_prime_table[0] * + sizeof(Ecore_List *)); + memset(hash->buckets, 0, ecore_prime_table[0] * sizeof(Ecore_List *)); + + ECORE_INIT_LOCKS(hash); + + return TRUE; +} + +/** + * @defgroup Ecore_Data_Hash_ADT_Destruction_Group Hash Destruction Functions + * + * Functions that destroy hash tables and their contents. + */ + +/** + * Sets the function to destroy the keys of the given hash. + * @param hash The given hash. + * @param function The function used to free the node keys. + * @return @c TRUE on success, @c FALSE on error. + * @ingroup Ecore_Data_Hash_ADT_Destruction_Group + */ +int ecore_hash_set_free_key(Ecore_Hash *hash, Ecore_Free_Cb function) +{ + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("function", function, FALSE); + + ECORE_WRITE_LOCK(hash); + hash->free_key = function; + ECORE_WRITE_UNLOCK(hash); + + return TRUE; +} + +/** + * Sets the function to destroy the values in the given hash. + * @param hash The given hash. + * @param function The function that will free the node values. + * @return @c TRUE on success, @c FALSE on error + * @ingroup Ecore_Data_Hash_ADT_Destruction_Group + */ +int ecore_hash_set_free_value(Ecore_Hash *hash, Ecore_Free_Cb function) +{ + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("function", function, FALSE); + + ECORE_WRITE_LOCK(hash); + hash->free_value = function; + ECORE_WRITE_UNLOCK(hash); + + return TRUE; +} + +/** + * @defgroup Ecore_Data_Hash_ADT_Data_Group Hash Data Functions + * + * Functions that set, access and delete values from the hash tables. + */ + +/** + * Sets a key-value pair in the given hash table. + * @param hash The given hash table. + * @param key The key. + * @param value The value. + * @return @c TRUE if successful, @c FALSE if not. + * @ingroup Ecore_Data_Hash_ADT_Data_Group + */ +int ecore_hash_set(Ecore_Hash *hash, void *key, void *value) +{ + int ret = FALSE; + Ecore_Hash_Node *node; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + ECORE_WRITE_LOCK(hash); + node = _ecore_hash_get_node(hash, key); + if (node) + node->value = value; + else { + node = _ecore_hash_node_new(key, value); + if (node) + ret = _ecore_hash_add_node(hash, node); + } + ECORE_WRITE_UNLOCK(hash); + + return ret; +} + +/** + * Frees the hash table and the data contained inside it. + * @param hash The hash table to destroy. + * @return @c TRUE on success, @c FALSE on error. + * @ingroup Ecore_Data_Hash_ADT_Destruction_Group + */ +void ecore_hash_destroy(Ecore_Hash *hash) +{ + unsigned int i = 0; + + CHECK_PARAM_POINTER("hash", hash); + + ECORE_WRITE_LOCK(hash); + + while (i < ecore_prime_table[hash->size]) { + if (hash->buckets[i]) + _ecore_hash_bucket_destroy(hash->buckets[i], + hash->free_key, hash->free_value); + i++; + } + + FREE(hash->buckets); + + ECORE_WRITE_UNLOCK(hash); + ECORE_DESTROY_LOCKS(hash); + + FREE(hash); + + return; +} + +/** + * @defgroup Ecore_Data_Hash_ADT_Traverse_Group Hash Traverse Functions + * + * Functions that iterate through hash tables. + */ + +/** + * Runs the @p for_each_func function on each entry in the given hash. + * @param hash The given hash. + * @param for_each_func The function that each entry is passed to. + * @param user_data a pointer passed to calls of for_each_func + * @return TRUE on success, FALSE otherwise. + * @ingroup Ecore_Data_Hash_ADT_Traverse_Group + */ +int ecore_hash_for_each_node(Ecore_Hash *hash, Ecore_For_Each for_each_func, + void *user_data) +{ + unsigned int i = 0; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE); + + ECORE_READ_LOCK(hash); + + while (i < ecore_prime_table[hash->size]) { + if (hash->buckets[i]) { + Ecore_Hash_Node *node; + + ecore_list_goto_first(hash->buckets[i]); + while ((node = ecore_list_next(hash->buckets[i]))) { + for_each_func(node, user_data); + } + } + i++; + } + + ECORE_READ_UNLOCK(hash); + + return TRUE; +} + +/** + * Retrieves an ecore_list of all keys in the given hash. + * @param hash The given hash. + * @return new ecore_list on success, NULL otherwise + * @ingroup Ecore_Data_Hash_ADT_Traverse_Group + */ +Ecore_List *ecore_hash_keys(Ecore_Hash *hash) +{ + unsigned int i = 0; + Ecore_List *keys; + + CHECK_PARAM_POINTER_RETURN("hash", hash, NULL); + + ECORE_READ_LOCK(hash); + + keys = ecore_list_new(); + + while (i < ecore_prime_table[hash->size]) { + if (hash->buckets[i]) { + Ecore_Hash_Node *node; + + ecore_list_goto_first(hash->buckets[i]); + while ((node = ecore_list_next(hash->buckets[i]))) { + ecore_list_append(keys, node->key); + } + } + i++; + } + + ECORE_READ_UNLOCK(hash); + + return keys; +} + +/** + * Prints the distribution of the given hash table for graphing. + * @param hash The given hash table. + */ +void +ecore_hash_dump_graph(Ecore_Hash *hash) +{ + unsigned int i; + + for (i = 0; i < ecore_prime_table[hash->size]; i++) + if (hash->buckets[i]) + printf("%d\t%u\n", i, ecore_list_nodes(hash->buckets[i])); + else + printf("%d\t0\n", i); +} + +static int +_ecore_hash_bucket_destroy(Ecore_List *list, Ecore_Free_Cb keyd, Ecore_Free_Cb valued) +{ + Ecore_Hash_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + while ((node = ecore_list_remove_first(list)) != NULL) + _ecore_hash_node_destroy(node, keyd, valued); + + ecore_list_destroy(list); + + return TRUE; +} + +/* + * @brief Add the node to the hash table + * @param hash: the hash table to add the key + * @param node: the node to add to the hash table + * @return Returns FALSE on error, TRUE on success + */ +static int +_ecore_hash_add_node(Ecore_Hash *hash, Ecore_Hash_Node *node) +{ + unsigned int hash_val; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + /* Check to see if the hash needs to be resized */ + if (ECORE_HASH_INCREASE(hash)) + _ecore_hash_increase(hash); + + /* Compute the position in the table */ + if (!hash->hash_func) + hash_val = (unsigned int)node->key % + ecore_prime_table[hash->size]; + else + hash_val = ECORE_COMPUTE_HASH(hash, node->key); + + /* Create the list if it's not already present */ + if (!hash->buckets[hash_val]) + hash->buckets[hash_val] = ecore_list_new(); + + /* Append the node to the list at the index position */ + if (!ecore_list_prepend(hash->buckets[hash_val], node)) + return FALSE; + hash->nodes++; + + return TRUE; +} + +/** + * Retrieves the value associated with the given key from the given hash + * table. + * @param hash The given hash table. + * @param key The key to search for. + * @return The value corresponding to key on success, @c NULL otherwise. + * @ingroup Ecore_Data_Hash_ADT_Data_Group + */ +void *ecore_hash_get(Ecore_Hash *hash, void *key) +{ + void *data; + Ecore_Hash_Node *node; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + node = _ecore_hash_get_node(hash, key); + if (!node) + return NULL; + + ECORE_READ_LOCK(node); + data = node->value; + ECORE_READ_UNLOCK(node); + + return data; +} + + +/** + * Removes the value associated with the given key in the given hash + * table. + * @param hash The given hash table. + * @param key The key to search for. + * @return The value corresponding to the key on success. @c NULL is + * returned if there is an error. + * @ingroup Ecore_Data_Hash_ADT_Data_Group + */ +void *ecore_hash_remove(Ecore_Hash *hash, void *key) +{ + Ecore_Hash_Node *node = NULL; + Ecore_List *list; + unsigned int hash_val; + void *ret = NULL; + + CHECK_PARAM_POINTER_RETURN("hash", hash, NULL); + + ECORE_WRITE_LOCK(hash); + + /* Compute the position in the table */ + if (!hash->hash_func) + hash_val = (unsigned int)key % ecore_prime_table[hash->size]; + else + hash_val = ECORE_COMPUTE_HASH(hash, key); + + /* + * If their is a list that could possibly hold the key/value pair + * traverse it and remove the hash node. + */ + if (hash->buckets[hash_val]) { + list = hash->buckets[hash_val]; + ecore_list_goto_first(list); + + /* + * Traverse the list to find the specified key + */ + if (hash->compare) { + while ((node = ecore_list_current(list)) && + hash->compare(node->key, key) != 0) + ecore_list_next(list); + } + else { + while ((node = ecore_list_current(list)) && + node->key != key) + ecore_list_next(list); + } + + if (node) { + ecore_list_remove(list); + ret = node->value; + node->value = NULL; + _ecore_hash_node_destroy(node, hash->free_key, + hash->free_value); + } + } + + if (ECORE_HASH_REDUCE(hash)) + _ecore_hash_decrease(hash); + + ECORE_WRITE_UNLOCK(hash); + + return ret; +} + +/* + * @brief Retrieve the node associated with key + * @param hash: the hash table to search for the key + * @param key: the key to search for in the hash table + * @return Returns NULL on error, node corresponding to key on success + */ +static Ecore_Hash_Node * +_ecore_hash_get_node(Ecore_Hash *hash, void *key) +{ + unsigned int hash_val; + Ecore_Hash_Node *node = NULL; + + CHECK_PARAM_POINTER_RETURN("hash", hash, NULL); + + ECORE_READ_LOCK(hash); + + /* Compute the position in the table */ + if (!hash->hash_func) + hash_val = (unsigned int)key % ecore_prime_table[hash->size]; + else + hash_val = ECORE_COMPUTE_HASH(hash, key); + + /* Grab the bucket at the specified position */ + if (hash->buckets[hash_val]) + node = _ecore_hash_get_bucket(hash, hash->buckets[hash_val], key); + + ECORE_READ_UNLOCK(hash); + + return node; +} + +/* + * @brief Search the hash bucket for a specified key + * @param hash: the hash table to retrieve the comparison function + * @param bucket: the list to search for the key + * @param key: the key to search for in the list + * @return Returns NULL on error or not found, the found node on success + */ +inline Ecore_Hash_Node * +_ecore_hash_get_bucket(Ecore_Hash *hash, Ecore_List *bucket, void *key) +{ + Ecore_Hash_Node *node = NULL; + + ECORE_READ_LOCK(hash); + ecore_list_goto_first(bucket); + + /* + * Traverse the list to find the desired node, if the node is in the + * list, then return the node. + */ + if (hash->compare) { + while ((node = ecore_list_next(bucket)) != NULL) { + ECORE_READ_LOCK(node); + if (hash->compare(node->key, key) == 0) { + ECORE_READ_UNLOCK(node); + ECORE_READ_UNLOCK(hash); + return node; + } + ECORE_READ_UNLOCK(node); + } + } + else { + while ((node = ecore_list_next(bucket)) != NULL) { + ECORE_READ_LOCK(node); + if (node->key == key) { + ECORE_READ_UNLOCK(node); + ECORE_READ_UNLOCK(hash); + return node; + } + ECORE_READ_UNLOCK(node); + } + } + ECORE_READ_UNLOCK(hash); + + return NULL; +} + +/* + * @brief Increase the size of the hash table by approx. 2 * current size + * @param hash: the hash table to increase the size of + * @return Returns TRUE on success, FALSE on error + */ +static int +_ecore_hash_increase(Ecore_Hash *hash) +{ + void *old; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + /* Max size reached so return FALSE */ + if (hash->size == PRIME_TABLE_MAX) + return FALSE; + + /* + * Increase the size of the hash and save a pointer to the old data + */ + hash->size++; + old = hash->buckets; + + /* + * Allocate a new bucket area, of the new larger size + */ + hash->buckets = (Ecore_List **)calloc(ecore_prime_table[hash->size], + sizeof(Ecore_List *)); + + /* + * Make sure the allocation succeeded, if not replace the old data and + * return a failure. + */ + if (!hash->buckets) { + hash->buckets = old; + hash->size--; + return FALSE; + } + hash->nodes = 0; + + /* + * Now move all of the old data into the new bucket area + */ + if (_ecore_hash_rehash(hash, old, hash->size - 1)) { + FREE(old); + return TRUE; + } + + /* + * Free the old buckets regardless of success. + */ + FREE(old); + + return FALSE; +} + +/* + * @brief Decrease the size of the hash table by < 1/2 * current size + * @param hash: the hash table to decrease the size of + * @return Returns TRUE on success, FALSE on error + */ +static int +_ecore_hash_decrease(Ecore_Hash *hash) +{ + Ecore_List **old; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + + if (ecore_prime_table[hash->size] == PRIME_MIN) + return FALSE; + + /* + * Decrease the hash size and store a pointer to the old data + */ + hash->size--; + old = hash->buckets; + + /* + * Allocate a new area to store the data + */ + hash->buckets = (Ecore_List **)malloc(ecore_prime_table[hash->size] * + sizeof(Ecore_List *)); + + /* + * Make sure allocation succeeded otherwise rreturn to the previous + * state + */ + if (!hash->buckets) { + hash->buckets = old; + hash->size++; + return FALSE; + } + + /* + * Zero out the new area + */ + memset(hash->buckets, 0, ecore_prime_table[hash->size] + * sizeof(Ecore_List *)); + hash->nodes = 0; + + if (_ecore_hash_rehash(hash, old, hash->size - 1)) { + FREE(old); + return TRUE; + } + + return FALSE; +} + +/* + * @brief Rehash the nodes of a table into the hash table + * @param hash: the hash to place the nodes of the table + * @param table: the table to remove the nodes from and place in hash + * @return Returns TRUE on success, FALSE on success + */ +inline int +_ecore_hash_rehash(Ecore_Hash *hash, Ecore_List **old_table, int old_size) +{ + unsigned int i; + Ecore_Hash_Node *node; + Ecore_List *old; + + CHECK_PARAM_POINTER_RETURN("hash", hash, FALSE); + CHECK_PARAM_POINTER_RETURN("old_table", old_table, FALSE); + + for (i = 0; i < ecore_prime_table[old_size]; i++) { + /* Hash into a new list to avoid loops of rehashing the same + * nodes */ + old = old_table[i]; + old_table[i] = NULL; + + /* Loop through re-adding each node to the hash table */ + while (old && (node = ecore_list_remove_last(old))) { + _ecore_hash_add_node(hash, node); + } + + /* Now free up the old list space */ + if (old) + ecore_list_destroy(old); + } + + return TRUE; +} + +/* + * @brief Create a new hash node for key and value storage + * @param key: the key for this node + * @param value: the value that the key references + * @return Returns NULL on error, a new hash node on success + */ +static Ecore_Hash_Node * +_ecore_hash_node_new(void *key, void *value) +{ + Ecore_Hash_Node *node; + + node = (Ecore_Hash_Node *)malloc(sizeof(Ecore_Hash_Node)); + if (!node) + return NULL; + + if (!_ecore_hash_node_init(node, key, value)) { + FREE(node); + return NULL; + } + + return node; +} + +/* + * @brief Initialize a hash node to some sane default values + * @param node: the node to set the values + * @param key: the key to reference this node + * @param value: the value that key refers to + * @return Returns TRUE on success, FALSE on error + */ +static int +_ecore_hash_node_init(Ecore_Hash_Node *node, void *key, void *value) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_INIT_LOCKS(node); + node->key = key; + node->value = value; + + return TRUE; +} + +/* + * @brief Destroy a node and call the specified callbacks to free data + * @param node: the node to be destroyed + * @param keyd: the function to free the key + * @param valued: the function to free the value + * @return Returns TRUE on success, FALSE on error + */ +static int +_ecore_hash_node_destroy(Ecore_Hash_Node *node, Ecore_Free_Cb keyd, + Ecore_Free_Cb valued) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (keyd) + keyd(node->key); + + if (valued) + valued(node->value); + + FREE(node); + + return TRUE; +} diff --git a/ecore/src/lib/ecore/ecore_idle_enterer.c b/ecore/src/lib/ecore/ecore_idle_enterer.c new file mode 100644 index 0000000..7b8c967 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_idle_enterer.c @@ -0,0 +1,105 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static Ecore_Idle_Enterer *idle_enterers = NULL; +static int idle_enterers_delete_me = 0; + +/** + * Add an idle enterer handler. + * @param func The function to call when entering an idle state. + * @param data The data to be passed to the @p func call + * @return A handle to the idle enterer callback if successful. Otherwise, + * NULL is returned. + * @ingroup Idle_Group + */ +Ecore_Idle_Enterer * +ecore_idle_enterer_add(int (*func) (void *data), const void *data) +{ + Ecore_Idle_Enterer *ie; + + if (!func) return NULL; + ie = calloc(1, sizeof(Ecore_Idle_Enterer)); + if (!ie) return NULL; + ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER); + ie->func = func; + ie->data = (void *)data; + idle_enterers = _ecore_list_append(idle_enterers, ie); + return ie; +} + +/** + * Delete an idle enterer callback. + * @param idle_enterer The idle enterer to delete + * @return The data pointer passed to the idler enterer callback on success. + * NULL otherwise. + * @ingroup Idle_Group + */ +void * +ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer) +{ + if (!ECORE_MAGIC_CHECK(idle_enterer, ECORE_MAGIC_IDLE_ENTERER)) + { + ECORE_MAGIC_FAIL(idle_enterer, ECORE_MAGIC_IDLE_ENTERER, + "ecore_idle_enterer_del"); + return NULL; + } + idle_enterer->delete_me = 1; + idle_enterers_delete_me = 1; + return idle_enterer->data; +} + +void +_ecore_idle_enterer_shutdown(void) +{ + while (idle_enterers) + { + Ecore_Idle_Enterer *ie; + + ie = idle_enterers; + idle_enterers = _ecore_list_remove(idle_enterers, ie); + ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE); + free(ie); + } + idle_enterers_delete_me = 0; +} + +void +_ecore_idle_enterer_call(void) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)idle_enterers; l; l = l->next) + { + Ecore_Idle_Enterer *ie; + + ie = (Ecore_Idle_Enterer *)l; + if (!ie->delete_me) + { + if (!ie->func(ie->data)) ecore_idle_enterer_del(ie); + } + } + if (idle_enterers_delete_me) + { + for (l = (Ecore_Oldlist *)idle_enterers; l;) + { + Ecore_Idle_Enterer *ie; + + ie = (Ecore_Idle_Enterer *)l; + l = l->next; + if (ie->delete_me) + { + idle_enterers = _ecore_list_remove(idle_enterers, ie); + ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE); + free(ie); + } + } + idle_enterers_delete_me = 0; + } +} + +int +_ecore_idle_enterer_exist(void) +{ + if (idle_enterers) return 1; + return 0; +} diff --git a/ecore/src/lib/ecore/ecore_idle_exiter.c b/ecore/src/lib/ecore/ecore_idle_exiter.c new file mode 100644 index 0000000..1b8a6ae --- /dev/null +++ b/ecore/src/lib/ecore/ecore_idle_exiter.c @@ -0,0 +1,104 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static Ecore_Idle_Exiter *idle_exiters = NULL; +static int idle_exiters_delete_me = 0; + +/** + * Add an idle exiter handler. + * @param func The function to call when exiting an idle state. + * @param data The data to be passed to the @p func call + * @return A handle to the idle exiter callback on success. NULL otherwise. + * @ingroup Idle_Group + */ +Ecore_Idle_Exiter * +ecore_idle_exiter_add(int (*func) (void *data), const void *data) +{ + Ecore_Idle_Exiter *ie; + + if (!func) return NULL; + ie = calloc(1, sizeof(Ecore_Idle_Exiter)); + if (!ie) return NULL; + ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_EXITER); + ie->func = func; + ie->data = (void *)data; + idle_exiters = _ecore_list_append(idle_exiters, ie); + return ie; +} + +/** + * Delete an idle exiter handler from the list to be run on exiting idle state. + * @param idle_exiter The idle exiter to delete + * @return The data pointer that was being being passed to the handler if + * successful. NULL otherwise. + * @ingroup Idle_Group + */ +void * +ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter) +{ + if (!ECORE_MAGIC_CHECK(idle_exiter, ECORE_MAGIC_IDLE_EXITER)) + { + ECORE_MAGIC_FAIL(idle_exiter, ECORE_MAGIC_IDLE_EXITER, + "ecore_idle_exiter_del"); + return NULL; + } + idle_exiter->delete_me = 1; + idle_exiters_delete_me = 1; + return idle_exiter->data; +} + +void +_ecore_idle_exiter_shutdown(void) +{ + while (idle_exiters) + { + Ecore_Idle_Exiter *ie; + + ie = idle_exiters; + idle_exiters = _ecore_list_remove(idle_exiters, ie); + ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE); + free(ie); + } + idle_exiters_delete_me = 0; +} + +void +_ecore_idle_exiter_call(void) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)idle_exiters; l; l = l->next) + { + Ecore_Idle_Exiter *ie; + + ie = (Ecore_Idle_Exiter *)l; + if (!ie->delete_me) + { + if (!ie->func(ie->data)) ecore_idle_exiter_del(ie); + } + } + if (idle_exiters_delete_me) + { + for (l = (Ecore_Oldlist *)idle_exiters; l;) + { + Ecore_Idle_Exiter *ie; + + ie = (Ecore_Idle_Exiter *)l; + l = l->next; + if (ie->delete_me) + { + idle_exiters = _ecore_list_remove(idle_exiters, ie); + ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE); + free(ie); + } + } + idle_exiters_delete_me = 0; + } +} + +int +_ecore_idle_exiter_exist(void) +{ + if (idle_exiters) return 1; + return 0; +} diff --git a/ecore/src/lib/ecore/ecore_idler.c b/ecore/src/lib/ecore/ecore_idler.c new file mode 100644 index 0000000..4332439 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_idler.c @@ -0,0 +1,106 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static Ecore_Idler *idlers = NULL; +static int idlers_delete_me = 0; + +/** + * Add an idler handler. + * @param func The function to call when idling. + * @param data The data to be passed to this @p func call. + * @return A idler handle if successfully added. NULL otherwise. + * @ingroup Idle_Group + */ +Ecore_Idler * +ecore_idler_add(int (*func) (void *data), const void *data) +{ + Ecore_Idler *ie; + + if (!func) return NULL; + ie = calloc(1, sizeof(Ecore_Idler)); + if (!ie) return NULL; + ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLER); + ie->func = func; + ie->data = (void *)data; + idlers = _ecore_list_append(idlers, ie); + return ie; +} + +/** + * Delete an idler callback from the list to be executed. + * @param idler The handle of the idler callback to delete + * @return The data pointer passed to the idler callback on success. NULL + * otherwise. + * @ingroup Idle_Group + */ +void * +ecore_idler_del(Ecore_Idler *idler) +{ + if (!ECORE_MAGIC_CHECK(idler, ECORE_MAGIC_IDLER)) + { + ECORE_MAGIC_FAIL(idler, ECORE_MAGIC_IDLER, + "ecore_idler_del"); + return NULL; + } + idler->delete_me = 1; + idlers_delete_me = 1; + return idler->data; +} + +void +_ecore_idler_shutdown(void) +{ + while (idlers) + { + Ecore_Idler *ie; + + ie = idlers; + idlers = _ecore_list_remove(idlers, ie); + ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE); + free(ie); + } + idlers_delete_me = 0; +} + +int +_ecore_idler_call(void) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)idlers; l; l = l->next) + { + Ecore_Idler *ie; + + ie = (Ecore_Idler *)l; + if (!ie->delete_me) + { + if (!ie->func(ie->data)) ecore_idler_del(ie); + } + } + if (idlers_delete_me) + { + for (l = (Ecore_Oldlist *)idlers; l;) + { + Ecore_Idler *ie; + + ie = (Ecore_Idler *)l; + l = l->next; + if (ie->delete_me) + { + idlers = _ecore_list_remove(idlers, ie); + ECORE_MAGIC_SET(ie, ECORE_MAGIC_NONE); + free(ie); + } + } + idlers_delete_me = 0; + } + if (idlers) return 1; + return 0; +} + +int +_ecore_idler_exist(void) +{ + if (idlers) return 1; + return 0; +} diff --git a/ecore/src/lib/ecore/ecore_list.c b/ecore/src/lib/ecore/ecore_list.c new file mode 100644 index 0000000..82562b9 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_list.c @@ -0,0 +1,1537 @@ +#include "ecore_private.h" +#include "Ecore.h" + +/* Return information about the list */ +static void *_ecore_list_current(Ecore_List * list); + +/* Adding functions */ +static int _ecore_list_insert(Ecore_List * list, Ecore_List_Node *node); +static int _ecore_list_append_0(Ecore_List * list, Ecore_List_Node *node); +static int _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node *node); + +/* Remove functions */ +static void *_ecore_list_remove_0(Ecore_List * list); +static void *_ecore_list_remove_first(Ecore_List * list); +static void *_ecore_list_remove_last(Ecore_List * list); + +/* Basic traversal functions */ +static void *_ecore_list_next(Ecore_List * list); +static void *_ecore_list_goto_last(Ecore_List * list); +static void *_ecore_list_goto_first(Ecore_List * list); +static void *_ecore_list_goto(Ecore_List * list, void *data); +static void *_ecore_list_goto_index(Ecore_List *list, int index); + +/* Iterative function */ +static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function, + void *user_data); + +/* Private double linked list functions */ +static void *_ecore_dlist_previous(Ecore_DList * list); +static void *_ecore_dlist_remove_first(Ecore_DList *list); +static void *_ecore_dlist_goto_index(Ecore_DList *list, int index); + +/* XXX: Begin deprecated code */ +void * +_ecore_list_append(void *in_list, void *in_item) +{ + Ecore_Oldlist *l, *new_l; + Ecore_Oldlist *list, *item; + + list = in_list; + item = in_item; + new_l = item; + new_l->next = NULL; + if (!list) + { + new_l->prev = NULL; + new_l->last = new_l; + return new_l; + } + if (list->last) l = list->last; + else for (l = list; l; l = l->next); + l->next = new_l; + new_l->prev = l; + list->last = new_l; + return list; +} + +void * +_ecore_list_prepend(void *in_list, void *in_item) +{ + Ecore_Oldlist *new_l; + Ecore_Oldlist *list, *item; + + list = in_list; + item = in_item; + new_l = item; + new_l->prev = NULL; + if (!list) + { + new_l->next = NULL; + new_l->last = new_l; + return new_l; + } + new_l->next = list; + list->prev = new_l; + new_l->last = list->last; + list->last = NULL; + return new_l; +} + +void * +_ecore_list_append_relative(void *in_list, void *in_item, void *in_relative) +{ + Ecore_Oldlist *l; + Ecore_Oldlist *list, *item, *relative; + + list = in_list; + item = in_item; + relative = in_relative; + for (l = list; l; l = l->next) + { + if (l == relative) + { + Ecore_Oldlist *new_l; + + new_l = item; + if (l->next) + { + new_l->next = l->next; + l->next->prev = new_l; + } + + else new_l->next = NULL; + l->next = new_l; + new_l->prev = l; + if (!new_l->next) + list->last = new_l; + return list; + } + } + return _ecore_list_append(list, item); +} + +void * +_ecore_list_prepend_relative(void *in_list, void *in_item, void *in_relative) +{ + Ecore_Oldlist *l; + Ecore_Oldlist *list, *item, *relative; + + list = in_list; + item = in_item; + relative = in_relative; + for (l = list; l; l = l->next) + { + if (l == relative) + { + Ecore_Oldlist *new_l; + + new_l = item; + new_l->prev = l->prev; + new_l->next = l; + l->prev = new_l; + if (new_l->prev) + { + new_l->prev->next = new_l; + if (!new_l->next) + list->last = new_l; + return list; + } + else + { + if (!new_l->next) + new_l->last = new_l; + else + { + new_l->last = list->last; + list->last = NULL; + } + return new_l; + } + } + } + return _ecore_list_prepend(list, item); +} + +void * +_ecore_list_remove(void *in_list, void *in_item) +{ + Ecore_Oldlist *return_l; + Ecore_Oldlist *list, *item; + + /* checkme */ + if(!in_list) + return in_list; + + list = in_list; + item = in_item; + if (!item) return list; + if (item->next) + item->next->prev = item->prev; + if (item->prev) + { + item->prev->next = item->next; + return_l = list; + } + else + { + return_l = item->next; + if (return_l) + return_l->last = list->last; + } + if (item == list->last) + list->last = item->prev; + item->next = NULL; + item->prev = NULL; + return return_l; +} + +void * +_ecore_list_find(void *in_list, void *in_item) +{ + Ecore_Oldlist *l; + Ecore_Oldlist *list, *item; + + list = in_list; + item = in_item; + for (l = list; l; l = l->next) + { + if (l == item) return item; + } + return NULL; +} +/* XXX: End deprecated code */ + +/** +@defgroup Ecore_Data_List_Creation_Group List Creation/Destruction Functions + +Functions that create, initialize and destroy Ecore_Lists. +*/ + +/** + * Create and initialize a new list. + * @return A new initialized list on success, @c NULL on failure. + * @ingroup Ecore_Data_List_Creation_Group + */ +Ecore_List *ecore_list_new() +{ + Ecore_List *list; + + list = (Ecore_List *)malloc(sizeof(Ecore_List)); + if (!list) + return NULL; + + if (!ecore_list_init(list)) { + FREE(list); + return NULL; + } + + return list; +} + +/** + * Initialize a list to some sane starting values. + * @param list The list to initialize. + * @return @c TRUE if successful, @c FALSE if an error occurs. + * @ingroup Ecore_Data_List_Creation_Group + */ +int ecore_list_init(Ecore_List *list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + memset(list, 0, sizeof(Ecore_List)); + + return TRUE; +} + +/** + * Free a list and all of it's nodes. + * @param list The list to be freed. + * @ingroup Ecore_Data_List_Creation_Group + */ +void ecore_list_destroy(Ecore_List * list) +{ + void *data; + + CHECK_PARAM_POINTER("list", list); + + while (list->first) { + data = _ecore_list_remove_first(list); + if (list->free_func) + list->free_func(data); + } + + FREE(list); +} + +/** + * Set the function for freeing data. + * @param list The list that will use this function when nodes are + * destroyed. + * @param free_func The function that will free the key data. + * @return @c TRUE on successful set, @c FALSE otherwise. + */ +int ecore_list_set_free_cb(Ecore_List * list, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + list->free_func = free_func; + + return TRUE; +} + +/** + * Checks the list for any nodes. + * @param list The list to check for nodes + * @return @c TRUE if no nodes in list, @c FALSE if the list contains nodes + */ +int ecore_list_is_empty(Ecore_List * list) +{ + int ret = TRUE; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + if (list->nodes) + ret = FALSE; + + return ret; +} + +/** + * Returns the number of the current node. + * @param list The list to return the number of the current node. + * @return The number of the current node in the list. + */ +int ecore_list_index(Ecore_List * list) +{ + int ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = list->index; + + return ret; +} + +/** + * Find the number of nodes in the list. + * @param list The list to find the number of nodes + * @return The number of nodes in the list. + */ +int ecore_list_nodes(Ecore_List * list) +{ + int ret = 0; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = list->nodes; + + return ret; +} + +/** +@defgroup Ecore_Data_List_Add_Item_Group List Item Adding Functions + +Functions that are used to add nodes to an Ecore_List. +*/ + +/** + * Append data to the list. + * @param list The list. + * @param data The data to append. + * @return @c FALSE if an error occurs, @c TRUE if appended successfully + * @ingroup Ecore_Data_List_Add_Item_Group + */ +inline int ecore_list_append(Ecore_List * list, void *data) +{ + int ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_list_node_new(); + node->data = data; + + ret = _ecore_list_append_0(list, node); + + return ret; +} + +/* For adding items to the end of the list */ +static int _ecore_list_append_0(Ecore_List * list, Ecore_List_Node *end) +{ + if (list->last) { + list->last->next = end; + } + + list->last = end; + + if (list->first == NULL) { + list->first = end; + list->index = 0; + list->current = NULL; + } + + if (list->index >= list->nodes) + list->index++; + + list->nodes++; + + return TRUE; +} + +/** + * Prepend data to the beginning of the list. + * @param list The list. + * @param data The data to prepend. + * @return @c FALSE if an error occurs, @c TRUE if prepended successfully. + * @ingroup Ecore_Data_List_Add_Item_Group + */ +inline int ecore_list_prepend(Ecore_List * list, void *data) +{ + int ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_list_node_new(); + node->data = data; + + ret = _ecore_list_prepend_0(list, node); + + return ret; +} + +/* For adding items to the beginning of the list */ +static int _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node *start) +{ + /* Put it at the beginning of the list */ + start->next = list->first; + + list->first = start; + + /* If no last node, then the first node is the last node */ + if (list->last == NULL) + list->last = list->first; + + list->nodes++; + list->index++; + + return TRUE; +} + +/** + * Insert data in front of the current point in the list. + * @param list The list to hold the inserted @p data. + * @param data The data to insert into @p list. + * @return @c FALSE if there is an error, @c TRUE on success + * @ingroup Ecore_Data_List_Add_Item_Group + */ +inline int ecore_list_insert(Ecore_List * list, void *data) +{ + int ret; + Ecore_List_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_list_node_new(); + node->data = data; + + ret = _ecore_list_insert(list, node); + + return ret; +} + +/* For adding items in front of the current position in the list */ +static int _ecore_list_insert(Ecore_List * list, Ecore_List_Node *new_node) +{ + /* + * If the current point is at the beginning of the list, then it's the + * same as prepending it to the list. + */ + if (list->current == list->first) + return _ecore_list_prepend_0(list, new_node); + + if (list->current == NULL) { + int ret_value; + + ret_value = _ecore_list_append_0(list, new_node); + list->current = list->last; + + return ret_value; + } + + /* Setup the fields of the new node */ + new_node->next = list->current; + + /* And hook the node into the list */ + _ecore_list_goto_index(list, ecore_list_index(list) - 1); + + list->current->next = new_node; + + /* Now move the current item to the inserted item */ + list->current = new_node; + list->index++; + list->nodes++; + + return TRUE; +} + +/** +@defgroup Ecore_Data_List_Remove_Item_Group List Item Removing Functions + +Functions that remove nodes from an Ecore_List. +*/ + +/** + * Remove the current item from the list. + * @param list The list to remove the current item + * @return A pointer to the removed data on success, @c NULL on failure. + * @ingroup Ecore_Data_List_Remove_Item_Group + */ +inline void *ecore_list_remove(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_remove_0(list); + + return ret; +} + +/* Remove the current item from the list */ +static void *_ecore_list_remove_0(Ecore_List * list) +{ + void *ret = NULL; + Ecore_List_Node *old; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (!list->current) + return FALSE; + + if (list->current == list->first) + return _ecore_list_remove_first(list); + + if (list->current == list->last) + return _ecore_list_remove_last(list); + + old = list->current; + + _ecore_list_goto_index(list, list->index - 1); + + list->current->next = old->next; + old->next = NULL; + ret = old->data; + old->data = NULL; + + _ecore_list_next(list); + + ecore_list_node_destroy(old, NULL); + list->nodes--; + + return ret; +} + +/** + * Remove and free the data in lists current position. + * @param list The list to remove and free the current item. + * @return @c TRUE on success, @c FALSE on error + * @ingroup Ecore_Data_List_Remove_Item_Group + */ +int ecore_list_remove_destroy(Ecore_List *list) +{ + void *data; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + data = _ecore_list_remove_0(list); + if (list->free_func) + list->free_func(data); + + return TRUE; +} + +/** + * Remove the first item from the list. + * @param list The list to remove the current item + * @return Returns a pointer to the removed data on success, @c NULL on + * failure. + * @ingroup Ecore_Data_List_Remove_Item_Group + */ +inline void *ecore_list_remove_first(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_remove_first(list); + + return ret; +} + +/* Remove the first item from the list */ +static void *_ecore_list_remove_first(Ecore_List * list) +{ + void *ret = NULL; + Ecore_List_Node *old; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (!list->first) + return FALSE; + + old = list->first; + + list->first = list->first->next; + + if (list->current == old) + list->current = list->first; + else + (list->index ? list->index-- : 0); + + if (list->last == old) + list->last = list->first; + + ret = old->data; + old->data = NULL; + + ecore_list_node_destroy(old, NULL); + list->nodes--; + + return ret; +} + +/** + * Remove the last item from the list. + * @param list The list to remove the last node from + * @return A pointer to the removed data on success, @c NULL on failure. + * @ingroup Ecore_Data_List_Remove_Item_Group + */ +inline void *ecore_list_remove_last(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_remove_last(list); + + return ret; +} + +/* Remove the last item from the list */ +static void *_ecore_list_remove_last(Ecore_List * list) +{ + void *ret = NULL; + Ecore_List_Node *old, *prev; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (!list->last) + return FALSE; + + old = list->last; + if (list->current == old) + list->current = NULL; + + if (list->first == old) + list->first = NULL; + for (prev = list->first; prev && prev->next != old; prev = prev->next); + list->last = prev; + if (prev) { + prev->next = NULL; + if (list->current == old) { + list->current = NULL; + } + } + + + if (old) { + old->next = NULL; + ret = old->data; + old->data = NULL; + } + + ecore_list_node_destroy(old, NULL); + list->nodes--; + + return ret; +} + +/** +@defgroup Ecore_Data_List_Traverse_Group List Traversal Functions + +Functions that can be used to traverse an Ecore_List. +*/ + +/** + * Make the current item the item with the given index number. + * @param list The list. + * @param index The position to move the current item. + * @return A pointer to new current item on success, @c NULL on failure. + * @ingroup Ecore_Data_List_Traverse_Group + */ +inline void *ecore_list_goto_index(Ecore_List * list, int index) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto_index(list, index); + + return ret; +} + +/* This is the non-threadsafe version, use this inside internal functions that + * already lock the list */ +static void *_ecore_list_goto_index(Ecore_List *list, int index) +{ + int i; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(list)) + return FALSE; + + if (index > ecore_list_nodes(list) || index < 0) + return FALSE; + + _ecore_list_goto_first(list); + + for (i = 0; i < index && _ecore_list_next(list); i++); + + if (i >= list->nodes) + return FALSE; + + list->index = i; + + return list->current->data; +} + +/** + * Make the current item the node that contains @p data. + * @param list The list. + * @param data The data to find. + * @return A pointer to @p data on success, @c NULL on failure. + * @ingroup Ecore_Data_List_Traverse_Group + */ +inline void *ecore_list_goto(Ecore_List * list, void *data) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto(list, data); + + return ret; +} + +/* Set the current position to the node containing data */ +static void *_ecore_list_goto(Ecore_List * list, void *data) +{ + int index; + Ecore_List_Node *node; + + if (!list) + return NULL; + + index = 0; + + node = list->first; + while (node && node->data) { + Ecore_List_Node *next; + + if (node->data == data) + break; + + next = node->next; + + node = next; + + index++; + } + + if (!node) + return NULL; + + list->current = node; + list->index = index; + + return list->current->data; +} + +/** + * Make the current item the first item in the list + * @param list The list. + * @return A pointer to the first item on success, @c NULL on failure + * @ingroup Ecore_Data_List_Traverse_Group + */ +inline void *ecore_list_goto_first(Ecore_List *list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto_first(list); + + return ret; +} + +/* Set the current position to the start of the list */ +static void *_ecore_list_goto_first(Ecore_List * list) +{ + if (!list || !list->first) + return NULL; + + list->current = list->first; + list->index = 0; + + return list->current->data; +} + +/** + * Make the current item the last item in the list. + * @param list The list. + * @return A pointer to the last item on success, @c NULL on failure. + * @ingroup Ecore_Data_List_Traverse_Group + */ +inline void *ecore_list_goto_last(Ecore_List * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto_last(list); + + return ret; +} + +/* Set the current position to the end of the list */ +static void *_ecore_list_goto_last(Ecore_List * list) +{ + if (!list || !list->last) + return NULL; + + list->current = list->last; + list->index = (list->nodes - 1); + + return list->current->data; +} + +/** + * Retrieve the data pointed to by the current item in @p list. + * @param list The list. + * @return Returns the data at current position, can be @c NULL. + */ +inline void *ecore_list_current(Ecore_List * list) +{ + void *ret; + + ret = _ecore_list_current(list); + + return ret; +} + +/* Return the data of the current node without incrementing */ +static void *_ecore_list_current(Ecore_List * list) +{ + void *ret; + + if (!list->current) + return NULL; + + ret = list->current->data; + + return ret; +} + +/** + * Retrieve the data pointed to by the current item, and make the next item + * the current item. + * @param list The list to retrieve data from. + * @return The current item in the list on success, @c NULL on failure. + */ +inline void *ecore_list_next(Ecore_List * list) +{ + void *data; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + data = _ecore_list_next(list); + + return data; +} + +/* Return the data contained in the current node and go to the next node */ +static void *_ecore_list_next(Ecore_List * list) +{ + void *data; + Ecore_List_Node *ret; + Ecore_List_Node *next; + + if (!list->current) + return NULL; + + ret = list->current; + next = list->current->next; + + list->current = next; + list->index++; + + data = ret->data; + + return data; +} + +/** + * Remove all nodes from @p list. + * @param list The list. + * @return Returns @c TRUE on success, @c FALSE on error. + * @note The data for each item on the list is not freed by + * @c ecore_list_clear(). + */ +int ecore_list_clear(Ecore_List * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + while (!ecore_list_is_empty(list)) + _ecore_list_remove_first(list); + + return TRUE; +} + +/** + * Execute function for each node in @p list. + * @param list The list. + * @param function The function to pass each node from @p list to. + * @return Returns @c TRUE on success, @c FALSE on failure. + * @ingroup Ecore_Data_List_Traverse_Group + */ +int ecore_list_for_each(Ecore_List *list, Ecore_For_Each function, + void *user_data) +{ + int ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_for_each(list, function, user_data); + + return ret; +} + +/* The real meat of executing the function for each data node */ +static int _ecore_list_for_each(Ecore_List *list, Ecore_For_Each function, + void *user_data) +{ + void *value; + + if (!list || !function) + return FALSE; + + _ecore_list_goto_first(list); + while ((value = _ecore_list_next(list)) != NULL) + function(value, user_data); + + return TRUE; +} + +/* Initialize a node to starting values */ +int ecore_list_node_init(Ecore_List_Node * node) +{ + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + node->next = NULL; + node->data = NULL; + + return TRUE; +} + +/** +@defgroup Ecore_Data_List_Node_Group List Node Functions + +Functions that are used in the creation, maintenance and destruction of +Ecore_List nodes. +*/ + +/** + * Allocates and initializes a new list node. + * @return A new Ecore_List_Node on success, @c NULL otherwise. + * @ingroup Ecore_Data_List_Node_Group + */ +Ecore_List_Node *ecore_list_node_new() +{ + Ecore_List_Node *new_node; + + new_node = malloc(sizeof(Ecore_List_Node)); + + if (!ecore_list_node_init(new_node)) { + FREE(new_node); + return NULL; + } + + return new_node; +} + +/** + * Calls the function to free the data and the node. + * @param node Node to destroy. + * @param free_func Function to call if @p node points to data to free. + * @return @c TRUE. + * @ingroup Ecore_Data_List_Node_Group + */ +int ecore_list_node_destroy(Ecore_List_Node * node, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (free_func && node->data) + free_func(node->data); + + FREE(node); + + return TRUE; +} + +/** + * @defgroup Ecore_Data_DList_Creation_Group Doubly Linked List Creation/Destruction Functions + * + * Functions used to create, initialize and destroy @c Ecore_DLists. + */ + +/** + * Creates and initialises a new doubly linked list. + * @return A new initialised doubly linked list on success, @c NULL + * on failure. + * @ingroup Ecore_Data_DList_Creation_Group + */ +Ecore_DList *ecore_dlist_new() +{ + Ecore_DList *list = NULL; + + list = (Ecore_DList *)malloc(sizeof(Ecore_DList)); + if (!list) + return NULL; + + if (!ecore_dlist_init(list)) { + IF_FREE(list); + return NULL; + } + + return list; +} + +/** + * Initialises a list to some sane starting values. + * @param list The doubly linked list to initialise. + * @return @c TRUE if successful, @c FALSE if an error occurs. + * @ingroup Ecore_Data_DList_Creation_Group + */ +int ecore_dlist_init(Ecore_DList *list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + memset(list, 0, sizeof(Ecore_DList)); + + return TRUE; +} + +/** + * Frees a doubly linked list and all of its nodes. + * @param list The doubly linked list to be freed. + * @ingroup Ecore_Data_DList_Creation_Group + */ +void ecore_dlist_destroy(Ecore_DList * list) +{ + void *data; + CHECK_PARAM_POINTER("list", list); + + while (list->first) { + data = _ecore_dlist_remove_first(list); + if (list->free_func) + list->free_func(data); + } + + FREE(list); +} + +/** + * Sets the function used for freeing data stored in a doubly linked list. + * @param list The doubly linked list that will use this function when + * nodes are destroyed. + * @param free_func The function that will free the key data + * @return @c TRUE on success, @c FALSE on failure. + * @ingroup Ecore_Data_DList_Creation_Group + */ +int ecore_dlist_set_free_cb(Ecore_DList * list, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_set_free_cb(ECORE_LIST(list), free_func); +} + +/** + * Returns whether there is anything in the given doubly linked list. + * @param list The given doubly linked list. + * @return @c TRUE if there are nodes, @c FALSE otherwise. + */ +int ecore_dlist_is_empty(Ecore_DList * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_is_empty(ECORE_LIST(list)); +} + +/** + * Retrieves the index of the current node of the given doubly linked list. + * @param list The given doubly linked list. + * @return The index of the current node. + */ +inline int ecore_dlist_index(Ecore_DList * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + return ecore_list_index(ECORE_LIST(list)); +} + +/** + * @defgroup Ecore_Data_DList_Add_Item_Group Doubly Linked List Adding Functions + * + * Functions that are used to add nodes to an Ecore_DList. + */ + +/** + * Appends data to the given doubly linked list. + * @param list The given doubly linked list. + * @param data The data to append. + * @return @c TRUE if the data is successfully appended, @c FALSE otherwise. + * @ingroup Ecore_Data_DList_Add_Item_Group + */ +int ecore_dlist_append(Ecore_DList * list, void *data) +{ + int ret; + Ecore_DList_Node *prev; + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_dlist_node_new(); + ECORE_LIST_NODE(node)->data = data; + + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->last); + ret = _ecore_list_append_0(ECORE_LIST(list), ECORE_LIST_NODE(node)); + if (ret) { + node->previous = prev; + } + + return ret; +} + +/** + * Adds data to the very beginning of the given doubly linked list. + * @param list The given doubly linked list. + * @param data The data to prepend. + * @return @c TRUE if the data is successfully prepended, @c FALSE otherwise. + * @ingroup Ecore_Data_DList_Add_Item_Group + */ +int ecore_dlist_prepend(Ecore_DList * list, void *data) +{ + int ret; + Ecore_DList_Node *prev; + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + node = ecore_dlist_node_new(); + ECORE_LIST_NODE(node)->data = data; + + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->first); + ret = _ecore_list_prepend_0(ECORE_LIST(list), ECORE_LIST_NODE(node)); + if (ret && prev) + prev->previous = node; + + return ret; +} + +/** + * Inserts data at the current point in the given doubly linked list. + * @param list The given doubly linked list. + * @param data The data to be inserted. + * @return @c TRUE on success, @c FALSE otherwise. + * @ingroup Ecore_Data_DList_Add_Item_Group + */ +int ecore_dlist_insert(Ecore_DList * list, void *data) +{ + int ret; + Ecore_DList_Node *prev; + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->current); + if (!prev) + prev = ECORE_DLIST_NODE(ECORE_LIST(list)->last); + + if (prev) + prev = prev->previous; + + node = ecore_dlist_node_new(); + ECORE_LIST_NODE(node)->data = data; + + ret = _ecore_list_insert(list, ECORE_LIST_NODE(node)); + if (!ret) { + return ret; + } + + if (ECORE_LIST_NODE(node)->next) + ECORE_DLIST_NODE(ECORE_LIST_NODE(node)->next)->previous = node; + + if (prev) + node->previous = prev; + + return ret; +} + +/** + * @defgroup Ecore_Data_DList_Remove_Item_Group Doubly Linked List Removing Functions + * + * Functions that remove nodes from an @c Ecore_DList. + */ + +/** + * Removes the current item from the given doubly linked list. + * @param list The given doubly linked list. + * @return A pointer to the removed data on success, @c NULL otherwise. + * @ingroup Ecore_Data_DList_Remove_Item_Group + */ +void *ecore_dlist_remove(Ecore_DList * list) +{ + void *ret; + Ecore_List *l2 = ECORE_LIST(list); + Ecore_DList_Node *node; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + if (l2->current) { + node = ECORE_DLIST_NODE(list->current->next); + if (node) + node->previous = ECORE_DLIST_NODE(l2->current)->previous; + } + ret = _ecore_list_remove_0(list); + + return ret; +} + +/** + * Removes the first item from the given doubly linked list. + * @param list The given doubly linked list. + * @return A pointer to the removed data on success, @c NULL on failure. + * @ingroup Ecore_Data_DList_Remove_Item_Group + */ +void *ecore_dlist_remove_first(Ecore_DList * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_dlist_remove_first(list); + + return ret; +} + +/** + * Removes and frees the data at the current position in the given doubly + * linked list. + * @param list The given doubly linked list. + * @return @c TRUE on success, @c FALSE otherwise. + * @ingroup Ecore_Data_DList_Remove_Item_Group + */ +int ecore_dlist_remove_destroy(Ecore_DList *list) +{ + void *data; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + data = ecore_dlist_remove(list); + if (!data) + return FALSE; + + if (list->free_func) + list->free_func(data); + + return TRUE; +} + +static void *_ecore_dlist_remove_first(Ecore_DList *list) +{ + void *ret; + + if (!list) + return FALSE; + + ret = _ecore_list_remove_first(list); + if (ret && ECORE_LIST(list)->first) + ECORE_DLIST_NODE(ECORE_LIST(list)->first)->previous = NULL; + + return ret; +} + +/** + * Removes the last item from the given doubly linked list. + * @param list The given doubly linked list. + * @return A pointer to the removed data on success, @c NULL otherwise. + * @ingroup Ecore_Data_DList_Remove_Item_Group + */ +void *ecore_dlist_remove_last(Ecore_DList * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_remove_last(list); + + return ret; +} + +/** + * Moves the current item to the index number in the given doubly linked list. + * @param list The given doubly linked list. + * @param index The position to move the current item + * @return The node at specified index on success, @c NULL on error. + */ +void *ecore_dlist_goto_index(Ecore_DList * list, int index) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_dlist_goto_index(list, index); + + return ret; +} + +/* This is the non-threadsafe version, use this inside internal functions that + * already lock the list */ +static void *_ecore_dlist_goto_index(Ecore_DList *list, int index) +{ + int i, increment; + + if (!list) + return FALSE; + + if (ecore_list_is_empty(ECORE_LIST(list))) + return FALSE; + + if (index > ecore_list_nodes(ECORE_LIST(list)) || index < 0) + return FALSE; + + if (ECORE_LIST(list)->index >= ECORE_LIST(list)->nodes) + _ecore_list_goto_last(ECORE_LIST(list)); + + if (index < ECORE_LIST(list)->index) + increment = -1; + else + increment = 1; + + for (i = ECORE_LIST(list)->index; i != index; i += increment) { + if (increment > 0) + _ecore_list_next(list); + else + _ecore_dlist_previous(list); + } + + return _ecore_list_current(list); +} + +/** + * @brief Move the current item to the node that contains data + * @param list: the list to move the current item in + * @param data: the data to find and set the current item to + * + * @return Returns specified data on success, NULL on error + */ +void *ecore_dlist_goto(Ecore_DList * list, void *data) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto(ECORE_LIST(list), data); + + return ret; +} + +/** + * @brief Move the current pointer to the first item in the list + * @param list: the list to change the current to the first item + * + * @return Returns a pointer to the first item on success, NULL on failure. + */ +void *ecore_dlist_goto_first(Ecore_DList *list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto_first(list); + + return ret; +} + +/** + * @brief Move the pointer to the current item to the last item + * @param list: the list to move the current item pointer to the last + * @return Returns a pointer to the last item in the list , NULL if empty. + */ +void *ecore_dlist_goto_last(Ecore_DList * list) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ret = _ecore_list_goto_last(ECORE_LIST(list)); + + return ret; +} + +/** + * @brief Return the data in the current list item + * @param list: the list to the return the current data + * @return Returns value of the current data item, NULL if no current item + */ +void *ecore_dlist_current(Ecore_DList * list) +{ + void *ret; + + ret = _ecore_list_current(ECORE_LIST(list)); + + return ret; +} + +/** + * @brief Move to the next item in the list and return current item + * @param list: the list to move to the next item in. + * @return Returns data in the current list node, or NULL on error + */ +void *ecore_dlist_next(Ecore_DList * list) +{ + void *data; + + data = _ecore_list_next(list); + + return data; +} + +/** + * @brief Move to the previous item and return current item + * @param list: the list to move to the previous item in. + * @return Returns data in the current list node, or NULL on error + */ +void *ecore_dlist_previous(Ecore_DList * list) +{ + void *data; + + data = _ecore_dlist_previous(list); + + return data; +} + +static void *_ecore_dlist_previous(Ecore_DList * list) +{ + void *data = NULL; + + if (!list) + return NULL; + + if (ECORE_LIST(list)->current) { + data = ECORE_LIST(list)->current->data; + ECORE_LIST(list)->current = ECORE_LIST_NODE(ECORE_DLIST_NODE( + ECORE_LIST(list)->current)->previous); + ECORE_LIST(list)->index--; + } + else + _ecore_list_goto_last(ECORE_LIST(list)); + + return data; +} + +/** + * @brief Remove all nodes from the list. + * @param list: the list to remove all nodes from + * + * @return Returns TRUE on success, FALSE on errors + */ +int ecore_dlist_clear(Ecore_DList * list) +{ + CHECK_PARAM_POINTER_RETURN("list", list, FALSE); + + ecore_list_clear(ECORE_LIST(list)); + + return TRUE; +} + +/* + * @brief Initialize a node to sane starting values + * @param node: the node to initialize + * @return Returns TRUE on success, FALSE on errors + */ +int ecore_dlist_node_init(Ecore_DList_Node * node) +{ + int ret; + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ret = ecore_list_node_init(ECORE_LIST_NODE(node)); + if (ret) + node->previous = NULL; + + return ret; +} + +/* + * @brief Allocate and initialize a new list node + * @return Returns NULL on error, new list node on success + */ +Ecore_DList_Node *ecore_dlist_node_new() +{ + Ecore_DList_Node *new_node; + + new_node = malloc(sizeof(Ecore_DList_Node)); + + if (!new_node) + return NULL; + + if (!ecore_dlist_node_init(new_node)) { + FREE(new_node); + return NULL; + } + + return new_node; +} + +/* + * @brief Call the data's free callback function, then free the node + * @param node: the node to be freed + * @param free_func: the callback function to execute on the data + * @return Returns TRUE on success, FALSE on error + */ +int ecore_dlist_node_destroy(Ecore_DList_Node * node, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("node", node, + FALSE); + + return ecore_list_node_destroy(ECORE_LIST_NODE(node), free_func); +} diff --git a/ecore/src/lib/ecore/ecore_main.c b/ecore/src/lib/ecore/ecore_main.c new file mode 100644 index 0000000..6944db4 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_main.c @@ -0,0 +1,635 @@ +#include "ecore_private.h" +#include "Ecore.h" + +#ifdef WIN32 +#include <winsock.h> +#endif + +#define FIX_HZ 1 + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> + +#ifdef FIX_HZ +#include <sys/param.h> +#ifndef HZ +#define HZ 100 +#endif +#endif + + +static int _ecore_main_select(double timeout); +static void _ecore_main_fd_handlers_cleanup(void); +static void _ecore_main_fd_handlers_call(void); +static int _ecore_main_fd_handlers_buf_call(void); +static void _ecore_main_loop_iterate_internal(int once_only); + +static int in_main_loop = 0; +static int do_quit = 0; +static Ecore_Fd_Handler *fd_handlers = NULL; +static int fd_handlers_delete_me = 0; + +static double t1 = 0.0; +static double t2 = 0.0; + +/** + * @defgroup Ecore_Main_Loop_Group Main Loop Functions + * + * These functions control the Ecore event handling loop. This loop is + * designed to work on embedded systems all the way to large and + * powerful mutli-cpu workstations. + * + * It serialises all system signals and events into a single event + * queue, that can be easily processed without needing to worry about + * concurrency. A properly written, event-driven program using this + * kind of programming does not need threads. It makes the program very + * robust and easy to follow. + * + * Here is an example of simple program and its basic event loop flow: + * @image html prog_flow.png + * + * For examples of setting up and using a main loop, see + * @ref event_handler_example.c and @ref timer_example.c. + */ + +/** + * Runs a single iteration of the main loop to process everything on the + * queue. + * @ingroup Ecore_Main_Loop_Group + */ +void +ecore_main_loop_iterate(void) +{ + _ecore_main_loop_iterate_internal(1); +} + +/** + * Runs the application main loop. + * + * This function will not return until @ref ecore_main_loop_quit is called. + * + * @ingroup Ecore_Main_Loop_Group + */ +void +ecore_main_loop_begin(void) +{ + in_main_loop++; + for (;do_quit == 0;) _ecore_main_loop_iterate_internal(0); + do_quit = 0; + in_main_loop--; +} + +/** + * Quits the main loop once all the events currently on the queue have + * been processed. + * @ingroup Ecore_Main_Loop_Group + */ +void +ecore_main_loop_quit(void) +{ + do_quit = 1; +} + +/** + * @defgroup Ecore_FD_Handler_Group File Event Handling Functions + * + * Functions that deal with file descriptor handlers. + */ + +/** + * Adds a callback for activity on the given file descriptor. + * + * @p func will be called during the execution of @ref ecore_main_loop_begin + * when the file descriptor is available for reading, or writing, or both. + * @p buf_func is called during event loop handling to check if data that has + * been read from the file descriptor is in a buffer and is available to + * read. + * + * @param fd The file descriptor to watch. + * @param flags To watch it for read (@c ECORE_FD_READ) and/or + * (@c ECORE_FD_WRITE) write ability. @c ECORE_FD_ERROR + * + * @param func The callback function. + * @param data The data to pass to the callback. + * @param buf_func The function to call to check if any data has been + * buffered and already read from the fd. Can be @c NULL. + * @param buf_data The data to pass to the @p buf_func function. + * @return A fd handler handle if successful. @c NULL otherwise. + * @ingroup Ecore_FD_Handler_Group + */ +Ecore_Fd_Handler * +ecore_main_fd_handler_add(int fd, Ecore_Fd_Handler_Flags flags, int (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data, int (*buf_func) (void *buf_data, Ecore_Fd_Handler *fd_handler), const void *buf_data) +{ + Ecore_Fd_Handler *fdh; + + if ((fd < 0) || + (flags == 0) || + (!func)) return NULL; + fdh = calloc(1, sizeof(Ecore_Fd_Handler)); + if (!fdh) return NULL; + ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER); + fdh->fd = fd; + fdh->flags = flags; + fdh->read_active = 0; + fdh->write_active = 0; + fdh->error_active = 0; + fdh->delete_me = 0; + fdh->func = func; + fdh->data = (void *)data; + fdh->buf_func = buf_func; + fdh->buf_data = (void *)buf_data; + fd_handlers = _ecore_list_append(fd_handlers, fdh); + return fdh; +} + +/** + * Deletes the given FD handler. + * @param fd_handler The given FD handler. + * @return The data pointer set using @ref ecore_main_fd_handler_add, + * for @p fd_handler on success. @c NULL otherwise. + * @ingroup Ecore_FD_Handler_Group + */ +void * +ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler) +{ + if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) + { + ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, + "ecore_main_fd_handler_del"); + return NULL; + } + fd_handler->delete_me = 1; + fd_handlers_delete_me = 1; + return fd_handler->data; +} + +void +ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler, void (*func) (void *data, Ecore_Fd_Handler *fd_handler), const void *data) +{ + if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) + { + ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, + "ecore_main_fd_handler_prepare_callback_set"); + return; + } + fd_handler->prep_func = func; + fd_handler->prep_data = (void *) data; +} + +/** + * Retrieves the file descriptor that the given handler is handling. + * @param fd_handler The given FD handler. + * @return The file descriptor the handler is watching. + * @ingroup Ecore_FD_Handler_Group + */ +int +ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler) +{ + if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) + { + ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, + "ecore_main_fd_handler_fd_get"); + return -1; + } + return fd_handler->fd; +} + +/** + * Return if read, write or error, or a combination thereof, is active on the + * file descriptor of the given FD handler. + * @param fd_handler The given FD handler. + * @param flags The flags, @c ECORE_FD_READ, @c ECORE_FD_WRITE or + * @c ECORE_FD_ERROR to query. + * @return @c 1 if any of the given flags are active. @c 0 otherwise. + * @ingroup Ecore_FD_Handler_Group + */ +int +ecore_main_fd_handler_active_get(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags) +{ + int ret; + + if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) + { + ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, + "ecore_main_fd_handler_active_get"); + return 0; + } + ret = 0; + if ((flags & ECORE_FD_READ) && (fd_handler->read_active)) ret = 1; + if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = 1; + if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = 1; + return ret; +} + +/** + * Set what active streams the given FD handler should be monitoring. + * @param fd_handler The given FD handler. + * @param flags The flags to be watching. + * @ingroup Ecore_FD_Handler_Group + */ +void +ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler, Ecore_Fd_Handler_Flags flags) +{ + if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER)) + { + ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER, + "ecore_main_fd_handler_active_set"); + return; + } + fd_handler->flags = flags; +} + +void +_ecore_main_shutdown(void) +{ + if (in_main_loop) + { + fprintf(stderr, + "\n" + "*** ECORE WARINING: Calling ecore_shutdown() while still in the main loop.\n" + "*** Program may crash or behave strangely now.\n"); + return; + } + while (fd_handlers) + { + Ecore_Fd_Handler *fdh; + + fdh = fd_handlers; + fd_handlers = _ecore_list_remove(fd_handlers, fdh); + ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); + free(fdh); + } + fd_handlers_delete_me = 0; +} + +static int +_ecore_main_select(double timeout) +{ + struct timeval tv, *t; + fd_set rfds, wfds, exfds; + int max_fd; + int ret; + Ecore_Oldlist *l; + + t = NULL; + if (timeout > 0.0) + { + int sec, usec; + +#ifdef FIX_HZ + timeout += (0.5 / HZ); + sec = (int)timeout; + usec = (int)((timeout - (double)sec) * 1000000); +#else + sec = (int)timeout; + usec = (int)((timeout - (double)sec) * 1000000); +#endif + tv.tv_sec = sec; + tv.tv_usec = usec; + t = &tv; + } + else if (timeout == 0.0) + { + tv.tv_sec = 0; + tv.tv_usec = 0; + t = &tv; + } + max_fd = 0; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&exfds); + + /* call the prepare callback for all handlers */ + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) + { + Ecore_Fd_Handler *fdh; + + fdh = (Ecore_Fd_Handler *)l; + + if (fdh->prep_func) + fdh->prep_func (fdh->prep_data, fdh); + } + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) + { + Ecore_Fd_Handler *fdh; + + fdh = (Ecore_Fd_Handler *)l; + if (fdh->flags & ECORE_FD_READ) + { + FD_SET(fdh->fd, &rfds); + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + if (fdh->flags & ECORE_FD_WRITE) + { + FD_SET(fdh->fd, &wfds); + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + if (fdh->flags & ECORE_FD_ERROR) + { + FD_SET(fdh->fd, &exfds); + if (fdh->fd > max_fd) max_fd = fdh->fd; + } + } +#ifndef WIN32 + if (_ecore_signal_count_get()) return -1; +#endif + ret = select(max_fd + 1, &rfds, &wfds, &exfds, t); + if (ret < 0) + { + if (errno == EINTR) return -1; + } + if (ret > 0) + { + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) + { + Ecore_Fd_Handler *fdh; + + fdh = (Ecore_Fd_Handler *)l; + if (!fdh->delete_me) + { + if (FD_ISSET(fdh->fd, &rfds)) + fdh->read_active = 1; + if (FD_ISSET(fdh->fd, &wfds)) + fdh->write_active = 1; + if (FD_ISSET(fdh->fd, &exfds)) + fdh->error_active = 1; + } + } + _ecore_main_fd_handlers_cleanup(); + return 1; + } + return 0; +} + +static void +_ecore_main_fd_handlers_cleanup(void) +{ + Ecore_Oldlist *l; + + if (!fd_handlers_delete_me) return; + for (l = (Ecore_Oldlist *)fd_handlers; l;) + { + Ecore_Fd_Handler *fdh; + + fdh = (Ecore_Fd_Handler *)l; + l = l->next; + if (fdh->delete_me) + { + fd_handlers = _ecore_list_remove(fd_handlers, fdh); + ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE); + free(fdh); + } + } + fd_handlers_delete_me = 0; +} + +static void +_ecore_main_fd_handlers_call(void) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) + { + Ecore_Fd_Handler *fdh; + + fdh = (Ecore_Fd_Handler *)l; + if (!fdh->delete_me) + { + if ((fdh->read_active) || + (fdh->write_active) || + (fdh->error_active)) + { + if (!fdh->func(fdh->data, fdh)) + { + fdh->delete_me = 1; + fd_handlers_delete_me = 1; + } + fdh->read_active = 0; + fdh->write_active = 0; + fdh->error_active = 0; + } + } + } +} + +static int +_ecore_main_fd_handlers_buf_call(void) +{ + Ecore_Oldlist *l; + int ret; + + ret = 0; + for (l = (Ecore_Oldlist *)fd_handlers; l; l = l->next) + { + Ecore_Fd_Handler *fdh; + + fdh = (Ecore_Fd_Handler *)l; + if (!fdh->delete_me) + { + if (fdh->buf_func) + { + if (fdh->buf_func(fdh->buf_data, fdh)) + { + ret |= fdh->func(fdh->data, fdh); + fdh->read_active = 1; + } + } + } + } + return ret; +} + +static void +_ecore_main_loop_iterate_internal(int once_only) +{ + double next_time; + int have_event = 0; + int have_signal; + + in_main_loop++; + /* expire any timers */ + { + double now; + + now = ecore_time_get(); + while (_ecore_timer_call(now)); + _ecore_timer_cleanup(); + } + /* any timers re-added as a result of these are allowed to go */ + _ecore_timer_enable_new(); +#ifndef WIN32 + /* process signals into events .... */ + while (_ecore_signal_count_get()) _ecore_signal_call(); +#endif + if (_ecore_event_exist()) + { + int ret; + + have_event = 1; + have_signal = 1; + ret = _ecore_main_select(0); + goto process_events; + } + /* call idle enterers ... */ + if (!once_only) + _ecore_idle_enterer_call(); + else + { + int ret; + + have_event = have_signal = 0; + ret = _ecore_main_select(0); + + if (ret > 0) have_event = 1; +#ifndef WIN32 + if (_ecore_signal_count_get() > 0) have_signal = 1; +#endif + + if (have_signal || have_event) + goto process_events; + } + + /* if these calls caused any biuffered events to appear - deal with them */ + while (_ecore_main_fd_handlers_buf_call()); + /* if ther are any - jump to processing them */ + if (_ecore_event_exist()) + { + int ret; + + have_event = 1; + have_signal = 1; + ret = _ecore_main_select(0); + goto process_events; + } + if (once_only) + { + _ecore_idle_enterer_call(); + in_main_loop--; + return; + } + +#ifndef WIN32 + if (_ecore_fps_debug) + { + t2 = ecore_time_get(); + if ((t1 > 0.0) && (t2 > 0.0)) + _ecore_fps_debug_runtime_add(t2 - t1); + } +#endif + start_loop: + if (do_quit) + { + in_main_loop--; + return; + } + if (!_ecore_event_exist()) + { + /* init flags */ + have_event = have_signal = 0; + next_time = _ecore_timer_next_get(); + /* no timers */ + if (next_time < 0) + { + /* no idlers */ + if (!_ecore_idler_exist()) + { + int ret; + + ret = _ecore_main_select(-1); + if (ret > 0) have_event = 1; +#ifndef WIN32 + if (_ecore_signal_count_get() > 0) have_signal = 1; +#endif + } + /* idlers */ + else + { + for (;;) + { + int ret; + + if (!_ecore_idler_call()) goto start_loop; + if (_ecore_event_exist()) break; + ret = _ecore_main_select(0); + if (ret > 0) have_event = 1; +#ifndef WIN32 + if (_ecore_signal_count_get() > 0) have_signal = 1; +#endif + if (have_event || have_signal) break; + next_time = _ecore_timer_next_get(); + if (next_time >= 0) goto start_loop; + if (do_quit) break; + } + } + } + /* timers */ + else + { + /* no idlers */ + if (!_ecore_idler_exist()) + { + int ret; + + ret = _ecore_main_select(next_time); + if (ret > 0) have_event = 1; +#ifndef WIN32 + if (_ecore_signal_count_get() > 0) have_signal = 1; +#endif + } + /* idlers */ + else + { + for (;;) + { + double cur_time, t; + int ret; + + if (!_ecore_idler_call()) goto start_loop; + if (_ecore_event_exist()) break; + ret = _ecore_main_select(0); + if (ret > 0) have_event = 1; +#ifndef WIN32 + if (_ecore_signal_count_get() > 0) have_signal = 1; +#endif + if ((have_event) || (have_signal)) break; + cur_time = ecore_time_get(); + t = ecore_time_get() - cur_time; + if (t >= next_time) break; + next_time = _ecore_timer_next_get(); + if (next_time < 0) goto start_loop; + if (do_quit) break; + } + } + } + } +#ifndef WIN32 + if (_ecore_fps_debug) + { + t1 = ecore_time_get(); + } +#endif + /* we came out of our "wait state" so idle has exited */ + if (!once_only) + _ecore_idle_exiter_call(); + /* call the fd handler per fd that became alive... */ + /* this should read or write any data to the monitored fd and then */ + /* post events onto the ecore event pipe if necessary */ + process_events: + if (have_event) _ecore_main_fd_handlers_call(); + do + { +#ifndef WIN32 + /* process signals into events .... */ + while (_ecore_signal_count_get()) _ecore_signal_call(); +#endif + + /* handle events ... */ + _ecore_event_call(); + _ecore_main_fd_handlers_cleanup(); + } + while (_ecore_main_fd_handlers_buf_call()); + if (once_only) _ecore_idle_enterer_call(); + in_main_loop--; +} diff --git a/ecore/src/lib/ecore/ecore_path.c b/ecore/src/lib/ecore/ecore_path.c new file mode 100644 index 0000000..9202eea --- /dev/null +++ b/ecore/src/lib/ecore/ecore_path.c @@ -0,0 +1,282 @@ +#include <Ecore.h> + +static Ecore_List *group_list = NULL; + +Ecore_Path_Group *__ecore_path_group_find(char *name); +Ecore_Path_Group *__ecore_path_group_find_id(int id); + +/** + * @defgroup Ecore_Path_Group Path Group Functions + * + * Functions that make it easier to find a file in a set of search paths. + * + * @todo Give this a better description. + */ + +/** + * Creates a new path group. + * @param group_name The name of the new group. + * @return @c 0 on error, the integer id of the new group on success. + * @ingroup Ecore_Path_Group + */ +int +ecore_path_group_new(char *group_name) +{ + Ecore_Path_Group *last; + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER_RETURN("group_name", group_name, -1); + + if (!group_list) { + group_list = ecore_list_new(); + } + else { + group = __ecore_path_group_find(group_name); + if (group) + return -1; + } + + group = (Ecore_Path_Group *)malloc(sizeof(Ecore_Path_Group)); + memset(group, 0, sizeof(Ecore_Path_Group)); + + group->name = strdup(group_name); + ecore_list_append(group_list, group); + + last = ecore_list_goto_last(group_list); + group->id = last->id + 1; + + return group->id; +} + +/** + * Destroys a previously created path group + * @param group_id The unique identifier for the group. + * @ingroup Ecore_Path_Group + */ +void +ecore_path_group_del(int group_id) +{ + Ecore_Path_Group *group; + + group = __ecore_path_group_find_id(group_id); + + if (!group) + return; + + if (group->paths) { + ecore_list_for_each(group->paths, + ECORE_FOR_EACH(free), NULL); + ecore_list_destroy(group->paths); + } + + free(group->name); + free(group); +} + +/** + * Adds a directory to be searched for files. + * @param group_id The unique identifier for the group to add the path. + * @param path The new path to be added to the group. + * @ingroup Ecore_Path_Group + */ +void +ecore_path_group_add(int group_id, char *path) +{ + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER("path", path); + + group = __ecore_path_group_find_id(group_id); + + if (!group) + return; + + if (!group->paths) + group->paths = ecore_list_new(); + + ecore_list_append(group->paths, strdup(path)); +} + +/** + * Removes the given directory from the given group. + * @param group_id The identifier for the given group. + * @param path The path of the directory to be removed. + * @ingroup Ecore_Path_Group + */ +void +ecore_path_group_remove(int group_id, char *path) +{ + char *found; + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER("path", path); + + group = __ecore_path_group_find_id(group_id); + + if (!group || !group->paths) + return; + + /* + * Find the path in the list of available paths + */ + ecore_list_goto_first(group->paths); + + while ((found = ecore_list_current(group->paths)) + && strcmp(found, path)) + ecore_list_next(group->paths); + + /* + * If the path is found, remove and free it + */ + if (found) { + ecore_list_remove(group->paths); + free(found); + } +} + +/** + * Finds a file in a group of paths. + * @param group_id The path group id to search. + * @param name The name of the file to find. + * @return A pointer to a newly allocated path location of the found file + * on success. @c NULL on failure. + * @ingroup Ecore_Path_Group + */ +char * +ecore_path_group_find(int group_id, char *name) +{ + int r; + char *p; + struct stat st; + char path[PATH_MAX]; + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER_RETURN("name", name, NULL); + + group = __ecore_path_group_find_id(group_id); + + /* + * Search the paths of the path group for the specified file name + */ + ecore_list_goto_first(group->paths); + p = ecore_list_next(group->paths); + do { + snprintf(path, PATH_MAX, "%s/%s", p, name); + r = stat(path, &st); + } while (((r < 0) || !S_ISREG(st.st_mode)) && + (p = ecore_list_next(group->paths))); + + if (p) + p = strdup(path); + + return p; +} + +/** + * Retrieves a list of all available files in the given path. + * @param group_id The identifier for the given path. + * @return A pointer to a newly allocated list of all files found in the paths + * identified by @p group_id. @c NULL otherwise. + * @ingroup Ecore_Path_Group + */ +Ecore_List * +ecore_path_group_available(int group_id) +{ + Ecore_List *avail = NULL; + Ecore_Path_Group *group; + char *path; + + group = __ecore_path_group_find_id(group_id); + + if (!group || !group->paths || ecore_list_is_empty(group->paths)) + return NULL; + + ecore_list_goto_first(group->paths); + + while ((path = ecore_list_next(group->paths)) != NULL) + { + DIR *dir; + struct stat st; + struct dirent *d; + + stat(path, &st); + + if (!S_ISDIR(st.st_mode)) + continue; + + dir = opendir(path); + + if (!dir) + continue; + + while ((d = readdir(dir)) != NULL) + { + char ppath[PATH_MAX]; + char *ext; + char n[PATH_MAX]; + int l; + + if (!strncmp(d->d_name, ".", 1)) + continue; + + ext = strrchr(d->d_name, '.'); + + if (!ext || strncmp(ext, ".so", 3)) + continue; + + snprintf(ppath, PATH_MAX, "%s/%s", path, d->d_name); + + stat(ppath, &st); + + if (!S_ISREG(st.st_mode)) + continue; + + l = strlen(d->d_name); + + strncpy(n, d->d_name, l - 2); + + if (!avail) + avail = ecore_list_new(); + + ecore_list_append(avail, strdup(n)); + } + } + + return avail; +} + +/* + * Find the specified group name + */ +Ecore_Path_Group * +__ecore_path_group_find(char *name) +{ + Ecore_Path_Group *group; + + CHECK_PARAM_POINTER_RETURN("name", name, NULL); + + ecore_list_goto_first(group_list); + + while ((group = ecore_list_next(group_list)) != NULL) + if (!strcmp(group->name, name)) + return group; + + return NULL; +} + +/* + * Find the specified group id + */ +Ecore_Path_Group * +__ecore_path_group_find_id(int id) +{ + Ecore_Path_Group *group; + + ecore_list_goto_first(group_list); + + while ((group = ecore_list_next(group_list)) != NULL) + if (group->id == id) + return group; + + return NULL; +} diff --git a/ecore/src/lib/ecore/ecore_plugin.c b/ecore/src/lib/ecore/ecore_plugin.c new file mode 100644 index 0000000..42d6203 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_plugin.c @@ -0,0 +1,109 @@ +#include <Ecore.h> + +#ifndef WIN32 +#include <dlfcn.h> + +static Ecore_List *loaded_plugins = NULL; + +/** + * @defgroup Ecore_Plugin Plugin Functions + * + * Functions that load modules of compiled code into memory. + */ + +/** + * Loads the specified plugin from the specified path group. + * @param group_id The path group to search for the plugin to load + * @param plugin_name The name of the plugin to load. + * @return A pointer to the newly loaded plugin on success, @c NULL on + * failure. + * @ingroup Ecore_Plugin + */ +Ecore_Plugin * +ecore_plugin_load(int group_id, char *plugin_name) +{ + char *path; + char temp[PATH_MAX]; + + Ecore_Plugin *plugin; + void *handle = NULL; + + CHECK_PARAM_POINTER_RETURN("plugin_name", plugin_name, NULL); + + snprintf(temp, PATH_MAX, "%s.so", plugin_name); + path = ecore_path_group_find(group_id, temp); + if (!path) + return NULL; + + handle = dlopen(path, RTLD_LAZY); + if (!handle) + return NULL; + + /* + * Allocate the new plugin and initialize it's fields + */ + plugin = malloc(sizeof(Ecore_Plugin)); + memset(plugin, 0, sizeof(Ecore_Plugin)); + + plugin->group = group_id; + plugin->name = strdup(plugin_name); + plugin->handle = handle; + + /* + * Now add it to the list of the groups loaded plugins + */ + if (!loaded_plugins) + loaded_plugins = ecore_list_new(); + + ecore_list_append(loaded_plugins, plugin); + + FREE(path); + + return plugin; +} + +/** + * Unloads the given plugin from memory. + * @param plugin The given plugin. + * @ingroup Ecore_Plugin + */ +void +ecore_plugin_unload(Ecore_Plugin * plugin) +{ + CHECK_PARAM_POINTER("plugin", plugin); + + if (!plugin->handle) + return; + + if (ecore_list_goto(loaded_plugins, plugin)) + ecore_list_remove(loaded_plugins); + + dlclose(plugin->handle); + + FREE(plugin->name); + FREE(plugin); +} + +/* + * Searches for the specified symbol in the given plugin. + * @param plugin The given plugin. + * @param symbol_name The symbol to search for. + * @return Address of the given symbol if successful. Otherwise, @c NULL. + * @ingroup Ecore_Plugin + */ +void * +ecore_plugin_call(Ecore_Plugin * plugin, char *symbol_name) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("plugin", plugin, NULL); + CHECK_PARAM_POINTER_RETURN("symbol_name", symbol_name, NULL); + + if (!plugin->handle) + return NULL; + + ret = dlsym(plugin->handle, symbol_name); + + return ret; +} +#endif diff --git a/ecore/src/lib/ecore/ecore_private.h b/ecore/src/lib/ecore/ecore_private.h new file mode 100644 index 0000000..89a7328 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_private.h @@ -0,0 +1,262 @@ +#ifndef _ECORE_PRIVATE_H +#define _ECORE_PRIVATE_H + +#include <stdio.h> +#include <stdlib.h> +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> +#include <sys/stat.h> +#include <fcntl.h> + +#ifndef WIN32 +#include <sys/mman.h> +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if HAVE___ATTRIBUTE__ +#define __UNUSED__ __attribute__((unused)) +#else +#define __UNUSED__ +#endif + +#define ECORE_MAGIC_NONE 0x1234fedc +#define ECORE_MAGIC_EXE 0xf7e812f5 +#define ECORE_MAGIC_TIMER 0xf7d713f4 +#define ECORE_MAGIC_IDLER 0xf7c614f3 +#define ECORE_MAGIC_IDLE_ENTERER 0xf7b515f2 +#define ECORE_MAGIC_IDLE_EXITER 0xf7601afd +#define ECORE_MAGIC_FD_HANDLER 0xf7a416f1 +#define ECORE_MAGIC_EVENT_HANDLER 0xf79317f0 +#define ECORE_MAGIC_EVENT_FILTER 0xf78218ff +#define ECORE_MAGIC_EVENT 0xf77119fe +#define ECORE_MAGIC_ANIMATOR 0xf7643ea5 + +#define ECORE_MAGIC Ecore_Magic __magic + +#define ECORE_MAGIC_SET(d, m) (d)->__magic = (m) +#define ECORE_MAGIC_CHECK(d, m) ((d) && ((d)->__magic == (m))) +#define ECORE_MAGIC_FAIL(d, m, fn) _ecore_magic_fail((d), (d) ? (d)->__magic : 0, (m), (fn)); + +typedef unsigned int Ecore_Magic; + +typedef struct _Ecore_Oldlist Ecore_Oldlist; +typedef struct _Ecore_Oldlist_Data Ecore_Oldlist_Data; + +struct _Ecore_Oldlist +{ + Ecore_Oldlist *next, *prev; + Ecore_Oldlist *last; +}; + +struct _Ecore_Oldlist_Data +{ + Ecore_Oldlist __list_data; + void *data; +}; + +#ifndef _ECORE_H +enum _Ecore_Fd_Handler_Flags +{ + ECORE_FD_READ = 1, + ECORE_FD_WRITE = 2, + ECORE_FD_ERROR = 4 +}; +typedef enum _Ecore_Fd_Handler_Flags Ecore_Fd_Handler_Flags; + +#ifndef WIN32 +typedef struct _Ecore_Exe Ecore_Exe; +#endif +typedef struct _Ecore_Timer Ecore_Timer; +typedef struct _Ecore_Idler Ecore_Idler; +typedef struct _Ecore_Idle_Enterer Ecore_Idle_Enterer; +typedef struct _Ecore_Idle_Exiter Ecore_Idle_Exiter; +typedef struct _Ecore_Fd_Handler Ecore_Fd_Handler; +typedef struct _Ecore_Event_Handler Ecore_Event_Handler; +typedef struct _Ecore_Event_Filter Ecore_Event_Filter; +typedef struct _Ecore_Event Ecore_Event; +typedef struct _Ecore_Animator Ecore_Animator; + +#ifndef WIN32 +struct _Ecore_Exe +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + pid_t pid; + void *data; +}; +#endif + +struct _Ecore_Timer +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + double in; + double at; + signed char delete_me : 1; + signed char just_added : 1; + int (*func) (void *data); + void *data; +}; + +struct _Ecore_Idler +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int delete_me : 1; + int (*func) (void *data); + void *data; +}; + +struct _Ecore_Idle_Enterer +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int delete_me : 1; + int (*func) (void *data); + void *data; +}; + +struct _Ecore_Idle_Exiter +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int delete_me : 1; + int (*func) (void *data); + void *data; +}; + +struct _Ecore_Fd_Handler +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int fd; + Ecore_Fd_Handler_Flags flags; + int read_active : 1; + int write_active : 1; + int error_active : 1; + int delete_me : 1; + int (*func) (void *data, Ecore_Fd_Handler *fd_handler); + void *data; + int (*buf_func) (void *data, Ecore_Fd_Handler *fd_handler); + void *buf_data; + void (*prep_func) (void *data, Ecore_Fd_Handler *fd_handler); + void *prep_data; +}; + +struct _Ecore_Event_Handler +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int type; + int delete_me : 1; + int (*func) (void *data, int type, void *event); + void *data; +}; + +struct _Ecore_Event_Filter +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int delete_me : 1; + void * (*func_start) (void *data); + int (*func_filter) (void *data, void *loop_data, int type, void *event); + void (*func_end) (void *data, void *loop_data); + void *loop_data; + void *data; +}; + +struct _Ecore_Event +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + int type; + void *event; + int delete_me : 1; + void (*func_free) (void *data, void *ev); + void *data; +}; + +struct _Ecore_Animator +{ + Ecore_Oldlist __list_data; + ECORE_MAGIC; + signed char delete_me : 1; + int (*func) (void *data); + void *data; +}; + +#endif + +void _ecore_magic_fail(void *d, Ecore_Magic m, Ecore_Magic req_m, const char *fname); + +void _ecore_timer_shutdown(void); +void _ecore_timer_cleanup(void); +void _ecore_timer_enable_new(void); +double _ecore_timer_next_get(void); +int _ecore_timer_call(double when); + +void _ecore_idler_shutdown(void); +int _ecore_idler_call(void); +int _ecore_idler_exist(void); + +void _ecore_idle_enterer_shutdown(void); +void _ecore_idle_enterer_call(void); +int _ecore_idle_enterer_exist(void); + +void _ecore_idle_exiter_shutdown(void); +void _ecore_idle_exiter_call(void); +int _ecore_idle_exiter_exist(void); + +void _ecore_event_shutdown(void); +int _ecore_event_exist(void); +Ecore_Event *_ecore_event_add(int type, void *ev, void (*func_free) (void *data, void *ev), void *data); +void *_ecore_event_del(Ecore_Event *event); +void _ecore_event_call(void); + +#ifndef WIN32 +void *_ecore_event_exe_exit_new(void); +void _ecore_event_exe_exit_free(void *data, void *ev); +#endif +void *_ecore_event_signal_user_new(void); +void *_ecore_event_signal_hup_new(void); +void *_ecore_event_signal_exit_new(void); +void *_ecore_event_signal_power_new(void); +void *_ecore_event_signal_realtime_new(void); + +void _ecore_main_shutdown(void); + +void _ecore_signal_shutdown(void); +void _ecore_signal_init(void); +int _ecore_signal_count_get(void); +void _ecore_signal_call(void); + +#ifndef WIN32 +void _ecore_exe_shutdown(void); +Ecore_Exe *_ecore_exe_find(pid_t pid); +void *_ecore_exe_free(Ecore_Exe *exe); +#endif + +void _ecore_animator_shutdown(void); + + +void *_ecore_list_append (void *in_list, void *in_item); +void *_ecore_list_prepend (void *in_list, void *in_item); +void *_ecore_list_append_relative (void *in_list, void *in_item, void *in_relative); +void *_ecore_list_prepend_relative (void *in_list, void *in_item, void *in_relative); +void *_ecore_list_remove (void *in_list, void *in_item); +void *_ecore_list_find (void *in_list, void *in_item); + +void _ecore_fps_debug_init(void); +void _ecore_fps_debug_shutdown(void); +void _ecore_fps_debug_runtime_add(double t); + + + +extern int _ecore_fps_debug; + +#endif diff --git a/ecore/src/lib/ecore/ecore_sheap.c b/ecore/src/lib/ecore/ecore_sheap.c new file mode 100644 index 0000000..b630608 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_sheap.c @@ -0,0 +1,419 @@ +#include <Ecore.h> + +static void _ecore_sheap_heapify(Ecore_Sheap *heap, int i); +static void _ecore_sheap_update_data(Ecore_Sheap *heap); + +/** + * Allocate and initialize a new binary heap + * @param compare The function for comparing keys, NULL for direct comparison + * @param size The number of elements to allow in the heap + * @return A pointer to the newly allocated binary heap on success, NULL on + * failure. + */ +Ecore_Sheap *ecore_sheap_new(Ecore_Compare_Cb compare, int size) +{ + Ecore_Sheap *heap = NULL; + + heap = (Ecore_Sheap *)malloc(sizeof(Ecore_Sheap)); + if (!heap) + return NULL; + memset(heap, 0, sizeof(Ecore_Sheap)); + + if (!ecore_sheap_init(heap, compare, size)) { + FREE(heap); + return NULL; + } + + return heap; +} + +/** + * Initialize a binary heap to default values + * @param heap The heap to initialize + * @param compare The function for comparing keys, NULL for direct comparison + * @param size The number of elements to allow in the heap + * @return TRUE on success, FALSE on failure + */ +int ecore_sheap_init(Ecore_Sheap *heap, Ecore_Compare_Cb compare, int size) +{ + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + heap->space = size; + if (!compare) + heap->compare = ecore_direct_compare; + else + heap->compare = compare; + heap->order = ECORE_SHEAP_MIN; + + heap->data = (void **)malloc(heap->space * sizeof(void *)); + if (!heap->data) + return FALSE; + memset(heap->data, 0, heap->space * sizeof(void *)); + + return TRUE; +} + +/** + * Free up the memory used by the heap + * + * Frees the memory used by @a heap, calls the destroy function on each data + * item if necessary. + * + * @param heap The heap to be freed + */ +void ecore_sheap_destroy(Ecore_Sheap *heap) +{ + int i; + + CHECK_PARAM_POINTER("heap", heap); + + /* + * Free data in heap + */ + if (heap->free_func) + for (i = 0; i < heap->size; i++) + heap->free_func(heap->data[i]); + + FREE(heap->data); + + FREE(heap); +} + +/** + * Set the function for freeing data. + * @param heap The heap that will use this function when nodes are + * destroyed. + * @param free_func The function that will free the key data. + * @return @c TRUE on successful set, @c FALSE otherwise. + */ +int ecore_sheap_set_free_cb(Ecore_Sheap *heap, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + heap->free_func = free_func; + + return TRUE; +} + +/** + * Insert new data into the heap. + * @param heap The heap to insert @a data. + * @param data The data to add to @a heap. + * @return TRUE on success, NULL on failure. Increases the size of the heap if + * it becomes larger than available space. + */ +int ecore_sheap_insert(Ecore_Sheap *heap, void *data) +{ + int i; + void *temp; + int parent; + int position; + + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + /* + * Increase the size of the allocated data area if there isn't enough + * space available to add this data + */ + if (heap->size >= heap->space) + return FALSE; + + heap->sorted = FALSE; + + /* + * Place the data at the end of the heap initially. Then determine the + * parent and position in the array of it's parent. + */ + heap->data[heap->size] = data; + position = heap->size; + heap->size++; + i = heap->size; + parent = PARENT(i) - 1; + + /* + * Check the order of the heap to decide where to place the inserted + * data. The loop is placed inside the if statement to reduce the + * number of branching decisions that must be predicted. + */ + if (heap->order == ECORE_SHEAP_MIN) { + while ((position > 0) && heap->compare(heap->data[parent], + heap->data[position]) > 0) { + + /* + * Swap the data with it's parents to move it up in + * the heap. + */ + temp = heap->data[position]; + heap->data[position] = heap->data[parent]; + heap->data[parent] = temp; + + /* + * Now determine the new position for the next + * iteration of the loop, as well as it's parents + * position. + */ + i = PARENT(i); + position = i - 1; + parent = PARENT(i) - 1; + } + } + else { + while ((position > 0) && heap->compare(heap->data[parent], + heap->data[position]) < 0) { + + /* + * Swap the data with it's parents to move it up in + * the heap. + */ + temp = heap->data[position]; + heap->data[position] = heap->data[PARENT(i) - 1]; + heap->data[PARENT(i) - 1] = temp; + + /* + * Now determine the new position for the next + * iteration of the loop, as well as it's parents + * position. + */ + i = PARENT(i); + position = i - 1; + parent = PARENT(i) - 1; + } + } + + return TRUE; +} + +/** + * Extract the item at the top of the heap + * @param heap The heap to remove the top item + * @return The top item of the heap on success, NULL on failure. + * @note The extract function maintains the heap properties after the + * extract. + */ +void *ecore_sheap_extract(Ecore_Sheap *heap) +{ + void *extreme; + + if (heap->size < 1) + return NULL; + + heap->sorted = FALSE; + + extreme = heap->data[0]; + heap->size--; + heap->data[0] = heap->data[heap->size]; + + _ecore_sheap_heapify(heap, 1); + + return extreme; +} + +/** + * Examine the item at the top of the heap + * @param heap The heap to examine the top item + * @return The top item of the heap on success, NULL on failure. + * @note The function does not alter the heap. + */ +void *ecore_sheap_extreme(Ecore_Sheap *heap) +{ + if (heap->size < 1) + return NULL; + + return heap->data[0]; +} + +/** + * Change the value of the specified item in the heap + * @param heap The heap to search for the item to change + * @param item The item in the heap to change + * @param newval The new value assigned to the item in the heap + * @return TRUE on success, FALSE on failure. + * @note The heap does not free the old data since it must be passed + * in, so the caller can perform the free if desired. + */ +int ecore_sheap_change(Ecore_Sheap *heap, void *item, void *newval) +{ + int i; + + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + for (i = 0; i < heap->size && heap->compare(heap->data[i], item); i++); + + if (i < heap->size) + heap->data[i] = newval; + else + return FALSE; + + /* + * FIXME: This is not the correct procedure when a change occurs. + */ + _ecore_sheap_heapify(heap, 1); + + return TRUE; +} + +/** + * Change the comparison function for the heap + * @param heap The heap to change comparison function + * @param compare The new function for comparing nodes + * @return TRUE on success, FALSE on failure. + * + * The comparison function is changed to @compare and the heap is heapified + * by the new comparison. + */ +int ecore_sheap_set_compare(Ecore_Sheap *heap, Ecore_Compare_Cb compare) +{ + CHECK_PARAM_POINTER_RETURN("heap", heap, FALSE); + + if (!compare) + heap->compare = ecore_direct_compare; + else + heap->compare = compare; + + _ecore_sheap_update_data(heap); + + return TRUE; +} + +/** + * Change the order of the heap + * @param heap The heap to change the order + * @param order The new order of the heap + * + * Changes the heap order of @heap and re-heapifies the data to this new + * order. The default order is a min heap. + */ +void ecore_sheap_set_order(Ecore_Sheap *heap, char order) +{ + CHECK_PARAM_POINTER("heap", heap); + + heap->order = order; + + _ecore_sheap_update_data(heap); +} + +/** + * Sort the data in the heap + * @param heap The heap to be sorted + * + * Sorts the data in the heap into the order that is used for the heap's + * data. + */ +void ecore_sheap_sort(Ecore_Sheap *heap) +{ + int i = 0; + void **new_data; + + CHECK_PARAM_POINTER("heap", heap); + + new_data = (void **)malloc(heap->size * sizeof(void *)); + + /* + * Extract the heap and insert into the new data array in order. + */ + while (heap->size > 0) + new_data[i++] = ecore_sheap_extract(heap); + + /* + * Free the old data array and update the heap with the new data, also + * mark as sorted. + */ + FREE(heap->data); + heap->data = new_data; + heap->size = i; + heap->sorted = TRUE; +} + +/* + * Access the item at the ith position in the heap + * @param heap The heap to access the internal data + * @param i The index of the data within the heap + * @return The data located at the ith position within @heap on success, + * NULL on failure. + * @note The data is guaranteed to be in sorted order. + */ +inline void *ecore_sheap_item(Ecore_Sheap *heap, int i) +{ + if (i >= heap->size) + return NULL; + + /* + * Make sure the data is sorted so we return the correct value. + */ + if (!heap->sorted) + ecore_sheap_sort(heap); + + return heap->data[i]; +} + +/* + * Regain the heap properties starting at position i + * @param heap The heap to regain heap properties + * @param i The position to start heapifying + */ +static void _ecore_sheap_heapify(Ecore_Sheap *heap, int i) +{ + int extreme; + int left = LEFT(i); + int right = RIGHT(i); + + if (heap->order == ECORE_SHEAP_MIN) { + if (left <= heap->size && heap->compare(heap->data[left - 1], + heap->data[i - 1]) < 0) + extreme = left; + else + extreme = i; + + if (right <= heap->size && heap->compare(heap->data[right - 1], + heap->data[extreme - 1]) < 0) + extreme = right; + } + else { + if (left <= heap->size && heap->compare(heap->data[left - 1], + heap->data[i - 1]) > 0) + extreme = left; + else + extreme = i; + + if (right <= heap->size && heap->compare(heap->data[right - 1], + heap->data[extreme - 1]) > 0) + extreme = right; + } + + /* + * If the data needs to be swapped down the heap, recurse on + * heapifying it's new placement. + */ + if (extreme != i) { + void *temp; + + temp = heap->data[extreme - 1]; + heap->data[extreme - 1] = heap->data[i - 1]; + heap->data[i - 1] = temp; + + _ecore_sheap_heapify(heap, extreme); + } +} + +static void _ecore_sheap_update_data(Ecore_Sheap *heap) +{ + int i, old_size; + void **data; + + /* + * Track the old values from the heap + */ + old_size = heap->size; + data = heap->data; + + /* + * + */ + heap->size = 0; + heap->data = malloc(heap->space * sizeof(void *)); + + for (i = 0; i < old_size; i++) + ecore_sheap_insert(heap, data[i]); + + FREE(data); +} diff --git a/ecore/src/lib/ecore/ecore_signal.c b/ecore/src/lib/ecore/ecore_signal.c new file mode 100644 index 0000000..fb45b1b --- /dev/null +++ b/ecore/src/lib/ecore/ecore_signal.c @@ -0,0 +1,455 @@ +#include "ecore_private.h" +#include "Ecore.h" + +#ifndef WIN32 + +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <unistd.h> +#include <assert.h> + +/* make mono happy - this is evil though... */ +#undef SIGPWR +/* valgrind in some versions/setups uses SIGRT's... hmmm */ +/* #undef SIGRTMIN */ + +typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo); + +static void _ecore_signal_callback_set(int sig, Signal_Handler func); +static void _ecore_signal_callback_ignore(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sigchld(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sigusr1(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sigusr2(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sighup(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sigquit(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sigint(int sig, siginfo_t *si, void *foo); +static void _ecore_signal_callback_sigterm(int sig, siginfo_t *si, void *foo); +#ifdef SIGPWR +static void _ecore_signal_callback_sigpwr(int sig, siginfo_t *si, void *foo); +#endif + +#ifdef SIGRTMIN +static void _ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo); +#endif + +static volatile sig_atomic_t sig_count = 0; +static volatile sig_atomic_t sigchld_count = 0; +static volatile sig_atomic_t sigusr1_count = 0; +static volatile sig_atomic_t sigusr2_count = 0; +static volatile sig_atomic_t sighup_count = 0; +static volatile sig_atomic_t sigquit_count = 0; +static volatile sig_atomic_t sigint_count = 0; +static volatile sig_atomic_t sigterm_count = 0; + +static volatile siginfo_t sigchld_info; +static volatile siginfo_t sigusr1_info; +static volatile siginfo_t sigusr2_info; +static volatile siginfo_t sighup_info; +static volatile siginfo_t sigquit_info; +static volatile siginfo_t sigint_info; +static volatile siginfo_t sigterm_info; + +#ifdef SIGPWR +static volatile sig_atomic_t sigpwr_count = 0; +static volatile siginfo_t sigpwr_info = {0}; +#endif + +#ifdef SIGRTMIN +static volatile sig_atomic_t *sigrt_count = NULL; +static volatile siginfo_t *sigrt_info = NULL; +#endif + +void +_ecore_signal_shutdown(void) +{ +#ifdef SIGRTMIN + int i, num = SIGRTMAX - SIGRTMIN; +#endif + + _ecore_signal_callback_set(SIGPIPE, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGALRM, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGCHLD, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGUSR1, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGUSR2, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGHUP, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGQUIT, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGINT, (Signal_Handler) SIG_DFL); + _ecore_signal_callback_set(SIGTERM, (Signal_Handler) SIG_DFL); +#ifdef SIGPWR + _ecore_signal_callback_set(SIGPWR, (Signal_Handler) SIG_DFL); + sigpwr_count = 0; +#endif + sigchld_count = 0; + sigusr1_count = 0; + sigusr2_count = 0; + sighup_count = 0; + sigquit_count = 0; + sigint_count = 0; + sigterm_count = 0; + sig_count = 0; + +#ifdef SIGRTMIN + for (i = 0; i < num; i++) { + _ecore_signal_callback_set(SIGRTMIN + i, (Signal_Handler) SIG_DFL); + sigrt_count[i] = 0; + } + + if (sigrt_count) { + free((sig_atomic_t *) sigrt_count); + sigrt_count = NULL; + } + + if (sigrt_info) { + free((siginfo_t *) sigrt_info); + sigrt_info = NULL; + } +#endif +} + +void +_ecore_signal_init(void) +{ +#ifdef SIGRTMIN + int i, num = SIGRTMAX - SIGRTMIN; +#endif + + _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore); + _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore); + _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld); + _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1); + _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2); + _ecore_signal_callback_set(SIGHUP, _ecore_signal_callback_sighup); + _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit); + _ecore_signal_callback_set(SIGINT, _ecore_signal_callback_sigint); + _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm); +#ifdef SIGPWR + _ecore_signal_callback_set(SIGPWR, _ecore_signal_callback_sigpwr); +#endif + +#ifdef SIGRTMIN + sigrt_count = calloc(1, sizeof(sig_atomic_t) * num); + assert(sigrt_count); + + sigrt_info = calloc(1, sizeof(siginfo_t) * num); + assert(sigrt_info); + + for (i = 0; i < num; i++) + _ecore_signal_callback_set(SIGRTMIN + i, _ecore_signal_callback_sigrt); +#endif +} + +int +_ecore_signal_count_get(void) +{ + return sig_count; +} + +void +_ecore_signal_call(void) +{ +#ifdef SIGRTMIN + int i, num = SIGRTMAX - SIGRTMIN; +#endif + + while (sigchld_count > 0) + { + pid_t pid; + int status; + + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) + { + Ecore_Event_Exe_Exit *e; + + e = _ecore_event_exe_exit_new(); + if (e) + { + if (WIFEXITED(status)) + { + e->exit_code = WEXITSTATUS(status); + e->exited = 1; + } + else if (WIFSIGNALED(status)) + { + e->exit_signal = WTERMSIG(status); + e->signalled = 1; + } + e->pid = pid; + e->exe = _ecore_exe_find(pid); + + if (sigchld_info.si_signo) + e->data = sigchld_info; + + _ecore_event_add(ECORE_EVENT_EXE_EXIT, e, + _ecore_event_exe_exit_free, NULL); + } + } + sigchld_count--; + sig_count--; + } + while (sigusr1_count > 0) + { + Ecore_Event_Signal_User *e; + + e = _ecore_event_signal_user_new(); + if (e) + { + e->number = 1; + + if (sigusr1_info.si_signo) + e->data = sigusr1_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL); + } + sigusr1_count--; + sig_count--; + } + while (sigusr2_count > 0) + { + Ecore_Event_Signal_User *e; + + e = _ecore_event_signal_user_new(); + if (e) + { + e->number = 2; + + if (sigusr2_info.si_signo) + e->data = sigusr2_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL); + } + sigusr2_count--; + sig_count--; + } + while (sighup_count > 0) + { + Ecore_Event_Signal_Hup *e; + + e = _ecore_event_signal_hup_new(); + if (e) + { + if (sighup_info.si_signo) + e->data = sighup_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e, NULL, NULL); + } + sighup_count--; + sig_count--; + } + while (sigquit_count > 0) + { + Ecore_Event_Signal_Exit *e; + + e = _ecore_event_signal_exit_new(); + if (e) + { + e->quit = 1; + + if (sigquit_info.si_signo) + e->data = sigquit_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL); + } + sigquit_count--; + sig_count--; + } + while (sigint_count > 0) + { + Ecore_Event_Signal_Exit *e; + + e = _ecore_event_signal_exit_new(); + if (e) + { + e->interrupt = 1; + + if (sigint_info.si_signo) + e->data = sigint_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL); + } + sigint_count--; + sig_count--; + } + while (sigterm_count > 0) + { + Ecore_Event_Signal_Exit *e; + + e = _ecore_event_signal_exit_new(); + if (e) + { + e->terminate = 1; + + if (sigterm_info.si_signo) + e->data = sigterm_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, NULL, NULL); + } + sigterm_count--; + sig_count--; + } +#ifdef SIGPWR + while (sigpwr_count > 0) + { + Ecore_Event_Signal_Power *e; + + e = _ecore_event_signal_power_new(); + if (e) + { + if (sigpwr_info.si_signo) + e->data = sigpwr_info; + + ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e, NULL, NULL); + } + sigpwr_count--; + sig_count--; + } +#endif + +#ifdef SIGRTMIN + for (i = 0; i < num; i++) + while (sigrt_count[i] > 0) { + Ecore_Event_Signal_Realtime *e; + + if ((e = _ecore_event_signal_realtime_new())) { + e->num = i; + + if (sigrt_info[i].si_signo) + e->data = sigrt_info[i]; + + ecore_event_add(ECORE_EVENT_SIGNAL_REALTIME, e, NULL, NULL); + } + + sigrt_count[i]--; + sig_count--; + } +#endif +} + +static void +_ecore_signal_callback_set(int sig, Signal_Handler func) +{ + struct sigaction sa; + + sa.sa_sigaction = func; + sa.sa_flags = SA_RESTART | SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sigaction(sig, &sa, NULL); +} + +static void +_ecore_signal_callback_ignore(int sig __UNUSED__, siginfo_t *si __UNUSED__, void *foo __UNUSED__) +{ +} + +static void +_ecore_signal_callback_sigchld(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigchld_info = *si; + else + sigchld_info.si_signo = 0; + + sigchld_count++; + sig_count++; +} + +static void +_ecore_signal_callback_sigusr1(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigusr1_info = *si; + else + sigusr1_info.si_signo = 0; + + sigusr1_count++; + sig_count++; +} + +static void +_ecore_signal_callback_sigusr2(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigusr2_info = *si; + else + sigusr2_info.si_signo = 0; + + sigusr2_count++; + sig_count++; +} + +static void +_ecore_signal_callback_sighup(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sighup_info = *si; + else + sighup_info.si_signo = 0; + + sighup_count++; + sig_count++; +} + +static void +_ecore_signal_callback_sigquit(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigquit_info = *si; + else + sigquit_info.si_signo = 0; + + sigquit_count++; + sig_count++; +} + +static void +_ecore_signal_callback_sigint(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigint_info = *si; + else + sigint_info.si_signo = 0; + + sigint_count++; + sig_count++; +} + +static void +_ecore_signal_callback_sigterm(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigterm_info = *si; + else + sigterm_info.si_signo = 0; + + sigterm_count++; + sig_count++; +} + +#ifdef SIGPWR +static void +_ecore_signal_callback_sigpwr(int sig __UNUSED__, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigpwr_info = *si; + else + sigpwr_info.si_signo = 0; + + sigpwr_count++; + sig_count++; +} +#endif + +#ifdef SIGRTMIN +static void +_ecore_signal_callback_sigrt(int sig, siginfo_t *si, void *foo __UNUSED__) +{ + if (si) + sigrt_info[sig - SIGRTMIN] = *si; + else + sigrt_info[sig - SIGRTMIN].si_signo = 0; + + sigrt_count[sig - SIGRTMIN]++; + sig_count++; +} +#endif +#endif diff --git a/ecore/src/lib/ecore/ecore_strings.c b/ecore/src/lib/ecore/ecore_strings.c new file mode 100644 index 0000000..032d2a5 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_strings.c @@ -0,0 +1,79 @@ +#include <Ecore.h> + +static Ecore_Hash *ecore_strings = NULL; + +/** + * @defgroup Ecore_String_Group String Instance Functions + * + * These functions allow you to store one copy of a string, and use it + * throughout your program. + */ + +/** + * Retrieves an instance of a string for use in an ecore program. + * @param string The string to retrieve an instance of. + * @return A pointer to an instance of the string on success. + * @c NULL on failure. + * @ingroup Ecore_String_Group + */ +char *ecore_string_instance(char *string) +{ + Ecore_String *str; + + CHECK_PARAM_POINTER_RETURN("string", string, NULL); + + /* + * No strings have been loaded at this point, so create the hash + * table for storing string info for later. + */ + if (!ecore_strings) + ecore_strings = ecore_hash_new(ecore_str_hash, ecore_str_compare); + + /* + * Check for a previous instance of the string, if not found, create + * it. + */ + str = ecore_hash_get(ecore_strings, string); + if (!str) { + + /* + * Allocate and initialize a new string reference. + */ + str = (Ecore_String *)malloc(sizeof(Ecore_String)); + + str->string = strdup(string); + str->references = 0; + + ecore_hash_set(ecore_strings, str->string, str); + } + + str->references++; + + return str->string; +} + +/** + * Notes that the given string has lost an instance. + * + * It will free the string if no other instances are left. + * + * @param string The given string. + * @ingroup Ecore_String_Group + */ +void ecore_string_release(char *string) +{ + Ecore_String *str; + + CHECK_PARAM_POINTER("string", string); + + str = ecore_hash_get(ecore_strings, string); + if (!str) + return; + + str->references--; + if (str->references < 1) { + ecore_hash_remove(ecore_strings, string); + FREE(str->string); + FREE(str); + } +} diff --git a/ecore/src/lib/ecore/ecore_time.c b/ecore/src/lib/ecore/ecore_time.c new file mode 100644 index 0000000..969f508 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_time.c @@ -0,0 +1,41 @@ +#include "ecore_private.h" +#include "Ecore.h" + +#include <sys/time.h> + +#ifndef HAVE_GETTIMEOFDAY +#ifdef WIN32 +#include <sys/timeb.h> + +static int gettimeofday (struct timeval *tv, void *unused) +{ + struct _timeb t; + + if (!tv) + return -1; + + _ftime (&t); + + tv->tv_sec = t.time; + tv->tv_usec = t.millitm * 1000; + + return 0; +} +#else +#error "Your platform isn't supported yet" +#endif +#endif + +/** + * Retrieves the current system time as a floating point value in seconds. + * @return The number of seconds since 12.00AM 1st January 1970. + * @ingroup Ecore_Time_Group + */ +double +ecore_time_get(void) +{ + struct timeval timev; + + gettimeofday(&timev, NULL); + return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000); +} diff --git a/ecore/src/lib/ecore/ecore_timer.c b/ecore/src/lib/ecore/ecore_timer.c new file mode 100644 index 0000000..3c24291 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_timer.c @@ -0,0 +1,223 @@ +#include "ecore_private.h" +#include "Ecore.h" + +static void _ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data); + +static int timers_added = 0; +static int timers_delete_me = 0; +static Ecore_Timer *timers = NULL; +static double last_check = 0.0; + +/** + * @defgroup Ecore_Time_Group Ecore Time Functions + * + * Functions that deal with time. These functions include those that simply + * retrieve it in a given format, and those that create events based on it. + */ + +/** + * Creates a timer to call the given function in the given period of time. + * @param in The interval in seconds. + * @param func The given function. If @p func returns 1, the timer is + * rescheduled for the next interval @p in. + * @param data Data to pass to @p func when it is called. + * @return A timer object on success. @c NULL on failure. + * @ingroup Ecore_Time_Group + */ +Ecore_Timer * +ecore_timer_add(double in, int (*func) (void *data), const void *data) +{ + double now; + Ecore_Timer *timer; + + if (!func) return NULL; + if (in < 0.0) in = 0.0; + timer = calloc(1, sizeof(Ecore_Timer)); + if (!timer) return NULL; + ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER); + now = ecore_time_get(); + _ecore_timer_set(timer, now + in, in, func, (void *)data); + return timer; +} + +/** + * Delete the specified timer from the timer list. + * @param timer The timer to delete. + * @return The data pointer set for the timer when @ref ecore_timer_add was + * called. @c NULL is returned if the function is unsuccessful. + * @ingroup Ecore_Time_Group + */ +void * +ecore_timer_del(Ecore_Timer *timer) +{ + if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER)) + { + ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER, + "ecore_timer_del"); + return NULL; + } + if (timer->delete_me) return timer->data; + timers_delete_me++; + timer->delete_me = 1; + return timer->data; +} + +/** + * Change the interval the timer ticks of. If set during + * a timer call, this will affect the next interval. + * + * @param timer The timer to change. + * @param in The interval in seconds. + * @ingroup Ecore_Time_Group + */ +void +ecore_timer_interval_set(Ecore_Timer *timer, double in) +{ + if (!ECORE_MAGIC_CHECK(timer, ECORE_MAGIC_TIMER)) + { + ECORE_MAGIC_FAIL(timer, ECORE_MAGIC_TIMER, + "ecore_timer_interval_set"); + return; + } + timer->in = in; +} + +void +_ecore_timer_shutdown(void) +{ + while (timers) + { + Ecore_Timer *timer; + + timer = timers; + timers = _ecore_list_remove(timers, timer); + ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE); + free(timer); + } +} + +void +_ecore_timer_cleanup(void) +{ + Ecore_Oldlist *l; + + if (!timers_delete_me) return; + for (l = (Ecore_Oldlist *)timers; l;) + { + Ecore_Timer *timer; + + timer = (Ecore_Timer *)l; + l = l->next; + if (timer->delete_me) + { + timers = _ecore_list_remove(timers, timer); + ECORE_MAGIC_SET(timer, ECORE_MAGIC_NONE); + free(timer); + timers_delete_me--; + if (timers_delete_me == 0) return; + } + } + timers_delete_me = 0; +} + +void +_ecore_timer_enable_new(void) +{ + Ecore_Oldlist *l; + + if (!timers_added) return; + timers_added = 0; + for (l = (Ecore_Oldlist *)timers; l; l = l->next) + { + Ecore_Timer *timer; + + timer = (Ecore_Timer *)l; + timer->just_added = 0; + } +} + +double +_ecore_timer_next_get(void) +{ + double now; + double in; + + if (!timers) return -1; + now = ecore_time_get(); + in = timers->at - now; + if (in < 0) in = 0; + return in; +} + +int +_ecore_timer_call(double when) +{ + Ecore_Oldlist *l; + Ecore_Timer *timer; + + if (!timers) return 0; + if (last_check > when) + { + /* User set time backwards */ + for (l = (Ecore_Oldlist *)timers; l; l = l->next) + { + timer = (Ecore_Timer *)l; + timer->at -= (last_check - when); + } + } + last_check = when; + for (l = (Ecore_Oldlist *)timers; l; l = l->next) + { + timer = (Ecore_Timer *)l; + if ((timer->at <= when) && + (!timer->just_added) && + (!timer->delete_me)) + { + timers = _ecore_list_remove(timers, timer); + _ecore_timer_call(when); + if ((!timer->delete_me) && (timer->func(timer->data))) + { + /* if the timer would have gone off more than 30 seconds ago, + * assume that the system hung and set the timer to go off + * timer->in from now. + */ + if ((timer->at + timer->in) < (when - 30.0)) + _ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data); + else + _ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data); + } + else + free(timer); + return 1; + } + } + return 0; +} + +static void +_ecore_timer_set(Ecore_Timer *timer, double at, double in, int (*func) (void *data), void *data) +{ + Ecore_Oldlist *l; + + timers_added = 1; + timer->at = at; + timer->in = in; + timer->func = func; + timer->data = data; + timer->just_added = 1; + if (timers) + { + for (l = ((Ecore_Oldlist *)(timers))->last; l; l = l->prev) + { + Ecore_Timer *t2; + + t2 = (Ecore_Timer *)l; + if (timer->at > t2->at) + { + timers = _ecore_list_append_relative(timers, timer, t2); + return; + } + } + } + timers = _ecore_list_prepend(timers, timer); +} diff --git a/ecore/src/lib/ecore/ecore_tree.c b/ecore/src/lib/ecore/ecore_tree.c new file mode 100644 index 0000000..55322dd --- /dev/null +++ b/ecore/src/lib/ecore/ecore_tree.c @@ -0,0 +1,816 @@ +#include <Ecore.h> + +/* A macro for determining the highest node at given branch */ +#define MAX_HEIGHT(node) (node ? MAX(node->max_left, node->max_right) : 0) + +/* Utility functions for searching the tree and returning a node, or its + * parent */ +Ecore_Tree_Node *tree_node_find(Ecore_Tree * tree, void *key); +Ecore_Tree_Node *tree_node_find_parent(Ecore_Tree * tree, void *key); + +/* Balancing functions, keep the tree balanced within a one node height + * difference */ +int tree_node_balance(Ecore_Tree * Tree, Ecore_Tree_Node * top_node); +int tree_node_rotate_right(Ecore_Tree * tree, Ecore_Tree_Node * top_node); +int tree_node_rotate_left(Ecore_Tree * tree, Ecore_Tree_Node * top_node); + +/* Fucntions for executing a specified function on each node of a tree */ +int tree_for_each_node(Ecore_Tree_Node * node, Ecore_For_Each for_each_func, + void *user_data); +int tree_for_each_node_value(Ecore_Tree_Node * node, + Ecore_For_Each for_each_func, void *user_data); + +/** + * @brief Allocate a new tree structure. + * @param compare_func: function used to compare the two values + * @return Returns NULL if the operation fails, otherwise the new tree + */ +Ecore_Tree *ecore_tree_new(Ecore_Compare_Cb compare_func) +{ + Ecore_Tree *new_tree; + + new_tree = ECORE_TREE(malloc(sizeof(Ecore_Tree))); + if (!new_tree) + return NULL; + + if (!ecore_tree_init(new_tree, compare_func)) { + IF_FREE(new_tree); + return NULL; + } + + return new_tree; +} + +/** + * @brief Initialize a tree structure to some sane initial values + * @param new_tree: the new tree structure to be initialized + * @param compare_func: the function used to compare node keys + * @return Returns TRUE on successful initialization, FALSE on an error + */ +int ecore_tree_init(Ecore_Tree * new_tree, Ecore_Compare_Cb compare_func) +{ + CHECK_PARAM_POINTER_RETURN("new_tree", new_tree, FALSE); + + memset(new_tree, 0, sizeof(Ecore_Tree)); + + if (!compare_func) + new_tree->compare_func = ecore_direct_compare; + else + new_tree->compare_func = compare_func; + + ECORE_INIT_LOCKS(new_tree); + + return TRUE; +} + +/* + * @brief Add a function to be called at node destroy time + * @param tree: the tree that will use this function when nodes are destroyed + * @param free_func: the function that will be passed the node being freed + * @return Returns TRUE on successful set, FALSE otherwise. + */ +int ecore_tree_set_free_cb(Ecore_Tree * tree, Ecore_Free_Cb free_func) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_WRITE_LOCK(tree); + tree->free_func = free_func; + ECORE_WRITE_UNLOCK(tree); + + return TRUE; +} + +/* + * @brief Initialize a new tree node + * @return Returns FALSE if the operation fails, otherwise TRUE + */ +int ecore_tree_node_init(Ecore_Tree_Node * new_node) +{ + CHECK_PARAM_POINTER_RETURN("new_node", new_node, FALSE); + + new_node->key = NULL; + new_node->value = NULL; + + new_node->parent = NULL; + new_node->right_child = NULL; + new_node->left_child = NULL; + + new_node->max_left = new_node->max_right = 0; + + ECORE_INIT_LOCKS(new_node); + + return TRUE; +} + +/* + * @brief Allocate a new tree node + * @return Returns NULL if the operation fails, otherwise the new node. + */ +Ecore_Tree_Node *ecore_tree_node_new() +{ + Ecore_Tree_Node *new_node; + + new_node = ECORE_TREE_NODE(malloc(sizeof(Ecore_Tree_Node))); + if (!new_node) + return NULL; + + if (!ecore_tree_node_init(new_node)) { + IF_FREE(new_node); + return NULL; + } + + return new_node; +} + +/* + * @brief Free a tree node and it's children. + * @param node: tree node to be free()'d + * @param data_free: callback for destroying the data held in node + * @return Returns TRUE if the node is destroyed successfully, FALSE if not. + * + * If you don't want the children free'd then you need to remove the node first. + */ +int ecore_tree_node_destroy(Ecore_Tree_Node * node, Ecore_Free_Cb data_free) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_WRITE_LOCK(node); + if (data_free) + data_free(node->value); + ECORE_WRITE_UNLOCK(node); + + ECORE_DESTROY_LOCKS(node); + + FREE(node); + + return TRUE; +} + +/* + * @brief Set the value of the node to value + * @param node: the node to be set + * @param value: the value to set the node to. + * @return Returns TRUE if the node is set successfully, FALSE if not. + */ +int ecore_tree_node_value_set(Ecore_Tree_Node * node, void *value) +{ + CHECK_PARAM_POINTER_RETURN("node", node, + FALSE); + + ECORE_WRITE_LOCK(node); + node->value = value; + ECORE_WRITE_UNLOCK(node); + + return TRUE; +} + +/* + * @brief Get the value of the node + * @param node: the node that contains the desired value + * @return Returns NULL if an error, otherwise the value associated with node + */ +void *ecore_tree_node_value_get(Ecore_Tree_Node * node) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + ECORE_READ_LOCK(node); + ret = node->value; + ECORE_READ_UNLOCK(node); + + return ret; +} + +/* + * @brief Set the value of the node's key to key + * @param node: the node to be set + * @param key: the value to set it's key to. + * @return Returns TRUE if the node is set successfully, FALSE if not. + */ +int ecore_tree_node_key_set(Ecore_Tree_Node * node, void *key) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + ECORE_WRITE_LOCK(node); + node->key = key; + ECORE_WRITE_UNLOCK(node); + + return TRUE; +} + +/* + * @brief Get the value of the node's key + * @param node: the node that contains the desired key + * + * @return Returns NULL if an error occurs, otherwise the key is returned + */ +void *ecore_tree_node_key_get(Ecore_Tree_Node * node) +{ + void *ret; + + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + ECORE_READ_LOCK(node); + ret = node->key; + ECORE_READ_UNLOCK(node); + + return ret; +} + +/** + * @brief Free the tree and it's stored data + * @param tree: the tree to destroy + * + * @return Returns TRUE if tree destroyed successfully, FALSE if not. + */ +int ecore_tree_destroy(Ecore_Tree * tree) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_WRITE_LOCK(tree); + while ((node = tree->tree)) { + ecore_tree_remove_node(tree, node); + ecore_tree_node_destroy(node, tree->free_func); + } + ECORE_WRITE_UNLOCK(tree); + ECORE_DESTROY_LOCKS(tree); + + FREE(tree); + + return TRUE; +} + +/** + * @brief Return the node corresponding to key + * @param tree: the tree to search + * @param key: the key to search for in the tree + * + * @return Returns the node corresponding to the key if found, otherwise NULL. + */ +Ecore_Tree_Node *ecore_tree_get_node(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *ret; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + ret = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + return ret; +} + +/** + * @brief Return the value corresponding to key + * @param tree: the tree to search + * @param key: the key to search for in @a tree + * @return Returns the value corresponding to the key if found, otherwise NULL. + */ +void *ecore_tree_get(Ecore_Tree * tree, void *key) +{ + void *ret; + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + ECORE_READ_LOCK(node); + ret = (node ? node->value : NULL); + ECORE_READ_UNLOCK(node); + + return ret; +} + +/** + * @brief Find the closest value greater than or equal to the key. + * @param tree The tree to search. + * @param key The key to search for in @a tree. + * @return NULL if no valid nodes, otherwise the node greater than or + * equal to the key + */ +void *ecore_tree_get_closest_larger(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + if (node) + return node; + + ECORE_READ_LOCK(tree); + node = tree_node_find_parent(tree, key); + + if (!node) { + ECORE_READ_UNLOCK(tree); + return NULL; + } + + ECORE_READ_LOCK(node); + if (tree->compare_func(node->key, key) < 0) + return NULL; + ECORE_READ_UNLOCK(node); + ECORE_READ_UNLOCK(tree); + + return node; +} + +/** + * @brief Find the closest value <= key + * @param tree the tree to search + * @param key the key to search for in tree + * @return Returns NULL if no valid nodes, otherwise the node <= key + */ +void *ecore_tree_get_closest_smaller(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + if (node) + return node; + + ECORE_READ_LOCK(tree); + node = tree_node_find_parent(tree, key); + ECORE_READ_LOCK(tree); + + if (node) + node = node->right_child; + + return node; +} + +/** + * Set the value associated with key to @a value. + * @param tree The tree that contains the key/value pair. + * @param key The key to identify which node to set a value. + * @param value Value to set the found node. + * @return TRUE if successful, FALSE if not. + */ +int ecore_tree_set(Ecore_Tree * tree, void *key, void *value) +{ + Ecore_Tree_Node *node = NULL; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + ECORE_READ_LOCK(tree); + node = tree_node_find(tree, key); + ECORE_READ_UNLOCK(tree); + + if (!node) { + node = ecore_tree_node_new(); + ecore_tree_node_key_set(node, key); + if (!ecore_tree_add_node(tree, node)) + return FALSE; + } + ecore_tree_node_value_set(node, value); + + ECORE_WRITE_LOCK(tree); + for (; node; node = node->parent) + tree_node_balance(tree, node); + ECORE_WRITE_UNLOCK(tree); + + return TRUE; +} + +/** + * Place a node in the tree. + * @param tree The tree to add @a node. + * @param node The node to add to @a tree. + * @return TRUE on a successful add, FALSE otherwise. + */ +int ecore_tree_add_node(Ecore_Tree * tree, Ecore_Tree_Node * node) +{ + Ecore_Tree_Node *travel = NULL; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + /* Find where to put this new node. */ + if (!tree->tree) { + tree->tree = node; + } else { + travel = tree_node_find_parent(tree, node->key); + node->parent = travel; + + /* The node is less than travel */ + if (tree->compare_func(node->key, travel->key) < 0) { + travel->right_child = node; + travel->max_left = 1; + /* The node is greater than travel */ + } else { + travel->left_child = node; + travel->max_right = 1; + } + } + + return TRUE; +} + + +/** + * Remove the node from the tree. + * @param tree The tree to remove @a node from. + * @param node The node to remove from @a tree. + * @return TRUE on a successful remove, FALSE otherwise. + */ +int ecore_tree_remove_node(Ecore_Tree * tree, Ecore_Tree_Node * node) +{ + Ecore_Tree_Node *traverse; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + /* + * Find the nearest value to the balanced one. + */ + if (node->left_child) { + traverse = node->left_child; + + /* Now work our way down right side of the traverse node. + * This will give us the node with the next closest value + * to the current node. If traverse had no right node, then + * this will stop at node's left node. */ + while (traverse->right_child) { + traverse = traverse->right_child; + } + + /* + * Hook any dropped leaves into the moved nodes spot + */ + if (traverse->parent) + traverse->parent->left_child = traverse->left_child; + } + else if (node->right_child) { + traverse = node->right_child; + + /* Now work our way down left side of the traverse node. + * This will give us the node with the next closest value + * to the current node. If traverse had no left node, then + * this will stop at node's right node. */ + while (traverse->left_child) { + traverse = traverse->left_child; + } + + /* + * Hook any dropped leaves into the moved nodes spot + */ + if (traverse->right_child) + traverse->right_child->parent = traverse->parent; + + if (traverse->parent) + traverse->parent->right_child = traverse->right_child; + else + tree->tree = traverse->right_child; + } + else + traverse = NULL; + + if (traverse) { + + /* + * Ensure that we don't get a recursive reference. + */ + if (node->right_child && node->right_child != traverse) { + node->right_child->parent = traverse; + traverse->right_child = node->right_child; + } + + if (node->left_child && node->left_child != traverse) { + node->left_child->parent = traverse; + traverse->left_child = node->left_child; + } + + /* + * Unlink the node to be moved from it's parent. + */ + if (traverse->parent) { + if (traverse->parent->left_child == traverse) + traverse->parent->left_child = NULL; + else + traverse->parent->right_child = NULL; + } + traverse->parent = node->parent; + } + + if (node->parent) { + if (node == node->parent->left_child) + node->parent->left_child = traverse; + else + node->parent->right_child = traverse; + } + + if (tree->tree == node) + tree->tree = traverse; + + node->parent = node->left_child = node->right_child = NULL; + + /* + * Rebalance the tree to ensure short search paths. + */ + while (traverse) { + tree_node_balance(tree, traverse); + traverse = traverse->parent; + } + + return TRUE; +} + +/** + * Remove the key from the tree. + * @param tree The tree to remove @a key. + * @param key The key to remove from @a tree. + * @return TRUE on a successful remove, FALSE otherwise. + */ +int ecore_tree_remove(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + if (!tree->tree) + return FALSE; + + /* Find the node we need to remove */ + node = tree_node_find(tree, key); + if (!node) + return FALSE; + + if (!ecore_tree_remove_node(tree, node)) + return FALSE; + + ecore_tree_node_destroy(node, tree->free_func); + + return TRUE; +} + +/** + * @brief Test to see if the tree has any nodes + * @param tree: the tree to check for nodes + * @return Returns TRUE if no nodes exist, FALSE otherwise + */ +int ecore_tree_is_empty(Ecore_Tree * tree) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + if (!tree->tree) + return TRUE; + + return FALSE; +} + +/** + * @brief Execute function for each value in the tree + * @param tree: the tree to traverse + * @param for_each_func: the function to execute for each value in the tree + * @param user_data: data passed to each for_each_func call + * @return Returns TRUE on success, FALSE on failure. + */ +int ecore_tree_for_each_node_value(Ecore_Tree * tree, + Ecore_For_Each for_each_func, void *user_data) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE); + + if (!tree->tree) + return FALSE; + + return tree_for_each_node_value(tree->tree, for_each_func, user_data); +} + +/** + * @brief Execute the function for each node in the tree + * @param tree: the tree to traverse + * @param for_each_func: the function to execute for each node + * @param user_data: data passed to each for_each_func call + * @return Returns TRUE on success, FALSE on failure. + */ +int ecore_tree_for_each_node(Ecore_Tree * tree, Ecore_For_Each for_each_func, + void *user_data) +{ + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + CHECK_PARAM_POINTER_RETURN("for_each_func", for_each_func, FALSE); + + if (!tree->tree) + return FALSE; + + return tree_for_each_node(tree->tree, for_each_func, user_data); +} + +/* Find the parent for the key */ +Ecore_Tree_Node *tree_node_find_parent(Ecore_Tree * tree, void *key) +{ + Ecore_Tree_Node *parent, *travel; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + parent = tree_node_find(tree, key); + if (parent) + parent = parent->parent; + + travel = tree->tree; + if (!travel) + return NULL; + + while (!parent) { + int compare; + + if ((compare = tree->compare_func(key, travel->key)) < 0) { + if (!travel->right_child) + parent = travel; + travel = travel->right_child; + } else { + if (!travel->left_child) + parent = travel; + travel = travel->left_child; + } + } + + return parent; +} + +/* Search for the node with a specified key */ +Ecore_Tree_Node *tree_node_find(Ecore_Tree * tree, void *key) +{ + int compare; + Ecore_Tree_Node *node; + + CHECK_PARAM_POINTER_RETURN("tree", tree, FALSE); + + node = tree->tree; + while (node && (compare = tree->compare_func(key, node->key)) != 0) { + + if (compare < 0) { + if (!node->right_child) { + return NULL; + } + + node = node->right_child; + } else { + if (!node->left_child) { + return NULL; + } + + node = node->left_child; + } + } + + return node; +} + +/* Balance the tree with respect to node */ +int tree_node_balance(Ecore_Tree * tree, Ecore_Tree_Node * top_node) +{ + int balance; + + CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); + + /* Get the height of the left branch. */ + if (top_node->right_child) { + top_node->max_left = MAX_HEIGHT(top_node->right_child) + 1; + } else + top_node->max_left = 0; + + /* Get the height of the right branch. */ + if (top_node->left_child) { + top_node->max_right = MAX_HEIGHT(top_node->left_child) + 1; + } else + top_node->max_right = 0; + + /* Determine which side has a larger height. */ + balance = top_node->max_right - top_node->max_left; + + /* if the left side has a height advantage >1 rotate right */ + if (balance < -1) + tree_node_rotate_right(tree, top_node); + /* else if the left side has a height advantage >1 rotate left */ + else if (balance > 1) + tree_node_rotate_left(tree, top_node); + + return TRUE; +} + +/* Tree is overbalanced to the left, so rotate nodes to the right. */ +int tree_node_rotate_right(Ecore_Tree * tree, Ecore_Tree_Node * top_node) +{ + Ecore_Tree_Node *temp; + + CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); + + /* The left branch's right branch becomes the nodes left branch, + * the left branch becomes the top node, and the node becomes the + * right branch. */ + temp = top_node->right_child; + top_node->right_child = temp->left_child; + temp->left_child = top_node; + + /* Make sure the nodes know who their new parents are and the tree + * structure knows the start of the tree. */ + temp->parent = top_node->parent; + if (temp->parent == NULL) + tree->tree = temp; + else { + if (temp->parent->left_child == top_node) + temp->parent->left_child = temp; + else + temp->parent->right_child = temp; + } + top_node->parent = temp; + + /* And recalculate node heights */ + tree_node_balance(tree, top_node); + tree_node_balance(tree, temp); + + return TRUE; +} + +/* The tree is overbalanced to the right, so we rotate nodes to the left */ +int tree_node_rotate_left(Ecore_Tree * tree, Ecore_Tree_Node * top_node) +{ + Ecore_Tree_Node *temp; + + CHECK_PARAM_POINTER_RETURN("top_node", top_node, FALSE); + + /* + * The right branch's left branch becomes the nodes right branch, + * the right branch becomes the top node, and the node becomes the + * left branch. + */ + temp = top_node->left_child; + top_node->left_child = temp->right_child; + temp->right_child = top_node; + + /* Make sure the nodes know who their new parents are. */ + temp->parent = top_node->parent; + if (temp->parent == NULL) + tree->tree = temp; + else { + if (temp->parent->left_child == top_node) + temp->parent->left_child = temp; + else + temp->parent->right_child = temp; + } + top_node->parent = temp; + + /* And recalculate node heights */ + tree_node_balance(tree, top_node); + tree_node_balance(tree, temp); + + return TRUE; +} + +/* + * @brief Execute a function for each node below this point in the tree. + * @param node: the highest node in the tree the function will be executed for + * @param for_each_func: the function to pass the nodes as data into + * @param user_data: data passed to each for_each_func call + * @return Returns FALSE if an error condition occurs, otherwise TRUE + */ +int tree_for_each_node(Ecore_Tree_Node * node, Ecore_For_Each for_each_func, + void *user_data) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (node->right_child) + tree_for_each_node(node->right_child, for_each_func, user_data); + + if (node->left_child) + tree_for_each_node(node->left_child, for_each_func, user_data); + + for_each_func(node, user_data); + + return TRUE; +} + + +/* + * @brief Execute a function for each node below this point in the tree. + * @param node: the highest node in the tree the function will be executed for + * @param for_each_func: the function to pass the nodes values as data + * @return Returns FALSE if an error condition occurs, otherwise TRUE + */ +int tree_for_each_node_value(Ecore_Tree_Node * node, + Ecore_For_Each for_each_func, void *user_data) +{ + CHECK_PARAM_POINTER_RETURN("node", node, FALSE); + + if (node->right_child) + tree_for_each_node_value(node->right_child, for_each_func, user_data); + + if (node->left_child) + tree_for_each_node_value(node->left_child, for_each_func, user_data); + + for_each_func(node->value, user_data); + + return TRUE; +} diff --git a/ecore/src/lib/ecore/ecore_value.c b/ecore/src/lib/ecore/ecore_value.c new file mode 100644 index 0000000..d893809 --- /dev/null +++ b/ecore/src/lib/ecore/ecore_value.c @@ -0,0 +1,118 @@ +/* ecore_value.c + +Copyright (C) 2001 Christopher Rosendahl <smugg@fatelabs.com> + Nathan Ingersoll <ningerso@d.umn.edu> + +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 the +rights to use, copy, modify, merge, publish, distribute, sublicense, 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 shall be included in +all copies of the Software and its documentation and acknowledgment shall be +given in the documentation and software packages that this Software was +used. + +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 NONINFRINGEMENT. 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. + +*/ + +#include <Ecore.h> + +const unsigned int ecore_prime_table[] = { 17, 31, 61, 127, 257, 509, 1021, + 2053, 4093, 8191, 16381, 32771, 65537, 131071, 262147, 524287, 1048573, + 2097143, 4194301, 8388617, 16777213 +}; + +inline void ecore_print_warning(const char *function, const char *sparam) +{ + fprintf(stderr, "***** Developer Warning ***** :\n" + "\tThis program is calling:\n\n" + "\t%s();\n\n" + "\tWith the parameter:\n\n" + "\t%s\n\n" + "\tbeing NULL. Please fix your program.\n", function, sparam); + fflush(stderr); +} + +/** + * Just casts the key to an unsigned int + * @param key The key to return compute a hash value + * @return The key cast to an unsigned int. + */ +unsigned int ecore_direct_hash(void *key) +{ + return ((unsigned int) key); +} + +/** + * Compute the hash value of a string + * @param key A pointer to the string to compute a hash value + * @return A computed hash value for @a key. + */ +unsigned int ecore_str_hash(void *key) +{ + int i; + unsigned int value = 0; + char *k = (char *) key; + + if (!k) + return 0; + + for (i = 0; k[i] != '\0'; i++) { + value ^= ((unsigned int) k[i] << ((i * 5) % + (sizeof(unsigned int) * 8))); + } + + return value; +} + +/** + * Perform a direct comparison of two keys' values + * @param key1 The first key to compare + * @param key2 The second key to compare + * @return A strcmp style value to indicate the larger key + */ +int ecore_direct_compare(void *key1, void *key2) +{ + unsigned int k1, k2; + + k1 = (unsigned int) key1; + k2 = (unsigned int) key2; + + if (k1 > k2) + return 1; + + if (k1 < k2) + return -1; + + return 0; +} + +/** + * Perform a string comparison of two keys values + * @param key1 The first key to compare + * @param key2 The second key to compare + * @return A strcmp style value to indicate the larger key + */ +int ecore_str_compare(void *key1, void *key2) +{ + char *k1, *k2; + + if (!key1 || !key2) + return ecore_direct_compare(key1, key2); + else if (key1 == key2) + return 0; + + k1 = (char *) key1; + k2 = (char *) key2; + + return strcmp(k1, k2); +} diff --git a/ecore/src/lib/ecore_con/.cvsignore b/ecore/src/lib/ecore_con/.cvsignore new file mode 100644 index 0000000..c9eb519 --- /dev/null +++ b/ecore/src/lib/ecore_con/.cvsignore @@ -0,0 +1,7 @@ +.deps +.libs +Ecore_Con.h +Makefile +Makefile.in +ecore_con.lo +libecore_con.la diff --git a/ecore/src/lib/ecore_con/CVS/Entries b/ecore/src/lib/ecore_con/CVS/Entries new file mode 100644 index 0000000..1740d38 --- /dev/null +++ b/ecore/src/lib/ecore_con/CVS/Entries @@ -0,0 +1,7 @@ +/.cvsignore/1.2/Wed Mar 31 16:47:45 2004//THEAD +/Ecore_Con.h/1.9/Fri Jun 24 13:38:27 2005//THEAD +/Makefile.am/1.10/Fri Jun 24 13:38:27 2005//THEAD +/ecore_con.c/1.41/Fri Apr 29 04:51:31 2005//THEAD +/ecore_con_private.h/1.8/Fri Jun 24 13:38:27 2005//THEAD +/ecore_con_url.c/1.6/Fri Jun 24 15:01:59 2005//THEAD +D diff --git a/ecore/src/lib/ecore_con/CVS/Repository b/ecore/src/lib/ecore_con/CVS/Repository new file mode 100644 index 0000000..282cc26 --- /dev/null +++ b/ecore/src/lib/ecore_con/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_con diff --git a/ecore/src/lib/ecore_con/CVS/Root b/ecore/src/lib/ecore_con/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_con/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_con/CVS/Tag b/ecore/src/lib/ecore_con/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_con/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_con/Ecore_Con.h b/ecore/src/lib/ecore_con/Ecore_Con.h new file mode 100644 index 0000000..fd022b3 --- /dev/null +++ b/ecore/src/lib/ecore_con/Ecore_Con.h @@ -0,0 +1,168 @@ +#ifndef _ECORE_CON_H +#define _ECORE_CON_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file Ecore_Con.h + * @brief Sockets functions. + * + * The Ecore Connection Library ( @c Ecore_Con ) provides simple mechanisms + * for communications between programs using reliable sockets. It saves + * the programmer from having to worry about file descripters and waiting + * for incoming connections. + * + * There are two main objects in the @c Ecore_Con library: the @c + * Ecore_Con_Server and the @c Ecore_Con_Client. + * + * The @c Ecore_Con_Server represents a server to connect to. It is + * represents a server that can be connected to. It is used regardless + * of whether the program is acting as a server or client itself. + * + * To create a listening server, call @c ecore_con_server_add(). + * + * To connect to a server, call @c ecore_con_server_connect(). Data can + * then be sent to the server using the @c ecore_con_server_send(). + * + * Whenever a client connection is made to an @c Ecore_Con_Server, a + * @c ECORE_CON_CLIENT_ADD event is emitted. Any event callbacks that are + * called receive a @c Ecore_Con_Client object, which represents a + * connection that that particular client. + * + * Functions are described in the following groupings: + * @li @ref Ecore_Con_Lib_Group + * @li @ref Ecore_Con_Server_Group + * @li @ref Ecore_Con_Client_Group + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ECORE_CON_PRIVATE_H + typedef void Ecore_Con_Server; /**< A connection handle */ + typedef void Ecore_Con_Client; /**< A connection handle */ + typedef void Ecore_Con_Url; + + typedef enum _Ecore_Con_Type + { + ECORE_CON_LOCAL_USER, + ECORE_CON_LOCAL_SYSTEM, + ECORE_CON_REMOTE_SYSTEM, + ECORE_CON_USE_SSL = 16 + } Ecore_Con_Type; + +#endif + + typedef struct _Ecore_Con_Event_Client_Add Ecore_Con_Event_Client_Add; + typedef struct _Ecore_Con_Event_Client_Del Ecore_Con_Event_Client_Del; + typedef struct _Ecore_Con_Event_Server_Add Ecore_Con_Event_Server_Add; + typedef struct _Ecore_Con_Event_Server_Del Ecore_Con_Event_Server_Del; + typedef struct _Ecore_Con_Event_Client_Data Ecore_Con_Event_Client_Data; + typedef struct _Ecore_Con_Event_Server_Data Ecore_Con_Event_Server_Data; + typedef struct _Ecore_Con_Event_Url_Data Ecore_Con_Event_Url_Data; + typedef struct _Ecore_Con_Event_Url_Complete Ecore_Con_Event_Url_Complete; + + struct _Ecore_Con_Event_Client_Add + { + Ecore_Con_Client *client; + }; + + struct _Ecore_Con_Event_Client_Del + { + Ecore_Con_Client *client; + }; + + struct _Ecore_Con_Event_Server_Add + { + Ecore_Con_Server *server; + }; + + struct _Ecore_Con_Event_Server_Del + { + Ecore_Con_Server *server; + }; + + struct _Ecore_Con_Event_Client_Data + { + Ecore_Con_Client *client; + void *data; + int size; + }; + + struct _Ecore_Con_Event_Server_Data + { + Ecore_Con_Server *server; + void *data; + int size; + }; + + struct _Ecore_Con_Event_Url_Data + { + Ecore_Con_Url *url_con; + void *data; + int size; + }; + + struct _Ecore_Con_Event_Url_Complete + { + Ecore_Con_Url *url_con; + int status; + }; + + extern int ECORE_CON_EVENT_CLIENT_ADD; + extern int ECORE_CON_EVENT_CLIENT_DEL; + extern int ECORE_CON_EVENT_SERVER_ADD; + extern int ECORE_CON_EVENT_SERVER_DEL; + extern int ECORE_CON_EVENT_CLIENT_DATA; + extern int ECORE_CON_EVENT_SERVER_DATA; + extern int ECORE_CON_EVENT_URL_DATA; + extern int ECORE_CON_EVENT_URL_COMPLETE; + + EAPI int ecore_con_init(void); + EAPI int ecore_con_shutdown(void); + + EAPI Ecore_Con_Server *ecore_con_server_add(Ecore_Con_Type type, const char *name, int port, const void *data); + + EAPI Ecore_Con_Server *ecore_con_server_connect(Ecore_Con_Type type, const char *name, int port, const void *data); + EAPI void *ecore_con_server_del(Ecore_Con_Server *svr); + EAPI void *ecore_con_server_data_get(Ecore_Con_Server *svr); + EAPI int ecore_con_server_connected_get(Ecore_Con_Server *svr); + EAPI int ecore_con_server_send(Ecore_Con_Server *svr, void *data, int size); + EAPI void ecore_con_server_client_limit_set(Ecore_Con_Server *svr, int client_limit, char reject_excess_clients); + + EAPI int ecore_con_client_send(Ecore_Con_Client *cl, void *data, int size); + EAPI Ecore_Con_Server *ecore_con_client_server_get(Ecore_Con_Client *cl); + EAPI void *ecore_con_client_del(Ecore_Con_Client *cl); + EAPI void ecore_con_client_data_set(Ecore_Con_Client *cl, const void *data); + EAPI void *ecore_con_client_data_get(Ecore_Con_Client *cl); + + EAPI int ecore_con_ssl_available_get(void); + + EAPI int ecore_con_url_init(void); + EAPI int ecore_con_url_shutdown(void); + EAPI Ecore_Con_Url *ecore_con_url_new(const char *url); + EAPI void ecore_con_url_destroy(Ecore_Con_Url *url_con); + EAPI int ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url); + EAPI int ecore_con_url_send(Ecore_Con_Url *url_con, void *data, size_t length, char *content_type); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_con/Makefile.am b/ecore/src/lib/ecore_con/Makefile.am new file mode 100644 index 0000000..e40be6e --- /dev/null +++ b/ecore/src/lib/ecore_con/Makefile.am @@ -0,0 +1,36 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_con \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_con \ +@SSL_CFLAGS@ @curl_cflags@ + +libecore_con_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_CON + +lib_LTLIBRARIES = libecore_con.la +include_HEADERS = \ +Ecore_Con.h + +libecore_con_la_SOURCES = \ +ecore_con.c \ +ecore_con_url.c \ +ecore_con_private.h + +libecore_con_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +@SSL_LIBS@ @winsock_libs@ @curl_libs@ + +libecore_con_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la + +endif + +EXTRA_DIST = \ +ecore_con.c \ +ecore_con_url.c \ +ecore_con_private.h diff --git a/ecore/src/lib/ecore_con/ecore_con.c b/ecore/src/lib/ecore_con/ecore_con.c new file mode 100644 index 0000000..b394ae2 --- /dev/null +++ b/ecore/src/lib/ecore_con/ecore_con.c @@ -0,0 +1,1270 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#include "Ecore.h" +#include "config.h" +#include "ecore_private.h" +#include "ecore_con_private.h" +#include "Ecore_Con.h" + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#elif WIN32 +#include <winsock.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <netdb.h> + +#if USE_OPENSSL +#include <time.h> +#endif + +static void _ecore_con_server_free(Ecore_Con_Server *svr); +static void _ecore_con_client_free(Ecore_Con_Client *cl); +static int _ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler); +static void _ecore_con_server_flush(Ecore_Con_Server *svr); +static void _ecore_con_client_flush(Ecore_Con_Client *cl); +static void _ecore_con_event_client_data_free(void *data, void *ev); +static void _ecore_con_event_server_data_free(void *data, void *ev); + +int ECORE_CON_EVENT_CLIENT_ADD = 0; +int ECORE_CON_EVENT_CLIENT_DEL = 0; +int ECORE_CON_EVENT_SERVER_ADD = 0; +int ECORE_CON_EVENT_SERVER_DEL = 0; +int ECORE_CON_EVENT_CLIENT_DATA = 0; +int ECORE_CON_EVENT_SERVER_DATA = 0; + +static Ecore_List *servers = NULL; +static int init_count = 0; + +#define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path)) + +/** + * @defgroup Ecore_Con_Lib_Group Ecore Connection Library Functions + * + * Utility functions that set up and shut down the Ecore Connection + * library. + */ + +/** + * Initialises the Ecore_Con library. + * @return Number of times the library has been initialised without being + * shut down. + * @ingroup Ecore_Con_Lib_Group + */ +int +ecore_con_init(void) +{ + init_count++; + if (!ECORE_CON_EVENT_CLIENT_ADD) + { + ECORE_CON_EVENT_CLIENT_ADD = ecore_event_type_new(); + ECORE_CON_EVENT_CLIENT_DEL = ecore_event_type_new(); + ECORE_CON_EVENT_SERVER_ADD = ecore_event_type_new(); + ECORE_CON_EVENT_SERVER_DEL = ecore_event_type_new(); + ECORE_CON_EVENT_CLIENT_DATA = ecore_event_type_new(); + ECORE_CON_EVENT_SERVER_DATA = ecore_event_type_new(); + +#if USE_OPENSSL + SSL_library_init(); + SSL_load_error_strings(); +#endif + } + if (!servers) + servers = ecore_list_new(); + return init_count; +} + +/** + * Shuts down the Ecore_Con library. + * @return Number of times the library has been initialised without being + * shut down. + * @ingroup Ecore_Con_Lib_Group + */ +int +ecore_con_shutdown(void) +{ + if (init_count > 0) + { + init_count--; + if (init_count > 0) return init_count; + while (!ecore_list_is_empty(servers)) + _ecore_con_server_free(ecore_list_remove_first(servers)); + ecore_list_destroy(servers); + servers = NULL; + } + return 0; +} + +/** + * @defgroup Ecore_Con_Server_Group Ecore Connection Server Functions + * + * Functions that operate on Ecore server objects. + */ + +/** + * Creates a server to listen for connections. + * + * The socket on which the server listens depends on the connection + * type: + * @li If @a compl_type is @c ECORE_CON_LOCAL_USER, the server will listen on + * the Unix socket "~/.ecore/[name]/[port]". + * @li If @a compl_type is @c ECORE_CON_LOCAL_SYSTEM, the server will listen + * on Unix socket "/tmp/.ecore_service|[name]|[port]". + * @li If @a compl_type is @c ECORE_CON_REMOTE_SYSTEM, the server will listen + * on TCP port @c port. + * + * @param compl_type The connection type. + * @param name Name to associate with the socket. It is used when + * generating the socket name of a Unix socket. Though + * it is not used for the TCP socket, it still needs to + * be a valid character array. @c NULL will not be + * accepted. + * @param port Number to identify socket. When a Unix socket is used, + * it becomes part of the socket name. When a TCP socket + * is used, it is used as the TCP port. + * @param data Data to associate with the created Ecore_Con_Server + * object. + * @return A new Ecore_Con_Server. + * @ingroup Ecore_Con_Server_Group + */ +Ecore_Con_Server * +ecore_con_server_add(Ecore_Con_Type compl_type, + const char *name, + int port, + const void *data) +{ + Ecore_Con_Server *svr; + Ecore_Con_Type type; + struct sockaddr_in socket_addr; + struct sockaddr_un socket_unix; + struct linger lin; + char buf[4096]; + + if (port < 0) return NULL; + /* local user socket: FILE: ~/.ecore/[name]/[port] */ + /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */ + /* remote system socket: TCP/IP: [name]:[port] */ + svr = calloc(1, sizeof(Ecore_Con_Server)); + if (!svr) return NULL; + + type = compl_type; +#if USE_OPENSSL + /* unset the SSL flag for the following checks */ + type &= ~ECORE_CON_USE_SSL; +#endif + + if ((type == ECORE_CON_LOCAL_USER) || + (type == ECORE_CON_LOCAL_SYSTEM)) + { + const char *homedir; + struct stat st; + mode_t pmode, mask; + + if (!name) goto error; + mask = + S_IRGRP | S_IWGRP | S_IXGRP | + S_IROTH | S_IWOTH | S_IXOTH; + if (type == ECORE_CON_LOCAL_USER) + { + homedir = getenv("HOME"); + if (!homedir) homedir = getenv("TMP"); + if (!homedir) homedir = "/tmp"; + mask = S_IRUSR | S_IWUSR | S_IXUSR; + snprintf(buf, sizeof(buf), "%s/.ecore", homedir); + if (stat(buf, &st) < 0) mkdir(buf, mask); + snprintf(buf, sizeof(buf), "%s/.ecore/%s", homedir, name); + if (stat(buf, &st) < 0) mkdir(buf, mask); + snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, name, port); + mask = + S_IRGRP | S_IWGRP | S_IXGRP | + S_IROTH | S_IWOTH | S_IXOTH; + } + else if (type == ECORE_CON_LOCAL_SYSTEM) + { + mask = 0; + if (name[0] == '/') + snprintf(buf, sizeof(buf), "%s|%i", name, port); + else + snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i", name, port); + } + pmode = umask(mask); + start: + svr->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (svr->fd < 0) + { + umask(pmode); + goto error; + } + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) + { + umask(pmode); + goto error; + } + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) + { + umask(pmode); + goto error; + } + lin.l_onoff = 1; + lin.l_linger = 100; + if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) + { + umask(pmode); + goto error; + } + socket_unix.sun_family = AF_UNIX; + strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path)); + if (bind(svr->fd, (struct sockaddr *)&socket_unix, LENGTH_OF_SOCKADDR_UN(&socket_unix)) < 0) + { + if (connect(svr->fd, (struct sockaddr *)&socket_unix, + LENGTH_OF_SOCKADDR_UN(&socket_unix)) < 0) + { + if ((type == ECORE_CON_LOCAL_USER) || + (type == ECORE_CON_LOCAL_SYSTEM)) + { + if (unlink(buf) < 0) + { + umask(pmode); + goto error; + } + else + goto start; + } + else + { + umask(pmode); + goto error; + } + } + else + { + umask(pmode); + goto error; + } + } + if (listen(svr->fd, 4096) < 0) + { + umask(pmode); + goto error; + } + svr->path = strdup(buf); + if (!svr->path) + { + umask(pmode); + goto error; + } + svr->fd_handler = ecore_main_fd_handler_add(svr->fd, + ECORE_FD_READ, + _ecore_con_svr_handler, svr, + NULL, NULL); + umask(pmode); + if (!svr->fd_handler) goto error; + } + else if (type == ECORE_CON_REMOTE_SYSTEM) + { + svr->fd = socket(AF_INET, SOCK_STREAM, 0); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + lin.l_onoff = 1; + lin.l_linger = 100; + if (setsockopt(svr->fd, SOL_SOCKET, SO_LINGER, &lin, sizeof(struct linger)) < 0) goto error; + socket_addr.sin_family = AF_INET; + socket_addr.sin_port = htons(port); + socket_addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0) goto error; + if (listen(svr->fd, 4096) < 0) goto error; + svr->fd_handler = ecore_main_fd_handler_add(svr->fd, + ECORE_FD_READ, + _ecore_con_svr_handler, svr, + NULL, NULL); + if (!svr->fd_handler) goto error; + } + +#if USE_OPENSSL + if (compl_type & ECORE_CON_USE_SSL) + { + /* SSLv3 gives *weird* results on my box, don't use it yet */ + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method()))) + goto error; + + if (!(svr->ssl = SSL_new(svr->ssl_ctx))) + goto error; + + SSL_set_fd(svr->ssl, svr->fd); + } +#endif + + svr->name = strdup(name); + if (!svr->name) goto error; + svr->type = type; + svr->port = port; + svr->data = (void *)data; + svr->created = 1; + svr->reject_excess_clients = 0; + svr->client_limit = -1; + svr->clients = ecore_list_new(); + ecore_list_append(servers, svr); + ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER); + return svr; + + error: + if (svr->name) free(svr->name); + if (svr->path) free(svr->path); + if (svr->fd >= 0) close(svr->fd); + if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler); + if (svr->write_buf) free(svr->write_buf); +#if USE_OPENSSL + if (svr->ssl) SSL_free(svr->ssl); + if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx); +#endif + free(svr); + return NULL; +} + +/** + * Creates a server object to represent the server listening at the + * given port. + * + * The socket to which the server connects depends on the connection type: + * @li If @a compl_type is @c ECORE_CON_LOCAL_USER, the function will + * connect to the server listening on the Unix socket + * "~/.ecore/[name]/[port]". + * @li If @a compl_type is @c ECORE_CON_LOCAL_SYSTEM, the function will + * connect to the server listening on the Unix socket + * "/tmp/.ecore_service|[name]|[port]". + * @li If @a compl_type is @c ECORE_CON_REMOTE_SYSTEM, the function will + * connect to the server listening on the TCP port "[name]:[port]". + * + * @param compl_type The connection type. + * @param name Name used when determining what socket to connect to. + * It is used to generate the socket name when the socket + * is a Unix socket. It is used as the hostname when + * connecting with a TCP socket. + * @param port Number to identify the socket to connect to. Used when + * generating the socket name for a Unix socket, or as the + * TCP port when connecting to a TCP socket. + * @param data Data to associate with the created Ecore_Con_Server + * object. + * @return A new Ecore_Con_Server. + * @ingroup Ecore_Con_Server_Group + */ +Ecore_Con_Server * +ecore_con_server_connect(Ecore_Con_Type compl_type, + const char *name, + int port, + const void *data) +{ + Ecore_Con_Server *svr; + Ecore_Con_Type type; + struct sockaddr_un socket_unix; + struct sockaddr_in socket_addr; + int curstate = 0; + char buf[4096]; + + if (!name) return NULL; + if (port < 0) return NULL; + /* local user socket: FILE: ~/.ecore/[name]/[port] */ + /* local system socket: FILE: /tmp/.ecore_service|[name]|[port] */ + /* remote system socket: TCP/IP: [name]:[port] */ + svr = calloc(1, sizeof(Ecore_Con_Server)); + if (!svr) return NULL; + + type = compl_type; +#if USE_OPENSSL + /* unset the SSL flag for the following checks */ + type &= ~ECORE_CON_USE_SSL; +#endif + + if ((type == ECORE_CON_LOCAL_USER) || + (type == ECORE_CON_LOCAL_SYSTEM)) + { + const char *homedir; + + if (type == ECORE_CON_LOCAL_USER) + { + homedir = getenv("HOME"); + if (!homedir) homedir = getenv("TMP"); + if (!homedir) homedir = "/tmp"; + snprintf(buf, sizeof(buf), "%s/.ecore/%s/%i", homedir, name, port); + } + else if (type == ECORE_CON_LOCAL_SYSTEM) + { + if (name[0] == '/') + snprintf(buf, sizeof(buf), "%s|%i", name, port); + else + snprintf(buf, sizeof(buf), "/tmp/.ecore_service|%s|%i", name, port); + } + svr->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) goto error; + socket_unix.sun_family = AF_UNIX; + strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path)); + if (connect(svr->fd, (struct sockaddr *)&socket_unix, LENGTH_OF_SOCKADDR_UN(&socket_unix)) < 0) goto error; + svr->path = strdup(buf); + if (!svr->path) goto error; + svr->fd_handler = ecore_main_fd_handler_add(svr->fd, + ECORE_FD_READ, + _ecore_con_cl_handler, svr, + NULL, NULL); + if (!svr->fd_handler) goto error; + { + /* we got our server! */ + Ecore_Con_Event_Server_Add *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Server_Add)); + if (e) + { + e->server = svr; + ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e, NULL, NULL); + } + } + } + else if (type == ECORE_CON_REMOTE_SYSTEM) + { + struct hostent *he; + + /* FIXME: gethostbyname is blocking... */ + if (!(he = gethostbyname(name))) goto error; + svr->fd = socket(AF_INET, SOCK_STREAM, 0); + if (svr->fd < 0) goto error; + if (fcntl(svr->fd, F_SETFL, O_NONBLOCK) < 0) goto error; + if (fcntl(svr->fd, F_SETFD, FD_CLOEXEC) < 0) goto error; + if (setsockopt(svr->fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) goto error; + socket_addr.sin_family = AF_INET; + socket_addr.sin_port = htons(port); + memcpy((struct in_addr *)&socket_addr.sin_addr, + he->h_addr, sizeof(struct in_addr)); + if (connect(svr->fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_in)) < 0) + { + if (errno != EINPROGRESS) + goto error; + svr->connecting = 1; + svr->fd_handler = ecore_main_fd_handler_add(svr->fd, + ECORE_FD_READ | ECORE_FD_WRITE, + _ecore_con_cl_handler, svr, + NULL, NULL); + } + else + svr->fd_handler = ecore_main_fd_handler_add(svr->fd, + ECORE_FD_READ, + _ecore_con_cl_handler, svr, + NULL, NULL); + + if (!svr->fd_handler) goto error; + } + +#if USE_OPENSSL + if (compl_type & ECORE_CON_USE_SSL) + { + /* SSLv3 gives *weird* results on my box, don't use it yet */ + if (!(svr->ssl_ctx = SSL_CTX_new(SSLv2_client_method()))) + goto error; + + if (!(svr->ssl = SSL_new(svr->ssl_ctx))) + goto error; + + SSL_set_fd(svr->ssl, svr->fd); + } +#endif + + svr->name = strdup(name); + if (!svr->name) goto error; + svr->type = type; + svr->port = port; + svr->data = (void *)data; + svr->created = 0; + svr->reject_excess_clients = 0; + svr->client_limit = -1; + svr->clients = ecore_list_new(); + ecore_list_append(servers, svr); + ECORE_MAGIC_SET(svr, ECORE_MAGIC_CON_SERVER); + return svr; + + error: + if (svr->name) free(svr->name); + if (svr->path) free(svr->path); + if (svr->fd >= 0) close(svr->fd); + if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler); +#if USE_OPENSSL + if (svr->ssl) SSL_free(svr->ssl); + if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx); +#endif + free(svr); + return NULL; +} + +/** + * Closes the connection and frees the given server. + * @param svr The given server. + * @return Data associated with the server when it was created. + * @ingroup Ecore_Con_Server_Group + */ +void * +ecore_con_server_del(Ecore_Con_Server *svr) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, + "ecore_con_server_del"); + return NULL; + } + data = svr->data; + _ecore_con_server_free(svr); + if (ecore_list_goto(servers, svr)) ecore_list_remove(servers); + return data; +} + +/** + * Retrieves the data associated with the given server. + * @param svr The given server. + * @return The associated data. + * @ingroup Ecore_Con_Server_Group + */ +void * +ecore_con_server_data_get(Ecore_Con_Server *svr) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, + "ecore_con_server_data_get"); + return NULL; + } + return svr->data; +} + +/** + * Retrieves whether the given server is currently connected. + * @todo Check that this function does what the documenter believes it does. + * @param svr The given server. + * @return @c 1 if the server is connected. @c 0 otherwise. + * @ingroup Ecore_Con_Server_Group + */ +int +ecore_con_server_connected_get(Ecore_Con_Server *svr) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, + "ecore_con_server_connected_get"); + return 0; + } + if (svr->connecting) return 0; + return 1; +} + +/** + * Sends the given data to the given server. + * @param svr The given server. + * @param data The given data. + * @param size Length of the data, in bytes, to send. + * @return The number of bytes sent. @c 0 will be returned if there is an + * error. + * @ingroup Ecore_Con_Server_Group + */ +int +ecore_con_server_send(Ecore_Con_Server *svr, void *data, int size) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, + "ecore_con_server_send"); + return 0; + } + if (svr->dead) return 0; + if (!data) return 0; + if (size < 1) return 0; + ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE); + if (svr->write_buf) + { + unsigned char *newbuf; + + newbuf = realloc(svr->write_buf, svr->write_buf_size + size); + if (newbuf) svr->write_buf = newbuf; + else return 0; + memcpy(svr->write_buf + svr->write_buf_size, data, size); + svr->write_buf_size += size; + } + else + { + svr->write_buf = malloc(size); + if (!svr->write_buf) return 0; + svr->write_buf_size = size; + memcpy(svr->write_buf, data, size); + } + return size; +} + +/** + * Sets a limit on the number of clients that can be handled concurrently + * by the given server, and a policy on what to do if excess clients try to + * connect. + * Beware that if you set this once ecore is already running, you may + * already have pending CLIENT_ADD events in your event queue. Those + * clients have already connected and will not be affected by this call. + * Only clients subsequently trying to connect will be affected. + * @param svr The given server. + * @param client_limit The maximum number of clients to handle + * concurrently. -1 means unlimited (default). 0 + * effectively disables the server. + * @param reject_excess_clients Set to 1 to automatically disconnect + * excess clients as soon as they connect if you are + * already handling client_limit clients. Set to 0 + * (default) to just hold off on the "accept()" + * system call until the number of active clients + * drops. This causes the kernel to queue up to 4096 + * connections (or your kernel's limit, whichever is + * lower). + * @ingroup Ecore_Con_Server_Group + */ +void +ecore_con_server_client_limit_set(Ecore_Con_Server *svr, int client_limit, char reject_excess_clients) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_CON_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_CON_SERVER, + "ecore_con_server_client_limit_set"); + return; + } + svr->client_limit = client_limit; + svr->reject_excess_clients = reject_excess_clients; +} + +/** + * @defgroup Ecore_Con_Client_Group Ecore Connection Client Functions + * + * Functions that operate on Ecore connection client objects. + */ + +/** + * Sends the given data to the given client. + * @param cl The given client. + * @param data The given data. + * @param size Length of the data, in bytes, to send. + * @return The number of bytes sent. @c 0 will be returned if there is an + * error. + * @ingroup Ecore_Con_Client_Group + */ +int +ecore_con_client_send(Ecore_Con_Client *cl, void *data, int size) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, + "ecore_con_client_send"); + return 0; + } + if (cl->dead) return 0; + if (!data) return 0; + if (size < 1) return 0; + ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ | ECORE_FD_WRITE); + if (cl->buf) + { + unsigned char *newbuf; + + newbuf = realloc(cl->buf, cl->buf_size + size); + if (newbuf) cl->buf = newbuf; + else return 0; + memcpy(cl->buf + cl->buf_size, data, size); + cl->buf_size += size; + } + else + { + cl->buf = malloc(size); + if (!cl->buf) return 0; + cl->buf_size = size; + memcpy(cl->buf, data, size); + } + return size; +} + +/** + * Retrieves the server representing the socket the client has + * connected to. + * @param cl The given client. + * @return The server that the client connected to. + * @ingroup Ecore_Con_Client_Group + */ +Ecore_Con_Server * +ecore_con_client_server_get(Ecore_Con_Client *cl) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, + "ecore_con_client_server_get"); + return NULL; + } + return cl->server; +} + +/** + * Closes the connection and frees memory allocated to the given client. + * @param cl The given client. + * @return Data associated with the client. + * @ingroup Ecore_Con_Client_Group + */ +void * +ecore_con_client_del(Ecore_Con_Client *cl) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, + "ecore_con_client_del"); + return NULL; + } + data = cl->data; + _ecore_con_client_free(cl); + if (ecore_list_goto(cl->server->clients, cl)) ecore_list_remove(cl->server->clients); + return data; +} + +/** + * Sets the data associated with the given client to @p data. + * @param cl The given client. + * @param data What to set the data to. + * @ingroup Ecore_Con_Client_Group + */ +void +ecore_con_client_data_set(Ecore_Con_Client *cl, const void *data) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, + "ecore_con_client_data_set"); + return; + } + cl->data = (void *)data; +} + +/** + * Retrieves the data associated with the given client. + * @param cl The given client. + * @return The data associated with @p cl. + * @ingroup Ecore_Con_Client_Group + */ +void * +ecore_con_client_data_get(Ecore_Con_Client *cl) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_CON_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_CON_CLIENT, + "ecore_con_client_data_get"); + return NULL; + } + return cl->data; +} + +/** + * Returns if SSL support is available + * @return 1 if SSL is available, 0 if it is not. + * @ingroup Ecore_Con_Client_Group + */ +int +ecore_con_ssl_available_get(void) +{ +#if USE_OPENSSL + return 1; +#else + return 0; +#endif +} + +static void +_ecore_con_server_free(Ecore_Con_Server *svr) +{ + ECORE_MAGIC_SET(svr, ECORE_MAGIC_NONE); + while ((svr->write_buf) && (!svr->dead)) _ecore_con_server_flush(svr); + if (svr->write_buf) free(svr->write_buf); + while (!ecore_list_is_empty(svr->clients)) + _ecore_con_client_free(ecore_list_remove_first(svr->clients)); + ecore_list_destroy(svr->clients); + if ((svr->created) && (svr->path)) unlink(svr->path); + if (svr->fd >= 0) close(svr->fd); +#if USE_OPENSSL + if (svr->ssl) + { + SSL_shutdown(svr->ssl); + SSL_free(svr->ssl); + } + if (svr->ssl_ctx) SSL_CTX_free(svr->ssl_ctx); +#endif + if (svr->name) free(svr->name); + if (svr->path) free(svr->path); + if (svr->fd_handler) ecore_main_fd_handler_del(svr->fd_handler); + free(svr); +} + +static void +_ecore_con_client_free(Ecore_Con_Client *cl) +{ + ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE); + while ((cl->buf) && (!cl->dead)) _ecore_con_client_flush(cl); + if (cl->buf) free(cl->buf); + if (cl->fd >= 0) close(cl->fd); + if (cl->fd_handler) ecore_main_fd_handler_del(cl->fd_handler); + free(cl); +} + +static int +_ecore_con_svr_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + Ecore_Con_Server *svr; + int new_fd; + struct sockaddr_in incoming; + size_t size_in; + + svr = data; + if (svr->dead) return 1; + if ((svr->client_limit >= 0) && (!svr->reject_excess_clients)) + { + if (ecore_list_nodes(svr->clients) >= svr->client_limit) return 1; + } + /* a new client */ + size_in = sizeof(struct sockaddr_in); + new_fd = accept(svr->fd, (struct sockaddr *)&incoming, &size_in); + if (new_fd >= 0) + { + Ecore_Con_Client *cl; + + if ((svr->client_limit >= 0) && (svr->reject_excess_clients)) + { + close(new_fd); + return 1; + } + + cl = calloc(1, sizeof(Ecore_Con_Client)); + if (!cl) + { + close(new_fd); + return 1; + } + fcntl(new_fd, F_SETFL, O_NONBLOCK); + fcntl(new_fd, F_SETFD, FD_CLOEXEC); + cl->fd = new_fd; + cl->server = svr; + cl->fd_handler = ecore_main_fd_handler_add(cl->fd, + ECORE_FD_READ, + _ecore_con_svr_cl_handler, + cl, NULL, NULL); + ECORE_MAGIC_SET(cl, ECORE_MAGIC_CON_CLIENT); + ecore_list_append(svr->clients, cl); + { + Ecore_Con_Event_Client_Add *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Client_Add)); + if (e) + { + e->client = cl; + ecore_event_add(ECORE_CON_EVENT_CLIENT_ADD, e, NULL, NULL); + } + } + } + return 1; +} + +#if USE_OPENSSL +/* Tries to connect an Ecore_Con_Server to an SSL host. + * Returns 1 on success, -1 on fatal errors and 0 if the caller + * should try again later. + */ +static int +svr_try_connect_ssl(Ecore_Con_Server *svr) +{ + int res, ssl_err, flag = 0; + + res = SSL_connect(svr->ssl); + if (res == 1) return 1; + ssl_err = SSL_get_error(svr->ssl, res); + + if (ssl_err == SSL_ERROR_NONE) return 1; + if (ssl_err == SSL_ERROR_WANT_READ) flag = ECORE_FD_READ; + else if (ssl_err == SSL_ERROR_WANT_WRITE) flag = ECORE_FD_WRITE; + else return -1; + if (flag) ecore_main_fd_handler_active_set(svr->fd_handler, flag); + return 0; +} +#endif + +static void +kill_server(Ecore_Con_Server *svr) +{ + Ecore_Con_Event_Server_Del *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Server_Del)); + if (e) + { + e->server = svr; + ecore_event_add(ECORE_CON_EVENT_SERVER_DEL, e, NULL, NULL); + } + + svr->dead = 1; + ecore_main_fd_handler_del(svr->fd_handler); + svr->fd_handler = NULL; +} + +static int +svr_try_connect_plain(Ecore_Con_Server *svr) +{ + int so_err = 0, size = sizeof(int); + + if (getsockopt(svr->fd, SOL_SOCKET, SO_ERROR, &so_err, &size) < 0) + so_err = -1; + + if (so_err != 0) + { + /* we lost our server! */ + kill_server(svr); + } + else + { + /* we got our server! */ + Ecore_Con_Event_Server_Add *e; + + svr->connecting = 0; + e = calloc(1, sizeof(Ecore_Con_Event_Server_Add)); + if (e) + { + e->server = svr; + ecore_event_add(ECORE_CON_EVENT_SERVER_ADD, e, NULL, NULL); + } + if (!svr->write_buf) + ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); + } + return (!svr->dead); +} + +/* returns 1 on success, 0 on failure */ +static int svr_try_connect (Ecore_Con_Server *svr) +{ +#if USE_OPENSSL + if (!svr->ssl) + { +#endif + return svr_try_connect_plain(svr); +#if USE_OPENSSL + } + else + switch (svr_try_connect_ssl(svr)) { + case 1: + return svr_try_connect_plain(svr); + case -1: + kill_server(svr); + return 0; + default: + return 0; + } +#endif +} + + +static int +_ecore_con_cl_handler(void *data, Ecore_Fd_Handler *fd_handler) +{ + Ecore_Con_Server *svr; +#if USE_OPENSSL + int ssl_err = SSL_ERROR_NONE; +#endif + + svr = data; + if (svr->dead) return 1; + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) + { + unsigned char *inbuf = NULL; + int inbuf_num = 0; + + if (svr->connecting && !svr_try_connect(svr)) + return 1; + + for (;;) + { + int num, lost_server = 0; + char buf[READBUFSIZ]; + +#if USE_OPENSSL + if (!svr->ssl) + { +#endif + if ((num = read(svr->fd, buf, READBUFSIZ)) < 1) + lost_server = (errno == EIO || errno == EBADF || + errno == EPIPE || errno == EINVAL || + errno == ENOSPC || num == 0); /* is num == 0 right? */ +#if USE_OPENSSL + } + else + { + num = SSL_read(svr->ssl, buf, READBUFSIZ); + if (num < 1) + { + ssl_err = SSL_get_error(svr->ssl, num); + lost_server = (ssl_err == SSL_ERROR_ZERO_RETURN); + } + else + ssl_err = SSL_ERROR_NONE; + } +#endif + if (num < 1) + { + if (inbuf) + { + Ecore_Con_Event_Server_Data *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Server_Data)); + if (e) + { + e->server = svr; + e->data = inbuf; + e->size = inbuf_num; + ecore_event_add(ECORE_CON_EVENT_SERVER_DATA, e, + _ecore_con_event_server_data_free, NULL); + } + } + if (lost_server) + { + /* we lost our server! */ + kill_server(svr); + return 1; + } + break; + } + else + { + inbuf = realloc(inbuf, inbuf_num + num); + memcpy(inbuf + inbuf_num, buf, num); + inbuf_num += num; + } + } + +#if USE_OPENSSL + if (svr->ssl && ssl_err == SSL_ERROR_WANT_READ) + ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); + else if (svr->ssl && ssl_err == SSL_ERROR_WANT_WRITE) + ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_WRITE); +#endif + } + else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) + { + if (svr->connecting && !svr_try_connect (svr)) + return 1; + + _ecore_con_server_flush(svr); + } + + return 1; +} + +static int +_ecore_con_svr_cl_handler(void *data, Ecore_Fd_Handler *fd_handler) +{ + Ecore_Con_Client *cl; + + cl = data; + if (cl->dead) return 1; + if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) + { + unsigned char *inbuf = NULL; + int inbuf_num = 0; + + for (;;) + { + char buf[65536]; + int num; + + errno = 0; + num = read(cl->fd, buf, 65536); + if (num < 1) + { + if (inbuf) + { + Ecore_Con_Event_Client_Data *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Client_Data)); + if (e) + { + e->client = cl; + e->data = inbuf; + e->size = inbuf_num; + ecore_event_add(ECORE_CON_EVENT_CLIENT_DATA, e, + _ecore_con_event_client_data_free, NULL); + } + } + if ((errno == EIO) || (errno == EBADF) || + (errno == EPIPE) || (errno == EINVAL) || + (errno == ENOSPC) || (num == 0)/* is num == 0 right? */) + { + /* we lost our client! */ + Ecore_Con_Event_Client_Del *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Client_Del)); + if (e) + { + e->client = cl; + ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e, NULL, NULL); + } + cl->dead = 1; + ecore_main_fd_handler_del(cl->fd_handler); + cl->fd_handler = NULL; + } + break; + } + else + { + inbuf = realloc(inbuf, inbuf_num + num); + memcpy(inbuf + inbuf_num, buf, num); + inbuf_num += num; + } + } + } + else if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_WRITE)) + _ecore_con_client_flush(cl); + return 1; +} + +static void +_ecore_con_server_flush(Ecore_Con_Server *svr) +{ + int count, num, lost_server = 0; +#if USE_OPENSSL + int ssl_err = SSL_ERROR_NONE; +#endif + + if (!svr->write_buf) return; + + /* check whether we need to write anything at all. + * we must not write zero bytes with SSL_write() since it + * causes undefined behaviour + */ + if (svr->write_buf_size == svr->write_buf_offset) + return; + + num = svr->write_buf_size - svr->write_buf_offset; +#if USE_OPENSSL + if (!svr->ssl) + { +#endif + count = write(svr->fd, svr->write_buf + svr->write_buf_offset, num); + if (count < 1) + lost_server = (errno == EIO || errno == EBADF || + errno == EPIPE || errno == EINVAL || + errno == ENOSPC); +#if USE_OPENSSL + } + else + { + count = SSL_write(svr->ssl, svr->write_buf + svr->write_buf_offset, num); + + if (count < 1) + { + ssl_err = SSL_get_error(svr->ssl, count); + lost_server = (ssl_err == SSL_ERROR_ZERO_RETURN); + } + } +#endif + + if (lost_server) + { + /* we lost our server! */ + kill_server(svr); + return; + } + + if (count < 1) + { +#if USE_OPENSSL + if (svr->ssl && ssl_err == SSL_ERROR_WANT_READ) + ecore_main_fd_handler_active_set(svr->fd_handler, + ECORE_FD_READ); + else if (svr->ssl && ssl_err == SSL_ERROR_WANT_WRITE) + ecore_main_fd_handler_active_set(svr->fd_handler, + ECORE_FD_WRITE); +#endif + return; + } + + svr->write_buf_offset += count; + if (svr->write_buf_offset >= svr->write_buf_size) + { + svr->write_buf_size = 0; + svr->write_buf_offset = 0; + free(svr->write_buf); + svr->write_buf = NULL; + ecore_main_fd_handler_active_set(svr->fd_handler, ECORE_FD_READ); + } +} + +static void +_ecore_con_client_flush(Ecore_Con_Client *cl) +{ + int count, num; + + if (!cl->buf) return; + num = cl->buf_size - cl->buf_offset; + count = write(cl->fd, cl->buf + cl->buf_offset, num); + if (count < 1) + { + if ((errno == EIO) || (errno == EBADF) || (errno == EPIPE) || + (errno == EINVAL) || (errno == ENOSPC)) + { + /* we lost our client! */ + Ecore_Con_Event_Client_Del *e; + + e = calloc(1, sizeof(Ecore_Con_Event_Client_Del)); + if (e) + { + e->client = cl; + ecore_event_add(ECORE_CON_EVENT_CLIENT_DEL, e, NULL, NULL); + } + cl->dead = 1; + ecore_main_fd_handler_del(cl->fd_handler); + cl->fd_handler = NULL; + } + return; + } + cl->buf_offset += count; + if (cl->buf_offset >= cl->buf_size) + { + cl->buf_size = 0; + cl->buf_offset = 0; + free(cl->buf); + cl->buf = NULL; + ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); + } +} + +static void +_ecore_con_event_client_data_free(void *data __UNUSED__, void *ev) +{ + Ecore_Con_Event_Client_Data *e; + + e = ev; + if (e->data) free(e->data); + free(e); +} + +static void +_ecore_con_event_server_data_free(void *data __UNUSED__, void *ev) +{ + Ecore_Con_Event_Server_Data *e; + + e = ev; + if (e->data) free(e->data); + free(e); +} diff --git a/ecore/src/lib/ecore_con/ecore_con_private.h b/ecore/src/lib/ecore_con/ecore_con_private.h new file mode 100644 index 0000000..d94793e --- /dev/null +++ b/ecore/src/lib/ecore_con/ecore_con_private.h @@ -0,0 +1,86 @@ +#ifndef _ECORE_CON_PRIVATE_H +#define _ECORE_CON_PRIVATE_H + +#define ECORE_MAGIC_CON_SERVER 0x77665544 +#define ECORE_MAGIC_CON_CLIENT 0x77556677 + +#if USE_OPENSSL +#include <openssl/ssl.h> +#endif +#ifdef HAVE_CURL +#include <curl/curl.h> +#endif + +#define READBUFSIZ 65536 + +typedef struct _Ecore_Con_Client Ecore_Con_Client; +typedef struct _Ecore_Con_Server Ecore_Con_Server; +#ifdef HAVE_CURL +typedef struct _Ecore_Con_Url Ecore_Con_Url; +#else +typedef void Ecore_Con_Url; +#endif + +typedef enum _Ecore_Con_Type +{ + ECORE_CON_LOCAL_USER, + ECORE_CON_LOCAL_SYSTEM, + ECORE_CON_REMOTE_SYSTEM +#if USE_OPENSSL + ,ECORE_CON_USE_SSL = 16 +#endif +} Ecore_Con_Type; + +struct _Ecore_Con_Client +{ + Ecore_List __list_data; + ECORE_MAGIC; + int fd; + Ecore_Con_Server *server; + void *data; + Ecore_Fd_Handler *fd_handler; + int buf_size; + int buf_offset; + unsigned char *buf; + char dead : 1; +}; + +struct _Ecore_Con_Server +{ + Ecore_List __list_data; + ECORE_MAGIC; + int fd; + Ecore_Con_Type type; + char *name; + int port; + char *path; + void *data; + Ecore_Fd_Handler *fd_handler; + Ecore_List *clients; + int write_buf_size; + int write_buf_offset; + unsigned char *write_buf; + char dead : 1; + char created : 1; + char connecting : 1; + char reject_excess_clients : 1; + int client_limit; + +#if USE_OPENSSL + SSL_CTX *ssl_ctx; + SSL *ssl; +#endif +}; + +#ifdef HAVE_CURL +struct _Ecore_Con_Url +{ + /* FIXME: ECORE_MAGIC ? */ + CURL *curl_easy; + char *url; + struct curl_slist *headers; + Ecore_Fd_Handler *fd_handler; + char active : 1; +}; +#endif +#endif diff --git a/ecore/src/lib/ecore_con/ecore_con_url.c b/ecore/src/lib/ecore_con/ecore_con_url.c new file mode 100644 index 0000000..2789233 --- /dev/null +++ b/ecore/src/lib/ecore_con/ecore_con_url.c @@ -0,0 +1,408 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +/* + * For info on how to use libcurl, see: + * http://curl.haxx.se/libcurl/c/libcurl-tutorial.html + */ + +/* + * Brief usage: + * 1. Create an Ecore_Con_Url object + * 2. Register to receive the ECORE_CON_EVENT_URL_COMPLETE event + * (and optionally the ECORE_CON_EVENT_URL_DATA event to receive + * the response, e.g. for HTTP/FTP downloads) + * 3. Set the URL with ecore_con_url_url_set(...); + * 4. Perform the operation with ecore_con_url_send(...); + * + * Note that it is good to reuse Ecore_Con_Url objects wherever possible, but + * bear in mind that each one can only perform one operation at a time. + * You need to wait for the ECORE_CON_EVENT_URL_COMPLETE event before re-using + * or destroying the object. + * + * Example Usage 1 (HTTP GET): + * ecore_con_url_url_set(url_con, "http://www.google.com"); + * ecore_con_url_send(url, NULL, 0, NULL); + * + * Example usage 2 (HTTP POST): + * ecore_con_url_url_set(url_con, "http://www.example.com/post_handler.cgi"); + * ecore_con_url_send(url, data, data_length, "multipart/form-data"); + * + * Example Usage 3 (FTP download): + * ecore_con_url_url_set(url_con, "ftp://ftp.example.com/pub/myfile"); + * ecore_con_url_send(url, NULL, 0, NULL); + * + * FIXME: Support more CURL features: Authentication, FTP upload, Progress callbacks and more... + */ +#include "Ecore.h" +#include "config.h" +#include "ecore_private.h" +#include "ecore_con_private.h" +#include "Ecore_Con.h" + +#ifdef HAVE_CURL +static int _ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_con_url_perform(Ecore_Con_Url *url_con); +size_t _ecore_con_url_data_cb(void *buffer, size_t size, size_t nmemb, void *userp); +static void _ecore_con_event_url_complete_free(void *data __UNUSED__, void *ev); +static void _ecore_con_event_url_data_free(void *data __UNUSED__, void *ev); +static int _ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match); + +int ECORE_CON_EVENT_URL_DATA = 0; +int ECORE_CON_EVENT_URL_COMPLETE = 0; + +static CURLM *curlm = NULL; +static Ecore_List *_url_con_list = NULL; +static fd_set _current_fd_set; +static int init_count = 0; +#endif + +int +ecore_con_url_init(void) +{ +#ifdef HAVE_CURL + if (!ECORE_CON_EVENT_URL_DATA) + { + ECORE_CON_EVENT_URL_DATA = ecore_event_type_new(); + ECORE_CON_EVENT_URL_COMPLETE = ecore_event_type_new(); + } + + if (!_url_con_list) + { + _url_con_list = ecore_list_new(); + if (!_url_con_list) return 0; + } + + if (!curlm) + { + FD_ZERO(&_current_fd_set); + if (curl_global_init(CURL_GLOBAL_NOTHING)) + { + ecore_list_destroy(_url_con_list); + _url_con_list = NULL; + return 0; + } + + curlm = curl_multi_init(); + if (!curlm) + { + ecore_list_destroy(_url_con_list); + _url_con_list = NULL; + return 0; + } + } + init_count++; + return 1; +#else + return 0; +#endif +} + +int +ecore_con_url_shutdown(void) +{ +#ifdef HAVE_CURL + + if (!init_count) + return 0; + + init_count--; + if (_url_con_list) + { + if (!ecore_list_is_empty(_url_con_list)) + { + Ecore_Con_Url *url_con; + while ((url_con = ecore_list_remove_first(_url_con_list))) + { + ecore_con_url_destroy(url_con); + } + } + ecore_list_destroy(_url_con_list); + _url_con_list = NULL; + } + + if (curlm) + { + curl_multi_cleanup(curlm); + curlm = NULL; + } + + curl_global_cleanup(); +#endif + return 1; +} + +Ecore_Con_Url * +ecore_con_url_new(const char *url) +{ +#ifdef HAVE_CURL + Ecore_Con_Url *url_con; + + if (!init_count) return NULL; + + url_con = calloc(1, sizeof(Ecore_Con_Url)); + if (!url_con) return NULL; + + url_con->curl_easy = curl_easy_init(); + if (!url_con->curl_easy) + { + free(url_con); + return NULL; + } + + ecore_con_url_url_set(url_con, url); + + curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEFUNCTION, _ecore_con_url_data_cb); + curl_easy_setopt(url_con->curl_easy, CURLOPT_WRITEDATA, url_con); + /* + * FIXME: Check that these timeouts are sensible defaults + * FIXME: Provide a means to change these timeouts + */ + curl_easy_setopt(url_con->curl_easy, CURLOPT_CONNECTTIMEOUT, 30); + curl_easy_setopt(url_con->curl_easy, CURLOPT_TIMEOUT, 300); + + return url_con; +#else + return NULL; +#endif +} + +void +ecore_con_url_destroy(Ecore_Con_Url *url_con) +{ +#ifdef HAVE_CURL + if (!url_con) return; + + if (url_con->fd_handler) + ecore_main_fd_handler_del(url_con->fd_handler); + if (url_con->curl_easy) + { + if (url_con->active) + curl_multi_remove_handle(curlm, url_con->curl_easy); + curl_easy_cleanup(url_con->curl_easy); + } + curl_slist_free_all(url_con->headers); + free(url_con->url); + free(url_con); +#endif +} + +int +ecore_con_url_url_set(Ecore_Con_Url *url_con, const char *url) +{ +#ifdef HAVE_CURL + if (url_con->active) return 0; + + free(url_con->url); + url_con->url = NULL; + if (url) + url_con->url = strdup(url); + curl_easy_setopt(url_con->curl_easy, CURLOPT_URL, url_con->url); + +#endif + return 1; +} + +int +ecore_con_url_send(Ecore_Con_Url *url_con, void *data, size_t length, char *content_type) +{ +#ifdef HAVE_CURL + char tmp[256]; + + if (url_con->active) return 0; + if (!url_con->url) return 0; + + curl_slist_free_all(url_con->headers); + url_con->headers = NULL; + + if (data) + { + curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, data); + curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDSIZE, length); + + if (content_type && (strlen(content_type) < 200)) + { + sprintf(tmp, "Content-type: %s", content_type); + url_con->headers = curl_slist_append(url_con->headers, tmp); + } + sprintf(tmp, "Content-length: %d", length); + url_con->headers = curl_slist_append(url_con->headers, tmp); + } + else + { + curl_easy_setopt(url_con->curl_easy, CURLOPT_POSTFIELDS, NULL); + } + + curl_easy_setopt(url_con->curl_easy, CURLOPT_HTTPHEADER, url_con->headers); + + return _ecore_con_url_perform(url_con); +#else + return 0; +#endif +} + +#ifdef HAVE_CURL +size_t +_ecore_con_url_data_cb(void *buffer, size_t size, size_t nmemb, void *userp) +{ + Ecore_Con_Url *url_con; + Ecore_Con_Event_Url_Data *e; + size_t real_size = size * nmemb; + + url_con = (Ecore_Con_Url *)userp; + e = calloc(1, sizeof(Ecore_Con_Event_Url_Data)); + if (e) + { + e->url_con = url_con; + e->data = buffer; + e->size = real_size; + ecore_event_add(ECORE_CON_EVENT_URL_DATA, e, + _ecore_con_event_url_data_free, NULL); + } + return real_size; +} + +/* + * FIXME: Use + * CURLOPT_PROGRESSFUNCTION and CURLOPT_PROGRESSDATA to + * get reports on progress. + * And maybe other nifty functions... + */ +static int +_ecore_con_url_perform(Ecore_Con_Url *url_con) +{ + fd_set read_set, write_set, exc_set; + int fd_max; + int fd; + int flags; + int still_running; + int completed_immediately = 0; + + ecore_list_append(_url_con_list, url_con); + + url_con->active = 1; + curl_multi_add_handle(curlm, url_con->curl_easy); + while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM); + + completed_immediately = _ecore_con_url_process_completed_jobs(url_con); + + if (!completed_immediately) + { + /* url_con still active -- set up an fd_handler */ + FD_ZERO(&read_set); + FD_ZERO(&write_set); + FD_ZERO(&exc_set); + + /* Stupid curl, why can't I get the fd to the current added job? */ + curl_multi_fdset(curlm, &read_set, &write_set, &exc_set, &fd_max); + for (fd = 0; fd <= fd_max; fd++) + { + if (!FD_ISSET(fd, &_current_fd_set)) + { + flags = 0; + if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ; + if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE; + if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR; + if (flags) + { + FD_SET(fd, &_current_fd_set); + url_con->fd_handler = ecore_main_fd_handler_add(fd, flags, + _ecore_con_url_fd_handler, + NULL, NULL, NULL); + } + } + } + if (!url_con->fd_handler) + { + /* Failed to set up an fd_handler */ + curl_multi_remove_handle(curlm, url_con->curl_easy); + url_con->active = 0; + return 0; + } + } + + return 1; +} + +static int +_ecore_con_url_fd_handler(void *data, Ecore_Fd_Handler *fd_handler) +{ + int still_running; + + /* FIXME: Can this run for a long time? Maybe limit how long it can run */ + while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM); + + _ecore_con_url_process_completed_jobs(NULL); + return 1; +} + +static int +_ecore_con_url_process_completed_jobs(Ecore_Con_Url *url_con_to_match) +{ + Ecore_Con_Url *url_con; + CURLMsg *curlmsg; + int n_remaining; + int job_matched = 0; + + /* Loop jobs and check if any are done */ + while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL) + { + if (curlmsg->msg != CURLMSG_DONE) continue; + + /* find the job which is done */ + ecore_list_goto_first(_url_con_list); + while ((url_con = ecore_list_current(_url_con_list))) + { + if (curlmsg->easy_handle == url_con->curl_easy) + { + /* We have found the completed job in our job list */ + if (url_con_to_match && (url_con == url_con_to_match)) { + job_matched = 1; + } + if (url_con->fd_handler) + { + FD_CLR(ecore_main_fd_handler_fd_get(url_con->fd_handler), + &_current_fd_set); + ecore_main_fd_handler_del(url_con->fd_handler); + url_con->fd_handler = NULL; + } + ecore_list_remove(_url_con_list); + curl_multi_remove_handle(curlm, url_con->curl_easy); + url_con->active = 0; + { + Ecore_Con_Event_Url_Complete *e; + e = calloc(1, sizeof(Ecore_Con_Event_Url_Complete)); + if (e) + { + e->url_con = url_con; + e->status = curlmsg->data.result; + ecore_event_add(ECORE_CON_EVENT_URL_COMPLETE, e, + _ecore_con_event_url_complete_free, NULL); + } + } + break; + } + ecore_list_next(_url_con_list); + } + } + return job_matched; +} +static void +_ecore_con_event_url_data_free(void *data __UNUSED__, void *ev) +{ + Ecore_Con_Event_Url_Data *e; + + e = ev; + free(e); +} + +static void +_ecore_con_event_url_complete_free(void *data __UNUSED__, void *ev) +{ + Ecore_Con_Event_Url_Complete *e; + + e = ev; + free(e); +} +#endif diff --git a/ecore/src/lib/ecore_config/.cvsignore b/ecore/src/lib/ecore_config/.cvsignore new file mode 100644 index 0000000..59bc827 --- /dev/null +++ b/ecore/src/lib/ecore_config/.cvsignore @@ -0,0 +1,8 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +libecore_config.la +ecore_config_ipc_ecore.la +system.db diff --git a/ecore/src/lib/ecore_config/CVS/Entries b/ecore/src/lib/ecore_config/CVS/Entries new file mode 100644 index 0000000..c0a38b1 --- /dev/null +++ b/ecore/src/lib/ecore_config/CVS/Entries @@ -0,0 +1,14 @@ +/.cvsignore/1.7/Sat Oct 23 14:27:10 2004//THEAD +/Ecore_Config.h/1.42/Wed Mar 2 07:06:34 2005//THEAD +/Makefile.am/1.28/Tue Jun 7 21:53:58 2005//THEAD +/ecore_config_db.c/1.6/Sat Jun 25 10:11:25 2005//THEAD +/ecore_config_extra.c/1.6/Tue Mar 22 20:40:19 2005//THEAD +/ecore_config_ipc.h/1.2/Wed Mar 2 07:06:34 2005//THEAD +/ecore_config_ipc_ecore.c/1.8/Sat Jun 25 10:11:25 2005//THEAD +/ecore_config_ipc_main.c/1.3/Tue Jun 7 21:54:07 2005//THEAD +/ecore_config_private.h/1.8/Sat Jun 25 10:11:25 2005//THEAD +/ecore_config_storage.c/1.9/Sat Jun 25 10:11:25 2005//THEAD +/ecore_config_util.c/1.2/Wed Mar 2 07:06:34 2005//THEAD +/ecore_config_util.h/1.2/Wed Mar 2 07:06:34 2005//THEAD +/ecore_config.c/1.60/Sat Jul 23 17:35:06 2005//THEAD +D diff --git a/ecore/src/lib/ecore_config/CVS/Entries.Log b/ecore/src/lib/ecore_config/CVS/Entries.Log new file mode 100644 index 0000000..8e2b110 --- /dev/null +++ b/ecore/src/lib/ecore_config/CVS/Entries.Log @@ -0,0 +1,2 @@ +A D/ipc//// +R D/ipc//// diff --git a/ecore/src/lib/ecore_config/CVS/Repository b/ecore/src/lib/ecore_config/CVS/Repository new file mode 100644 index 0000000..eac9a27 --- /dev/null +++ b/ecore/src/lib/ecore_config/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_config diff --git a/ecore/src/lib/ecore_config/CVS/Root b/ecore/src/lib/ecore_config/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_config/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_config/CVS/Tag b/ecore/src/lib/ecore_config/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_config/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_config/Ecore_Config.h b/ecore/src/lib/ecore_config/Ecore_Config.h new file mode 100644 index 0000000..650feeb --- /dev/null +++ b/ecore/src/lib/ecore_config/Ecore_Config.h @@ -0,0 +1,308 @@ +#ifndef _ECORE_CONFIG_H +# define _ECORE_CONFIG_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file + * @brief Provides the Enlightened Property Library. + * + * This file provies all headers and structs for use with Ecore_Config. + * Using individual header files should not be necessary. + */ + +# define DIR_DELIMITER '/' +# define ECORE_CONFIG_FLOAT_PRECISION 1000 + +# ifndef TRUE +# define FALSE (0) +# define TRUE (!FALSE) +# endif + +/* FIXME: this should only be included if evas is present */ +# include <Evas.h> + +# define ECORE_CONFIG_GLOBAL_ID "_system" + +/* structures */ + +/** + * Valid configuration property types. + */ +typedef enum Ecore_Config_Type +{ + PT_NIL = 0, /**< Property with no value. */ + PT_INT = 1, /**< Integer property type. */ + PT_FLT = 2, /**< Float property type. */ + PT_STR = 3, /**< String property type. */ + PT_RGB = 4, /**< Colour property type. */ + PT_THM = 5, /**< Theme property type. */ + PT_BLN = 6, /**< Boolean property type. */ +} Ecore_Config_Type; + +typedef enum Ecore_Config_Flag +{ + PF_NONE = 0, + PF_BOUNDS = 1, + PF_MODIFIED = 2, + PF_SYSTEM = 4, + PF_CMDLN = 8 +} Ecore_Config_Flag; + +/** + * Property change callback function prototype. + */ +typedef int (*Ecore_Config_Listener) (const char *key, + const Ecore_Config_Type type, + const int tag, void *data); + +typedef struct Ecore_Config_Listener_List +{ + Ecore_Config_Listener listener; + const char *name; + void *data; + int tag; + struct Ecore_Config_Listener_List *next; +} Ecore_Config_Listener_List; + +/** + * The actual property for storing a key-value pair. + */ +typedef struct Ecore_Config_Prop +{ + char *key; /* Property key. */ + char *description; /* Description set by ecore_config_descibe. */ + char short_opt; /* short identifier on command line (-f) */ + char *long_opt; /* long identifier on command line (--foo) */ + char *ptr; /* Used as the value when the property is a string or theme. */ + Ecore_Config_Type type; /* Property type. */ + long val; /* Used as the value when the property is an integer, float or colour. */ + long lo; /* Lower bound for the value when the property is an integer or float. */ + long hi; /* Higher bound for the value when the property is an integer or float. */ + long step; /* Increment for the value when the property is an integer or float. */ + Ecore_Config_Flag flags; /// < Configuration flags. + Ecore_Config_Listener_List *listeners; /* List of change listeners. */ + void *data; /// < Stores extra data for the property. + struct Ecore_Config_Prop *next; /* Pointer to the next property in the list. */ +} Ecore_Config_Prop; + +/* + * A container for a list of properties. Provided so that an + * application can use different set of properties at any time. This + * is useful for multiple window support. + */ +typedef struct Ecore_Config_Bundle +{ + char *identifier; /* Identifier for this set of properties (window ID for example) */ + char *owner; /* This is used to store the application name related to the bundle */ + long serial; /* Unique identifier to identify bundle */ + Ecore_Config_Prop *data; /* Pointer to root of property list */ + void *user_data; /* App specific pointer to "other data" */ + struct Ecore_Config_Bundle *next; /* Pointer to next bundle in this application */ +} Ecore_Config_Bundle; + +typedef struct Ecore_Config_Server +{ + void *server; + char *name; + Ecore_Config_Bundle *bundles; /* data anchor */ + struct Ecore_Config_Server *next; +} Ecore_Config_Server; + +# ifdef __cplusplus +extern "C" +{ +# endif + +/* global ptrs to save passing them through the API */ + extern EAPI Ecore_Config_Server *__ecore_config_server_global; + extern EAPI Ecore_Config_Server *__ecore_config_server_local; + extern EAPI Ecore_Config_Bundle *__ecore_config_bundle_local; + extern EAPI char *__ecore_config_app_name; + + EAPI Ecore_Config_Prop *ecore_config_get(const char *key); + EAPI const char *ecore_config_type_get(const Ecore_Config_Prop * e); + EAPI int ecore_config_boolean_get(const char *key); + EAPI void *ecore_config_data_get(const char *key); + EAPI char *ecore_config_string_get(const char *key); + EAPI long ecore_config_int_get(const char *key); + EAPI int ecore_config_rgb_get(const char *key, int *r, int *g, + int *b); + EAPI int ecore_config_argb_get(const char *key, int *a, int *r, + int *g, int *b); + EAPI char *ecore_config_rgbstr_get(const char *key); + EAPI char *ecore_config_argbstr_get(const char *key); + EAPI float ecore_config_float_get(const char *key); + EAPI char *ecore_config_theme_get(const char *key); + EAPI char *ecore_config_as_string_get(const char *key); + EAPI int ecore_config_bound(Ecore_Config_Prop * e); + EAPI int ecore_config_describe(const char *key, char *desc); + EAPI int ecore_config_short_opt_set(const char *key, + char short_opt); + EAPI int ecore_config_long_opt_set(const char *key, + char *long_opt); + EAPI int ecore_config_set(const char *key, char *val); + EAPI int ecore_config_typed_set(const char *key, const void *val, + int type); + EAPI int ecore_config_boolean_set(const char *key, int val); + EAPI int ecore_config_string_set(const char *key, char *val); + EAPI int ecore_config_int_set(const char *key, int val); + EAPI char *ecore_config_rgb_to_argb(char *rgb); + EAPI int ecore_config_rgb_set(const char *key, char *val); + EAPI int ecore_config_argb_set(const char *key, char *val); + EAPI int ecore_config_float_set(const char *key, float val); + EAPI int ecore_config_theme_set(const char *key, char *val); + EAPI int ecore_config_theme_preview_group_set(const char *key, + char *group); + EAPI int ecore_config_as_string_set(const char *key, char *val); + + EAPI int ecore_config_default(const char *key, char *val, + float lo, float hi, float step); + EAPI int ecore_config_typed_default(const char *key, void *val, + int type); + EAPI int ecore_config_boolean_default(const char *key, int val); + EAPI int ecore_config_int_default(const char *key, int val); + EAPI int ecore_config_int_default_bound(const char *key, int val, + int lo, int hi, int step); + EAPI int ecore_config_string_default(const char *key, const char *val); + EAPI int ecore_config_float_default(const char *key, float val); + EAPI int ecore_config_float_default_bound(const char *key, + float val, float lo, + float hi, float step); + EAPI int ecore_config_rgb_default(const char *key, char *val); + EAPI int ecore_config_argb_default(const char *keym, char *val); + EAPI int ecore_config_theme_default(const char *key, char *val); + + EAPI int ecore_config_listen(const char *name, const char *key, + Ecore_Config_Listener listener, + int tag, void *data); + EAPI int ecore_config_deaf(const char *name, const char *key, + Ecore_Config_Listener listener); + EAPI Ecore_Config_Prop *ecore_config_dst(Ecore_Config_Prop * e); + EAPI int ecore_config_type_guess(const char *key, const char *val); + + EAPI Ecore_Config_Bundle *ecore_config_bundle_new(Ecore_Config_Server * srv, + const char *id); + EAPI Ecore_Config_Bundle *ecore_config_bundle_1st_get(Ecore_Config_Server * srv); + EAPI Ecore_Config_Bundle *ecore_config_bundle_next_get(Ecore_Config_Bundle * ns); + EAPI Ecore_Config_Bundle *ecore_config_bundle_by_serial_get(Ecore_Config_Server * + srv, long serial); + EAPI Ecore_Config_Bundle *ecore_config_bundle_by_label_get(Ecore_Config_Server * + srv, + const char *label); + EAPI long ecore_config_bundle_serial_get(Ecore_Config_Bundle * ns); + EAPI char *ecore_config_bundle_label_get(Ecore_Config_Bundle * ns); + + EAPI int ecore_config_init(const char *name); + EAPI int ecore_config_shutdown(void); + + EAPI int ecore_config_system_init(void); + EAPI int ecore_config_system_shutdown(void); + + EAPI int ecore_config_load(void); + EAPI int ecore_config_file_load(const char *file); + EAPI int ecore_config_save(void); + EAPI int ecore_config_file_save(const char *file); + +/* error codes */ +# define ECORE_CONFIG_ERR_NOTSUPP (-16) +# define ECORE_CONFIG_ERR_NOFILE (-15) +# define ECORE_CONFIG_ERR_META_DLFAIL (-14) +# define ECORE_CONFIG_ERR_META_FILE (-13) +# define ECORE_CONFIG_ERR_META_FORMAT (-12) +# define ECORE_CONFIG_ERR_MONMIS (-11) +# define ECORE_CONFIG_ERR_NOEXEC (-10) +# define ECORE_CONFIG_ERR_PARTIAL (-9) +# define ECORE_CONFIG_ERR_PATHEX (-8) +# define ECORE_CONFIG_ERR_TYPEMISMATCH (-7) +# define ECORE_CONFIG_ERR_MUTEX (-6) +# define ECORE_CONFIG_ERR_NOTFOUND (-5) /* Error indicating that the item searched for could not be found. */ +# define ECORE_CONFIG_ERR_OOM (-4) /* Error given when the program runs out of memory. */ +# define ECORE_CONFIG_ERR_IGNORED (-3) /* Error occurred, but was ignored. */ +# define ECORE_CONFIG_ERR_NODATA (-2) /* Error given when necessary data is not provided. */ +# define ECORE_CONFIG_ERR_FAIL (-1) /* Failure result. */ +# define ECORE_CONFIG_ERR_SUCC (0) /* Success result. */ + +# define ECORE_CONFIG_PARSE_HELP (-2) /* Help was displayed */ +# define ECORE_CONFIG_PARSE_EXIT (-1) /* An error occurred */ +# define ECORE_CONFIG_PARSE_CONTINUE (0) /* Arguments parsed successfully */ + +/* convenience mathods in convenience.c */ + /* FIXME: this should only be included if evas is present */ + EAPI int ecore_config_evas_font_path_apply(Evas * evas); + EAPI char *ecore_config_theme_search_path_get(void); + EAPI int ecore_config_theme_search_path_append(char *append); + + EAPI char *ecore_config_theme_default_path_get(void); + EAPI char *ecore_config_theme_with_path_from_name_get(char *name); + EAPI char *ecore_config_theme_with_path_get(const char *key); + EAPI void ecore_config_args_display(void); + EAPI int ecore_config_args_parse(void); + EAPI void ecore_config_args_callback_str_add(char short_opt, + char *long_opt, char *desc, + void (*func)(char *val, void *data), + void *data); + EAPI void ecore_config_args_callback_noarg_add(char short_opt, + char *long_opt, char *desc, + void (*func)(char *val, void *data), + void *data); + EAPI void ecore_config_app_describe(char *description); + + EAPI int ecore_config_create(const char *key, void *val, + char short_opt, char *long_opt, + char *desc); + EAPI int ecore_config_typed_create(const char *key, void *val, + int type, char short_opt, + char *long_opt, char *desc); + EAPI int ecore_config_boolean_create(const char *key, int val, + char short_opt, char *long_opt, + char *desc); + EAPI int ecore_config_int_create(const char *key, int val, + char short_opt, char *long_opt, + char *desc); + EAPI int ecore_config_int_create_bound(const char *key, int val, + int low, int high, + int step, char short_opt, + char *long_opt, + char *desc); + EAPI int ecore_config_string_create(const char *key, char *val, + char short_opt, + char *long_opt, char *desc); + EAPI int ecore_config_float_create(const char *key, float val, + char short_opt, char *long_opt, + char *desc); + EAPI int ecore_config_float_create_bound(const char *key, + float val, float low, + float high, float step, + char short_opt, + char *long_opt, + char *desc); + EAPI int ecore_config_rgb_create(const char *key, char *val, + char short_opt, char *long_opt, + char *desc); + EAPI int ecore_config_argb_create(const char *key, char *val, + char short_opt, char *long_opt, + char *desc); + EAPI int ecore_config_theme_create(const char *key, char *val, + char short_opt, char *long_opt, + char *desc); + +# ifdef __cplusplus +} +# endif +#endif diff --git a/ecore/src/lib/ecore_config/Makefile.am b/ecore/src/lib/ecore_config/Makefile.am new file mode 100644 index 0000000..795eef4 --- /dev/null +++ b/ecore/src/lib/ecore_config/Makefile.am @@ -0,0 +1,65 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_ipc \ +-I$(top_srcdir)/ \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_ipc \ +-I$(top_builddir)/ \ +@evas_cflags@ @eet_cflags@ + +CLEANFILES = $(DB) + +libecore_config_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_CONFIG + +#DB = system.db +#$(DB): Makefile +# edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /e/theme/name str "winter" +# edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /e/font/path str "$(pkgdatadir)/data/fonts" +# edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /apps/web/browser str `which firefox 2>/dev/null || which phoenix 2>/dev/null || which mozilla 2>/dev/null || which opera 2>/dev/null || which konqueror 2>/dev/null || which epiphany 2>/dev/null` +# edb_ed $(top_builddir)/src/lib/ecore_config/$(DB) add /apps/web/email str `which thunderbird 2>/dev/null || which mozilla 2>/dev/null || which kmail 2>/dev/null || which sylpheed 2>/dev/null || which evolution 2>/dev/null` + +lib_LTLIBRARIES = libecore_config.la +include_HEADERS = \ +Ecore_Config.h + +#config_DATA = $(DB) +#configdir = $(pkgdatadir) + +libecore_config_la_SOURCES = \ +ecore_config.c \ +ecore_config_ipc_main.c \ +ecore_config_ipc_ecore.c \ +ecore_config_util.c \ +ecore_config_storage.c \ +ecore_config_extra.c \ +ecore_config_db.c \ +ecore_config_private.h + +libecore_config_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_ipc/libecore_ipc.la \ +@eet_libs@ \ +@evas_libs@ + +libecore_config_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_ipc/libecore_ipc.la + + +endif + +EXTRA_DIST = \ +Ecore_Config.h \ +ecore_config.c \ +ecore_config_ipc_ecore.c \ +ecore_config_ipc_main.c \ +ecore_config_ipc.h \ +ecore_config_util.c \ +ecore_config_util.h \ +ecore_config_storage.c + diff --git a/ecore/src/lib/ecore_config/ecore_config.c b/ecore/src/lib/ecore_config/ecore_config.c new file mode 100644 index 0000000..df6ea43 --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config.c @@ -0,0 +1,1623 @@ +#include "Ecore_Config.h" +#include "config.h" +#include "ecore_config_private.h" +#include "ecore_config_ipc.h" + +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <limits.h> +#include <unistd.h> +#include "ecore_config_util.h" + +int DEBUG = 0; +Ecore_Config_Server *__ecore_config_server_global = NULL; +Ecore_Config_Server *__ecore_config_server_local = NULL; +Ecore_Config_Bundle *__ecore_config_bundle_local = NULL; +char *__ecore_config_app_name = NULL; +int __ecore_config_system_init = 0; + +static int _ecore_config_system_init_no_load(void); +static int _ecore_config_system_load(void); + +static const char *_ecore_config_type[] = + { "undefined", "integer", "float", "string", "colour", "theme", "boolean" }; + +/** + * @defgroup Ecore_Config_Property_Group Ecore Config Property Functions + * + * Functions that retrieve or set the attributes relating to a property. + */ + +/** + * Removes the given property from the local configuration and destroys it. + * @param e Property to destroy. + * @return @c NULL + * @ingroup Ecore_Config_Property_Group + */ +Ecore_Config_Prop * +ecore_config_dst(Ecore_Config_Prop * e) +{ + Ecore_Config_Bundle *t; + Ecore_Config_Prop *p, *c; + Ecore_Config_Listener_List *l; + + p = NULL; + c = e; + t = __ecore_config_bundle_local; + + if (!e || !e->key) + return NULL; + if (t) + { + if (t->data == e) + t->data = e->next; + else + { + do + { + p = c; + c = c->next; + } + while (c && (c != e)); + if (c) /* remove from list if even in there */ + p->next = c->next; + } + } + + while (e->listeners) + { + l = e->listeners; + e->listeners = e->listeners->next; + free(l); + } + + if (e->key) + free(e->key); + if (e->ptr && (e->type == PT_STR)) + free(e->ptr); + + memset(e, 0, sizeof(Ecore_Config_Prop)); + free(e); + + return NULL; +} + +/** + * @defgroup Ecore_Config_Get_Group Configuration Retrieve Functions + * + * Functions that retrieve configuration values, based on type. + */ + +/** + * Returns the property with the given key. + * @param key The unique name of the wanted property. + * @return The property that corresponds to the given key. @c NULL if the + * key could not be found. + * @ingroup Ecore_Config_Get_Group + */ +Ecore_Config_Prop * +ecore_config_get(const char *key) +{ + Ecore_Config_Bundle *t; + Ecore_Config_Prop *e; + + t = __ecore_config_bundle_local; + if (!t || !key) + return NULL; + e = t->data; + while (e) + { + if (!strcmp(key, e->key)) + return e; + e = e->next; + } + return NULL; +} + +/** + * Returns the type of the property. + * @param e Property to get the type of. + * @returns The type of the property. If the property is invalid, then the + * string "not found" is returned. + * @ingroup Ecore_Config_Property_Group + */ +const char * +ecore_config_type_get(const Ecore_Config_Prop * e) +{ + if (e) + { + return _ecore_config_type[e->type]; + } + return "not found"; +} + +/** + * Obtains the data pointed to by the specified property. + * @param key The property key. + * @return Data pointer used by the property. + * @ingroup Ecore_Config_Get_Group + */ +void * +ecore_config_data_get(const char *key) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + return (e ? ((e->type == PT_STR) ? ((void *)&e->ptr) : ((void *)&e->val)) + : NULL); +} + +/** + * Returns the specified property as a string. + * @param key The property key. + * @return The string value of the property. The function returns @c NULL if + * the property is not a string or is not set. + * @ingroup Ecore_Config_Get_Group + */ +char * +ecore_config_string_get(const char *key) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + return (e && (e->type == PT_STR)) ? strdup(e->ptr) : NULL; +} + +/** + * Returns the specified property as an integer. + * @param key The property key. + * @return The value of the property. The function returns -1 if the + * property is not an integer or is not set. + * @ingroup Ecore_Config_Get_Group + */ +int +ecore_config_boolean_get(const char *key) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + return (e && ((e->type == PT_INT) || (e->type == PT_BLN))) ? (e->val != 0) : -1; +} + +/** + * Returns the specified property as a long integer. + * @param key The property key. + * @return The integer value of the property. The function returns 0 if the + * property is not an integer or is not set. + * @ingroup Ecore_Config_Get_Group + */ +long +ecore_config_int_get(const char *key) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + return (e && ((e->type == PT_INT) || (e->type == PT_RGB))) ? e->val : 0L; +} + +/** + * Returns the specified property as a float. + * @param key The property key. + * @return The float value of the property. The function returns 0.0 if the + * property is not a float or is not set. + * @ingroup Ecore_Config_Get_Group + */ +float +ecore_config_float_get(const char *key) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + return (e + && (e->type == + PT_FLT)) ? ((float)e->val / ECORE_CONFIG_FLOAT_PRECISION) : 0.0; +} + +/** + * Finds the red, green and blue values of a color property. + * @param key The property key. + * @param r A pointer to an integer to store the red value into. + * @param g A pointer to an integer to store the green value into. + * @param b A pointer to an integer to store the blue value into. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_FAIL + * otherwise. + * @ingroup Ecore_Config_Get_Group + * @deprecated + */ +int +ecore_config_rgb_get(const char *key, int *r, int *g, int *b) +{ + int alpha; + return ecore_config_argb_get(key, &alpha, r, g, b); +} + +/** + * Finds the alpha, red, green and blue values of a color property. + * @param key The property key. + * @param a A pointer to an integer to store the alpha value into. + * @param r A pointer to an integer to store the red value into. + * @param g A pointer to an integer to store the green value into. + * @param b A pointer to an integer to store the blue value into. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_FAIL + * otherwise. + * @ingroup Ecore_Config_Get_Group + */ +int +ecore_config_argb_get(const char *key, int *a, int *r, int *g, int *b) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + + if (e && ((e->type == PT_RGB))) + { + *a = (e->val >> 24) & 0xff; + *r = (e->val >> 16) & 0xff; + *g = (e->val >> 8) & 0xff; + *b = e->val & 0xff; + return ECORE_CONFIG_ERR_SUCC; + } + return ECORE_CONFIG_ERR_FAIL; +} + +/** + * Returns a color property as a string of hexadecimal characters. + * @param key The property key. + * @return A string of hexadecimal characters in the format #rrggbb. + * @ingroup Ecore_Config_Get_Group + * @deprecated + */ +char * +ecore_config_rgbstr_get(const char *key) +{ + char *argb, *rgb; + + argb = ecore_config_argbstr_get(key); + rgb = argb + 2; + *rgb = '#'; + return rgb; +} + +/** + * Returns a color property as a string of hexadecimal characters. + * @param key The property key. + * @return A string of hexadecimal characters in the format #aarrggbb. + * @ingroup Ecore_Config_Get_Group + */ +char * +ecore_config_argbstr_get(const char *key) +{ + char *r; + + r = NULL; + esprintf(&r, "#%08x", ecore_config_int_get(key)); + return r; +} + +/** + * Returns a theme property. + * @param key The property key. + * @return The name of the theme the property refers to. The function returns + * @c NULL if the property is not a theme or is not set. + * @ingroup Ecore_Config_Get_Group + */ +char * +ecore_config_theme_get(const char *key) +{ + Ecore_Config_Prop *e; + + e = ecore_config_get(key); + return (e && (e->type == PT_THM)) ? strdup(e->ptr) : NULL; +} + +/** + * Retrieves the key as a string. + * @param key The property key. + * @return Returns a character array in the form of 'key:type=value'. @c NULL + * is returned if the property does not exist. + * @ingroup Ecore_Config_Get_Group + */ +char * +ecore_config_as_string_get(const char *key) +{ + Ecore_Config_Prop *e; + char *r; + + r = NULL; + if (!(e = ecore_config_get(key))) + E(0, "no such property, \"%s\"...\n", key); + else + { + const char *type = ecore_config_type_get(e); + + switch (e->type) + { + case PT_NIL: + esprintf(&r, "%s:%s=<nil>", key, type); + break; + case PT_INT: + esprintf(&r, "%s:%s=%ld", key, type, ecore_config_int_get(key)); + break; + case PT_BLN: + esprintf(&r, "%s:%s=%ld", key, type, ecore_config_boolean_get(key)); + break; + case PT_FLT: + esprintf(&r, "%s:%s=%lf", key, type, ecore_config_float_get(key)); + break; + case PT_STR: + esprintf(&r, "%s:%s=\"%s\"", key, type, + ecore_config_string_get(key)); + break; + case PT_RGB: + esprintf(&r, "%s:%s=#%08x", key, type, ecore_config_int_get(key)); + break; + case PT_THM: + esprintf(&r, "%s:%s=\"%s\"", key, type, + ecore_config_theme_get(key)); + break; + default: + esprintf(&r, "%s:unknown_type", key); + break; + } + } + return r; +} + +int +ecore_config_bound(Ecore_Config_Prop * e) +{ + int ret; + long v; + + ret = ECORE_CONFIG_ERR_SUCC; + + if (!e) + return ECORE_CONFIG_ERR_FAIL; + if (e->flags & PF_BOUNDS) + { + if ((e->val < e->lo)) + { + E(0, + "ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...\n", + e->key, e->val, e->lo); + e->val = e->lo; + } + else if ((e->val > e->hi)) + { + E(0, + "ecore_config_bounds(\"%s\",%ld): value out of range; adjusted to %ld...\n", + e->key, e->val, e->hi); + e->val = e->hi; + } + else + ret = ECORE_CONFIG_ERR_IGNORED; + } + else + ret = ECORE_CONFIG_ERR_IGNORED; + + if (e->step) + { + v = ((int)(e->val / e->step)) * e->step; + if (v != e->val) + { + if (e->type == PT_FLT) + E(0, + "ecore_config_bound(\"%s\"): float value %f not a multiple of %f, adjusted to %f...\n", + e->key, ((double)e->val) / ECORE_CONFIG_FLOAT_PRECISION, + ((double)e->step) / ECORE_CONFIG_FLOAT_PRECISION, + ((double)v) / ECORE_CONFIG_FLOAT_PRECISION); + else + E(0, + "ecore_config_bound(\"%s\"): integer value %ld not a multiple of %ld, adjusted to %ld...\n", + e->key, e->val, e->step, v); + ret = ECORE_CONFIG_ERR_SUCC; + e->val = v; + } + } + + return ret; +} + +/** + * Tries to guess the type of a property. + * + * This function first checks to see if the property exists. If it does, then + * the type of the stored property is returned. Otherwise, the function tries + * to guess the type of the property based on @p val. + * + * @param key The property key. + * @param val The value in string form. + * @return The type of the property determined by the function. Note that if + * val is @c NULL, @c PT_NIL will be returned. + */ +int +ecore_config_type_guess(const char *key, const char *val) +{ + Ecore_Config_Prop *p; + char *l; + long v; + + l = NULL; + + if ((p = ecore_config_get(key)) && p->type != PT_NIL) + return p->type; + + if (!val) + return PT_NIL; + if (val[0] == '#') + return PT_RGB; + v = strtol(val, &l, 10); + if (*l) + { + float f; + + if (sscanf(val, "%f%*s", &f) != 1) + return PT_STR; + return PT_FLT; + } + return PT_INT; +} + +static int +ecore_config_typed_val(Ecore_Config_Prop * e, const void *val, int type) +{ + char *l; + long v; + int *i; + float *f; + + l = NULL; + v = 0; + + if (!(val)) + e->ptr = NULL; + else + { + if (type == PT_INT) + { + i = (int *)val; + e->val = (long)*i; + e->type = PT_INT; + } + else if (type == PT_BLN ) + { + i = (int *)val; + e->val = (long)*i; + e->type = PT_BLN; + } + else if (type == PT_STR || type == PT_THM) + { + if (!(e->ptr = strdup(val))) + return ECORE_CONFIG_ERR_OOM; + if (e->type == PT_NIL) + e->type = type; + } + else if (type == PT_RGB) + { + if (((char *)val)[0] == '#') + { + if ((v = strtol(&((char *)val)[1], &l, 16)) < 0) + { + v = 0; + E(0, + "ecore_config_val: key \"%s\" -- hexadecimal value less than zero, bound to zero...\n", + (char *)val); + l = (char *)val; + } + } + else + { + E(0, + "ecore_config_val: key \"%s\" -- value \"%s\" not a valid hexadecimal RGB value?\n", + e->key, (char *)val); + return ECORE_CONFIG_ERR_FAIL; + } + if (*l) + E(0, + "ecore_config_val: key \"%s\" -- value \"%s\" not a valid hexadecimal RGB value?\n", + e->key, (char *)val); + else + { + e->val = v; + e->type = PT_RGB; + } + } + else if (type == PT_FLT) + { + f = (float *)val; + e->val = (long)((*f) * ECORE_CONFIG_FLOAT_PRECISION); + e->type = PT_FLT; + } + else + e->type = PT_NIL; + + ecore_config_bound(e); + e->flags |= PF_MODIFIED; + e->flags = e->flags & ~PF_CMDLN; + return ECORE_CONFIG_ERR_SUCC; + } + return ECORE_CONFIG_ERR_IGNORED; +} + +static int +ecore_config_typed_add(const char *key, const void *val, int type) +{ + int error = ECORE_CONFIG_ERR_SUCC; + Ecore_Config_Prop *e; + Ecore_Config_Bundle *t; + + t = __ecore_config_bundle_local; + if (!key) + return ECORE_CONFIG_ERR_NODATA; + + if (!(e = malloc(sizeof(Ecore_Config_Prop)))) + goto ret; + memset(e, 0, sizeof(Ecore_Config_Prop)); + + if (!(e->key = strdup(key))) + { + error = ECORE_CONFIG_ERR_OOM; + goto ret_free_nte; + } + + if ((error = ecore_config_typed_val(e, val, type) != ECORE_CONFIG_ERR_SUCC)) + goto ret_free_key; + + e->next = t ? t->data : NULL; + if (t) + { + t->data = e; + return ECORE_CONFIG_ERR_SUCC; + } + + ret_free_key: + free(e->key); + ret_free_nte: + free(e); + ret: + if (error == ECORE_CONFIG_ERR_SUCC) + error = ECORE_CONFIG_ERR_FAIL; + return error; +} + +static int +ecore_config_add(const char *key, const char *val) +{ + int type; + + type = ecore_config_type_guess(key, val); + return ecore_config_typed_add(key, val, type); +} + +/** + * Sets the description field of the indicated property. + * @param key The property key. + * @param desc Description string. + * @note The description string is copied for the property's use. You can + * free @p desc once this function is called. + * @ingroup Ecore_Config_Property_Group + */ +int +ecore_config_describe(const char *key, char *desc) +{ + Ecore_Config_Prop *e; + + if (!(e = ecore_config_get(key))) + return ECORE_CONFIG_ERR_NODATA; + e->description = strdup(desc); + return ECORE_CONFIG_ERR_SUCC; +} + +/** + * Set the short option character of a property. + * @param key The property key. + * @param short_opt Character used to indicate the value of a property + * given on the command line. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA + * is returned if the property does not exist. + * @ingroup Ecore_Config_Property_Group + */ +int +ecore_config_short_opt_set(const char *key, char short_opt) +{ + Ecore_Config_Prop *e; + + if (!(e = ecore_config_get(key))) + return ECORE_CONFIG_ERR_NODATA; + e->short_opt = short_opt; + return ECORE_CONFIG_ERR_SUCC; +} + +/** + * Set the long option string of the property. + * @param key The property key. + * @param long_opt String used to indicate the value of a property given + * on the command line. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA + * is returned if the property does not exist. + * @ingroup Ecore_Config_Property_Group + */ +int +ecore_config_long_opt_set(const char *key, char *long_opt) +{ + Ecore_Config_Prop *e; + + if (!(e = ecore_config_get(key))) + return ECORE_CONFIG_ERR_NODATA; + if (e->long_opt) + free(e->long_opt); + if (long_opt) + e->long_opt = strdup(long_opt); + return ECORE_CONFIG_ERR_SUCC; +} + +/** + * Sets the indicated property to the given value and type. + * @param key The property key. + * @param val A pointer to the value to set the property to. + * @param type The type of the property. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Property_Group + */ +int +ecore_config_typed_set(const char *key, const void *val, int type) +{ + Ecore_Config_Prop *e; + Ecore_Config_Listener_List *l; + int ret; + + if (!key) + return ECORE_CONFIG_ERR_NODATA; +/* if (!t) { * global prop * + e=ecore_config_get(key); + if (e) + for(l=e->listeners;l;l=l->next) + l->listener(e->key,e->type,l->tag,l->data,t); + return ECORE_CONFIG_ERR_SUCC; + } +*/ + if (!(e = ecore_config_get(key))) + return ecore_config_typed_add(key, val, type); + + if ((ret = ecore_config_typed_val(e, val, type)) == ECORE_CONFIG_ERR_SUCC) + { + for (l = e->listeners; l; l = l->next) + l->listener(e->key, e->type, l->tag, l->data); + } + else + { + E(0, + "ecore_config_typed_set(\"%s\"): ecore_config_typed_val() failed: %d\n", + key, ret); + } + + return ret; +} + +/** + * @defgroup Ecore_Config_Set_Group Ecore Config Setters + * + * Functions that set the value of a property. + */ + +/** + * Sets the indicated property to the value indicated by @a val. + * @param key The property key. + * @param val String representation of value to set. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_set(const char *key, char *val) +{ + int type; + int tmpi; + float tmpf; + + type = ecore_config_type_guess(key, val); + if (type == PT_INT || type == PT_BLN) + { + tmpi = atoi(val); + return ecore_config_typed_set(key, (void *)&tmpi, type); + } + else if (type == PT_FLT) + { + tmpf = atof(val); + return ecore_config_typed_set(key, (void *)&tmpf, type); + } + else + return ecore_config_typed_set(key, (void *)val, type); +} + +/** + * Sets the indicated property to the value given in the string. + * @param key The property key. + * @param val String representation of the value. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_as_string_set(const char *key, char *val) +{ + return ecore_config_set(key, val); +} + +/** + * Sets the indicated property to the given boolean. + * @param key The property key. + * @param val Boolean integer to set the property to. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_boolean_set(const char *key, int val) +{ + val = val ? 1 : 0; + return ecore_config_typed_set(key, (void *)&val, PT_BLN); +} + +/** + * Sets the indicated property to the given integer. + * @param key The property key. + * @param val Integer to set the property to. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_int_set(const char *key, int val) +{ + return ecore_config_typed_set(key, (void *)&val, PT_INT); +} + +/** + * Sets the indicated property to the given string. + * @param key The property key. + * @param val String to set the property to. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_string_set(const char *key, char *val) +{ + return ecore_config_typed_set(key, (void *)val, PT_STR); +} + +/** + * Sets the indicated property to the given float value. + * @param key The property key. + * @param val Float to set the property to. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_float_set(const char *key, float val) +{ + return ecore_config_typed_set(key, (void *)&val, PT_FLT); +} + +char * +ecore_config_rgb_to_argb(char *rgb) +{ + char *argb; + + argb = malloc(strlen(rgb) + 2); + strncpy(argb, "#ff", 3); + strncat(argb, rgb+1, strlen(rgb - 1)); + return argb; +} + +/** + * Sets the indicated property to a color value. + * @param key The property key + * @param val Color value in RGB format. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + * @deprecated + */ +int +ecore_config_rgb_set(const char *key, char *val) +{ + char *argb; + int ret; + + argb = ecore_config_rgb_to_argb(val); + ret = ecore_config_argb_set(key, argb); + free(argb); + return ret; +} + +/** + * Sets the indicated property to a color value. + * @param key The property key + * @param val Color value in ARGB format. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_argb_set(const char *key, char *val) +{ + return ecore_config_typed_set(key, (void *)val, PT_RGB); +} + +/** + * Sets the indicated property to a theme name. + * @param key The property key. + * @param val String giving the name of the theme. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_theme_set(const char *key, char *val) +{ + return ecore_config_typed_set(key, (void *)val, PT_THM); +} + +/** + * Sets the theme preview group of an indicated property. + * @param key The property key. + * @param group The group name. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Set_Group + */ +int +ecore_config_theme_preview_group_set(const char *key, char *group) +{ + int ret; + Ecore_Config_Prop *e; + + ret = ECORE_CONFIG_ERR_SUCC; + if (!(e = ecore_config_get(key))) + { /* prop doesn't exist yet */ + if ((ret = ecore_config_typed_add(key, "", PT_THM)) != ECORE_CONFIG_ERR_SUCC) /* try to add it */ + return ret; /* ...failed */ + if (!(e = ecore_config_get(key))) /* get handle */ + return ECORE_CONFIG_ERR_FAIL; + } + if (e->data) + free(e->data); + e->data = strdup(group); + + return ret; +} + +int +ecore_config_typed_default(const char *key, void *val, int type) +{ + int ret; + Ecore_Config_Prop *e; + + ret = ECORE_CONFIG_ERR_SUCC; + + if (!(e = ecore_config_get(key))) + { /* prop doesn't exist yet */ + if ((ret = ecore_config_typed_add(key, val, type)) != ECORE_CONFIG_ERR_SUCC) /* try to add it */ + return ret; /* ...failed */ + if (!(e = ecore_config_get(key))) /* get handle */ + return ECORE_CONFIG_ERR_FAIL; + e->flags = e->flags & ~PF_MODIFIED; + } + else if (!(e->flags & PF_MODIFIED) && !(e->flags & PF_SYSTEM)) + { + ecore_config_typed_set(key, val, type); + if (!(e = ecore_config_get(key))) /* get handle */ + return ECORE_CONFIG_ERR_FAIL; + e->flags = e->flags & ~PF_MODIFIED; + } + return ret; +} + +/** + * @defgroup Ecore_Config_Default_Group Ecore Config Defaults + * + * Functions that are used to set the default values of properties. + */ + +/** + * Sets the indicated property if it has not already been set or loaded. + * @param key The property key. + * @param val Default value of the key. + * @param lo Lowest valid value for the key. + * @param hi Highest valid value for the key. + * @param step Used by integer and float values. + * @return @c ECORE_CONFIG_ERR_SUCC if there are no errors. + * @note The @p lo, @p hi and @p step parameters are only used when storing + * integer and float properties. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_default(const char *key, char *val, float lo, float hi, float step) +{ + int ret, type; + Ecore_Config_Prop *e; + + type = ecore_config_type_guess(key, val); + ret = ecore_config_typed_default(key, val, type); + e = ecore_config_get(key); + if (e) + { + if (type == PT_INT) + { + e->step = step; + e->flags |= PF_BOUNDS; + e->lo = lo; + e->hi = hi; + ecore_config_bound(e); + } + else if (type == PT_FLT) + { + e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION); + e->flags |= PF_BOUNDS; + e->lo = (int)(lo * ECORE_CONFIG_FLOAT_PRECISION); + e->hi = (int)(hi * ECORE_CONFIG_FLOAT_PRECISION); + ecore_config_bound(e); + } + } + + return ret; +} + +/** + * Sets the indicated property to the given boolean if the property has not yet + * been set. + * @param key The property key. + * @param val Boolean Integer to set the value to. + * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_boolean_default(const char *key, int val) +{ + val = val ? 1 : 0; + return ecore_config_typed_default(key, (void *)&val, PT_BLN); +} + +/** + * Sets the indicated property to the given integer if the property has not yet + * been set. + * @param key The property key. + * @param val Integer to set the value to. + * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_int_default(const char *key, int val) +{ + return ecore_config_typed_default(key, (void *)&val, PT_INT); +} + +/** + * Sets the indicated property to the given integer if the property has not yet + * been set. + * + * The bounds and step values are set regardless. + * + * @param key The property key. + * @param val Integer to set the property to. + * @param low Lowest valid integer value for the property. + * @param high Highest valid integer value for the property. + * @param step Increment value for the property. + * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_int_default_bound(const char *key, int val, int low, int high, + int step) +{ + Ecore_Config_Prop *e; + int ret; + + ret = ecore_config_typed_default(key, (void *)&val, PT_INT); + e = ecore_config_get(key); + if (e) + { + e->step = step; + e->flags |= PF_BOUNDS; + e->lo = low; + e->hi = high; + ecore_config_bound(e); + } + + return ret; +} + +/** + * Sets the indicated property to the given string if the property has not yet + * been set. + * @param key The property key. + * @param val String to set the property to. + * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_string_default(const char *key, const char *val) +{ + return ecore_config_typed_default(key, (void *)val, PT_STR); +} + +/** + * Sets the indicated property to the given float if the property has not yet + * been set. + * @param key The property key. + * @param val Float to set the property to. + * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_float_default(const char *key, float val) +{ + return ecore_config_typed_default(key, (void *)&val, PT_FLT); +} + +/** + * Sets the indicated property to the given float if the property has not yet + * been set. + * + * The bounds and step values are set regardless. + * + * @param key The property key. + * @param val Float to set the property to. + * @param low Lowest valid integer value for the property. + * @param high Highest valid float value for the property. + * @param step Increment value for the property. + * @return @c ECORE_CONFIG_ERR_SUCC if there were no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_float_default_bound(const char *key, float val, float low, + float high, float step) +{ + Ecore_Config_Prop *e; + int ret; + + ret = ecore_config_typed_default(key, (void *)&val, PT_FLT); + e = ecore_config_get(key); + if (e) + { + e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION); + e->flags |= PF_BOUNDS; + e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION); + e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION); + ecore_config_bound(e); + } + + return ret; +} + +/** + * Sets the indicated property to a color value if the property has not yet + * been set. + * @param key The property key. + * @param val Color value in RGB format. + * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. + * @ingroup Ecore_Config_Default_Group + * @deprecated + */ +int +ecore_config_rgb_default(const char *key, char *val) +{ + char *argb; + int ret; + + argb = ecore_config_rgb_to_argb(val); + ret = ecore_config_argb_default(key, argb); + free(argb); + return ret; +} + +/** + * Sets the indicated property to a color value if the property has not yet + * been set. + * @param key The property key. + * @param val Color value in ARGB format. + * @return @c ECORE_CONFIG_ERR_SUCC if there are no problems. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_argb_default(const char *key, char *val) +{ + return ecore_config_typed_default(key, (void *)val, PT_RGB); +} + +/** + * Sets the indicated property to a theme name if the property has not yet + * been set. + * @param key The property key. + * @param val String giving the name of the theme. + * @return @c ECORE_CONFIG_ERR_SUCC if the property is set successfully. + * @ingroup Ecore_Config_Default_Group + */ +int +ecore_config_theme_default(const char *key, char *val) +{ + return ecore_config_typed_default(key, (void *)val, PT_THM); +} + +/** + * @defgroup Ecore_Config_Listeners_Group Ecore Config Listeners + * + * Functions that set and unset property listener callbacks. + */ + +/** + * Adds a callback function to the list of functions called when a property + * changes. + * @param name Name of the callback. + * @param key The key of the property to listen to. + * @param listener Listener callback function. + * @param tag Tag to pass to @p listener when it is called. + * @param data Data to pass to @p listener when it is called. + * @return @c ECORE_CONFIG_ERR_SUCC if successful in setting up the callback. + * @ingroup Ecore_Config_Listeners_Group + */ +int +ecore_config_listen(const char *name, const char *key, + Ecore_Config_Listener listener, int tag, void *data) +{ + Ecore_Config_Prop *e; + Ecore_Config_Listener_List *l; + + if (!key) + return ECORE_CONFIG_ERR_NODATA; + + if (!(e = ecore_config_get(key))) + { + int ret = ecore_config_add(key, ""); + + if (ret != ECORE_CONFIG_ERR_SUCC) + { + E(0, "ecore_config_listen: ecore_config_add(\"%s\") failed: %d\n", + key, ret); + return ret; + } + if (!(e = ecore_config_get(key))) + { + E(0, "ecore_config_listen: list of properties corrupted!?\n"); + return ECORE_CONFIG_ERR_FAIL; + } + } + + for (l = e->listeners; l; l = l->next) + if (!strcmp(l->name, name) || (l->listener == listener)) + { + E(1, + "ecore_config_listen: %s is already listening for changes of %s...\n", + name, key); + return ECORE_CONFIG_ERR_IGNORED; + } + + if (!(l = malloc(sizeof(Ecore_Config_Listener_List)))) + return ECORE_CONFIG_ERR_OOM; + + E(1, "registering listener \"%s\" for \"%s\" (%d)...\n", name, key, e->type); + + memset(l, 0, sizeof(Ecore_Config_Listener_List)); + + l->listener = listener; + l->name = name; + l->data = data; + l->tag = tag; + l->next = e->listeners; + e->listeners = l; + + if (e->type != PT_NIL) /* call right on creation if prop exists and has val */ + listener(key, e->type, tag, data); + + return ECORE_CONFIG_ERR_SUCC; +} + +/** + * Removes a listener callback. + * @param name Name of the callback to remove. + * @param key The property key the callback is listening to. + * @param listener The callback function to remove. + * @return @c ECORE_CONFIG_ERR_SUCC if successful in removing the callback. + * If no callback matches the given parameters, then + * @c ECORE_CONFIG_ERR_NOTFOUND is returned. If @c NULL is passed + * for the key pointer, @c ECORE_CONFIG_ERR_NODATA is returned. + * @ingroup Ecore_Config_Listeners_Group + */ +int +ecore_config_deaf(const char *name, const char *key, + Ecore_Config_Listener listener) +{ + Ecore_Config_Prop *e; + Ecore_Config_Listener_List *l, *p; + int ret; + + ret = ECORE_CONFIG_ERR_NOTFOUND; + + if (!key) + return ECORE_CONFIG_ERR_NODATA; + + if (!(e = ecore_config_get(key))) + return ECORE_CONFIG_ERR_NOTFOUND; + + for (p = NULL, l = e->listeners; l; p = l) + { + Ecore_Config_Listener_List *nl; + + nl = l->next; + if ((name && !strcmp(l->name, name)) || (l->listener == listener)) + { + ret = ECORE_CONFIG_ERR_SUCC; + if (!p) + e->listeners = e->listeners->next; + else + p->next = l->next; + memset(l, 0, sizeof(Ecore_Config_Listener)); + free(l); + } + l = nl; + } + + return ret; +} + +/** + * Locates the first configuration bundle on the given server. + * @param srv The configuration server. + * @return Pointer to the first configuration bundle. + */ +Ecore_Config_Bundle * +ecore_config_bundle_1st_get(Ecore_Config_Server * srv) +{ /* anchor: global, but read-only */ + return srv->bundles; +} + +/** + * Locates the configuration bundle after the given one. + * @param ns The configuration bundle. + * @return The next configuration bundle. + */ +Ecore_Config_Bundle * +ecore_config_bundle_next_get(Ecore_Config_Bundle * ns) +{ + return ns ? ns->next : NULL; +} + +/** + * Locates a configuration bundle on a configuration server based on its serial + * number. + * @param srv The configuration server. + * @param serial Serial number. + * @return The configuration bundle with the given serial number. + */ +Ecore_Config_Bundle * +ecore_config_bundle_by_serial_get(Ecore_Config_Server * srv, long serial) +{ + Ecore_Config_Bundle *eb; + + eb = srv->bundles; + + if (serial < 0) + return NULL; + else if (serial == 0) + { + Ecore_Config_Bundle *r = eb; + + return r; + } + + while (eb) + { + if (eb->serial == serial) + return eb; + eb = eb->next; + } + return NULL; +} + +/** + * Gets the Ecore_Config_Bundle with the given identifier from the given + * server. + * @param srv The configuration server. + * @param label The bundle's identifier string. + * @return The bundle with the given identifier string, or @c NULL if it + * could not be found. + */ +Ecore_Config_Bundle * +ecore_config_bundle_by_label_get(Ecore_Config_Server * srv, const char *label) +{ + Ecore_Config_Bundle *ns; + + ns = srv->bundles; + + while (ns) + { + if (ns->identifier && !strcmp(ns->identifier, label)) + return ns; + ns = ns->next; + } + return NULL; +} + +/** + * Retrieves the bundle's serial number. + * @param ns The configuration bundle. + * @return The bundle's identifier string, or -1 if ns is @c NULL. + */ +long +ecore_config_bundle_serial_get(Ecore_Config_Bundle * ns) +{ + return ns ? ns->serial : -1; +} + +/** + * Retrieves the bundle's identifier. + * @param ns The configuration bundle. + * @return The bundle's identifer string. + */ +char * +ecore_config_bundle_label_get(Ecore_Config_Bundle * ns) +{ + return ns ? ns->identifier : NULL; +} + +/** + * Creates a new Ecore_Config_Bundle. + * @param srv Config server. + * @param identifier Identifier string for the new bundle. + * @return A pointer to a new Ecore_Config_Bundle. @c NULL is returned if the + * structure couldn't be allocated. + */ +Ecore_Config_Bundle * +ecore_config_bundle_new(Ecore_Config_Server * srv, const char *identifier) +{ + Ecore_Config_Bundle *t; + static long ss; + + ss = 0; /* bundle unique serial */ + + if ((t = malloc(sizeof(Ecore_Config_Bundle)))) + { + memset(t, 0, sizeof(Ecore_Config_Bundle)); + + t->identifier = (char *)identifier; + t->serial = ++ss; + t->owner = srv->name; + t->next = srv->bundles; + srv->bundles = t; + } + return t; +} + +static Ecore_Config_Server * +do_init(const char *name) +{ + return _ecore_config_ipc_init(name); +} + +static Ecore_Config_Server * +ecore_config_init_local(const char *name) +{ + char *p; + char *buf; + + if ((p = getenv("HOME"))) + { /* debug-only ### FIXME */ + if (!(buf = malloc(PATH_MAX * sizeof(char)))) + return NULL; + snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name); + unlink(buf); + + free(buf); + } + + return do_init(name); +} + +static Ecore_Config_Server * +ecore_config_init_global(const char *name) +{ + char *p; + int global; + char *buf; + global = 0; + + if ((p = getenv("HOME"))) + { /* debug-only ### FIXME */ + if (!(buf = malloc(PATH_MAX * sizeof(char)))) + return NULL; + snprintf(buf, PATH_MAX, "%s/.ecore/%s/.global", p, name); + global = creat(buf, S_IRWXU); + + if (global) + close(global); + + free(buf); + } + + return do_init(name); +} + +/** + * @defgroup Ecore_Config_App_Lib_Group Ecore Config App Library Functions + * + * Functions that are used to start up and shutdown the Enlightened + * Property Library when used directly by an application. + */ + +/** + * Initializes the Enlightened Property Library. + * + * Either this function or @ref ecore_config_system_init must be run + * before any other function in the Enlightened Property Library, even + * if you have run @ref ecore_init . The name given is used to + * determine the default configuration to load. + * + * @param name Application name + * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up. + * @c ECORE_CONFIG_ERR_FAIL otherwise. + * @ingroup Ecore_Config_App_Lib_Group + */ +int +ecore_config_init(const char *name) +{ + char *path; + Ecore_Config_Prop *list; + Ecore_Config_Bundle *temp; + _ecore_config_system_init_no_load(); + + __ecore_config_app_name = strdup(name); + __ecore_config_server_local = ecore_config_init_local(name); + if (!__ecore_config_server_local) + return ECORE_CONFIG_ERR_FAIL; + + temp = __ecore_config_bundle_local; + list = __ecore_config_bundle_local->data; + __ecore_config_bundle_local = + ecore_config_bundle_new(__ecore_config_server_local, "config"); + __ecore_config_bundle_local->data = list; + free(temp); + + path = ecore_config_theme_default_path_get(); + ecore_config_string_default("/e/themes/search_path", path); + if (path) + free(path); + + list = ecore_config_get("/e/themes/search_path"); + if (list) + { + list->flags |= PF_SYSTEM; + list->flags &= ~PF_MODIFIED; + } + + return _ecore_config_system_load(); +} + +/** + * Frees memory and shuts down the library for an application. + * @return @c ECORE_CONFIG_ERR_IGNORED . + * @ingroup Ecore_Config_App_Lib_Group + */ +int +ecore_config_shutdown(void) +{ + return ecore_config_system_shutdown(); +} + +/** + * @defgroup Ecore_Config_Lib_Lib_Group Ecore Config Library Functions + * + * Functions that are used to start up and shutdown the Enlightened + * Property Library when used directly by an application. + */ + +/** + * Initializes the Enlightened Property Library. + * + * This function is meant to be run from other programming libraries. + * It should not be called from applications. + * + * This function (or @ref ecore_config_init ) + * must be run before any other function in the + * Enlightened Property Library, even if you have run @ref ecore_init . + * + * @return @c ECORE_CONFIG_ERR_SUCC if the library is successfully set up. + * @c ECORE_CONFIG_ERR_FAIL otherwise. + * @ingroup Ecore_Config_Lib_Lib_Group + */ +int +ecore_config_system_init(void) +{ + _ecore_config_system_init_no_load(); + return _ecore_config_system_load(); +} + +static int +_ecore_config_system_init_no_load(void) +{ + char *p; + + __ecore_config_system_init++; + if (__ecore_config_system_init > 1) + return ECORE_CONFIG_ERR_IGNORED; + + DEBUG = -1; + if ((p = getenv("ECORE_CONFIG_DEBUG")) && strlen(p) > 0) + { + DEBUG = atoi(p); + } + + __ecore_config_server_global = + ecore_config_init_global(ECORE_CONFIG_GLOBAL_ID); + if (!__ecore_config_server_global) + return ECORE_CONFIG_ERR_FAIL; + + __ecore_config_bundle_local = + ecore_config_bundle_new(__ecore_config_server_global, "system"); + + /* set up a simple default path */ + ecore_config_string_default("/e/themes/search_path", PACKAGE_DATA_DIR "../ewl/themes"); + + return ECORE_CONFIG_ERR_SUCC; +} + + +static int +_ecore_config_system_load(void) +{ + char *buf, *p; + Ecore_Config_Prop *sys; + + if (__ecore_config_system_init != 1) + return ECORE_CONFIG_ERR_FAIL; + + if ((p = getenv("HOME"))) + { /* debug-only ### FIXME */ + if ((buf = malloc(PATH_MAX * sizeof(char)))) + { + snprintf(buf, PATH_MAX, "%s/.e/config.eet", p); + if (ecore_config_file_load(buf) != 0) { + /* even if this file (system.eet) dosen't exist we can + * continue without it as it isn't striclty necessary. + */ + ecore_config_file_load(PACKAGE_DATA_DIR "/system.eet"); + } + sys = __ecore_config_bundle_local->data; + while (sys) + { + /* unmark it modified - modification will mean it has been overridden */ + sys->flags &= ~PF_MODIFIED; + /* mark as system so that examine can hide them */ + sys->flags |= PF_SYSTEM; + sys = sys->next; + } + } + free(buf); + } + + return ECORE_CONFIG_ERR_SUCC; +} + + +/** + * Frees memory and shuts down the library for other programming libraries. + * @return @c ECORE_CONFIG_ERR_IGNORED + * @ingroup Ecore_Config_Lib_Lib_Group + */ +int +ecore_config_system_shutdown(void) +{ + int ret; + + __ecore_config_system_init--; + if (__ecore_config_system_init > 0) + return ECORE_CONFIG_ERR_IGNORED; + + ret = _ecore_config_ipc_exit(); + if (__ecore_config_app_name) + free(__ecore_config_app_name); + free(__ecore_config_bundle_local); + free(__ecore_config_server_local); + free(__ecore_config_server_global); + return ret; +} + diff --git a/ecore/src/lib/ecore_config/ecore_config_db.c b/ecore/src/lib/ecore_config/ecore_config_db.c new file mode 100644 index 0000000..59e673b --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_db.c @@ -0,0 +1,286 @@ +#include "Ecore_Config.h" +#include "ecore_config_private.h" +#include <Eet.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <limits.h> + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <locale.h> + +struct _Ecore_Config_DB_File +{ + Eet_File *ef; +}; + +Ecore_Config_DB_File * +_ecore_config_db_open_read(const char *file) +{ + Eet_File *ef; + Ecore_Config_DB_File *db; + + eet_init(); + db = malloc(sizeof(Ecore_Config_DB_File)); + if (!db) return NULL; + ef = eet_open((char*)file, EET_FILE_MODE_READ); + if (!ef) + { + free(db); + return NULL; + } + db->ef = ef; + return db; +} + +Ecore_Config_DB_File * +_ecore_config_db_open_write(const char *file) +{ + Eet_File *ef; + Ecore_Config_DB_File *db; + + eet_init(); + db = malloc(sizeof(Ecore_Config_DB_File)); + if (!db) return NULL; + ef = eet_open((char*)file, EET_FILE_MODE_WRITE); + if (!ef) + { + free(db); + return NULL; + } + db->ef = ef; + return db; +} + +void +_ecore_config_db_close(Ecore_Config_DB_File *db) +{ + eet_close(db->ef); + free(db); + eet_shutdown(); +} + +char ** +_ecore_config_db_keys_get(Ecore_Config_DB_File *db, int *num_ret) +{ + char **keys; + int key_count; + int i; + + keys = eet_list(db->ef, (char*)"*", &key_count); + if (!keys) + { + *num_ret = 0; + return NULL; + } + /* make keys freeable - this is safe to do */ + for (i = 0; i < key_count; i++) keys[i] = strdup(keys[i]); + *num_ret = key_count; + return keys; +} + +Ecore_Config_Type +_ecore_config_db_key_type_get(Ecore_Config_DB_File *db, const char *key) +{ + char *data; + int size; + + data = eet_read(db->ef, (char*)key, &size); + if (data) + { + if (size <= 2) + { + free(data); + return PT_NIL; + } + if (data[size - 1] != 0) + { + free(data); + return PT_NIL; + } + return (Ecore_Config_Type) data[0]; + } + return PT_NIL; +} + +int +_ecore_config_db_read(Ecore_Config_DB_File *db, const char *key) +{ + char *data, *value; + int size; + Ecore_Config_Prop *prop; + Ecore_Config_Type type; + + data = eet_read(db->ef, (char*)key, &size); + if (data) + { + int l; + char *prev_locale; + + if (size <= 2) + { + free(data); + return 0; + } + if (data[size - 1] != 0) + { + free(data); + return 0; + } + /* "type" NIL 1242 NIL */ + l = strlen(data); + if (l >= (size - 1)) + { + free(data); + return 0; + } + + type = data[0]; + value = data + l + 1; + prop = ecore_config_get(key); + + switch (type) + { + case PT_INT: + case PT_BLN: + { + int tmp; + prev_locale = setlocale(LC_NUMERIC, "C"); + tmp = atoi(value); + if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + + ecore_config_typed_set(key, (void *)&tmp, type); + break; + } + case PT_FLT: + { + float tmp; + prev_locale = setlocale(LC_NUMERIC, "C"); + tmp = atof(value); + if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + + ecore_config_typed_set(key, (void *)&tmp, type); + break; + } + case PT_STR: + case PT_RGB: + case PT_THM: + ecore_config_typed_set(key, (void *)value, type); + break; + default: + E(0, "Type %d not handled\n", type); + } + free(data); + return 1; + } + return 0; +} + +/* +void * +_ecore_config_db_key_data_get(Ecore_Config_DB_File *db, const char *key, int *size_ret) +{ + char *data; + int size; + + data = eet_read(db->ef, (char*)key, &size); + if (data) + { + int l; + char *dat; + + if (size <= 2) + { + free(data); + return NULL; + } + if (data[size - 1] != 0) + { + free(data); + return NULL; + } + * "type" NIL data_goes_here NIL * + l = strlen(data); + if (l >= (size - 1)) + { + free(data); + return NULL; + } + dat = malloc(size - (l + 2)); + memcpy(dat, data + l + 1, size - (l + 2)); + free(data); + *size_ret = size - (l + 2); + return dat; + } + return NULL; +}*/ + +void +_ecore_config_db_write(Ecore_Config_DB_File *db, const char *key) +{ + char buf[256]; + int num; + char *prev_locale; + // Ecore_Config_Prop *prop; + Ecore_Config_Type type; + + + type = ecore_config_get(key)->type; + prev_locale = setlocale(LC_NUMERIC, "C"); + + switch (type) + { + case PT_INT: + num = snprintf(buf, sizeof(buf), "%c %i ", (char) type, + (int) ecore_config_int_get(key)); + break; + case PT_BLN: + num = snprintf(buf, sizeof(buf), "%c %i ", (char) type, + (int) ecore_config_int_get(key)); + break; + case PT_FLT: + num = snprintf(buf, sizeof(buf), "%c %16.16f ", (char) type, + ecore_config_float_get(key)); + break; + case PT_STR: + num = snprintf(buf, sizeof(buf), "%c %s ", (char) type, + ecore_config_string_get(key)); + break; + case PT_THM: + num = snprintf(buf, sizeof(buf), "%c %s ", (char) type, + ecore_config_theme_get(key)); + break; + case PT_RGB: + num = snprintf(buf, sizeof(buf), "%c %s ", (char) type, + ecore_config_argbstr_get(key)); + break; + default: + E(0, "Type %d not handled\n", type); + } + + if (prev_locale) setlocale(LC_NUMERIC, prev_locale); + buf[1] = 0; + buf[num - 1] = 0; + eet_write(db->ef, (char*)key, buf, num, 1); +} +/* +void +_ecore_config_db_key_data_set(Ecore_Config_DB_File *db, const char *key, void *data, int data_size) +{ + char *buf; + int num; + + num = 1 + 1 + data_size + 1; + buf = malloc(num); + if (!buf) return; + buf[0] = (char) PT_BIN; + buf[1] = 0; + memcpy(buf + 2, data, data_size); + buf[num - 1] = 0; + eet_write(db->ef, (char*)key, buf, num, 1); + free(buf); +}*/ diff --git a/ecore/src/lib/ecore_config/ecore_config_extra.c b/ecore/src/lib/ecore_config/ecore_config_extra.c new file mode 100644 index 0000000..bdc8b8c --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_extra.c @@ -0,0 +1,828 @@ +#include "Ecore_Config.h" +#include "Ecore.h" + +#include "config.h" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> + +typedef struct __Ecore_Config_Arg_Callback _Ecore_Config_Arg_Callback; +struct __Ecore_Config_Arg_Callback +{ + char short_opt; + char *long_opt; + char *description; + void *data; + void (*func)(char *val, void *data); + Ecore_Config_Type type; + _Ecore_Config_Arg_Callback *next; +}; + +char *__ecore_config_app_description; +_Ecore_Config_Arg_Callback *_ecore_config_arg_callbacks; + +/* shorthand prop setup code to make client apps a little smaller ;) */ + +/** + * Creates a new property, if it does not already exist, and sets its + * attributes to those given. + * + * The type of the property is guessed from the key and the value + * given. + * + * @param key The property key. + * @param val Pointer to default value of key. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_create(const char *key, void *val, char short_opt, char *long_opt, + char *desc) +{ + int type = ecore_config_type_guess(key, val); + + return ecore_config_typed_create(key, val, type, short_opt, long_opt, desc); +} + +/** + * Creates a new property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Pointer to default value of key. + * @param type Type of the property. + * @param short_opt Short option used to set the property from + * command line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_typed_create(const char *key, void *val, int type, char short_opt, + char *long_opt, char *desc) +{ + int ret; + + if ((ret = + ecore_config_typed_default(key, val, type)) != ECORE_CONFIG_ERR_SUCC) + return ret; + if ((ret = + ecore_config_short_opt_set(key, short_opt)) != ECORE_CONFIG_ERR_SUCC) + return ret; + if ((ret = + ecore_config_long_opt_set(key, long_opt)) != ECORE_CONFIG_ERR_SUCC) + return ret; + ret = ecore_config_describe(key, desc); + return ret; +} + +/** + * Creates a new boolean property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default boolean value of key. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_boolean_create(const char *key, int val, char short_opt, + char *long_opt, char *desc) +{ + return + ecore_config_typed_create(key, (void *)&val, PT_BLN, short_opt, long_opt, + desc); +} + +/** + * Creates a new integer property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default integer value of key. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_int_create(const char *key, int val, char short_opt, + char *long_opt, char *desc) +{ + return + ecore_config_typed_create(key, (void *)&val, PT_INT, short_opt, long_opt, + desc); +} + +/** + * Creates a new integer property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default integer value of key. + * @param low Lowest valid integer value for the property. + * @param high Highest valid integer value for the property. + * @param step Increment value for the property. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_int_create_bound(const char *key, int val, int low, int high, + int step, char short_opt, char *long_opt, + char *desc) +{ + Ecore_Config_Prop *e; + int ret; + + ret = + ecore_config_typed_create(key, (void *)&val, PT_INT, short_opt, long_opt, + desc); + if (ret != ECORE_CONFIG_ERR_SUCC) + return ret; + e = ecore_config_get(key); + if (e) + { + e->step = step; + e->flags |= PF_BOUNDS; + e->lo = low; + e->hi = high; + ecore_config_bound(e); + } + return ret; +} + +/** + * Creates a new string property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default value of key. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_string_create(const char *key, char *val, char short_opt, + char *long_opt, char *desc) +{ + return + ecore_config_typed_create(key, (void *)val, PT_STR, short_opt, long_opt, + desc); +} + +/** + * Creates a new float property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default float value of key. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_float_create(const char *key, float val, char short_opt, + char *long_opt, char *desc) +{ + return + ecore_config_typed_create(key, (void *)&val, PT_FLT, short_opt, long_opt, + desc); +} + +/** + * Creates a new float property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default float value of key. + * @param low Lowest valid float value for the property. + * @param high Highest valid float value for the property. + * @param step Increment value for the property. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_float_create_bound(const char *key, float val, float low, + float high, float step, char short_opt, + char *long_opt, char *desc) +{ + Ecore_Config_Prop *e; + int ret; + + ret = + ecore_config_typed_create(key, (void *)&val, PT_FLT, short_opt, long_opt, + desc); + e = ecore_config_get(key); + if (e) + { + e->step = (int)(step * ECORE_CONFIG_FLOAT_PRECISION); + e->flags |= PF_BOUNDS; + e->lo = (int)(low * ECORE_CONFIG_FLOAT_PRECISION); + e->hi = (int)(high * ECORE_CONFIG_FLOAT_PRECISION); + ecore_config_bound(e); + } + return ret; +} + +/** + * Creates a new color property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default color value of key, as a hexadecimal string. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + * @deprecated + */ +int +ecore_config_rgb_create(const char *key, char *val, char short_opt, + char *long_opt, char *desc) +{ + char *argb; + int ret; + + argb = ecore_config_rgb_to_argb(val); + ret = ecore_config_argb_create(key, argb, short_opt, long_opt, desc); + free(argb); + return ret; +} + +/** + * Creates a new color property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default color value of key, as a hexadecimal string. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_argb_create(const char *key, char *val, char short_opt, + char *long_opt, char *desc) +{ + return + ecore_config_typed_create(key, (void *)val, PT_RGB, short_opt, long_opt, + desc); +} + +/** + * Creates a new theme property, if it does not already exist, and sets its + * attributes to those given. + * @param key The property key. + * @param val Default theme name for the property. + * @param short_opt Short option used to set the property from command + * line. + * @param long_opt Long option used to set the property from command line. + * @param desc String description of property. + * @return @c ECORE_CONFIG_ERR_SUCC on success. + * @ingroup Ecore_Config_Create_Group + */ +int +ecore_config_theme_create(const char *key, char *val, char short_opt, + char *long_opt, char *desc) +{ + return + ecore_config_typed_create(key, (void *)val, PT_THM, short_opt, long_opt, + desc); +} + +/* this should only be built if evas is present */ + +/** + * Calls evas_font_path_append on @p evas for each of the font names stored + * in the property "/e/font/path". + * @param evas Evas object to append the font names to. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA + * is returned if the property has not been set. + */ +int +ecore_config_evas_font_path_apply(Evas * evas) +{ + char *font_path, *font_path_tmp, *ptr, *end; + + font_path = ecore_config_string_get("/e/font/path"); + + if (!font_path) + return ECORE_CONFIG_ERR_NODATA; + ptr = font_path; + end = font_path + strlen(font_path); + font_path_tmp = font_path; + while (ptr && ptr < end) + { + while (*ptr != '|' && ptr < end) + ptr++; + if (ptr < end) + *ptr = '\0'; + + evas_font_path_append(evas, font_path_tmp); + ptr++; + font_path_tmp = ptr; + } + + free(font_path); + + return ECORE_CONFIG_ERR_SUCC; +} + +/** + * Retrieves the default theme search path. + * + * @return The default theme search path. + */ +char * +ecore_config_theme_default_path_get(void) +{ + char *path, *home; + int len; + + home = getenv("HOME"); + len = strlen(PACKAGE_DATA_DIR "/../") + strlen(__ecore_config_app_name) + + strlen("/themes/") + 1; + if (home) + len += strlen(home) + strlen("/.e/apps/") + + strlen(__ecore_config_app_name) + + strlen("/themes/|"); /* no \0, as that is above */ + + if (!(path = malloc(len))) + return NULL; + + *path = '\0'; + if (home) + { + strcat(path, home); + strcat(path, "/.e/apps/"); + strcat(path, __ecore_config_app_name); + strcat(path, "/themes/|"); + } + strcat(path, PACKAGE_DATA_DIR "/../"); + strcat(path, __ecore_config_app_name); + strcat(path, "/themes/"); + + return path; +} + +/** + * Retrieves the search path used to find themes. + * + * The search path is stored in the property "/e/themes/search_path". If + * the property has not been set, the default path used is + * "/usr/local/share/<app_name>/themes|~/.e/apps/<app_name>/themes". + * See @ref ecore_config_theme_default_path_get for more information about + * the default path. + * + * @return The search path. @c NULL is returned if there is no memory left. + */ +char * +ecore_config_theme_search_path_get(void) +{ + char *search_path; + search_path = ecore_config_string_get("/e/themes/search_path"); + + /* this should no longer be the case, as it is defaulted in init */ + if (!search_path) + { + search_path = ecore_config_theme_default_path_get(); + if (search_path) + { + ecore_config_string_default("/e/themes/search_path", search_path); + free(search_path); + } + } + return search_path; +} + +/** + * Adds the given path to the search path used to find themes. + * + * If the search path is successfully, the new search path will be saved + * into the property "/e/themes/search_path". Therefore, this function + * should be called @b after @ref ecore_config_load to allow a user to + * override the default search path. + * + * @param path The given + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_FAIL + * will be returned if @p path already exists in the search path. + * @c ECORE_CONFIG_ERR_FAIL is returned if @p path is @c NULL. + */ +int +ecore_config_theme_search_path_append(char *path) +{ + char *search_path, *loc, *new_search_path; + int len, search_len; + Ecore_Config_Prop *prop; + + if (!path) + return ECORE_CONFIG_ERR_NODATA; + search_path = ecore_config_theme_search_path_get(); + + loc = strstr(search_path, path); + len = strlen(path); + search_len = strlen(search_path); + + if (loc == NULL || (loc != search_path && *(loc - 1) != '|') || + (loc != (search_path + search_len - len) && *(loc + len - 1) != '|')) + { + new_search_path = malloc(search_len + len + 2); /* 2 = \0 + | */ + strcpy(new_search_path, search_path); + strncat(new_search_path, "|", 1); + strncat(new_search_path, path, len); + + ecore_config_string_set("/e/themes/search_path", new_search_path); + prop = ecore_config_get("/e/themes/search_path"); + if (prop) + prop->flags &= ~PF_MODIFIED; + + free(new_search_path); + + return ECORE_CONFIG_ERR_SUCC; + } + return ECORE_CONFIG_ERR_FAIL; +} + +/** + * Retrieve a theme file's full path. + * + * The search path for theme files is given by @ref + * ecore_config_theme_search_path_get . + * + * @param name The name of the theme. + * @return A full path to the theme on success. @c NULL will be returned + * if @p name is @c NULL or no theme matching the given name could + * be found. + */ +char * +ecore_config_theme_with_path_from_name_get(char *name) +{ + char *search_path, *search_path_tmp, *ptr, *end, *file; + struct stat st; + + if (!name) + return NULL; /* no theme specified (nor a default) */ + + search_path = ecore_config_theme_search_path_get(); + ptr = search_path; + end = search_path + strlen(search_path); + search_path_tmp = search_path; + while (ptr && ptr < end) + { + while (*ptr != '|' && ptr < end) + ptr++; + if (ptr < end) + *ptr = '\0'; + + file = malloc(strlen(search_path_tmp) + strlen(name) + 6); + /* 6 = / + .edj + \0 */ + + snprintf(file, strlen(search_path_tmp) + strlen(name) + 6, + "%s/%s.edj", search_path_tmp, name); + + if (stat(file, &st) == 0) + { + free(search_path); + return file; + } + free(file); + ptr++; + search_path_tmp = ptr; + } + + free(search_path); + + return NULL; /* we could not find the theme with that name in search path */ +} + +/** + * Retrieves the full path to the theme file of the theme stored in the + * given property. + * + * The search path for themes is given by @ref + * ecore_config_theme_search_path_get . + * + * @param key The given property. + * @return A full path to the theme on success, or @c NULL on failure. + * This function will fail if no key is specified or not theme + * matching that given by the property @p key could be found. + */ +char * +ecore_config_theme_with_path_get(const char *key) +{ + return + ecore_config_theme_with_path_from_name_get(ecore_config_theme_get(key)); +} + +static const char *_ecore_config_short_types[] = + { " ", "<int> ", "<flt> ", "<str> ", "<rgb> ", "<str> ", "<bool>" }; + +/** + * Prints the property list of the local configuration bundle to output. + */ +void +ecore_config_args_display(void) +{ + Ecore_Config_Prop *props; + _Ecore_Config_Arg_Callback *callbacks; + + if (__ecore_config_app_description) + printf("%s\n\n", __ecore_config_app_description); + printf("Supported Options:\n"); + printf(" -h, --help\t Print this text\n"); + if (!__ecore_config_bundle_local) + return; + props = __ecore_config_bundle_local->data; + while (props) + { + /* if it is a system prop, or cannot be set on command line hide it */ + if (props->flags & PF_SYSTEM || (!props->short_opt && !props->long_opt)) + { + props = props->next; + continue; + } + printf(" %c%c%c --%s\t%s %s\n", props->short_opt ? '-' : ' ', + props->short_opt ? props->short_opt : ' ', + props->short_opt ? ',' : ' ', + props->long_opt ? props->long_opt : props->key, + _ecore_config_short_types[props->type], + props->description ? props->description : + "(no description available)"); + + props = props->next; + } + callbacks = _ecore_config_arg_callbacks; + while (callbacks) + { + printf(" %c%c%c --%s\t%s %s\n", callbacks->short_opt ? '-' : ' ', + callbacks->short_opt ? callbacks->short_opt : ' ', + callbacks->short_opt ? ',' : ' ', + callbacks->long_opt ? callbacks->long_opt : "", + _ecore_config_short_types[callbacks->type], + callbacks->description ? callbacks->description : + "(no description available)"); + + callbacks = callbacks->next; + } +} + +static int +ecore_config_parse_set(Ecore_Config_Prop * prop, char *arg, char *opt, + char opt2) +{ + if (!arg) + { + if (opt) + printf("Missing expected argument for option --%s\n", opt); + else + printf("Missing expected argument for option -%c\n", opt2); + return ECORE_CONFIG_PARSE_EXIT; + } + else + { + ecore_config_set(prop->key, arg); + prop->flags |= PF_CMDLN; + } + return ECORE_CONFIG_PARSE_CONTINUE; +} + +static void +ecore_config_args_callback_add(char short_opt, char *long_opt, char *desc, + void (*func)(char *val, void *data), + void *data, Ecore_Config_Type type) { + _Ecore_Config_Arg_Callback *new_cb; + + new_cb = malloc(sizeof(_Ecore_Config_Arg_Callback)); + new_cb->short_opt = short_opt; + if (long_opt) + new_cb->long_opt = strdup(long_opt); + if (desc) + new_cb->description = strdup(desc); + new_cb->data = data; + new_cb->func = func; + new_cb->type = type; + + new_cb->next = _ecore_config_arg_callbacks; + _ecore_config_arg_callbacks = new_cb; +} + +void +ecore_config_args_callback_str_add(char short_opt, char *long_opt, char *desc, + void (*func)(char *val, void *data), + void *data) { + ecore_config_args_callback_add(short_opt, long_opt, desc, func, data, PT_STR); +} + +void +ecore_config_args_callback_noarg_add(char short_opt, char *long_opt, char *desc, + void (*func)(char *val, void *data), + void *data) { + ecore_config_args_callback_add(short_opt, long_opt, desc, func, data, PT_NIL); +} + +/** + * Parse the arguments set by @ref ecore_app_args_set and set properties + * accordingly. + * + * @return @c ECORE_CONFIG_PARSE_CONTINUE if successful. + * @c ECORE_CONFIG_PARSE_EXIT is returned if an unrecognised option + * is found. @c ECORE_CONFIG_PARSE_HELP is returned if help was + * displayed. + */ +int +ecore_config_args_parse(void) +{ + int argc; + char **argv; + int nextarg, next_short_opt, found, ret; + char *arg; + char *long_opt, short_opt; + Ecore_Config_Prop *prop; + _Ecore_Config_Arg_Callback *callback; + + ecore_app_args_get(&argc, &argv); + nextarg = 1; + while (nextarg < argc) + { + arg = argv[nextarg]; + + if (*arg != '-') + { + printf("Unexpected attribute \"%s\"\n", arg); + nextarg++; + continue; + } + + next_short_opt = 1; + short_opt = *(arg + next_short_opt); + + if (short_opt == '-') + { + long_opt = arg + 2; + + if (!strcmp(long_opt, "help")) + { + ecore_config_args_display(); + return ECORE_CONFIG_PARSE_HELP; + } + + found = 0; + prop = __ecore_config_bundle_local->data; + while (prop) + { + if ((prop->long_opt && !strcmp(long_opt, prop->long_opt)) + || !strcmp(long_opt, prop->key)) + { + found = 1; + if ((ret = + ecore_config_parse_set(prop, argv[++nextarg], + long_opt, + '\0')) != + ECORE_CONFIG_PARSE_CONTINUE) + return ret; + break; + } + prop = prop->next; + } + if (!found) + { + callback = _ecore_config_arg_callbacks; + while (callback) + { + if ((callback->long_opt && + !strcmp(long_opt, callback->long_opt))) + { + found = 1; + if (callback->type == PT_NIL) + { + callback->func(NULL, callback->data); + } + else + { + if (!argv[++nextarg]) + { + printf("Missing expected argument for option --%s\n", long_opt); + return ECORE_CONFIG_PARSE_EXIT; + } + callback->func(argv[nextarg], callback->data); + } + break; + } + callback = callback->next; + } + } + if (!found) + { + printf("Unrecognised option \"%s\"\n", long_opt); + printf("Try using -h or --help for more information.\n\n"); + return ECORE_CONFIG_PARSE_EXIT; + } + } + else + { + while (short_opt) + { + if (short_opt == 'h') + { + ecore_config_args_display(); + return ECORE_CONFIG_PARSE_HELP; + } + else + { + found = 0; + prop = __ecore_config_bundle_local->data; + while (prop) + { + if (short_opt == prop->short_opt) + { + found = 1; + if ((ret = + ecore_config_parse_set(prop, + argv[++nextarg], + NULL, + short_opt)) != + ECORE_CONFIG_PARSE_CONTINUE) + return ret; + break; + } + prop = prop->next; + } + + if (!found) + { + callback = _ecore_config_arg_callbacks; + while (callback) + { + if (short_opt == callback->short_opt) + { + found = 1; + if (callback->type == PT_NIL) + { + callback->func(NULL, callback->data); + } + else + { + if (!argv[++nextarg]) + { + printf("Missing expected argument for option -%c\n", short_opt); + return ECORE_CONFIG_PARSE_EXIT; + } + callback->func(argv[nextarg], callback->data); + } + break; + } + callback = callback->next; + } + } + if (!found) + { + printf("Unrecognised option '%c'\n", short_opt); + printf + ("Try using -h or --help for more information.\n\n"); + return ECORE_CONFIG_PARSE_EXIT; + } + } + short_opt = *(arg + ++next_short_opt); + } + } + nextarg++; + } + + return ECORE_CONFIG_PARSE_CONTINUE; +} + +/** + * Sets the description string used by @ref ecore_config_args_display . + * @param description Description of application. + */ +void +ecore_config_app_describe(char *description) +{ + if (__ecore_config_app_description) + free(__ecore_config_app_description); + __ecore_config_app_description = strdup(description); +} diff --git a/ecore/src/lib/ecore_config/ecore_config_ipc.h b/ecore/src/lib/ecore_config/ecore_config_ipc.h new file mode 100644 index 0000000..7b3dea1 --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_ipc.h @@ -0,0 +1,50 @@ +#include <Ecore_Ipc.h> +#include "Ecore_Config.h" + +typedef enum +{ + IPC_NONE, + IPC_PROP_LIST, + IPC_PROP_DESC, + IPC_PROP_GET, + IPC_PROP_SET, /* end of the codes shared by evidence and econf */ + + IPC_GLOBAL_PROP_LIST, + + IPC_BUNDLE_LIST, + IPC_BUNDLE_NEW, + IPC_BUNDLE_LABEL_GET, + IPC_BUNDLE_LABEL_SET, + IPC_BUNDLE_LABEL_FIND, + + IPC_LAST +} Ecore_Config_Ipc_Call; + +Ecore_Config_Server *_ecore_config_ipc_init(const char *pipe_name); +int _ecore_config_ipc_exit(void); + +Ecore_Config_Server *_ecore_config_server_convert(void *srv); + +char *_ecore_config_ipc_prop_list(Ecore_Config_Server * srv, + const long serial); +char *_ecore_config_ipc_prop_desc(Ecore_Config_Server * srv, + const long serial, + const char *key); +char *_ecore_config_ipc_prop_get(Ecore_Config_Server * srv, + const long serial, + const char *key); +int _ecore_config_ipc_prop_set(Ecore_Config_Server * srv, + const long serial, + const char *key, + const char *val); + +char *_ecore_config_ipc_bundle_list(Ecore_Config_Server * srv); +int _ecore_config_ipc_bundle_new(Ecore_Config_Server * srv, + const char *); +char *_ecore_config_ipc_bundle_label_get(Ecore_Config_Server * + srv, const long); +int _ecore_config_ipc_bundle_label_set(Ecore_Config_Server * + srv, const long, + const char *); +long _ecore_config_ipc_bundle_label_find(Ecore_Config_Server * + srv, const char *); diff --git a/ecore/src/lib/ecore_config/ecore_config_ipc_ecore.c b/ecore/src/lib/ecore_config/ecore_config_ipc_ecore.c new file mode 100644 index 0000000..289c690 --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_ipc_ecore.c @@ -0,0 +1,378 @@ +/* by Azundris, with thanks to Corey Donohoe <atmos@atmos.org> */ +#include "ecore_private.h" +#include "ecore_config_ipc.h" +#include "ecore_config_util.h" +#include "ecore_config_private.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <ctype.h> + +#include <Ecore.h> +#include <Ecore_Ipc.h> + +#include "Ecore_Config.h" +#include "config.h" + + +/*****************************************************************************/ + +static int +_ecore_config_ipc_ecore_string_get(char **m, char **r) +{ + char *q; + int l = 0; + + if (!m || !*m) + return ECORE_CONFIG_ERR_NODATA; + if (!r) + return ECORE_CONFIG_ERR_FAIL; + q = *m; + if (*q != 's') + return ECORE_CONFIG_ERR_TYPEMISMATCH; + q++; + l = (*(q++)) << 8; + l += *(q++); + *r = q; + q += l; + *m = q; + E(1, "IPC/eCore: got string-%d \"%s\"\n", l, *r); + return ECORE_CONFIG_ERR_SUCC; +} + +static char * +_ecore_config_ipc_global_prop_list(Ecore_Config_Server * srv __UNUSED__, long serial __UNUSED__) +{ + Ecore_Config_DB_File *db; + char **keys; + int key_count, x; + estring *s; + int f; + char buf[PATH_MAX], *p; + // char *data; UNUSED + Ecore_Config_Type type; + + db = NULL; + s = estring_new(8192); + f = 0; + if ((p = getenv("HOME"))) + { + snprintf(buf, sizeof(buf), "%s/.e/config.eet", p); + if (!(db = _ecore_config_db_open_read(buf))) + { + strcpy(buf, PACKAGE_DATA_DIR"/system.eet"); + if (!(db = _ecore_config_db_open_read(buf))) + return NULL; + } + } + if (!db) return NULL; + key_count = 0; + keys = _ecore_config_db_keys_get(db, &key_count); + if (keys) + { + for (x = 0; x < key_count; x++) + { + type = _ecore_config_db_key_type_get(db, keys[x]); + switch (type) + { + case PT_INT: + estring_appendf(s, "%s%s: integer", f ? "\n" : "", keys[x]); + break; + case PT_BLN: + estring_appendf(s, "%s%s: boolean", f ? "\n" : "", keys[x]); + break; + case PT_FLT: + estring_appendf(s, "%s%s: float", f ? "\n" : "", keys[x]); + break; + case PT_STR: + estring_appendf(s, "%s%s: string", f ? "\n" : "", keys[x]); + break; + case PT_RGB: + estring_appendf(s, "%s%s: colour", f ? "\n" : "", keys[x]); + break; + case PT_THM: + estring_appendf(s, "%s%s: theme", f ? "\n" : "", keys[x]); + break; + default: + estring_appendf(s, "%s%s: unknown", f ? "\n" : "", keys[x]); + continue; + } + f = 1; + } + } + _ecore_config_db_close(db); + if (keys) + { + for (x = 0; x < key_count; x++) + { + free(keys[x]); + } + free(keys); + } + + return estring_disown(s); +} + +/*****************************************************************************/ + +static int +_ecore_config_ipc_ecore_send(Ecore_Ipc_Event_Client_Data * e, int code, + char *reply) +{ + static int our_ref = 0; + int len = reply ? strlen(reply) + 1 : 0; + + our_ref++; + E(1, "IPC/eCore: replying [0,0] %d IRT %d => %d {\"%s\":%d}\n", our_ref, + e->ref, code, reply ? reply : "", len); + return ecore_ipc_client_send(e->client, 0, 0, our_ref, e->ref, code, reply, + len); +} + +/*****************************************************************************/ + +static int +_ecore_config_ipc_ecore_handle_request(Ecore_Ipc_Server * server, + Ecore_Ipc_Event_Client_Data * e) +{ + Ecore_Config_Server *srv; + long serial; + int ret; + char *r, *k, *v, *m; + + srv = _ecore_config_server_convert(server); + serial = e->minor; + ret = ECORE_CONFIG_ERR_FAIL; + r = NULL; + m = (char *)e->data; + E(1, "IPC/eCore: client sent: [%d,%d] #%d (%d) @ %p\n", e->major, e->minor, + e->ref, e->size, server); + + switch (e->major) + { + case IPC_PROP_LIST: + if (srv == __ecore_config_server_global) + r = _ecore_config_ipc_global_prop_list(srv, serial); + else + r = _ecore_config_ipc_prop_list(srv, serial); + break; + case IPC_PROP_DESC: + if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC) + r = _ecore_config_ipc_prop_desc(srv, serial, k); + break; + case IPC_PROP_GET: + if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC) + r = _ecore_config_ipc_prop_get(srv, serial, k); + break; + case IPC_PROP_SET: + if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC) + { + if (_ecore_config_ipc_ecore_string_get(&m, &v) == + ECORE_CONFIG_ERR_SUCC) + return _ecore_config_ipc_ecore_send(e, + _ecore_config_ipc_prop_set + (srv, serial, k, v), NULL); + } + break; + + case IPC_BUNDLE_LIST: + r = _ecore_config_ipc_bundle_list(srv); + break; + case IPC_BUNDLE_NEW: + if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC) + return _ecore_config_ipc_ecore_send(e, + k ? + _ecore_config_ipc_bundle_new(srv, + k) : + ECORE_CONFIG_ERR_FAIL, NULL); + break; + case IPC_BUNDLE_LABEL_SET: + if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC) + return _ecore_config_ipc_ecore_send(e, + k ? + _ecore_config_ipc_bundle_label_set + (srv, serial, + k) : ECORE_CONFIG_ERR_FAIL, + NULL); + break; + case IPC_BUNDLE_LABEL_FIND: + if (_ecore_config_ipc_ecore_string_get(&m, &k) == ECORE_CONFIG_ERR_SUCC) + return _ecore_config_ipc_ecore_send(e, + _ecore_config_ipc_bundle_label_find + (srv, k), NULL); + break; + case IPC_BUNDLE_LABEL_GET: + r = _ecore_config_ipc_bundle_label_get(srv, serial); + break; + } + + ret = + _ecore_config_ipc_ecore_send(e, + r ? ECORE_CONFIG_ERR_SUCC : + ECORE_CONFIG_ERR_FAIL, r); + if (r) + { + free(r); + return ret; + } + return ECORE_CONFIG_ERR_NOTFOUND; +} + +/*****************************************************************************/ + +static int +_ecore_config_ipc_client_add(void *data, int type __UNUSED__, void *event) +{ + Ecore_Ipc_Server **server; + Ecore_Ipc_Event_Client_Data *e; + + server = (Ecore_Ipc_Server **) data; + e = (Ecore_Ipc_Event_Client_Data *) event; + + if (*server != ecore_ipc_client_server_get(e->client)) + return 1; + + E(1, "IPC/eCore: Client connected. @ %p\n", server); + return 1; +} + +static int +_ecore_config_ipc_client_del(void *data, int type __UNUSED__, void *event) +{ + Ecore_Ipc_Server **server; + Ecore_Ipc_Event_Client_Data *e; + + server = (Ecore_Ipc_Server **) data; + e = (Ecore_Ipc_Event_Client_Data *) event; + + if (*server != ecore_ipc_client_server_get(e->client)) + return 1; + + E(1, "IPC/eCore: Client disconnected. @ %p\n", server); + return 1; +} + +static int +_ecore_config_ipc_client_sent(void *data, int type __UNUSED__, void *event) +{ + Ecore_Ipc_Server **server; + Ecore_Ipc_Event_Client_Data *e; + + server = (Ecore_Ipc_Server **) data; + e = (Ecore_Ipc_Event_Client_Data *) event; + + if (*server != ecore_ipc_client_server_get(e->client)) + return 1; + + _ecore_config_ipc_ecore_handle_request(*server, e); + return 1; +} + +/*****************************************************************************/ + +int +_ecore_config_ipc_ecore_init(const char *pipe_name, void **data) +{ + Ecore_Ipc_Server **server; + struct stat st; + char *p; + int port; + char socket[PATH_MAX]; + + server = (Ecore_Ipc_Server **) data; + port = 0; + if (!server) + return ECORE_CONFIG_ERR_FAIL; + +/* if(*server) + return ECORE_CONFIG_ERR_IGNORED; */ + + ecore_init(); + if (ecore_ipc_init() < 1) + return ECORE_CONFIG_ERR_FAIL; + + if ((p = getenv("HOME"))) + { /* debug-only ### FIXME */ + int stale; + + stale = 1; + while (stale) + { + snprintf(socket, PATH_MAX, "%s/.ecore/%s/%d", p, pipe_name, port); + + if (!stat(socket, &st)) + { + E(0, "IPC/eCore: pipe \"%s\" already exists!?\n", socket); +/* if(unlink(buf)) + E(0,"IPC/eCore: could not remove pipe \"%s\": %d\n",buf,errno); }}*/ + port++; + } + else + { + stale = 0; + } + } + } + *server = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, pipe_name, port, NULL); + ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD, + _ecore_config_ipc_client_add, server); + ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL, + _ecore_config_ipc_client_del, server); + ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA, + _ecore_config_ipc_client_sent, server); + + if (server) + { + E(1, "IPC/eCore: Server is listening on %s.\n", pipe_name); + } + + return ECORE_CONFIG_ERR_SUCC; +} + +int +_ecore_config_ipc_ecore_exit(void **data) +{ + int ret; + Ecore_Ipc_Server **server; + + ret = ECORE_CONFIG_ERR_SUCC; + server = (Ecore_Ipc_Server **) data; + + if (!server) + return ECORE_CONFIG_ERR_FAIL; + + if (*server) + { + ecore_ipc_server_del(*server); + *server = NULL; + } + + ecore_ipc_shutdown(); + + return ret; +} + +/*****************************************************************************/ + +int +_ecore_config_ipc_ecore_poll(void **data) +{ + Ecore_Ipc_Server **server; + + server = (Ecore_Ipc_Server **) data; + + if (!server) + return ECORE_CONFIG_ERR_FAIL; + + ecore_main_loop_iterate(); + + return ECORE_CONFIG_ERR_SUCC; +} + +/*****************************************************************************/ diff --git a/ecore/src/lib/ecore_config/ecore_config_ipc_main.c b/ecore/src/lib/ecore_config/ecore_config_ipc_main.c new file mode 100644 index 0000000..b4adf27 --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_ipc_main.c @@ -0,0 +1,284 @@ +/* ############## bad */ +#define HAVE_EVAS2 + +#include "Ecore_Config.h" +#include "ecore_config_util.h" +#include "ecore_config_ipc.h" + +#include "config.h" +#include "ecore_config_private.h" + +#include <signal.h> +#include <dlfcn.h> +#include <stdio.h> +#include <glob.h> +#include <sys/param.h> +#include <limits.h> +#include <string.h> +#include <stdlib.h> /* malloc(), free() */ + +#ifndef TRUE +# define FALSE 0 +# define TRUE (!FALSE) +#endif + +static Ecore_Config_Server *__ecore_config_servers; +static unsigned long ipc_timer = 0L; + +extern int _ecore_config_ipc_ecore_init(const char *pipe_name, void **data); +extern int _ecore_config_ipc_ecore_exit(void **data); +extern int _ecore_config_ipc_ecore_poll(void **data); + +Ecore_Config_Server * +_ecore_config_server_convert(void *srv) +{ + Ecore_Config_Server *srv_tmp; + + srv_tmp = __ecore_config_servers; + while (srv_tmp) + { + if (srv_tmp->server == srv) + return srv_tmp; + srv_tmp = srv_tmp->next; + } + + return __ecore_config_server_global; +} + +/*****************************************************************************/ +/* INTERFACE FOR IPC MODULES */ +/*****************************/ + +char * +_ecore_config_ipc_prop_list(Ecore_Config_Server * srv, const long serial) +{ + Ecore_Config_Bundle *theme; + Ecore_Config_Prop *e; + estring *s; + int f; + + theme = ecore_config_bundle_by_serial_get(srv, serial); + e = theme ? theme->data : NULL; + s = estring_new(8192); + f = 0; + while (e) + { + /* ignore system properties in listings, unless they have been overridden */ + if (e->flags & PF_SYSTEM && !(e->flags & PF_MODIFIED)) + { + e = e->next; + continue; + } + estring_appendf(s, "%s%s: %s", f ? "\n" : "", e->key, + ecore_config_type_get(e)); + if (e->flags & PF_BOUNDS) + { + if (e->type == PT_FLT) + estring_appendf(s, ", range %le..%le", + (float)e->lo / ECORE_CONFIG_FLOAT_PRECISION, + (float)e->hi / ECORE_CONFIG_FLOAT_PRECISION); + else + estring_appendf(s, ", range %d..%d", e->lo, e->hi); + } + if (e->type == PT_THM) + estring_appendf(s, ", group %s", e->data ? e->data : "Main"); + f = 1; + e = e->next; + } + + return estring_disown(s); +} + +char * +_ecore_config_ipc_prop_desc(Ecore_Config_Server * srv, const long serial, + const char *key) +{ +#ifdef HAVE_EVAS2 + Ecore_Config_Bundle *theme; + Ecore_Config_Prop *e; + + theme = ecore_config_bundle_by_serial_get(srv, serial); + e = ecore_config_get(key); + + if (e) + { + estring *s = estring_new(512); + + estring_appendf(s, "%s: %s", e->key, ecore_config_type_get(e)); + if (e->flags & PF_BOUNDS) + estring_appendf(s, ", range %d..%d", e->lo, e->hi); + return estring_disown(s); + } +#endif + return strdup("<undefined>"); +} + +char * +_ecore_config_ipc_prop_get(Ecore_Config_Server * srv, const long serial, + const char *key) +{ +#ifdef HAVE_EVAS2 + char *ret; + Ecore_Config_Bundle *theme; + + ret = NULL; + theme = ecore_config_bundle_by_serial_get(srv, serial); + if ((ret = ecore_config_as_string_get( /*theme, */ key))) + return ret; +#endif + return strdup("<undefined>"); +} + +int +_ecore_config_ipc_prop_set(Ecore_Config_Server * srv, const long serial, + const char *key, const char *val) +{ +#ifdef HAVE_EVAS2 + int ret; + Ecore_Config_Bundle *theme; + + theme = ecore_config_bundle_by_serial_get(srv, serial); + ret = ecore_config_set(key, (char *)val); + E(1, "ipc.prop.set(%s->%s,\"%s\") => %d\n", theme ? theme->identifier : "", + key, val, ret); + return ret; +#else + return ECORE_CONFIG_ERR_NOTSUPP; +#endif +} + +/*****************************************************************************/ + +char * +_ecore_config_ipc_bundle_list(Ecore_Config_Server * srv) +{ + Ecore_Config_Bundle *ns; + estring *s; + int f; + + ns = ecore_config_bundle_1st_get(srv); + s = estring_new(8192); + f = 0; + if (!ns) + return strdup("<no_bundles_created>"); + + while (ns) + { + estring_appendf(s, "%s%d: %s", f ? "\n" : "", + ecore_config_bundle_serial_get(ns), + ecore_config_bundle_label_get(ns)); + f = 1; + ns = ecore_config_bundle_next_get(ns); + } + + return estring_disown(s); +} + +int +_ecore_config_ipc_bundle_new(Ecore_Config_Server * srv, const char *label) +{ + if (ecore_config_bundle_new(srv, label)) + return ECORE_CONFIG_ERR_SUCC; + return ECORE_CONFIG_ERR_FAIL; +} + +char * +_ecore_config_ipc_bundle_label_get(Ecore_Config_Server * srv, const long serial) +{ + Ecore_Config_Bundle *ns; + char *label; + + ns = ecore_config_bundle_by_serial_get(srv, serial); + label = ecore_config_bundle_label_get(ns); + return strdup(label ? label : "<no such bundle>"); +} + +int +_ecore_config_ipc_bundle_label_set(Ecore_Config_Server * srv, const long serial, + const char *label) +{ + Ecore_Config_Bundle *ns; + + ns = ecore_config_bundle_by_serial_get(srv, serial); + if (!(ns->identifier = malloc(sizeof(label)))) + return ECORE_CONFIG_ERR_OOM; + memcpy(ns->identifier, label, sizeof(label)); + return ECORE_CONFIG_ERR_SUCC; +} + +long +_ecore_config_ipc_bundle_label_find(Ecore_Config_Server * srv, + const char *label) +{ + Ecore_Config_Bundle *ns; + + ns = ecore_config_bundle_by_label_get(srv, label); + return ns ? ecore_config_bundle_serial_get(ns) : -1; +} + +static int +_ecore_config_ipc_poll(void *data) +{ + Ecore_Config_Server *s; + + s = __ecore_config_servers; + while (s) + { + _ecore_config_ipc_ecore_poll(&s->server); + s = s->next; + } + + return TRUE; +} + +int +_ecore_config_ipc_exit(void) +{ + Ecore_Config_Server *l; + + if (ipc_timer) + timeout_remove(ipc_timer); + l = __ecore_config_servers; + while (l) + { + _ecore_config_ipc_ecore_exit(&l->server); + l = l->next; + } + + return ECORE_CONFIG_ERR_SUCC; +} + +Ecore_Config_Server * +_ecore_config_ipc_init(const char *pipe_name) +{ + int ret; + Ecore_Config_Server *list; + Ecore_Config_Server *ret_srv; + + list = NULL; + ret_srv = NULL; + list = NULL; + + list = malloc(sizeof(Ecore_Config_Server)); + memset(list, 0, sizeof(Ecore_Config_Server)); + if ((ret = _ecore_config_ipc_ecore_init(pipe_name, &list->server)) != ECORE_CONFIG_ERR_SUCC) + { + E(2, "_ecore_config_ipc_init: failed to register %s, code %d\n", + pipe_name, ret); + } + + E(2, "_ecore_config_ipc_init: registered \"%s\"...\n", pipe_name); + + list->name = strdup(pipe_name); + list->next = __ecore_config_servers; + + __ecore_config_servers = list; + if (!ret_srv) + ret_srv = list; + + if (!ipc_timer) + ipc_timer = timeout_add(100, _ecore_config_ipc_poll, NULL); + + return ret_srv; +} +/*****************************************************************************/ diff --git a/ecore/src/lib/ecore_config/ecore_config_private.h b/ecore/src/lib/ecore_config/ecore_config_private.h new file mode 100644 index 0000000..2b8ed47 --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_private.h @@ -0,0 +1,28 @@ +#ifndef _ECORE_CONFIG_PRIVATE_H +# define _ECORE_CONFIG_PRIVATE_H + +/* debug */ +extern int DEBUG; +#ifdef __sgi +# define D +# define E +#else +# define D(fmt,args...) do { if(DEBUG>=0) fprintf(stderr,fmt,## args); } while(0); +# define E(lvl,args...) do { if(DEBUG>=(lvl)) fprintf(stderr,## args); } while(0) +#endif + +typedef struct _Ecore_Config_DB_File Ecore_Config_DB_File; + +int _ecore_config_mod_init(const char *pipe_name, void **data); +int _ecore_config_mod_exit(void **data); +int _ecore_config_mod_poll(void **data); + +Ecore_Config_DB_File *_ecore_config_db_open_read(const char *file); +Ecore_Config_DB_File *_ecore_config_db_open_write(const char *file); +void _ecore_config_db_close(Ecore_Config_DB_File *db); +char **_ecore_config_db_keys_get(Ecore_Config_DB_File *db, int *num_ret); +Ecore_Config_Type _ecore_config_db_key_type_get(Ecore_Config_DB_File *db, const char *key); +int _ecore_config_db_read(Ecore_Config_DB_File *db, const char *key); +void _ecore_config_db_write(Ecore_Config_DB_File *db, const char *key); + +#endif diff --git a/ecore/src/lib/ecore_config/ecore_config_storage.c b/ecore/src/lib/ecore_config/ecore_config_storage.c new file mode 100644 index 0000000..e3cba38 --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_storage.c @@ -0,0 +1,172 @@ +#include "Ecore_Config.h" +#include "ecore_config_private.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <limits.h> + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +/** + * Loads the default configuration. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA + * is returned if the file cannot be loaded. + * @ingroup Ecore_Config_File_Group + */ +int +ecore_config_load(void) +{ + char file[PATH_MAX]; + + if (!__ecore_config_app_name) + return ECORE_CONFIG_ERR_FAIL; + + snprintf(file, PATH_MAX, "%s/.e/apps/%s/config.eet", getenv("HOME"), + __ecore_config_app_name); + return ecore_config_file_load(file); +} + +/** + * Saves the current configuration to the default file. + * @return @c ECORE_CONFIG_ERR_SUCC is returned on success. + * @c ECORE_CONFIG_ERR_FAIL is returned if the data cannot be + * saved. + * @ingroup Ecore_Config_File_Group + */ +int +ecore_config_save(void) +{ + char file[PATH_MAX]; + + if (!__ecore_config_app_name) + return ECORE_CONFIG_ERR_FAIL; + + snprintf(file, PATH_MAX, "%s/.e/apps/%s/config.eet", getenv("HOME"), + __ecore_config_app_name); + return ecore_config_file_save(file); +} + +/** + * Load the given configuration file to the local configuration. + * @param file Name of the file to load. + * @return @c ECORE_CONFIG_ERR_SUCC on success. @c ECORE_CONFIG_ERR_NODATA + * is returned if the file cannot be loaded. + * @ingroup Ecore_Config_File_Group + */ +int +ecore_config_file_load(const char *file) +{ + Ecore_Config_DB_File *db; + char **keys; + int key_count; + int x; + // double ftmp; UNUSED + // int pt; UNUSED + // int itmp; UNUSED + // Ecore_Config_Type type; UNUSED + char *data; + + db = NULL; + data = NULL; + + db = _ecore_config_db_open_read(file); + if (!db) + { + E(0, "Cannot open database from file %s!\n", file); + return ECORE_CONFIG_ERR_NODATA; + } + key_count = 0; + keys = _ecore_config_db_keys_get(db, &key_count); + if (keys) + { + for (x = 0; x < key_count; x++) + { + _ecore_config_db_read(db, keys[x]); + } + } + _ecore_config_db_close(db); + if (keys) + { + for (x = 0; x < key_count; x++) + { + free(keys[x]); + } + free(keys); + } + return ECORE_CONFIG_ERR_SUCC; +} + +static void +_ecore_config_recurse_mkdir(const char *file) +{ + char *file_ptr; + char *file_tmp; + struct stat status; + + file_tmp = strdup(file); + file_ptr = file_tmp + strlen(file_tmp); + while (*file_ptr != '/' && file_ptr > file_tmp) + file_ptr--; + *file_ptr = '\0'; + + if (stat(file_tmp, &status)) + { + _ecore_config_recurse_mkdir(file_tmp); + mkdir(file_tmp, S_IRUSR | S_IWUSR | S_IXUSR); + } + free(file_tmp); +} + +/** + * Saves the local configuration to the given file. + * @param file Name of the file to save to. + * @return @c ECORE_CONFIG_ERR_SUCC is returned on success. + * @c ECORE_CONFIG_ERR_FAIL is returned if the data cannot be + * saved. + * @ingroup Ecore_Config_File_Group + */ +int +ecore_config_file_save(const char *file) +{ + Ecore_Config_Prop *next; + Ecore_Config_DB_File *db; + struct stat status; + + next = __ecore_config_bundle_local->data; + db = NULL; + + /* if file does not exist check to see if the dirs exist, creating if not */ + if (stat(file, &status)) + _ecore_config_recurse_mkdir(file); + + db = _ecore_config_db_open_write(file); + if (!db) + { + E(0, "Cannot open database from file %s!\n", file); + return ECORE_CONFIG_ERR_FAIL; + } + + while (next) + { + /* let the config_db deal with this + * handyande: hmm, not sure that it ever does - reinstating until + * further discussions satisfy me! + */ + if (!(next->flags & PF_MODIFIED) || next->flags & PF_CMDLN) + { + next = next->next; + continue; + } + + _ecore_config_db_write(db, next->key); + + next = next->next; + } + + _ecore_config_db_close(db); + return ECORE_CONFIG_ERR_SUCC; +} diff --git a/ecore/src/lib/ecore_config/ecore_config_util.c b/ecore/src/lib/ecore_config/ecore_config_util.c new file mode 100644 index 0000000..07f625a --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_util.c @@ -0,0 +1,781 @@ +/* azundris */ + +/*#include <glib.h>*/ + +#include <sys/types.h> +#include <sys/time.h> /* gimetimeofday() */ +#include <stdio.h> /* NULL */ +#include <stdlib.h> /* malloc(), free() */ +#include <string.h> /* str...() */ +#include <ctype.h> /* isspace() */ + +#include <stdarg.h> /* varargs in dlmulti() */ +#include <dlfcn.h> /* dlopen() and friends for dlmulti() */ + +/* #ifdef HAVE_GLIB2 */ +/* # include <glib/gmain.h> */ +/* #endif */ + +#include "ecore_private.h" + +#include "Ecore_Config.h" +#include "ecore_config_util.h" + +#include "ecore_config_private.h" + +#define CHUNKLEN 4096 + +/*****************************************************************************/ +/* MISC */ +/********/ + +int +dlmulti(const char *name, const char *file, int flag, void **libr, const char *fmt, ...) +{ +#define MAX_SYM_LEN 256 + va_list ap; + void *lib; + int ret = ECORE_CONFIG_ERR_SUCC; + char buf[MAX_SYM_LEN] = "\0"; + + if (!libr) + return ECORE_CONFIG_ERR_FAIL; + + if (!name) + name = file; + + *libr = NULL; + + if ((lib = dlopen(file, flag))) + { + void **funr, *fun; + char *b, *e; + size_t l; + int required = 1; + + va_start(ap, fmt); + while (*fmt) + { + switch (*fmt) + { + case '?': + required = 0; + fmt++; + break; + + case '!': + case '.': + required = 1; + fmt++; + break; + + case '\t': + case '\n': + case '\r': + case ';': + case ',': + case ' ': + fmt++; + break; + + default: + e = b = (char *)fmt; + while (*e && (strchr("?!.,; \t\n\r", *e) == NULL)) + e++; + + fmt = e; + if (e == b) + ret = ECORE_CONFIG_ERR_NODATA; + else if ((l = (e - b)) >= MAX_SYM_LEN) + ret = ECORE_CONFIG_ERR_OOM; + else + { + memcpy(buf, b, l); + buf[l] = '\0'; + funr = va_arg(ap, void **); + + if (!(fun = dlsym(lib, buf))) + { + if ((ret = + required ? ECORE_CONFIG_ERR_NOTFOUND : + ECORE_CONFIG_ERR_PARTIAL) == + ECORE_CONFIG_ERR_NOTFOUND) + E(1, + "DLMulti: library/plugin/engine \"%s\" (\"%s\") did not contain required function \"%s\"...\n", + name, file, buf); + } + E(2, "DLMulti: %p => %p %c\"%s\"\n", fun, funr, + required ? '!' : '?', buf); + if (funr) + *funr = fun; + } + required = 1; + } + } + + va_end(ap); + + if ((ret == ECORE_CONFIG_ERR_SUCC) || (ret == ECORE_CONFIG_ERR_PARTIAL)) + *libr = lib; + else + dlclose(lib); + } + else + ret = ECORE_CONFIG_ERR_NODATA; + + return ret; +} + +#if 0 /* Unused */ +/*****************************************************************************/ + +unsigned long +now(long delay) +{ + static struct timeval tv; + unsigned long r; + + gettimeofday(&tv, NULL); + r = tv.tv_sec * 1000 + (((float)tv.tv_usec) / 1000.0) + delay; + return r; +} +#endif + +/*****************************************************************************/ + +int +parse_line(char *in, char **o1, char **o2, char **o3, char **o4) +{ +#define PLMAX 16 + int c; + char *p = in; + char *r[PLMAX]; + + for (c = 0; c < PLMAX; c++) + r[c] = NULL; + + c = 0; + if (!in || !*in) + goto pl_end; + + do + { + while (isspace(*p)) + *(p++) = '\0'; + + if (!*p || (strchr("#;", *p) && (!p[1] || isspace(p[1])))) + *p = '\0'; /* it ends HERE */ + else + { + if (*p == '\"') + { + r[c++] = ++p; + while (*p && (*p != '\"')) + { + if ((*p == '\\') && p[1]) + p += 2; + else + p++; + } + if (*p) + *(p++) = '\0'; + } + else + { + r[c++] = p; + while (*p && !isspace(*p)) + p++; + } + } + } + while (*p); + + pl_end: + if (o1) + *o1 = r[0]; + if (o2) + *o2 = r[1]; + if (o3) + *o3 = r[2]; + if (o4) + *o4 = r[3]; + + return c; +} + +/*****************************************************************************/ + +/*char *unit_size(char *size) { + gchar *unit="byte"; + long s; + + if((s=atol(size))&&(s>=1024)) { + if((s>(1024*1024*1024))) { + unit="GB"; + s=(long)(s/(1024*1024)); } + else if((s>(1024*1024))) { + unit="MB"; + s=(long)(s/1024); } + else + unit="KB"; + + if((s/1024)>31) + sprintf(size,"%ld %s",(long)(s/1024),unit); + else + sprintf(size,"%.1f %s",((float)s)/1024,unit); } + else + sprintf(size,"%ld %s",s,unit); + + return size; } + +*/ + +/*****************************************************************************/ + +void +qsrt(void *a[], void *data, int lo, int hi, + int (*compare) (const void *, const void *, const void *)) +{ + int h, l; + void *p, *t; + + if (lo < hi) + { + l = lo; + h = hi; + p = a[hi]; + + do + { + while ((l < h) && (compare(data, a[l], p) <= 0)) + l = l + 1; + while ((h > l) && (compare(data, a[h], p) >= 0)) + h = h - 1; + if (l < h) + { + t = a[l]; + a[l] = a[h]; + a[h] = t; + } + } + while (l < h); + + t = a[l]; + a[l] = a[hi]; + a[hi] = t; + + qsrt(a, data, lo, l - 1, compare); + qsrt(a, data, l + 1, hi, compare); + } +} + +/*****************************************************************************/ +/* TIMERS */ +/**********/ + +#ifdef HAVE_GLIB2 + +unsigned long +timeout_add(uint f, int (*fun) (void *), void *data) +{ + return g_timeout_add((guint) f, (GSourceFunc) fun, (gpointer) data); +} + +int +timeout_remove(unsigned long handle) +{ + return g_source_remove(handle) ? ECORE_CONFIG_ERR_SUCC : + ECORE_CONFIG_ERR_FAIL; +} + +#else + +unsigned long +timeout_add(uint f __UNUSED__, int (*fun) (void *) __UNUSED__, void *data __UNUSED__) +{ + return 0; +} + +int +timeout_remove(unsigned long handle __UNUSED__) +{ + return ECORE_CONFIG_ERR_NOTSUPP; +} + +#endif /* HAVE_GLIB2 */ + +/*****************************************************************************/ +/* HASHES */ +/**********/ + +int +eslist_free(eslist ** l) +{ + eslist *e, *f; + + if (!l) + return ECORE_CONFIG_ERR_NODATA; + for (e = *l; e; e = f) + { + f = e->next; + free(e); + } + *l = NULL; + return ECORE_CONFIG_ERR_SUCC; +} + +int +eslist_next(eslist ** e) +{ + if (!e || !*e) + return ECORE_CONFIG_ERR_NODATA; + *e = (*e)->next; + return ECORE_CONFIG_ERR_SUCC; +} + +void * +eslist_payload(eslist ** e) +{ + return (!e || !*e) ? NULL : (*e)->payload; +} + +int +eslist_prepend(eslist ** e, void *p) +{ + eslist *f; + + if (!e) + return ECORE_CONFIG_ERR_NODATA; + + if (!(f = malloc(sizeof(eslist)))) + return ECORE_CONFIG_ERR_OOM; + + f->payload = p; + f->next = *e; + + *e = f; + + return ECORE_CONFIG_ERR_SUCC; +} + +int +eslist_append(eslist ** e, void *p) +{ + eslist *f; + + if (!e) + return ECORE_CONFIG_ERR_NODATA; + + if (!(f = malloc(sizeof(eslist)))) + return ECORE_CONFIG_ERR_OOM; + + f->payload = p; + f->next = NULL; + + if (!*e) + *e = f; + else + { + eslist *g = *e; + + while (g->next) + g = g->next; + g->next = f; + } + + return ECORE_CONFIG_ERR_SUCC; +} + +/*****************************************************************************/ +/* HASHES */ +/**********/ + +#ifdef HAVE_GLIB2 + +void * +hash_table_new(void (*freekey), void (*freeval)) +{ + return g_hash_table_new_full(g_str_hash, g_str_equal, freekey, freeval); +} + +void * +hash_table_fetch(void *hashtable, char *key) +{ + return g_hash_table_lookup(hashtable, key); +} + +int +hash_table_insert(void *hashtable, char *key, void *value) +{ + g_hash_table_insert(hashtable, key, value); + return ECORE_CONFIG_ERR_SUCC; +} + +int +hash_table_replace(void *hashtable, char *key, void *value) +{ + g_hash_table_replace(hashtable, key, value); + return ECORE_CONFIG_ERR_SUCC; +} + +int +hash_table_remove(void *hashtable, char *key) +{ + g_hash_table_remove(hashtable, key); + return ECORE_CONFIG_ERR_SUCC; +} + +int +hash_table_dst(void *hashtable) +{ + g_hash_table_destroy(hashtable); + return ECORE_CONFIG_ERR_SUCC; +} + +int +hash_table_walk(void *hashtable, hash_walker fun, void *data) +{ + g_hash_table_foreach(hashtable, (GHFunc) fun, data); + return ECORE_CONFIG_ERR_SUCC; +} + +#else + +void * +hash_table_new(void (*freekey) __UNUSED__, void (*freeval) __UNUSED__) +{ + return NULL; +} + +void * +hash_table_fetch(void *hashtable __UNUSED__, char *key __UNUSED__) +{ + return NULL; +} + +int +hash_table_insert(void *hashtable __UNUSED__, char *key __UNUSED__, void *value __UNUSED__) +{ + return ECORE_CONFIG_ERR_NOTSUPP; +} + +int +hash_table_replace(void *hashtable __UNUSED__, char *key __UNUSED__, void *value __UNUSED__) +{ + return ECORE_CONFIG_ERR_NOTSUPP; +} + +int +hash_table_remove(void *hashtable __UNUSED__, char *key __UNUSED__) +{ + return ECORE_CONFIG_ERR_NOTSUPP; +} + +int +hash_table_dst(void *hashtable __UNUSED__) +{ + return ECORE_CONFIG_ERR_NOTSUPP; +} + +int +hash_table_walk(void *hashtable __UNUSED__, hash_walker fun __UNUSED__, void *data __UNUSED__) +{ + return ECORE_CONFIG_ERR_NOTSUPP; +} + +#endif /* HAVE_GLIB2 */ + +/*****************************************************************************/ +/* STRINGS */ +/***********/ + +estring * +estring_new(int size) +{ + estring *e = malloc(sizeof(estring)); + + if (e) + { + memset(e, 0, sizeof(estring)); + if ((size > 0) && (e->str = malloc(size))) + e->alloc = size; + } + return e; +} + +estring * +estring_dst(estring * e) +{ + if (e) + { + if (e->str) + free(e->str); + free(e); + } + return NULL; +} + +char * +estring_disown(estring * e) +{ + if (e) + { + char *r = e->str; + + free(e); + return r; + } + return NULL; +} + +char * +estring_free(estring * e, int release_payload) +{ /* glib compat */ + if (release_payload) + { + estring_dst(e); + return NULL; + } + return estring_disown(e); +} + +int +estring_truncate(estring * e, int size) +{ + if (!e || (size < 0)) + return ECORE_CONFIG_ERR_FAIL; + if (e->used <= size) + return e->used; + e->str[size] = '\0'; + e->used = size; + return size; +} + +int +estring_printf(estring * e, const char *fmt, ...) +{ + int need; + va_list ap; + char *p; + + if (!e) + return ECORE_CONFIG_ERR_FAIL; + + if (!(e->str)) + { + if (!(e->str = (char *)malloc(e->alloc = 512))) + return ECORE_CONFIG_ERR_OOM; + } + + retry: + va_start(ap, fmt); + need = vsnprintf(e->str, e->alloc, fmt, ap); + va_end(ap); + + if ((need >= e->alloc) || (need < 0)) + { + if (need < 0) + need = 2 * e->alloc; + else + need++; + if (!(p = (char *)realloc(e->str, need))) + { + free(e->str); + e->alloc = e->used = 0; + return ECORE_CONFIG_ERR_OOM; + } + e->alloc = need; + e->str = p; + goto retry; + } + + return e->used = need; +} + +int +estring_appendf(estring * e, const char *fmt, ...) +{ + int need; + va_list ap; + char *p; + + if (!e) + return ECORE_CONFIG_ERR_FAIL; + + if (!e->str) + { + e->used = e->alloc = 0; + if (!(e->str = (char *)malloc(e->alloc = 512))) + return ECORE_CONFIG_ERR_OOM; + } + + retry: + va_start(ap, fmt); + need = vsnprintf(e->str + e->used, e->alloc - e->used, fmt, ap); + va_end(ap); + + if ((need >= (e->alloc - e->used)) || (need < 0)) + { + if (need < 0) + need = 2 * e->alloc; + else + need++; + need += e->used; + need += (CHUNKLEN - (need % CHUNKLEN)); + + if (!(p = (char *)realloc(e->str, need))) + { + free(e->str); + e->alloc = e->used = 0; + return ECORE_CONFIG_ERR_OOM; + } + e->alloc = need; + e->str = p; + goto retry; + } + + return e->used += need; +} + +int +esprintf(char **result, const char *fmt, ...) +{ + int need, have; + va_list ap; + char *n; + + if (!result) + return ECORE_CONFIG_ERR_FAIL; + + if (!(n = (char *)malloc(have = 512))) + return ECORE_CONFIG_ERR_OOM; + + retry: + va_start(ap, fmt); + need = vsnprintf(n, have, fmt, ap); + va_end(ap); + + if ((need >= have) || (need < 0)) + { + char *p; + + if (need < 0) + need = 2 * have; + else + need++; + if (!(p = (char *)realloc(n, need))) + { + free(n); + return ECORE_CONFIG_ERR_OOM; + } + have = need; + n = p; + goto retry; + } + + if (*result) + free(*result); + *result = n; + + return need; +} + +#if 0 +int +ejoin(char **result, char *delim, ...) +{ + int dl, cl, ret = ECORE_CONFIG_ERR_SUCC; + va_list ap; + char *e, *n; + + if (!result) + return ECORE_CONFIG_ERR_FAIL; + if (!delim) + delim = ""; + dl = strlen(delim); + + va_start(ap, delim); + cl = -dl; + while ((e = va_arg(ap, char *))) + cl += strlen(e) + dl; + + va_end(ap); + + if (cl <= 0) + { + if (!(n = strdup(""))) + ret = ECORE_CONFIG_ERR_OOM; + } + else if (!(n = malloc(cl + 1))) + ret = ECORE_CONFIG_ERR_OOM; + else + { + char *p = n; + + va_start(ap, delim); + while ((e = va_arg(ap, char *))) + { + if (dl && (p != n)) + { + strcpy(p, delim); + p += dl; + } + strcpy(p, e); + p += strlen(p); + } + va_end(ap); + } + + if (*result) + free(*result); + *result = n; + + return ret; +} + +int +ecat(char **result, ...) +{ + int cl, ret = ECORE_CONFIG_ERR_SUCC; + va_list ap; + char *e, *n; + + if (!result) + return ECORE_CONFIG_ERR_FAIL; + + va_start(ap, result); + cl = 0; + while ((e = va_arg(ap, char *))) + cl += strlen(e); + + va_end(ap); + + if (cl <= 0) + { + if (!(n = strdup(""))) + ret = ECORE_CONFIG_ERR_OOM; + } + else if (!(n = malloc(cl + 1))) + ret = ECORE_CONFIG_ERR_OOM; + else + { + char *p = n; + + va_start(ap, result); + while ((e = va_arg(ap, char *))) + { + strcpy(p, e); + p += strlen(p); + } + va_end(ap); + } + + if (*result) + free(*result); + *result = n; + + return ret; +} +#endif + +/*****************************************************************************/ diff --git a/ecore/src/lib/ecore_config/ecore_config_util.h b/ecore/src/lib/ecore_config/ecore_config_util.h new file mode 100644 index 0000000..eff279e --- /dev/null +++ b/ecore/src/lib/ecore_config/ecore_config_util.h @@ -0,0 +1,63 @@ +#define TIMER_STOP 0 +#define TIMER_CONT 1 + +typedef struct _estring +{ + char *str; + int alloc, used; +} estring; + +typedef struct _eslist +{ + void *payload; + struct _eslist *next; +} eslist; + +int parse_line(char *, char **, char **, char **, char **); +char *unit_size(char *size); + +/*unsigned long now(long delay);*/ +void qsrt(void *a[], void *data, int lo, int hi, + int (*compare) (const void *, const void *, + const void *)); +int dlmulti(const char *name, const char *file, int flag, void **libr, + const char *fmt, ...); + +typedef void (*hash_walker) (char *key, void *value, void *data); + +void *hash_table_new(void (*freekey), void (*freeval)); +void *hash_table_fetch(void *hashtable, char *key); +int hash_table_insert(void *hashtable, char *key, void *value); +int hash_table_replace(void *hashtable, char *key, void *value); +int hash_table_remove(void *hashtable, char *key); +int hash_table_dst(void *hashtable); +int hash_table_walk(void *hashtable, hash_walker fun, + void *data); + +int eslist_free(eslist **); +int eslist_next(eslist **); + +#define ESLIST_NEXT(e) (e=e->next) +void *eslist_payload(eslist **); + +#define ESLIST_PAYLOAD(e) ((e)->payload) +int eslist_prepend(eslist **, void *); +int eslist_append(eslist **, void *); + +estring *estring_new(int size); +estring *estring_dst(estring * e); +char *estring_disown(estring * e); +char *estring_free(estring * e, int release_payload); /* glib compat */ +int estring_printf(estring * e, const char *fmt, ...); +int estring_appendf(estring * e, const char *fmt, ...); +int estring_truncate(estring * e, int size); + +#define ESTRING_GET_CSTRING(a) ((a)->str) + +int esprintf(char **result, const char *fmt, ...); +int ejoin(char **result, const char *delim, ...); +int ecat(char **result, ...); + +unsigned long timeout_add(unsigned int f, int (*fun) (void *), + void *data); +int timeout_remove(unsigned long handle); diff --git a/ecore/src/lib/ecore_dbus/.cvsignore b/ecore/src/lib/ecore_dbus/.cvsignore new file mode 100644 index 0000000..33d062e --- /dev/null +++ b/ecore/src/lib/ecore_dbus/.cvsignore @@ -0,0 +1,7 @@ +.deps +.libs +Ecore_Con.h +Makefile +Makefile.in +*.lo +libecore_dbus.la diff --git a/ecore/src/lib/ecore_dbus/CVS/Entries b/ecore/src/lib/ecore_dbus/CVS/Entries new file mode 100644 index 0000000..c6fd67d --- /dev/null +++ b/ecore/src/lib/ecore_dbus/CVS/Entries @@ -0,0 +1,6 @@ +/.cvsignore/1.2/Mon Jun 6 09:41:44 2005//THEAD +/Ecore_DBus.h/1.2/Fri Jun 10 02:41:37 2005//THEAD +/Makefile.am/1.3/Fri Apr 29 09:45:12 2005//THEAD +/ecore_dbus.c/1.3/Fri Jun 10 02:41:37 2005//THEAD +/ecore_dbus_private.h/1.1/Fri Apr 29 05:29:29 2005//THEAD +D diff --git a/ecore/src/lib/ecore_dbus/CVS/Repository b/ecore/src/lib/ecore_dbus/CVS/Repository new file mode 100644 index 0000000..a763d9e --- /dev/null +++ b/ecore/src/lib/ecore_dbus/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_dbus diff --git a/ecore/src/lib/ecore_dbus/CVS/Root b/ecore/src/lib/ecore_dbus/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_dbus/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_dbus/CVS/Tag b/ecore/src/lib/ecore_dbus/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_dbus/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_dbus/Ecore_DBus.h b/ecore/src/lib/ecore_dbus/Ecore_DBus.h new file mode 100644 index 0000000..3087a20 --- /dev/null +++ b/ecore/src/lib/ecore_dbus/Ecore_DBus.h @@ -0,0 +1,209 @@ +#ifndef _ECORE_DBUS_H +#define _ECORE_DBUS_H +#endif + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _Ecore_DBus_Server Ecore_DBus_Server; + typedef struct _Ecore_DBus_Client Ecore_DBus_Client; + typedef struct _Ecore_DBus_Event_Server_Add Ecore_DBus_Event_Server_Add; + typedef struct _Ecore_DBus_Event_Server_Del Ecore_DBus_Event_Server_Del; + typedef struct _Ecore_DBus_Event_Server_Data Ecore_DBus_Event_Server_Data; + typedef struct _Ecore_DBus_Message Ecore_DBus_Message; + typedef struct _Ecore_DBus_Message_Field Ecore_DBus_Message_Field; + typedef struct _Ecore_DBus_Auth Ecore_DBus_Auth; + typedef unsigned char* (*Ecore_DBus_Auth_Transaction)(void*); + + typedef enum _Ecore_DBus_Type + { + ECORE_DBUS_BUS_SESSION, + ECORE_DBUS_BUS_SYSTEM, + ECORE_DBUS_BUS_ACTIVATION + } Ecore_DBus_Type; + + typedef enum _Ecore_DBus_Message_Type + { + ECORE_DBUS_MESSAGE_TYPE_INVALID, + ECORE_DBUS_MESSAGE_TYPE_METHOD_CALL, + ECORE_DBUS_MESSAGE_TYPE_METHOD_RETURN, + ECORE_DBUS_MESSAGE_TYPE_ERROR, + ECORE_DBUS_MESSAGE_TYPE_SIGNAL + } Ecore_DBus_Message_Type; + + /* message data types */ + typedef enum _Ecore_DBus_Data_Type + { + ECORE_DBUS_DATA_TYPE_INVALID = ((int) '\0'), + ECORE_DBUS_DATA_TYPE_NIL = ((int) '\0'), + ECORE_DBUS_DATA_TYPE_BYTE = ((int) 'y'), + ECORE_DBUS_DATA_TYPE_BOOLEAN = ((int) 'b'), /* 0,1 */ + ECORE_DBUS_DATA_TYPE_INT32 = ((int) 'i'), + ECORE_DBUS_DATA_TYPE_UINT32 =((int) 'u'), + ECORE_DBUS_DATA_TYPE_INT64 = ((int) 'x'), + ECORE_DBUS_DATA_TYPE_UINT64 = ((int) 't'), + ECORE_DBUS_DATA_TYPE_DOUBLE = ((int) 'd'), + ECORE_DBUS_DATA_TYPE_STRING = ((int) 's'), + ECORE_DBUS_DATA_TYPE_CUSTOM = ((int) 'c'), + ECORE_DBUS_DATA_TYPE_ARRAY =((int) 'a'), + ECORE_DBUS_DATA_TYPE_DICT = ((int) 'm'), + ECORE_DBUS_DATA_TYPE_OBJECT_PATH = ((int) 'o') + } Ecore_DBus_Data_Type; + + typedef enum _Ecore_DBus_Message_Header_Field + { + ECORE_DBUS_HEADER_FIELD_INVALID, + ECORE_DBUS_HEADER_FIELD_PATH, + ECORE_DBUS_HEADER_FIELD_INTERFACE, + ECORE_DBUS_HEADER_FIELD_MEMBER, + ECORE_DBUS_HEADER_FIELD_ERROR_NAME, + ECORE_DBUS_HEADER_FIELD_REPLY_SERIAL, + ECORE_DBUS_HEADER_FIELD_DESTINATION, + ECORE_DBUS_HEADER_FIELD_SENDER, + ECORE_DBUS_HEADER_FIELD_SIGNATURE + } Ecore_DBus_Message_Header_Field; + + typedef enum _Ecore_DBus_Auth_Type + { + ECORE_DBUS_AUTH_TYPE_EXTERNAL, + ECORE_DBUS_AUTH_MAGIC_COOKIE, + ECORE_DBUS_AUTH_TYPE_DBUS_COOKIE_SHA1, + ECORE_DBUS_AUTH_TYPE_KERBEROS_V4, + ECORE_DBUS_AUTH_TYPE_SKEY + } Ecore_DBus_Auth_Type; + + struct _Ecore_DBus_Auth + { + char *name; + unsigned int num_transactions; + Ecore_DBus_Auth_Transaction transactions[5]; + }; + + struct _Ecore_DBus_Event_Server_Add + { + Ecore_DBus_Server *server; + }; + + struct _Ecore_DBus_Event_Server_Del + { + Ecore_DBus_Server *server; + }; + + struct _Ecore_DBus_Message_Field + { + Ecore_List __list_data; + Ecore_DBus_Data_Type type; + unsigned int offset; + unsigned int count; /* number of elements, usefull for structs, arrays, dicts */ + unsigned int hfield; /* if the field is a header field, we need the type of it */ + }; + + struct _Ecore_DBus_Message + { + /* header fields */ + unsigned char byte_order; + unsigned char type; + unsigned char flags; + unsigned char protocol; + unsigned long hlength; + unsigned long blength; + unsigned long serial; + + Ecore_DBus_Server *ref_server; + + unsigned char *header; + unsigned int hpos; + Ecore_DBus_Message_Field *header_fields; + unsigned char *body; + unsigned int bpos; + Ecore_DBus_Message_Field *body_fields; + unsigned char *signature; + }; + + extern int ECORE_DBUS_EVENT_SERVER_ADD; + extern int ECORE_DBUS_EVENT_SERVER_DATA; + + /* Message byte order */ +#define DBUS_LITTLE_ENDIAN ('l') /* LSB first */ +#define DBUS_BIG_ENDIAN ('B') /* MSB first */ + + /* Protocol version */ +#define DBUS_MAJOR_PROTOCOL_VERSION 0 + + + /* Max length in bytes of a service or interface or member name */ +#define DBUS_MAXIMUM_NAME_LENGTH 256 + + /* Max length of a match rule string */ +#define DBUS_MAXIMUM_MATCH_RULE_LENGTH 1024 + + + /* Header flags */ +#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED 0x1 +#define DBUS_HEADER_FLAG_AUTO_ACTIVATION 0x2 + + +#define DBUS_HEADER_FIELD_LAST DBUS_HEADER_FIELD_SIGNATURE + + /* Services */ +#define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS "org.freedesktop.DBus" + + /* Paths */ +#define DBUS_PATH_ORG_FREEDESKTOP_DBUS "/org/freedesktop/DBus" +#define DBUS_PATH_ORG_FREEDESKTOP_LOCAL "/org/freedesktop/Local" + + /* Interfaces, these #define don't do much other than + * * catch typos at compile time + * */ +#define DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS "org.freedesktop.DBus" +#define DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE "org.freedesktop.Introspectable" + + /* This is a special interface whose methods can only be invoked + * by the local implementation (messages from remote apps aren't + * allowed to specify this interface). + */ +#define DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL "org.freedesktop.Local" + /* Service owner flags */ +#define DBUS_SERVICE_FLAG_PROHIBIT_REPLACEMENT 0x1 +#define DBUS_SERVICE_FLAG_REPLACE_EXISTING 0x2 + + /* Service replies */ +#define DBUS_SERVICE_REPLY_PRIMARY_OWNER 0x1 +#define DBUS_SERVICE_REPLY_IN_QUEUE 0x2 +#define DBUS_SERVICE_REPLY_SERVICE_EXISTS 0x4 +#define DBUS_SERVICE_REPLY_ALREADY_OWNER 0x8 + + /* Activation replies */ +#define DBUS_ACTIVATION_REPLY_ACTIVATED 0x0 +#define DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE 0x1 + + /* connection */ + EAPI int ecore_dbus_init(void); + EAPI Ecore_DBus_Server* ecore_dbus_server_connect(Ecore_DBus_Type compl_type, char *name, int port, const void *data); + /* message */ + EAPI unsigned int ecore_dbus_message_new_method_call(Ecore_DBus_Server *svr,char *service,char *path,char *interface,char *method,char *fmt, ...); + EAPI void ecore_dbus_message_print(Ecore_DBus_Message *msg); + EAPI void * ecore_dbus_get_header_field(Ecore_DBus_Message *,Ecore_DBus_Message_Field *, Ecore_DBus_Message_Header_Field); + EAPI void * ecore_dbus_get_body_field(Ecore_DBus_Message *,Ecore_DBus_Message_Field *, unsigned int); + +#ifdef __cplusplus +} +#endif diff --git a/ecore/src/lib/ecore_dbus/Makefile.am b/ecore/src/lib/ecore_dbus/Makefile.am new file mode 100644 index 0000000..3758ca7 --- /dev/null +++ b/ecore/src/lib/ecore_dbus/Makefile.am @@ -0,0 +1,39 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_con \ +-I$(top_builddir)/src/lib/ecore_dbus \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_con \ +-I$(top_srcdir)/src/lib/ecore_dbus \ +@SSL_CFLAGS@ + +libecore_dbus_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs \ +-L$(top_builddir)/src/lib/ecore_con/.libs + +if BUILD_ECORE_DBUS + +lib_LTLIBRARIES = libecore_dbus.la +include_HEADERS = \ +Ecore_DBus.h + +libecore_dbus_la_SOURCES = \ +ecore_dbus.c \ +ecore_dbus_private.h + +libecore_dbus_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_con/libecore_con.la \ +@SSL_LIBS@ + +libecore_dbus_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_con/libecore_con.la + +endif + +EXTRA_DIST = \ +ecore_dbus.c \ +ecore_dbus_private.h diff --git a/ecore/src/lib/ecore_dbus/ecore_dbus.c b/ecore/src/lib/ecore_dbus/ecore_dbus.c new file mode 100644 index 0000000..6f2e1a6 --- /dev/null +++ b/ecore/src/lib/ecore_dbus/ecore_dbus.c @@ -0,0 +1,1235 @@ +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <stdarg.h> + +#include "Ecore.h" +#include "ecore_private.h" +#include "Ecore_Con.h" +#include "Ecore_DBus.h" +#include "ecore_dbus_private.h" + +/********************************************************************************/ +/* About */ +/********************************************************************************/ +/* Author: Jorge Luis Zapata */ +/* Version: 0.2.1 */ +/********************************************************************************/ +/* Todo */ +/********************************************************************************/ +/* free allocated data */ +/* make other authentication mechanisms besides external */ +/********************************************************************************/ +/* Changelog */ +/********************************************************************************/ +/* 0.0 usable interface */ +/* 0.1 change dbus spec version (0.11): */ +/* different header format */ +/* new type signature */ +/* header length = 8 byte multiple */ +/* paddings value must be null */ +/* body need not to end in a 8 byte boundary */ +/* new data type: variant,signature,dict */ +/* ecore_oldlist cant join two lists so is difficult to handle compound */ +/* data types (variant,struct,dict,array) in a stack way */ +/* 0.2 change again the spec version (0.8) */ +/* i realized that the first version was correct, when i read the spec */ +/* for ecore_dbus 0.1 i was reading a previous version :( */ +/* put again the data type byte in each marshaled data */ +/* */ +/* 29-03-05 */ +/* 0.2.1 some segfault fixes, new tests */ + +static int ecore_dbus_server_send(Ecore_DBus_Server * svr, + char *command, int length); +Ecore_Oldlist *_ecore_dbus_message_print_field(Ecore_Oldlist * l, + unsigned char *buf); +void _ecore_dbus_message_print_raw(unsigned char *msg, + unsigned int msg_len); + +/**********************/ +/* ecore dbus message */ +/**********************/ + +#define BODY_LEN 64 +#define HEADER_LEN 16 + +/* length functions */ +/********************/ +/* all of these increase the length */ +void +_ecore_dbus_message_increase_lengthz(unsigned char **buf, + unsigned int old_length, unsigned int size) +{ + *buf = realloc(*buf, old_length + size); + memset(*buf + old_length, 0, size); +} + +void +_ecore_dbus_message_increase_length(unsigned char **buf, + unsigned int new_length) +{ + *buf = realloc(*buf, new_length); +} + +/* padding functions */ +/*********************/ +/* all of these increase the length */ +void +_ecore_dbus_message_4byte_padding(unsigned char **buf, unsigned int *old_length) +{ + unsigned int padding; + + padding = *old_length % 4; + if (padding != 0) + { + padding = 4 - padding; + _ecore_dbus_message_increase_lengthz(buf, *old_length, padding); + } + *old_length += padding; +} +void +_ecore_dbus_message_8byte_padding(unsigned char **buf, unsigned int *old_length) +{ + unsigned int padding; + + padding = *old_length % 8; + if (padding != 0) + { + padding = 8 - padding; + _ecore_dbus_message_increase_lengthz(buf, *old_length, padding); + } + *old_length += padding; +} + +void +_ecore_dbus_message_skip_8byte_padding(unsigned int *old_length) +{ + unsigned int padding; + + padding = *old_length % 8; + if (padding != 0) + *old_length += 8 - padding; + return; +} + +void +_ecore_dbus_message_skip_4byte_padding(unsigned int *old_length) /* DONE */ +{ + unsigned int padding; + + padding = *old_length % 4; + if (padding != 0) + *old_length += 4 - padding; + return; +} + +/* appending/reading functions */ +/*******************************/ +/* non of these increase the length */ +void +_ecore_dbus_message_append_nbytes(unsigned char *buf, unsigned char *data, + unsigned int data_length) +{ + memcpy(buf, data, data_length); +} + +void +_ecore_dbus_message_append_byte(unsigned char *buf, unsigned char c) +{ + *buf = c; +} + +void +_ecore_dbus_message_append_uint32(unsigned char *buf, unsigned long int i) +{ + unsigned char *c; + + c = (unsigned char *)&i; + *(buf + 0) = *(c + 0); + *(buf + 1) = *(c + 1); + *(buf + 2) = *(c + 2); + *(buf + 3) = *(c + 3); +} + +unsigned long +_ecore_dbus_message_read_uint32(unsigned char *buf) +{ + return *(unsigned long *)buf; +} + +unsigned char +_ecore_dbus_message_read_byte(unsigned char *buf) +{ + return *(unsigned char *)buf; +} + +/* field functions */ +/*******************/ + +/* memory allocation */ +/**********************/ +Ecore_DBus_Message * +_ecore_dbus_message_new(Ecore_DBus_Server * svr) +{ + Ecore_DBus_Message *msg = calloc(1, sizeof(Ecore_DBus_Message)); + + msg->ref_server = svr; + msg->body_fields = NULL; + msg->header_fields = NULL; + msg->hpos = 0; + msg->bpos = 0; + msg->header = NULL; + msg->body = NULL; + msg->hlength = 0; + msg->blength = 0; + return msg; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_new_field(Ecore_DBus_Data_Type type, unsigned int offset) +{ + Ecore_DBus_Message_Field *f; + + f = malloc(sizeof(Ecore_DBus_Message_Field)); + f->offset = offset; + f->type = type; + f->count = 0; + return f; +} + +void +_ecore_dbus_message_free(void *data, void *ev) +{ + Ecore_DBus_Message *msg = ev; + Ecore_Oldlist *l = (Ecore_Oldlist *) msg->body_fields; + Ecore_Oldlist *next; + + while (l) + { + next = l->next; + free(l); + l = next; + } + l = (Ecore_Oldlist *) msg->header_fields; + while (l) + { + next = l->next; + free(l); + l = next; + } + free(msg->header); + free(msg->body); + free(msg); +} + +/* signature functions */ +/***********************/ + +/* marshal functions */ +/*********************/ + +/* cambiar todos los *msg por char** asi se podra cambiar el puntero sin problemas */ +/* agregarle el parametro de signature por si se quiere q agregue una variable al signature */ +/* y pasarle la lista de campos por si pone el argumento en la lista del header o del body */ + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_byte(unsigned char **buf, unsigned int *old_length, + unsigned char c) +{ + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_increase_length(buf, *old_length + 1); // increase the length + 1, old_length changed + _ecore_dbus_message_append_byte(*buf + *old_length, ECORE_DBUS_DATA_TYPE_BYTE); // append the data type + *old_length += 1; + _ecore_dbus_message_increase_length(buf, *old_length + 1); // increase the length + 1, old_length changed + _ecore_dbus_message_append_byte(*buf + *old_length, c); // append c at cur_length + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_BYTE, *old_length); // create field + *old_length += 1; + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_uint32(unsigned char **buf, + unsigned int *old_length, + unsigned long int i) +{ + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_increase_length(buf, *old_length + 1); // increase the length + 1, old_length changed + _ecore_dbus_message_append_byte(*buf + *old_length, ECORE_DBUS_DATA_TYPE_UINT32); // append the data type + *old_length += 1; + _ecore_dbus_message_4byte_padding(buf, old_length); + _ecore_dbus_message_increase_length(buf, *old_length + 4); + _ecore_dbus_message_append_uint32(*buf + *old_length, i); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_UINT32, *old_length); + *old_length += 4; + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_path(unsigned char **buf, unsigned int *old_length, + unsigned char *str) +{ + int str_len; + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_increase_length(buf, *old_length + 1); // increase the length + 1, old_length changed + _ecore_dbus_message_append_byte(*buf + *old_length, ECORE_DBUS_DATA_TYPE_OBJECT_PATH); // append the data type + *old_length += 1; + + str_len = strlen((char *)str); + _ecore_dbus_message_4byte_padding(buf, old_length); + _ecore_dbus_message_increase_length(buf, *old_length + 4); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_OBJECT_PATH, + *old_length); + _ecore_dbus_message_append_uint32(*buf + *old_length, str_len); + *old_length += 4; + _ecore_dbus_message_increase_length(buf, *old_length + str_len + 1); // for the \n + _ecore_dbus_message_append_nbytes(*buf + *old_length, str, str_len + 1); // append all the string including \n + *old_length += str_len + 1; + + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_string(unsigned char **buf, + unsigned int *old_length, unsigned char *str) +{ + int str_len; + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_increase_length(buf, *old_length + 1); // increase the length + 1, new_length changed + _ecore_dbus_message_append_byte(*buf + *old_length, ECORE_DBUS_DATA_TYPE_STRING); // append the data type + *old_length += 1; // old_length = new_length + + str_len = strlen((char *)str); + _ecore_dbus_message_4byte_padding(buf, old_length); + _ecore_dbus_message_increase_length(buf, *old_length + 4); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_STRING, *old_length); + _ecore_dbus_message_append_uint32(*buf + *old_length, str_len); + *old_length += 4; + _ecore_dbus_message_increase_length(buf, *old_length + str_len + 1); // for the \n + _ecore_dbus_message_append_nbytes(*buf + *old_length, str, str_len + 1); // append all the string including \n + *old_length += str_len + 1; + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_array(unsigned char **msg, unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_8byte_padding(msg, old_length); + _ecore_dbus_message_increase_length(msg, *old_length + 4); // for the array length value + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_ARRAY, *old_length); + *old_length += 4; + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_data(unsigned char **buf, unsigned int *old_length, + Ecore_DBus_Data_Type type, void *data) +{ + Ecore_DBus_Message_Field *f = NULL; + + switch (type) + { + case ECORE_DBUS_DATA_TYPE_UINT32: + f = _ecore_dbus_message_marshal_uint32(buf, old_length, + *(unsigned long *)data); + break; + case ECORE_DBUS_DATA_TYPE_STRING: + f = _ecore_dbus_message_marshal_string(buf, old_length, + (unsigned char *)data); + break; + case ECORE_DBUS_DATA_TYPE_OBJECT_PATH: + f = _ecore_dbus_message_marshal_path(buf, old_length, + (unsigned char *)data); + break; + case ECORE_DBUS_DATA_TYPE_INVALID: + case ECORE_DBUS_DATA_TYPE_BYTE: + case ECORE_DBUS_DATA_TYPE_BOOLEAN: + case ECORE_DBUS_DATA_TYPE_INT32: + case ECORE_DBUS_DATA_TYPE_INT64: + case ECORE_DBUS_DATA_TYPE_UINT64: + case ECORE_DBUS_DATA_TYPE_DOUBLE: + case ECORE_DBUS_DATA_TYPE_CUSTOM: + case ECORE_DBUS_DATA_TYPE_ARRAY: + case ECORE_DBUS_DATA_TYPE_DICT: + default: + printf("[ecore_dbus] unknown/unhandled data type %c\n", type); + break; + } + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_marshal_custom_header(unsigned char **buf, + unsigned int *old_length, + unsigned int code, + Ecore_DBus_Data_Type type, void *data) +{ + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_increase_length(buf, *old_length + 1); // increase the length + 1, old_length changed + _ecore_dbus_message_append_byte(*buf + *old_length, code); // append header field name at cur_length + *old_length += 1; + f = _ecore_dbus_message_marshal_data(buf, old_length, type, data); // marshal header field data + f->hfield = code; + return f; +} + +/* unmarshal functions */ +/***********************/ + +Ecore_DBus_Message_Field * +_ecore_dbus_message_unmarshal_int32(unsigned char *buf, + unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_skip_4byte_padding(old_length); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_INT32, *old_length); + *old_length += 4; + return f; + +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_unmarshal_uint32(unsigned char *buf, + unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f; + + _ecore_dbus_message_skip_4byte_padding(old_length); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_UINT32, *old_length); + *old_length += 4; + return f; + +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_unmarshal_string(unsigned char *buf, + unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f; + unsigned long str_len; + + _ecore_dbus_message_skip_4byte_padding(old_length); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_STRING, *old_length); + str_len = _ecore_dbus_message_read_uint32(buf + *old_length); + *old_length += 4; + *old_length += str_len + 1; + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_unmarshal_path(unsigned char *buf, unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f; + unsigned long str_len; + + _ecore_dbus_message_skip_4byte_padding(old_length); + f = _ecore_dbus_message_new_field(ECORE_DBUS_DATA_TYPE_OBJECT_PATH, + *old_length); + str_len = _ecore_dbus_message_read_uint32(buf + *old_length); + *old_length += 4; + *old_length += str_len + 1; + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_unmarshal_data(unsigned char *buf, unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f = NULL; + unsigned char type = _ecore_dbus_message_read_byte(buf + *old_length); + + *old_length += 1; + switch (type) + { + case ECORE_DBUS_DATA_TYPE_INT32: + f = _ecore_dbus_message_unmarshal_int32(buf, old_length); + break; + case ECORE_DBUS_DATA_TYPE_UINT32: + f = _ecore_dbus_message_unmarshal_uint32(buf, old_length); + break; + case ECORE_DBUS_DATA_TYPE_STRING: + f = _ecore_dbus_message_unmarshal_string(buf, old_length); + break; + case ECORE_DBUS_DATA_TYPE_OBJECT_PATH: + f = _ecore_dbus_message_unmarshal_path(buf, old_length); + break; + case ECORE_DBUS_DATA_TYPE_BYTE: + case ECORE_DBUS_DATA_TYPE_BOOLEAN: + case ECORE_DBUS_DATA_TYPE_INT64: + case ECORE_DBUS_DATA_TYPE_UINT64: + case ECORE_DBUS_DATA_TYPE_DOUBLE: + case ECORE_DBUS_DATA_TYPE_CUSTOM: + case ECORE_DBUS_DATA_TYPE_ARRAY: + case ECORE_DBUS_DATA_TYPE_DICT: + case ECORE_DBUS_DATA_TYPE_INVALID: + default: + printf("[ecore_dbus] unknown/unhandled data type %c\n", type); + break; + } + return f; +} + +Ecore_DBus_Message_Field * +_ecore_dbus_message_unmarshal_custom_header(unsigned char *buf, + unsigned int *old_length) +{ + Ecore_DBus_Message_Field *f; + unsigned int code; + + code = _ecore_dbus_message_read_byte(buf + *old_length); // get header field name at cur_length + *old_length += 1; + f = _ecore_dbus_message_unmarshal_data(buf, old_length); // unmarshal header field data + f->hfield = code; + return f; +} + +Ecore_DBus_Message * +_ecore_dbus_message_unmarshal(Ecore_DBus_Server * svr, unsigned char *message) +{ + Ecore_DBus_Message_Field *f; + + /* init */ + /********/ + Ecore_DBus_Message *msg = _ecore_dbus_message_new(svr); + + printf("[ecore_dbus] unmarshaling\n"); + /* message header */ + /******************/ + /* common fields */ + msg->byte_order = *(message + 0); + msg->type = *(message + 1); + msg->flags = *(message + 2); + msg->protocol = *(message + 3); + msg->hlength = *(unsigned long *)(message + 4); + msg->blength = *(unsigned long *)(message + 8); + msg->serial = *(unsigned long *)(message + 12); + if (msg->type == ECORE_DBUS_MESSAGE_TYPE_INVALID) + { + printf("[ecore_dbus] message type invalid\n"); + return NULL; + } + /* memcpy the header part */ + _ecore_dbus_message_increase_length(&msg->header, msg->hlength); + _ecore_dbus_message_append_nbytes(msg->header, message, msg->hlength); + msg->hpos += 16; + /* custom fields */ + while ((msg->hpos + 8 - (msg->hpos % 8)) < msg->hlength) + { + f = _ecore_dbus_message_unmarshal_custom_header(message, &msg->hpos); + msg->header_fields = _ecore_list_append(msg->header_fields, f); + } + msg->hpos = msg->hlength; + /* message body */ + /****************/ + message += msg->hlength; + _ecore_dbus_message_increase_length(&msg->body, msg->blength); + _ecore_dbus_message_append_nbytes(msg->body, message, msg->blength); + while (msg->bpos < msg->blength) + { + f = _ecore_dbus_message_unmarshal_data(message, &msg->bpos); + msg->body_fields = _ecore_list_append(msg->body_fields, f); + + } + return msg; +} + +/* header functions */ +/********************/ +void +_ecore_dbus_message_common_header(Ecore_DBus_Message * msg, int type, int flags) +{ + _ecore_dbus_message_increase_lengthz(&msg->header, msg->hpos, 16); // the body,header length arent filled only alloc + msg->header[0] = msg->byte_order = 'l'; // endiannes (1) + msg->header[1] = msg->type = (char)type; // type (1) + msg->header[2] = msg->flags = 0x0; // flags (1) 0x1 = no reply expected, 0x2 auto activiation + msg->header[3] = msg->protocol = 0x0; // protocol (1) + msg->ref_server->cnt_msg++; // autoincrement the client_serial (0 is invalid) + *(msg->header + 12) = msg->serial = msg->ref_server->cnt_msg; + msg->hpos = 16; +} + +void * +_ecore_dbus_get_field(unsigned char *buf, Ecore_DBus_Message_Field * f) +{ + switch (f->type) + { + case ECORE_DBUS_DATA_TYPE_INT32: + case ECORE_DBUS_DATA_TYPE_UINT32: + case ECORE_DBUS_DATA_TYPE_BYTE: + case ECORE_DBUS_DATA_TYPE_BOOLEAN: + case ECORE_DBUS_DATA_TYPE_INT64: + case ECORE_DBUS_DATA_TYPE_UINT64: + case ECORE_DBUS_DATA_TYPE_DOUBLE: + return buf + f->offset; + break; + case ECORE_DBUS_DATA_TYPE_STRING: + case ECORE_DBUS_DATA_TYPE_OBJECT_PATH: + return buf + f->offset + 4; + break; + case ECORE_DBUS_DATA_TYPE_CUSTOM: + case ECORE_DBUS_DATA_TYPE_ARRAY: + case ECORE_DBUS_DATA_TYPE_DICT: + case ECORE_DBUS_DATA_TYPE_INVALID: + default: + printf("[ecore_dbus] unknown/unhandled data type %c\n", f->type); + break; + + } + return NULL; +} + +void * +ecore_dbus_get_body_field(Ecore_DBus_Message * m, Ecore_DBus_Message_Field * mf, + unsigned int pos) +{ + Ecore_Oldlist *l, *list; + + list = (Ecore_Oldlist *) mf; + unsigned int i = 0; + + for (l = list; l; l = l->next) + { + if (i == pos) + return _ecore_dbus_get_field(m->body, + (Ecore_DBus_Message_Field *) l); + i++; + } + return NULL; +} + +void * +ecore_dbus_get_header_field(Ecore_DBus_Message * m, + Ecore_DBus_Message_Field * mf, + Ecore_DBus_Message_Header_Field hft) +{ + Ecore_Oldlist *l, *list; + + list = (Ecore_Oldlist *) mf; + for (l = list; l; l = l->next) + if (((Ecore_DBus_Message_Field *) l)->hfield == hft) + return _ecore_dbus_get_field(m->header, + (Ecore_DBus_Message_Field *) l); + return NULL; +} + +/* printing functions */ +/**********************/ +Ecore_Oldlist * +_ecore_dbus_message_print_field(Ecore_Oldlist * l, unsigned char *buf) +{ + int i; + Ecore_DBus_Message_Field *f; + + f = (Ecore_DBus_Message_Field *) l; + switch (f->type) + { + case ECORE_DBUS_DATA_TYPE_BYTE: + printf + ("[ecore_dbus] field BYTE : value offset = %d value = %d\n", + f->offset, (char)*(buf + f->offset)); + break; + case ECORE_DBUS_DATA_TYPE_OBJECT_PATH: + printf + ("[ecore_dbus] field PATH : value offset = %d length = %d value = %s\n", + f->offset, *(buf + f->offset), (buf + f->offset + 4)); + break; + case ECORE_DBUS_DATA_TYPE_STRING: + printf + ("[ecore_dbus] field STRING : value offset = %d length = %d value = %s\n", + f->offset, *(buf + f->offset), (buf + f->offset + 4)); + break; + case ECORE_DBUS_DATA_TYPE_INT32: + printf + ("[ecore_dbus] field INT32 : value offset = %d value = %ld\n", + f->offset, (long int)*(buf + f->offset)); + break; + case ECORE_DBUS_DATA_TYPE_UINT32: + printf + ("[ecore_dbus] field UINT32 : value offset = %d value = %lu\n", + f->offset, (unsigned long int)*(buf + f->offset)); + break; + case ECORE_DBUS_DATA_TYPE_ARRAY: + printf + ("[ecore_dbus] field ARRAY : value offset = %d length = %lu elements = %u\n", + f->offset, *(unsigned long int *)(buf + f->offset), f->count); + printf("[ecore_dbus] * ARRAY elements begin *\n"); + l = l->next; + for (i = 0; i < f->count; i++) + l = _ecore_dbus_message_print_field(l, buf); + printf("[ecore_dbus] * ARRAY elements end *\n"); + return l; + break; + default: + printf("[ecore_dbus] field !UNKNOWN! : %c\n", f->type); + break; + } + return l->next; +} + +Ecore_Oldlist * +_ecore_dbus_message_print_header_field(Ecore_Oldlist * l, unsigned char *buf) +{ + static const char *header_fields[] = + { "INVALID", "PATH", "INTERFACE", "MEMBER", "ERROR_NAME", "REPLY_SERIAL", +"DESTINATION", "SERIAL", "SIGNATURE" }; + Ecore_DBus_Message_Field *f; + + f = (Ecore_DBus_Message_Field *) l; + printf("[ecore_dbus] header field %s ", header_fields[f->hfield]); + l = _ecore_dbus_message_print_field(l, buf); + return l; +} + +void +_ecore_dbus_message_print_fields(Ecore_DBus_Message_Field * f) +{ + int i = 0; + Ecore_Oldlist *l; + + l = (Ecore_Oldlist *) f; + while (l) + { + printf("%d\n", i); + l = l->next; + i++; + } + +} + +void +_ecore_dbus_message_print_raw(unsigned char *msg, unsigned int msg_len) +{ + int i; + + printf("[ecore_dbus] raw message:\n"); + for (i = 0; i < msg_len; i++) + { + if (msg[i] == 0) + printf(","); + else if (msg[i] < 21) + printf("*"); + else + printf("%c", msg[i]); + } + printf("\n"); + printf("[ecore_dbus] end raw message\n"); +} + +void +ecore_dbus_message_print(Ecore_DBus_Message * msg) +{ + Ecore_Oldlist *list; + static const char *msg_type[] = + { "INVALID", "METHOD_CALL", "METHOD_RETURN", "ERROR", "SIGNAL" }; + printf("[ecore_dbus] per field message:\n"); + printf("[ecore_dbus] header fields:\n"); + /* header common fields */ + printf("[ecore_dbus] header endianess : %c\n", msg->byte_order); + printf("[ecore_dbus] header type : %s\n", msg_type[msg->type]); + printf("[ecore_dbus] header flags : %c\n", msg->flags + 48); + printf("[ecore_dbus] header protocol : %c\n", msg->protocol + 48); + printf("[ecore_dbus] header hlength : %u\n", + *(unsigned int *)(msg->header + 4)); + printf("[ecore_dbus] header blength : %lu\n", msg->blength); + printf("[ecore_dbus] header serial : %lu\n", msg->serial); + + /* header custom fields */ + list = (Ecore_Oldlist *) msg->header_fields; + while (list) + { + list = _ecore_dbus_message_print_header_field(list, msg->header); + } + /* body fields */ + printf("[ecore_dbus] body fields:\n"); + list = (Ecore_Oldlist *) msg->body_fields; + while (list) + { + list = _ecore_dbus_message_print_field(list, msg->body); + } + printf("[ecore_dbus] end per field message\n"); + +} + +/* message type functions */ +/**************************/ +/* podria retornar el id del mensaje, para asi saber las respuestas y poderlas referenciar en el cliente */ +/* la idea aca seria hacer una funcion q llame metodos remotos, or ej: ("org.freedesktop.DBus", "/org/freedesktop/DBus","org.freedesktop.DBus","AddMatch","%s",rule);*/ +/* el parsing de los argumentos a la funcion podrian ser similares al printf s = string, d = int, f = float etc */ + +unsigned int +ecore_dbus_message_new_method_call(Ecore_DBus_Server * svr, char *service, + char *path, char *interface, char *method, + char *fmt, ...) +{ + va_list ap; + + Ecore_DBus_Message_Field *f; + + /* init message */ + Ecore_DBus_Message *msg = _ecore_dbus_message_new(svr); + + /* common header */ + _ecore_dbus_message_common_header(msg, ECORE_DBUS_MESSAGE_TYPE_METHOD_CALL, + 0); + /* custom header */ + if (path) + { + f = _ecore_dbus_message_marshal_custom_header(&msg->header, &msg->hpos, + 1, + ECORE_DBUS_DATA_TYPE_OBJECT_PATH, + path); + msg->header_fields = _ecore_list_append(msg->header_fields, f); + } + + if (interface) + { + f = _ecore_dbus_message_marshal_custom_header(&msg->header, &msg->hpos, + 2, + ECORE_DBUS_DATA_TYPE_STRING, + interface); + msg->header_fields = _ecore_list_append(msg->header_fields, f); + } + if (method) + { + f = _ecore_dbus_message_marshal_custom_header(&msg->header, &msg->hpos, + 3, + ECORE_DBUS_DATA_TYPE_STRING, + method); + msg->header_fields = _ecore_list_append(msg->header_fields, f); + } + if (service) + { + f = _ecore_dbus_message_marshal_custom_header(&msg->header, &msg->hpos, + 6, + ECORE_DBUS_DATA_TYPE_STRING, + service); + msg->header_fields = _ecore_list_append(msg->header_fields, f); + } + if (fmt) + { + f = _ecore_dbus_message_marshal_custom_header(&msg->header, &msg->hpos, + 8, + ECORE_DBUS_DATA_TYPE_STRING, + fmt); + msg->header_fields = _ecore_list_append(msg->header_fields, f); + } + _ecore_dbus_message_8byte_padding(&msg->header, &msg->hpos); + /* header length */ + *(msg->header + 4) = msg->hlength = msg->hpos; + /* message body */ + va_start(ap, fmt); + while (*fmt) + { + switch (*fmt) + { + case ECORE_DBUS_DATA_TYPE_UINT32: + f = _ecore_dbus_message_marshal_uint32(&msg->body, &msg->bpos, + va_arg(ap, unsigned long)); + msg->body_fields = _ecore_list_append(msg->body_fields, f); + break; + case ECORE_DBUS_DATA_TYPE_STRING: + f = _ecore_dbus_message_marshal_string(&msg->body, &msg->bpos, + (unsigned char *)va_arg(ap, char *)); + msg->body_fields = _ecore_list_append(msg->body_fields, f); + break; + case ECORE_DBUS_DATA_TYPE_OBJECT_PATH: + f = _ecore_dbus_message_marshal_path(&msg->body, &msg->bpos, + (unsigned char *)va_arg(ap, char *)); + msg->body_fields = _ecore_list_append(msg->body_fields, f); + break; + case ECORE_DBUS_DATA_TYPE_INVALID: + case ECORE_DBUS_DATA_TYPE_BYTE: + case ECORE_DBUS_DATA_TYPE_BOOLEAN: + case ECORE_DBUS_DATA_TYPE_INT32: + case ECORE_DBUS_DATA_TYPE_INT64: + case ECORE_DBUS_DATA_TYPE_UINT64: + case ECORE_DBUS_DATA_TYPE_DOUBLE: + case ECORE_DBUS_DATA_TYPE_CUSTOM: + case ECORE_DBUS_DATA_TYPE_ARRAY: + case ECORE_DBUS_DATA_TYPE_DICT: + default: + printf("[ecore_dbus] unknown/unhandled data type %c\n", *fmt); + break; + } + *fmt++; + } + va_end(ap); + *(unsigned int *)(msg->header + 8) = msg->blength = msg->bpos; + /* show message */ + /*ecore_dbus_message_print(msg); + * _ecore_dbus_message_print_raw(msg->header,msg->hlength); + * _ecore_dbus_message_print_raw(msg->body,msg->blength); */ + /* send message */ + ecore_dbus_server_send(svr, (char *)msg->header, msg->hlength); + if (msg->body) + ecore_dbus_server_send(svr, (char *)msg->body, msg->blength); + /* free data TODO free the list of fields */ + /*for(i=0; i<8; i++) + * free(msg->header_fields[i]); + * free(msg->buf); + * free(msg); */ + return msg->serial; +} + +/*******************/ +/* ecore_dbus_auth */ +/*******************/ + +static char *_ecore_dbus_getuid(void); +static char *_ecore_dbus_hex_encode(char *src_str); + +/* helper functions */ +static char * +_ecore_dbus_getuid(void) +{ + /* this calculation is from comp.lang.c faq */ +#define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ + int len; + char *uid; + char *tmp; + + tmp = (char *)malloc(MAX_LONG_LEN); + len = snprintf(tmp, MAX_LONG_LEN, "%ld", (long) getuid()); + uid = (char *)malloc(len + 1); + uid = memcpy(uid, tmp, len); + uid[len] = '\0'; + + free(tmp); + return uid; +} + +/* encodes a string into a string of hex values */ +/* each byte is two hex digits */ +static char * +_ecore_dbus_hex_encode(char *src_str) +{ + const char hexdigits[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' + }; + char *enc_str; + char *p; + char *end; + int len; + int i = 0; + + len = strlen(src_str); + p = src_str; + end = p + len; + + enc_str = malloc(2 * len + 1); + while (p != end) + { + enc_str[i] = hexdigits[(*p >> 4)]; + i++; + enc_str[i] = hexdigits[(*p & 0x0f)]; + i++; + p++; + } + enc_str[i] = '\0'; + return enc_str; +} + +unsigned char * +_ecore_dbus_auth_external(void *data) +{ + char *uid, *enc_uid, *msg; + + uid = _ecore_dbus_getuid(); + enc_uid = _ecore_dbus_hex_encode(uid); + free(uid); + msg = malloc(strlen(enc_uid) + 17); + sprintf(msg, "AUTH EXTERNAL %s\r\n", enc_uid); + free(enc_uid); + return (unsigned char *)msg; +} + +/*****************************/ +/* main ecore_dbus functions */ +/*****************************/ + +int ECORE_DBUS_EVENT_CLIENT_ADD = 0; +int ECORE_DBUS_EVENT_CLIENT_DEL = 0; +int ECORE_DBUS_EVENT_SERVER_ADD = 0; +int ECORE_DBUS_EVENT_SERVER_DEL = 0; +int ECORE_DBUS_EVENT_CLIENT_DATA = 0; +int ECORE_DBUS_EVENT_SERVER_DATA = 0; + +static const Ecore_DBus_Auth auths[] = { + {"EXTERNAL", 1, {_ecore_dbus_auth_external, NULL, NULL, NULL, NULL}}, + {"MAGIC_COOKIE", 0, {NULL, NULL, NULL, NULL, NULL}}, + {"DBUS_COOKIE_SHA1", 0, {NULL, NULL, NULL, NULL, NULL}}, + {"KERBEROS_V4", 0, {NULL, NULL, NULL, NULL, NULL}}, + {"SKEY", 0, {NULL, NULL, NULL, NULL, NULL}}, +}; + +static int init_count = 0; +static Ecore_List *servers = NULL; + +static int _ecore_dbus_event_client_add(void *data, int ev_type, + void *ev); +static int _ecore_dbus_event_client_del(void *data, int ev_type, + void *ev); +static int _ecore_dbus_event_server_add(void *data, int ev_type, + void *ev); +static int _ecore_dbus_event_server_del(void *data, int ev_type, + void *ev); +static int _ecore_dbus_event_client_data(void *data, int ev_type, + void *ev); +static int _ecore_dbus_event_server_data(void *data, int ev_type, + void *ev); +/* helpers */ +void _ecore_dbus_message_free(void *data, void *ev); + +int +ecore_dbus_init(void) +{ + if (!init_count) + ecore_con_init(); + init_count++; + if (!ECORE_DBUS_EVENT_CLIENT_ADD) + { + ECORE_DBUS_EVENT_CLIENT_ADD = ecore_event_type_new(); + ECORE_DBUS_EVENT_CLIENT_DEL = ecore_event_type_new(); + ECORE_DBUS_EVENT_SERVER_ADD = ecore_event_type_new(); + ECORE_DBUS_EVENT_SERVER_DEL = ecore_event_type_new(); + ECORE_DBUS_EVENT_CLIENT_DATA = ecore_event_type_new(); + ECORE_DBUS_EVENT_SERVER_DATA = ecore_event_type_new(); + + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, + _ecore_dbus_event_client_add, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, + _ecore_dbus_event_client_del, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, + _ecore_dbus_event_server_add, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, + _ecore_dbus_event_server_del, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, + _ecore_dbus_event_client_data, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, + _ecore_dbus_event_server_data, NULL); + } + return init_count; +} + +Ecore_DBus_Server * +ecore_dbus_server_connect(Ecore_DBus_Type compl_type, char *name, int port, + const void *data) +{ + /* TODO */ + /* se tiene q conectar por direccion (unix socket path) */ + /* o por BUS directo */ + + Ecore_DBus_Server *svr; + Ecore_DBus_Type type; + Ecore_Con_Type extra = 0; + + svr = calloc(1, sizeof(Ecore_DBus_Server)); + if (!svr) + return NULL; + type = compl_type; + switch (type) + { + case ECORE_DBUS_BUS_SESSION: + svr->server = + ecore_con_server_connect(ECORE_CON_LOCAL_USER | extra, name, port, + svr); + break; + case ECORE_DBUS_BUS_SYSTEM: + svr->server = + ecore_con_server_connect(ECORE_CON_LOCAL_USER | extra, name, port, + svr); + break; + + default: + free(svr); + return NULL; + } + if (!svr->server) + { + printf("no hay servidor\n"); + free(svr); + return NULL; + } + svr->authenticated = 0; + svr->cnt_msg = 0; + svr->auth_type = -1; + svr->auth_type_transaction = 0; + servers = _ecore_list_append(servers, svr); + + return svr; +} + +int +ecore_dbus_server_send(Ecore_DBus_Server * svr, char *command, int length) +{ + int ret; + + ret = ecore_con_server_send(svr->server, command, length); + printf + ("[ecore_dbus] ecore_dbus_server: %p ecore_con_server: %p sent %d of %d bytes\n", + svr, svr->server, ret, length); + return ret; +} + +/* private functions */ +static int +_ecore_dbus_event_client_add(void *data, int ev_type, void *ev) +{ + printf("CLIENT ADDED \n"); + printf("this line should appear\n"); + return 1; +} + +static int +_ecore_dbus_event_client_del(void *data, int ev_type, void *ev) +{ + return 0; +} + +static int +_ecore_dbus_event_server_add(void *data, int ev_type, void *ev) +{ + + Ecore_DBus_Event_Server_Add *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(e->server))) + return 1; + { + Ecore_DBus_Server *svr; + + svr = ecore_con_server_data_get(e->server); + ecore_dbus_server_send(svr, "\0", 1); + ecore_dbus_server_send(svr, "AUTH\r\n", 6); + printf("[ecore_dbus] begining auth process\n"); + } + return 0; +} + +static int +_ecore_dbus_event_server_del(void *udata, int ev_type, void *ev) +{ + Ecore_Con_Event_Server_Del *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(e->server))) + return 1; + { + Ecore_DBus_Server *svr; + + svr = ecore_con_server_data_get(e->server); + { + Ecore_DBus_Event_Server_Del *e2; + + e2 = calloc(1, sizeof(Ecore_DBus_Event_Server_Del)); + if (e2) + { + e2->server = svr; + ecore_event_add(ECORE_DBUS_EVENT_SERVER_DEL, e2, NULL, NULL); + } + } + } + return 0; +} + +static int +_ecore_dbus_event_client_data(void *udata, int ev_type, void *ev) +{ + printf("CLIENT DATA"); + return 1; +} + +static int +_ecore_dbus_event_server_data(void *udata, int ev_type, void *ev) +{ + Ecore_Con_Event_Server_Data *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(e->server))) + return 1; + + { + Ecore_DBus_Server *svr; + Ecore_DBus_Event_Server_Add *svr_add; + + svr = ecore_con_server_data_get(e->server); + + /* authentication protocol */ + /***************************/ + if (!svr->authenticated) + { + const Ecore_DBus_Auth *auth; + Ecore_DBus_Auth_Transaction trans; + + if (!strncmp(e->data, "OK", 2)) + { + printf("[ecore_dbus] auth type %s successful\n", + auths[svr->auth_type].name); + ecore_dbus_server_send(svr, "BEGIN\r\n", 7); + svr->authenticated = 1; + svr_add = malloc(sizeof(Ecore_DBus_Event_Server_Add)); + svr_add->server = svr; + ecore_event_add(ECORE_DBUS_EVENT_SERVER_ADD, svr_add, NULL, + NULL); + } + if (!strncmp(e->data, "DATA", 4)) + { + printf("[ecore_dbus] requering data (unaivable)\n"); + } + if (!strncmp(e->data, "ERROR", 5)) + { + printf("[ecore_dbus] auth process error\n"); + } + if (!strncmp(e->data, "REJECTED", 8)) + { + unsigned char *msg; + + if (svr->auth_type >= 0) + printf("[ecore_dbus] auth type %s rejected\n", + auths[svr->auth_type].name); + svr->auth_type++; + auth = &auths[svr->auth_type]; + trans = auth->transactions[0]; + printf("[ecore_dbus] auth type %s started\n", auth->name); + msg = trans(NULL); + ecore_dbus_server_send(svr, (char *)msg, strlen((char *)msg)); + free(msg); + + } + } + /* message protocol */ + /********************/ + else + { + Ecore_DBus_Message *msg; + unsigned int offset = 0; + + printf("[ecore_dbus] received server data, %d bytes\n", e->size); + while (e->size) + { + msg = _ecore_dbus_message_unmarshal(svr, e->data + offset); + if (msg == NULL) + break; + offset += msg->hlength + msg->blength; + e->size -= msg->hlength + msg->blength; + printf("[ecore_dbus] dbus message length %lu bytes, still %d\n", + msg->hlength + msg->blength, e->size); + /*ecore_dbus_message_print(msg); */ + ecore_event_add(ECORE_DBUS_EVENT_SERVER_DATA, msg, + _ecore_dbus_message_free, NULL); + + } + } + } + return 1; +} diff --git a/ecore/src/lib/ecore_dbus/ecore_dbus_private.h b/ecore/src/lib/ecore_dbus/ecore_dbus_private.h new file mode 100644 index 0000000..f9e1a8e --- /dev/null +++ b/ecore/src/lib/ecore_dbus/ecore_dbus_private.h @@ -0,0 +1,56 @@ +#ifndef _ECORE_DBUS_PRIVATE_H +#define _ECORE_DBUS_PRIVATE_H + +struct _Ecore_DBus_Client +{ + Ecore_DBus_Client *client; +}; + +struct _Ecore_DBus_Server +{ + Ecore_List __list_data; + Ecore_Con_Server *server; + Ecore_DBus_Client *clients; + /* unsigned char *buf; */ + /* int buf_size; */ + unsigned int cnt_msg; + Ecore_List *msg_queue; + /* void *data;*/ + unsigned int authenticated; + int auth_type; + unsigned int auth_type_transaction; +}; + +/* Errors */ +/* WARNING dont change order or ABI breaks. */ +#define DBUS_ERROR_FAILED "org.freedesktop.DBus.Error.Failed" +#define DBUS_ERROR_NO_MEMORY "org.freedesktop.DBus.Error.NoMemory" +#define DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND "org.freedesktop.DBus.Error.ServiceNotFound" +#define DBUS_ERROR_SERVICE_DOES_NOT_EXIST "org.freedesktop.DBus.Error.ServiceDoesNotExist" +#define DBUS_ERROR_SERVICE_HAS_NO_OWNER "org.freedesktop.DBus.Error.ServiceHasNoOwner" +#define DBUS_ERROR_NO_REPLY "org.freedesktop.DBus.Error.NoReply" +#define DBUS_ERROR_IO_ERROR "org.freedesktop.DBus.Error.IOError" +#define DBUS_ERROR_BAD_ADDRESS "org.freedesktop.DBus.Error.BadAddress" +#define DBUS_ERROR_NOT_SUPPORTED "org.freedesktop.DBus.Error.NotSupported" +#define DBUS_ERROR_LIMITS_EXCEEDED "org.freedesktop.DBus.Error.LimitsExceeded" +#define DBUS_ERROR_ACCESS_DENIED "org.freedesktop.DBus.Error.AccessDenied" +#define DBUS_ERROR_AUTH_FAILED "org.freedesktop.DBus.Error.AuthFailed" +#define DBUS_ERROR_NO_SERVER "org.freedesktop.DBus.Error.NoServer" +#define DBUS_ERROR_TIMEOUT "org.freedesktop.DBus.Error.Timeout" +#define DBUS_ERROR_NO_NETWORK "org.freedesktop.DBus.Error.NoNetwork" +#define DBUS_ERROR_ADDRESS_IN_USE "org.freedesktop.DBus.Error.AddressInUse" +#define DBUS_ERROR_DISCONNECTED "org.freedesktop.DBus.Error.Disconnected" +#define DBUS_ERROR_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs" +#define DBUS_ERROR_FILE_NOT_FOUND "org.freedesktop.DBus.Error.FileNotFound" +#define DBUS_ERROR_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod" +#define DBUS_ERROR_TIMED_OUT "org.freedesktop.DBus.Error.TimedOut" +#define DBUS_ERROR_MATCH_RULE_NOT_FOUND "org.freedesktop.DBus.Error.MatchRuleNotFound" +#define DBUS_ERROR_MATCH_RULE_INVALID "org.freedesktop.DBus.Error.MatchRuleInvalid" +#define DBUS_ERROR_SPAWN_EXEC_FAILED "org.freedesktop.DBus.Error.Spawn.ExecFailed" +#define DBUS_ERROR_SPAWN_FORK_FAILED "org.freedesktop.DBus.Error.Spawn.ForkFailed" +#define DBUS_ERROR_SPAWN_CHILD_EXITED "org.freedesktop.DBus.Error.Spawn.ChildExited" +#define DBUS_ERROR_SPAWN_CHILD_SIGNALED "org.freedesktop.DBus.Error.Spawn.ChildSignaled" +#define DBUS_ERROR_SPAWN_FAILED "org.freedesktop.DBus.Error.Spawn.Failed" +#define DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN "org.freedesktop.DBus.Error.UnixProcessIdUnknown" + +#endif diff --git a/ecore/src/lib/ecore_evas/.cvsignore b/ecore/src/lib/ecore_evas/.cvsignore new file mode 100644 index 0000000..0bf42a4 --- /dev/null +++ b/ecore/src/lib/ecore_evas/.cvsignore @@ -0,0 +1,10 @@ +.deps +.libs +Ecore_Evas.h +Makefile +Makefile.in +ecore_evas.lo +ecore_evas_fb.lo +ecore_evas_x.lo +ecore_evas_buffer.lo +libecore_evas.la diff --git a/ecore/src/lib/ecore_evas/CVS/Entries b/ecore/src/lib/ecore_evas/CVS/Entries new file mode 100644 index 0000000..b0e1a5c --- /dev/null +++ b/ecore/src/lib/ecore_evas/CVS/Entries @@ -0,0 +1,9 @@ +/.cvsignore/1.3/Tue Feb 22 12:42:23 2005//THEAD +/Ecore_Evas.h/1.11/Thu Jul 7 03:33:17 2005//THEAD +/Makefile.am/1.11/Thu Mar 10 15:19:38 2005//THEAD +/ecore_evas.c/1.18/Sat Jan 8 18:40:31 2005//THEAD +/ecore_evas_private.h/1.12/Sat Jun 25 07:23:38 2005//THEAD +/ecore_evas_buffer.c/1.5/Mon Jul 25 17:01:56 2005//THEAD +/ecore_evas_fb.c/1.12/Mon Jul 25 17:01:56 2005//THEAD +/ecore_evas_x.c/1.50/Mon Jul 25 17:01:56 2005//THEAD +D diff --git a/ecore/src/lib/ecore_evas/CVS/Repository b/ecore/src/lib/ecore_evas/CVS/Repository new file mode 100644 index 0000000..d85de4a --- /dev/null +++ b/ecore/src/lib/ecore_evas/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_evas diff --git a/ecore/src/lib/ecore_evas/CVS/Root b/ecore/src/lib/ecore_evas/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_evas/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_evas/CVS/Tag b/ecore/src/lib/ecore_evas/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_evas/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_evas/Ecore_Evas.h b/ecore/src/lib/ecore_evas/Ecore_Evas.h new file mode 100644 index 0000000..108de52 --- /dev/null +++ b/ecore/src/lib/ecore_evas/Ecore_Evas.h @@ -0,0 +1,165 @@ +#ifndef _ECORE_EVAS_H +#define _ECORE_EVAS_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file Ecore_Evas.h + * @brief Evas wrapper functions + */ + +/* FIXME: + * to do soon: + * - iconfication api needs to work + * - maximization api nees to work + * - document all calls + * + * later: + * - buffer back-end that renders to an evas_image_object ??? + * - qt back-end ??? + * - dfb back-end ??? (dfb's threads make this REALLY HARD) + */ + +#include <Evas.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* these are dummy and just tell u what API levels ecore_evas supports - not if + * the actual support is compiled in. you need to query for that separately. + */ +#define HAVE_ECORE_EVAS_X 1 +#define HAVE_ECORE_EVAS_FB 1 +#define HAVE_ECORE_EVAS_GL 1 + +typedef enum +{ + ECORE_EVAS_ENGINE_SOFTWARE_X11, + ECORE_EVAS_ENGINE_SOFTWARE_FB, + ECORE_EVAS_ENGINE_GL_X11, + ECORE_EVAS_ENGINE_SOFTWARE_BUFFER +} Ecore_Evas_Engine_Type; + +#ifndef _ECORE_X_H +#define _ECORE_X_WINDOW_PREDEF +typedef unsigned int Ecore_X_Window; +#endif + +#ifndef _ECORE_EVAS_PRIVATE_H +/* basic data types */ +typedef void Ecore_Evas; +#endif + +/* module setup/shutdown calls */ + +EAPI int ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine); + +EAPI int ecore_evas_init(void); +EAPI int ecore_evas_shutdown(void); + +/* engine/target specific init calls */ +EAPI Ecore_Evas *ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h); +EAPI Ecore_X_Window ecore_evas_software_x11_window_get(Ecore_Evas *ee); +EAPI Ecore_X_Window ecore_evas_software_x11_subwindow_get(Ecore_Evas *ee); +EAPI void ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_software_x11_direct_resize_get(Ecore_Evas *ee); + +EAPI Ecore_Evas *ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, int x, int y, int w, int h); +EAPI Ecore_X_Window ecore_evas_gl_x11_window_get(Ecore_Evas *ee); +EAPI Ecore_X_Window ecore_evas_gl_x11_subwindow_get(Ecore_Evas *ee); +EAPI void ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_gl_x11_direct_resize_get(Ecore_Evas *ee); + +EAPI Ecore_Evas *ecore_evas_fb_new(char *disp_name, int rotation, int w, int h); + +EAPI Ecore_Evas *ecore_evas_buffer_new(int w, int h); +EAPI const int *ecore_evas_buffer_pixels_get(Ecore_Evas *ee); + +EAPI Evas_Object *ecore_evas_object_image_new(Ecore_Evas *ee_target); + +/* generic manipulation calls */ +EAPI void ecore_evas_free(Ecore_Evas *ee); +EAPI void *ecore_evas_data_get(Ecore_Evas *ee, const char *key); +EAPI void ecore_evas_data_set(Ecore_Evas *ee, const char *key, const void *data); +EAPI void ecore_evas_callback_resize_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_move_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_show_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_hide_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_destroy_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_focus_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_focus_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_mouse_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_mouse_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_pre_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI void ecore_evas_callback_post_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); +EAPI Evas *ecore_evas_get(Ecore_Evas *ee); +EAPI void ecore_evas_move(Ecore_Evas *ee, int x, int y); +EAPI void ecore_evas_resize(Ecore_Evas *ee, int w, int h); +EAPI void ecore_evas_move_resize(Ecore_Evas *ee, int x, int y, int w, int h); +EAPI void ecore_evas_geometry_get(Ecore_Evas *ee, int *x, int *y, int *w, int *h); +EAPI void ecore_evas_rotation_set(Ecore_Evas *ee, int rot); +EAPI int ecore_evas_rotation_get(Ecore_Evas *ee); +EAPI void ecore_evas_shaped_set(Ecore_Evas *ee, int shaped); +EAPI int ecore_evas_shaped_get(Ecore_Evas *ee); +EAPI void ecore_evas_show(Ecore_Evas *ee); +EAPI void ecore_evas_hide(Ecore_Evas *ee); +EAPI int ecore_evas_visibility_get(Ecore_Evas *ee); +EAPI void ecore_evas_raise(Ecore_Evas *ee); +EAPI void ecore_evas_lower(Ecore_Evas *ee); +EAPI void ecore_evas_title_set(Ecore_Evas *ee, const char *t); +EAPI const char *ecore_evas_title_get(Ecore_Evas *ee); +EAPI void ecore_evas_name_class_set(Ecore_Evas *ee, const char *n, const char *c); +EAPI void ecore_evas_name_class_get(Ecore_Evas *ee, const char **n, const char **c); +EAPI void ecore_evas_size_min_set(Ecore_Evas *ee, int w, int h); +EAPI void ecore_evas_size_min_get(Ecore_Evas *ee, int *w, int *h); +EAPI void ecore_evas_size_max_set(Ecore_Evas *ee, int w, int h); +EAPI void ecore_evas_size_max_get(Ecore_Evas *ee, int *w, int *h); +EAPI void ecore_evas_size_base_set(Ecore_Evas *ee, int w, int h); +EAPI void ecore_evas_size_base_get(Ecore_Evas *ee, int *w, int *h); +EAPI void ecore_evas_size_step_set(Ecore_Evas *ee, int w, int h); +EAPI void ecore_evas_size_step_get(Ecore_Evas *ee, int *w, int *h); +EAPI void ecore_evas_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y); +EAPI void ecore_evas_cursor_get(Ecore_Evas *ee, char **file, int *layer, int *hot_x, int *hot_y); +EAPI void ecore_evas_layer_set(Ecore_Evas *ee, int layer); +EAPI int ecore_evas_layer_get(Ecore_Evas *ee); +EAPI void ecore_evas_focus_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_focus_get(Ecore_Evas *ee); +EAPI void ecore_evas_iconified_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_iconified_get(Ecore_Evas *ee); +EAPI void ecore_evas_borderless_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_borderless_get(Ecore_Evas *ee); +EAPI void ecore_evas_override_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_override_get(Ecore_Evas *ee); +EAPI void ecore_evas_maximized_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_maximized_get(Ecore_Evas *ee); +EAPI void ecore_evas_fullscreen_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_fullscreen_get(Ecore_Evas *ee); +EAPI void ecore_evas_avoid_damage_set(Ecore_Evas *ee, int on); +EAPI int ecore_evas_avoid_damage_get(Ecore_Evas *ee); +EAPI void ecore_evas_withdrawn_set(Ecore_Evas *ee, int withdrawn); +EAPI int ecore_evas_withdrawn_get(Ecore_Evas *ee); +EAPI void ecore_evas_sticky_set(Ecore_Evas *ee, int sticky); +EAPI int ecore_evas_sticky_get(Ecore_Evas *ee); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_evas/Makefile.am b/ecore/src/lib/ecore_evas/Makefile.am new file mode 100644 index 0000000..a79da95 --- /dev/null +++ b/ecore/src/lib/ecore_evas/Makefile.am @@ -0,0 +1,69 @@ +MAINTAINERCLEANFILES = Makefile.in + +if BUILD_ECORE_X +ECORE_X_INC = -I$(top_srcdir)/src/lib/ecore_x +ECORE_X_LIB = $(top_builddir)/src/lib/ecore_x/libecore_x.la +ECORE_X_LDF = -L$(top_builddir)/src/lib/ecore_x/.libs +else +ECORE_X_INC = +ECORE_X_LIB = +ECORE_X_LDF = +endif + +if BUILD_ECORE_FB +ECORE_FB_INC = -I$(top_srcdir)/src/lib/ecore_fb +ECORE_FB_LIB = $(top_builddir)/src/lib/ecore_fb/libecore_fb.la +ECORE_FB_LDF = -L$(top_builddir)/src/lib/ecore_fb/.libs +else +ECORE_FB_INC = +ECORE_FB_LIB = +ECORE_FB_LDF = +endif + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_evas \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_evas \ +$(ECORE_X_INC) \ +$(ECORE_FB_INC) \ +@evas_cflags@ + +libecore_evas_la_LDFLAGS = -version-info 1:0:0 \ +$(ECORE_X_LDF) \ +$(ECORE_FB_LDF) \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_EVAS + +lib_LTLIBRARIES = libecore_evas.la +include_HEADERS = \ +Ecore_Evas.h + +libecore_evas_la_SOURCES = \ +ecore_evas.c \ +ecore_evas_private.h \ +ecore_evas_x.c \ +ecore_evas_fb.c \ +ecore_evas_buffer.c + +libecore_evas_la_LIBADD = \ +$(ECORE_X_LIB) \ +$(ECORE_FB_LIB) \ +$(top_builddir)/src/lib/ecore/libecore.la \ +@evas_libs@ + +libecore_evas_la_DEPENDENCIES = \ +$(ECORE_X_LIB) \ +$(ECORE_FB_LIB) \ +$(top_builddir)/src/lib/ecore/libecore.la + +endif + +EXTRA_DIST = \ +ecore_evas.c \ +ecore_evas_private.h \ +ecore_evas_x.c \ +ecore_evas_fb.c \ +ecore_evas_buffer.c + diff --git a/ecore/src/lib/ecore_evas/ecore_evas.c b/ecore/src/lib/ecore_evas/ecore_evas.c new file mode 100644 index 0000000..b6e57cd --- /dev/null +++ b/ecore/src/lib/ecore_evas/ecore_evas.c @@ -0,0 +1,1605 @@ +#include "config.h" +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_evas_private.h" +#include "Ecore_Evas.h" + +static int _ecore_evas_init_count = 0; + +/** + * Query if a particular renginering engine target has support + * @param engine The engine to check support for + * @return 1 if the particualr engine is supported, 0 if it is not + * + * Query if engine @param engine is supported by ecore_evas. 1 is returned if + * it is, and 0 is returned if it is not supported. + */ +int +ecore_evas_engine_type_supported_get(Ecore_Evas_Engine_Type engine) +{ + switch (engine) + { + case ECORE_EVAS_ENGINE_SOFTWARE_X11: +#ifdef BUILD_ECORE_X + return 1; +#else + return 0; +#endif + break; + case ECORE_EVAS_ENGINE_SOFTWARE_FB: +#ifdef BUILD_ECORE_EVAS_FB + return 1; +#else + return 0; +#endif + break; + case ECORE_EVAS_ENGINE_GL_X11: +#ifdef BUILD_ECORE_EVAS_GL + return 1; +#else + return 0; +#endif + break; + case ECORE_EVAS_ENGINE_SOFTWARE_BUFFER: +#ifdef BUILD_ECORE_EVAS_BUFFER + return 1; +#else + return 0; +#endif + break; + default: + return 0; + break; + }; + return 0; +} + +/** + * Init the Evas system. + * @return greater than 0 on success, 0 on failure + * + * Set up the Evas wrapper system. + */ +int +ecore_evas_init(void) +{ + if (_ecore_evas_init_count == 0) + evas_init (); + return ++_ecore_evas_init_count; +} + +/** + * Shut down the Evas system. + * @return 0 if ecore evas is fully shut down, or > 0 if it still needs to be shut down + * + * This closes the Evas system down. + */ +int +ecore_evas_shutdown(void) +{ + _ecore_evas_init_count--; + if (_ecore_evas_init_count == 0) + { +#ifdef BUILD_ECORE_X + while (_ecore_evas_x_shutdown()); +#endif +#ifdef BUILD_ECORE_EVAS_FB + while (_ecore_evas_fb_shutdown()); +#endif +#ifdef BUILD_ECORE_EVAS_BUFFER + while (_ecore_evas_buffer_shutdown()); +#endif + evas_shutdown(); + } + if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0; + return _ecore_evas_init_count; +} + +/** + * Free an Ecore_Evas + * @param ee The Ecore_Evas to free + * + * This frees up any memory used by the Ecore_Evas. + */ +void +ecore_evas_free(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_free"); + return; + } + ECORE_MAGIC_SET(ee, ECORE_MAGIC_NONE); + while (ee->sub_ecore_evas) + { + ecore_evas_free(ee->sub_ecore_evas->data); + } + if (ee->data) evas_hash_free(ee->data); + if (ee->driver) free(ee->driver); + if (ee->name) free(ee->name); + if (ee->prop.title) free(ee->prop.title); + if (ee->prop.name) free(ee->prop.name); + if (ee->prop.clas) free(ee->prop.clas); + if (ee->prop.cursor.file) free(ee->prop.cursor.file); + if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object); + if (ee->evas) evas_free(ee->evas); + ee->data = NULL; + ee->driver = NULL; + ee->name = NULL; + ee->prop.title = NULL; + ee->prop.name = NULL; + ee->prop.clas = NULL; + ee->prop.cursor.file = NULL; + ee->prop.cursor.object = NULL; + ee->evas = NULL; + if (ee->engine.func->fn_free) ee->engine.func->fn_free(ee); + free(ee); +} + +void * +ecore_evas_data_get(Ecore_Evas *ee, const char *key) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_data_get"); + return NULL; + } + + if (!key) return NULL; + + return evas_hash_find(ee->data, key); +} + +void +ecore_evas_data_set(Ecore_Evas *ee, const char *key, const void *data) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_data_set"); + return; + } + + if (!key) return; + + ee->data = evas_hash_del(ee->data, key, NULL); + ee->data = evas_hash_add(ee->data, key, data); +} + +#define IFC(_ee, _fn) if (_ee->engine.func->_fn) {_ee->engine.func->_fn +#define IFE return;} + +/** + * Set a callback for Ecore_Evas resize events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee is resized. + */ +void +ecore_evas_callback_resize_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_resize_set"); + return; + } + IFC(ee, fn_callback_resize_set) (ee, func); + IFE; + ee->func.fn_resize = func; +} + +/** + * Set a callback for Ecore_Evas move events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee is moved. + */ +void +ecore_evas_callback_move_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_move_set"); + return; + } + IFC(ee, fn_callback_move_set) (ee, func); + IFE; + ee->func.fn_move = func; +} + +/** + * Set a callback for Ecore_Evas show events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee is shown. + */ +void +ecore_evas_callback_show_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_show_set"); + return; + } + IFC(ee, fn_callback_show_set) (ee, func); + IFE; + ee->func.fn_show = func; +} + +/** + * Set a callback for Ecore_Evas hide events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee is hidden. + */ +void +ecore_evas_callback_hide_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_hide_set"); + return; + } + IFC(ee, fn_callback_hide_set) (ee, func); + IFE; + ee->func.fn_hide = func; +} + +/** + * Set a callback for Ecore_Evas delete request events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee gets a delete request. + */ +void +ecore_evas_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_delete_request_set"); + return; + } + IFC(ee, fn_callback_delete_request_set) (ee, func); + IFE; + ee->func.fn_delete_request = func; +} + +/** + * Set a callback for Ecore_Evas destroy events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee is destroyed. + */ +void +ecore_evas_callback_destroy_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_destroy_set"); + return; + } + IFC(ee, fn_callback_destroy_set) (ee, func); + IFE; + ee->func.fn_destroy = func; +} + +/** + * Set a callback for Ecore_Evas focus in events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee gets focus. + */ +void +ecore_evas_callback_focus_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_focus_in_set"); + return; + } + IFC(ee, fn_callback_focus_in_set) (ee, func); + IFE; + ee->func.fn_focus_in = func; +} + +/** + * Set a callback for Ecore_Evas focus out events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever @p ee loses focus. + */ +void +ecore_evas_callback_focus_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_focus_out_set"); + return; + } + IFC(ee, fn_callback_focus_out_set) (ee, func); + IFE; + ee->func.fn_focus_out = func; +} + +/** + * Set a callback for Ecore_Evas mouse in events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever the mouse enters @p ee. + */ +void +ecore_evas_callback_mouse_in_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_mouse_in_set"); + return; + } + IFC(ee, fn_callback_mouse_in_set) (ee, func); + IFE; + ee->func.fn_mouse_in = func; +} + +/** + * Set a callback for Ecore_Evas mouse out events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called whenever the mouse leaves @p ee. + */ +void +ecore_evas_callback_mouse_out_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_mouse_out_set"); + return; + } + IFC(ee, fn_callback_mouse_out_set) (ee, func); + IFE; + ee->func.fn_mouse_out = func; +} + +/** + * Set a callback for Ecore_Evas mouse pre render events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called just before the evas in @p ee is rendered. + */ +void +ecore_evas_callback_pre_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_pre_render_set"); + return; + } + IFC(ee, fn_callback_pre_render_set) (ee, func); + IFE; + ee->func.fn_pre_render = func; +} + +/** + * Set a callback for Ecore_Evas mouse post render events. + * @param ee The Ecore_Evas to set callbacks on + * @param func The function to call + + * A call to this function will set a callback on an Ecore_Evas, causing + * @p func to be called just after the evas in @p ee is rendered. + */ +void +ecore_evas_callback_post_render_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_callback_post_render_set"); + return; + } + IFC(ee, fn_callback_post_render_set) (ee, func); + IFE; + ee->func.fn_post_render = func; +} + +/** + * Get an Ecore_Evas's Evas + * @param ee The Ecore_Evas whose Evas you wish to get + * @return The Evas wrapped by @p ee + * + * This function returns the Evas contained within @p ee. + */ +Evas * +ecore_evas_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_get"); + return NULL; + } + return ee->evas; +} + +/** + * Move an Ecore_Evas + * @param ee The Ecore_Evas to move + * @param x The x coordinate to move to + * @param y The y coordinate to move to + * + * This moves @p ee to the screen coordinates (@p x, @p y) + */ +void +ecore_evas_move(Ecore_Evas *ee, int x, int y) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_move"); + return; + } + IFC(ee, fn_move) (ee, x, y); + IFE; +} + +/** + * Resize an Ecore_Evas + * @param ee The Ecore_Evas to move + * @param w The w coordinate to resize to + * @param h The h coordinate to resize to + * + * This resizes @p ee to @p w x @p h + */ +void +ecore_evas_resize(Ecore_Evas *ee, int w, int h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_resize"); + return; + } + if (w < 1) w = 1; + if (h < 1) h = 1; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + IFC(ee, fn_resize) (ee, h, w); + IFE; + } + else + { + IFC(ee, fn_resize) (ee, w, h); + IFE; + } +} + +/** + * Resize an Ecore_Evas + * @param ee The Ecore_Evas to move + * @param x The x coordinate to move to + * @param y The y coordinate to move to + * @param w The w coordinate to resize to + * @param h The h coordinate to resize to + * + * This moves @p ee to the screen coordinates (@p x, @p y) and resizes + * it to @p w x @p h. + * + */ +void +ecore_evas_move_resize(Ecore_Evas *ee, int x, int y, int w, int h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_move_resize"); + return; + } + if (w < 1) w = 1; + if (h < 1) h = 1; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + IFC(ee, fn_move_resize) (ee, x, y, h, w); + IFE; + } + else + { + IFC(ee, fn_move_resize) (ee, x, y, w, h); + IFE; + } +} + +/** + * Get the geometry of an Ecore_Evas + * @param ee The Ecore_Evas whose geometry y + * @param x A pointer to an int to place the x coordinate in + * @param y A pointer to an int to place the y coordinate in + * @param w A pointer to an int to place the w size in + * @param h A pointer to an int to place the h size in + * + * This function takes four pointers to (already allocated) ints, and places + * the geometry of @p ee in them. + * + * @code + * int x, y, w, h; + * ecore_evas_geometry_get(ee, &x, &y, &w, &h); + * @endcode + * + */ +void +ecore_evas_geometry_get(Ecore_Evas *ee, int *x, int *y, int *w, int *h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_geometry_get"); + return; + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + if (x) *x = ee->x; + if (y) *y = ee->y; + if (w) *w = ee->h; + if (h) *h = ee->w; + } + else + { + if (x) *x = ee->x; + if (y) *y = ee->y; + if (w) *w = ee->w; + if (h) *h = ee->h; + } +} + +/** + * Set the rotation of an Ecore_Evas' window + * + * @param ee The Ecore_Evas + * @param rot the angle (in degrees) of rotation. + * + * The allowed values of @p rot depend on the engine being used. Most only + * allow multiples of 90. + */ +void +ecore_evas_rotation_set(Ecore_Evas *ee, int rot) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_rotation_set"); + return; + } + rot = rot % 360; + while (rot < 0) rot += 360; + while (rot >= 360) rot -= 360; + IFC(ee, fn_rotation_set) (ee, rot); + IFE; +} + +/** + * Set the rotation of an Ecore_Evas' window + * + * @param ee The Ecore_Evas + * @return the angle (in degrees) of rotation. + * + */ +int +ecore_evas_rotation_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_rotation_get"); + return 0; + } + return ee->rotation; +} + +/** + * Set whether an Ecore_Evas is shaped or not. + * @param ee The Ecore_Evas to shape + * @param shaped 1 to shape, 0 to not + * + * This function allows one to make an Ecore_Evas shaped to the contents of the + * evas. If @p shaped is 1, @p ee will be transparent in parts of the evas that + * contain no objects. If @p shaped is 0, then @p ee will be rectangular, and + * and parts with no data will show random framebuffer artifacting. For + * non-shaped Ecore_Evases, it is recommend to cover the entire evas with a + * background object. + */ +void +ecore_evas_shaped_set(Ecore_Evas *ee, int shaped) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_shaped_set"); + return; + } + IFC(ee, fn_shaped_set) (ee, shaped); + IFE; +} + +/** + * Query whether an Ecore_Evas is shaped or not. + * @param ee The Ecore_Evas to query. + * @return 1 if shaped, 0 if not. + * + * This function returns 1 if @p ee is shaped, and 0 if not. + */ +int +ecore_evas_shaped_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_shaped_get"); + return 0; + } + return ee->shaped ? 1:0; +} + +/** + * Show an Ecore_Evas' window + * @param ee The Ecore_Evas to show. + * + * This function makes @p ee visible. + */ +void +ecore_evas_show(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_show"); + return; + } + IFC(ee, fn_show) (ee); + IFE; +} + +/** + * Hide an Ecore_Evas' window + * @param ee The Ecore_Evas to show. + * + * This function makes @p ee hidden. + */ +void +ecore_evas_hide(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_hide"); + return; + } + IFC(ee, fn_hide) (ee); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is visible or not. + * @param ee The Ecore_Evas to query. + * @return 1 if visible, 0 if not. + * + * This function queries @p ee and returns 1 if it is visible, and 0 if not. + */ +int +ecore_evas_visibility_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_visibility_get"); + return 0; + } + return ee->visible ? 1:0; +} + +/** + * Raise and Ecore_Evas' window. + * @param ee The Ecore_Evas to raise. + * + * This functions raises the Ecore_Evas to the front. + */ +void +ecore_evas_raise(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_raise"); + return; + } + IFC(ee, fn_raise) (ee); + IFE; +} + +/** + * Lower an Ecore_Evas' window. + * @param ee The Ecore_Evas to raise. + * + * This functions lowers the Ecore_Evas to the back. + */ +void +ecore_evas_lower(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_lower"); + return; + } + IFC(ee, fn_lower) (ee); + IFE; +} + +/** + * Set the title of an Ecore_Evas' window + * @param ee The Ecore_Evas whose title you wish to set. + * @param t The title + * + * This function sets the title of @p ee to @p t. + */ +void +ecore_evas_title_set(Ecore_Evas *ee, const char *t) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_title_set"); + return; + } + IFC(ee, fn_title_set) (ee, t); + IFE; +} + +/** + * Get the title of an Ecore_Evas' window + * @param ee The Ecore_Evas whose title you wish to get. + * @return The title of @p ee. + * + * This function returns the title of @p ee. + */ +const char * +ecore_evas_title_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_title_get"); + return NULL; + } + return ee->prop.title; +} + +/** + * Set the name and class of an Ecore_Evas' window + * @param ee the Ecore_Evas + * @param n the name + * @param c the class + * + * This function sets the name of @p ee to @p n, and its class to @p c. + */ +void +ecore_evas_name_class_set(Ecore_Evas *ee, const char *n, const char *c) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_name_class_set"); + return; + } + IFC(ee, fn_name_class_set) (ee, n, c); + IFE; +} + +/** + * Get the name and class of an Ecore_Evas' window + * @p ee The Ecore_Evas to query + * @p n A pointer to a string to place the name in. + * @p c A pointer to a string to place the class in. + * + * This function gets puts the name of @p ee into @p n, and its class into + * @p c. + */ +void +ecore_evas_name_class_get(Ecore_Evas *ee, const char **n, const char **c) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_name_class_get"); + return; + } + if (n) *n = ee->prop.name; + if (c) *c = ee->prop.clas; +} + +/** + * Set the min size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w The minimum width + * @param h The minimum height + * + * This function sets the minimum size of @p ee to @p w x @p h. + */ +void +ecore_evas_size_min_set(Ecore_Evas *ee, int w, int h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_min_set"); + return; + } + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + IFC(ee, fn_size_min_set) (ee, h, w); + IFE; + } + else + { + IFC(ee, fn_size_min_set) (ee, w, h); + IFE; + } +} + +/** + * Get the min size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w A pointer to an int to place the min width in. + * @param h A pointer to an int to place the min height in. + * + * This function puts the minimum size of @p ee into @p w and @p h. + */ +void +ecore_evas_size_min_get(Ecore_Evas *ee, int *w, int *h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_min_get"); + return; + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + if (w) *w = ee->prop.min.h; + if (h) *h = ee->prop.min.w; + } + else + { + if (w) *w = ee->prop.min.w; + if (h) *h = ee->prop.min.h; + } +} + +/** + * Set the max size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w The maximum width + * @param h The maximum height + * + * This function sets the maximum size of @p ee to @p w x @p h. + */ +void +ecore_evas_size_max_set(Ecore_Evas *ee, int w, int h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_max_set"); + return; + } + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + IFC(ee, fn_size_max_set) (ee, h, w); + IFE; + } + else + { + IFC(ee, fn_size_max_set) (ee, w, h); + IFE; + } +} + +/** + * Get the max size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w A pointer to an int to place the max width in. + * @param h A pointer to an int to place the max height in. + * + * This function puts the maximum size of @p ee into @p w and @p h. + */ +void +ecore_evas_size_max_get(Ecore_Evas *ee, int *w, int *h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_max_get"); + return; + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + if (w) *w = ee->prop.max.h; + if (h) *h = ee->prop.max.w; + } + else + { + if (w) *w = ee->prop.max.w; + if (h) *h = ee->prop.max.h; + } +} + +/** + * Set the base size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w The base width + * @param h The base height + * + * This function sets the base size of @p ee to @p w x @p h. + */ +void +ecore_evas_size_base_set(Ecore_Evas *ee, int w, int h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_base_set"); + return; + } + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + IFC(ee, fn_size_base_set) (ee, h, w); + IFE; + } + else + { + IFC(ee, fn_size_base_set) (ee, w, h); + IFE; + } +} + +/** + * Get the base size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w A pointer to an int to place the base width in. + * @param h A pointer to an int to place the base height in. + * + * This function puts the base size of @p ee into @p w and @p h. + */ +void +ecore_evas_size_base_get(Ecore_Evas *ee, int *w, int *h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_base_get"); + return; + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + if (w) *w = ee->prop.base.h; + if (h) *h = ee->prop.base.w; + } + else + { + if (w) *w = ee->prop.base.w; + if (h) *h = ee->prop.base.h; + } +} + +/** + * Set the step size of an Ecore_Evas + * @param ee The Ecore_Evas to set + * @param w The step width + * @param h The step height + * + * This function sets the step size of @p ee to @p w x @p h. This limits the + * size of an Ecore_Evas to always being an integer multiple of the step size. + */ +void +ecore_evas_size_step_set(Ecore_Evas *ee, int w, int h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_step_set"); + return; + } + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + IFC(ee, fn_size_step_set) (ee, h, w); + IFE; + } + else + { + IFC(ee, fn_size_step_set) (ee, w, h); + IFE; + } +} + +/** + * Get the step size of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @param w A pointer to an int to place the step width in. + * @param h A pointer to an int to place the step height in. + * + * This function puts the step size of @p ee into @p w and @p h. + */ +void +ecore_evas_size_step_get(Ecore_Evas *ee, int *w, int *h) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_size_step_get"); + return; + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + if (w) *w = ee->prop.step.h; + if (h) *h = ee->prop.step.w; + } + else + { + if (w) *w = ee->prop.step.w; + if (h) *h = ee->prop.step.h; + } +} + +/** + * Set the cursor of an Ecore_Evas + * @param ee The Ecore_Evas + * @param file The path to an image file for the cursor + * @param layer + * @param hot_x The x coordinate of the cursor's hot spot + * @param hot_y The y coordinate of the cursor's hot spot + * + * This function makes the mouse cursor over @p ee be the image specified by + * @p file. The actual point within the image that the mouse is at is specified + * by @p hot_x and @p hot_y, which are coordinates with respect to the top left + * corner of the cursor image. + */ +void +ecore_evas_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_cursor_set"); + return; + } + IFC(ee, fn_cursor_set) (ee, file, layer, hot_x, hot_y); + IFE; +} + +/** + * Get information about an Ecore_Evas' cursor + * @param ee The Ecore_Evas to set + * @param file A pointer to a string to place the cursor file name in. + * @param layer A pointer to an int to place the cursor's layer in.. + * @param hot_x A pointer to an int to place the cursor's hot_x coordinate in. + * @param hot_y A pointer to an int to place the cursor's hot_y coordinate in. + * + * This function queries information about an Ecore_Evas' cursor. + */ +void +ecore_evas_cursor_get(Ecore_Evas *ee, char **file, int *layer, int *hot_x, int *hot_y) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_cursor_get"); + return; + } + if (file) *file = ee->prop.cursor.file; + if (layer) *layer = ee->prop.cursor.layer; + if (hot_x) *hot_x = ee->prop.cursor.hot.x; + if (hot_y) *hot_y = ee->prop.cursor.hot.y; +} + +/** + * Set the layer of an Ecore_Evas' window + * @param ee The Ecore_Evas + * @param layer The layer to put @p ee on. + * + * This function moves @p ee to the layer @p layer. + */ +void +ecore_evas_layer_set(Ecore_Evas *ee, int layer) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_layer_set"); + return; + } + IFC(ee, fn_layer_set) (ee, layer); + IFE; +} + +/** + * Get the layer of an Ecore_Evas' window + * @param ee The Ecore_Evas to set + * @return the layer @p ee's window is on. + * + */ +int +ecore_evas_layer_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_layer_get"); + return 0; + } + return ee->prop.layer; +} + +/** + * Set the focus of an Ecore_Evas' window + * @param ee The Ecore_Evas + * @param on 1 for focus, 0 to defocus. + * + * This function focuses @p ee if @p on is 1, or defocuses @p ee if @p on is 0. + */ +void +ecore_evas_focus_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_focus_set"); + return; + } + IFC(ee, fn_focus_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is focused or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee if focused, 0 if not. + * + */ +int +ecore_evas_focus_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_focus_get"); + return 0; + } + return ee->prop.focused ? 1:0; +} + +/** + * Iconify or uniconify an Ecore_Evas' window + * @param ee The Ecore_Evas + * @param on 1 to iconify, 0 to uniconify. + * + * This function iconifies @p ee if @p on is 1, or uniconifies @p ee if @p on + * is 0. + */ +void +ecore_evas_iconified_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_iconified_set"); + return; + } + IFC(ee, fn_iconified_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is iconified or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee is iconified, 0 if not. + * + */ +int +ecore_evas_iconified_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_iconified_get"); + return 0; + } + return ee->prop.iconified ? 1:0; +} + +/** + * Set whether an Ecore_Evas' window is borderless or not + * @param ee The Ecore_Evas + * @param on 1 for borderless, 0 for bordered. + * + * This function makes @p ee borderless if @p on is 1, or bordered if @p on + * is 0. + */ +void +ecore_evas_borderless_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_borderless_set"); + return; + } + IFC(ee, fn_borderless_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is borderless or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee is borderless, 0 if not. + * + */ +int +ecore_evas_borderless_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_borderless_get"); + return 0; + } + return ee->prop.borderless ? 1:0; +} + +/** + * Tell the WM whether or not to ignore an Ecore_Evas' window + * @param ee The Ecore_Evas + * @param on 1 to ignore, 0 to not. + * + * This function causes the window manager to ignore @p ee if @p on is 1, + * or not ignore @p ee if @p on is 0. + */ +void +ecore_evas_override_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_override_set"); + return; + } + IFC(ee, fn_override_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is overridden or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee is overridden, 0 if not. + * + */ +int +ecore_evas_override_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_override_get"); + return 0; + } + return ee->prop.override ? 1:0; +} + +/** + * Maximize (or unmaximize) an Ecore_Evas' window + * @param ee The Ecore_Evas + * @param on 1 to maximize, 0 to unmaximize. + * + * This function maximizes @p ee if @p on is 1, or unmaximizes @p ee + * if @p on is 0. + */ +void +ecore_evas_maximized_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_maximized_set"); + return; + } + IFC(ee, fn_maximized_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is maximized or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee is maximized, 0 if not. + * + */ +int +ecore_evas_maximized_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_maximized_get"); + return 0; + } + return ee->prop.maximized ? 1:0; +} + +/** + * Set whether or not an Ecore_Evas' window is fullscreen + * @param ee The Ecore_Evas + * @param on 1 fullscreen, 0 not. + * + * This function causes @p ee to be fullscreen if @p on is 1, + * or not if @p on is 0. + */ +void +ecore_evas_fullscreen_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_fullscreen_set"); + return; + } + IFC(ee, fn_fullscreen_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window is fullscreen or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee is fullscreen, 0 if not. + * + */ +int +ecore_evas_fullscreen_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_fullscreen_get"); + return 0; + } + return ee->prop.fullscreen ? 1:0; +} + +/** + * Set whether or not an Ecore_Evas' window should avoid damage + * + * @param ee The Ecore_Evas + * @param on 1 to avoid damage, 0 to not + * + * This function causes @p ee to be drawn to a pixmap to avoid recalculations. + * On expose events it will copy from the pixmap to the window. + */ +void +ecore_evas_avoid_damage_set(Ecore_Evas *ee, int on) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_avoid_damage_set"); + return; + } + IFC(ee, fn_avoid_damage_set) (ee, on); + IFE; +} + +/** + * Query whether an Ecore_Evas' window avoids damage or not + * @param ee The Ecore_Evas to set + * @return 1 if @p ee avoids damage, 0 if not. + * + */ +int +ecore_evas_avoid_damage_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_avoid_damage_get"); + return 0; + } + return ee->prop.avoid_damage ? 1:0; +} + +/** + * Set the withdrawn state of an Ecore_Evas' window. + * @param ee The Ecore_Evas whose window's withdrawn state is set. + * @param withdrawn The Ecore_Evas window's new withdrawn state. + * + */ +void +ecore_evas_withdrawn_set(Ecore_Evas *ee, int withdrawn) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_withdrawn_set"); + return; + } + + IFC(ee, fn_withdrawn_set) (ee, withdrawn); + IFE; +} + +/** + * Returns the withdrawn state of an Ecore_Evas' window. + * @param ee The Ecore_Evas whose window's withdrawn state is returned. + * @return The Ecore_Evas window's withdrawn state. + * + */ +int +ecore_evas_withdrawn_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_withdrawn_get"); + return 0; + } else + return ee->prop.withdrawn ? 1:0; +} + +/** + * Set the sticky state of an Ecore_Evas window. + * + * @param ee The Ecore_Evas whose window's sticky state is set. + * @param sticky The Ecore_Evas window's new sticky state. + * + */ +void +ecore_evas_sticky_set(Ecore_Evas *ee, int sticky) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_sticky_set"); + return; + } + + IFC(ee, fn_sticky_set) (ee, sticky); + IFE; +} + +/** + * Returns the sticky state of an Ecore_Evas' window. + * + * @param ee The Ecore_Evas whose window's sticky state is returned. + * @return The Ecore_Evas window's sticky state. + * + */ +int +ecore_evas_sticky_get(Ecore_Evas *ee) +{ + if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS)) + { + ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS, + "ecore_evas_sticky_get"); + return 0; + } else + return ee->prop.sticky ? 1:0; +} + +#ifndef WIN32 +/* fps debug calls - for debugging how much time your app actually spends */ +/* rendering graphics... :) */ + +static int _ecore_evas_fps_debug_init_count = 0; +static int _ecore_evas_fps_debug_fd = -1; +unsigned int *_ecore_evas_fps_rendertime_mmap = NULL; + +void +_ecore_evas_fps_debug_init(void) +{ + char buf[4096]; + + _ecore_evas_fps_debug_init_count++; + if (_ecore_evas_fps_debug_init_count > 1) return; + snprintf(buf, sizeof(buf), "/tmp/.ecore_evas_fps_debug-%i", (int)getpid()); + _ecore_evas_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR); + if (_ecore_evas_fps_debug_fd < 0) + { + unlink(buf); + _ecore_evas_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR); + } + if (_ecore_evas_fps_debug_fd >= 0) + { + unsigned int zero = 0; + + write(_ecore_evas_fps_debug_fd, &zero, sizeof(unsigned int)); + _ecore_evas_fps_rendertime_mmap = mmap(NULL, sizeof(unsigned int), + PROT_READ | PROT_WRITE, + MAP_SHARED, + _ecore_evas_fps_debug_fd, 0); + } +} + +void +_ecore_evas_fps_debug_shutdown(void) +{ + _ecore_evas_fps_debug_init_count--; + if (_ecore_evas_fps_debug_init_count > 0) return; + if (_ecore_evas_fps_debug_fd >= 0) + { + char buf[4096]; + + snprintf(buf, sizeof(buf), "/tmp/.ecore_evas_fps_debug-%i", (int)getpid()); + unlink(buf); + if (_ecore_evas_fps_rendertime_mmap) + { + munmap(_ecore_evas_fps_rendertime_mmap, sizeof(int)); + _ecore_evas_fps_rendertime_mmap = NULL; + } + close(_ecore_evas_fps_debug_fd); + _ecore_evas_fps_debug_fd = -1; + } +} + +void +_ecore_evas_fps_debug_rendertime_add(double t) +{ + if ((_ecore_evas_fps_debug_fd >= 0) && + (_ecore_evas_fps_rendertime_mmap)) + { + unsigned int tm; + + tm = (unsigned int)(t * 1000000.0); + /* i know its not 100% theoretically guaranteed, but i'd say a write */ + /* of an int could be considered atomic for all practical purposes */ + /* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */ + /* this can run for about 4294 seconds becore looping. if you are */ + /* doing performance testing in one run for over an hour... well */ + /* time to restart or handle a loop condition :) */ + *(_ecore_evas_fps_rendertime_mmap) += tm; + } +} +#endif diff --git a/ecore/src/lib/ecore_evas/ecore_evas_buffer.c b/ecore/src/lib/ecore_evas/ecore_evas_buffer.c new file mode 100644 index 0000000..84e0078 --- /dev/null +++ b/ecore/src/lib/ecore_evas/ecore_evas_buffer.c @@ -0,0 +1,634 @@ +#include "config.h" +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_evas_private.h" +#include "Ecore_Evas.h" + +#ifdef BUILD_ECORE_EVAS_BUFFER +static int _ecore_evas_init_count = 0; + +static int _ecore_evas_fps_debug = 0; + +static Ecore_Evas *ecore_evases = NULL; + +static void +_ecore_evas_mouse_move_process(Ecore_Evas *ee, int x, int y, unsigned int timestamp) +{ + ee->mouse.x = x; + ee->mouse.y = y; + evas_event_feed_mouse_move(ee->evas, x, y, timestamp, NULL); +} + +static int +_ecore_evas_buffer_init(void) +{ + _ecore_evas_init_count++; + if (_ecore_evas_init_count > 1) return _ecore_evas_init_count; + if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1; + if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init(); + return _ecore_evas_init_count; +} + +static void +_ecore_evas_buffer_free(Ecore_Evas *ee) +{ + ecore_evases = _ecore_list_remove(ecore_evases, ee); + _ecore_evas_buffer_shutdown(); + if (ee->engine.buffer.image) + { + Ecore_Evas *ee2; + + ee2 = evas_object_data_get(ee->engine.buffer.image, "Ecore_Evas_Parent"); + evas_object_del(ee->engine.buffer.image); + ee2->sub_ecore_evas = evas_list_remove(ee2->sub_ecore_evas, ee); + } + else + free(ee->engine.buffer.pixels); +} + +static void +_ecore_evas_resize(Ecore_Evas *ee, int w, int h) +{ + Evas_Engine_Info_Buffer *einfo; + + if (w < 1) w = 1; + if (h < 1) h = 1; + if ((w == ee->w) && (h == ee->h)) return; + ee->w = w; + ee->h = h; + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + + if (ee->engine.buffer.image) + { + ee->engine.buffer.pixels = evas_object_image_data_get(ee->engine.buffer.image, 1); + } + else + { + if (ee->engine.buffer.pixels) free(ee->engine.buffer.pixels); + ee->engine.buffer.pixels = malloc(ee->w * ee->h * sizeof(int)); + } + + einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ee->evas); + if (einfo) + { + einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32; + einfo->info.dest_buffer = ee->engine.buffer.pixels; + einfo->info.dest_buffer_row_bytes = ee->w * sizeof(int); + einfo->info.use_color_key = 0; + einfo->info.alpha_threshold = 0; + einfo->info.func.new_update_region = NULL; + einfo->info.func.free_update_region = NULL; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +int +_ecore_evas_buffer_shutdown(void) +{ + _ecore_evas_init_count--; + if (_ecore_evas_init_count == 0) + { + while (ecore_evases) + ecore_evas_free((Ecore_Evas *)(ecore_evases->data)); + if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown(); + } + if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0; + return _ecore_evas_init_count; +} + +void +_ecore_evas_buffer_render(Ecore_Evas *ee) +{ + Evas_List *updates, *l, *ll; + + for (ll = ee->sub_ecore_evas; ll; ll = ll->next) + { + Ecore_Evas *ee2; + + ee2 = ll->data; + if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); + _ecore_evas_buffer_render(ee2); + if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); + } + if (ee->engine.buffer.image) + { + int w, h; + + evas_object_image_size_get(ee->engine.buffer.image, &w, &h); + if ((w != ee->w) || (h != ee->h)) + _ecore_evas_resize(ee, w, h); + } + updates = evas_render_updates(ee->evas); + if (ee->engine.buffer.image) + { + for (l = updates; l; l = l->next) + { + Evas_Rectangle *r; + + r = l->data; + if (ee->engine.buffer.image) + evas_object_image_data_update_add(ee->engine.buffer.image, + r->x, r->y, r->w, r->h); + } + } + if (updates) evas_render_updates_free(updates); +} + +static void +_ecore_evas_buffer_coord_translate(Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y) +{ + Evas_Coord xx, yy, fx, fy, fw, fh; + + evas_object_geometry_get(ee->engine.buffer.image, &xx, &yy, NULL, NULL); + evas_object_image_fill_get(ee->engine.buffer.image, &fx, &fy, &fw, &fh); + + if (fw < 1) fw = 1; + xx = (*x - xx) - fx; + while (xx < 0) xx += fw; + while (xx > fw) xx -= fw; + *x = (ee->w * xx) / fw; + + if (fh < 1) fh = 1; + yy = (*y - yy) - fy; + while (yy < 0) yy += fh; + while (yy > fh) yy -= fh; + *y = (ee->h * yy) / fh; +} + +static void +_ecore_evas_buffer_cb_mouse_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + Evas_Event_Mouse_In *ev; + + ee = data; + ev = event_info; + evas_event_feed_mouse_in(ee->evas, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_mouse_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + Evas_Event_Mouse_Out *ev; + + ee = data; + ev = event_info; + evas_event_feed_mouse_out(ee->evas, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + Ecore_Evas *ee; + Evas_Event_Mouse_Down *ev; + + ee = data; + ev = event_info; + evas_event_feed_mouse_down(ee->evas, ev->button, ev->flags, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + Ecore_Evas *ee; + Evas_Event_Mouse_Up *ev; + + ee = data; + ev = event_info; + evas_event_feed_mouse_up(ee->evas, ev->button, ev->flags, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + Ecore_Evas *ee; + Evas_Event_Mouse_Move *ev; + Evas_Coord x, y; + + ee = data; + ev = event_info; + x = ev->cur.canvas.x; + y = ev->cur.canvas.y; + _ecore_evas_buffer_coord_translate(ee, &x, &y); + _ecore_evas_mouse_move_process(ee, x, y, ev->timestamp); +} + +static void +_ecore_evas_buffer_cb_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +{ + Ecore_Evas *ee; + Evas_Event_Mouse_Wheel *ev; + + ee = data; + ev = event_info; + evas_event_feed_mouse_wheel(ee->evas, ev->direction, ev->z, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_free(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + + ee = data; + if (ee->driver) + ecore_evas_free(ee); +} + +static void +_ecore_evas_buffer_cb_key_down(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info) +{ + Ecore_Evas *ee; + Evas_Event_Key_Down *ev; + + ee = data; + ev = event_info; + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Shift")) + evas_key_modifier_on(e, "Shift"); + else + evas_key_modifier_off(e, "Shift"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Control")) + evas_key_modifier_on(e, "Control"); + else + evas_key_modifier_off(e, "Control"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Alt")) + evas_key_modifier_on(e, "Alt"); + else + evas_key_modifier_off(e, "Alt"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Meta")) + evas_key_modifier_on(e, "Meta"); + else + evas_key_modifier_off(e, "Meta"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Hyper")) + evas_key_modifier_on(e, "Hyper"); + else + evas_key_modifier_off(e, "Hyper"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Super")) + evas_key_modifier_on(e, "Super"); + else + evas_key_modifier_off(e, "Super"); + if (evas_key_lock_is_set(evas_key_lock_get(e), "Scroll_Lock")) + evas_key_lock_on(e, "Scroll_Lock"); + else + evas_key_lock_off(e, "Scroll_Lock"); + if (evas_key_lock_is_set(evas_key_lock_get(e), "Num_Lock")) + evas_key_lock_on(e, "Num_Lock"); + else + evas_key_lock_off(e, "Num_Lock"); + if (evas_key_lock_is_set(evas_key_lock_get(e), "Caps_Lock")) + evas_key_lock_on(e, "Caps_Lock"); + else + evas_key_lock_off(e, "Caps_Lock"); + evas_event_feed_key_down(ee->evas, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_key_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info) +{ + Ecore_Evas *ee; + Evas_Event_Key_Up *ev; + + ee = data; + ev = event_info; + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Shift")) + evas_key_modifier_on(e, "Shift"); + else + evas_key_modifier_off(e, "Shift"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Control")) + evas_key_modifier_on(e, "Control"); + else + evas_key_modifier_off(e, "Control"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Alt")) + evas_key_modifier_on(e, "Alt"); + else + evas_key_modifier_off(e, "Alt"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Meta")) + evas_key_modifier_on(e, "Meta"); + else + evas_key_modifier_off(e, "Meta"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Hyper")) + evas_key_modifier_on(e, "Hyper"); + else + evas_key_modifier_off(e, "Hyper"); + if (evas_key_modifier_is_set(evas_key_modifier_get(e), "Super")) + evas_key_modifier_on(e, "Super"); + else + evas_key_modifier_off(e, "Super"); + if (evas_key_lock_is_set(evas_key_lock_get(e), "Scroll_Lock")) + evas_key_lock_on(e, "Scroll_Lock"); + else + evas_key_lock_off(e, "Scroll_Lock"); + if (evas_key_lock_is_set(evas_key_lock_get(e), "Num_Lock")) + evas_key_lock_on(e, "Num_Lock"); + else + evas_key_lock_off(e, "Num_Lock"); + if (evas_key_lock_is_set(evas_key_lock_get(e), "Caps_Lock")) + evas_key_lock_on(e, "Caps_Lock"); + else + evas_key_lock_off(e, "Caps_Lock"); + evas_event_feed_key_up(ee->evas, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, NULL); +} + +static void +_ecore_evas_buffer_cb_focus_in(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + + ee = data; + ee->prop.focused = 1; + if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee); +} + +static void +_ecore_evas_buffer_cb_focus_out(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + + ee = data; + ee->prop.focused = 0; + if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee); +} + +static void +_ecore_evas_buffer_cb_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + + ee = data; + ee->visible = 1; + if (ee->func.fn_show) ee->func.fn_show(ee); +} + +static void +_ecore_evas_buffer_cb_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Ecore_Evas *ee; + + ee = data; + ee->visible = 0; + if (ee->func.fn_hide) ee->func.fn_hide(ee); +} + +static const Ecore_Evas_Engine_Func _ecore_buffer_engine_func = +{ + _ecore_evas_buffer_free, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_resize, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; +#endif + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_Evas * +ecore_evas_buffer_new(int w, int h) +{ +#ifdef BUILD_ECORE_EVAS_BUFFER + Evas_Engine_Info_Buffer *einfo; + Ecore_Evas *ee; + int rmethod; + + rmethod = evas_render_method_lookup("buffer"); + if (!rmethod) return NULL; + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + _ecore_evas_buffer_init(); + + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_buffer_engine_func; + + ee->driver = strdup("buffer"); + + if (w < 1) w = 1; + if (h < 1) h = 1; + ee->rotation = 0; + ee->visible = 1; + ee->w = w; + ee->h = h; + + ee->prop.max.w = 0; + ee->prop.max.h = 0; + ee->prop.layer = 0; + ee->prop.focused = 1; + ee->prop.borderless = 1; + ee->prop.override = 1; + ee->prop.maximized = 1; + ee->prop.fullscreen = 0; + ee->prop.withdrawn = 0; + ee->prop.sticky = 0; + + /* init evas here */ + ee->evas = evas_new(); + evas_output_method_set(ee->evas, rmethod); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + ee->engine.buffer.pixels = malloc(w * h * sizeof(int)); + + einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ee->evas); + if (einfo) + { + einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32; + einfo->info.dest_buffer = ee->engine.buffer.pixels; + einfo->info.dest_buffer_row_bytes = ee->w * sizeof(int); + einfo->info.use_color_key = 0; + einfo->info.alpha_threshold = 0; + einfo->info.func.new_update_region = NULL; + einfo->info.func.free_update_region = NULL; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + evas_key_modifier_add(ee->evas, "Shift"); + evas_key_modifier_add(ee->evas, "Control"); + evas_key_modifier_add(ee->evas, "Alt"); + evas_key_modifier_add(ee->evas, "Meta"); + evas_key_modifier_add(ee->evas, "Hyper"); + evas_key_modifier_add(ee->evas, "Super"); + evas_key_lock_add(ee->evas, "Caps_Lock"); + evas_key_lock_add(ee->evas, "Num_Lock"); + evas_key_lock_add(ee->evas, "Scroll_Lock"); + + evas_event_feed_mouse_in(ee->evas, 0, NULL); + + ecore_evases = _ecore_list_prepend(ecore_evases, ee); + return ee; +#else + return NULL; +#endif +} + +const int * +ecore_evas_buffer_pixels_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_EVAS_BUFFER + _ecore_evas_buffer_render(ee); + return ee->engine.buffer.pixels; +#else + return NULL; +#endif +} + +Evas_Object * +ecore_evas_object_image_new(Ecore_Evas *ee_target) +{ +#ifdef BUILD_ECORE_EVAS_BUFFER + Evas_Object *o; + Evas_Engine_Info_Buffer *einfo; + Ecore_Evas *ee; + int rmethod; + int w, h; + + rmethod = evas_render_method_lookup("buffer"); + if (!rmethod) return NULL; + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; + + o = evas_object_image_add(ee_target->evas); + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + _ecore_evas_buffer_init(); + + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_buffer_engine_func; + + ee->driver = strdup("buffer"); + + w = 1; + h = 1; + ee->rotation = 0; + ee->visible = 0; + ee->w = w; + ee->h = h; + + ee->prop.max.w = 0; + ee->prop.max.h = 0; + ee->prop.layer = 0; + ee->prop.focused = 0; + ee->prop.borderless = 1; + ee->prop.override = 1; + ee->prop.maximized = 0; + ee->prop.fullscreen = 0; + ee->prop.withdrawn = 0; + ee->prop.sticky = 0; + + /* init evas here */ + ee->evas = evas_new(); + evas_output_method_set(ee->evas, rmethod); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + ee->engine.buffer.image = o; + evas_object_data_set(ee->engine.buffer.image, "Ecore_Evas", ee); + evas_object_data_set(ee->engine.buffer.image, "Ecore_Evas_Parent", ee_target); + evas_object_image_size_set(o, ee->w, ee->h); + evas_object_image_alpha_set(o, 1); + ee->engine.buffer.pixels = evas_object_image_data_get(o, 1); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_MOUSE_IN, + _ecore_evas_buffer_cb_mouse_in, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_MOUSE_OUT, + _ecore_evas_buffer_cb_mouse_out, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_MOUSE_DOWN, + _ecore_evas_buffer_cb_mouse_down, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_MOUSE_UP, + _ecore_evas_buffer_cb_mouse_up, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_MOUSE_MOVE, + _ecore_evas_buffer_cb_mouse_move, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_MOUSE_WHEEL, + _ecore_evas_buffer_cb_mouse_wheel, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_FREE, + _ecore_evas_buffer_cb_free, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_KEY_DOWN, + _ecore_evas_buffer_cb_key_down, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_KEY_UP, + _ecore_evas_buffer_cb_key_up, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_FOCUS_IN, + _ecore_evas_buffer_cb_focus_in, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_FOCUS_OUT, + _ecore_evas_buffer_cb_focus_out, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_SHOW, + _ecore_evas_buffer_cb_show, ee); + evas_object_event_callback_add(ee->engine.buffer.image, + EVAS_CALLBACK_HIDE, + _ecore_evas_buffer_cb_hide, ee); + einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(ee->evas); + if (einfo) + { + einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32; + einfo->info.dest_buffer = ee->engine.buffer.pixels; + einfo->info.dest_buffer_row_bytes = ee->w * sizeof(int); + einfo->info.use_color_key = 0; + einfo->info.alpha_threshold = 0; + einfo->info.func.new_update_region = NULL; + einfo->info.func.free_update_region = NULL; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + evas_key_modifier_add(ee->evas, "Shift"); + evas_key_modifier_add(ee->evas, "Control"); + evas_key_modifier_add(ee->evas, "Alt"); + evas_key_modifier_add(ee->evas, "Meta"); + evas_key_modifier_add(ee->evas, "Hyper"); + evas_key_modifier_add(ee->evas, "Super"); + evas_key_lock_add(ee->evas, "Caps_Lock"); + evas_key_lock_add(ee->evas, "Num_Lock"); + evas_key_lock_add(ee->evas, "Scroll_Lock"); + + ee_target->sub_ecore_evas = evas_list_append(ee_target->sub_ecore_evas, ee); + return o; +#else + return NULL; +#endif +} diff --git a/ecore/src/lib/ecore_evas/ecore_evas_fb.c b/ecore/src/lib/ecore_evas/ecore_evas_fb.c new file mode 100644 index 0000000..b0a6d2a --- /dev/null +++ b/ecore/src/lib/ecore_evas/ecore_evas_fb.c @@ -0,0 +1,542 @@ +#include "config.h" +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_evas_private.h" +#include "Ecore_Evas.h" +#ifdef BUILD_ECORE_EVAS_FB +#include "Ecore_Fb.h" +#endif + +#ifdef BUILD_ECORE_EVAS_FB +static int _ecore_evas_init_count = 0; + +static int _ecore_evas_fps_debug = 0; + +static Ecore_Evas *ecore_evases = NULL; +static Ecore_Event_Handler *ecore_evas_event_handlers[5]; +static Ecore_Idle_Enterer *ecore_evas_idle_enterer = NULL; + +static void +_ecore_evas_mouse_move_process(Ecore_Evas *ee, int x, int y, unsigned int timestamp) +{ + int fbw, fbh; + + ee->mouse.x = x; + ee->mouse.y = y; + ecore_fb_size_get(&fbw, &fbh); + if (ee->prop.cursor.object) + { + evas_object_show(ee->prop.cursor.object); + if (ee->rotation == 0) + evas_object_move(ee->prop.cursor.object, + x - ee->prop.cursor.hot.x, + y - ee->prop.cursor.hot.y); + else if (ee->rotation == 90) + evas_object_move(ee->prop.cursor.object, + (fbh - ee->h) + ee->h - y - 1 - ee->prop.cursor.hot.x, + x - ee->prop.cursor.hot.y); + else if (ee->rotation == 180) + evas_object_move(ee->prop.cursor.object, + (fbw - ee->w) + ee->w - x - 1 - ee->prop.cursor.hot.x, + (fbh - ee->h) + ee->h - y - 1 - ee->prop.cursor.hot.y); + else if (ee->rotation == 270) + evas_object_move(ee->prop.cursor.object, + y - ee->prop.cursor.hot.x, + (fbw - ee->w) + ee->w - x - 1 - ee->prop.cursor.hot.y); + } + if (ee->rotation == 0) + evas_event_feed_mouse_move(ee->evas, x, y, timestamp, NULL); + else if (ee->rotation == 90) + evas_event_feed_mouse_move(ee->evas, (fbh - ee->h) + ee->h - y - 1, x, timestamp, NULL); + else if (ee->rotation == 180) + evas_event_feed_mouse_move(ee->evas, (fbw - ee->w) + ee->w - x - 1, (fbh - ee->h) + ee->h - y - 1, timestamp, NULL); + else if (ee->rotation == 270) + evas_event_feed_mouse_move(ee->evas, y, (fbw - ee->w) + ee->w - x - 1, timestamp, NULL); +} + +static Ecore_Evas * +_ecore_evas_fb_match(void) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)ecore_evases; l; l = l->next) + { + Ecore_Evas *ee; + + ee = (Ecore_Evas *)l; + return ee; + } + return NULL; +} + +static void +_ecore_evas_fb_lose(void *data __UNUSED__) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)ecore_evases; l; l = l->next) + { + Ecore_Evas *ee; + + ee = (Ecore_Evas *)l; + ee->visible = 0; + } +} + +static void +_ecore_evas_fb_gain(void *data __UNUSED__) +{ + Ecore_Oldlist *l; + + for (l = (Ecore_Oldlist *)ecore_evases; l; l = l->next) + { + Ecore_Evas *ee; + + ee = (Ecore_Evas *)l; + ee->visible = 1; + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + } +} + +static int +_ecore_evas_event_key_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_Fb_Event_Key_Down *e; + + e = event; + ee = _ecore_evas_fb_match(); + if (!ee) return 1; /* pass on event */ + evas_event_feed_key_down(ee->evas, e->keyname, e->keysymbol, e->key_compose, NULL, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL); + return 0; /* dont pass it on */ +} + +static int +_ecore_evas_event_key_up(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_Fb_Event_Key_Up *e; + + e = event; + ee = _ecore_evas_fb_match(); + if (!ee) return 1; /* pass on event */ + evas_event_feed_key_up(ee->evas, e->keyname, e->keysymbol, e->key_compose, NULL, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL); + return 0; /* dont pass it on */ +} + +static int +_ecore_evas_event_mouse_button_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_Fb_Event_Mouse_Button_Down *e; + Evas_Button_Flags flags = EVAS_BUTTON_NONE; + + e = event; + ee = _ecore_evas_fb_match(); + if (!ee) return 1; /* pass on event */ + _ecore_evas_mouse_move_process(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff)); + if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK; + if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK; + evas_event_feed_mouse_down(ee->evas, e->button, flags, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL); + return 0; /* dont pass it on */ +} + +static int +_ecore_evas_event_mouse_button_up(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_Fb_Event_Mouse_Button_Up *e; + + e = event; + ee = _ecore_evas_fb_match(); + if (!ee) return 1; /* pass on event */ + _ecore_evas_mouse_move_process(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff)); + evas_event_feed_mouse_up(ee->evas, e->button, EVAS_BUTTON_NONE, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL); + return 0; /* dont pass it on */ +} + +static int +_ecore_evas_event_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_Fb_Event_Mouse_Move *e; + + e = event; + ee = _ecore_evas_fb_match(); + if (!ee) return 1; /* pass on event */ + _ecore_evas_mouse_move_process(ee, e->x, e->y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff)); + return 0; /* dont pass it on */ +} + +static int +_ecore_evas_idle_enter(void *data __UNUSED__) +{ + Ecore_Oldlist *l; + double t1 = 0.; + double t2 = 0.; + + if (_ecore_evas_fps_debug) + { + t1 = ecore_time_get(); + } + for (l = (Ecore_Oldlist *)ecore_evases; l; l = l->next) + { + Ecore_Evas *ee; + + ee = (Ecore_Evas *)l; + if (ee->visible) + { +#ifdef BUILD_ECORE_EVAS_BUFFER + Evas_List *ll; +#endif + + if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); +#ifdef BUILD_ECORE_EVAS_BUFFER + for (ll = ee->sub_ecore_evas; ll; ll = ll->next) + { + Ecore_Evas *ee2; + + ee2 = ll->data; + if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); + _ecore_evas_buffer_render(ee2); + if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); + } +#endif + evas_render(ee->evas); + if (ee->func.fn_post_render) ee->func.fn_post_render(ee); + } + } + if (_ecore_evas_fps_debug) + { + t2 = ecore_time_get(); + _ecore_evas_fps_debug_rendertime_add(t2 - t1); + } + return 1; +} + +static int +_ecore_evas_fb_init(void) +{ + _ecore_evas_init_count++; + if (_ecore_evas_init_count > 1) return _ecore_evas_init_count; + if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1; + ecore_evas_idle_enterer = ecore_idle_enterer_add(_ecore_evas_idle_enter, NULL); + ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_FB_EVENT_KEY_DOWN, _ecore_evas_event_key_down, NULL); + ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_FB_EVENT_KEY_UP, _ecore_evas_event_key_up, NULL); + ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, _ecore_evas_event_mouse_button_down, NULL); + ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, _ecore_evas_event_mouse_button_up, NULL); + ecore_evas_event_handlers[4] = ecore_event_handler_add(ECORE_FB_EVENT_MOUSE_MOVE, _ecore_evas_event_mouse_move, NULL); + if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init(); + return _ecore_evas_init_count; +} + +static void +_ecore_evas_fb_free(Ecore_Evas *ee) +{ + ecore_evases = _ecore_list_remove(ecore_evases, ee); + _ecore_evas_fb_shutdown(); + ecore_fb_shutdown(); +} + +static void +_ecore_evas_resize(Ecore_Evas *ee, int w, int h) +{ + if ((w == ee->w) && (h == ee->h)) return; + ee->w = w; + ee->h = h; + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +static void +_ecore_evas_move_resize(Ecore_Evas *ee, int x __UNUSED__, int y __UNUSED__, int w, int h) +{ + if ((w == ee->w) && (h == ee->h)) return; + ee->w = w; + ee->h = h; + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +static void +_ecore_evas_rotation_set(Ecore_Evas *ee, int rotation) +{ + Evas_Engine_Info_FB *einfo; + int rot_dif; + + if (ee->rotation == rotation) return; + einfo = (Evas_Engine_Info_FB *)evas_engine_info_get(ee->evas); + if (!einfo) return; + rot_dif = ee->rotation - rotation; + if (rot_dif < 0) rot_dif = -rot_dif; + if (rot_dif != 180) + { + + einfo->info.rotation = rotation; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + if (!ee->prop.fullscreen) + { + int tmp; + + tmp = ee->w; + ee->w = ee->h; + ee->h = tmp; + } + else + { + if ((rotation == 0) || (rotation == 180)) + { + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + } + else + { + evas_output_size_set(ee->evas, ee->h, ee->w); + evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + } + } + ee->rotation = rotation; + } + else + { + einfo->info.rotation = rotation; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + ee->rotation = rotation; + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w); + else + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + _ecore_evas_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff)); + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +static void +_ecore_evas_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y) +{ + int x, y; + + if (!file) + { + if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object); + if (ee->prop.cursor.file) free(ee->prop.cursor.file); + ee->prop.cursor.object = NULL; + ee->prop.cursor.file = NULL; + ee->prop.cursor.layer = 0; + ee->prop.cursor.hot.x = 0; + ee->prop.cursor.hot.y = 0; + return; + } + if (!ee->prop.cursor.object) ee->prop.cursor.object = evas_object_image_add(ee->evas); + if (ee->prop.cursor.file) free(ee->prop.cursor.file); + ee->prop.cursor.file = strdup(file); + ee->prop.cursor.layer = layer; + ee->prop.cursor.hot.x = hot_x; + ee->prop.cursor.hot.y = hot_y; + evas_pointer_output_xy_get(ee->evas, &x, &y); + evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer); + evas_object_color_set(ee->prop.cursor.object, 255, 255, 255, 255); + evas_object_move(ee->prop.cursor.object, + x - ee->prop.cursor.hot.x, + y - ee->prop.cursor.hot.y); + evas_object_image_file_set(ee->prop.cursor.object, ee->prop.cursor.file, NULL); + evas_object_image_size_get(ee->prop.cursor.object, &x, &y); + evas_object_resize(ee->prop.cursor.object, x, y); + evas_object_image_fill_set(ee->prop.cursor.object, 0, 0, x, y); + evas_object_pass_events_set(ee->prop.cursor.object, 1); + if (evas_pointer_inside_get(ee->evas)) + evas_object_show(ee->prop.cursor.object); +} + +static void +_ecore_evas_fullscreen_set(Ecore_Evas *ee, int on) +{ + int resized = 0; + + if (((ee->prop.fullscreen) && (on)) || + ((!ee->prop.fullscreen) && (!on))) return; + if (on) + { + int w, h; + + ee->engine.fb.real_w = ee->w; + ee->engine.fb.real_h = ee->h; + w = ee->w; + h = ee->h; + ecore_fb_size_get(&w, &h); + if ((w == 0) && (h == 0)) + { + w = ee->w; + h = ee->h; + } + if ((w != ee->w) || (h != ee->h)) resized = 1; + ee->w = w; + ee->h = h; + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + } + else + { + if ((ee->engine.fb.real_w != ee->w) || (ee->engine.fb.real_h != ee->h)) resized = 1; + ee->w = ee->engine.fb.real_w; + ee->h = ee->engine.fb.real_h; + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + } + ee->prop.fullscreen = on; + if (resized) + { + if (ee->func.fn_resize) ee->func.fn_resize(ee); + } +} + +int +_ecore_evas_fb_shutdown(void) +{ + _ecore_evas_init_count--; + if (_ecore_evas_init_count == 0) + { + int i; + + while (ecore_evases) ecore_evas_free(ecore_evases); + for (i = 0; i < 5; i++) + ecore_event_handler_del(ecore_evas_event_handlers[i]); + ecore_idle_enterer_del(ecore_evas_idle_enterer); + ecore_evas_idle_enterer = NULL; + if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown(); + } + if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0; + return _ecore_evas_init_count; +} + +static const Ecore_Evas_Engine_Func _ecore_fb_engine_func = +{ + _ecore_evas_fb_free, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_resize, + _ecore_evas_move_resize, + _ecore_evas_rotation_set, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_cursor_set, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_fullscreen_set, + NULL, + NULL, + NULL +}; +#endif + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_Evas * +ecore_evas_fb_new(char *disp_name, int rotation, int w, int h) +{ +#ifdef BUILD_ECORE_EVAS_FB + Evas_Engine_Info_FB *einfo; + Ecore_Evas *ee; + int rmethod; + + rmethod = evas_render_method_lookup("fb"); + if (!rmethod) return NULL; + if (!ecore_fb_init(disp_name)) return NULL; + ecore_fb_callback_gain_set(_ecore_evas_fb_gain, NULL); + ecore_fb_callback_lose_set(_ecore_evas_fb_lose, NULL); + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + _ecore_evas_fb_init(); + + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_fb_engine_func; + + ee->driver = strdup("fb"); + if (disp_name) ee->name = strdup(disp_name); + + if (w < 1) w = 1; + if (h < 1) h = 1; + ee->rotation = rotation; + ee->visible = 1; + ee->w = w; + ee->h = h; + + ee->prop.max.w = 0; + ee->prop.max.h = 0; + ee->prop.layer = 0; + ee->prop.focused = 1; + ee->prop.borderless = 1; + ee->prop.override = 1; + ee->prop.maximized = 1; + ee->prop.fullscreen = 0; + ee->prop.withdrawn = 0; + ee->prop.sticky = 0; + + /* init evas here */ + ee->evas = evas_new(); + evas_output_method_set(ee->evas, rmethod); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + einfo = (Evas_Engine_Info_FB *)evas_engine_info_get(ee->evas); + if (einfo) + { + einfo->info.virtual_terminal = 0; + einfo->info.device_number = 0; + einfo->info.refresh = 0; + einfo->info.rotation = ee->rotation; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + evas_key_modifier_add(ee->evas, "Shift"); + evas_key_modifier_add(ee->evas, "Control"); + evas_key_modifier_add(ee->evas, "Alt"); + evas_key_modifier_add(ee->evas, "Meta"); + evas_key_modifier_add(ee->evas, "Hyper"); + evas_key_modifier_add(ee->evas, "Super"); + evas_key_lock_add(ee->evas, "Caps_Lock"); + evas_key_lock_add(ee->evas, "Num_Lock"); + evas_key_lock_add(ee->evas, "Scroll_Lock"); + + evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL); + + ecore_evases = _ecore_list_prepend(ecore_evases, ee); + return ee; +#else + return NULL; +#endif +} diff --git a/ecore/src/lib/ecore_evas/ecore_evas_private.h b/ecore/src/lib/ecore_evas/ecore_evas_private.h new file mode 100644 index 0000000..675816d --- /dev/null +++ b/ecore/src/lib/ecore_evas/ecore_evas_private.h @@ -0,0 +1,216 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#ifndef _ECORE_EVAS_PRIVATE_H +#define _ECORE_EVAS_PRIVATE_H + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#ifndef WIN32 +#include <sys/mman.h> +#endif + +#include <Evas.h> + +#define ECORE_MAGIC_EVAS 0x76543211 + +#ifdef BUILD_ECORE_X +#include "Ecore_X.h" +#include <Evas_Engine_Software_X11.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#ifdef BUILD_ECORE_EVAS_GL +#include <Evas_Engine_GL_X11.h> +#endif +#endif +#ifdef BUILD_ECORE_EVAS_FB +#include <Evas_Engine_FB.h> +#endif +#ifdef BUILD_ECORE_EVAS_BUFFER +#include <Evas_Engine_Buffer.h> +#endif + +typedef struct _Ecore_Evas Ecore_Evas; +typedef struct _Ecore_Evas_Engine Ecore_Evas_Engine; +typedef struct _Ecore_Evas_Engine_Func Ecore_Evas_Engine_Func; + +struct _Ecore_Evas_Engine_Func +{ + void (*fn_free) (Ecore_Evas *ee); + void (*fn_callback_resize_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_move_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_show_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_hide_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_delete_request_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_destroy_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_focus_in_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_focus_out_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_mouse_in_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_mouse_out_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_pre_render_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_callback_post_render_set) (Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)); + void (*fn_move) (Ecore_Evas *ee, int x, int y); + void (*fn_resize) (Ecore_Evas *ee, int w, int h); + void (*fn_move_resize) (Ecore_Evas *ee, int x, int y, int w, int h); + void (*fn_rotation_set) (Ecore_Evas *ee, int rot); + void (*fn_shaped_set) (Ecore_Evas *ee, int shaped); + void (*fn_show) (Ecore_Evas *ee); + void (*fn_hide) (Ecore_Evas *ee); + void (*fn_raise) (Ecore_Evas *ee); + void (*fn_lower) (Ecore_Evas *ee); + void (*fn_title_set) (Ecore_Evas *ee, const char *t); + void (*fn_name_class_set) (Ecore_Evas *ee, const char *n, const char *c); + void (*fn_size_min_set) (Ecore_Evas *ee, int w, int h); + void (*fn_size_max_set) (Ecore_Evas *ee, int w, int h); + void (*fn_size_base_set) (Ecore_Evas *ee, int w, int h); + void (*fn_size_step_set) (Ecore_Evas *ee, int w, int h); + void (*fn_cursor_set) (Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y); + void (*fn_layer_set) (Ecore_Evas *ee, int layer); + void (*fn_focus_set) (Ecore_Evas *ee, int on); + void (*fn_iconified_set) (Ecore_Evas *ee, int on); + void (*fn_borderless_set) (Ecore_Evas *ee, int on); + void (*fn_override_set) (Ecore_Evas *ee, int on); + void (*fn_maximized_set) (Ecore_Evas *ee, int on); + void (*fn_fullscreen_set) (Ecore_Evas *ee, int on); + void (*fn_avoid_damage_set) (Ecore_Evas *ee, int on); + void (*fn_withdrawn_set) (Ecore_Evas *ee, int withdrawn); + void (*fn_sticky_set) (Ecore_Evas *ee, int sticky); +}; + +struct _Ecore_Evas_Engine +{ + Ecore_Evas_Engine_Func *func; + +#ifdef BUILD_ECORE_X + struct { + Ecore_X_Window win_root; + Ecore_X_Window win_container; + Ecore_X_Window win; + Ecore_X_Pixmap pmap; + Ecore_X_Pixmap mask; + Ecore_X_GC gc; + Region damages; + unsigned char direct_resize : 1; + unsigned char using_bg_pixmap : 1; + struct { + /* + unsigned char modal : 1; + */ + unsigned char sticky : 1; + /* + unsigned char maximized_v : 1; + unsigned char maximized_h : 1; + unsigned char shaded : 1; + unsigned char skip_taskbar : 1; + unsigned char skip_pager : 1; + unsigned char fullscreen : 1; + */ + unsigned char above : 1; + unsigned char below : 1; + } state; + } x; +#endif +#ifdef BUILD_ECORE_EVAS_FB + struct { + int real_w; + int real_h; + } fb; +#endif +#ifdef BUILD_ECORE_EVAS_BUFFER + struct { + void *pixels; + Evas_Object *image; + } buffer; +#endif +}; + +struct _Ecore_Evas +{ + Ecore_List __list_data; + ECORE_MAGIC; + Evas *evas; + char *driver; + char *name; + int x, y, w, h; + short rotation; + char shaped : 1; + char visible : 1; + char should_be_visible : 1; + + Evas_Hash *data; + + struct { + int x, y; + } mouse; + + struct { + int w, h; + } expecting_resize; + + struct { + char *title; + char *name; + char *clas; + struct { + int w, h; + } min, + max, + base, + step; + struct { + Evas_Object *object; + char *file; + int layer; + struct { + int x, y; + } hot; + } cursor; + int layer; + char focused : 1; + char iconified : 1; + char borderless : 1; + char override : 1; + char maximized : 1; + char fullscreen : 1; + char avoid_damage : 1; + char withdrawn : 1; + char sticky : 1; + } prop; + + struct { + void (*fn_resize) (Ecore_Evas *ee); + void (*fn_move) (Ecore_Evas *ee); + void (*fn_show) (Ecore_Evas *ee); + void (*fn_hide) (Ecore_Evas *ee); + void (*fn_delete_request) (Ecore_Evas *ee); + void (*fn_destroy) (Ecore_Evas *ee); + void (*fn_focus_in) (Ecore_Evas *ee); + void (*fn_focus_out) (Ecore_Evas *ee); + void (*fn_mouse_in) (Ecore_Evas *ee); + void (*fn_mouse_out) (Ecore_Evas *ee); + void (*fn_pre_render) (Ecore_Evas *ee); + void (*fn_post_render) (Ecore_Evas *ee); + } func; + + Ecore_Evas_Engine engine; + Evas_List *sub_ecore_evas; +}; + +#ifdef BUILD_ECORE_X +int _ecore_evas_x_shutdown(void); +#endif +#ifdef BUILD_ECORE_EVAS_FB +int _ecore_evas_fb_shutdown(void); +#endif +#ifdef BUILD_ECORE_EVAS_BUFFER +int _ecore_evas_buffer_shutdown(void); +void _ecore_evas_buffer_render(Ecore_Evas *ee); +#endif + +void _ecore_evas_fps_debug_init(void); +void _ecore_evas_fps_debug_shutdown(void); +void _ecore_evas_fps_debug_rendertime_add(double t); + +#endif diff --git a/ecore/src/lib/ecore_evas/ecore_evas_x.c b/ecore/src/lib/ecore_evas/ecore_evas_x.c new file mode 100644 index 0000000..243ddb6 --- /dev/null +++ b/ecore/src/lib/ecore_evas/ecore_evas_x.c @@ -0,0 +1,1938 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "config.h" +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_evas_private.h" +#include "Ecore_Evas.h" +#ifdef BUILD_ECORE_X +#include "Ecore_X.h" +#endif + +#ifdef BUILD_ECORE_X +static int _ecore_evas_init_count = 0; + +static int _ecore_evas_fps_debug = 0; + +static Ecore_Evas *ecore_evases = NULL; +static Evas_Hash *ecore_evases_hash = NULL; +static Ecore_Event_Handler *ecore_evas_event_handlers[16]; +static Ecore_Idle_Enterer *ecore_evas_idle_enterer = NULL; + +static void +_ecore_evas_x_render(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_EVAS_BUFFER + Evas_List *ll; +#endif + +#ifdef BUILD_ECORE_EVAS_BUFFER + for (ll = ee->sub_ecore_evas; ll; ll = ll->next) + { + Ecore_Evas *ee2; + + ee2 = ll->data; + if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); + _ecore_evas_buffer_render(ee2); + if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); + } +#endif + if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); + if (ee->prop.avoid_damage) + { + Evas_List *updates, *l; + + updates = evas_render_updates(ee->evas); +#if 0 + for (l = updates; l; l = l->next) + { + Evas_Rectangle *r; + + r = l->data; + printf("DMG render [%p] %ix%i, [%i %i %ix%i]\n", + ee, ee->w, ee->h, r->x, r->y, r->w, r->h); + } +#endif + if (ee->engine.x.using_bg_pixmap) + { + if (updates) + { + for (l = updates; l; l = l->next) + { + Evas_Rectangle *r; + + r = l->data; + ecore_x_window_area_clear(ee->engine.x.win, r->x, r->y, r->w, r->h); + } + if ((ee->shaped) && (updates)) + { + if (ee->prop.fullscreen) + ecore_x_window_shape_mask_set(ee->engine.x.win, ee->engine.x.mask); + else + ecore_x_window_shape_mask_set(ee->engine.x.win_container, ee->engine.x.mask); + } + } + if (updates) evas_render_updates_free(updates); + } + else + { + for (l = updates; l; l = l->next) + { + Evas_Rectangle *r; + XRectangle xr; + Region tmpr; + + if (!ee->engine.x.damages) + ee->engine.x.damages = XCreateRegion(); + r = l->data; + tmpr = XCreateRegion(); + if (ee->rotation == 0) + { + xr.x = r->x; + xr.y = r->y; + xr.width = r->w; + xr.height = r->h; + } + else if (ee->rotation == 90) + { + xr.x = r->y; + xr.y = ee->h - r->x - r->w; + xr.width = r->h; + xr.height = r->w; + } + else if (ee->rotation == 180) + { + xr.x = ee->w - r->x - r->w; + xr.y = ee->h - r->y - r->h; + xr.width = r->w; + xr.height = r->h; + } + else if (ee->rotation == 270) + { + xr.x = ee->w - r->y - r->h; + xr.y = r->x; + xr.width = r->h; + xr.height = r->w; + } + XUnionRectWithRegion(&xr, ee->engine.x.damages, tmpr); + XDestroyRegion(ee->engine.x.damages); + ee->engine.x.damages = tmpr; + } + if (ee->engine.x.damages) + { + if ((ee->shaped) && (updates)) + { + if (ee->prop.fullscreen) + ecore_x_window_shape_mask_set(ee->engine.x.win, ee->engine.x.mask); + else + ecore_x_window_shape_mask_set(ee->engine.x.win_container, ee->engine.x.mask); + } + XSetRegion(ecore_x_display_get(), ee->engine.x.gc, ee->engine.x.damages); + /* debug rendering */ + /* + XSetForeground(ecore_x_display_get(), ee->engine.x.gc, rand()); + XFillRectangle(ecore_x_display_get(), ee->engine.x.win, ee->engine.x.gc, + 0, 0, ee->w, ee->h); + XSync(ecore_x_display_get(), False); + usleep(20000); + XSync(ecore_x_display_get(), False); + */ + ecore_x_pixmap_paste(ee->engine.x.pmap, ee->engine.x.win, ee->engine.x.gc, + 0, 0, ee->w, ee->h, 0, 0); + XDestroyRegion(ee->engine.x.damages); + ee->engine.x.damages = 0; + } + if (updates) evas_render_updates_free(updates); + } + } + else if ((ee->visible) || + ((ee->should_be_visible) && (ee->prop.fullscreen)) || + ((ee->should_be_visible) && (ee->prop.override))) + { + if (ee->shaped) + { + Evas_List *updates; + + updates = evas_render_updates(ee->evas); + if (updates) + { + if (ee->prop.fullscreen) + ecore_x_window_shape_mask_set(ee->engine.x.win, ee->engine.x.mask); + else + ecore_x_window_shape_mask_set(ee->engine.x.win_container, ee->engine.x.mask); + evas_render_updates_free(updates); + } + } + else + { + Evas_List *updates; + + updates = evas_render_updates(ee->evas); + if (updates) + { +#if 0 + Evas_List *l; + + printf("RENDER [%p] [%i] %ix%i\n", + ee, ee->visible, ee->w, ee->h); + for (l = updates; l; l = l->next) + { + Evas_Rectangle *r; + + r = l->data; + printf(" render [%i %i %ix%i]\n", + r->x, r->y, r->w, r->h); + } +#endif + evas_render_updates_free(updates); + } + } + } + if (ee->func.fn_post_render) ee->func.fn_post_render(ee); +} + +static void +_ecore_evas_x_mouse_move_process(Ecore_Evas *ee, int x, int y, unsigned int timestamp) +{ + ee->mouse.x = x; + ee->mouse.y = y; + if (ee->prop.cursor.object) + { + evas_object_show(ee->prop.cursor.object); + if (ee->rotation == 0) + evas_object_move(ee->prop.cursor.object, + x - ee->prop.cursor.hot.x, + y - ee->prop.cursor.hot.y); + else if (ee->rotation == 90) + evas_object_move(ee->prop.cursor.object, + ee->h - y - 1 - ee->prop.cursor.hot.x, + x - ee->prop.cursor.hot.y); + else if (ee->rotation == 180) + evas_object_move(ee->prop.cursor.object, + ee->w - x - 1 - ee->prop.cursor.hot.x, + ee->h - y - 1 - ee->prop.cursor.hot.y); + else if (ee->rotation == 270) + evas_object_move(ee->prop.cursor.object, + y - ee->prop.cursor.hot.x, + ee->w - x - 1 - ee->prop.cursor.hot.y); + } + if (ee->rotation == 0) + evas_event_feed_mouse_move(ee->evas, x, y, timestamp, NULL); + else if (ee->rotation == 90) + evas_event_feed_mouse_move(ee->evas, ee->h - y - 1, x, timestamp, NULL); + else if (ee->rotation == 180) + evas_event_feed_mouse_move(ee->evas, ee->w - x - 1, ee->h - y - 1, timestamp, NULL); + else if (ee->rotation == 270) + evas_event_feed_mouse_move(ee->evas, y, ee->w - x - 1, timestamp, NULL); +} + +static char * +_ecore_evas_x_winid_str_get(Ecore_X_Window win) +{ + const char *vals = "qWeRtYuIoP5-$&<~"; + static char id[9]; + unsigned int val; + + val = (unsigned int)win; + id[0] = vals[(val >> 28) & 0xf]; + id[1] = vals[(val >> 24) & 0xf]; + id[2] = vals[(val >> 20) & 0xf]; + id[3] = vals[(val >> 16) & 0xf]; + id[4] = vals[(val >> 12) & 0xf]; + id[5] = vals[(val >> 8) & 0xf]; + id[6] = vals[(val >> 4) & 0xf]; + id[7] = vals[(val ) & 0xf]; + id[8] = 0; + return id; +} + +static Ecore_Evas * +_ecore_evas_x_match(Ecore_X_Window win) +{ + return evas_hash_find(ecore_evases_hash, _ecore_evas_x_winid_str_get(win)); +} + +static void +_ecore_evas_x_resize_shape(Ecore_Evas *ee) +{ + Evas_Engine_Info_Software_X11 *einfo; + + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); + if (einfo) + { + GC gc; + XGCValues gcv; + + if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); + ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1); + gcv.foreground = 0; + gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, + GCForeground, + &gcv); + XFillRectangle(ecore_x_display_get(), ee->engine.x.mask, gc, + 0, 0, ee->w, ee->h); + XFreeGC(ecore_x_display_get(), gc); + einfo->info.mask = ee->engine.x.mask; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + + } +} + +static void +_ecore_evas_x_modifier_locks_update(Ecore_Evas *ee, int modifiers) +{ + if (modifiers & ECORE_X_MODIFIER_SHIFT) + evas_key_modifier_on(ee->evas, "Shift"); + else + evas_key_modifier_off(ee->evas, "Shift"); + if (modifiers & ECORE_X_MODIFIER_CTRL) + evas_key_modifier_on(ee->evas, "Control"); + else + evas_key_modifier_off(ee->evas, "Control"); + if (modifiers & ECORE_X_MODIFIER_ALT) + evas_key_modifier_on(ee->evas, "Alt"); + else + evas_key_modifier_off(ee->evas, "Alt"); + if (modifiers & ECORE_X_MODIFIER_WIN) + { + evas_key_modifier_on(ee->evas, "Super"); + evas_key_modifier_on(ee->evas, "Hyper"); + } + else + { + evas_key_modifier_off(ee->evas, "Super"); + evas_key_modifier_off(ee->evas, "Hyper"); + } + if (modifiers & ECORE_X_LOCK_SCROLL) + evas_key_lock_on(ee->evas, "Scroll_Lock"); + else + evas_key_lock_off(ee->evas, "Scroll_Lock"); + if (modifiers & ECORE_X_LOCK_NUM) + evas_key_lock_on(ee->evas, "Num_Lock"); + else + evas_key_lock_off(ee->evas, "Num_Lock"); + if (modifiers & ECORE_X_LOCK_CAPS) + evas_key_lock_on(ee->evas, "Caps_Lock"); + else + evas_key_lock_off(ee->evas, "Caps_Lock"); +} + +static int +_ecore_evas_x_event_key_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Key_Down *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + evas_event_feed_key_down(ee->evas, e->keyname, e->keysymbol, e->key_compose, NULL, e->time, NULL); + return 1; +} + +static int +_ecore_evas_x_event_key_up(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Key_Up *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + evas_event_feed_key_up(ee->evas, e->keyname, e->keysymbol, e->key_compose, NULL, e->time, NULL); + return 1; +} + +static int +_ecore_evas_x_event_mouse_button_down(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Mouse_Button_Down *e; + Evas_Button_Flags flags = EVAS_BUTTON_NONE; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); + if (e->double_click) flags |= EVAS_BUTTON_DOUBLE_CLICK; + if (e->triple_click) flags |= EVAS_BUTTON_TRIPLE_CLICK; + evas_event_feed_mouse_down(ee->evas, e->button, flags, e->time, NULL); + return 1; +} + +static int +_ecore_evas_x_event_mouse_button_up(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Mouse_Button_Up *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); + evas_event_feed_mouse_up(ee->evas, e->button, EVAS_BUTTON_NONE, e->time, NULL); + return 1; +} + +static int +_ecore_evas_x_event_mouse_wheel(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Mouse_Wheel *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + + if (!ee) + return 1; /* pass on event */ + + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); + evas_event_feed_mouse_wheel(ee->evas, e->direction, e->z, e->time, NULL); + + return 1; +} + +static int +_ecore_evas_x_event_mouse_move(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Mouse_Move *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); + return 1; +} + +static int +_ecore_evas_x_event_mouse_in(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Mouse_In *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (e->event_win == ee->engine.x.win_container) return 0; +/* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */ + if (ee->func.fn_mouse_in) ee->func.fn_mouse_in(ee); + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + evas_event_feed_mouse_in(ee->evas, e->time, NULL); + _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); + return 1; +} + +static int +_ecore_evas_x_event_mouse_out(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Mouse_Out *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (e->event_win == ee->engine.x.win_container) return 0; +/* if (e->mode != ECORE_X_EVENT_MODE_NORMAL) return 0; */ + _ecore_evas_x_modifier_locks_update(ee, e->modifiers); + _ecore_evas_x_mouse_move_process(ee, e->x, e->y, e->time); + evas_event_feed_mouse_out(ee->evas, e->time, NULL); + if (ee->func.fn_mouse_out) ee->func.fn_mouse_out(ee); + if (ee->prop.cursor.object) evas_object_hide(ee->prop.cursor.object); + return 1; +} + +static int +_ecore_evas_x_event_window_focus_in(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Focus_In *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + ee->prop.focused = 1; + if (ee->func.fn_focus_in) ee->func.fn_focus_in(ee); + return 1; +} + +static int +_ecore_evas_x_event_window_focus_out(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Focus_Out *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (ee->prop.fullscreen) + ecore_x_window_focus(ee->engine.x.win); + ee->prop.focused = 0; + if (ee->func.fn_focus_out) ee->func.fn_focus_out(ee); + return 1; +} + +static int +_ecore_evas_x_event_window_damage(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Damage *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (ee->engine.x.using_bg_pixmap) return 1; + if (ee->prop.avoid_damage) + { + XRectangle xr; + Region tmpr; + + if (!ee->engine.x.damages) ee->engine.x.damages = XCreateRegion(); + tmpr = XCreateRegion(); + xr.x = e->x; + xr.y = e->y; + xr.width = e->w; + xr.height = e->h; + XUnionRectWithRegion(&xr, ee->engine.x.damages, tmpr); + XDestroyRegion(ee->engine.x.damages); + ee->engine.x.damages = tmpr; + } + else + { + if (ee->rotation == 0) + evas_damage_rectangle_add(ee->evas, + e->x, + e->y, + e->w, e->h); + else if (ee->rotation == 90) + evas_damage_rectangle_add(ee->evas, + ee->h - e->y - e->h, + e->x, + e->h, e->w); + else if (ee->rotation == 180) + evas_damage_rectangle_add(ee->evas, + ee->w - e->x - e->w, + ee->h - e->y - e->h, + e->w, e->h); + else if (ee->rotation == 270) + evas_damage_rectangle_add(ee->evas, + e->y, + ee->w - e->x - e->w, + e->h, e->w); + } + return 1; +} + +static int +_ecore_evas_x_event_window_destroy(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Destroy *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (ee->func.fn_destroy) ee->func.fn_destroy(ee); + ecore_evas_free(ee); + return 1; +} + +static int +_ecore_evas_x_event_window_configure(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Configure *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if ((ee->prop.fullscreen) && (e->win == ee->engine.x.win_container)) return 0; + if (ee->engine.x.direct_resize) return 0; + + if ((e->from_wm) || (ee->prop.fullscreen) || (ee->prop.override)) + { + if ((ee->x != e->x) || (ee->y != e->y)) + { + ee->x = e->x; + ee->y = e->y; + if (ee->func.fn_move) ee->func.fn_move(ee); + } + } + if ((ee->w != e->w) || (ee->h != e->h)) + { + ee->w = e->w; + ee->h = e->h; + if (e->win == ee->engine.x.win_container) + ecore_x_window_move_resize(ee->engine.x.win, 0, 0, ee->w, ee->h); + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + evas_output_size_set(ee->evas, ee->h, ee->w); + evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + } + else + { + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + } + if (ee->prop.avoid_damage) + { + ecore_evas_avoid_damage_set(ee, 0); + ecore_evas_avoid_damage_set(ee, 1); + } + if (ee->shaped) + { + _ecore_evas_x_resize_shape(ee); + } + if ((ee->expecting_resize.w > 0) && + (ee->expecting_resize.h > 0)) + { + if ((ee->expecting_resize.w == ee->w) && + (ee->expecting_resize.h == ee->h)) + _ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, + ecore_x_current_time_get()); + ee->expecting_resize.w = 0; + ee->expecting_resize.h = 0; + } + if (ee->func.fn_resize) ee->func.fn_resize(ee); + } + return 1; +} + +static int +_ecore_evas_x_event_window_delete_request(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Delete_Request *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (ee->func.fn_delete_request) ee->func.fn_delete_request(ee); + return 1; +} + +static int +_ecore_evas_x_event_window_show(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Show *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (ee->visible) return 0; /* dont pass it on */ + ee->visible = 1; + if (ee->func.fn_show) ee->func.fn_show(ee); + return 1; +} + +static int +_ecore_evas_x_event_window_hide(void *data __UNUSED__, int type __UNUSED__, void *event) +{ + Ecore_Evas *ee; + Ecore_X_Event_Window_Hide *e; + + e = event; + ee = _ecore_evas_x_match(e->win); + if (!ee) return 1; /* pass on event */ + if (!ee->visible) return 0; /* dont pass it on */ + ee->visible = 0; + if (ee->func.fn_hide) ee->func.fn_hide(ee); + return 1; +} + +/* FIXME, should be in idler */ +static void +_ecore_evas_x_size_pos_hints_update(Ecore_Evas *ee) +{ + ecore_x_icccm_size_pos_hints_set(ee->engine.x.win_container, + 1 /*request_pos */, + ECORE_X_GRAVITY_NW /* gravity */, + ee->prop.min.w /* min_w */, + ee->prop.min.h /* min_h */, + ee->prop.max.w /* max_w */, + ee->prop.max.h /* max_h */, + ee->prop.base.w /* base_w */, + ee->prop.base.h /* base_h */, + ee->prop.step.w /* step_x */, + ee->prop.step.h /* step_y */, + 0 /* min_aspect */, + 0 /* max_aspect */); +} + +/* FIXME, should be in idler */ +static void +_ecore_evas_x_state_update(Ecore_Evas *ee) +{ + Ecore_X_Window_State state[10]; + int num; + + num = 0; + + /* + if (bd->client.netwm.state.modal) + state[num++] = ECORE_X_WINDOW_STATE_MODAL; + */ + if (ee->engine.x.state.sticky) + state[num++] = ECORE_X_WINDOW_STATE_STICKY; + /* + if (bd->client.netwm.state.maximized_v) + state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_VERT; + if (bd->client.netwm.state.maximized_h) + state[num++] = ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ; + if (bd->client.netwm.state.shaded) + state[num++] = ECORE_X_WINDOW_STATE_SHADED; + if (bd->client.netwm.state.skip_taskbar) + state[num++] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR; + if (bd->client.netwm.state.skip_pager) + state[num++] = ECORE_X_WINDOW_STATE_SKIP_PAGER; + if (bd->client.netwm.state.hidden) + state[num++] = ECORE_X_WINDOW_STATE_HIDDEN; + if (bd->client.netwm.state.fullscreen) + state[num++] = ECORE_X_WINDOW_STATE_FULLSCREEN; + */ + if (ee->engine.x.state.above) + state[num++] = ECORE_X_WINDOW_STATE_ABOVE; + if (ee->engine.x.state.below) + state[num++] = ECORE_X_WINDOW_STATE_BELOW; + + ecore_x_netwm_window_state_set(ee->engine.x.win_container, state, num); +} + +void +_ecore_evas_x_layer_update(Ecore_Evas *ee) +{ + if (ee->should_be_visible) + { + /* We need to send a netwm request to the wm */ + /* FIXME: Do we have to remove old state before adding new? */ + if (ee->prop.layer < 3) + { + if (ee->engine.x.state.above) + { + ee->engine.x.state.above = 0; + ecore_x_netwm_state_request_send(ee->engine.x.win_container, + ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_ABOVE, -1, 0); + } + if (!ee->engine.x.state.below) + { + ee->engine.x.state.below = 1; + ecore_x_netwm_state_request_send(ee->engine.x.win_container, + ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_BELOW, -1, 1); + } + } + else if (ee->prop.layer > 5) + { + if (ee->engine.x.state.below) + { + ee->engine.x.state.below = 0; + ecore_x_netwm_state_request_send(ee->engine.x.win_container, + ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_BELOW, -1, 0); + } + if (!ee->engine.x.state.above) + { + ee->engine.x.state.above = 1; + ecore_x_netwm_state_request_send(ee->engine.x.win_container, + ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_ABOVE, -1, 1); + } + } + else + { + if (ee->engine.x.state.below) + { + ee->engine.x.state.below = 0; + ecore_x_netwm_state_request_send(ee->engine.x.win_container, + ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_BELOW, -1, 0); + } + if (ee->engine.x.state.above) + { + ee->engine.x.state.above = 0; + ecore_x_netwm_state_request_send(ee->engine.x.win_container, + ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_ABOVE, -1, 0); + } + } + } + else + { + /* Just set the state */ + if (ee->prop.layer < 3) + { + if ((ee->engine.x.state.above) || (!ee->engine.x.state.below)) + { + ee->engine.x.state.above = 0; + ee->engine.x.state.below = 1; + _ecore_evas_x_state_update(ee); + } + } + else if (ee->prop.layer > 5) + { + if ((!ee->engine.x.state.above) || (ee->engine.x.state.below)) + { + ee->engine.x.state.above = 1; + ee->engine.x.state.below = 0; + _ecore_evas_x_state_update(ee); + } + } + else + { + if ((ee->engine.x.state.above) || (ee->engine.x.state.below)) + { + ee->engine.x.state.above = 0; + ee->engine.x.state.below = 0; + _ecore_evas_x_state_update(ee); + } + } + } + /* FIXME: Set gnome layer */ +} + +static int +_ecore_evas_x_idle_enter(void *data __UNUSED__) +{ + Ecore_Oldlist *l; + double t1 = 0.0; + double t2 = 0.0; + + if (_ecore_evas_fps_debug) + { + t1 = ecore_time_get(); + } + for (l = (Ecore_Oldlist *)ecore_evases; l; l = l->next) + { + Ecore_Evas *ee; + + ee = (Ecore_Evas *)l; + _ecore_evas_x_render(ee); + } + ecore_x_flush(); + if (_ecore_evas_fps_debug) + { + t2 = ecore_time_get(); + _ecore_evas_fps_debug_rendertime_add(t2 - t1); + } + return 1; +} + +static int +_ecore_evas_x_init(void) +{ + _ecore_evas_init_count++; + if (_ecore_evas_init_count > 1) return _ecore_evas_init_count; + if (getenv("ECORE_EVAS_FPS_DEBUG")) _ecore_evas_fps_debug = 1; + ecore_evas_idle_enterer = ecore_idle_enterer_add(_ecore_evas_x_idle_enter, NULL); + ecore_evas_event_handlers[0] = ecore_event_handler_add(ECORE_X_EVENT_KEY_DOWN, _ecore_evas_x_event_key_down, NULL); + ecore_evas_event_handlers[1] = ecore_event_handler_add(ECORE_X_EVENT_KEY_UP, _ecore_evas_x_event_key_up, NULL); + ecore_evas_event_handlers[2] = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_DOWN, _ecore_evas_x_event_mouse_button_down, NULL); + ecore_evas_event_handlers[3] = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_BUTTON_UP, _ecore_evas_x_event_mouse_button_up, NULL); + ecore_evas_event_handlers[4] = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_MOVE, _ecore_evas_x_event_mouse_move, NULL); + ecore_evas_event_handlers[5] = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_IN, _ecore_evas_x_event_mouse_in, NULL); + ecore_evas_event_handlers[6] = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_OUT, _ecore_evas_x_event_mouse_out, NULL); + ecore_evas_event_handlers[7] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_IN, _ecore_evas_x_event_window_focus_in, NULL); + ecore_evas_event_handlers[8] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_FOCUS_OUT, _ecore_evas_x_event_window_focus_out, NULL); + ecore_evas_event_handlers[9] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DAMAGE, _ecore_evas_x_event_window_damage, NULL); + ecore_evas_event_handlers[10] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DESTROY, _ecore_evas_x_event_window_destroy, NULL); + ecore_evas_event_handlers[11] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_CONFIGURE, _ecore_evas_x_event_window_configure, NULL); + ecore_evas_event_handlers[12] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_DELETE_REQUEST, _ecore_evas_x_event_window_delete_request, NULL); + ecore_evas_event_handlers[13] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_SHOW, _ecore_evas_x_event_window_show, NULL); + ecore_evas_event_handlers[14] = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_HIDE, _ecore_evas_x_event_window_hide, NULL); + ecore_evas_event_handlers[15] = ecore_event_handler_add(ECORE_X_EVENT_MOUSE_WHEEL, _ecore_evas_x_event_mouse_wheel, NULL); + if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_init(); + return _ecore_evas_init_count; +} + +static void +_ecore_evas_x_free(Ecore_Evas *ee) +{ + ecore_x_window_del(ee->engine.x.win); + ecore_x_window_del(ee->engine.x.win_container); + if (ee->engine.x.pmap) ecore_x_pixmap_del(ee->engine.x.pmap); + if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); + if (ee->engine.x.gc) ecore_x_gc_del(ee->engine.x.gc); + if (ee->engine.x.damages) XDestroyRegion(ee->engine.x.damages); + ee->engine.x.pmap = 0; + ee->engine.x.mask = 0; + ee->engine.x.gc = 0; + ee->engine.x.damages = 0; + ecore_evases_hash = evas_hash_del(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win), ee); + ecore_evases_hash = evas_hash_del(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win_container), ee); + ecore_evases = _ecore_list_remove(ecore_evases, ee); + _ecore_evas_x_shutdown(); + ecore_x_shutdown(); +} + +static void +_ecore_evas_x_callback_delete_request_set(Ecore_Evas *ee, void (*func) (Ecore_Evas *ee)) +{ + if (func) + ecore_x_icccm_protocol_set(ee->engine.x.win_container, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 1); + else + ecore_x_icccm_protocol_set(ee->engine.x.win_container, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 0); + ee->func.fn_delete_request = func; +} + +static void +_ecore_evas_x_move(Ecore_Evas *ee, int x, int y) +{ + ecore_x_window_move(ee->engine.x.win_container, x, y); + if (!ee->should_be_visible) + { + /* We need to request pos */ + _ecore_evas_x_size_pos_hints_update(ee); + } +} + +static void +_ecore_evas_x_resize(Ecore_Evas *ee, int w, int h) +{ + ecore_x_window_resize(ee->engine.x.win_container, w, h); + if (ee->engine.x.direct_resize) + { + ecore_x_window_move_resize(ee->engine.x.win, 0, 0, w, h); + if ((ee->w != w) || (ee->h != h)) + { + ee->w = w; + ee->h = h; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + evas_output_size_set(ee->evas, ee->h, ee->w); + evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + } + else + { + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + } + if (ee->prop.avoid_damage) + { + ecore_evas_avoid_damage_set(ee, 0); + ecore_evas_avoid_damage_set(ee, 1); + } + if (ee->shaped) + { + _ecore_evas_x_resize_shape(ee); + } + } + } +} + +static void +_ecore_evas_x_move_resize(Ecore_Evas *ee, int x, int y, int w, int h) +{ + ecore_x_window_move_resize(ee->engine.x.win_container, x, y, w, h); + if (ee->engine.x.direct_resize) + { + ecore_x_window_move_resize(ee->engine.x.win, 0, 0, w, h); + if ((ee->w != w) || (ee->h != h)) + { + ee->w = w; + ee->h = h; + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + evas_output_size_set(ee->evas, ee->h, ee->w); + evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + } + else + { + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + } + if (ee->prop.avoid_damage) + { + ecore_evas_avoid_damage_set(ee, 0); + ecore_evas_avoid_damage_set(ee, 1); + } + if (ee->shaped) + { + _ecore_evas_x_resize_shape(ee); + } + } + } +} + +static void +_ecore_evas_x_rotation_set(Ecore_Evas *ee, int rotation) +{ + Evas_Engine_Info_Software_X11 *einfo; + int rot_dif; + + if (ee->rotation == rotation) return; + if (!strcmp(ee->driver, "gl_x11")) return; + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); + if (!einfo) return; + rot_dif = ee->rotation - rotation; + if (rot_dif < 0) rot_dif = -rot_dif; + if (rot_dif != 180) + { + int minw, minh, maxw, maxh, basew, baseh, stepw, steph; + + einfo->info.rotation = rotation; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + if (!ee->prop.fullscreen) + { + ecore_x_window_resize(ee->engine.x.win_container, ee->h, ee->w); + ee->expecting_resize.w = ee->h; + ee->expecting_resize.h = ee->w; + } + else + { + int w, h; + + ecore_x_window_size_get(ee->engine.x.win_container, &w, &h); + ecore_x_window_resize(ee->engine.x.win_container, h, w); + if ((rotation == 0) || (rotation == 180)) + { + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + } + else + { + evas_output_size_set(ee->evas, ee->h, ee->w); + evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + } + if (ee->func.fn_resize) ee->func.fn_resize(ee); + } + ecore_evas_size_min_get(ee, &minw, &minh); + ecore_evas_size_max_get(ee, &maxw, &maxh); + ecore_evas_size_base_get(ee, &basew, &baseh); + ecore_evas_size_step_get(ee, &stepw, &steph); + ee->rotation = rotation; + ecore_evas_size_min_set(ee, minh, minw); + ecore_evas_size_max_set(ee, maxh, maxw); + ecore_evas_size_base_set(ee, baseh, basew); + ecore_evas_size_step_set(ee, steph, stepw); + _ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, + ecore_x_current_time_get()); + } + else + { + einfo->info.rotation = rotation; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + ee->rotation = rotation; + _ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, + ecore_x_current_time_get()); + if (ee->func.fn_resize) ee->func.fn_resize(ee); + } + if ((ee->rotation == 90) || (ee->rotation == 270)) + evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w); + else + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); +} + +static void +_ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped) +{ + Evas_Engine_Info_Software_X11 *einfo; + + if (((ee->shaped) && (shaped)) || + ((!ee->shaped) && (!shaped))) + return; + if (!strcmp(ee->driver, "gl_x11")) return; + ee->shaped = shaped; + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); + if (einfo) + { + if (ee->shaped) + { + GC gc; + XGCValues gcv; + + ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1); + gcv.foreground = 0; + gc = XCreateGC(ecore_x_display_get(), ee->engine.x.mask, + GCForeground, + &gcv); + XFillRectangle(ecore_x_display_get(), ee->engine.x.mask, gc, + 0, 0, ee->w, ee->h); + XFreeGC(ecore_x_display_get(), gc); + einfo->info.mask = ee->engine.x.mask; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + } + else + { + if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask); + ee->engine.x.mask = 0; + einfo->info.mask = 0; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + ecore_x_window_shape_mask_set(ee->engine.x.win, 0); + ecore_x_window_shape_mask_set(ee->engine.x.win_container, 0); + } + } +} + +static void +_ecore_evas_x_show(Ecore_Evas *ee) +{ + ee->should_be_visible = 1; + if (ee->prop.avoid_damage) + _ecore_evas_x_render(ee); + if (!ee->prop.fullscreen) + ecore_x_window_show(ee->engine.x.win_container); + ecore_x_window_show(ee->engine.x.win); + if (ee->prop.fullscreen) + ecore_x_window_focus(ee->engine.x.win); +} + +static void +_ecore_evas_x_hide(Ecore_Evas *ee) +{ + if (!ee->prop.fullscreen) + ecore_x_window_hide(ee->engine.x.win_container); + ecore_x_window_hide(ee->engine.x.win); + ee->should_be_visible = 0; +} + +static void +_ecore_evas_x_raise(Ecore_Evas *ee) +{ + if (!ee->prop.fullscreen) + ecore_x_window_raise(ee->engine.x.win_container); + else + ecore_x_window_raise(ee->engine.x.win); +} + +static void +_ecore_evas_x_lower(Ecore_Evas *ee) +{ + if (!ee->prop.fullscreen) + ecore_x_window_lower(ee->engine.x.win_container); + else + ecore_x_window_lower(ee->engine.x.win); +} + +static void +_ecore_evas_x_title_set(Ecore_Evas *ee, const char *t) +{ + if (ee->prop.title) free(ee->prop.title); + ee->prop.title = NULL; + if (t) ee->prop.title = strdup(t); + ecore_x_icccm_title_set(ee->engine.x.win_container, ee->prop.title); + ecore_x_netwm_name_set(ee->engine.x.win_container, ee->prop.title); +} + +static void +_ecore_evas_x_name_class_set(Ecore_Evas *ee, const char *n, const char *c) +{ + if (ee->prop.name) free(ee->prop.name); + if (ee->prop.clas) free(ee->prop.clas); + ee->prop.name = NULL; + ee->prop.clas = NULL; + ee->prop.name = strdup(n); + ee->prop.clas = strdup(c); + ecore_x_icccm_name_class_set(ee->engine.x.win_container, ee->prop.name, ee->prop.clas); +} + +static void +_ecore_evas_x_size_min_set(Ecore_Evas *ee, int w, int h) +{ + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->prop.min.w == w) && (ee->prop.min.h == h)) return; + ee->prop.min.w = w; + ee->prop.min.h = h; + _ecore_evas_x_size_pos_hints_update(ee); +} + +static void +_ecore_evas_x_size_max_set(Ecore_Evas *ee, int w, int h) +{ + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->prop.max.w == w) && (ee->prop.max.h == h)) return; + ee->prop.max.w = w; + ee->prop.max.h = h; + _ecore_evas_x_size_pos_hints_update(ee); +} + +static void +_ecore_evas_x_size_base_set(Ecore_Evas *ee, int w, int h) +{ + if (w < 0) w = 0; + if (h < 0) h = 0; + if ((ee->prop.base.w == w) && (ee->prop.base.h == h)) return; + ee->prop.base.w = w; + ee->prop.base.h = h; + _ecore_evas_x_size_pos_hints_update(ee); +} + +static void +_ecore_evas_x_size_step_set(Ecore_Evas *ee, int w, int h) +{ + if (w < 1) w = 1; + if (h < 1) h = 1; + if ((ee->prop.step.w == w) && (ee->prop.step.h == h)) return; + ee->prop.step.w = w; + ee->prop.step.h = h; + _ecore_evas_x_size_pos_hints_update(ee); +} + +static void +_ecore_evas_x_cursor_set(Ecore_Evas *ee, const char *file, int layer, int hot_x, int hot_y) +{ + int x, y; + + if (!file) + { + if (ee->prop.cursor.object) evas_object_del(ee->prop.cursor.object); + if (ee->prop.cursor.file) free(ee->prop.cursor.file); + ee->prop.cursor.object = NULL; + ee->prop.cursor.file = NULL; + ee->prop.cursor.layer = 0; + ee->prop.cursor.hot.x = 0; + ee->prop.cursor.hot.y = 0; + ecore_x_window_cursor_show(ee->engine.x.win, 1); + return; + } + ecore_x_window_cursor_show(ee->engine.x.win, 0); + if (!ee->prop.cursor.object) ee->prop.cursor.object = evas_object_image_add(ee->evas); + if (ee->prop.cursor.file) free(ee->prop.cursor.file); + ee->prop.cursor.file = strdup(file); + ee->prop.cursor.layer = layer; + ee->prop.cursor.hot.x = hot_x; + ee->prop.cursor.hot.y = hot_y; + evas_pointer_output_xy_get(ee->evas, &x, &y); + evas_object_layer_set(ee->prop.cursor.object, ee->prop.cursor.layer); + evas_object_color_set(ee->prop.cursor.object, 255, 255, 255, 255); + evas_object_move(ee->prop.cursor.object, + x - ee->prop.cursor.hot.x, + y - ee->prop.cursor.hot.y); + evas_object_image_file_set(ee->prop.cursor.object, ee->prop.cursor.file, NULL); + evas_object_image_size_get(ee->prop.cursor.object, &x, &y); + evas_object_resize(ee->prop.cursor.object, x, y); + evas_object_image_fill_set(ee->prop.cursor.object, 0, 0, x, y); + evas_object_pass_events_set(ee->prop.cursor.object, 1); + if (evas_pointer_inside_get(ee->evas)) + evas_object_show(ee->prop.cursor.object); +} + +/* + * @param ee + * @param layer If < 3, @a ee will be put below all other windows. + * If > 5, @a ee will be "always-on-top" + * If = 4, @a ee will be put in the default layer. + * Acceptable values range from 1 to 255 (0 reserved for + * desktop windows) + */ +static void +_ecore_evas_x_layer_set(Ecore_Evas *ee, int layer) +{ + if (ee->prop.layer == layer) return; + + /* FIXME: Should this logic be here? */ + if (layer < 1) + layer = 1; + else if (layer > 255) + layer = 255; + + ee->prop.layer = layer; + _ecore_evas_x_layer_update(ee); +} + +static void +_ecore_evas_x_focus_set(Ecore_Evas *ee, int on __UNUSED__) +{ + ecore_x_window_focus(ee->engine.x.win_container); +} + +static void +_ecore_evas_x_iconified_set(Ecore_Evas *ee, int on) +{ + if (((ee->prop.iconified) && (on)) || + ((!ee->prop.iconified) && (!on))) return; + ee->prop.iconified = on; + if (on) + { + ecore_x_icccm_hints_set(ee->engine.x.win_container, + 1 /* accepts_focus */, + ECORE_X_WINDOW_STATE_HINT_ICONIC /* initial_state */, + 0 /* icon_pixmap */, + 0 /* icon_mask */, + 0 /* icon_window */, + 0 /* window_group */, + 0 /* is_urgent */); + ecore_x_icccm_iconic_request_send(ee->engine.x.win_container, ee->engine.x.win_root); + } + else + { + ecore_x_icccm_hints_set(ee->engine.x.win_container, + 1 /* accepts_focus */, + ECORE_X_WINDOW_STATE_HINT_NORMAL /* initial_state */, + 0 /* icon_pixmap */, + 0 /* icon_mask */, + 0 /* icon_window */, + 0 /* window_group */, + 0 /* is_urgent */); + ecore_evas_show(ee); + } +} + +static void +_ecore_evas_x_borderless_set(Ecore_Evas *ee, int on) +{ + if (((ee->prop.borderless) && (on)) || + ((!ee->prop.borderless) && (!on))) return; + ee->prop.borderless = on; + ecore_x_mwm_borderless_set(ee->engine.x.win_container, ee->prop.borderless); +} + +/* FIXME: This function changes the initial state of the ee + * whilest the iconic function changes the current state! */ +static void +_ecore_evas_x_withdrawn_set(Ecore_Evas *ee, int withdrawn) +{ + Ecore_X_Window_State_Hint hint; + + if ((ee->prop.withdrawn && withdrawn) || + (!ee->prop.withdrawn && !withdrawn)) return; + + ee->prop.withdrawn = withdrawn; + if (withdrawn) + hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else + hint = ECORE_X_WINDOW_STATE_HINT_NORMAL; + + ecore_x_icccm_hints_set(ee->engine.x.win_container, + 1 /* accepts_focus */, + hint /* initial_state */, + 0 /* icon_pixmap */, + 0 /* icon_mask */, + 0 /* icon_window */, + 0 /* window_group */, + 0 /* is_urgent */); +} + +static void +_ecore_evas_x_sticky_set(Ecore_Evas *ee, int sticky) +{ + if ((ee->prop.sticky && sticky) || + (!ee->prop.sticky && !sticky)) return; + + ee->prop.sticky = sticky; + ee->engine.x.state.sticky = sticky; + if (ee->should_be_visible) + ecore_x_netwm_state_request_send(ee->engine.x.win_container, ee->engine.x.win_root, + ECORE_X_WINDOW_STATE_STICKY, -1, sticky); + else + _ecore_evas_x_state_update(ee); +} + +static void +_ecore_evas_x_override_set(Ecore_Evas *ee, int on) +{ + if (((ee->prop.override) && (on)) || + ((!ee->prop.override) && (!on))) return; + ecore_x_window_hide(ee->engine.x.win); + ecore_x_window_reparent(ee->engine.x.win, ee->engine.x.win_root, 0, 0); + ecore_x_window_del(ee->engine.x.win_container); + ecore_evases_hash = evas_hash_del(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win_container), ee); + if (on) + ee->engine.x.win_container = ecore_x_window_override_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h); + else + { + Ecore_X_Window_State_Hint hint; + if (ee->prop.withdrawn) + hint = ECORE_X_WINDOW_STATE_HINT_WITHDRAWN; + else + hint = ECORE_X_WINDOW_STATE_HINT_NORMAL; + + ee->engine.x.win_container = ecore_x_window_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h); + ecore_x_icccm_title_set(ee->engine.x.win_container, ee->prop.title); + ecore_x_netwm_name_set(ee->engine.x.win_container, ee->prop.title); + ecore_x_icccm_name_class_set(ee->engine.x.win_container, ee->prop.name, ee->prop.clas); + if (ee->func.fn_delete_request) + ecore_x_icccm_protocol_set(ee->engine.x.win_container, ECORE_X_WM_PROTOCOL_DELETE_REQUEST, 1); + _ecore_evas_x_size_pos_hints_update(ee); + ecore_x_mwm_borderless_set(ee->engine.x.win_container, ee->prop.borderless); + _ecore_evas_x_layer_update(ee); + ecore_x_icccm_hints_set(ee->engine.x.win_container, 1 /* accepts_focus */, + hint /* initial_state */, 0 /* icon_pixmap */, 0 /* icon_mask */, + 0 /* icon_window */, 0 /* window_group */, 0 /* is_urgent */); + _ecore_evas_x_state_update(ee); + } + ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win_container), ee); + ecore_x_window_reparent(ee->engine.x.win, ee->engine.x.win_container, 0, 0); + ecore_x_window_show(ee->engine.x.win); + if (ee->visible) ecore_x_window_show(ee->engine.x.win_container); + if (ee->prop.focused) ecore_x_window_focus(ee->engine.x.win_container); + ee->prop.override = on; +} + +static void +_ecore_evas_x_fullscreen_set(Ecore_Evas *ee, int on) +{ + if (((ee->prop.fullscreen) && (on)) || + ((!ee->prop.fullscreen) && (!on))) return; + if (on) + { + int rw, rh; + + ecore_x_window_size_get(0, &rw, &rh); + ecore_x_window_move_resize(ee->engine.x.win, 0, 0, rw, rh); + ecore_x_window_reparent(ee->engine.x.win, ee->engine.x.win_root, 0, 0); + ecore_x_window_raise(ee->engine.x.win); + ecore_x_window_show(ee->engine.x.win); + ecore_x_window_focus(ee->engine.x.win); + ecore_x_window_hide(ee->engine.x.win_container); + ecore_x_window_shape_mask_set(ee->engine.x.win_container, 0); + if (ee->should_be_visible) + { + ecore_x_window_show(ee->engine.x.win); + ecore_x_window_focus(ee->engine.x.win); + } + ee->x = 0; + ee->y = 0; + ee->w = rw; + ee->h = rh; + } + else + { + int pw, ph; + + ecore_x_window_size_get(ee->engine.x.win_container, &pw, &ph); + ecore_x_window_reparent(ee->engine.x.win, ee->engine.x.win_container, 0, 0); + ecore_x_window_move_resize(ee->engine.x.win, 0, 0, pw, ph); + ecore_x_window_shape_mask_set(ee->engine.x.win, 0); + if (ee->should_be_visible) ecore_x_window_show(ee->engine.x.win_container); + ee->w = pw; + ee->h = ph; + } + ecore_x_window_move_resize(ee->engine.x.win, 0, 0, ee->w, ee->h); + if ((ee->rotation == 90) || (ee->rotation == 270)) + { + evas_output_size_set(ee->evas, ee->h, ee->w); + evas_output_viewport_set(ee->evas, 0, 0, ee->h, ee->w); + } + else + { + evas_output_size_set(ee->evas, ee->w, ee->h); + evas_output_viewport_set(ee->evas, 0, 0, ee->w, ee->h); + } + if (ee->prop.avoid_damage) + { + ecore_evas_avoid_damage_set(ee, 0); + ecore_evas_avoid_damage_set(ee, 1); + } + if (ee->shaped) + { + _ecore_evas_x_resize_shape(ee); + } + if ((ee->expecting_resize.w > 0) && + (ee->expecting_resize.h > 0)) + { + if ((ee->expecting_resize.w == ee->w) && + (ee->expecting_resize.h == ee->h)) + _ecore_evas_x_mouse_move_process(ee, ee->mouse.x, ee->mouse.y, + ecore_x_current_time_get()); + ee->expecting_resize.w = 0; + ee->expecting_resize.h = 0; + } + ee->prop.fullscreen = on; + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +static void +_ecore_evas_x_avoid_damage_set(Ecore_Evas *ee, int on) +{ + Evas_Engine_Info_Software_X11 *einfo; + + if (((ee->prop.avoid_damage) && (on)) || + ((!ee->prop.avoid_damage) && (!on))) + return; + if (!strcmp(ee->driver, "gl_x11")) return; + ee->prop.avoid_damage = on; + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); + if (einfo) + { + if (ee->prop.avoid_damage) + { + ee->engine.x.pmap = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 0); + ee->engine.x.gc = ecore_x_gc_new(ee->engine.x.pmap); + einfo->info.drawable = ee->engine.x.pmap; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + if ((ee->rotation == 90) || (ee->rotation == 270)) + evas_damage_rectangle_add(ee->evas, 0, 0, ee->h, ee->w); + else + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + if (ee->engine.x.direct_resize) + { +/* Turn this off for now + ee->engine.x.using_bg_pixmap = 1; + ecore_x_window_pixmap_set(ee->engine.x.win, ee->engine.x.pmap); + */ + } + } + else + { + if (ee->engine.x.pmap) ecore_x_pixmap_del(ee->engine.x.pmap); + if (ee->engine.x.gc) ecore_x_gc_del(ee->engine.x.gc); + if (ee->engine.x.using_bg_pixmap) + { + ecore_x_window_pixmap_set(ee->engine.x.win, 0); + ee->engine.x.using_bg_pixmap = 0; + } + ee->engine.x.pmap = 0; + ee->engine.x.gc = 0; + einfo->info.drawable = ee->engine.x.win; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + } +} + +int +_ecore_evas_x_shutdown(void) +{ + _ecore_evas_init_count--; + if (_ecore_evas_init_count == 0) + { + int i; + + while (ecore_evases) ecore_evas_free(ecore_evases); + for (i = 0; i < 16; i++) + ecore_event_handler_del(ecore_evas_event_handlers[i]); + ecore_idle_enterer_del(ecore_evas_idle_enterer); + ecore_evas_idle_enterer = NULL; + if (_ecore_evas_fps_debug) _ecore_evas_fps_debug_shutdown(); + } + if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0; + return _ecore_evas_init_count; +} + +static const Ecore_Evas_Engine_Func _ecore_x_engine_func = +{ + _ecore_evas_x_free, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_x_callback_delete_request_set, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + _ecore_evas_x_move, + _ecore_evas_x_resize, + _ecore_evas_x_move_resize, + _ecore_evas_x_rotation_set, + _ecore_evas_x_shaped_set, + _ecore_evas_x_show, + _ecore_evas_x_hide, + _ecore_evas_x_raise, + _ecore_evas_x_lower, + _ecore_evas_x_title_set, + _ecore_evas_x_name_class_set, + _ecore_evas_x_size_min_set, + _ecore_evas_x_size_max_set, + _ecore_evas_x_size_base_set, + _ecore_evas_x_size_step_set, + _ecore_evas_x_cursor_set, + _ecore_evas_x_layer_set, + _ecore_evas_x_focus_set, + _ecore_evas_x_iconified_set, + _ecore_evas_x_borderless_set, + _ecore_evas_x_override_set, + NULL, + _ecore_evas_x_fullscreen_set, + _ecore_evas_x_avoid_damage_set, + _ecore_evas_x_withdrawn_set, + _ecore_evas_x_sticky_set +}; +#endif + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_Evas * +ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent, + int x, int y, int w, int h) +{ +#ifdef BUILD_ECORE_X + Evas_Engine_Info_Software_X11 *einfo; + Ecore_Evas *ee; + int rmethod; + + rmethod = evas_render_method_lookup("software_x11"); + if (!rmethod) return NULL; + if (!ecore_x_init(disp_name)) return NULL; + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + _ecore_evas_x_init(); + + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func; + + ee->driver = strdup("software_x11"); + if (disp_name) ee->name = strdup(disp_name); + + if (w < 1) w = 1; + if (h < 1) h = 1; + ee->x = x; + ee->y = y; + ee->w = w; + ee->h = h; + + ee->prop.max.w = 32767; + ee->prop.max.h = 32767; + ee->prop.layer = 4; + + /* init evas here */ + ee->evas = evas_new(); + evas_output_method_set(ee->evas, rmethod); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + ee->engine.x.win_root = parent; + ee->engine.x.win_container = ecore_x_window_new(parent, x, y, w, h); + ee->engine.x.win = ecore_x_window_override_new(ee->engine.x.win_container, 0, 0, w, h); + + einfo = (Evas_Engine_Info_Software_X11 *)evas_engine_info_get(ee->evas); + if (einfo) + { + int screen; + + /* FIXME: this is inefficient as its a round trip */ + screen = DefaultScreen(ecore_x_display_get()); + if (ScreenCount(ecore_x_display_get()) > 1) + { + Ecore_X_Window *roots; + int num, i; + + num = 0; + roots = ecore_x_window_root_list(&num); + if (roots) + { + XWindowAttributes at; + + if (XGetWindowAttributes(ecore_x_display_get(), + parent, &at)) + { + for (i = 0; i < num; i++) + { + if (at.root == roots[i]) + { + screen = i; + break; + } + } + } + free(roots); + } + } + einfo->info.display = ecore_x_display_get(); + einfo->info.visual = DefaultVisual(ecore_x_display_get(), screen); + einfo->info.colormap = DefaultColormap(ecore_x_display_get(), screen); + einfo->info.drawable = ee->engine.x.win; + einfo->info.depth = DefaultDepth(ecore_x_display_get(), screen); + einfo->info.rotation = 0; + einfo->info.debug = 0; + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + evas_key_modifier_add(ee->evas, "Shift"); + evas_key_modifier_add(ee->evas, "Control"); + evas_key_modifier_add(ee->evas, "Alt"); + evas_key_modifier_add(ee->evas, "Meta"); + evas_key_modifier_add(ee->evas, "Hyper"); + evas_key_modifier_add(ee->evas, "Super"); + evas_key_lock_add(ee->evas, "Caps_Lock"); + evas_key_lock_add(ee->evas, "Num_Lock"); + evas_key_lock_add(ee->evas, "Scroll_Lock"); + + ecore_evases = _ecore_list_prepend(ecore_evases, ee); + ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win), ee); + ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win_container), ee); + return ee; +#else + return NULL; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_X_Window +ecore_evas_software_x11_window_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_X + return ee->engine.x.win_container; +#else + return 0; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_X_Window +ecore_evas_software_x11_subwindow_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_X + return ee->engine.x.win; +#else + return 0; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +void +ecore_evas_software_x11_direct_resize_set(Ecore_Evas *ee, int on) +{ +#ifdef BUILD_ECORE_X + ee->engine.x.direct_resize = on; + if (ee->prop.avoid_damage) + { + if (ee->engine.x.direct_resize) + { +/* turn this off for now + ee->engine.x.using_bg_pixmap = 1; + ecore_x_window_pixmap_set(ee->engine.x.win, ee->engine.x.pmap); + */ + } + else + { + ee->engine.x.using_bg_pixmap = 0; + ecore_x_window_pixmap_set(ee->engine.x.win, 0); + ecore_x_window_area_expose(ee->engine.x.win, 0, 0, ee->w, ee->h); + } + } +#else + return; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +int +ecore_evas_software_x11_direct_resize_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_X + return ee->engine.x.direct_resize; +#else + return 0; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_Evas * +ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent, + int x, int y, int w, int h) +{ +#ifdef BUILD_ECORE_EVAS_GL + Evas_Engine_Info_GL_X11 *einfo; + Ecore_Evas *ee; + int rmethod; + + rmethod = evas_render_method_lookup("gl_x11"); + if (!rmethod) return NULL; + if (!ecore_x_init(disp_name)) return NULL; + ee = calloc(1, sizeof(Ecore_Evas)); + if (!ee) return NULL; + + ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); + + _ecore_evas_x_init(); + + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_x_engine_func; + + ee->driver = strdup("gl_x11"); + if (disp_name) ee->name = strdup(disp_name); + + if (w < 1) w = 1; + if (h < 1) h = 1; + ee->x = x; + ee->y = y; + ee->w = w; + ee->h = h; + + ee->prop.max.w = 32767; + ee->prop.max.h = 32767; + ee->prop.layer = 4; + + /* init evas here */ + ee->evas = evas_new(); + evas_output_method_set(ee->evas, rmethod); + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + ee->engine.x.win_root = parent; + ee->engine.x.win_container = ecore_x_window_new(parent, x, y, w, h); + einfo = (Evas_Engine_Info_GL_X11 *)evas_engine_info_get(ee->evas); + if (einfo) + { + XSetWindowAttributes attr; + int screen; + + /* FIXME: this is inefficient as its a round trip */ + screen = DefaultScreen(ecore_x_display_get()); + if (ScreenCount(ecore_x_display_get()) > 1) + { + Ecore_X_Window *roots; + int num, i; + + num = 0; + roots = ecore_x_window_root_list(&num); + if (roots) + { + XWindowAttributes at; + + if (XGetWindowAttributes(ecore_x_display_get(), + parent, &at)) + { + for (i = 0; i < num; i++) + { + if (at.root == roots[i]) + { + screen = i; + break; + } + } + } + free(roots); + } + } + attr.backing_store = NotUseful; + attr.override_redirect = True; + attr.colormap = einfo->func.best_colormap_get(ecore_x_display_get(), screen); + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.event_mask = + KeyPressMask | KeyReleaseMask | + ExposureMask | ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | + PointerMotionMask | StructureNotifyMask | VisibilityChangeMask | + FocusChangeMask | PropertyChangeMask | ColormapChangeMask; + attr.bit_gravity = ForgetGravity; + + ee->engine.x.win = + XCreateWindow(ecore_x_display_get(), + ee->engine.x.win_container, + 0, 0, + w, h, 0, + einfo->func.best_depth_get(ecore_x_display_get(), screen), + InputOutput, + einfo->func.best_visual_get(ecore_x_display_get(), screen), + CWBackingStore | CWColormap | + CWBackPixmap | CWBorderPixel | + CWBitGravity | CWEventMask | + CWOverrideRedirect, + &attr); + einfo->info.display = ecore_x_display_get(); + einfo->info.visual = einfo->func.best_visual_get(ecore_x_display_get(), screen); + einfo->info.colormap = einfo->func.best_colormap_get(ecore_x_display_get(), screen); + einfo->info.drawable = ee->engine.x.win; + einfo->info.depth = einfo->func.best_depth_get(ecore_x_display_get(), screen); + evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo); + } + evas_key_modifier_add(ee->evas, "Shift"); + evas_key_modifier_add(ee->evas, "Control"); + evas_key_modifier_add(ee->evas, "Alt"); + evas_key_modifier_add(ee->evas, "Meta"); + evas_key_modifier_add(ee->evas, "Hyper"); + evas_key_modifier_add(ee->evas, "Super"); + evas_key_lock_add(ee->evas, "Caps_Lock"); + evas_key_lock_add(ee->evas, "Num_Lock"); + evas_key_lock_add(ee->evas, "Scroll_Lock"); + + ecore_evases = _ecore_list_prepend(ecore_evases, ee); + ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win), ee); + ecore_evases_hash = evas_hash_add(ecore_evases_hash, _ecore_evas_x_winid_str_get(ee->engine.x.win_container), ee); + return ee; +#else + return NULL; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_X_Window +ecore_evas_gl_x11_window_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_EVAS_GL + return ee->engine.x.win_container; +#else + return 0; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_X_Window +ecore_evas_gl_x11_subwindow_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_X + return ee->engine.x.win; +#else + return 0; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +void +ecore_evas_gl_x11_direct_resize_set(Ecore_Evas *ee, int on) +{ +#ifdef BUILD_ECORE_X + ee->engine.x.direct_resize = on; +#else + return; +#endif +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +int +ecore_evas_gl_x11_direct_resize_get(Ecore_Evas *ee) +{ +#ifdef BUILD_ECORE_X + return ee->engine.x.direct_resize; +#else + return 0; +#endif +} + diff --git a/ecore/src/lib/ecore_fb/.cvsignore b/ecore/src/lib/ecore_fb/.cvsignore new file mode 100644 index 0000000..8b1bf12 --- /dev/null +++ b/ecore/src/lib/ecore_fb/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +ecore_fb.lo +libecore_fb.la diff --git a/ecore/src/lib/ecore_fb/CVS/Entries b/ecore/src/lib/ecore_fb/CVS/Entries new file mode 100644 index 0000000..2a35cfe --- /dev/null +++ b/ecore/src/lib/ecore_fb/CVS/Entries @@ -0,0 +1,7 @@ +/.cvsignore/1.2/Fri Jan 16 16:59:03 2004//THEAD +/Ecore_Fb.h/1.5/Tue Dec 14 03:21:42 2004//THEAD +/Makefile.am/1.7/Thu Mar 10 15:19:39 2005//THEAD +/ecore_fb.c/1.11/Tue May 31 22:42:24 2005//THEAD +/ecore_fb_keytab.h/1.1/Tue Dec 14 16:12:05 2004//THEAD +/ecore_fb_private.h/1.2/Tue Sep 23 08:09:31 2003//THEAD +D diff --git a/ecore/src/lib/ecore_fb/CVS/Repository b/ecore/src/lib/ecore_fb/CVS/Repository new file mode 100644 index 0000000..ffa9ebb --- /dev/null +++ b/ecore/src/lib/ecore_fb/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_fb diff --git a/ecore/src/lib/ecore_fb/CVS/Root b/ecore/src/lib/ecore_fb/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_fb/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_fb/CVS/Tag b/ecore/src/lib/ecore_fb/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_fb/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_fb/Ecore_Fb.h b/ecore/src/lib/ecore_fb/Ecore_Fb.h new file mode 100644 index 0000000..9ec1596 --- /dev/null +++ b/ecore/src/lib/ecore_fb/Ecore_Fb.h @@ -0,0 +1,116 @@ +#ifndef _ECORE_FB_H +#define _ECORE_FB_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file + * @brief Ecore frame buffer system functions. + */ + +/* FIXME: + * maybe a new module? + * - code to get battery info + * - code to get thermal info + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ECORE_FB_EVENT_KEY_DOWN; /**< FB Key Down event */ +extern int ECORE_FB_EVENT_KEY_UP; /**< FB Key Up event */ +extern int ECORE_FB_EVENT_MOUSE_BUTTON_DOWN; /**< FB Mouse Down event */ +extern int ECORE_FB_EVENT_MOUSE_BUTTON_UP; /**< FB Mouse Up event */ +extern int ECORE_FB_EVENT_MOUSE_MOVE; /**< FB Mouse Move event */ + +typedef struct _Ecore_Fb_Event_Key_Down Ecore_Fb_Event_Key_Down; /**< FB Key Down event */ +typedef struct _Ecore_Fb_Event_Key_Up Ecore_Fb_Event_Key_Up; /**< FB Key Up event */ +typedef struct _Ecore_Fb_Event_Mouse_Button_Down Ecore_Fb_Event_Mouse_Button_Down; /**< FB Mouse Down event */ +typedef struct _Ecore_Fb_Event_Mouse_Button_Up Ecore_Fb_Event_Mouse_Button_Up; /**< FB Mouse Up event */ +typedef struct _Ecore_Fb_Event_Mouse_Move Ecore_Fb_Event_Mouse_Move; /**< FB Mouse Move event */ + +struct _Ecore_Fb_Event_Key_Down /** FB Key Down event */ +{ + char *keyname; /**< The name of the key that was pressed */ + char *keysymbol; /**< The logical symbol of the key that was pressed */ + char *key_compose; /**< The UTF-8 string conversion if any */ +}; + +struct _Ecore_Fb_Event_Key_Up /** FB Key Up event */ +{ + char *keyname; /**< The name of the key that was released */ + char *keysymbol; /**< The logical symbol of the key that was pressed */ + char *key_compose; /**< The UTF-8 string conversion if any */ +}; + +struct _Ecore_Fb_Event_Mouse_Button_Down /** FB Mouse Down event */ +{ + int button; /**< Mouse button that was pressed (1 - 32) */ + int x; /**< Mouse co-ordinates when mouse button was pressed */ + int y; /**< Mouse co-ordinates when mouse button was pressed */ + int double_click : 1; /**< Set if click was a double click */ + int triple_click : 1; /**< Set if click was a triple click */ +}; + +struct _Ecore_Fb_Event_Mouse_Button_Up /** FB Mouse Up event */ +{ + int button; /**< Mouse button that was released (1 - 32) */ + int x; /**< Mouse co-ordinates when mouse button was raised */ + int y; /**< Mouse co-ordinates when mouse button was raised */ +}; + +struct _Ecore_Fb_Event_Mouse_Move /** FB Mouse Move event */ +{ + int x; /**< Mouse co-ordinates where the mouse cursor moved to */ + int y; /**< Mouse co-ordinates where the mouse cursor moved to */ +}; + +EAPI int ecore_fb_init(const char *name); +EAPI int ecore_fb_shutdown(void); + +EAPI void ecore_fb_double_click_time_set(double t); +EAPI double ecore_fb_double_click_time_get(void); + +EAPI void ecore_fb_size_get(int *w, int *h); + +EAPI void ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap); +EAPI void ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap); + +EAPI void ecore_fb_backlight_set(int on); +EAPI int ecore_fb_backlight_get(void); + +EAPI void ecore_fb_backlight_brightness_set(double br); +EAPI double ecore_fb_backlight_brightness_get(void); + +EAPI void ecore_fb_led_set(int on); +EAPI void ecore_fb_led_blink_set(double speed); + +EAPI void ecore_fb_contrast_set(double cr); +EAPI double ecore_fb_contrast_get(void); + +EAPI double ecore_fb_light_sensor_get(void); + +EAPI void ecore_fb_callback_gain_set(void (*func) (void *data), void *data); +EAPI void ecore_fb_callback_lose_set(void (*func) (void *data), void *data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_fb/Makefile.am b/ecore/src/lib/ecore_fb/Makefile.am new file mode 100644 index 0000000..46f9374 --- /dev/null +++ b/ecore/src/lib/ecore_fb/Makefile.am @@ -0,0 +1,32 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore + +libecore_fb_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_FB + +lib_LTLIBRARIES = libecore_fb.la +include_HEADERS = \ +Ecore_Fb.h + +libecore_fb_la_SOURCES = \ +ecore_fb.c \ +ecore_fb_private.h \ +ecore_fb_keytab.h + +libecore_fb_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la + +libecore_fb_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la + +endif + +EXTRA_DIST = \ +Ecore_Fb.h \ +ecore_fb.c \ +ecore_fb_private.h diff --git a/ecore/src/lib/ecore_fb/ecore_fb.c b/ecore/src/lib/ecore_fb/ecore_fb.c new file mode 100644 index 0000000..14c18fa --- /dev/null +++ b/ecore/src/lib/ecore_fb/ecore_fb.c @@ -0,0 +1,1273 @@ + +#include "Ecore.h" +#include "ecore_fb_private.h" +#include "Ecore_Fb.h" +#include "ecore_private.h" + +#include <fcntl.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <termios.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <linux/kd.h> +#include <linux/vt.h> +#include <linux/fb.h> +#include <sys/ioctl.h> +#include <signal.h> + +typedef struct _Ecore_Fb_Ts_Event Ecore_Fb_Ts_Event; +typedef struct _Ecore_Fb_Ts_Calibrate Ecore_Fb_Ts_Calibrate; +typedef struct _Ecore_Fb_Ts_Backlight Ecore_Fb_Ts_Backlight; +typedef struct _Ecore_Fb_Ts_Contrast Ecore_Fb_Ts_Contrast; +typedef struct _Ecore_Fb_Ts_Led Ecore_Fb_Ts_Led; +typedef struct _Ecore_Fb_Ts_Flite Ecore_Fb_Ts_Flite; +typedef struct _Ecore_Fb_Ps2_Event Ecore_Fb_Ps2_Event; + +struct _Ecore_Fb_Ts_Event +{ + unsigned short pressure; + unsigned short x; + unsigned short y; + unsigned short _unused; +}; + +struct _Ecore_Fb_Ts_Calibrate +{ + int xscale; + int xtrans; + int yscale; + int ytrans; + int xyswap; +}; + +struct _Ecore_Fb_Ts_Backlight +{ + int on; + unsigned char brightness; +}; + +struct _Ecore_Fb_Ts_Contrast +{ + unsigned char contrast; +}; + +struct _Ecore_Fb_Ts_Led +{ + unsigned char on; + unsigned char blink_time; + unsigned char on_time; + unsigned char off_time; +}; + +struct _Ecore_Fb_Ts_Flite +{ + unsigned char mode; + unsigned char pwr; + unsigned char brightness; +}; + +struct _Ecore_Fb_Ps2_Event +{ + unsigned char button; + unsigned char x; + unsigned char y; + unsigned char z; +}; + +static void _ecore_fb_size_get(int *w, int *h); +static int _ecore_fb_ts_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_fb_kbd_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_fb_ps2_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static void _ecore_fb_event_free_key_down(void *data, void *ev); +static void _ecore_fb_event_free_key_up(void *data, void *ev); +static int _ecore_fb_signal_usr_handler(void *data, int type, void *ev); +static void _ecore_fb_vt_switch(int vt); + +int ECORE_FB_EVENT_KEY_DOWN = 0; +int ECORE_FB_EVENT_KEY_UP = 0; +int ECORE_FB_EVENT_MOUSE_BUTTON_DOWN = 0; +int ECORE_FB_EVENT_MOUSE_BUTTON_UP = 0; +int ECORE_FB_EVENT_MOUSE_MOVE = 0; + +static Ecore_Event_Handler *_ecore_fb_user_handler = NULL; +static Ecore_Event_Filter *_ecore_fb_filter_handler = NULL; +static Ecore_Fd_Handler *_ecore_fb_ts_fd_handler_handle = NULL; +static Ecore_Fd_Handler *_ecore_fb_kbd_fd_handler_handle = NULL; +static int _ecore_fb_init_count = 0; +static int _ecore_fb_ts_fd = 0; +static int _ecore_fb_ps2_fd = 0; +static int _ecore_fb_kbd_fd = 0; +static int _ecore_fb_tty_fd = 0; +static int _ecore_fb_console_w = 0; +static int _ecore_fb_console_h = 0; +static int _ecore_fb_ts_event_byte_count = 0; +static int _ecore_fb_ps2_event_byte_count = 0; +static Ecore_Fb_Ts_Event _ecore_fb_ts_event; +static Ecore_Fb_Ps2_Event _ecore_fb_ps2_event; +static int _ecore_fb_tty_prev_mode = 0; +static int _ecore_fb_tty_prev_kd_mode = 0; +static struct termios _ecore_fb_tty_prev_tio_mode; +static struct vt_mode _ecore_fb_vt_prev_mode; +static int _ecore_fb_current_vt = 0; +static int _ecore_fb_ctrl = 0; +static int _ecore_fb_alt = 0; +static int _ecore_fb_shift = 0; +static int _ecore_fb_lock = 0; + +static void (*_ecore_fb_func_fb_lost) (void *data) = NULL; +static void *_ecore_fb_func_fb_lost_data = NULL; +static void (*_ecore_fb_func_fb_gain) (void *data) = NULL; +static void *_ecore_fb_func_fb_gain_data = NULL; + +static void *_ecore_fb_event_filter_start(void *data); +static int _ecore_fb_event_filter_filter(void *data, void *loop_data, int type, void *event); +static void _ecore_fb_event_filter_end(void *data, void *loop_data); + +static double _ecore_fb_double_click_time = 0.25; + +static struct _Ecore_Fb_Ts_Calibrate _ecore_fb_ts_cal = {1,1,0,0,0}; +static int _ecore_fb_ts_apply_cal = 0; + +static const char *_ecore_fb_kbd_syms[128 * 6] = +{ +#include "ecore_fb_keytab.h" +}; + +static const char *_ecore_fb_btn_syms[128] = +{ + "0x00", + "Escape", + "F1", + "F2", + "F3", + "F4", + "Up", + "Right", + "Left", + "Down", + "Return", + "0x1b", + "0x1c", + "0x1d", + "0x1e", + "0x1f", + "0x20", + "0x21", + "0x22", + "0x23", + "0x24", + "0x25", + "0x26", + "0x27", + "0x28", + "0x29", + "0x2a", + "0x2b", + "0x2c", + "0x2d", + "0x2e", + "0x2f", + "0x30", + "0x31", + "0x32", + "0x33", + "0x34", + "0x35", + "0x36", + "0x37", + "0x38", + "0x39", + "0x3a", + "0x3b", + "0x3c", + "0x3d", + "0x3e", + "0x3f", + "0x40", + "0x41", + "0x42", + "0x43", + "0x44", + "0x45", + "0x46", + "0x47", + "0x48", + "0x49", + "0x4a", + "0x4b", + "0x4c", + "0x4d", + "0x4e", + "0x4f", + "0x50", + "0x51", + "0x52", + "0x53", + "0x54", + "0x55", + "0x56", + "0x57", + "0x58", + "0x59", + "0x5a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0x5f", + "0x60", + "0x61", + "0x62", + "0x63", + "0x64", + "0x65", + "0x66", + "0x67", + "0x68", + "0x69", + "0x6a", + "0x6b", + "0x6c", + "0x6d", + "0x6e", + "0x6f", + "0x70", + "0x71", + "0x72", + "0x73", + "0x74", + "0x75", + "0x76", + "0x77", + "0x78", + "0x79", + "0x7a", + "0x7b", + "0x7c", + "0x7d", + "0x7e", + "0x7f" +}; + +/** + * @defgroup Ecore_FB_Library_Group Framebuffer Library Functions + * + * Functions used to set up and shut down the Ecore_Framebuffer functions. + */ + +/** + * Sets up the Ecore_Fb library. + * @param name device target name + * @return @c 0 on failure. Otherwise, the number of times the library has + * been initialised without being shut down. + * @ingroup Ecore_FB_Library_Group + */ +int +ecore_fb_init(const char *name __UNUSED__) +{ + int prev_flags; + + _ecore_fb_init_count++; + if (_ecore_fb_init_count > 1) return _ecore_fb_init_count; + _ecore_fb_ts_fd = open("/dev/touchscreen/0", O_RDONLY); + if (_ecore_fb_ts_fd >= 0) + { + prev_flags = fcntl(_ecore_fb_ts_fd, F_GETFL); + fcntl(_ecore_fb_ts_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ts_fd, + ECORE_FD_READ, + _ecore_fb_ts_fd_handler, NULL, + NULL, NULL); + if (!_ecore_fb_ts_fd_handler_handle) + { + close(_ecore_fb_ts_fd); + } + } + if (_ecore_fb_ts_fd < 0) + { + _ecore_fb_ps2_fd = open("/dev/psaux", O_RDWR); + if (_ecore_fb_ps2_fd >= 0) + { + prev_flags = fcntl(_ecore_fb_ps2_fd, F_GETFL); + fcntl(_ecore_fb_ps2_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ps2_fd, + ECORE_FD_READ, + _ecore_fb_ps2_fd_handler, NULL, + NULL, NULL); + if (!_ecore_fb_ts_fd_handler_handle) + { + close(_ecore_fb_ps2_fd); + } + } + } + _ecore_fb_kbd_fd = open("/dev/touchscreen/key", O_RDONLY); + _ecore_fb_tty_fd = open("/dev/tty0", O_RDONLY); + if (_ecore_fb_tty_fd >= 0) + { + struct termios tio; + struct vt_mode new_vtmode; + int vtno; + + if ((ioctl(_ecore_fb_tty_fd, VT_OPENQRY, &vtno) != -1)) + { + char buf[64]; + + _ecore_fb_current_vt = vtno; + ioctl(_ecore_fb_tty_fd, VT_ACTIVATE, _ecore_fb_current_vt); + close(_ecore_fb_tty_fd); + snprintf(buf, sizeof(buf), "/dev/tty%i", _ecore_fb_current_vt); +/* FIXME: switch away works.. but switch to the allocated vt doesnt */ +/* printf("%s\n", buf); */ + _ecore_fb_tty_fd = open(buf, O_RDWR); + if (_ecore_fb_current_vt == 1) + { + Ecore_Event_Signal_User *e; + + e = _ecore_event_signal_user_new(); + if (e) + { + e->number = 2; + ecore_event_add(ECORE_EVENT_SIGNAL_USER, e, NULL, NULL); + } + } + } + tcgetattr(_ecore_fb_tty_fd, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_tty_fd, KDGETMODE, &_ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_tty_fd, KDGKBMODE, &_ecore_fb_tty_prev_mode); + ioctl(_ecore_fb_tty_fd, VT_GETMODE, &_ecore_fb_vt_prev_mode); + tio.c_iflag = tio.c_oflag = tio.c_cflag = tio.c_lflag = 0; + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + new_vtmode.mode = VT_PROCESS; + new_vtmode.waitv = 0; + new_vtmode.relsig = SIGUSR1; + new_vtmode.acqsig = SIGUSR2; + tcsetattr(_ecore_fb_tty_fd, TCSAFLUSH, &tio); + ioctl(_ecore_fb_tty_fd, KDSETMODE, KD_GRAPHICS); + ioctl(_ecore_fb_tty_fd, KDSKBMODE, K_MEDIUMRAW); + ioctl(_ecore_fb_tty_fd, VT_SETMODE, &new_vtmode); + } + if (_ecore_fb_kbd_fd <= 0) _ecore_fb_kbd_fd = _ecore_fb_tty_fd; + if (_ecore_fb_kbd_fd >= 0) + { + prev_flags = fcntl(_ecore_fb_kbd_fd, F_GETFL); + fcntl(_ecore_fb_kbd_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_kbd_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_kbd_fd, + ECORE_FD_READ, + _ecore_fb_kbd_fd_handler, NULL, + NULL, NULL); + if (!_ecore_fb_kbd_fd_handler_handle) + { + tcsetattr(_ecore_fb_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); + close(_ecore_fb_tty_fd); + close(_ecore_fb_ts_fd); + close(_ecore_fb_kbd_fd); + if (_ecore_fb_ps2_fd > 0) close(_ecore_fb_ps2_fd); + if (_ecore_fb_tty_fd != _ecore_fb_kbd_fd) + close(_ecore_fb_tty_fd); + ecore_main_fd_handler_del(_ecore_fb_ts_fd_handler_handle); + _ecore_fb_ts_fd_handler_handle = NULL; + _ecore_fb_init_count--; + return 0; + } + } + if (!ECORE_FB_EVENT_KEY_DOWN) + { + ECORE_FB_EVENT_KEY_DOWN = ecore_event_type_new(); + ECORE_FB_EVENT_KEY_UP = ecore_event_type_new(); + ECORE_FB_EVENT_MOUSE_BUTTON_DOWN = ecore_event_type_new(); + ECORE_FB_EVENT_MOUSE_BUTTON_UP = ecore_event_type_new(); + ECORE_FB_EVENT_MOUSE_MOVE = ecore_event_type_new(); + + } + _ecore_fb_size_get(&_ecore_fb_console_w, &_ecore_fb_console_h); + _ecore_fb_user_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, + _ecore_fb_signal_usr_handler, + NULL); + _ecore_fb_filter_handler = ecore_event_filter_add(_ecore_fb_event_filter_start, _ecore_fb_event_filter_filter, _ecore_fb_event_filter_end, NULL); + return _ecore_fb_init_count; +} + +/** + * Shuts down the Ecore_Fb library. + * @return @c The number of times the system has been initialised without + * being shut down. + * @ingroup Ecore_FB_Library_Group + */ +int +ecore_fb_shutdown(void) +{ + _ecore_fb_init_count--; + if (_ecore_fb_init_count > 0) return _ecore_fb_init_count; + if (_ecore_fb_init_count < 0) + { + _ecore_fb_init_count = 0; + return 0; + } + if (_ecore_fb_tty_fd != 0) + { + tcsetattr(_ecore_fb_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); + ioctl(_ecore_fb_tty_fd, VT_SETMODE, &_ecore_fb_vt_prev_mode); + close(_ecore_fb_tty_fd); + if (_ecore_fb_tty_fd == _ecore_fb_kbd_fd) _ecore_fb_kbd_fd = 0; + } + if (_ecore_fb_ps2_fd > 0) close(_ecore_fb_ps2_fd); + if (_ecore_fb_ts_fd >= 0) close(_ecore_fb_ts_fd); + if (_ecore_fb_kbd_fd >= 0) close(_ecore_fb_kbd_fd); + if (_ecore_fb_ts_fd_handler_handle) + ecore_main_fd_handler_del(_ecore_fb_ts_fd_handler_handle); + if (_ecore_fb_kbd_fd_handler_handle) + ecore_main_fd_handler_del(_ecore_fb_kbd_fd_handler_handle); + if (_ecore_fb_user_handler) + ecore_event_handler_del(_ecore_fb_user_handler); + ecore_event_filter_del(_ecore_fb_filter_handler); + _ecore_fb_ts_fd = 0; + _ecore_fb_kbd_fd = 0; + _ecore_fb_tty_fd = 0; + _ecore_fb_ps2_fd = 0; + _ecore_fb_ts_fd_handler_handle = NULL; + _ecore_fb_filter_handler = NULL; + _ecore_fb_kbd_fd_handler_handle = NULL; + _ecore_fb_user_handler = NULL; + _ecore_fb_ctrl = 0; + _ecore_fb_alt = 0; + return _ecore_fb_init_count; +} + +/** + * @defgroup Ecore_FB_Click_Group Framebuffer Double Click Functions + * + * Functions that deal with the double click time of the framebuffer. + */ + +/** + * 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_FB_Click_Group + */ +void +ecore_fb_double_click_time_set(double t) +{ + if (t < 0.0) t = 0.0; + _ecore_fb_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_FB_Click_Group + */ +double +ecore_fb_double_click_time_get(void) +{ + return _ecore_fb_double_click_time; +} + +/** + * Retrieves the width and height of the current frame buffer in pixels. + * @param w Pointer to an integer in which to store the width. + * @param h Pointer to an interge in which to store the height. + */ +void +ecore_fb_size_get(int *w, int *h) +{ + if (w) *w = _ecore_fb_console_w; + if (h) *h = _ecore_fb_console_h; +} + +/** + * @defgroup Ecore_FB_Calibrate_Group Framebuffer Calibration Functions + * + * Functions that calibrate the screen. + */ + +/** + * Calibrates the touschreen using the given parameters. + * @param xscale X scaling, where 256 = 1.0 + * @param xtrans X translation. + * @param yscale Y scaling. + * @param ytrans Y translation. + * @param xyswap Swap X & Y flag. + * @ingroup Ecore_FB_Calibrate_Group + */ +void +ecore_fb_touch_screen_calibrate_set(int xscale, int xtrans, int yscale, int ytrans, int xyswap) +{ + Ecore_Fb_Ts_Calibrate cal; + + if (_ecore_fb_ts_fd < 0) return; + cal.xscale = xscale; + cal.xtrans = xtrans; + cal.yscale = yscale; + cal.ytrans = ytrans; + cal.xyswap = xyswap; + if (ioctl(_ecore_fb_ts_fd, TS_SET_CAL, (void *)&cal)) + { + _ecore_fb_ts_cal = cal; + _ecore_fb_ts_apply_cal = 1; + } +} + +/** + * Retrieves the calibration parameters of the touchscreen. + * @param xscale Pointer to an integer in which to store the X scaling. + * Note that 256 = 1.0. + * @param xtrans Pointer to an integer in which to store the X translation. + * @param yscale Pointer to an integer in which to store the Y scaling. + * @param ytrans Pointer to an integer in which to store the Y translation. + * @param xyswap Pointer to an integer in which to store the Swap X & Y flag. + * @ingroup Ecore_FB_Calibrate_Group + */ +void +ecore_fb_touch_screen_calibrate_get(int *xscale, int *xtrans, int *yscale, int *ytrans, int *xyswap) +{ + Ecore_Fb_Ts_Calibrate cal; + + if (_ecore_fb_ts_fd < 0) return; + if (!_ecore_fb_ts_apply_cal) + { + if (ioctl(_ecore_fb_ts_fd, TS_GET_CAL, (void *)&cal)) + _ecore_fb_ts_cal = cal; + } + else + cal = _ecore_fb_ts_cal; + if (xscale) *xscale = cal.xscale; + if (xtrans) *xtrans = cal.xtrans; + if (yscale) *yscale = cal.yscale; + if (ytrans) *ytrans = cal.ytrans; + if (xyswap) *xyswap = cal.xyswap; +} + +/** + * @defgroup Ecore_FB_Backlight_Group Framebuffer Backlight Functions + * + * Functions that deal with the backlight of a framebuffer's screen. + */ + +/** + * Turns on or off the backlight. + * @param on @c 1 to turn the backlight on. @c 0 to turn it off. + * @ingroup Ecore_FB_Backlight_Group + */ +void +ecore_fb_backlight_set(int on) +{ + Ecore_Fb_Ts_Backlight bl; + + if (_ecore_fb_ts_fd < 0) return; + ioctl(_ecore_fb_ts_fd, TS_GET_BACKLIGHT, &bl); + bl.on = on; + ioctl(_ecore_fb_ts_fd, TS_SET_BACKLIGHT, &bl); +} + +/** + * Retrieves the backlight state. + * @return Whether the backlight is on. + * @ingroup Ecore_FB_Backlight_Group + */ +int +ecore_fb_backlight_get(void) +{ + Ecore_Fb_Ts_Backlight bl; + + if (_ecore_fb_ts_fd < 0) return 1; + ioctl(_ecore_fb_ts_fd, TS_GET_BACKLIGHT, &bl); + return bl.on; +} + +/** + * Sets the backlight brightness. + * @param br Brightness between 0.0 to 1.0, where 0.0 is darkest and 1.0 + * is brightest. + * @ingroup Ecore_FB_Backlight_Group + */ +void +ecore_fb_backlight_brightness_set(double br) +{ + Ecore_Fb_Ts_Backlight bl; + int val; + + if (br < 0) br = 0; + if (br > 1) br = 1; + val = (int)(255.0 * br); + ioctl(_ecore_fb_ts_fd, TS_GET_BACKLIGHT, &bl); + bl.brightness = val; + ioctl(_ecore_fb_ts_fd, TS_SET_BACKLIGHT, &bl); +} + +/** + * Retrieves the backlight brightness. + * @return The current backlight brigntess, where 0.0 is the darkest and + * 1.0 is the brightest. + * @ingroup Ecore_FB_Backlight_Group + */ +double +ecore_fb_backlight_brightness_get(void) +{ + Ecore_Fb_Ts_Backlight bl; + + if (_ecore_fb_ts_fd < 0) return 1.0; + ioctl(_ecore_fb_ts_fd, TS_GET_BACKLIGHT, &bl); + return (double)bl.brightness / 255.0; +} + +/** + * @defgroup Ecore_FB_LED_Group Framebuffer LED Functions + * + * Functions that deal with the light emitting diode connected to the + * current framebuffer. + */ + +/** + * Sets whether the current framebuffer's LED to the given state. + * @param on @c 1 to indicate the LED should be on, @c 0 if it should be off. + * @ingroup Ecore_FB_LED_Group + */ +void +ecore_fb_led_set(int on) +{ + Ecore_Fb_Ts_Led led; + + if (_ecore_fb_ts_fd < 0) return; + if (on) led.on = 1; + else led.on = 0; + ioctl(_ecore_fb_ts_fd, LED_ON, &led); +} + +/** + * Makes the LED of the current framebuffer blink. + * @param speed Number to give the speed on the blink. + * @ingroup Ecore_FB_LED_Group + * @todo Documentation: Work out what speed the units are in. + */ +void +ecore_fb_led_blink_set(double speed) +{ + Ecore_Fb_Ts_Led led; + + if (_ecore_fb_ts_fd < 0) return; + led.on = 1; + led.on_time = (unsigned char)(speed * 10); + led.off_time = (unsigned char)(speed * 10); + led.blink_time = 255; + ioctl(_ecore_fb_ts_fd, LED_ON, &led); +} + +/** + * @defgroup Ecore_FB_Contrast_Group Framebuffer Contrast Functions + * + * Values that set and retrieve the contrast of a framebuffer screen. + */ + +/** + * Sets the contrast used by the framebuffer screen. + * @param cr Value between 0 and 1 that gives the new contrast of the screen. + * @ingroup Ecore_FB_Contrast_Group + */ +void +ecore_fb_contrast_set(double cr) +{ + Ecore_Fb_Ts_Contrast ct; + int val; + + if (cr < 0) cr = 0; + if (cr > 1) cr = 1; + val = (int)(255.0 * cr); + ct.contrast = val; + ioctl(_ecore_fb_ts_fd, TS_SET_CONTRAST, &ct); +} + +/** + * Retrieves the contrast currently being used by the framebuffer screen. + * @return A value between 0 and 1 that represents the current contrast of the + * screen. + * @ingroup Ecore_FB_Contrast_Group + */ +double +ecore_fb_contrast_get(void) +{ + Ecore_Fb_Ts_Contrast ct; + + if (_ecore_fb_ts_fd < 0) return 1.0; + ioctl(_ecore_fb_ts_fd, TS_GET_CONTRAST, &ct); + return (double)ct.contrast / 255.0; +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +double +ecore_fb_light_sensor_get(void) +{ + Ecore_Fb_Ts_Flite fl; + + if (_ecore_fb_ts_fd < 0) return 0.0; + fl.mode = 3; + fl.brightness = 0; + ioctl(_ecore_fb_ts_fd, FLITE_ON, &fl); + return (double)fl.brightness / 255.0; +} + +/** + * To be documented. + * + * FIXME: To be fixed. + * @todo Documentation: Find out what this does. + */ +void +ecore_fb_callback_gain_set(void (*func) (void *data), void *data) +{ + _ecore_fb_func_fb_gain = func; + _ecore_fb_func_fb_gain_data = data; +} + +/** + * To be documented. + * + * FIXME: To be fixed. + * @todo Documentation: Find out what this does. + */ +void +ecore_fb_callback_lose_set(void (*func) (void *data), void *data) +{ + _ecore_fb_func_fb_lost = func; + _ecore_fb_func_fb_lost_data = data; +} + +static void +_ecore_fb_size_get(int *w, int *h) +{ + struct fb_var_screeninfo fb_var; + int fb; + + fb = open("/dev/fb0", O_RDWR); + if (fb < 0) + { + if (w) *w = 0; + if (h) *h = 0; + return; + } + if (ioctl(fb, FBIOGET_VSCREENINFO, &fb_var) == -1) + { + if (w) *w = 0; + if (h) *h = 0; + return; + } + close(fb); + if (w) *w = fb_var.xres; + if (h) *h = fb_var.yres; +} + +static int +_ecore_fb_ts_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + static int prev_x = 0, prev_y = 0, prev_pressure = 0; + static double last_time = 0; + static double last_last_time = 0; + int v = 0; + + do + { + int x, y, pressure; + int num; + char *ptr; + double t; + int did_triple = 0; + + ptr = (char *)&(_ecore_fb_ts_event); + ptr += _ecore_fb_ts_event_byte_count; + num = sizeof(Ecore_Fb_Ts_Event) - _ecore_fb_ts_event_byte_count; + v = read(_ecore_fb_ts_fd, ptr, num); + if (v < 0) return 1; + _ecore_fb_ts_event_byte_count += v; + if (v < num) return 1; + t = ecore_time_get(); + _ecore_fb_ts_event_byte_count = 0; + if (_ecore_fb_ts_apply_cal) + { + x = ((_ecore_fb_ts_cal.xscale * _ecore_fb_ts_event.x) >> 8) + _ecore_fb_ts_cal.xtrans; + y = ((_ecore_fb_ts_cal.yscale * _ecore_fb_ts_event.y) >> 8) + _ecore_fb_ts_cal.ytrans; + } + else + { + x = _ecore_fb_ts_event.x; + y = _ecore_fb_ts_event.y; + } + pressure = _ecore_fb_ts_event.pressure; + /* add event to queue */ + /* always add a move event */ + if ((pressure) || (prev_pressure)) + { + /* MOVE: mouse is down and was */ + Ecore_Fb_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Move)); + if (!e) goto retry; + e->x = x; + e->y = y; + ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + if ((pressure) && (!prev_pressure)) + { + /* DOWN: mouse is down, but was not now */ + Ecore_Fb_Event_Mouse_Button_Down *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->button = 1; + if ((t - last_time) <= _ecore_fb_double_click_time) + e->double_click = 1; + if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time)) + { + did_triple = 1; + e->triple_click = 1; + } + ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL); + } + else if ((!pressure) && (prev_pressure)) + { + /* UP: mouse was down, but is not now */ + Ecore_Fb_Event_Mouse_Button_Up *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up)); + if (!e) goto retry; + e->x = prev_x; + e->y = prev_y; + e->button = 1; + ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL); + } + if (did_triple) + { + last_time = 0; + last_last_time = 0; + } + else + { + last_last_time = last_time; + last_time = t; + } + retry: + prev_x = x; + prev_y = y; + prev_pressure = pressure; + } + while (v > 0); + return 1; +} + +static int +_ecore_fb_kbd_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + int v = 0; + + do + { + unsigned char buf; + + v = read(_ecore_fb_kbd_fd, &buf, 1); + if (v < 0) return 1; + if (v < 1) return 1; + if (buf & 0x80) + { + /* DOWN */ + int vt_switch = -1; + Ecore_Fb_Event_Key_Down *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Key_Down)); + if (!e) goto retry; + if (_ecore_fb_kbd_fd == _ecore_fb_tty_fd) + { + int add = 0; + + if (_ecore_fb_shift) add = 1; + else if (_ecore_fb_lock) add = 2; + e->keyname = strdup(_ecore_fb_kbd_syms[(buf & 0x7f) * 6]); + e->keysymbol = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + add]); + e->key_compose = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + 3 + add]); + } + else + e->keyname = strdup(_ecore_fb_btn_syms[buf & 0x7f]); + if (!e->keyname) + { + free(e); + goto retry; + } + ecore_event_add(ECORE_FB_EVENT_KEY_DOWN, e, _ecore_fb_event_free_key_down, NULL); + if (!strcmp(e->keyname, "Control_L")) + _ecore_fb_ctrl++; + else if (!strcmp(e->keyname, "Control_R")) + _ecore_fb_ctrl++; + else if (!strcmp(e->keyname, "Alt_L")) + _ecore_fb_alt++; + else if (!strcmp(e->keyname, "Alt_R")) + _ecore_fb_alt++; + else if (!strcmp(e->keyname, "Shift_L")) + _ecore_fb_shift++; + else if (!strcmp(e->keyname, "Shift_R")) + _ecore_fb_shift++; + else if (!strcmp(e->keyname, "Caps_Lock")) + _ecore_fb_lock++; + else if (!strcmp(e->keyname, "F1")) vt_switch = 0; + else if (!strcmp(e->keyname, "F2")) vt_switch = 1; + else if (!strcmp(e->keyname, "F3")) vt_switch = 2; + else if (!strcmp(e->keyname, "F4")) vt_switch = 3; + else if (!strcmp(e->keyname, "F5")) vt_switch = 4; + else if (!strcmp(e->keyname, "F6")) vt_switch = 5; + else if (!strcmp(e->keyname, "F7")) vt_switch = 6; + else if (!strcmp(e->keyname, "F8")) vt_switch = 7; + else if (!strcmp(e->keyname, "F9")) vt_switch = 8; + else if (!strcmp(e->keyname, "F10")) vt_switch = 9; + else if (!strcmp(e->keyname, "F11")) vt_switch = 10; + else if (!strcmp(e->keyname, "F12")) vt_switch = 11; + if (_ecore_fb_ctrl > 2) _ecore_fb_ctrl = 2; + if (_ecore_fb_alt > 2) _ecore_fb_alt = 2; + if ((vt_switch >= 0) && + (_ecore_fb_ctrl) && + (_ecore_fb_alt)) + _ecore_fb_vt_switch(vt_switch); + } + else + { + /* UP */ + Ecore_Fb_Event_Key_Up *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Key_Up)); + if (!e) goto retry; + if (_ecore_fb_kbd_fd == _ecore_fb_tty_fd) + { + int add = 0; + + if (_ecore_fb_shift) add = 1; + else if (_ecore_fb_lock) add = 2; + e->keyname = strdup(_ecore_fb_kbd_syms[(buf & 0x7f) * 6]); + e->keysymbol = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + add]); + e->key_compose = strdup(_ecore_fb_kbd_syms[((buf & 0x7f) * 6) + 3 + add]); + } + else + e->keyname = strdup(_ecore_fb_btn_syms[buf & 0x7f]); + if (!e->keyname) + { + free(e); + goto retry; + } + ecore_event_add(ECORE_FB_EVENT_KEY_UP, e, _ecore_fb_event_free_key_up, NULL); + if (!strcmp(e->keyname, "Control_L")) + _ecore_fb_ctrl--; + else if (!strcmp(e->keyname, "Control_R")) + _ecore_fb_ctrl--; + else if (!strcmp(e->keyname, "Alt_L")) + _ecore_fb_alt--; + else if (!strcmp(e->keyname, "Alt_R")) + _ecore_fb_alt--; + else if (!strcmp(e->keyname, "Shift_L")) + _ecore_fb_shift--; + else if (!strcmp(e->keyname, "Shift_R")) + _ecore_fb_shift--; + else if (!strcmp(e->keyname, "Caps_Lock")) + _ecore_fb_lock--; + if (_ecore_fb_ctrl < 0) _ecore_fb_ctrl = 0; + if (_ecore_fb_alt < 0) _ecore_fb_alt = 0; + if (_ecore_fb_shift < 0) _ecore_fb_shift = 0; + if (_ecore_fb_lock < 0) _ecore_fb_lock = 0; + } + retry: + ; + } + while (v > 0); + return 1; +} + +static int +_ecore_fb_ps2_fd_handler(void *data __UNUSED__, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + static int prev_x = 0, prev_y = 0, prev_button = 0; + static double last_time = 0; + static double last_last_time = 0; + int v = 0; + + do + { + int x, y, button, i; + int num; + char *ptr; + double t; + int did_triple = 0; + + ptr = (char *)&(_ecore_fb_ps2_event); + ptr += _ecore_fb_ps2_event_byte_count; + num = sizeof(Ecore_Fb_Ps2_Event) - _ecore_fb_ps2_event_byte_count; + v = read(_ecore_fb_ps2_fd, ptr, num); + if (v < 0) return 1; + _ecore_fb_ps2_event_byte_count += v; + if (v < num) return 1; + t = ecore_time_get(); + _ecore_fb_ps2_event_byte_count = 0; + if (_ecore_fb_ps2_event.button & 0x10) + x = prev_x + (0xffffff00 | _ecore_fb_ps2_event.x); + else + x = prev_x + _ecore_fb_ps2_event.x; + if (_ecore_fb_ps2_event.button & 0x20) + y = prev_y - (0xffffff00 | _ecore_fb_ps2_event.y); + else + y = prev_y - _ecore_fb_ps2_event.y; + button = _ecore_fb_ps2_event.button & 0x7; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (x >= _ecore_fb_console_w) x = _ecore_fb_console_w - 1; + if (y >= _ecore_fb_console_h) y = _ecore_fb_console_h - 1; + /* add event to queue */ + /* always add a move event */ + if (1) + { + /* MOVE: mouse is down and was */ + Ecore_Fb_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Move)); + if (!e) goto retry; + e->x = x; + e->y = y; + ecore_event_add(ECORE_FB_EVENT_MOUSE_MOVE, e, NULL, NULL); + } + for (i = 1; i <= 3; i++) + { + int mask; + + mask = 1 << (i - 1); + if (((button & mask)) && (!(prev_button & mask))) + { + /* DOWN: mouse is down, but was not now */ + Ecore_Fb_Event_Mouse_Button_Down *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Down)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->button = 1; + if ((t - last_time) <= _ecore_fb_double_click_time) + e->double_click = 1; + if ((t - last_last_time) <= (2 * _ecore_fb_double_click_time)) + { + did_triple = 1; + e->triple_click = 1; + } + ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_DOWN, e, NULL, NULL); + } + else if ((!(button & mask)) && ((prev_button & mask))) + { + /* UP: mouse was down, but is not now */ + Ecore_Fb_Event_Mouse_Button_Up *e; + + e = calloc(1, sizeof(Ecore_Fb_Event_Mouse_Button_Up)); + if (!e) goto retry; + e->x = x; + e->y = y; + e->button = 1; + ecore_event_add(ECORE_FB_EVENT_MOUSE_BUTTON_UP, e, NULL, NULL); + } + } + if (did_triple) + { + last_time = 0; + last_last_time = 0; + } + else + { + last_last_time = last_time; + last_time = t; + } + retry: + prev_x = x; + prev_y = y; + prev_button = button; + } + while (v > 0); + return 1; +} + +static void +_ecore_fb_event_free_key_down(void *data __UNUSED__, void *ev) +{ + Ecore_Fb_Event_Key_Up *e; + + e = ev; + free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static void +_ecore_fb_event_free_key_up(void *data __UNUSED__, void *ev) +{ + Ecore_Fb_Event_Key_Up *e; + + e = ev; + free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static int +_ecore_fb_signal_usr_handler(void *data __UNUSED__, int type __UNUSED__, void *ev) +{ + Ecore_Event_Signal_User *e; + + e = (Ecore_Event_Signal_User *)ev; + if (e->number == 1) + { + /* release */ + if (_ecore_fb_func_fb_lost) + _ecore_fb_func_fb_lost(_ecore_fb_func_fb_lost_data); + if (_ecore_fb_ps2_fd > 0) close(_ecore_fb_ps2_fd); + if (_ecore_fb_ts_fd >= 0) close(_ecore_fb_ts_fd); + if (_ecore_fb_ts_fd_handler_handle) + ecore_main_fd_handler_del(_ecore_fb_ts_fd_handler_handle); + _ecore_fb_ps2_fd = 0; + _ecore_fb_ts_fd = 0; + _ecore_fb_ts_fd_handler_handle = NULL; + ioctl(_ecore_fb_tty_fd, VT_RELDISP, 1); + } + else if (e->number == 2) + { + int prev_flags; + + /* gain */ + if (_ecore_fb_func_fb_gain) + _ecore_fb_func_fb_gain(_ecore_fb_func_fb_gain_data); + if (!_ecore_fb_ts_fd) + { + _ecore_fb_ts_fd = open("/dev/touchscreen/0", O_RDONLY); + if (_ecore_fb_ts_fd >= 0) + { + prev_flags = fcntl(_ecore_fb_ts_fd, F_GETFL); + fcntl(_ecore_fb_ts_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ts_fd, + ECORE_FD_READ, + _ecore_fb_ts_fd_handler, NULL, + NULL, NULL); + if (!_ecore_fb_ts_fd_handler_handle) + { + close(_ecore_fb_ts_fd); + } + } + } + if (_ecore_fb_ts_fd < 0) + { + if (!_ecore_fb_ps2_fd) + { + _ecore_fb_ps2_fd = open("/dev/psaux", O_RDWR); + if (_ecore_fb_ps2_fd >= 0) + { + prev_flags = fcntl(_ecore_fb_ps2_fd, F_GETFL); + fcntl(_ecore_fb_ps2_fd, F_SETFL, prev_flags | O_NONBLOCK); + _ecore_fb_ts_fd_handler_handle = ecore_main_fd_handler_add(_ecore_fb_ps2_fd, + ECORE_FD_READ, + _ecore_fb_ps2_fd_handler, NULL, + NULL, NULL); + if (!_ecore_fb_ts_fd_handler_handle) + { + close(_ecore_fb_ps2_fd); + } + } + } + } + if (_ecore_fb_tty_fd != 0) + { + struct termios tio; + struct vt_mode new_vtmode; + + tio.c_iflag = tio.c_oflag = tio.c_cflag = tio.c_lflag = 0; + tio.c_cc[VTIME] = 0; + tio.c_cc[VMIN] = 1; + new_vtmode.mode = VT_PROCESS; + new_vtmode.waitv = 0; + new_vtmode.relsig = SIGUSR1; + new_vtmode.acqsig = SIGUSR2; + tcsetattr(_ecore_fb_tty_fd, TCSAFLUSH, &tio); + ioctl(_ecore_fb_tty_fd, KDSETMODE, KD_GRAPHICS); + ioctl(_ecore_fb_tty_fd, KDSKBMODE, K_MEDIUMRAW); + ioctl(_ecore_fb_tty_fd, VT_SETMODE, &new_vtmode); + } + } + return 1; +} + +static void +_ecore_fb_vt_switch(int vt) +{ + vt++; + if (_ecore_fb_tty_fd != 0) + { + if (vt != _ecore_fb_current_vt) + { + tcsetattr(_ecore_fb_tty_fd, TCSAFLUSH, &_ecore_fb_tty_prev_tio_mode); + ioctl(_ecore_fb_tty_fd, KDSETMODE, _ecore_fb_tty_prev_kd_mode); + ioctl(_ecore_fb_tty_fd, KDSKBMODE, _ecore_fb_tty_prev_mode); + } + } + ioctl(_ecore_fb_tty_fd, VT_ACTIVATE, vt); +} + +typedef struct _Ecore_Fb_Filter_Data Ecore_Fb_Filter_Data; + +struct _Ecore_Fb_Filter_Data +{ + int last_event_type; +}; + +static void * +_ecore_fb_event_filter_start(void *data __UNUSED__) +{ + Ecore_Fb_Filter_Data *filter_data; + + filter_data = calloc(1, sizeof(Ecore_Fb_Filter_Data)); + return filter_data; +} + +static int +_ecore_fb_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__) +{ + Ecore_Fb_Filter_Data *filter_data; + + filter_data = loop_data; + if (!filter_data) return 1; + if (type == ECORE_FB_EVENT_MOUSE_MOVE) + { + if ((filter_data->last_event_type) == ECORE_FB_EVENT_MOUSE_MOVE) + { + filter_data->last_event_type = type; + return 0; + } + } + filter_data->last_event_type = type; + return 1; +} + +static void +_ecore_fb_event_filter_end(void *data __UNUSED__, void *loop_data) +{ + Ecore_Fb_Filter_Data *filter_data; + + filter_data = loop_data; + if (filter_data) free(filter_data); +} diff --git a/ecore/src/lib/ecore_fb/ecore_fb_keytab.h b/ecore/src/lib/ecore_fb/ecore_fb_keytab.h new file mode 100644 index 0000000..dfc17b3 --- /dev/null +++ b/ecore/src/lib/ecore_fb/ecore_fb_keytab.h @@ -0,0 +1,128 @@ + "0x00", "0x00", "0x00", /**/"", "", "",/***/ + "Escape", "Escape", "Escape", /**/"", "", "",/***/ + "1", "exclam", "1", /**/"1", "!", "1",/***/ + "2", "at", "2", /**/"2", "@", "2",/***/ + "3", "numbersign", "3", /**/"3", "#", "3",/***/ + "4", "dollar", "4", /**/"4", "$", "4",/***/ + "5", "percent", "5", /**/"5", "%", "5",/***/ + "6", "asciicircumm", "6", /**/"6", "^", "6",/***/ + "7", "ampersand", "7", /**/"7", "&", "7",/***/ + "8", "asterik", "8", /**/"8", "*", "8",/***/ + "9", "parenleft", "9", /**/"9", "(", "9",/***/ + "0", "parenright", "0", /**/"0", ")", "0",/***/ + "minus", "underscore", "minus", /**/"-", "_", "-",/***/ + "equal", "plus", "equal", /**/"=", "+", "=",/***/ + "BackSpace", "BackSpace", "BackSpace", /**/"\010","\010","\010",/***/ + "Tab", "ISO_Left_Tab", "Tab", /**/"\011","", "\011",/***/ + "q", "Q", "Q", /**/"q", "Q", "Q",/***/ + "w", "W", "W", /**/"w", "W", "W",/***/ + "e", "E", "E", /**/"e", "E", "E",/***/ + "r", "R", "R", /**/"r", "R", "R",/***/ + "t", "T", "T", /**/"t", "T", "T",/***/ + "y", "Y", "Y", /**/"y", "Y", "Y",/***/ + "u", "U", "U", /**/"u", "U", "U",/***/ + "i", "I", "I", /**/"i", "I", "I",/***/ + "o", "O", "O", /**/"o", "O", "O",/***/ + "p", "P", "P", /**/"p", "P", "P",/***/ + "bracketleft", "braceleft", "bracketleft", /**/"[", "{", "[",/***/ + "bracketright", "braceright", "bracketright", /**/"]", "}", "]",/***/ + "Return", "Return", "Return", /**/"\015","\015","\015",/***/ + "Control_L", "Control_L", "Control_L", /**/"", "", "",/***/ + "a", "A", "A", /**/"a", "A", "A",/***/ + "s", "S", "S", /**/"s", "S", "S",/***/ + "d", "D", "D", /**/"d", "D", "D",/***/ + "f", "F", "F", /**/"f", "F", "F",/***/ + "g", "G", "G", /**/"g", "G", "G",/***/ + "h", "h", "H", /**/"h", "H", "H",/***/ + "j", "J", "J", /**/"j", "J", "J",/***/ + "k", "K", "K", /**/"k", "K", "K",/***/ + "l", "L", "L", /**/"l", "L", "L",/***/ + "semicolon", "colon", "semicolon", /**/";", ":", ";",/***/ + "apostrophe", "quotedbl", "apostrophe", /**/"'", "\"", "'",/***/ + "grave", "asciitilde", "grave", /**/"`", "~", "`",/***/ + "Shift_L", "Shift_L", "Shift_L", /**/"", "", "",/***/ + "backslash", "bar", "backslash", /**/"\\", "|", "\\",/***/ + "z", "Z", "Z", /**/"z", "Z", "Z",/***/ + "x", "X", "X", /**/"x", "X", "X",/***/ + "c", "C", "C", /**/"c", "C", "C",/***/ + "v", "V", "V", /**/"v", "V", "V",/***/ + "b", "B", "B", /**/"b", "B", "B",/***/ + "n", "N", "N", /**/"n", "N", "N",/***/ + "m", "M", "M", /**/"m", "M", "M",/***/ + "comma", "less", "comma", /**/",", "<", ",",/***/ + "period", "greater", "period", /**/".", ">", ".",/***/ + "slash", "question", "slash", /**/"/", "?", "/",/***/ + "Shift_R", "Shift_R", "Shift_R", /**/"", "", "",/***/ + "KP_Multiply", "KP_Multiply", "KP_Multiply", /**/"", "*", "",/***/ + "Alt_L", "Alt_L", "Alt_L", /**/"", "", "",/***/ + "space", "space", "space", /**/" ", " ", " ",/***/ + "Caps_Lock", "Caps_Lock", "Caps_Lock", /**/"", "", "",/***/ + "F1", "F1", "F1", /**/"", "", "",/***/ + "F2", "F2", "F2", /**/"", "", "",/***/ + "F3", "F3", "F3", /**/"", "", "",/***/ + "F4", "F4", "F4", /**/"", "", "",/***/ + "F5", "F5", "F5", /**/"", "", "",/***/ + "F6", "F6", "F6", /**/"", "", "",/***/ + "F7", "F7", "F7", /**/"", "", "",/***/ + "F8", "F8", "F8", /**/"", "", "",/***/ + "F9", "F9", "F9", /**/"", "", "",/***/ + "F10", "F10", "F10", /**/"", "", "",/***/ + "Num_Lock", "Num_Lock", "Num_Lock", /**/"", "", "",/***/ + "Scroll_Lock", "Scroll_Lock", "Scroll_Lock", /**/"", "", "",/***/ + "KP_Home", "KP_7", "KP_Home", /**/"", "7", "",/***/ + "KP_Up", "KP_8", "KP_Up", /**/"", "8", "",/***/ + "KP_Prior", "KP_9", "KP_Prior", /**/"", "9", "",/***/ + "KP_Subtract", "KP_Subtract", "KP_Subtract", /**/"", "", "",/***/ + "KP_Left", "KP_4", "KP_Left", /**/"", "4", "",/***/ + "KP_Begin", "KP_5", "KP_Begin", /**/"", "5", "",/***/ + "KP_Right", "KP_6", "KP_Right", /**/"", "6", "",/***/ + "KP_Add", "KP_Add", "KP_Add", /**/"", "", "",/***/ + "KP_End", "KP_1", "KP_End", /**/"", "1", "",/***/ + "KP_Down", "KP_2", "KP_Down", /**/"", "2", "",/***/ + "KP_Next", "KP_3", "KP_Next", /**/"", "3", "",/***/ + "KP_Insert", "KP_0", "KP_Insert", /**/"", "0", "",/***/ + "KP_Delete", "KP_Decimal", "KP_Delete", /**/"", ".", "",/***/ + "0x54", "0x54", "0x54", /**/"", "", "",/***/ + "0x55", "0x55", "0x55", /**/"", "", "",/***/ + "0x56", "0x56", "0x56", /**/"", "", "",/***/ + "F11", "F11", "F11", /**/"", "", "",/***/ + "F12", "F12", "F12", /**/"", "", "",/***/ + "0x59", "0x59", "0x59", /**/"", "", "",/***/ + "0x5a", "0x5a", "0x5a", /**/"", "", "",/***/ + "0x5b", "0x5b", "0x5b", /**/"", "", "",/***/ + "0x5c", "0x5c", "0x5c", /**/"", "", "",/***/ + "0x5d", "0x5d", "0x5d", /**/"", "", "",/***/ + "0x5e", "0x5e", "0x5e", /**/"", "", "",/***/ + "0x5f", "0x5f", "0x5f", /**/"", "", "",/***/ + "KP_Enter", "KP_Enter", "KP_Enter", /**/"", "", "",/***/ + "Control_R", "Control_R", "Control_R", /**/"", "", "",/***/ + "KP_Divide", "KP_Divide", "KP_Divide", /**/"", "", "",/***/ + "Print", "Print", "Print", /**/"", "", "",/***/ + "Alt_R", "Alt_R", "Alt_R", /**/"", "", "",/***/ + "0x65", "0x65", "0x65", /**/"", "", "",/***/ + "Home", "Home", "Home", /**/"", "", "",/***/ + "Up", "Up", "Up", /**/"", "", "",/***/ + "Prior", "Prior", "Prior", /**/"", "", "",/***/ + "Left", "Left", "Left", /**/"", "", "",/***/ + "Right", "Right", "Right", /**/"", "", "",/***/ + "End", "End", "End", /**/"", "", "",/***/ + "Down", "Down", "Down", /**/"", "", "",/***/ + "Next", "Next", "Next", /**/"", "", "",/***/ + "Insert", "Insert", "Insert", /**/"", "", "",/***/ + "Delete", "Delete", "Delete", /**/"\177","\177","\177",/***/ + "0x70", "0x70", "0x70", /**/"", "", "",/***/ + "0x71", "0x71", "0x71", /**/"", "", "",/***/ + "0x72", "0x72", "0x72", /**/"", "", "",/***/ + "0x73", "0x73", "0x73", /**/"", "", "",/***/ + "0x74", "0x74", "0x74", /**/"", "", "",/***/ + "0x75", "0x75", "0x75", /**/"", "", "",/***/ + "0x76", "0x76", "0x76", /**/"", "", "",/***/ + "Pause", "Pause", "Pause", /**/"", "", "",/***/ + "0x78", "0x78", "0x78", /**/"", "", "",/***/ + "0x79", "0x79", "0x79", /**/"", "", "",/***/ + "0x7a", "0x7a", "0x7a", /**/"", "", "",/***/ + "0x7b", "0x7b", "0x7b", /**/"", "", "",/***/ + "0x7c", "0x7c", "0x7c", /**/"", "", "",/***/ + "Super_L", "Super_L", "Super_L", /**/"", "", "",/***/ + "Super_R", "Super_R", "Super_R", /**/"", "", "",/***/ + "0x7f", "0x7f", "0x7f", /**/"", "", "" /***/ diff --git a/ecore/src/lib/ecore_fb/ecore_fb_private.h b/ecore/src/lib/ecore_fb/ecore_fb_private.h new file mode 100644 index 0000000..3c27a34 --- /dev/null +++ b/ecore/src/lib/ecore_fb/ecore_fb_private.h @@ -0,0 +1,30 @@ +#ifndef _ECORE_FB_PRIVATE_H +#define _ECORE_FB_PRIVATE_H + +/* hacks to stop people NEEDING #include <linux/h3600_ts.h> */ +#ifndef TS_SET_CAL +#define TS_SET_CAL 0x4014660b +#endif +#ifndef TS_GET_CAL +#define TS_GET_CAL 0x8014660a +#endif +#ifndef TS_SET_BACKLIGHT +#define TS_SET_BACKLIGHT 0x40086614 +#endif +#ifndef TS_GET_BACKLIGHT +#define TS_GET_BACKLIGHT 0x80086614 +#endif +#ifndef LED_ON +#define LED_ON 0x40046605 +#endif +#ifndef TS_SET_CONTRAST +#define TS_SET_CONTRAST 0x40046615 +#endif +#ifndef TS_GET_CONTRAST +#define TS_GET_CONTRAST 0x80046615 +#endif +#ifndef FLITE_ON +#define FLITE_ON 0x40046607 +#endif + +#endif diff --git a/ecore/src/lib/ecore_file/.cvsignore b/ecore/src/lib/ecore_file/.cvsignore new file mode 100644 index 0000000..be74149 --- /dev/null +++ b/ecore/src/lib/ecore_file/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +libecore_file.la diff --git a/ecore/src/lib/ecore_file/CVS/Entries b/ecore/src/lib/ecore_file/CVS/Entries new file mode 100644 index 0000000..5ad56ea --- /dev/null +++ b/ecore/src/lib/ecore_file/CVS/Entries @@ -0,0 +1,13 @@ +/.cvsignore/1.1/Sun Feb 20 12:17:07 2005//THEAD +/Ecore_File.h/1.13/Wed Jun 22 14:51:36 2005//THEAD +/Makefile.am/1.8/Fri Jun 17 23:52:32 2005//THEAD +/ecore_file.c/1.11/Fri Jun 17 23:52:32 2005//THEAD +/ecore_file_download.c/1.5/Wed Jun 22 14:51:37 2005//THEAD +/ecore_file_monitor.c/1.2/Wed Mar 30 06:35:12 2005//THEAD +/ecore_file_monitor_fam.c/1.4/Wed Apr 20 09:20:33 2005//THEAD +/ecore_file_monitor_inotify.c/1.4/Wed Apr 20 09:20:33 2005//THEAD +/ecore_file_monitor_poll.c/1.8/Wed Apr 20 09:20:33 2005//THEAD +/ecore_file_path.c/1.2/Sun Jun 12 14:08:46 2005//THEAD +/ecore_file_private.h/1.7/Fri Jun 17 23:52:32 2005//THEAD +/ecore_file_utils.c/1.1/Sun Feb 20 12:17:07 2005//THEAD +D diff --git a/ecore/src/lib/ecore_file/CVS/Repository b/ecore/src/lib/ecore_file/CVS/Repository new file mode 100644 index 0000000..bba5b7a --- /dev/null +++ b/ecore/src/lib/ecore_file/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_file diff --git a/ecore/src/lib/ecore_file/CVS/Root b/ecore/src/lib/ecore_file/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_file/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_file/CVS/Tag b/ecore/src/lib/ecore_file/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_file/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_file/Ecore_File.h b/ecore/src/lib/ecore_file/Ecore_File.h new file mode 100644 index 0000000..541d51a --- /dev/null +++ b/ecore/src/lib/ecore_file/Ecore_File.h @@ -0,0 +1,91 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#ifndef ECORE_FILE_H +#define ECORE_FILE_H + +/* + * TODO: + * - More events, move/rename of directory file + */ + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +#include <Ecore.h> +#include <time.h> + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _Ecore_File_Monitor Ecore_File_Monitor; + typedef struct _Ecore_File_Monitor_Event Ecore_File_Monitor_Event; + + typedef enum + { + ECORE_FILE_EVENT_NONE, + ECORE_FILE_EVENT_CREATED_FILE, + ECORE_FILE_EVENT_CREATED_DIRECTORY, + ECORE_FILE_EVENT_DELETED_FILE, + ECORE_FILE_EVENT_DELETED_DIRECTORY, + ECORE_FILE_EVENT_DELETED_SELF, + ECORE_FILE_EVENT_MODIFIED + } Ecore_File_Event; + + + EAPI int ecore_file_init (void); + EAPI int ecore_file_shutdown (void); + EAPI time_t ecore_file_mod_time (const char *file); + EAPI int ecore_file_exists (const char *file); + EAPI int ecore_file_is_dir (const char *file); + EAPI int ecore_file_mkdir (const char *dir); + EAPI int ecore_file_rmdir (const char *dir); + EAPI int ecore_file_mkpath (const char *path); + EAPI int ecore_file_cp (const char *src, const char *dst); + EAPI int ecore_file_mv (const char *src, const char *dst); + EAPI char *ecore_file_realpath (const char *file); + EAPI int ecore_file_unlink (const char *file); + EAPI char *ecore_file_get_file (char *path); + EAPI char *ecore_file_get_dir (char *path); + + EAPI int ecore_file_can_exec (const char *file); + EAPI char *ecore_file_readlink (const char *link); + EAPI Ecore_List *ecore_file_ls (const char *dir); + + EAPI Ecore_File_Monitor *ecore_file_monitor_add(const char *path, + void (*func) (void *data, + Ecore_File_Monitor *ecore_file_monitor, + Ecore_File_Event event, + const char *path), + void *data); + EAPI void ecore_file_monitor_del(Ecore_File_Monitor *ecore_file_monitor); + EAPI const char *ecore_file_monitor_path_get(Ecore_File_Monitor *ecore_file_monitor); + + EAPI int ecore_file_app_installed(const char *app); + + EAPI int ecore_file_download(const char *url, const char *dst, + void (*completion_cb)(void *data, + const char *file, + int status), + void *data); + EAPI int ecore_file_download_protocol_available(const char *protocol); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/ecore/src/lib/ecore_file/Makefile.am b/ecore/src/lib/ecore_file/Makefile.am new file mode 100644 index 0000000..6aceac6 --- /dev/null +++ b/ecore/src/lib/ecore_file/Makefile.am @@ -0,0 +1,40 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore \ +@curl_cflags@ + +libecore_file_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_FILE + +lib_LTLIBRARIES = libecore_file.la +include_HEADERS = Ecore_File.h + +libecore_file_la_SOURCES = \ +ecore_file.c \ +ecore_file_private.h \ +ecore_file_monitor.c \ +ecore_file_monitor_fam.c \ +ecore_file_monitor_inotify.c \ +ecore_file_monitor_poll.c \ +ecore_file_path.c \ +ecore_file_download.c + +libecore_file_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +@fam_libs@ @curl_libs@ + +endif + +EXTRA_DIST = \ +ecore_file.c \ +ecore_file_private.h \ +ecore_file_monitor.c \ +ecore_file_monitor_fam.c \ +ecore_file_monitor_inotify.c \ +ecore_file_monitor_poll.c \ +ecore_file_path.c + diff --git a/ecore/src/lib/ecore_file/ecore_file.c b/ecore/src/lib/ecore_file/ecore_file.c new file mode 100644 index 0000000..e71fc19 --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file.c @@ -0,0 +1,257 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_file_private.h" + +/* externally accessible functions */ +int +ecore_file_init() +{ + if (!ecore_file_monitor_init()) + return 0; + if (!ecore_file_path_init()) + return 0; + if (!ecore_file_download_init()) + return 0; + return 1; +} + +int +ecore_file_shutdown() +{ + if (!ecore_file_monitor_shutdown()) + return 0; + if (!ecore_file_path_shutdown()) + return 0; + if (!ecore_file_download_shutdown()) + return 0; + return 1; +} + +time_t +ecore_file_mod_time(const char *file) +{ + struct stat st; + + if (stat(file, &st) < 0) return 0; + return st.st_mtime; +} + +int +ecore_file_exists(const char *file) +{ + struct stat st; + + if (stat(file, &st) < 0) return 0; + return 1; +} + +int +ecore_file_is_dir(const char *file) +{ + struct stat st; + + if (stat(file, &st) < 0) return 0; + if (S_ISDIR(st.st_mode)) return 1; + return 0; +} + +static mode_t default_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; + +int +ecore_file_mkdir(const char *dir) +{ + if (mkdir(dir, default_mode) < 0) return 0; + return 1; +} + +int +ecore_file_rmdir(const char *dir) +{ + if (rmdir(dir) < 0) return 0; + return 1; +} + +int +ecore_file_unlink(const char *file) +{ + if (unlink(file) < 0) return 0; + return 1; +} + +int +ecore_file_mkpath(const char *path) +{ + char ss[PATH_MAX]; + int i; + + ss[0] = 0; + i = 0; + while (path[i]) + { + if (i == sizeof(ss) - 1) return 0; + ss[i] = path[i]; + ss[i + 1] = 0; + if (path[i] == '/') + { + ss[i] = 0; + if ((ecore_file_exists(ss)) && (!ecore_file_is_dir(ss))) return 0; + else if (!ecore_file_exists(ss)) ecore_file_mkdir(ss); + ss[i] = '/'; + } + i++; + } + if ((ecore_file_exists(ss)) && (!ecore_file_is_dir(ss))) return 0; + else if (!ecore_file_exists(ss)) ecore_file_mkdir(ss); + return 1; +} + +int +ecore_file_cp(const char *src, const char *dst) +{ + FILE *f1, *f2; + char buf[16384]; + size_t num; + + f1 = fopen(src, "rb"); + if (!f1) return 0; + f2 = fopen(dst, "wb"); + if (!f2) + { + fclose(f1); + return 0; + } + while ((num = fread(buf, 1, 16384, f1)) > 0) fwrite(buf, 1, num, f2); + fclose(f1); + fclose(f2); + return 1; +} + +int +ecore_file_mv(const char *src, const char *dst) +{ + if (ecore_file_exists(dst)) return 0; + if (rename(src, dst)) return 0; + return 1; +} + +char * +ecore_file_realpath(const char *file) +{ + char buf[PATH_MAX]; + struct stat st; + + if (!realpath(file, buf) || stat(buf, &st)) return strdup(""); + return strdup(buf); +} + +char * +ecore_file_get_file(char *path) +{ + char *result = NULL; + + if (!path) return NULL; + if ((result = strrchr(path, '/'))) result++; + else result = path; + return result; +} + +char * +ecore_file_get_dir(char *file) +{ + char *p; + char buf[PATH_MAX]; + + strncpy(buf, file, PATH_MAX); + p = strrchr(buf, '/'); + if (!p) + { + return strdup(file); + } + *p = 0; + return strdup(buf); +} + +int +ecore_file_can_exec(const char *file) +{ + static int have_uid = 0; + static uid_t uid = -1; + static gid_t gid = -1; + struct stat st; + int ok; + + if (!file) return 0; + if (stat(file, &st) < 0) return 0; + + ok = 0; + if (!have_uid) uid = getuid(); + if (!have_uid) gid = getgid(); + have_uid = 1; + if (st.st_uid == uid) + { + if (st.st_mode & S_IXUSR) ok = 1; + } + else if (st.st_gid == gid) + { + if (st.st_mode & S_IXGRP) ok = 1; + } + else + { + if (st.st_mode & S_IXOTH) ok = 1; + } + return(ok); +} + +char * +ecore_file_readlink(const char *link) +{ + char buf[PATH_MAX]; + int count; + + if ((count = readlink(link, buf, sizeof(buf))) < 0) return NULL; + buf[count] = 0; + return strdup(buf); +} + +Ecore_List * +ecore_file_ls(const char *dir) +{ + DIR *dirp; + struct dirent *dp; + Ecore_List *list; + + dirp = opendir(dir); + if (!dirp) return NULL; + list = ecore_list_new(); + while ((dp = readdir(dirp))) + { + if ((strcmp(dp->d_name, ".")) && (strcmp(dp->d_name, ".."))) + { + char *file, *f; + + /* insertion sort */ + ecore_list_goto_first(list); + while ((file = ecore_list_current(list))) + { + if (strcmp(file, dp->d_name) > 0) + { + f = strdup(dp->d_name); + ecore_list_insert(list, f); + break; + } + ecore_list_next(list); + } + /* nowhwre to go? just append it */ + if (!file) + { + f = strdup(dp->d_name); + ecore_list_append(list, f); + } + } + } + closedir(dirp); + + ecore_list_goto_first(list); + return list; +} diff --git a/ecore/src/lib/ecore_file/ecore_file_download.c b/ecore/src/lib/ecore_file/ecore_file_download.c new file mode 100644 index 0000000..500a051 --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_download.c @@ -0,0 +1,292 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_file_private.h" + +#ifdef HAVE_CURL +#include <curl/curl.h> + +typedef struct _Ecore_File_Download_Job Ecore_File_Download_Job; + +struct _Ecore_File_Download_Job +{ + Ecore_Fd_Handler *fd_handler; + CURL *curl; + void (*completion_cb)(void *data, const char *file, int status); + void *data; + FILE *file; + char *dst; +}; + +Ecore_File_Download_Job *_ecore_file_download_curl(const char *url, const char *dst, + void (*completion_cb)(void *data, const char *file, int status), + void *data); +static int _ecore_file_download_curl_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); + +static CURLM *curlm; +static Ecore_List *_job_list; +static fd_set _current_fd_set; +#endif + +int +ecore_file_download_init(void) +{ +#ifdef HAVE_CURL + FD_ZERO(&_current_fd_set); + _job_list = ecore_list_new(); + if (!_job_list) return 0; + + if (curl_global_init(CURL_GLOBAL_NOTHING)) return 0; + + curlm = curl_multi_init(); + if (!curlm) + { + ecore_list_destroy(_job_list); + _job_list = NULL; + return 0; + } +#endif + return 1; +} + +int +ecore_file_download_shutdown(void) +{ +#ifdef HAVE_CURL + Ecore_File_Download_Job *job; + + if (!ecore_list_is_empty(_job_list)) + { + ecore_list_goto_first(_job_list); + while ((job = ecore_list_next(_job_list))) + { + ecore_main_fd_handler_del(job->fd_handler); + curl_multi_remove_handle(curlm, job->curl); + curl_easy_cleanup(job->curl); + fclose(job->file); + free(job->dst); + free(job); + } + } + ecore_list_destroy(_job_list); + curl_multi_cleanup(curlm); + curl_global_cleanup(); +#endif + return 1; +} + +int +ecore_file_download(const char *url, const char *dst, + void (*completion_cb)(void *data, const char *file, int status), + void *data) +{ + if (!ecore_file_is_dir(ecore_file_get_dir(dst))) return 0; + if (ecore_file_exists(dst)) return 0; + + /* FIXME: Add handlers for http and ftp! */ + if (!strncmp(url, "file://", 7)) + { + /* FIXME: Maybe fork? Might take a while to copy. + * Check filesize? */ + /* Just copy it */ + + url += 7; + /* skip hostname */ + url = strchr(url, '/'); + return ecore_file_cp(url, dst); + } +#ifdef HAVE_CURL + else if ((!strncmp(url, "http://", 7)) || + (!strncmp(url, "ftp://", 6))) + { + /* download */ + Ecore_File_Download_Job *job; + + job = _ecore_file_download_curl(url, dst, completion_cb, data); + if (job) + return 1; + else + return 0; + } +#endif + else + { + return 0; + } +} + +int +ecore_file_download_protocol_available(const char *protocol) +{ + if (!strncmp(protocol, "file://", 7)) return 1; +#ifdef HAVE_CURL + else if (!strncmp(protocol, "http://", 7)) return 1; + else if (!strncmp(protocol, "ftp://", 6)) return 1; +#endif + + return 0; +} + +#ifdef HAVE_CURL +/* + * FIXME: Use + * CURLOPT_PROGRESSFUNCTION and CURLOPT_PROGRESSDATA to + * get reports on progress. + * And maybe other nifty functions... + */ +Ecore_File_Download_Job * +_ecore_file_download_curl(const char *url, const char *dst, + void (*completion_cb)(void *data, const char *file, + int status), + void *data) +{ + CURLMsg *curlmsg; + fd_set read_set, write_set, exc_set; + int fd_max; + int fd; + int flags; + int n_remaining, still_running; + Ecore_File_Download_Job *job; + + job = calloc(1, sizeof(Ecore_File_Download_Job)); + if (!job) return NULL; + + job->file = fopen(dst, "wb"); + if (!job->file) + { + free(job); + return NULL; + } + job->curl = curl_easy_init(); + if (!job->curl) + { + fclose(job->file); + free(job); + return NULL; + } + curl_easy_setopt(job->curl, CURLOPT_URL, url); + curl_easy_setopt(job->curl, CURLOPT_WRITEDATA, job->file); + + job->data = data; + job->completion_cb = completion_cb; + job->dst = strdup(dst); + ecore_list_append(_job_list, job); + + curl_multi_add_handle(curlm, job->curl); + while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM); + + /* check for completed jobs */ + while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL) + { + Ecore_File_Download_Job *current; + + if (curlmsg->msg != CURLMSG_DONE) continue; + + /* find the job which is done */ + ecore_list_goto_first(_job_list); + while ((current = ecore_list_current(_job_list))) + { + if (curlmsg->easy_handle == current->curl) + { + /* We have a match -- delete the job */ + if (current == job) + job = NULL; + if (current->fd_handler) + { + FD_CLR(ecore_main_fd_handler_fd_get(current->fd_handler), + &_current_fd_set); + ecore_main_fd_handler_del(current->fd_handler); + } + ecore_list_remove(_job_list); + curl_multi_remove_handle(curlm, current->curl); + curl_easy_cleanup(current->curl); + fclose(current->file); + if (current->completion_cb) + current->completion_cb(current->data, current->dst, + curlmsg->data.result); + free(current->dst); + free(current); + break; + } + ecore_list_next(_job_list); + } + } + + if (job) + { + FD_ZERO(&read_set); + FD_ZERO(&write_set); + FD_ZERO(&exc_set); + + /* Stupid curl, why can't I get the fd to the current added job? */ + curl_multi_fdset(curlm, &read_set, &write_set, &exc_set, &fd_max); + for (fd = 0; fd <= fd_max; fd++) + { + if (!FD_ISSET(fd, &_current_fd_set)) + { + flags = 0; + if (FD_ISSET(fd, &read_set)) flags |= ECORE_FD_READ; + if (FD_ISSET(fd, &write_set)) flags |= ECORE_FD_WRITE; + if (FD_ISSET(fd, &exc_set)) flags |= ECORE_FD_ERROR; + if (flags) + { + FD_SET(fd, &_current_fd_set); + job->fd_handler = ecore_main_fd_handler_add(fd, flags, + _ecore_file_download_curl_fd_handler, + NULL, NULL, NULL); + } + } + } + if (!job->fd_handler) + { + curl_easy_cleanup(job->curl); + fclose(job->file); + free(job); + job = NULL; + } + } + + return job; +} + +static int +_ecore_file_download_curl_fd_handler(void *data, Ecore_Fd_Handler *fd_handler) +{ + Ecore_File_Download_Job *job; + CURLMsg *curlmsg; + int n_remaining, still_running; + + /* FIXME: Can this run for a long time? Maybe limit how long it can run */ + while (curl_multi_perform(curlm, &still_running) == CURLM_CALL_MULTI_PERFORM); + + /* Loop jobs and check if any are done */ + while ((curlmsg = curl_multi_info_read(curlm, &n_remaining)) != NULL) + { + if (curlmsg->msg != CURLMSG_DONE) continue; + + /* find the job which is done */ + ecore_list_goto_first(_job_list); + while ((job = ecore_list_current(_job_list))) + { + if (curlmsg->easy_handle == job->curl) + { + /* We have a match -- delete the job */ + FD_CLR(ecore_main_fd_handler_fd_get(job->fd_handler), + &_current_fd_set); + ecore_list_remove(_job_list); + ecore_main_fd_handler_del(job->fd_handler); + curl_multi_remove_handle(curlm, job->curl); + curl_easy_cleanup(job->curl); + fclose(job->file); + if (job->completion_cb) + job->completion_cb(job->data, job->dst, !curlmsg->data.result); + free(job->dst); + free(job); + break; + } + ecore_list_next(_job_list); + } + } + return 1; +} +#endif diff --git a/ecore/src/lib/ecore_file/ecore_file_monitor.c b/ecore/src/lib/ecore_file/ecore_file_monitor.c new file mode 100644 index 0000000..e270e01 --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_monitor.c @@ -0,0 +1,126 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_file_private.h" + +typedef enum { + ECORE_FILE_MONITOR_TYPE_NONE, +#ifdef HAVE_INOTIFY + ECORE_FILE_MONITOR_TYPE_INOTIFY, +#endif +#ifdef HAVE_FAM + ECORE_FILE_MONITOR_TYPE_FAM, +#endif +#ifdef HAVE_POLL + ECORE_FILE_MONITOR_TYPE_POLL +#endif +} Ecore_File_Monitor_Type; + +static Ecore_File_Monitor_Type monitor_type = ECORE_FILE_MONITOR_TYPE_NONE; + +int +ecore_file_monitor_init(void) +{ +#ifdef HAVE_INOTIFY +#if 0 + monitor_type = ECORE_FILE_MONITOR_TYPE_INOTIFY; + if (ecore_file_monitor_inotify_init()) + return 1; +#endif +#endif +#ifdef HAVE_FAM +#if 0 + monitor_type = ECORE_FILE_MONITOR_TYPE_FAM; + if (ecore_file_monitor_fam_init()) + return 1; +#endif +#endif +#ifdef HAVE_POLL + monitor_type = ECORE_FILE_MONITOR_TYPE_POLL; + if (ecore_file_monitor_poll_init()) + return 1; +#endif + monitor_type = ECORE_FILE_MONITOR_TYPE_NONE; + return 0; +} + +int +ecore_file_monitor_shutdown(void) +{ + switch (monitor_type) + { + case ECORE_FILE_MONITOR_TYPE_NONE: + return 1; +#ifdef HAVE_INOTIFY + case ECORE_FILE_MONITOR_TYPE_INOTIFY: + return ecore_file_monitor_inotify_shutdown(); +#endif +#ifdef HAVE_FAM + case ECORE_FILE_MONITOR_TYPE_FAM: + return ecore_file_monitor_fam_shutdown(); +#endif +#ifdef HAVE_POLL + case ECORE_FILE_MONITOR_TYPE_POLL: + return ecore_file_monitor_poll_shutdown(); +#endif + } + return 0; +} + +Ecore_File_Monitor * +ecore_file_monitor_add(const char *path, + void (*func) (void *data, Ecore_File_Monitor *em, + Ecore_File_Event event, + const char *path), + void *data) +{ + switch (monitor_type) + { + case ECORE_FILE_MONITOR_TYPE_NONE: + return NULL; +#ifdef HAVE_INOTIFY + case ECORE_FILE_MONITOR_TYPE_INOTIFY: + return ecore_file_monitor_inotify_add(path, func, data); +#endif +#ifdef HAVE_FAM + case ECORE_FILE_MONITOR_TYPE_FAM: + return ecore_file_monitor_fam_add(path, func, data); +#endif +#ifdef HAVE_POLL + case ECORE_FILE_MONITOR_TYPE_POLL: + return ecore_file_monitor_poll_add(path, func, data); +#endif + } + return NULL; +} + +void +ecore_file_monitor_del(Ecore_File_Monitor *em) +{ + switch (monitor_type) + { + case ECORE_FILE_MONITOR_TYPE_NONE: + break; +#ifdef HAVE_INOTIFY + case ECORE_FILE_MONITOR_TYPE_INOTIFY: + ecore_file_monitor_inotify_del(em); + break; +#endif +#ifdef HAVE_FAM + case ECORE_FILE_MONITOR_TYPE_FAM: + ecore_file_monitor_fam_del(em); + break; +#endif +#ifdef HAVE_POLL + case ECORE_FILE_MONITOR_TYPE_POLL: + ecore_file_monitor_poll_del(em); + break; +#endif + } +} + +const char * +ecore_file_monitor_path_get(Ecore_File_Monitor *em) +{ + return em->path; +} diff --git a/ecore/src/lib/ecore_file/ecore_file_monitor_fam.c b/ecore/src/lib/ecore_file/ecore_file_monitor_fam.c new file mode 100644 index 0000000..ffdfe7d --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_monitor_fam.c @@ -0,0 +1,305 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_file_private.h" + +/* + * TODO: + * - When several subdirectories are created really fast, the code + * doesn't keep up! + * - Same for deletion of files in deleted directories! + */ + +#ifdef HAVE_FAM + +#include <fam.h> + +typedef struct _Ecore_File_Monitor_Fam Ecore_File_Monitor_Fam; +typedef struct _Ecore_File Ecore_File; + +#define ECORE_FILE_MONITOR_FAM(x) ((Ecore_File_Monitor_Fam *)(x)) + +struct _Ecore_File_Monitor_Fam +{ + Ecore_File_Monitor monitor; + FAMRequest *request; +}; + +struct _Ecore_File +{ + Ecore_Oldlist __list_data; + char *name; +}; + +static Ecore_Fd_Handler *_fdh = NULL; +static FAMConnection *_fc = NULL; +static Ecore_Oldlist *_monitors = NULL; + +static int _ecore_file_monitor_fam_handler(void *data, Ecore_Fd_Handler *fdh); +static Ecore_File *_ecore_file_monitor_fam_file_find(Ecore_File_Monitor *em, char *name); +static Ecore_File_Event _ecore_file_monitor_fam_event_get(FAMCodes code, int self, int is_dir); + +int +ecore_file_monitor_fam_init(void) +{ + _fc = calloc(1, sizeof(FAMConnection)); + if (!_fc) return 0; + + FAMOpen(_fc); + _fdh = ecore_main_fd_handler_add(FAMCONNECTION_GETFD(_fc), ECORE_FD_READ, + _ecore_file_monitor_fam_handler, NULL, NULL, NULL); + + return 1; +} + +int +ecore_file_monitor_fam_shutdown(void) +{ + Ecore_Oldlist *l; + + for (l = _monitors; l;) + { + Ecore_File_Monitor *em; + + em = ECORE_FILE_MONITOR(l); + l = l->next; + ecore_file_monitor_fam_del(em); + } + if (_fdh) ecore_main_fd_handler_del(_fdh); + if (_fc) + { + FAMClose(_fc); + free(_fc); + } + return 1; +} + +Ecore_File_Monitor * +ecore_file_monitor_fam_add(const char *path, + void (*func) (void *data, + Ecore_File_Monitor *em, + Ecore_File_Event event, + const char *path), + void *data) +{ + Ecore_File_Monitor *em; + int len; + + em = calloc(1, sizeof(Ecore_File_Monitor_Fam)); + if (!em) return NULL; + + em->func = func; + em->data = data; + + em->path = strdup(path); + len = strlen(em->path); + if (em->path[len - 1] == '/') + em->path[len - 1] = 0; + + if (ecore_file_exists(em->path)) + { + ECORE_FILE_MONITOR_FAM(em)->request = calloc(1, sizeof(FAMRequest)); + if (!ECORE_FILE_MONITOR_FAM(em)->request) + { + ecore_file_monitor_fam_del(em); + return NULL; + } + if (ecore_file_is_dir(em->path)) + { + FAMMonitorDirectory(_fc, em->path, ECORE_FILE_MONITOR_FAM(em)->request, em); + } + else + { + FAMMonitorFile(_fc, em->path, ECORE_FILE_MONITOR_FAM(em)->request, em); + } + } + else + { + ecore_file_monitor_fam_del(em); + return NULL; + } + + _monitors = _ecore_list_append(_monitors, em); + + return em; +} + +void +ecore_file_monitor_fam_del(Ecore_File_Monitor *em) +{ + Ecore_Oldlist *l; + + for (l = em->files; l; l = l->next) + { + Ecore_File *f; + + f = (Ecore_File *)l; + free(f->name); + free(f); + } + + _monitors = _ecore_list_remove(_monitors, em); + + if (ECORE_FILE_MONITOR_FAM(em)->request) + { + FAMCancelMonitor(_fc, ECORE_FILE_MONITOR_FAM(em)->request); + free(ECORE_FILE_MONITOR_FAM(em)->request); + } + free(em->path); + free(em); +} + +static int +_ecore_file_monitor_fam_handler(void *data, Ecore_Fd_Handler *fdh) +{ + int pending, i; + + while ((pending = FAMPending(_fc))) + { + for (i = 0; i < pending; i++) + { + Ecore_File_Monitor *em; + FAMEvent fe; + Ecore_File_Event event; + char buf[PATH_MAX]; + int len, self; + + buf[0] = 0; + + FAMNextEvent(_fc, &fe); + len = strlen(fe.filename); + if (fe.filename[len - 1] == '/') + fe.filename[len - 1] = 0; + self = !strcmp(em->path, fe.filename); + if (!self) + snprintf(buf, sizeof(buf), "%s/%s", em->path, fe.filename); + + event = _ecore_file_monitor_fam_event_get(fe.code, self, ecore_file_is_dir(buf)); + em = fe.userdata; + if (!em) continue; + if (event == ECORE_FILE_EVENT_NONE) continue; +#if 0 + if (!strcmp(em->path, fe.filename)) + { + Evas_List *l; + + if (event == ECORE_FILE_EVENT_DELETED) + { + /* Notify all files deleted */ + for (l = em->files; l;) + { + Ecore_File *f; + char buf[PATH_MAX]; + + f = l->data; + l = l->next; + snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name); + em->func(em->data, em, f->type, ECORE_FILE_EVENT_DELETED, buf); + free(f->name); + free(f); + } + em->files = evas_list_free(em->files); + em->func(em->data, em, em->type, event, em->path); + em->type = ECORE_FILE_TYPE_NONE; + } + else + { + em->func(em->data, em, em->type, event, em->path); + } + } + else + { + Ecore_File *f; + + switch (event) + { + case ECORE_FILE_EVENT_NONE: + break; + case ECORE_FILE_EVENT_EXISTS: + f = _ecore_file_monitor_fam_file_find(em, fe.filename); + if (f) + { + em->func(em->data, em, f->type, event, buf); + break; + } + case ECORE_FILE_EVENT_CREATED: + f = calloc(1, sizeof(Ecore_File)); + if (!f) break; + + f->type = ecore_file_is_dir(buf) ? + ECORE_FILE_TYPE_DIRECTORY : + ECORE_FILE_TYPE_FILE; + f->name = strdup(fe.filename); + em->files = evas_list_append(em->files, f); + em->func(em->data, em, f->type, event, buf); + break; + case ECORE_FILE_EVENT_DELETED: + f = _ecore_file_monitor_fam_file_find(em, fe.filename); + if (f) + { + em->files = evas_list_remove(em->files, f); + em->func(em->data, em, f->type, event, buf); + free(f->name); + free(f); + } + break; + case ECORE_FILE_EVENT_CHANGED: + em->func(em->data, em, f->type, event, buf); + break; + } + } +#endif + } + } + return 1; +} + +static Ecore_File * +_ecore_file_monitor_fam_file_find(Ecore_File_Monitor *em, char *name) +{ + for (l = em->files; l; l = l->next) + { + Ecore_File *f; + f = l->data; + if (!strcmp(f->name, name)) + return f; + } + return NULL; +} + +static Ecore_File_Event +_ecore_file_monitor_fam_event_get(FAMCodes code, int self, int is_dir) +{ + switch (code) + { + case FAMCreated: + if (self) + return ECORE_FILE_EVENT_NONE; + else if (is_dir) + return ECORE_FILE_EVENT_CREATED_DIRECTORY; + else + return ECORE_FILE_EVENT_CREATED_FILE; + break; + case FAMDeleted: + if (self) + return ECORE_FILE_EVENT_DELETED_SELF; + else if (is_dir) + return ECORE_FILE_EVENT_DELETED_DIRECTORY; + else + return ECORE_FILE_EVENT_DELETED_FILE; + break; + case FAMChanged: + if (!is_dir) + return ECORE_FILE_EVENT_MODIFIED; + break; + case FAMExists: + case FAMStartExecuting: + case FAMStopExecuting: + case FAMMoved: + case FAMAcknowledge: + case FAMEndExist: + return ECORE_FILE_EVENT_NONE; + } + return ECORE_FILE_EVENT_NONE; +} +#endif diff --git a/ecore/src/lib/ecore_file/ecore_file_monitor_inotify.c b/ecore/src/lib/ecore_file/ecore_file_monitor_inotify.c new file mode 100644 index 0000000..1f8c34f --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_monitor_inotify.c @@ -0,0 +1,235 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_file_private.h" + +/* + * TODO: + */ + +#ifdef HAVE_INOTIFY + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <linux/inotify.h> + +typedef struct _Ecore_File_Monitor_Inotify Ecore_File_Monitor_Inotify; + +#define ECORE_FILE_MONITOR_INOTIFY(x) ((Ecore_File_Monitor_Inotify *)(x)) + +struct _Ecore_File_Monitor_Inotify +{ + Ecore_File_Monitor monitor; + int wd; +}; + +static Ecore_Fd_Handler *_fdh = NULL; +static Ecore_Oldlist *_monitors = NULL; + +static int _ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh); +static Ecore_File_Monitor *_ecore_file_monitor_inotify_monitor_find(int wd); +static void _ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, + char *file, int mask); + +int +ecore_file_monitor_inotify_init(void) +{ + int fd; + + fd = open("/dev/inotify", O_RDONLY); + if (fd < 0) + return 0; + + _fdh = ecore_main_fd_handler_add(fd, ECORE_FD_READ, _ecore_file_monitor_inotify_handler, + NULL, NULL, NULL); + if (!_fdh) + { + close(fd); + return 0; + } + + return 1; +} + +int +ecore_file_monitor_inotify_shutdown(void) +{ + int fd; + Ecore_Oldlist *l; + + for (l = _monitors; l;) + { + Ecore_File_Monitor *em; + + em = ECORE_FILE_MONITOR(l); + l = l->next; + ecore_file_monitor_inotify_del(em); + } + + if (_fdh) + { + fd = ecore_main_fd_handler_fd_get(_fdh); + ecore_main_fd_handler_del(_fdh); + close(fd); + } + return 1; +} + +Ecore_File_Monitor * +ecore_file_monitor_inotify_add(const char *path, + void (*func) (void *data, Ecore_File_Monitor *em, + Ecore_File_Event event, + const char *path), + void *data) +{ + Ecore_File_Monitor *em; + int len; + + em = calloc(1, sizeof(Ecore_File_Monitor_Inotify)); + if (!em) return NULL; + + em->func = func; + em->data = data; + + em->path = strdup(path); + len = strlen(em->path); + if (em->path[len - 1] == '/') + em->path[len - 1] = 0; + + if (ecore_file_exists(em->path)) + { + struct inotify_watch_request request; + + request.name = em->path; + request.mask = IN_MODIFY| + IN_MOVED_FROM|IN_MOVED_TO| + IN_DELETE_SUBDIR|IN_DELETE_FILE| + IN_CREATE_SUBDIR|IN_CREATE_FILE| + IN_DELETE_SELF|IN_UNMOUNT; + ECORE_FILE_MONITOR_INOTIFY(em)->wd = ioctl(ecore_main_fd_handler_fd_get(_fdh), + INOTIFY_WATCH, &request); + if (ECORE_FILE_MONITOR_INOTIFY(em)->wd < 0) + { + printf("ioctl error\n"); + ecore_file_monitor_inotify_del(em); + return NULL; + } + } + else + { + ecore_file_monitor_inotify_del(em); + return NULL; + } + + _monitors = _ecore_list_append(_monitors, em); + + return em; +} + +void +ecore_file_monitor_inotify_del(Ecore_File_Monitor *em) +{ + int fd; + + _monitors = _ecore_list_remove(_monitors, em); + + fd = ecore_main_fd_handler_fd_get(_fdh); + if (ECORE_FILE_MONITOR_INOTIFY(em)->wd) + ioctl(fd, INOTIFY_IGNORE, ECORE_FILE_MONITOR_INOTIFY(em)->wd); + free(em->path); + free(em); +} + +static int +_ecore_file_monitor_inotify_handler(void *data, Ecore_Fd_Handler *fdh) +{ + Ecore_File_Monitor *em; + char buffer[16384]; + struct inotify_event *event; + int i = 0; + int event_size; + ssize_t size; + + size = read(ecore_main_fd_handler_fd_get(fdh), buffer, sizeof(buffer)); + while (i < size) + { + event = (struct inotify_event *)&buffer[i]; + event_size = sizeof(struct inotify_event) + event->len; + i += event_size; + + em = _ecore_file_monitor_inotify_monitor_find(event->wd); + if (!em) continue; + + _ecore_file_monitor_inotify_events(em, event->name, event->mask); + } + + return 1; +} + +static Ecore_File_Monitor * +_ecore_file_monitor_inotify_monitor_find(int wd) +{ + Ecore_Oldlist *l; + + for (l = _monitors; l; l = l->next) + { + Ecore_File_Monitor *em; + + em = ECORE_FILE_MONITOR(l); + + if (ECORE_FILE_MONITOR_INOTIFY(em)->wd == wd) + return em; + } + return NULL; +} + +static void +_ecore_file_monitor_inotify_events(Ecore_File_Monitor *em, char *file, int mask) +{ + char buf[PATH_MAX]; + if (file) + snprintf(buf, sizeof(buf), "%s/%s", em->path, file); + else + strcpy(buf, em->path); + + if (mask & IN_MODIFY) + { + if (!ecore_file_is_dir(buf)) + em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf); + } + if (mask & IN_MOVED_FROM) + { + printf("MOVE_FROM "); + } + if (mask & IN_MOVED_TO) + { + printf("MOVE_TO "); + } + if (mask & IN_DELETE_SUBDIR) + { + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_DIRECTORY, buf); + } + if (mask & IN_DELETE_FILE) + { + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_FILE, buf); + } + if (mask & IN_CREATE_SUBDIR) + { + em->func(em->data, em, ECORE_FILE_EVENT_CREATED_DIRECTORY, buf); + } + if (mask & IN_CREATE_FILE) + { + em->func(em->data, em, ECORE_FILE_EVENT_CREATED_FILE, buf); + } + if (mask & IN_DELETE_SELF) + { + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path); + } + if (mask & IN_UNMOUNT) + { + printf("UNMOUNT "); + } +} +#endif diff --git a/ecore/src/lib/ecore_file/ecore_file_monitor_poll.c b/ecore/src/lib/ecore_file/ecore_file_monitor_poll.c new file mode 100644 index 0000000..420084c --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_monitor_poll.c @@ -0,0 +1,357 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_private.h" +#include "ecore_file_private.h" + +#ifdef HAVE_POLL + +/* + * TODO: + * - Implement recursive as an option! + * - Keep whole path or just name of file? (Memory or CPU...) + * - Remove requests without files? + * - Change poll time + */ + +typedef struct _Ecore_File_Monitor_Poll Ecore_File_Monitor_Poll; +typedef struct _Ecore_File Ecore_File; + +#define ECORE_FILE_MONITOR_POLL(x) ((Ecore_File_Monitor_Poll *)(x)) + +struct _Ecore_File_Monitor_Poll +{ + Ecore_File_Monitor monitor; + int mtime; + unsigned char deleted; +}; + +struct _Ecore_File +{ + Ecore_Oldlist __list_data; + char *name; + int mtime; + unsigned char is_dir; +}; + +#define ECORE_FILE_INTERVAL_MIN 1.0 +#define ECORE_FILE_INTERVAL_STEP 0.5 +#define ECORE_FILE_INTERVAL_MAX 5.0 + +static double _interval = ECORE_FILE_INTERVAL_MIN; +static Ecore_Timer *_timer = NULL; +static Ecore_Oldlist *_monitors = NULL; +static int _lock = 0; + +static int _ecore_file_monitor_poll_handler(void *data); +static void _ecore_file_monitor_poll_check(Ecore_File_Monitor *em); +static int _ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name); + +int +ecore_file_monitor_poll_init(void) +{ + return 1; +} + +int +ecore_file_monitor_poll_shutdown(void) +{ + Ecore_Oldlist *l; + + for (l = _monitors; l;) + { + Ecore_File_Monitor *em; + + em = ECORE_FILE_MONITOR(l); + l = l->next; + ecore_file_monitor_poll_del(em); + } + + if (_timer) + { + ecore_timer_del(_timer); + _timer = NULL; + } + return 1; +} + +Ecore_File_Monitor * +ecore_file_monitor_poll_add(const char *path, + void (*func) (void *data, Ecore_File_Monitor *em, + Ecore_File_Event event, + const char *path), + void *data) +{ + Ecore_File_Monitor *em; + int len; + + if (!path) return NULL; + if (!func) return NULL; + + em = calloc(1, sizeof(Ecore_File_Monitor_Poll)); + if (!em) return NULL; + + if (!_timer) + _timer = ecore_timer_add(_interval, _ecore_file_monitor_poll_handler, NULL); + else + ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN); + + em->path = strdup(path); + len = strlen(em->path); + if (em->path[len - 1] == '/') + em->path[len - 1] = 0; + + em->func = func; + em->data = data; + + ECORE_FILE_MONITOR_POLL(em)->mtime = ecore_file_mod_time(em->path); + if (ecore_file_exists(em->path)) + { + if (ecore_file_is_dir(em->path)) + { + /* Check for subdirs */ + Ecore_List *files; + char *file; + + files = ecore_file_ls(em->path); + if (files) + { + while ((file = ecore_list_next(files))) + { + Ecore_File *f; + char buf[PATH_MAX]; + + f = calloc(1, sizeof(Ecore_File)); + if (!f) + { + free(file); + continue; + } + + snprintf(buf, sizeof(buf), "%s/%s", em->path, file); + f->name = file; + f->mtime = ecore_file_mod_time(buf); + f->is_dir = ecore_file_is_dir(buf); + em->files = _ecore_list_append(em->files, f); + } + ecore_list_destroy(files); + } + } + } + else + { + ecore_file_monitor_poll_del(em); + return NULL; + } + + _monitors = _ecore_list_append(_monitors, em); + + return em; +} + +void +ecore_file_monitor_poll_del(Ecore_File_Monitor *em) +{ + Ecore_Oldlist *l; + + if (_lock) + { + ECORE_FILE_MONITOR_POLL(em)->deleted = 1; + return; + } + + /* Remove files */ + for (l = em->files; l;) + { + Ecore_File *file; + + file = (Ecore_File *)l; + l = l->next; + free(file->name); + free(file); + } + + _monitors = _ecore_list_remove(_monitors, em); + + free(em->path); + free(em); + + if ((!_monitors) && (_timer)) + { + ecore_timer_del(_timer); + _timer = NULL; + } + else + ecore_timer_interval_set(_timer, ECORE_FILE_INTERVAL_MIN); +} + +static int +_ecore_file_monitor_poll_handler(void *data __UNUSED__) +{ + Ecore_Oldlist *l; + + _interval += ECORE_FILE_INTERVAL_STEP; + + _lock = 1; + for (l = _monitors; l; l = l->next) + { + Ecore_File_Monitor *em; + + em = ECORE_FILE_MONITOR(l); + _ecore_file_monitor_poll_check(em); + } + _lock = 0; + + if (_interval > ECORE_FILE_INTERVAL_MAX) + _interval = ECORE_FILE_INTERVAL_MAX; + ecore_timer_interval_set(_timer, _interval); + + for (l = _monitors; l;) + { + Ecore_File_Monitor *em; + + em = ECORE_FILE_MONITOR(l); + l = l->next; + if (ECORE_FILE_MONITOR_POLL(em)->deleted) + ecore_file_monitor_del(em); + } + return 1; +} + +static void +_ecore_file_monitor_poll_check(Ecore_File_Monitor *em) +{ + int mtime; + int is_dir; + + mtime = ecore_file_mod_time(em->path); + is_dir = ecore_file_is_dir(em->path); + if (mtime < ECORE_FILE_MONITOR_POLL(em)->mtime) + { + Ecore_Oldlist *l; + Ecore_File_Event event; + + /* Notify all files deleted */ + for (l = em->files; l;) + { + Ecore_File *f; + char buf[PATH_MAX]; + + f = (Ecore_File *)l; + l = l->next; + + snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name); + if (f->is_dir) + event = ECORE_FILE_EVENT_DELETED_DIRECTORY; + else + event = ECORE_FILE_EVENT_DELETED_FILE; + em->func(em->data, em, event, buf); + free(f->name); + free(f); + } + em->files = NULL; + em->func(em->data, em, ECORE_FILE_EVENT_DELETED_SELF, em->path); + _interval = ECORE_FILE_INTERVAL_MIN; + } + else + { + Ecore_Oldlist *l; + + /* Check for changed files */ + for (l = em->files; l;) + { + Ecore_File *f; + char buf[PATH_MAX]; + int mtime; + Ecore_File_Event event; + + f = (Ecore_File *)l; + l = l->next; + + snprintf(buf, sizeof(buf), "%s/%s", em->path, f->name); + mtime = ecore_file_mod_time(buf); + if (mtime < f->mtime) + { + if (f->is_dir) + event = ECORE_FILE_EVENT_DELETED_DIRECTORY; + else + event = ECORE_FILE_EVENT_DELETED_FILE; + + em->func(em->data, em, event, buf); + em->files = _ecore_list_remove(em->files, f); + free(f->name); + free(f); + _interval = ECORE_FILE_INTERVAL_MIN; + } + else if ((mtime > f->mtime) && !(f->is_dir)) + { + em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, buf); + _interval = ECORE_FILE_INTERVAL_MIN; + } + f->mtime = mtime; + } + + /* Check for new files */ + if (ECORE_FILE_MONITOR_POLL(em)->mtime < mtime) + { + Ecore_List *files; + char *file; + + /* Files have been added or removed */ + files = ecore_file_ls(em->path); + while ((file = ecore_list_next(files))) + { + Ecore_File *f; + char buf[PATH_MAX]; + Ecore_File_Event event; + + if (_ecore_file_monitor_poll_checking(em, file)) + { + free(file); + continue; + } + + snprintf(buf, sizeof(buf), "%s/%s", em->path, file); + f = calloc(1, sizeof(Ecore_File)); + if (!f) + { + free(file); + continue; + } + + f->name = file; + f->mtime = ecore_file_mod_time(buf); + f->is_dir = ecore_file_is_dir(buf); + if (f->is_dir) + event = ECORE_FILE_EVENT_CREATED_DIRECTORY; + else + event = ECORE_FILE_EVENT_CREATED_FILE; + em->func(em->data, em, event, buf); + em->files = _ecore_list_append(em->files, f); + } + ecore_list_destroy(files); + if (!ecore_file_is_dir(em->path)) + em->func(em->data, em, ECORE_FILE_EVENT_MODIFIED, em->path); + _interval = ECORE_FILE_INTERVAL_MIN; + } + } + ECORE_FILE_MONITOR_POLL(em)->mtime = mtime; +} + +static int +_ecore_file_monitor_poll_checking(Ecore_File_Monitor *em, char *name) +{ + Ecore_Oldlist *l; + + for (l = em->files; l; l = l->next) + { + Ecore_File *f; + + f = (Ecore_File *)l; + if (!strcmp(f->name, name)) + return 1; + } + + return 0; +} +#endif diff --git a/ecore/src/lib/ecore_file/ecore_file_path.c b/ecore/src/lib/ecore_file/ecore_file_path.c new file mode 100644 index 0000000..d1b5d71 --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_path.c @@ -0,0 +1,84 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_file_private.h" + +Ecore_List *__ecore_file_path_bin; + +static Ecore_List *_ecore_file_path_from_env(const char *env); + +int +ecore_file_path_init(void) +{ + __ecore_file_path_bin = _ecore_file_path_from_env("PATH"); + return 1; +} + +int +ecore_file_path_shutdown(void) +{ + ecore_list_destroy(__ecore_file_path_bin); + return 1; +} + +Ecore_List * +_ecore_file_path_from_env(const char *env) +{ + Ecore_List *path; + char *env_path, *p, *last; + + path = ecore_list_new(); + + env_path = getenv(env); + if (!env_path) + return path; + + env_path = strdup(env_path); + last = env_path; + for (p = env_path; *p; p++) + { + if (*p == ':') + *p = '\0'; + + if (!*p) + { + ecore_list_append(path, strdup(last)); + last = p+1; + } + + } + if (p > last) + ecore_list_append(path, last); + + free(env_path); + return path; +} + +int +ecore_file_app_installed(const char *app) +{ + int found; + char *dir; + char buf[PATH_MAX]; + + if (!app) + return 0; + + found = 0; + + if (ecore_list_is_empty(__ecore_file_path_bin)) + return 0; + ecore_list_goto_first(__ecore_file_path_bin); + + while ((dir = ecore_list_next(__ecore_file_path_bin)) != NULL) + { + snprintf(buf, sizeof(buf), "%s/%s", dir, app); + if (ecore_file_exists(buf) && ecore_file_can_exec(buf)) + { + found = 1; + break; + } + } + + return found; +} diff --git a/ecore/src/lib/ecore_file/ecore_file_private.h b/ecore/src/lib/ecore_file/ecore_file_private.h new file mode 100644 index 0000000..b691655 --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_private.h @@ -0,0 +1,75 @@ +#define _GNU_SOURCE + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "config.h" + +#include "ecore_private.h" +#include "Ecore.h" +#include "Ecore_File.h" + +/* ecore_file_monitor */ +int ecore_file_monitor_init(void); +int ecore_file_monitor_shutdown(void); + +#define ECORE_FILE_MONITOR(x) ((Ecore_File_Monitor *)(x)) + +struct _Ecore_File_Monitor +{ + Ecore_Oldlist __list_data; + void (*func) (void *data, + Ecore_File_Monitor *ecore_file_monitor, + Ecore_File_Event event, + const char *path); + + char *path; + void *data; + Ecore_Oldlist *files; +}; + +#ifdef HAVE_INOTIFY +EAPI int ecore_file_monitor_inotify_init(void); +EAPI int ecore_file_monitor_inotify_shutdown(void); +EAPI Ecore_File_Monitor *ecore_file_monitor_inotify_add(const char *path, + void (*func) (void *data, + Ecore_File_Monitor *ecore_file_monitor, + Ecore_File_Event event, + const char *path), + void *data); +EAPI void ecore_file_monitor_inotify_del(Ecore_File_Monitor *ecore_file_monitor); +#endif + +#ifdef HAVE_FAM +EAPI int ecore_file_monitor_fam_init(void); +EAPI int ecore_file_monitor_fam_shutdown(void); +EAPI Ecore_File_Monitor *ecore_file_monitor_fam_add(const char *path, + void (*func) (void *data, + Ecore_File_Monitor *ecore_file_monitor, + Ecore_File_Event event, + const char *path), + void *data); +EAPI void ecore_file_monitor_fam_del(Ecore_File_Monitor *ecore_file_monitor); +#endif + +#ifdef HAVE_POLL +EAPI int ecore_file_monitor_poll_init(void); +EAPI int ecore_file_monitor_poll_shutdown(void); +EAPI Ecore_File_Monitor *ecore_file_monitor_poll_add(const char *path, + void (*func) (void *data, + Ecore_File_Monitor *ecore_file_monitor, + Ecore_File_Event event, + const char *path), + void *data); +EAPI void ecore_file_monitor_poll_del(Ecore_File_Monitor *ecore_file_monitor); + +/* ecore_file_path */ +int ecore_file_path_init(void); +int ecore_file_path_shutdown(void); + +/* ecore_file_download */ +int ecore_file_download_init(void); +int ecore_file_download_shutdown(void); + +#endif diff --git a/ecore/src/lib/ecore_file/ecore_file_utils.c b/ecore/src/lib/ecore_file/ecore_file_utils.c new file mode 100644 index 0000000..b3217ad --- /dev/null +++ b/ecore/src/lib/ecore_file/ecore_file_utils.c @@ -0,0 +1,4 @@ +void +_ecore_file_add_slash(char *path) +{ +} diff --git a/ecore/src/lib/ecore_ipc/.cvsignore b/ecore/src/lib/ecore_ipc/.cvsignore new file mode 100644 index 0000000..f98e6f6 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/.cvsignore @@ -0,0 +1,7 @@ +.deps +.libs +Ecore_Ipc.h +Makefile +Makefile.in +ecore_ipc.lo +libecore_ipc.la diff --git a/ecore/src/lib/ecore_ipc/CVS/Entries b/ecore/src/lib/ecore_ipc/CVS/Entries new file mode 100644 index 0000000..789fd35 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/CVS/Entries @@ -0,0 +1,6 @@ +/.cvsignore/1.2/Mon Apr 12 19:35:26 2004//THEAD +/Ecore_Ipc.h/1.11/Thu May 12 14:45:15 2005//THEAD +/Makefile.am/1.8/Thu Mar 10 15:19:40 2005//THEAD +/ecore_ipc.c/1.20/Thu May 12 14:45:15 2005//THEAD +/ecore_ipc_private.h/1.5/Sat Apr 2 15:59:55 2005//THEAD +D diff --git a/ecore/src/lib/ecore_ipc/CVS/Repository b/ecore/src/lib/ecore_ipc/CVS/Repository new file mode 100644 index 0000000..328a12d --- /dev/null +++ b/ecore/src/lib/ecore_ipc/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_ipc diff --git a/ecore/src/lib/ecore_ipc/CVS/Root b/ecore/src/lib/ecore_ipc/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_ipc/CVS/Tag b/ecore/src/lib/ecore_ipc/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_ipc/Ecore_Ipc.h b/ecore/src/lib/ecore_ipc/Ecore_Ipc.h new file mode 100644 index 0000000..36b7b70 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/Ecore_Ipc.h @@ -0,0 +1,312 @@ +#ifndef _ECORE_IPC_H +#define _ECORE_IPC_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file Ecore_Ipc.h + * @brief Ecore inter-process communication functions. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ECORE_IPC_PRIVATE_H + typedef void Ecore_Ipc_Server; /**< An IPC connection handle */ + typedef void Ecore_Ipc_Client; /**< An IPC connection handle */ +#endif + +/** + * Macros used for generic data packing + */ +EAPI unsigned short _ecore_ipc_swap_16(unsigned short v); +EAPI unsigned int _ecore_ipc_swap_32(unsigned int v); +EAPI unsigned long long _ecore_ipc_swap_64(unsigned long long v); + +#ifdef WORDS_BIGENDIAN +#define ECORE_IPC_SWAP2NET64(x) _ecore_ipc_swap_64(x) +#define ECORE_IPC_SWAP2CPU64(x) _ecore_ipc_swap_64(x) +#define ECORE_IPC_SWAP2NET32(x) _ecore_ipc_swap_32(x) +#define ECORE_IPC_SWAP2CPU32(x) _ecore_ipc_swap_32(x) +#define ECORE_IPC_SWAP2NET16(x) _ecore_ipc_swap_16(x) +#define ECORE_IPC_SWAP2CPU16(x) _ecore_ipc_swap_16(x) +#define ECORE_IPC_SWAP2NET8(x) (x) +#define ECORE_IPC_SWAP2CPU8(x) (x) +#else +#define ECORE_IPC_SWAP2NET64(x) (x) +#define ECORE_IPC_SWAP2CPU64(x) (x) +#define ECORE_IPC_SWAP2NET32(x) (x) +#define ECORE_IPC_SWAP2CPU32(x) (x) +#define ECORE_IPC_SWAP2NET16(x) (x) +#define ECORE_IPC_SWAP2CPU16(x) (x) +#define ECORE_IPC_SWAP2NET8(x) (x) +#define ECORE_IPC_SWAP2CPU8(x) (x) +#endif + +/* 1, 2, 4 and 8 byte datatypes */ +/* unpacking */ +#define ECORE_IPC_GET64(v)\ + { \ + p->v = ECORE_IPC_SWAP2CPU64(*(long long *)(ptr)); \ + ptr += 8; \ + } +#define ECORE_IPC_GET32(v)\ + { \ + p->v = ECORE_IPC_SWAP2CPU32(*(int *)(ptr)); \ + ptr += 4; \ + } +#define ECORE_IPC_GET16(v)\ + { \ + p->v = ECORE_IPC_SWAP2CPU16(*(short *)(ptr)); \ + ptr += 2; \ + } +#define ECORE_IPC_GET8(v) \ + { \ + p->v = ECORE_IPC_SWAP2CPU8(*(char *)(ptr)); \ + ptr += 1; \ + } +/* packing */ +#define ECORE_IPC_PUT64(v)\ + { \ + *(long long *)(ptr) = ECORE_IPC_SWAP2NET64(p->v); \ + ptr += 8; \ + } +#define ECORE_IPC_PUT32(v)\ + { \ + *(int *)(ptr) = ECORE_IPC_SWAP2NET32(p->v); \ + ptr += 4; \ + } +#define ECORE_IPC_PUT16(v)\ + { \ + *(short *)(ptr) = ECORE_IPC_SWAP2NET16(p->v); \ + ptr += 2; \ + } +#define ECORE_IPC_PUT8(v) \ + { \ + *(char *)(ptr) = ECORE_IPC_SWAP2NET8(p->v); \ + ptr += 1; \ + } +/* padding data */ +#define ECORE_IPC_PAD8() ptr += 1 +#define ECORE_IPC_PAD16() ptr += 2 +#define ECORE_IPC_PAD32() ptr += 4 +#define ECORE_IPC_PAD64() ptr += 8 + +/* counting data when encoding lists */ +#define ECORE_IPC_CNT8() len += 1 +#define ECORE_IPC_CNT16() len += 2 +#define ECORE_IPC_CNT32() len += 4 +#define ECORE_IPC_CNT64() len += 8 + +/* strings */ +#define ECORE_IPC_CHEKS() if (*((unsigned char *)d + s - 1) != 0) return 0; +#define ECORE_IPC_GETS(v) \ + { \ + if (ptr < ((unsigned char *)d + s)) \ + { \ + p->v = (char *)ptr; \ + ptr += strlen(p->v) + 1; \ + } \ + } +#define ECORE_IPC_PUTS(v, l)\ + { \ + strcpy((char *)ptr, p->v); \ + ptr += l + 1; \ + } + +/* handy to calculate what sized block we need to alloc */ +#define ECORE_IPC_SLEN(l, v) ((l = strlen(p->v)) + 1) +#define ECORE_IPC_CNTS(v) len += strlen(p->v) + 1 + +/* saves typing function headers */ +#define ECORE_IPC_DEC_STRUCT_PROTO(x) static int x(void *d, int s, void *pp) +#define ECORE_IPC_ENC_STRUCT_PROTO(x) static void *x(void *pp, int *s) +#define ECORE_IPC_DEC_EVAS_LIST_PROTO(x) static Evas_List *x(void *d, int s) +#define ECORE_IPC_ENC_EVAS_LIST_PROTO(x) static void *x(Evas_List *lp, int *s) + + +/* decoder setup - saves typing. requires data packet of exact size, or fail */ +#define ECORE_IPC_DEC_STRUCT_HEAD_EXACT(typ, x) \ + typ *p; \ + unsigned char *ptr; \ + p = (typ *)pp; \ + if (!d) return 0; if (s != (x)) return 0; \ + ptr = d; +/* decoder setup - saves typing. requires data packet of a minimum size */ +#define ECORE_IPC_DEC_STRUCT_HEAD_MIN(typ, x) \ + typ *p; \ + unsigned char *ptr; \ + p = (typ *)pp; \ + if (!d) return 0; if (s < (x)) return 0; \ + ptr = d; +/* footer for the hell of it */ +#define ECORE_IPC_DEC_STRUCT_FOOT() return 1 +/* header for encoder - gives native strct type and size of flattened packet */ +#define ECORE_IPC_ENC_STRUCT_HEAD(typ, sz) \ + typ *p; \ + unsigned char *d, *ptr; \ + int len; \ + *s = 0; \ + if(!pp) return NULL; \ + p = (typ *)pp; \ + len = sz; \ + d = malloc(len); \ + if (!d) return NULL; \ + *s = len; \ + ptr = d; +/* footer for the hell of it */ +#define ECORE_IPC_ENC_STRUCT_FOOT() return d + +#define ECORE_IPC_DEC_EVAS_LIST_HEAD(typ) \ + unsigned char *ptr; \ + Evas_List *l; \ + typ *p; \ + l = NULL; \ + ptr = d; \ + while(ptr < (unsigned char *)(d + s)) \ + { \ + p = malloc(sizeof(typ)); + +#define ECORE_IPC_DEC_EVAS_LIST_FOOT() \ + l = evas_list_append(l, p); \ + } \ + return l +#define ECORE_IPC_ENC_EVAS_LIST_HEAD_START(typ) \ + Evas_List *l; \ + typ *p; \ + unsigned char *d, *ptr; \ + int len; \ + *s = 0; \ + len = 0; \ + for (l = lp; l; l = l->next) \ + { \ + p = l->data; +#define ECORE_IPC_ENC_EVAS_LIST_HEAD_FINISH() \ + } \ + d = malloc(len); \ + if(!d) return NULL; \ + *s = len; \ + ptr = d; \ + for (l = lp; l; l = l->next) \ + { \ + p = l->data; + +#define ECORE_IPC_ENC_EVAS_LIST_FOOT() \ + } \ + return d + + typedef enum _Ecore_Ipc_Type + { + ECORE_IPC_LOCAL_USER, + ECORE_IPC_LOCAL_SYSTEM, + ECORE_IPC_REMOTE_SYSTEM, + ECORE_IPC_USE_SSL = 16 + } Ecore_Ipc_Type; + + typedef struct _Ecore_Ipc_Event_Client_Add Ecore_Ipc_Event_Client_Add; + typedef struct _Ecore_Ipc_Event_Client_Del Ecore_Ipc_Event_Client_Del; + typedef struct _Ecore_Ipc_Event_Server_Add Ecore_Ipc_Event_Server_Add; + typedef struct _Ecore_Ipc_Event_Server_Del Ecore_Ipc_Event_Server_Del; + typedef struct _Ecore_Ipc_Event_Client_Data Ecore_Ipc_Event_Client_Data; + typedef struct _Ecore_Ipc_Event_Server_Data Ecore_Ipc_Event_Server_Data; + + struct _Ecore_Ipc_Event_Client_Add + { + Ecore_Ipc_Client *client; + }; + + struct _Ecore_Ipc_Event_Client_Del + { + Ecore_Ipc_Client *client; + }; + + struct _Ecore_Ipc_Event_Server_Add + { + Ecore_Ipc_Server *server; + }; + + struct _Ecore_Ipc_Event_Server_Del + { + Ecore_Ipc_Server *server; + }; + + struct _Ecore_Ipc_Event_Client_Data + { + Ecore_Ipc_Client *client; + /* FIXME: this needs to become an ipc message */ + int major; + int minor; + int ref; + int ref_to; + int response; + void *data; + int size; + }; + + struct _Ecore_Ipc_Event_Server_Data + { + Ecore_Ipc_Server *server; + /* FIXME: this needs to become an ipc message */ + int major; + int minor; + int ref; + int ref_to; + int response; + void *data; + int size; + }; + + extern int ECORE_IPC_EVENT_CLIENT_ADD; + extern int ECORE_IPC_EVENT_CLIENT_DEL; + extern int ECORE_IPC_EVENT_SERVER_ADD; + extern int ECORE_IPC_EVENT_SERVER_DEL; + extern int ECORE_IPC_EVENT_CLIENT_DATA; + extern int ECORE_IPC_EVENT_SERVER_DATA; + + EAPI int ecore_ipc_init(void); + EAPI int ecore_ipc_shutdown(void); + + /* FIXME: need to add protocol type parameter */ + EAPI Ecore_Ipc_Server *ecore_ipc_server_add(Ecore_Ipc_Type type, const char *name, int port, const void *data); + + /* FIXME: need to add protocol type parameter */ + EAPI Ecore_Ipc_Server *ecore_ipc_server_connect(Ecore_Ipc_Type type, char *name, int port, const void *data); + EAPI void *ecore_ipc_server_del(Ecore_Ipc_Server *svr); + EAPI void *ecore_ipc_server_data_get(Ecore_Ipc_Server *svr); + EAPI int ecore_ipc_server_connected_get(Ecore_Ipc_Server *svr); + /* FIXME: this needs to become an ipc message */ + EAPI int ecore_ipc_server_send(Ecore_Ipc_Server *svr, int major, int minor, int ref, int ref_to, int response, void *data, int size); + EAPI void ecore_ipc_server_client_limit_set(Ecore_Ipc_Server *svr, int client_limit, char reject_excess_clients); + + /* FIXME: this needs to become an ipc message */ + EAPI int ecore_ipc_client_send(Ecore_Ipc_Client *cl, int major, int minor, int ref, int ref_to, int response, void *data, int size); + EAPI Ecore_Ipc_Server *ecore_ipc_client_server_get(Ecore_Ipc_Client *cl); + EAPI void *ecore_ipc_client_del(Ecore_Ipc_Client *cl); + EAPI void ecore_ipc_client_data_set(Ecore_Ipc_Client *cl, const void *data); + EAPI void *ecore_ipc_client_data_get(Ecore_Ipc_Client *cl); + + EAPI int ecore_ipc_ssl_available_get(void); + /* FIXME: need to add a callback to "ok" large ipc messages greater than */ + /* a certain size (seurity/DOS attack safety) */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_ipc/Makefile.am b/ecore/src/lib/ecore_ipc/Makefile.am new file mode 100644 index 0000000..48d8746 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/Makefile.am @@ -0,0 +1,39 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_con \ +-I$(top_builddir)/src/lib/ecore_ipc \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_con \ +-I$(top_srcdir)/src/lib/ecore_ipc \ +@SSL_CFLAGS@ + +libecore_ipc_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs \ +-L$(top_builddir)/src/lib/ecore_con/.libs + +if BUILD_ECORE_IPC + +lib_LTLIBRARIES = libecore_ipc.la +include_HEADERS = \ +Ecore_Ipc.h + +libecore_ipc_la_SOURCES = \ +ecore_ipc.c \ +ecore_ipc_private.h + +libecore_ipc_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_con/libecore_con.la \ +@SSL_LIBS@ @winsock_libs@ + +libecore_ipc_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_con/libecore_con.la + +endif + +EXTRA_DIST = \ +ecore_ipc.c \ +ecore_ipc_private.h diff --git a/ecore/src/lib/ecore_ipc/ecore_ipc.c b/ecore/src/lib/ecore_ipc/ecore_ipc.c new file mode 100644 index 0000000..cbe2c03 --- /dev/null +++ b/ecore/src/lib/ecore_ipc/ecore_ipc.c @@ -0,0 +1,1257 @@ +#include "Ecore.h" +#include "config.h" +#include "Ecore_Con.h" +#include "ecore_private.h" +#include "ecore_ipc_private.h" +#include "Ecore_Ipc.h" + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#elif WIN32 +#include <winsock.h> +#endif + +#define DLT_ZERO 0 +#define DLT_ONE 1 +#define DLT_SAME 2 +#define DLT_SHL 3 +#define DLT_SHR 4 +#define DLT_ADD8 5 +#define DLT_DEL8 6 +#define DLT_ADDU8 7 +#define DLT_DELU8 8 +#define DLT_ADD16 9 +#define DLT_DEL16 10 +#define DLT_ADDU16 11 +#define DLT_DELU16 12 +#define DLT_SET 13 +#define DLT_R1 14 +#define DLT_R2 15 + +/* byte swappers - for dealing with big vs little endian machines */ +unsigned short +_ecore_ipc_swap_16(unsigned short v) +{ + unsigned char *s, t; + + s = (unsigned char *)(&v); + t = s[0]; s[0] = s[1]; s[1] = t; + return v; +} + +unsigned int +_ecore_ipc_swap_32(unsigned int v) +{ + unsigned char *s, t; + + s = (unsigned char *)(&v); + t = s[0]; s[0] = s[3]; s[3] = t; + t = s[1]; s[1] = s[2]; s[2] = t; + return v; +} + +unsigned long long +_ecore_ipc_swap_64(unsigned long long v) +{ + unsigned char *s, t; + + s = (unsigned char *)(&v); + t = s[0]; s[0] = s[7]; s[7] = t; + t = s[1]; s[1] = s[6]; s[6] = t; + t = s[2]; s[2] = s[5]; s[5] = t; + t = s[3]; s[3] = s[4]; s[4] = t; + return v; +} + +static int _ecore_ipc_dlt_int(int out, int prev, int *mode); +static int _ecore_ipc_ddlt_int(int in, int prev, int mode); + +static int +_ecore_ipc_dlt_int(int out, int prev, int *mode) +{ + int dlt; + + /* 0 byte */ + if (out == 0) + { + *mode = DLT_ZERO; + return 0; + } + if (out == (int)0xffffffff) + { + *mode = DLT_ONE; + return 0; + } + if (out == prev) + { + *mode = DLT_SAME; + return 0; + } + if (out == prev << 1) + { + *mode = DLT_SHL; + return 0; + } + if (out == prev >> 1) + { + *mode = DLT_SHR; + return 0; + } + /* 1 byte */ + dlt = out - prev; + if (!(dlt & 0xffffff00)) + { + *mode = DLT_ADD8; + return dlt & 0xff; + } + dlt = prev - out; + if (!(dlt & 0xffffff00)) + { + *mode = DLT_DEL8; + return dlt & 0xff; + } + dlt = out - prev; + if (!(dlt & 0x00ffffff)) + { + *mode = DLT_ADDU8; + return (dlt >> 24) & 0xff; + } + dlt = prev - out; + if (!(dlt & 0x00ffffff)) + { + *mode = DLT_DELU8; + return (dlt >> 24) & 0xff; + } + /* 2 byte */ + dlt = out - prev; + if (!(dlt & 0xffff0000)) + { + *mode = DLT_ADD16; + return dlt & 0xfffff; + } + dlt = prev - out; + if (!(dlt & 0xffff0000)) + { + *mode = DLT_DEL16; + return dlt & 0xffff; + } + dlt = out - prev; + if (!(dlt & 0x0000ffff)) + { + *mode = DLT_ADDU16; + return (dlt >> 16) & 0xffff; + } + dlt = prev - out; + if (!(dlt & 0x0000ffff)) + { + *mode = DLT_DELU16; + return (dlt >> 16) & 0xffff; + } + /* 4 byte */ + *mode = DLT_SET; + return out; +} + +static int +_ecore_ipc_ddlt_int(int in, int prev, int mode) +{ + switch (mode) + { + case DLT_ZERO: + return 0; + break; + case DLT_ONE: + return 0xffffffff; + break; + case DLT_SAME: + return prev; + break; + case DLT_SHL: + return prev << 1; + break; + case DLT_SHR: + return prev >> 1; + break; + case DLT_ADD8: + return prev + in; + break; + case DLT_DEL8: + return prev - in; + break; + case DLT_ADDU8: + return prev + (in << 24); + break; + case DLT_DELU8: + return prev - (in << 24); + break; + case DLT_ADD16: + return prev + in; + break; + case DLT_DEL16: + return prev - in; + break; + case DLT_ADDU16: + return prev + (in << 16); + break; + case DLT_DELU16: + return prev - (in << 16); + break; + case DLT_SET: + return in; + break; + case DLT_R1: + return 0; + break; + case DLT_R2: + return 0; + break; + default: + break; + } + return 0; +} + +static int _ecore_ipc_event_client_add(void *data, int ev_type, void *ev); +static int _ecore_ipc_event_client_del(void *data, int ev_type, void *ev); +static int _ecore_ipc_event_server_add(void *data, int ev_type, void *ev); +static int _ecore_ipc_event_server_del(void *data, int ev_type, void *ev); +static int _ecore_ipc_event_client_data(void *data, int ev_type, void *ev); +static int _ecore_ipc_event_server_data(void *data, int ev_type, void *ev); +static void _ecore_ipc_event_client_data_free(void *data, void *ev); +static void _ecore_ipc_event_server_data_free(void *data, void *ev); + +int ECORE_IPC_EVENT_CLIENT_ADD = 0; +int ECORE_IPC_EVENT_CLIENT_DEL = 0; +int ECORE_IPC_EVENT_SERVER_ADD = 0; +int ECORE_IPC_EVENT_SERVER_DEL = 0; +int ECORE_IPC_EVENT_CLIENT_DATA = 0; +int ECORE_IPC_EVENT_SERVER_DATA = 0; + +static int init_count = 0; +static Ecore_Ipc_Server *servers = NULL; + +/** + * @defgroup Ecore_IPC_Library_Group IPC Library Functions + * + * Functions that set up and shut down the Ecore IPC Library. + */ + +/** + * Initialises the Ecore IPC library. + * @return Number of times the library has been initialised without + * being shut down. + * @ingroup Ecore_IPC_Library_Group + */ +int +ecore_ipc_init(void) +{ + if (!init_count) ecore_con_init(); + init_count++; + if (!ECORE_IPC_EVENT_CLIENT_ADD) + { + ECORE_IPC_EVENT_CLIENT_ADD = ecore_event_type_new(); + ECORE_IPC_EVENT_CLIENT_DEL = ecore_event_type_new(); + ECORE_IPC_EVENT_SERVER_ADD = ecore_event_type_new(); + ECORE_IPC_EVENT_SERVER_DEL = ecore_event_type_new(); + ECORE_IPC_EVENT_CLIENT_DATA = ecore_event_type_new(); + ECORE_IPC_EVENT_SERVER_DATA = ecore_event_type_new(); + + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, _ecore_ipc_event_client_add, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, _ecore_ipc_event_client_del, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, _ecore_ipc_event_server_add, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, _ecore_ipc_event_server_del, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, _ecore_ipc_event_client_data, NULL); + ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, _ecore_ipc_event_server_data, NULL); + } + return init_count; +} + +/** + * Shuts down the Ecore IPC library. + * @return Number of times the library has been initialised without being + * shut down. + * @ingroup Ecore_IPC_Library_Group + */ +int +ecore_ipc_shutdown(void) +{ + if (init_count > 0) + { + init_count--; + if (init_count > 0) return init_count; + while (servers) ecore_ipc_server_del(servers); + ecore_con_shutdown(); + } + return 0; +} + +/** + * @defgroup Ecore_IPC_Server_Group IPC Server Functions + * + * Functions the deal with IPC server objects. + */ + +/** + * Creates an IPC server that listens for connections. + * + * For more details about the @p compl_type, @p name and @p port + * parameters, see the @ref ecore_con_server_add documentation. + * + * @param compl_type The connection type. + * @param name Name to associate with the socket used for connection. + * @param port Number to identify with socket used for connection. + * @param data Data to associate with the IPC server. + * @return New IPC server. If there is an error, @c NULL is returned. + * @ingroup Ecore_IPC_Server_Group + * @todo Need to add protocol type parameter to this function. + */ +Ecore_Ipc_Server * +ecore_ipc_server_add(Ecore_Ipc_Type compl_type, const char *name, int port, const void *data) +{ + Ecore_Ipc_Server *svr; + Ecore_Ipc_Type type; + Ecore_Con_Type extra = 0; + + svr = calloc(1, sizeof(Ecore_Ipc_Server)); + if (!svr) return NULL; + type = compl_type; + type &= ~ECORE_IPC_USE_SSL; + if (compl_type & ECORE_IPC_USE_SSL) extra = ECORE_CON_USE_SSL; + switch (type) + { + case ECORE_IPC_LOCAL_USER: + svr->server = ecore_con_server_add(ECORE_CON_LOCAL_USER | extra, name, port, svr); + break; + case ECORE_IPC_LOCAL_SYSTEM: + svr->server = ecore_con_server_add(ECORE_CON_LOCAL_SYSTEM | extra, name, port, svr); + break; + case ECORE_IPC_REMOTE_SYSTEM: + svr->server = ecore_con_server_add(ECORE_CON_REMOTE_SYSTEM | extra, name, port, svr); + break; + default: + free(svr); + return NULL; + } + if (!svr->server) + { + free(svr); + return NULL; + } + svr->data = (void *)data; + servers = _ecore_list_append(servers, svr); + ECORE_MAGIC_SET(svr, ECORE_MAGIC_IPC_SERVER); + return svr; +} + +/** + * Creates an IPC server object to represent the IPC server listening + * on the given port. + * + * For more details about the @p compl_type, @p name and @p port + * parameters, see the @ref ecore_con_server_connect documentation. + * + * @param compl_type The IPC connection type. + * @param name Name used to determine which socket to use for the + * IPC connection. + * @param port Number used to identify the socket to use for the + * IPC connection. + * @param data Data to associate with the server. + * @return A new IPC server. @c NULL is returned on error. + * @ingroup Ecore_IPC_Server_Group + * @todo Need to add protocol type parameter. + */ +Ecore_Ipc_Server * +ecore_ipc_server_connect(Ecore_Ipc_Type compl_type, char *name, int port, const void *data) +{ + Ecore_Ipc_Server *svr; + Ecore_Ipc_Type type; + Ecore_Con_Type extra = 0; + + svr = calloc(1, sizeof(Ecore_Ipc_Server)); + if (!svr) return NULL; + type = compl_type; + type &= ~ECORE_IPC_USE_SSL; + if (compl_type & ECORE_IPC_USE_SSL) extra = ECORE_CON_USE_SSL; + switch (type) + { + case ECORE_IPC_LOCAL_USER: + svr->server = ecore_con_server_connect(ECORE_CON_LOCAL_USER | extra, name, port, svr); + break; + case ECORE_IPC_LOCAL_SYSTEM: + svr->server = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM | extra, name, port, svr); + break; + case ECORE_IPC_REMOTE_SYSTEM: + svr->server = ecore_con_server_connect(ECORE_CON_REMOTE_SYSTEM | extra, name, port, svr); + break; + default: + free(svr); + return NULL; + } + if (!svr->server) + { + free(svr); + return NULL; + } + svr->data = (void *)data; + servers = _ecore_list_append(servers, svr); + ECORE_MAGIC_SET(svr, ECORE_MAGIC_IPC_SERVER); + return svr; +} + +/** + * Closes the connection and frees the given IPC server. + * @param svr The given IPC server. + * @return The data associated with the server when it was created. + * @ingroup Ecore_IPC_Server_Group + */ +void * +ecore_ipc_server_del(Ecore_Ipc_Server *svr) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER, + "ecore_ipc_server_del"); + return NULL; + } + ECORE_MAGIC_SET(svr, ECORE_MAGIC_NONE); + data = svr->data; + while (svr->clients) ecore_ipc_client_del((Ecore_Ipc_Client *)svr->clients); + ecore_con_server_del(svr->server); + servers = _ecore_list_remove(servers, svr); + if (svr->buf) free(svr->buf); + free(svr); + return data; +} + +/** + * Retrieves the data associated with the given IPC server. + * @param svr The given IPC server. + * @return The associated data. + * @ingroup Ecore_IPC_Server_Group + */ +void * +ecore_ipc_server_data_get(Ecore_Ipc_Server *svr) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER, + "ecore_ipc_server_data_get"); + return NULL; + } + return svr->data; +} + +/** + * Retrieves whether the given IPC server is currently connected. + * @param svr The given IPC server. + * @return @c 1 if the server is connected. @c 0 otherwise. + * @ingroup Ecore_IPC_Server_Group + */ +int +ecore_ipc_server_connected_get(Ecore_Ipc_Server *svr) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER, + "ecore_ipc_server_connected_get"); + return 0; + } + return ecore_con_server_connected_get(svr->server); +} + +#define SVENC(_member) \ + d = _ecore_ipc_dlt_int(msg._member, svr->prev.o._member, &md); \ + if (md >= DLT_SET) \ + { \ + unsigned int v; \ + unsigned char *dd; \ + dd = (unsigned char *)&v; \ + v = d; \ + v = htonl(v); \ + *(dat + s + 0) = dd[0]; \ + *(dat + s + 1) = dd[1]; \ + *(dat + s + 2) = dd[2]; \ + *(dat + s + 3) = dd[3]; \ + s += 4; \ + } \ + else if (md >= DLT_ADD16) \ + { \ + unsigned short v; \ + unsigned char *dd; \ + dd = (unsigned char *)&v; \ + v = d; \ + v = htons(v); \ + *(dat + s + 0) = dd[0]; \ + *(dat + s + 1) = dd[1]; \ + s += 2; \ + } \ + else if (md >= DLT_ADD8) \ + { \ + *(dat + s + 0) = (unsigned char)d; \ + s += 1; \ + } + +/** + * Sends a message to the given IPC server. + * + * The content of the parameters, excluding the @p svr paramter, is up to + * the client. + * + * @param svr The given IPC server. + * @param major Major opcode of the message. + * @param minor Minor opcode of the message. + * @param ref Message reference number. + * @param ref_to Reference number of the message this message refers to. + * @param response Requires response. + * @param data The data to send as part of the message. + * @param size Length of the data, in bytes, to send. + * @return Number of bytes sent. @c 0 is returned if there is an error. + * @ingroup Ecore_IPC_Server_Group + * @todo This function needs to become an IPC message. + * @todo Fix up the documentation: Make sure what ref_to and response are. + */ +int +ecore_ipc_server_send(Ecore_Ipc_Server *svr, int major, int minor, int ref, int ref_to, int response, void *data, int size) +{ + Ecore_Ipc_Msg_Head msg; + int ret; + int *head, md = 0, d, s; + unsigned char dat[sizeof(Ecore_Ipc_Msg_Head)]; + + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER, + "ecore_ipc_server_send"); + return 0; + } + if (size < 0) size = 0; + msg.major = major; + msg.minor = minor; + msg.ref = ref; + msg.ref_to = ref_to; + msg.response = response; + msg.size = size; + head = (int *)dat; + s = 4; + SVENC(major); + *head = md; + SVENC(minor); + *head |= md << (4 * 1); + SVENC(ref); + *head |= md << (4 * 2); + SVENC(ref_to); + *head |= md << (4 * 3); + SVENC(response); + *head |= md << (4 * 4); + SVENC(size); + *head |= md << (4 * 5); + *head = htonl(*head); + svr->prev.o = msg; + ret = ecore_con_server_send(svr->server, dat, s); + if (size > 0) ret += ecore_con_server_send(svr->server, data, size); + return ret; +} + +/** + * Sets a limit on the number of clients that can be handled concurrently + * by the given server, and a policy on what to do if excess clients try to + * connect. + * Beware that if you set this once ecore is already running, you may + * already have pending CLIENT_ADD events in your event queue. Those + * clients have already connected and will not be affected by this call. + * Only clients subsequently trying to connect will be affected. + * @param svr The given server. + * @param client_limit The maximum number of clients to handle + * concurrently. -1 means unlimited (default). 0 + * effectively disables the server. + * @param reject_excess_clients Set to 1 to automatically disconnect + * excess clients as soon as they connect if you are + * already handling client_limit clients. Set to 0 + * (default) to just hold off on the "accept()" + * system call until the number of active clients + * drops. This causes the kernel to queue up to 4096 + * connections (or your kernel's limit, whichever is + * lower). + * @ingroup Ecore_Ipc_Server_Group + */ +void +ecore_ipc_server_client_limit_set(Ecore_Ipc_Server *svr, int client_limit, char reject_excess_clients) +{ + if (!ECORE_MAGIC_CHECK(svr, ECORE_MAGIC_IPC_SERVER)) + { + ECORE_MAGIC_FAIL(svr, ECORE_MAGIC_IPC_SERVER, + "ecore_ipc_server_client_limit_set"); + return; + } + ecore_con_server_client_limit_set(svr->server, client_limit, reject_excess_clients); +} + +#define CLENC(_member) \ + d = _ecore_ipc_dlt_int(msg._member, cl->prev.o._member, &md); \ + if (md >= DLT_SET) \ + { \ + unsigned int v; \ + unsigned char *dd; \ + dd = (unsigned char *)&v; \ + v = d; \ + v = htonl(v); \ + *(dat + s + 0) = dd[0]; \ + *(dat + s + 1) = dd[1]; \ + *(dat + s + 2) = dd[2]; \ + *(dat + s + 3) = dd[3]; \ + s += 4; \ + } \ + else if (md >= DLT_ADD16) \ + { \ + unsigned short v; \ + unsigned char *dd; \ + dd = (unsigned char *)&v; \ + v = d; \ + v = htons(v); \ + *(dat + s + 0) = dd[0]; \ + *(dat + s + 1) = dd[1]; \ + s += 2; \ + } \ + else if (md >= DLT_ADD8) \ + { \ + *(dat + s) = (unsigned char)d; \ + s += 1; \ + } + +/** + * @defgroup Ecore_IPC_Client_Group IPC Client Functions + * + * Functions that deal with IPC client objects. + */ + +/** + * Sends a message to the given IPC client. + * @param cl The given IPC client. + * @param major Major opcode of the message. + * @param minor Minor opcode of the message. + * @param ref Reference number of the message. + * @param ref_to Reference number of the message this message refers to. + * @param response Requires response. + * @param data The data to send as part of the message. + * @param size Length of the data, in bytes, to send. + * @return The number of bytes sent. @c 0 will be returned if there is + * an error. + * @ingroup Ecore_IPC_Client_Group + * @todo This function needs to become an IPC message. + * @todo Make sure ref_to and response parameters are described correctly. + */ +int +ecore_ipc_client_send(Ecore_Ipc_Client *cl, int major, int minor, int ref, int ref_to, int response, void *data, int size) +{ + Ecore_Ipc_Msg_Head msg; + int ret; + int *head, md = 0, d, s; + unsigned char dat[sizeof(Ecore_Ipc_Msg_Head)]; + + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT, + "ecore_ipc_client_send"); + return 0; + } + if (size < 0) size = 0; + msg.major = major; + msg.minor = minor; + msg.ref = ref; + msg.ref_to = ref_to; + msg.response = response; + msg.size = size; + head = (int *)dat; + s = 4; + CLENC(major); + *head = md; + CLENC(minor); + *head |= md << (4 * 1); + CLENC(ref); + *head |= md << (4 * 2); + CLENC(ref_to); + *head |= md << (4 * 3); + CLENC(response); + *head |= md << (4 * 4); + CLENC(size); + *head |= md << (4 * 5); + *head = htonl(*head); + cl->prev.o = msg; + ret = ecore_con_client_send(cl->client, dat, s); + if (size > 0) ret += ecore_con_client_send(cl->client, data, size); + return ret; +} + +/** + * Retrieves the IPC server that the given IPC client is connected to. + * @param cl The given IPC client. + * @return The IPC server the IPC client is connected to. + * @ingroup Ecore_IPC_Client_Group + */ +Ecore_Ipc_Server * +ecore_ipc_client_server_get(Ecore_Ipc_Client *cl) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT, + "ecore_ipc_client_server_get"); + return NULL; + } + return (ecore_con_server_data_get(ecore_con_client_server_get(cl->client))); +} + +/** + * Closes the connection and frees memory allocated to the given IPC + * client. + * @param cl The given client. + * @return Data associated with the client. + * @ingroup Ecore_IPC_Client_Group + */ +void * +ecore_ipc_client_del(Ecore_Ipc_Client *cl) +{ + void *data; + Ecore_Ipc_Server *svr; + + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT, + "ecore_ipc_client_del"); + return NULL; + } + ECORE_MAGIC_SET(cl, ECORE_MAGIC_NONE); + data = cl->data; + svr = ecore_con_server_data_get(ecore_con_client_server_get(cl->client)); + ecore_con_client_del(cl->client); + svr->clients = _ecore_list_remove(svr->clients, cl); + if (cl->buf) free(cl->buf); + free(cl); + return data; +} + +/** + * Sets the IPC data associated with the given IPC client to @p data. + * @param cl The given IPC client. + * @param data The data to associate with the IPC client. + * @ingroup Ecore_IPC_Client_Group + */ +void +ecore_ipc_client_data_set(Ecore_Ipc_Client *cl, const void *data) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT, + "ecore_ipc_client_data_set"); + return; + } + cl->data = (void *)data; +} + +/** + * Retrieves the data that has been associated with the given IPC client. + * @param cl The given client. + * @return The data associated with the IPC client. + * @ingroup Ecore_IPC_Client_Group + */ +void * +ecore_ipc_client_data_get(Ecore_Ipc_Client *cl) +{ + if (!ECORE_MAGIC_CHECK(cl, ECORE_MAGIC_IPC_CLIENT)) + { + ECORE_MAGIC_FAIL(cl, ECORE_MAGIC_IPC_CLIENT, + "ecore_ipc_client_data_get"); + return NULL; + } + return cl->data; +} + +/** + * Returns if SSL support is available + * @return 1 if SSL is available, 0 if it is not. + * @ingroup Ecore_Con_Client_Group + */ +int +ecore_ipc_ssl_available_get(void) +{ + return ecore_con_ssl_available_get(); +} + + +static int +_ecore_ipc_event_client_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev) +{ + Ecore_Con_Event_Client_Add *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1; + /* handling code here */ + { + Ecore_Ipc_Client *cl; + Ecore_Ipc_Server *svr; + + cl = calloc(1, sizeof(Ecore_Ipc_Client)); + if (!cl) return 0; + svr = ecore_con_server_data_get(ecore_con_client_server_get(e->client)); + ECORE_MAGIC_SET(cl, ECORE_MAGIC_IPC_CLIENT); + cl->client = e->client; + ecore_con_client_data_set(cl->client, (void *)cl); + svr->clients = _ecore_list_append(svr->clients, cl); + { + Ecore_Ipc_Event_Client_Add *e2; + + e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Add)); + if (e2) + { + e2->client = cl; + ecore_event_add(ECORE_IPC_EVENT_CLIENT_ADD, e2, NULL, NULL); + } + } + } + return 0; +} + +static int +_ecore_ipc_event_client_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev) +{ + Ecore_Con_Event_Client_Del *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1; + /* handling code here */ + { + Ecore_Ipc_Client *cl; + + cl = ecore_con_client_data_get(e->client); + { + Ecore_Ipc_Event_Client_Del *e2; + + e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Del)); + if (e2) + { + e2->client = cl; + ecore_event_add(ECORE_IPC_EVENT_CLIENT_DEL, e2, NULL, NULL); + } + } + } + return 0; +} + +static int +_ecore_ipc_event_server_add(void *data __UNUSED__, int ev_type __UNUSED__, void *ev) +{ + Ecore_Con_Event_Server_Add *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(e->server))) return 1; + /* handling code here */ + { + Ecore_Ipc_Server *svr; + + svr = ecore_con_server_data_get(e->server); + { + Ecore_Ipc_Event_Server_Add *e2; + + e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Add)); + if (e2) + { + e2->server = svr; + ecore_event_add(ECORE_IPC_EVENT_SERVER_ADD, e2, NULL, NULL); + } + } + } + return 0; +} + +static int +_ecore_ipc_event_server_del(void *data __UNUSED__, int ev_type __UNUSED__, void *ev) +{ + Ecore_Con_Event_Server_Del *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(e->server))) return 1; + /* handling code here */ + { + Ecore_Ipc_Server *svr; + + svr = ecore_con_server_data_get(e->server); + { + Ecore_Ipc_Event_Server_Del *e2; + + e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Del)); + if (e2) + { + e2->server = svr; + ecore_event_add(ECORE_IPC_EVENT_SERVER_DEL, e2, NULL, NULL); + } + } + } + return 0; +} + +#define CLSZ(_n) \ + md = ((head >> (4 * _n)) & 0xf); \ + if (md >= DLT_SET) s += 4; \ + else if (md >= DLT_ADD16) s += 2; \ + else if (md >= DLT_ADD8) s += 1; + +#define CLDEC(_n, _member) \ + md = ((head >> (4 * _n)) & 0xf); \ + if (md >= DLT_SET) \ + { \ + unsigned int v; \ + unsigned char *dv; \ + dv = (unsigned char *)&v; \ + dv[0] = *(cl->buf + offset + s + 0); \ + dv[1] = *(cl->buf + offset + s + 1); \ + dv[2] = *(cl->buf + offset + s + 2); \ + dv[3] = *(cl->buf + offset + s + 3); \ + d = (int)ntohl(d); \ + s += 4; \ + } \ + else if (md >= DLT_ADD16) \ + { \ + unsigned short v; \ + unsigned char *dv; \ + dv = (unsigned char *)&v; \ + dv[0] = *(cl->buf + offset + s + 0); \ + dv[1] = *(cl->buf + offset + s + 1); \ + d = (int)ntohs(v); \ + s += 2; \ + } \ + else if (md >= DLT_ADD8) \ + { \ + unsigned char v; \ + unsigned char *dv; \ + dv = (unsigned char *)&v; \ + dv[0] = *(cl->buf + offset + s + 0); \ + d = (int)v; \ + s += 1; \ + } \ + msg._member = _ecore_ipc_ddlt_int(d, cl->prev.i._member, md); + +static int +_ecore_ipc_event_client_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev) +{ + Ecore_Con_Event_Client_Data *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(ecore_con_client_server_get(e->client)))) return 1; + /* handling code here */ + { + Ecore_Ipc_Client *cl; + Ecore_Ipc_Msg_Head msg; + int offset = 0; + unsigned char *buf; + + cl = ecore_con_client_data_get(e->client); + + if (!cl->buf) + { + cl->buf_size = e->size; + cl->buf = e->data; + e->data = NULL; /* take it out of the old event */ + } + else + { + unsigned char *buf; + + buf = realloc(cl->buf, cl->buf_size + e->size); + if (!buf) + { + free(cl->buf); + cl->buf = 0; + cl->buf_size = 0; + return 0; + } + cl->buf = buf; + memcpy(cl->buf + cl->buf_size, e->data, e->size); + cl->buf_size += e->size; + } + /* examine header */ + redo: + if ((cl->buf_size - offset) >= (int)sizeof(int)) + { + int s, md, d, head; + unsigned char *dd; + + dd = (unsigned char *)&head; + dd[0] = *(cl->buf + offset + 0); + dd[1] = *(cl->buf + offset + 1); + dd[2] = *(cl->buf + offset + 2); + dd[3] = *(cl->buf + offset + 3); + head = ntohl(head); + dd = (unsigned char *)&d; + s = 4; + CLSZ(0); + CLSZ(1); + CLSZ(2); + CLSZ(3); + CLSZ(4); + CLSZ(5); + if ((cl->buf_size - offset) < s) + { + if (offset > 0) goto scroll; + return 0; + } + + s = 4; + CLDEC(0, major); + CLDEC(1, minor); + CLDEC(2, ref); + CLDEC(3, ref_to); + CLDEC(4, response); + CLDEC(5, size); + if (msg.size < 0) msg.size = 0; + /* there is enough data in the buffer for a full message */ + if ((cl->buf_size - offset) >= (s + msg.size)) + { + Ecore_Ipc_Event_Client_Data *e2; + + buf = NULL; + if (msg.size > 0) + { + buf = malloc(msg.size); + if (!buf) return 0; + memcpy(buf, cl->buf + offset + s, msg.size); + } + e2 = calloc(1, sizeof(Ecore_Ipc_Event_Client_Data)); + if (e2) + { + e2->client = cl; + e2->major = msg.major; + e2->minor = msg.minor; + e2->ref = msg.ref; + e2->ref_to = msg.ref_to; + e2->response = msg.response; + e2->size = msg.size; + e2->data = buf; + ecore_event_add(ECORE_IPC_EVENT_CLIENT_DATA, e2, + _ecore_ipc_event_client_data_free, NULL); + } + cl->prev.i = msg; + offset += (s + msg.size); + if (cl->buf_size == offset) + { + free(cl->buf); + cl->buf = NULL; + cl->buf_size = 0; + return 0; + } + goto redo; + } + else goto scroll; + } + else + { + scroll: + buf = malloc(cl->buf_size - offset); + if (!buf) + { + free(cl->buf); + cl->buf = NULL; + cl->buf_size = 0; + return 0; + } + memcpy(buf, cl->buf + offset, cl->buf_size - offset); + free(cl->buf); + cl->buf = buf; + cl->buf_size -= offset; + } + } + return 0; +} + +#define SVSZ(_n) \ + md = ((head >> (4 * _n)) & 0xf); \ + if (md >= DLT_SET) s += 4; \ + else if (md >= DLT_ADD16) s += 2; \ + else if (md >= DLT_ADD8) s += 1; + +#define SVDEC(_n, _member) \ + md = ((head >> (4 * _n)) & 0xf); \ + if (md >= DLT_SET) \ + { \ + unsigned int v; \ + unsigned char *dv; \ + dv = (unsigned char *)&v; \ + dv[0] = *(svr->buf + offset + s + 0); \ + dv[1] = *(svr->buf + offset + s + 1); \ + dv[2] = *(svr->buf + offset + s + 2); \ + dv[3] = *(svr->buf + offset + s + 3); \ + d = (int)ntohl(d); \ + s += 4; \ + } \ + else if (md >= DLT_ADD16) \ + { \ + unsigned short v; \ + unsigned char *dv; \ + dv = (unsigned char *)&v; \ + dv[0] = *(svr->buf + offset + s + 0); \ + dv[1] = *(svr->buf + offset + s + 1); \ + d = (int)ntohs(v); \ + s += 2; \ + } \ + else if (md >= DLT_ADD8) \ + { \ + unsigned char v; \ + unsigned char *dv; \ + dv = (unsigned char *)&v; \ + dv[0] = *(svr->buf + offset + s + 0); \ + d = (int)v; \ + s += 1; \ + } \ + msg._member = _ecore_ipc_ddlt_int(d, svr->prev.i._member, md); + +static int +_ecore_ipc_event_server_data(void *data __UNUSED__, int ev_type __UNUSED__, void *ev) +{ + Ecore_Con_Event_Server_Data *e; + + e = ev; + if (!_ecore_list_find(servers, ecore_con_server_data_get(e->server))) return 1; + /* handling code here */ + { + Ecore_Ipc_Server *svr; + Ecore_Ipc_Msg_Head msg; + int offset = 0; + unsigned char *buf; + + svr = ecore_con_server_data_get(e->server); + + if (!svr->buf) + { + svr->buf_size = e->size; + svr->buf = e->data; + e->data = NULL; /* take it out of the old event */ + } + else + { + unsigned char *buf; + + buf = realloc(svr->buf, svr->buf_size + e->size); + if (!buf) + { + free(svr->buf); + svr->buf = 0; + svr->buf_size = 0; + return 0; + } + svr->buf = buf; + memcpy(svr->buf + svr->buf_size, e->data, e->size); + svr->buf_size += e->size; + } + /* examine header */ + redo: + if ((svr->buf_size - offset) >= (int)sizeof(int)) + { + int s, md, d, head; + unsigned char *dd; + + dd = (unsigned char *)&head; + dd[0] = *(svr->buf + offset + 0); + dd[1] = *(svr->buf + offset + 1); + dd[2] = *(svr->buf + offset + 2); + dd[3] = *(svr->buf + offset + 3); + head = ntohl(head); + dd = (unsigned char *)&d; + s = 4; + SVSZ(0); + SVSZ(1); + SVSZ(2); + SVSZ(3); + SVSZ(4); + SVSZ(5); + if ((svr->buf_size - offset) < s) + { + if (offset > 0) goto scroll; + return 0; + } + + s = 4; + SVDEC(0, major); + SVDEC(1, minor); + SVDEC(2, ref); + SVDEC(3, ref_to); + SVDEC(4, response); + SVDEC(5, size); + if (msg.size < 0) msg.size = 0; + /* there is enough data in the buffer for a full message */ + if ((svr->buf_size - offset) >= (s + msg.size)) + { + Ecore_Ipc_Event_Server_Data *e2; + + buf = NULL; + if (msg.size > 0) + { + buf = malloc(msg.size); + if (!buf) return 0; + memcpy(buf, svr->buf + offset + s, msg.size); + } + e2 = calloc(1, sizeof(Ecore_Ipc_Event_Server_Data)); + if (e2) + { + e2->server = svr; + e2->major = msg.major; + e2->minor = msg.minor; + e2->ref = msg.ref; + e2->ref_to = msg.ref_to; + e2->response = msg.response; + e2->size = msg.size; + e2->data = buf; + ecore_event_add(ECORE_IPC_EVENT_SERVER_DATA, e2, + _ecore_ipc_event_server_data_free, NULL); + } + svr->prev.i = msg; + offset += (s + msg.size); + if (svr->buf_size == offset) + { + free(svr->buf); + svr->buf = NULL; + svr->buf_size = 0; + return 0; + } + goto redo; + } + else goto scroll; + } + else + { + scroll: + buf = malloc(svr->buf_size - offset); + if (!buf) + { + free(svr->buf); + svr->buf = NULL; + svr->buf_size = 0; + return 0; + } + memcpy(buf, svr->buf + offset, svr->buf_size - offset); + free(svr->buf); + svr->buf = buf; + svr->buf_size -= offset; + } + } + return 0; +} + +static void +_ecore_ipc_event_client_data_free(void *data __UNUSED__, void *ev) +{ + Ecore_Ipc_Event_Client_Data *e; + + e = ev; + if (e->data) free(e->data); + free(e); +} + +static void +_ecore_ipc_event_server_data_free(void *data __UNUSED__, void *ev) +{ + Ecore_Ipc_Event_Server_Data *e; + + e = ev; + if (e->data) free(e->data); + free(e); +} diff --git a/ecore/src/lib/ecore_ipc/ecore_ipc_private.h b/ecore/src/lib/ecore_ipc/ecore_ipc_private.h new file mode 100644 index 0000000..0e4d6ea --- /dev/null +++ b/ecore/src/lib/ecore_ipc/ecore_ipc_private.h @@ -0,0 +1,66 @@ +#ifndef _ECORE_IPC_PRIVATE_H +#define _ECORE_IPC_PRIVATE_H + +#if USE_OPENSSL +#include <openssl/ssl.h> +#endif + +#define ECORE_MAGIC_IPC_SERVER 0x87786556 +#define ECORE_MAGIC_IPC_CLIENT 0x78875665 + +typedef struct _Ecore_Ipc_Client Ecore_Ipc_Client; +typedef struct _Ecore_Ipc_Server Ecore_Ipc_Server; +typedef struct _Ecore_Ipc_Msg_Head Ecore_Ipc_Msg_Head; + + +#ifdef __sgi +#pragma pack 4 +#endif +struct _Ecore_Ipc_Msg_Head +{ + int head; + int major; + int minor; + int ref; + int ref_to; + int response; + int size; +} +#ifdef _GNU_C_ +__attribute__ ((packed)); +#endif +; +#ifdef __sgi +#pragma pack 0 +#endif + +struct _Ecore_Ipc_Client +{ + Ecore_List __list_data; + ECORE_MAGIC; + Ecore_Con_Client *client; + void *data; + unsigned char *buf; + int buf_size; + + struct { + Ecore_Ipc_Msg_Head i, o; + } prev; +}; + +struct _Ecore_Ipc_Server +{ + Ecore_List __list_data; + ECORE_MAGIC; + Ecore_Con_Server *server; + Ecore_Ipc_Client *clients; + void *data; + unsigned char *buf; + int buf_size; + + struct { + Ecore_Ipc_Msg_Head i, o; + } prev; +}; + +#endif diff --git a/ecore/src/lib/ecore_job/.cvsignore b/ecore/src/lib/ecore_job/.cvsignore new file mode 100644 index 0000000..0aac4af --- /dev/null +++ b/ecore/src/lib/ecore_job/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +ecore_job.lo +libecore_job.la diff --git a/ecore/src/lib/ecore_job/CVS/Entries b/ecore/src/lib/ecore_job/CVS/Entries new file mode 100644 index 0000000..93e034b --- /dev/null +++ b/ecore/src/lib/ecore_job/CVS/Entries @@ -0,0 +1,6 @@ +/.cvsignore/1.1/Thu Nov 13 12:30:47 2003//THEAD +/Ecore_Job.h/1.4/Thu Nov 25 05:17:17 2004//THEAD +/Makefile.am/1.6/Thu Mar 10 15:19:41 2005//THEAD +/ecore_job.c/1.7/Wed Mar 2 07:06:42 2005//THEAD +/ecore_job_private.h/1.2/Tue Sep 23 08:09:31 2003//THEAD +D diff --git a/ecore/src/lib/ecore_job/CVS/Repository b/ecore/src/lib/ecore_job/CVS/Repository new file mode 100644 index 0000000..65ef847 --- /dev/null +++ b/ecore/src/lib/ecore_job/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_job diff --git a/ecore/src/lib/ecore_job/CVS/Root b/ecore/src/lib/ecore_job/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_job/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_job/CVS/Tag b/ecore/src/lib/ecore_job/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_job/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_job/Ecore_Job.h b/ecore/src/lib/ecore_job/Ecore_Job.h new file mode 100644 index 0000000..e676ede --- /dev/null +++ b/ecore/src/lib/ecore_job/Ecore_Job.h @@ -0,0 +1,41 @@ +#ifndef _ECORE_JOB_H +#define _ECORE_JOB_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file + * @brief Functions for dealing with Ecore jobs. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ECORE_JOB_PRIVATE_H +typedef void Ecore_Job; /**< A job handle */ +#endif + +EAPI Ecore_Job *ecore_job_add(void (*func) (void *data), const void *data); +EAPI void *ecore_job_del(Ecore_Job *job); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_job/Makefile.am b/ecore/src/lib/ecore_job/Makefile.am new file mode 100644 index 0000000..476b7c0 --- /dev/null +++ b/ecore/src/lib/ecore_job/Makefile.am @@ -0,0 +1,31 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore + +libecore_job_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_JOB + +lib_LTLIBRARIES = libecore_job.la +include_HEADERS = \ +Ecore_Job.h + +libecore_job_la_SOURCES = \ +ecore_job.c \ +ecore_job_private.h + +libecore_job_la_LIBADD = \ +$(top_builddir)/src/lib/ecore/libecore.la + +libecore_job_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la + +endif + +EXTRA_DIST = \ +Ecore_Job.h \ +ecore_job.c \ +ecore_job_private.h diff --git a/ecore/src/lib/ecore_job/ecore_job.c b/ecore/src/lib/ecore_job/ecore_job.c new file mode 100644 index 0000000..b4fba2a --- /dev/null +++ b/ecore/src/lib/ecore_job/ecore_job.c @@ -0,0 +1,86 @@ +#include "Ecore.h" +#include "ecore_private.h" +#include "ecore_job_private.h" +#include "Ecore_Job.h" + +static int _ecore_job_event_handler(void *data, int type, void *ev); +static void _ecore_job_event_free(void *data, void *ev); + +static int ecore_event_job_type = 0; + +/** + * Add a job to the event queue. + * @param func The function to call when the job gets handled. + * @param data Data pointer to be passed to the job function when the job is + * handled. + * @return The handle of the job. @c NULL is returned if the job could not be + * added to the queue. + * @ingroup Ecore_Job_Group + * @note Once the job has been executed, the job handle is invalid. + */ +Ecore_Job * +ecore_job_add(void (*func) (void *data), const void *data) +{ + Ecore_Job *job; + + if (!func) return NULL; + if (!ecore_event_job_type) + { + ecore_event_job_type = ecore_event_type_new(); + ecore_event_handler_add(ecore_event_job_type, _ecore_job_event_handler, NULL); + } + job = calloc(1, sizeof(Ecore_Job)); + if (!job) return NULL; + ECORE_MAGIC_SET(job, ECORE_MAGIC_JOB); + job->event = ecore_event_add(ecore_event_job_type, job, _ecore_job_event_free, NULL); + if (!job->event) + { + free(job); + return NULL; + } + job->func = func; + job->data = (void *)data; + return job; +} + +/** + * Delete a queued job that has not yet been executed. + * @param job Handle of the job to delete. + * @return The data pointer that was to be passed to the job. + * @ingroup Ecore_Job_Group + */ +void * +ecore_job_del(Ecore_Job *job) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(job, ECORE_MAGIC_JOB)) + { + ECORE_MAGIC_FAIL(job, ECORE_MAGIC_JOB, + "ecore_job_del"); + return NULL; + } + data = job->data; + ECORE_MAGIC_SET(job, ECORE_MAGIC_NONE); + ecore_event_del(job->event); + return data; +} + +static int +_ecore_job_event_handler(void *data __UNUSED__, int type __UNUSED__, void *ev) +{ + Ecore_Job *job; + + job = ev; + job->func(job->data); + return 0; +} + +static void +_ecore_job_event_free(void *data __UNUSED__, void *ev) +{ + Ecore_Job *job; + + job = ev; + free(ev); +} diff --git a/ecore/src/lib/ecore_job/ecore_job_private.h b/ecore/src/lib/ecore_job/ecore_job_private.h new file mode 100644 index 0000000..d5795f2 --- /dev/null +++ b/ecore/src/lib/ecore_job/ecore_job_private.h @@ -0,0 +1,16 @@ +#ifndef _ECORE_JOB_PRIVATE_H +#define _ECORE_JOB_PRIVATE_H + +#define ECORE_MAGIC_JOB 0x76543210 + +typedef struct _Ecore_Job Ecore_Job; + +struct _Ecore_Job +{ + ECORE_MAGIC; + Ecore_Event *event; + void (*func) (void *data); + void *data; +}; + +#endif diff --git a/ecore/src/lib/ecore_txt/.cvsignore b/ecore/src/lib/ecore_txt/.cvsignore new file mode 100644 index 0000000..e599172 --- /dev/null +++ b/ecore/src/lib/ecore_txt/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +ecore_txt.lo +libecore_txt.la diff --git a/ecore/src/lib/ecore_txt/CVS/Entries b/ecore/src/lib/ecore_txt/CVS/Entries new file mode 100644 index 0000000..bdeacd8 --- /dev/null +++ b/ecore/src/lib/ecore_txt/CVS/Entries @@ -0,0 +1,6 @@ +/.cvsignore/1.2/Fri Jan 16 16:59:05 2004//THEAD +/Ecore_Txt.h/1.4/Mon Nov 29 22:26:30 2004//THEAD +/Makefile.am/1.5/Thu Mar 10 15:19:42 2005//THEAD +/ecore_txt.c/1.6/Wed Mar 2 07:06:42 2005//THEAD +/ecore_txt_private.h/1.1/Thu Oct 9 07:49:59 2003//THEAD +D diff --git a/ecore/src/lib/ecore_txt/CVS/Repository b/ecore/src/lib/ecore_txt/CVS/Repository new file mode 100644 index 0000000..6d66175 --- /dev/null +++ b/ecore/src/lib/ecore_txt/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_txt diff --git a/ecore/src/lib/ecore_txt/CVS/Root b/ecore/src/lib/ecore_txt/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_txt/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_txt/CVS/Tag b/ecore/src/lib/ecore_txt/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_txt/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_txt/Ecore_Txt.h b/ecore/src/lib/ecore_txt/Ecore_Txt.h new file mode 100644 index 0000000..60dc659 --- /dev/null +++ b/ecore/src/lib/ecore_txt/Ecore_Txt.h @@ -0,0 +1,36 @@ +#ifndef _ECORE_TXT_H +#define _ECORE_TXT_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @file Ecore_Txt.h + * @brief Provides a text encoding conversion function. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +EAPI char *ecore_txt_convert(const char *enc_from, const char *enc_to, const char *text); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_txt/Makefile.am b/ecore/src/lib/ecore_txt/Makefile.am new file mode 100644 index 0000000..e3fdd01 --- /dev/null +++ b/ecore/src/lib/ecore_txt/Makefile.am @@ -0,0 +1,34 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore \ +@iconv_cflags@ + +libecore_txt_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs + +if BUILD_ECORE_TXT + +lib_LTLIBRARIES = libecore_txt.la +include_HEADERS = \ +Ecore_Txt.h + +libecore_txt_la_SOURCES = \ +ecore_txt.c \ +ecore_txt_private.h + +# FIXME: may have to link with -liconv +libecore_txt_la_LIBADD = \ +@iconv_libs@ + + +libecore_txt_la_DEPENDENCIES = + + +endif + +EXTRA_DIST = \ +Ecore_Txt.h \ +ecore_txt.c \ +ecore_txt_private.h diff --git a/ecore/src/lib/ecore_txt/ecore_txt.c b/ecore/src/lib/ecore_txt/ecore_txt.c new file mode 100644 index 0000000..cab8f5d --- /dev/null +++ b/ecore/src/lib/ecore_txt/ecore_txt.c @@ -0,0 +1,78 @@ +#include "ecore_txt_private.h" +#include "Ecore_Txt.h" + +#include <iconv.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> + +/** + * To be documented. + * + * FIXME: Finish this. + */ +char * +ecore_txt_convert(const char *enc_from, const char *enc_to, const char *text) +{ + iconv_t ic; + char *new_txt, *inp, *outp; + size_t inb, outb, outlen, tob, outalloc; + + if (!text) return strdup(""); + ic = iconv_open(enc_to, enc_from); + if (!ic) return strdup(""); + new_txt = malloc(64); + inb = strlen(text); + outb = 64; + inp = (char*)text; + outp = new_txt; + outalloc = 64; + outlen = 0; + tob = 0; + + for (;;) + { + size_t count; + + tob = outb; + count = iconv(ic, &inp, &inb, &outp, &outb); + outlen += tob - outb; + if (count == (size_t)(-1)) + { + if (errno == E2BIG) + { + new_txt = realloc(new_txt, outalloc + 64); + outalloc += 64; + outb += 64; + } + else if (errno == EILSEQ) + { + if (new_txt) free(new_txt); + new_txt = NULL; + break; + } + else if (errno == EINVAL) + { + if (new_txt) free(new_txt); + new_txt = NULL; + break; + } + else + { + if (new_txt) free(new_txt); + new_txt = NULL; + break; + } + } + if (inb == 0) + { + if (outalloc == outlen) new_txt = realloc(new_txt, outalloc + 1); + new_txt[outlen] = 0; + break; + } + } + iconv_close(ic); + return new_txt; +} diff --git a/ecore/src/lib/ecore_txt/ecore_txt_private.h b/ecore/src/lib/ecore_txt/ecore_txt_private.h new file mode 100644 index 0000000..b3e975a --- /dev/null +++ b/ecore/src/lib/ecore_txt/ecore_txt_private.h @@ -0,0 +1,4 @@ +#ifndef _ECORE_TXT_PRIVATE_H +#define _ECORE_TXT_PRIVATE_H + +#endif diff --git a/ecore/src/lib/ecore_x/.cvsignore b/ecore/src/lib/ecore_x/.cvsignore new file mode 100644 index 0000000..8728e80 --- /dev/null +++ b/ecore/src/lib/ecore_x/.cvsignore @@ -0,0 +1,6 @@ +.deps +.libs +Makefile +Makefile.in +*.lo +libecore_x.la diff --git a/ecore/src/lib/ecore_x/CVS/Entries b/ecore/src/lib/ecore_x/CVS/Entries new file mode 100644 index 0000000..907365e --- /dev/null +++ b/ecore/src/lib/ecore_x/CVS/Entries @@ -0,0 +1,23 @@ +/.cvsignore/1.4/Tue Sep 21 19:18:44 2004//THEAD +/Ecore_X.h/1.138/Sat Jun 25 07:23:38 2005//THEAD +/Ecore_X_Atoms.h/1.10/Mon Jun 6 15:04:28 2005//THEAD +/Ecore_X_Cursor.h/1.2/Fri Apr 30 03:10:17 2004//THEAD +/Makefile.am/1.23/Mon Jun 6 09:40:00 2005//THEAD +/ecore_x.c/1.91/Tue Jul 12 15:27:45 2005//THEAD +/ecore_x_dnd.c/1.20/Sun Apr 10 10:20:18 2005//THEAD +/ecore_x_e.c/1.2/Mon May 16 12:59:26 2005//THEAD +/ecore_x_error.c/1.5/Wed Jun 22 06:47:44 2005//THEAD +/ecore_x_events.c/1.68/Tue Jul 12 15:27:46 2005//THEAD +/ecore_x_gc.c/1.4/Thu Jul 15 13:43:15 2004//THEAD +/ecore_x_icccm.c/1.34/Fri Jun 17 09:05:22 2005//THEAD +/ecore_x_mwm.c/1.4/Fri Jun 10 04:18:24 2005//THEAD +/ecore_x_netwm.c/1.36/Fri Jun 10 04:18:24 2005//THEAD +/ecore_x_pixmap.c/1.5/Thu Aug 12 11:29:18 2004//THEAD +/ecore_x_private.h/1.46/Tue Jul 12 15:27:46 2005//THEAD +/ecore_x_selection.c/1.26/Mon May 16 12:59:26 2005//THEAD +/ecore_x_sync.c/1.2/Mon Jun 6 15:04:28 2005//THEAD +/ecore_x_window.c/1.41/Sat Jun 25 07:23:38 2005//THEAD +/ecore_x_window_prop.c/1.72/Sat Jun 25 00:15:19 2005//THEAD +/ecore_x_window_shape.c/1.6/Sat Apr 23 05:06:18 2005//THEAD +/ecore_x_xinerama.c/1.2/Sat Feb 5 12:59:35 2005//THEAD +D diff --git a/ecore/src/lib/ecore_x/CVS/Repository b/ecore/src/lib/ecore_x/CVS/Repository new file mode 100644 index 0000000..df9cfee --- /dev/null +++ b/ecore/src/lib/ecore_x/CVS/Repository @@ -0,0 +1 @@ +e17/libs/ecore/src/lib/ecore_x diff --git a/ecore/src/lib/ecore_x/CVS/Root b/ecore/src/lib/ecore_x/CVS/Root new file mode 100644 index 0000000..0b69fe3 --- /dev/null +++ b/ecore/src/lib/ecore_x/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/enlightenment diff --git a/ecore/src/lib/ecore_x/CVS/Tag b/ecore/src/lib/ecore_x/CVS/Tag new file mode 100644 index 0000000..3903919 --- /dev/null +++ b/ecore/src/lib/ecore_x/CVS/Tag @@ -0,0 +1 @@ +NHEAD diff --git a/ecore/src/lib/ecore_x/Ecore_X.h b/ecore/src/lib/ecore_x/Ecore_X.h new file mode 100644 index 0000000..68ff1dd --- /dev/null +++ b/ecore/src/lib/ecore_x/Ecore_X.h @@ -0,0 +1,1320 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifndef _ECORE_X_H +#define _ECORE_X_H + +#ifdef EAPI +#undef EAPI +#endif +#ifdef WIN32 +# ifdef BUILDING_DLL +# define EAPI __declspec(dllexport) +# else +# define EAPI __declspec(dllimport) +# endif +#else +# ifdef GCC_HASCLASSVISIBILITY +# define EAPI __attribute__ ((visibility("default"))) +# else +# define EAPI +# endif +#endif + +/** + * @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 +typedef Ecore_X_ID Ecore_X_Pixmap; +typedef Ecore_X_ID Ecore_X_Drawable; +typedef void * Ecore_X_GC; +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 Ecore_X_ID Ecore_X_Sync_Counter; +typedef Ecore_X_ID Ecore_X_Sync_Alarm; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _Ecore_X_Rectangle { + int x, y; + unsigned int width, height; +} Ecore_X_Rectangle; + +typedef enum _Ecore_X_Window_State { + /** The window is iconified. */ + ECORE_X_WINDOW_STATE_ICONIFIED, + + /** The window is a modal dialog box. */ + ECORE_X_WINDOW_STATE_MODAL, + + /** The window manager should keep the window's position fixed + * even if the virtual desktop scrolls. */ + ECORE_X_WINDOW_STATE_STICKY, + + /** The window has the maximum vertical size. */ + ECORE_X_WINDOW_STATE_MAXIMIZED_VERT, + + /** The window has the maximum horizontal size. */ + ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ, + + /** The window is shaded. */ + ECORE_X_WINDOW_STATE_SHADED, + + /** The window should not be included in the taskbar. */ + ECORE_X_WINDOW_STATE_SKIP_TASKBAR, + + /** The window should not be included in the pager. */ + ECORE_X_WINDOW_STATE_SKIP_PAGER, + + /** The window is invisible (i.e. minimized/iconified) */ + ECORE_X_WINDOW_STATE_HIDDEN, + + /** The window should fill the entire screen and have no + * window border/decorations */ + ECORE_X_WINDOW_STATE_FULLSCREEN, + + /* The following are not documented because they are not + * intended for use in applications. */ + ECORE_X_WINDOW_STATE_ABOVE, + ECORE_X_WINDOW_STATE_BELOW, + + /* FIXME: Documentation */ + ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION, + + /* Unknown state */ + ECORE_X_WINDOW_STATE_UNKNOWN + +} 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; + +#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 + +extern EAPI Ecore_X_Atom ECORE_X_DND_ACTION_COPY; +extern EAPI Ecore_X_Atom ECORE_X_DND_ACTION_MOVE; +extern EAPI Ecore_X_Atom ECORE_X_DND_ACTION_LINK; +extern EAPI Ecore_X_Atom ECORE_X_DND_ACTION_ASK; +extern EAPI Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE; + +typedef enum _Ecore_X_Selection { + ECORE_X_SELECTION_PRIMARY, + ECORE_X_SELECTION_SECONDARY, + ECORE_X_SELECTION_XDND, + ECORE_X_SELECTION_CLIPBOARD +} 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; + +typedef struct _Ecore_X_Event_Key_Down Ecore_X_Event_Key_Down; +typedef struct _Ecore_X_Event_Key_Up Ecore_X_Event_Key_Up; +typedef struct _Ecore_X_Event_Mouse_Button_Down Ecore_X_Event_Mouse_Button_Down; +typedef struct _Ecore_X_Event_Mouse_Button_Up Ecore_X_Event_Mouse_Button_Up; +typedef struct _Ecore_X_Event_Mouse_Move Ecore_X_Event_Mouse_Move; +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_Mouse_Wheel Ecore_X_Event_Mouse_Wheel; +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_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_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_Sync_Counter Ecore_X_Event_Sync_Counter; +typedef struct _Ecore_X_Event_Sync_Alarm Ecore_X_Event_Sync_Alarm; + +typedef struct _Ecore_X_Event_Window_Delete_Request Ecore_X_Event_Window_Delete_Request; +typedef struct _Ecore_X_Event_Window_Prop_Title_Change Ecore_X_Event_Window_Prop_Title_Change; +typedef struct _Ecore_X_Event_Window_Prop_Visible_Title_Change Ecore_X_Event_Window_Prop_Visible_Title_Change; +typedef struct _Ecore_X_Event_Window_Prop_Icon_Name_Change Ecore_X_Event_Window_Prop_Icon_Name_Change; +typedef struct _Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change; +typedef struct _Ecore_X_Event_Window_Prop_Client_Machine_Change Ecore_X_Event_Window_Prop_Client_Machine_Change; +typedef struct _Ecore_X_Event_Window_Prop_Name_Class_Change Ecore_X_Event_Window_Prop_Name_Class_Change; +typedef struct _Ecore_X_Event_Window_Prop_Pid_Change Ecore_X_Event_Window_Prop_Pid_Change; +typedef struct _Ecore_X_Event_Window_Prop_Desktop_Change Ecore_X_Event_Window_Prop_Desktop_Change; + +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; + +struct _Ecore_X_Event_Key_Down +{ + char *keyname; + char *keysymbol; + char *key_compose; + int modifiers; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Key_Up +{ + char *keyname; + char *keysymbol; + char *key_compose; + int modifiers; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Mouse_Button_Down +{ + int button; + int modifiers; + int x, y; + struct { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; + int double_click : 1; + int triple_click : 1; +}; + +struct _Ecore_X_Event_Mouse_Button_Up +{ + int button; + int modifiers; + int x, y; + struct { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Mouse_Move +{ + int modifiers; + int x, y; + struct { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Mouse_In +{ + int modifiers; + int x, y; + struct { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_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; + struct { + int x, y; + } root; + Ecore_X_Window win; + Ecore_X_Window event_win; + Ecore_X_Event_Mode mode; + Ecore_X_Event_Detail detail; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Mouse_Wheel +{ + int direction; /* 0 = default up/down wheel FIXME: more wheel types */ + int z; /* ...,-2,-1 = down, 1,2,... = up */ + int modifiers; + int x, y; + + struct { + int x, y; + } root; + + Ecore_X_Window win; + Ecore_X_Window event_win; + 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; + 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; + int override; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Destroy +{ + Ecore_X_Window win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Hide +{ + Ecore_X_Window win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Show +{ + Ecore_X_Window 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 parent; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Configure +{ + Ecore_X_Window win; + Ecore_X_Window abovewin; + int x, y, w, h; + int border; + int override : 1; + int from_wm : 1; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Window_Configure_Request +{ + Ecore_X_Window 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_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_Time time; +}; + +struct _Ecore_X_Event_Window_Stack_Request +{ + Ecore_X_Window win; + 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; + int installed; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Selection_Clear +{ + Ecore_X_Window win; + Ecore_X_Selection selection; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Selection_Request +{ + Ecore_X_Window win; + Ecore_X_Time time; +}; + +struct _Ecore_X_Event_Selection_Notify +{ + Ecore_X_Window win; + Ecore_X_Time time; + Ecore_X_Selection selection; + char *target; + void *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; +}; + +struct _Ecore_X_Selection_Data +{ + unsigned char *data; + int length; + + 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_Event_Xdnd_Status +{ + Ecore_X_Window win, target; + int will_accept; + 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; + int completed; + 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; +}; + +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_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_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; +}; + +extern EAPI int ECORE_X_EVENT_KEY_DOWN; +extern EAPI int ECORE_X_EVENT_KEY_UP; +extern EAPI int ECORE_X_EVENT_MOUSE_BUTTON_DOWN; +extern EAPI int ECORE_X_EVENT_MOUSE_BUTTON_UP; +extern EAPI int ECORE_X_EVENT_MOUSE_MOVE; +extern EAPI int ECORE_X_EVENT_MOUSE_IN; +extern EAPI int ECORE_X_EVENT_MOUSE_OUT; +extern EAPI int ECORE_X_EVENT_MOUSE_WHEEL; +extern EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN; +extern EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT; +extern EAPI int ECORE_X_EVENT_WINDOW_KEYMAP; +extern EAPI int ECORE_X_EVENT_WINDOW_DAMAGE; +extern EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_CREATE; +extern EAPI int ECORE_X_EVENT_WINDOW_DESTROY; +extern EAPI int ECORE_X_EVENT_WINDOW_HIDE; +extern EAPI int ECORE_X_EVENT_WINDOW_SHOW; +extern EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST; +extern EAPI int ECORE_X_EVENT_WINDOW_REPARENT; +extern EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE; +extern EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST; +extern EAPI int ECORE_X_EVENT_WINDOW_GRAVITY; +extern EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST; +extern EAPI int ECORE_X_EVENT_WINDOW_STACK; +extern EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST; +extern EAPI int ECORE_X_EVENT_WINDOW_PROPERTY; +extern EAPI int ECORE_X_EVENT_WINDOW_COLORMAP; +extern EAPI int ECORE_X_EVENT_WINDOW_MAPPING; +extern EAPI int ECORE_X_EVENT_SELECTION_CLEAR; +extern EAPI int ECORE_X_EVENT_SELECTION_REQUEST; +extern EAPI int ECORE_X_EVENT_SELECTION_NOTIFY; +extern EAPI int ECORE_X_EVENT_CLIENT_MESSAGE; +extern EAPI int ECORE_X_EVENT_WINDOW_SHAPE; +extern EAPI int ECORE_X_EVENT_SYNC_COUNTER; +extern EAPI int ECORE_X_EVENT_SYNC_ALARM; + +extern EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST; +/* +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE; +extern EAPI int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE; +*/ + +extern EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST; +extern EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST; +extern EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST; +extern EAPI int ECORE_X_EVENT_PING; +extern EAPI int ECORE_X_EVENT_DESKTOP_CHANGE; + +extern EAPI int ECORE_X_EVENT_XDND_ENTER; +extern EAPI int ECORE_X_EVENT_XDND_POSITION; +extern EAPI int ECORE_X_EVENT_XDND_STATUS; +extern EAPI int ECORE_X_EVENT_XDND_LEAVE; +extern EAPI int ECORE_X_EVENT_XDND_DROP; +extern EAPI int ECORE_X_EVENT_XDND_FINISHED; + +extern EAPI int ECORE_X_MODIFIER_SHIFT; +extern EAPI int ECORE_X_MODIFIER_CTRL; +extern EAPI int ECORE_X_MODIFIER_ALT; +extern EAPI int ECORE_X_MODIFIER_WIN; + +extern EAPI int ECORE_X_LOCK_SCROLL; +extern EAPI int ECORE_X_LOCK_NUM; +extern EAPI int ECORE_X_LOCK_CAPS; + +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 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_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_UNKNOWN +} 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; + +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; + +/* Window layer constants */ +#define ECORE_X_WINDOW_LAYER_BELOW 2 +#define ECORE_X_WINDOW_LAYER_NORMAL 4 +#define ECORE_X_WINDOW_LAYER_ABOVE 6 + +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 int ecore_x_fd_get(void); +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 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 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 int ecore_x_selection_primary_set(Ecore_X_Window w, unsigned char *data, int size); +EAPI int ecore_x_selection_primary_clear(void); +EAPI int ecore_x_selection_secondary_set(Ecore_X_Window w, unsigned char *data, int size); +EAPI int ecore_x_selection_secondary_clear(void); +EAPI int ecore_x_selection_xdnd_set(Ecore_X_Window w, unsigned char *data, int size); +EAPI int ecore_x_selection_xdnd_clear(void); +EAPI int ecore_x_selection_clipboard_set(Ecore_X_Window w, unsigned char *data, int size); +EAPI int ecore_x_selection_clipboard_clear(void); +EAPI void ecore_x_selection_primary_request(Ecore_X_Window w, char *target); +EAPI void ecore_x_selection_primary_request_data_get(void **buf, int *len); +EAPI void ecore_x_selection_secondary_request(Ecore_X_Window w, char *target); +EAPI void ecore_x_selection_secondary_request_data_get(void **buf, int *len); +EAPI void ecore_x_selection_xdnd_request(Ecore_X_Window w, char *target); +EAPI void ecore_x_selection_xdnd_request_data_get(void **buf, int *len); +EAPI void ecore_x_selection_clipboard_request(Ecore_X_Window w, char *target); +EAPI void ecore_x_selection_clipboard_request_data_get(void **buf, int *len); +EAPI void ecore_x_selection_converter_add(char *target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret)); +EAPI void ecore_x_selection_converter_atom_add(Ecore_X_Atom target, int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret)); +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, unsigned char *data, int size)); +EAPI void ecore_x_selection_parser_del(const char *target); + +EAPI void ecore_x_dnd_aware_set(Ecore_X_Window win, int on); +EAPI int ecore_x_dnd_version_get(Ecore_X_Window win); +EAPI int 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, int on); +EAPI int ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size); +EAPI void ecore_x_dnd_drop(void); +EAPI void ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action); +EAPI void ecore_x_dnd_send_finished(void); + +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 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_del(Ecore_X_Window win); +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, int 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_at_xy_get(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_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 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 int 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_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_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_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 void ecore_x_window_shape_events_select(Ecore_X_Window win, int on); + +EAPI Ecore_X_Pixmap ecore_x_pixmap_new(Ecore_X_Window win, int w, int h, int dep); +EAPI void ecore_x_pixmap_del(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); +EAPI void ecore_x_gc_del(Ecore_X_GC gc); + +EAPI int 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 int ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type, const void *data, int len); + + +/* FIXME: these funcs need categorising */ +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 Ecore_X_Window *ecore_x_window_root_list(int *num_ret); +EAPI Ecore_X_Window ecore_x_window_root_first_get(void); +EAPI int 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_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, + int 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, + int is_urgent); +EAPI int ecore_x_icccm_hints_get(Ecore_X_Window win, + int *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, + int *is_urgent); +EAPI void ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win, + int 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 int ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win, + int *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_set(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol, + int on); +EAPI int 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 int 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, int borderless); + +/* netwm */ +EAPI void ecore_x_netwm_init(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 int 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 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, int 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_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_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 int 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 int 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 int 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 int ecore_x_netwm_icon_get(Ecore_X_Window win, int *width, int *height, unsigned int **data, int *num); +EAPI void ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, int x, int y, int width, int height); +EAPI int 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 int ecore_x_netwm_pid_get(Ecore_X_Window win, int *pid); +EAPI void ecore_x_netwm_handled_icons_set(Ecore_X_Window win); +EAPI int 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 int 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 int 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 int ecore_x_netwm_window_type_get(Ecore_X_Window win, Ecore_X_Window_Type *type); +EAPI int 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, int on); +EAPI void ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity); +EAPI int 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 int ecore_x_netwm_frame_size_get(Ecore_X_Window win, int *fl, int *fr, int *ft, int *fb); +EAPI int 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, int set); +EAPI void ecore_x_netwm_desktop_request_send(Ecore_X_Window win, Ecore_X_Window root, unsigned int desktop); + + + + +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 int ecore_x_xinerama_screen_count_get(void); +EAPI int ecore_x_xinerama_screen_geometry_get(int screen, int *x, int *y, int *w, int *h); + +/* FIXME: these funcs need categorising */ +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 Ecore_X_Window *ecore_x_window_root_list(int *num_ret); +EAPI int 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); + +typedef struct _Ecore_X_Window_Attributes +{ + Ecore_X_Window root; + int x, y, w, h; + int border; + int depth; + char visible : 1; + char viewable : 1; + char override : 1; + char input_only : 1; + char 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; + /* FIXME: missing + * Colormap comormap; + * int map_installed; + * Screen *screen; + * Visual *visual; + */ +} Ecore_X_Window_Attributes; + +EAPI int 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 int 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 int ecore_x_pointer_grab(Ecore_X_Window win); +EAPI int ecore_x_pointer_confine_grab(Ecore_X_Window win); +EAPI void ecore_x_pointer_ungrab(void); +EAPI int ecore_x_pointer_warp(Ecore_X_Window win, int x, int y); +EAPI int 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(int (*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, char *key, + int mod, int any_mod); +EAPI void ecore_x_window_key_ungrab(Ecore_X_Window win, 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_sync.c */ +EAPI Ecore_X_Sync_Alarm ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter); +EAPI int ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ecore/src/lib/ecore_x/Ecore_X_Atoms.h b/ecore/src/lib/ecore_x/Ecore_X_Atoms.h new file mode 100644 index 0000000..759016c --- /dev/null +++ b/ecore/src/lib/ecore_x/Ecore_X_Atoms.h @@ -0,0 +1,152 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#ifndef _ECORE_X_ATOMS_H +#define _ECORE_X_ATOMS_H + +#include "Ecore_X.h" + +/** + * @file + * @brief Ecore X atoms + */ + +/* General */ +extern Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING; +extern Ecore_X_Atom ECORE_X_ATOM_FILE_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_STRING; +extern Ecore_X_Atom ECORE_X_ATOM_TEXT; +extern Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT; + +/* ICCCM */ +extern Ecore_X_Atom ECORE_X_ATOM_WM_STATE; +extern Ecore_X_Atom ECORE_X_ATOM_WM_DELETE_WINDOW; +extern Ecore_X_Atom ECORE_X_ATOM_WM_TAKE_FOCUS; +extern Ecore_X_Atom ECORE_X_ATOM_WM_PROTOCOLS; +extern Ecore_X_Atom ECORE_X_ATOM_WM_CLASS; +extern Ecore_X_Atom ECORE_X_ATOM_WM_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_WM_COMMAND; +extern Ecore_X_Atom ECORE_X_ATOM_WM_ICON_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_MACHINE; +extern Ecore_X_Atom ECORE_X_ATOM_WM_CHANGE_STATE; +extern Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_WINDOWS; +extern Ecore_X_Atom ECORE_X_ATOM_WM_WINDOW_ROLE; +extern Ecore_X_Atom ECORE_X_ATOM_WM_HINTS; +extern Ecore_X_Atom ECORE_X_ATOM_WM_NORMAL_HINTS; +extern Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_LEADER; +extern Ecore_X_Atom ECORE_X_ATOM_WM_TRANSIENT_FOR; +extern Ecore_X_Atom ECORE_X_ATOM_WM_SAVE_YOURSELF; + +/* MWM */ +extern Ecore_X_Atom ECORE_X_ATOM_MOTIF_WM_HINTS; + +/* GNOME */ +extern Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER; + +/* EWMH */ +extern Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTED; +extern Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS; +extern Ecore_X_Atom ECORE_X_ATOM_NET_VIRTUAL_ROOTS; +extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_NAMES; +extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_GEOMETRY; +extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_VIEWPORT; +extern Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_LAYOUT; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WORKAREA; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_CURRENT_DESKTOP; +extern Ecore_X_Atom ECORE_X_ATOM_NET_SHOWING_DESKTOP; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST; +extern Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST_STACKING; +extern Ecore_X_Atom ECORE_X_ATOM_NET_ACTIVE_WINDOW; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_DESKTOP; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT_PARTIAL; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_GEOMETRY; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_PID; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_HANDLED_ICONS; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_USER_TIME; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_CLOSE_WINDOW; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_MOVERESIZE; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MOVE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_RESIZE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_SHADE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_STICK; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CLOSE; /*x*/ + +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MODAL; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_STICKY; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SHADED; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_HIDDEN; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_ABOVE; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_BELOW; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_OPACITY; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS; +extern Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS; + +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_PING; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST; +extern Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER; + +/* Selections */ +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_PRIMARY; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_SECONDARY; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD; + +/* DND */ +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_XDND; +extern Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_XDND; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_AWARE; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_TYPE_LIST; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_COPY; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_PRIVATE; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_ASK; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LIST; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_DESCRIPTION; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_ENTER; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_LEAVE; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_STATUS; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_POSITION; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_DROP; +extern Ecore_X_Atom ECORE_X_ATOM_XDND_FINISHED; + +#endif /* _ECORE_X_ATOMS_H */ diff --git a/ecore/src/lib/ecore_x/Ecore_X_Cursor.h b/ecore/src/lib/ecore_x/Ecore_X_Cursor.h new file mode 100644 index 0000000..af2e97a --- /dev/null +++ b/ecore/src/lib/ecore_x/Ecore_X_Cursor.h @@ -0,0 +1,86 @@ +#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_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 diff --git a/ecore/src/lib/ecore_x/Makefile.am b/ecore/src/lib/ecore_x/Makefile.am new file mode 100644 index 0000000..6b3bac9 --- /dev/null +++ b/ecore/src/lib/ecore_x/Makefile.am @@ -0,0 +1,81 @@ +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = \ +@Xcursor_cflags@ \ +@Xprint_cflags@ \ +@Xinerama_cflags@ \ +@x_cflags@ \ +-I$(top_srcdir)/src/lib/ecore \ +-I$(top_srcdir)/src/lib/ecore_txt \ +-I$(top_srcdir)/src/lib/ecore_job \ +-I$(top_builddir)/src/lib/ecore \ +-I$(top_builddir)/src/lib/ecore_txt \ +-I$(top_builddir)/src/lib/ecore_job + +libecore_x_la_LDFLAGS = -version-info 1:0:0 \ +-L$(top_builddir)/src/lib/ecore/.libs \ +-L$(top_builddir)/src/lib/ecore_txt/.libs \ +-L$(top_builddir)/src/lib/ecore_job/.libs + +if BUILD_ECORE_X + +lib_LTLIBRARIES = libecore_x.la +include_HEADERS = \ +Ecore_X.h \ +Ecore_X_Atoms.h \ +Ecore_X_Cursor.h + +libecore_x_la_SOURCES = \ +ecore_x.c \ +ecore_x_dnd.c \ +ecore_x_sync.c \ +ecore_x_error.c \ +ecore_x_events.c \ +ecore_x_icccm.c \ +ecore_x_netwm.c \ +ecore_x_mwm.c \ +ecore_x_e.c \ +ecore_x_selection.c \ +ecore_x_window.c \ +ecore_x_window_prop.c \ +ecore_x_window_shape.c \ +ecore_x_pixmap.c \ +ecore_x_gc.c \ +ecore_x_xinerama.c \ +ecore_x_private.h + +libecore_x_la_LIBADD = \ +@Xcursor_libs@ \ +@Xprint_libs@ \ +@Xinerama_libs@ \ +@x_ldflags@ \ +@x_libs@ \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_txt/libecore_txt.la \ +$(top_builddir)/src/lib/ecore_job/libecore_job.la + +libecore_x_la_DEPENDENCIES = \ +$(top_builddir)/src/lib/ecore/libecore.la \ +$(top_builddir)/src/lib/ecore_txt/libecore_txt.la \ +$(top_builddir)/src/lib/ecore_job/libecore_job.la + +endif + +EXTRA_DIST = \ +Ecore_X.h \ +Ecore_X_Atoms.h \ +Ecore_X_Cursor.h \ +ecore_x.c \ +ecore_x_dnd.c \ +ecore_x_sync.c \ +ecore_x_error.c \ +ecore_x_events.c \ +ecore_x_icccm.c \ +ecore_x_netwm.c \ +ecore_x_selection.c \ +ecore_x_window.c \ +ecore_x_window_prop.c \ +ecore_x_window_shape.c \ +ecore_x_pixmap.c \ +ecore_x_gc.c \ +ecore_x_private.h diff --git a/ecore/src/lib/ecore_x/ecore_x.c b/ecore/src/lib/ecore_x/ecore_x.c new file mode 100644 index 0000000..2d52bc3 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x.c @@ -0,0 +1,1685 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_private.h" +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +static int _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler); +static int _ecore_x_key_mask_get(KeySym sym); +static void *_ecore_x_event_filter_start(void *data); +static int _ecore_x_event_filter_filter(void *data, void *loop_data,int type, void *event); +static void _ecore_x_event_filter_end(void *data, void *loop_data); + +static Ecore_Fd_Handler *_ecore_x_fd_handler_handle = NULL; +static Ecore_Event_Filter *_ecore_x_filter_handler = NULL; +static int _ecore_x_event_shape_id = 0; +static int _ecore_x_event_sync_id = 0; +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; +int _ecore_x_xcursor = 0; + +Ecore_X_Window _ecore_x_private_win = 0; + +/* FIXME - These are duplicates after making ecore atoms public */ +Ecore_X_Atom ECORE_X_ATOM_FILE_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_STRING = 0; +Ecore_X_Atom ECORE_X_ATOM_TEXT = 0; +Ecore_X_Atom ECORE_X_ATOM_UTF8_STRING = 0; +Ecore_X_Atom ECORE_X_ATOM_COMPOUND_TEXT = 0; + +Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; + +/* + * GNOME hints. + */ +Ecore_X_Atom ECORE_X_ATOM_WIN_LAYER = 0; + +/* + * Other hints. + */ +Ecore_X_Atom ECORE_X_ATOM_SELECTION_TARGETS; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_PRIMARY = 0; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_SECONDARY = 0; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_CLIPBOARD = 0; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_PRIMARY = 0; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_SECONDARY = 0; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD = 0; + +Ecore_X_Atom ECORE_X_ATOM_SELECTION_XDND = 0; +Ecore_X_Atom ECORE_X_ATOM_SELECTION_PROP_XDND = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_AWARE = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ENTER = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_TYPE_LIST = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_POSITION = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_COPY = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_MOVE = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LINK = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_PRIVATE = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_ASK = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_LIST = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_ACTION_DESCRIPTION = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_PROXY = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_STATUS = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_DROP = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_FINISHED = 0; +Ecore_X_Atom ECORE_X_ATOM_XDND_LEAVE = 0; + +/* Xdnd atoms that need to be exposed to the application interface */ +Ecore_X_Atom ECORE_X_DND_ACTION_COPY = 0; +Ecore_X_Atom ECORE_X_DND_ACTION_MOVE = 0; +Ecore_X_Atom ECORE_X_DND_ACTION_LINK = 0; +Ecore_X_Atom ECORE_X_DND_ACTION_ASK = 0; +Ecore_X_Atom ECORE_X_DND_ACTION_PRIVATE = 0; + +int ECORE_X_EVENT_KEY_DOWN = 0; +int ECORE_X_EVENT_KEY_UP = 0; +int ECORE_X_EVENT_MOUSE_BUTTON_DOWN = 0; +int ECORE_X_EVENT_MOUSE_BUTTON_UP = 0; +int ECORE_X_EVENT_MOUSE_MOVE = 0; +int ECORE_X_EVENT_MOUSE_IN = 0; +int ECORE_X_EVENT_MOUSE_OUT = 0; +int ECORE_X_EVENT_MOUSE_WHEEL = 0; +int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0; +int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0; +int ECORE_X_EVENT_WINDOW_KEYMAP = 0; +int ECORE_X_EVENT_WINDOW_DAMAGE = 0; +int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_CREATE = 0; +int ECORE_X_EVENT_WINDOW_DESTROY = 0; +int ECORE_X_EVENT_WINDOW_HIDE = 0; +int ECORE_X_EVENT_WINDOW_SHOW = 0; +int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0; +int ECORE_X_EVENT_WINDOW_REPARENT = 0; +int ECORE_X_EVENT_WINDOW_CONFIGURE = 0; +int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0; +int ECORE_X_EVENT_WINDOW_GRAVITY = 0; +int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0; +int ECORE_X_EVENT_WINDOW_STACK = 0; +int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0; +int ECORE_X_EVENT_WINDOW_PROPERTY = 0; +int ECORE_X_EVENT_WINDOW_COLORMAP = 0; +int ECORE_X_EVENT_WINDOW_MAPPING = 0; +int ECORE_X_EVENT_SELECTION_CLEAR = 0; +int ECORE_X_EVENT_SELECTION_REQUEST = 0; +int ECORE_X_EVENT_SELECTION_NOTIFY = 0; +int ECORE_X_EVENT_CLIENT_MESSAGE = 0; +int ECORE_X_EVENT_WINDOW_SHAPE = 0; +int ECORE_X_EVENT_SYNC_COUNTER = 0; +int ECORE_X_EVENT_SYNC_ALARM = 0; + +int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0; +/* +int ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = 0; +int ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 0; +*/ + +int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0; +int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0; +int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0; +int ECORE_X_EVENT_PING = 0; +int ECORE_X_EVENT_DESKTOP_CHANGE = 0; + +int ECORE_X_EVENT_XDND_ENTER = 0; +int ECORE_X_EVENT_XDND_POSITION = 0; +int ECORE_X_EVENT_XDND_STATUS = 0; +int ECORE_X_EVENT_XDND_LEAVE = 0; +int ECORE_X_EVENT_XDND_DROP = 0; +int ECORE_X_EVENT_XDND_FINISHED = 0; + +int ECORE_X_MODIFIER_SHIFT = 0; +int ECORE_X_MODIFIER_CTRL = 0; +int ECORE_X_MODIFIER_ALT = 0; +int ECORE_X_MODIFIER_WIN = 0; + +int ECORE_X_LOCK_SCROLL = 0; +int ECORE_X_LOCK_NUM = 0; +int ECORE_X_LOCK_CAPS = 0; + +/** + * @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 + */ +int +ecore_x_init(const char *name) +{ + int shape_base = 0; + int shape_err_base = 0; + int sync_base = 0; + int sync_err_base = 0; + + if (_ecore_x_init_count > 0) + { + _ecore_x_init_count++; + return _ecore_x_init_count; + } + _ecore_x_disp = XOpenDisplay((char *)name); + if (!_ecore_x_disp) return 0; + _ecore_x_error_handler_init(); + _ecore_x_event_handlers_num = LASTEvent; + + if (XShapeQueryExtension(_ecore_x_disp, &shape_base, &shape_err_base)) + _ecore_x_event_shape_id = shape_base + ShapeNotify; + if (_ecore_x_event_shape_id >= LASTEvent) + _ecore_x_event_handlers_num = _ecore_x_event_shape_id + 1; + + 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; + } + if (_ecore_x_event_sync_id + XSyncAlarmNotify >= LASTEvent) + _ecore_x_event_handlers_num = _ecore_x_event_sync_id + XSyncAlarmNotify + 1; + + _ecore_x_event_handlers = calloc(_ecore_x_event_handlers_num, sizeof(void *)); + if (!_ecore_x_event_handlers) + { + XCloseDisplay(_ecore_x_disp); + _ecore_x_fd_handler_handle = NULL; + _ecore_x_disp = NULL; + return 0; + } +#ifdef ECORE_XCURSOR + _ecore_x_xcursor = XcursorSupportsARGB(_ecore_x_disp); +#endif + _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[MappingNotify] = _ecore_x_event_handle_mapping_notify; + _ecore_x_event_handlers[ClientMessage] = _ecore_x_event_handle_client_message; + 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_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; + } + if (!ECORE_X_EVENT_KEY_DOWN) + { + ECORE_X_EVENT_KEY_DOWN = ecore_event_type_new(); + ECORE_X_EVENT_KEY_UP = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_BUTTON_DOWN = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_BUTTON_UP = ecore_event_type_new(); + ECORE_X_EVENT_MOUSE_MOVE = 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_MOUSE_WHEEL = 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_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_SYNC_COUNTER = ecore_event_type_new(); + ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new(); + + ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new(); + /* + ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE = ecore_event_type_new(); + ECORE_X_EVENT_WINDOW_PROP_DESKTOP_CHANGE = 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_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(); + } + + /* 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_Mode_switch); + if (!ECORE_X_MODIFIER_WIN) + ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Meta_L); + + 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_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) + { + XCloseDisplay(_ecore_x_disp); + free(_ecore_x_event_handlers); + _ecore_x_fd_handler_handle = NULL; + _ecore_x_disp = NULL; + _ecore_x_event_handlers = NULL; + return 0; + } + _ecore_x_filter_handler = ecore_event_filter_add(_ecore_x_event_filter_start, _ecore_x_event_filter_filter, _ecore_x_event_filter_end, NULL); + + ECORE_X_ATOM_COMPOUND_TEXT = XInternAtom(_ecore_x_disp, "COMPOUND_TEXT", False); + ECORE_X_ATOM_UTF8_STRING = XInternAtom(_ecore_x_disp, "UTF8_STRING", False); + ECORE_X_ATOM_FILE_NAME = XInternAtom(_ecore_x_disp, "FILE_NAME", False); + ECORE_X_ATOM_STRING = XInternAtom(_ecore_x_disp, "STRING", False); + ECORE_X_ATOM_TEXT = XInternAtom(_ecore_x_disp, "TEXT", False); + + /* Set up the ICCCM hints */ + ecore_x_icccm_init(); + + ECORE_X_ATOM_MOTIF_WM_HINTS = XInternAtom(_ecore_x_disp, "_MOTIF_WM_HINTS", False); + + ECORE_X_ATOM_WIN_LAYER = XInternAtom(_ecore_x_disp, "_WIN_LAYER", False); + + /* 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_ATOM_SELECTION_TARGETS = XInternAtom(_ecore_x_disp, "TARGETS", False); + ECORE_X_ATOM_SELECTION_PRIMARY = XA_PRIMARY; + ECORE_X_ATOM_SELECTION_SECONDARY = XA_SECONDARY; + ECORE_X_ATOM_SELECTION_CLIPBOARD = XInternAtom(_ecore_x_disp, "CLIPBOARD", False); + ECORE_X_ATOM_SELECTION_PROP_PRIMARY = XInternAtom(_ecore_x_disp, "_ECORE_SELECTION_PRIMARY", False); + ECORE_X_ATOM_SELECTION_PROP_SECONDARY = XInternAtom(_ecore_x_disp, "_ECORE_SELECTION_SECONDARY", False); + ECORE_X_ATOM_SELECTION_PROP_CLIPBOARD = XInternAtom(_ecore_x_disp, "_ECORE_SELECTION_CLIPBOARD", False); + ECORE_X_ATOM_SELECTION_PROP_XDND = XInternAtom(_ecore_x_disp, "JXSelectionWindowProperty", False); + ECORE_X_ATOM_SELECTION_XDND = XInternAtom(_ecore_x_disp, "XdndSelection", False); + ECORE_X_ATOM_XDND_AWARE = XInternAtom(_ecore_x_disp, "XdndAware", False); + ECORE_X_ATOM_XDND_TYPE_LIST = XInternAtom(_ecore_x_disp, "XdndTypeList", False); + ECORE_X_ATOM_XDND_ENTER = XInternAtom(_ecore_x_disp, "XdndEnter", False); + ECORE_X_ATOM_XDND_POSITION = XInternAtom(_ecore_x_disp, "XdndPosition", False); + ECORE_X_ATOM_XDND_ACTION_COPY = XInternAtom(_ecore_x_disp, "XdndActionCopy", False); + ECORE_X_ATOM_XDND_ACTION_MOVE = XInternAtom(_ecore_x_disp, "XdndActionMove", False); + ECORE_X_ATOM_XDND_ACTION_PRIVATE = XInternAtom(_ecore_x_disp, "XdndActionPrivate", False); + ECORE_X_ATOM_XDND_ACTION_ASK = XInternAtom(_ecore_x_disp, "XdndActionAsk", False); + ECORE_X_ATOM_XDND_ACTION_LIST = XInternAtom(_ecore_x_disp, "XdndActionList", False); + ECORE_X_ATOM_XDND_ACTION_LINK = XInternAtom(_ecore_x_disp, "XdndActionLink", False); + ECORE_X_ATOM_XDND_ACTION_DESCRIPTION = XInternAtom(_ecore_x_disp, "XdndActionDescription", False); + ECORE_X_ATOM_XDND_PROXY = XInternAtom(_ecore_x_disp, "XdndProxy", False); + ECORE_X_ATOM_XDND_STATUS = XInternAtom(_ecore_x_disp, "XdndStatus", False); + ECORE_X_ATOM_XDND_LEAVE = XInternAtom(_ecore_x_disp, "XdndLeave", False); + ECORE_X_ATOM_XDND_DROP = XInternAtom(_ecore_x_disp, "XdndDrop", False); + ECORE_X_ATOM_XDND_FINISHED = XInternAtom(_ecore_x_disp, "XdndFinished", False); + + /* Initialize the globally defined xdnd atoms */ + ECORE_X_DND_ACTION_COPY = ECORE_X_ATOM_XDND_ACTION_COPY; + ECORE_X_DND_ACTION_MOVE = ECORE_X_ATOM_XDND_ACTION_MOVE; + ECORE_X_DND_ACTION_LINK = ECORE_X_ATOM_XDND_ACTION_LINK; + ECORE_X_DND_ACTION_ASK = ECORE_X_ATOM_XDND_ACTION_ASK; + ECORE_X_DND_ACTION_PRIVATE = ECORE_X_ATOM_XDND_ACTION_PRIVATE; + + _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_init_count++; + + _ecore_x_private_win = ecore_x_window_override_new(0, -77, -777, 123, 456); + + return _ecore_x_init_count; +} + +static int +_ecore_x_shutdown(int close_display) +{ + _ecore_x_init_count--; + if (_ecore_x_init_count > 0) return _ecore_x_init_count; + if (!_ecore_x_disp) return _ecore_x_init_count; + if (close_display) + XCloseDisplay(_ecore_x_disp); + else + close(ConnectionNumber(_ecore_x_disp)); + free(_ecore_x_event_handlers); + ecore_main_fd_handler_del(_ecore_x_fd_handler_handle); + ecore_event_filter_del(_ecore_x_filter_handler); + _ecore_x_fd_handler_handle = NULL; + _ecore_x_filter_handler = NULL; + _ecore_x_disp = NULL; + _ecore_x_event_handlers = NULL; + _ecore_x_selection_shutdown(); + _ecore_x_dnd_shutdown(); + if (_ecore_x_init_count < 0) _ecore_x_init_count = 0; + 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. + * @ingroup Ecore_X_Init_Group + */ +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 + */ +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 + */ +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 + */ +int +ecore_x_fd_get(void) +{ + return ConnectionNumber(_ecore_x_disp); +} + +/** + * 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 + */ +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 + */ +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 + */ +void +ecore_x_flush(void) +{ + XFlush(_ecore_x_disp); +} + +/** + * Flushes the command buffer and waits until all requests have been + * processed by the server. + * @ingroup Ecore_X_Flush_Group + */ +void +ecore_x_sync(void) +{ + 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. + */ +void +ecore_x_killall(Ecore_X_Window root) +{ + int screens; + int i, j; + + XGrabServer(_ecore_x_disp); + screens = ScreenCount(_ecore_x_disp); + + /* Tranverse window tree starting from root, and drag each + * before the firing squad */ + for (i = 0; i < screens; ++i) + { + Window root_r; + Window parent_r; + Window *children_r = NULL; + unsigned int num_children = 0; + + 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 woning window @p win + * + * @param win Window of the client to be killed + */ +void +ecore_x_kill(Ecore_X_Window win) +{ + XKillClient(_ecore_x_disp, win); +} + +/** + * Return the last event time + */ +Ecore_X_Time +ecore_x_current_time_get(void) +{ + return _ecore_x_event_last_time; +} + +static int +_ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + Display *d; + + d = data; + while (XPending(d)) + { + XEvent ev; + + XNextEvent(d, &ev); + if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num)) + { + if (_ecore_x_event_handlers[ev.type]) + _ecore_x_event_handlers[ev.type] (&ev); + } + } + return 1; +} + +static int +_ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) +{ + Display *d; + + d = data; + if (XPending(d)) return 1; + return 0; +} + +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 = 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; +} + +typedef struct _Ecore_X_Filter_Data Ecore_X_Filter_Data; + +struct _Ecore_X_Filter_Data +{ + int last_event_type; +}; + +static void * +_ecore_x_event_filter_start(void *data __UNUSED__) +{ + Ecore_X_Filter_Data *filter_data; + + filter_data = calloc(1, sizeof(Ecore_X_Filter_Data)); + return filter_data; +} + +static int +_ecore_x_event_filter_filter(void *data __UNUSED__, void *loop_data,int type, void *event __UNUSED__) +{ + Ecore_X_Filter_Data *filter_data; + + filter_data = loop_data; + if (!filter_data) return 1; + if (type == ECORE_X_EVENT_MOUSE_MOVE) + { + if ((filter_data->last_event_type) == ECORE_X_EVENT_MOUSE_MOVE) + { + filter_data->last_event_type = type; + return 0; + } + } + filter_data->last_event_type = type; + return 1; +} + +static void +_ecore_x_event_filter_end(void *data __UNUSED__, void *loop_data) +{ + Ecore_X_Filter_Data *filter_data; + + filter_data = loop_data; + if (filter_data) free(filter_data); +} + + + + + + + + + + + + + + + + + + + + + + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/* FIXME: these funcs need categorising */ +/*****************************************************************************/ + +/** + * 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. + */ +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; + + 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. + */ +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; + + 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. + */ +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; + + 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; +} + +/** + * 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. + */ +Ecore_X_Window * +ecore_x_window_root_list(int *num_ret) +{ + int num, i; + Ecore_X_Window *roots; + + if (!num_ret) return NULL; + *num_ret = 0; +#ifdef ECORE_XPRINT + { + Screen **ps = NULL; + int psnum = 0; + + num = ScreenCount(_ecore_x_disp); + 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((num - overlap) * sizeof(Window)); + 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 + 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 + return roots; +} + +Ecore_X_Window +ecore_x_window_root_first_get(void) +{ + int num; + Ecore_X_Window root, *roots = NULL; + + 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 __UNUSED__) +{ + if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) && + (ecore_x_error_code_get() == BadAccess)) + _ecore_x_window_manage_failed = 1; +} + +int +ecore_x_window_manage(Ecore_X_Window win) +{ + XWindowAttributes att; + + if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True) return 0; + 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 0; + } + return 1; +} + +void +ecore_x_window_container_manage(Ecore_X_Window win) +{ + XSelectInput(_ecore_x_disp, win, + ResizeRedirectMask | + SubstructureRedirectMask | + SubstructureNotifyMask); +} + +void +ecore_x_window_client_manage(Ecore_X_Window win) +{ + XSelectInput(_ecore_x_disp, win, + PropertyChangeMask | + ResizeRedirectMask | + FocusChangeMask | + ColormapChangeMask | + VisibilityChangeMask | + StructureNotifyMask + ); + XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); +} + +void +ecore_x_window_sniff(Ecore_X_Window win) +{ + XSelectInput(_ecore_x_disp, win, + PropertyChangeMask | + SubstructureNotifyMask); +} + +void +ecore_x_window_client_sniff(Ecore_X_Window win) +{ + XSelectInput(_ecore_x_disp, win, + PropertyChangeMask | + FocusChangeMask | + ColormapChangeMask | + VisibilityChangeMask | + StructureNotifyMask); + XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); +} + +/** + * Retrieves the atom value associated with the given name. + * @param name The given name. + * @return Associated atom value. + */ +Ecore_X_Atom +ecore_x_atom_get(const char *name) +{ + if (!_ecore_x_disp) return 0; + return XInternAtom(_ecore_x_disp, name, False); +} + + + + + + +int +ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret) +{ + XWindowAttributes att; + + if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return 0; + 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.your_event_mask; + att_ret->event_mask.no_propagate = att.do_not_propagate_mask; + att_ret->window_gravity = att.win_gravity; + att_ret->pixel_gravity = att.win_gravity; + att_ret->colormap = att.colormap; + return 1; +} + +void +ecore_x_window_save_set_add(Ecore_X_Window win) +{ + XAddToSaveSet(_ecore_x_disp, win); +} + +void +ecore_x_window_save_set_del(Ecore_X_Window win) +{ + XRemoveFromSaveSet(_ecore_x_disp, win); +} + +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; + + 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; +} + + + + + + +int +ecore_x_cursor_color_supported_get(void) +{ + return _ecore_x_xcursor; +} + +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 + 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] = (a << 24) | (r << 16) | (g << 8) | (b); + } + c = XcursorImageLoadCursor(_ecore_x_disp, xci); + XcursorImageDestroy(xci); + return c; + } + } + else +#endif + { + 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 = 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 = 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)); + v = (((d2 * 255) / (d1 + d2)) * 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, pmap, 0, &gcv); + XPutImage(_ecore_x_disp, pmap, gc, xim, 0, 0, 0, 0, w, h); + XFreeGC(_ecore_x_disp, gc); + + pix = 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; +} + +void +ecore_x_cursor_free(Ecore_X_Cursor c) +{ + 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()! + */ +Ecore_X_Cursor +ecore_x_cursor_shape_get(int shape) +{ + /* Shapes are defined in Ecore_X_Cursor.h */ + return XCreateFontCursor(_ecore_x_disp, shape); +} + +int +ecore_x_pointer_grab(Ecore_X_Window win) +{ + return XGrabPointer(_ecore_x_disp, win, False, + ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + None, None, CurrentTime); +} + +int +ecore_x_pointer_confine_grab(Ecore_X_Window win) +{ + return XGrabPointer(_ecore_x_disp, win, False, + ButtonPressMask | ButtonReleaseMask | + EnterWindowMask | LeaveWindowMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + win, None, CurrentTime); +} + +void +ecore_x_pointer_ungrab(void) +{ + XUngrabPointer(_ecore_x_disp, CurrentTime); +} + +int +ecore_x_pointer_warp(Ecore_X_Window win, int x, int y) +{ + return XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y); +} + +int +ecore_x_keyboard_grab(Ecore_X_Window win) +{ + return XGrabKeyboard(_ecore_x_disp, win, False, + GrabModeAsync, GrabModeAsync, + CurrentTime); +} + +void ecore_x_keyboard_ungrab(void) +{ + XUngrabKeyboard(_ecore_x_disp, CurrentTime); +} + +void +ecore_x_grab(void) +{ + _ecore_x_grab_count++; + + if (_ecore_x_grab_count == 1) + XGrabServer(_ecore_x_disp); +} + +void +ecore_x_ungrab(void) +{ + _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); + XSync(_ecore_x_disp, False); + } +} + +int _ecore_window_grabs_num = 0; +Window *_ecore_window_grabs = NULL; +int (*_ecore_window_grab_replay_func) (void *data, int event_type, void *event); +void *_ecore_window_grab_replay_data; + +void +ecore_x_passive_grab_replay_func_set(int (*func) (void *data, int event_type, void *event), void *data) +{ + _ecore_window_grab_replay_func = func; + _ecore_window_grab_replay_data = data; +} + +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; + + b = button; + if (b == 0) b = AnyButton; + m = 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++; + _ecore_window_grabs = realloc(_ecore_window_grabs, + _ecore_window_grabs_num * sizeof(Window)); + _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; + + 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--; + _ecore_window_grabs = realloc(_ecore_window_grabs, + _ecore_window_grabs_num * sizeof(Window)); + } + } +} + +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; + + b = button; + if (b == 0) b = AnyButton; + m = 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; + +void +ecore_x_window_key_grab(Ecore_X_Window win, char *key, + int mod, int any_mod) +{ + KeyCode keycode = 0; + KeySym keysym; + unsigned int m; + unsigned int locks[8]; + int i; + + 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 = 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, True, GrabModeSync, GrabModeAsync); + _ecore_key_grabs_num++; + _ecore_key_grabs = realloc(_ecore_key_grabs, + _ecore_key_grabs_num * sizeof(Window)); + _ecore_key_grabs[_ecore_key_grabs_num - 1] = win; +} + +void +_ecore_x_key_grab_remove(Ecore_X_Window win) +{ + int i, shuffle = 0; + + 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--; + _ecore_key_grabs = realloc(_ecore_key_grabs, + _ecore_key_grabs_num * sizeof(Window)); + } + } +} + +void +ecore_x_window_key_ungrab(Ecore_X_Window win, char *key, + int mod, int any_mod) +{ + KeyCode keycode = 0; + KeySym keysym; + unsigned int m; + unsigned int locks[8]; + int i; + + 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 = 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 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 !0 on success. + */ +int +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; + + 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); +} + +/** + * 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 20. + * + * @return !0 on success. + */ +int +ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type, + const void *data, int len) +{ + XEvent xev; + + 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); +} + +void +ecore_x_focus_reset(void) +{ + XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime); +} + +void +ecore_x_events_allow_all(void) +{ + XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime); +} + +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; +} + +void +ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y) +{ + Window rwin, cwin; + int rx, ry, wx, wy; + unsigned int mask; + + XQueryPointer(_ecore_x_disp, win, &rwin, &cwin, &rx, &ry, &wx, &wy, &mask); + if (x) *x = wx; + if (y) *y = wy; +} +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ diff --git a/ecore/src/lib/ecore_x/ecore_x_dnd.c b/ecore/src/lib/ecore_x/ecore_x_dnd.c new file mode 100644 index 0000000..84f3357 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_dnd.c @@ -0,0 +1,405 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +static Ecore_X_DND_Source *_source = NULL; +static Ecore_X_DND_Target *_target = NULL; +static int _ecore_x_dnd_init_count = 0; + +void +_ecore_x_dnd_init(void) +{ + if (!_ecore_x_dnd_init_count) + { + _source = calloc(1, sizeof(Ecore_X_DND_Source)); + _source->version = ECORE_X_DND_VERSION; + _source->win = None; + _source->dest = None; + _source->state = ECORE_X_DND_SOURCE_IDLE; + + _target = calloc(1, sizeof(Ecore_X_DND_Target)); + _target->win = None; + _target->source = None; + _target->state = ECORE_X_DND_TARGET_IDLE; + } + + _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; +} + +void +ecore_x_dnd_aware_set(Ecore_X_Window win, int on) +{ + Ecore_X_Atom prop_data = ECORE_X_DND_VERSION; + + 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); +} + +int +ecore_x_dnd_version_get(Ecore_X_Window win) +{ + unsigned char *prop_data; + int num; + + 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); + return version; + } + else + return 0; +} + +int +ecore_x_dnd_type_isset(Ecore_X_Window win, const char *type) +{ + int num, i, ret = 0; + unsigned char *data; + Ecore_X_Atom *atoms, atom; + + 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 = 1; + break; + } + } + + XFree(data); + return ret; +} + +void +ecore_x_dnd_type_set(Ecore_X_Window win, const char *type, int 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; + + 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; + + 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); +} + +Ecore_X_DND_Source * +_ecore_x_dnd_source_get(void) +{ + return _source; +} + +Ecore_X_DND_Target * +_ecore_x_dnd_target_get(void) +{ + return _target; +} + +int +ecore_x_dnd_begin(Ecore_X_Window source, unsigned char *data, int size) +{ + + if (!ecore_x_dnd_version_get(source)) + return 0; + + /* Take ownership of XdndSelection */ + if (!ecore_x_selection_xdnd_set(source, data, size)) + return 0; + + _source->win = source; + printf("source: 0x%x\n", source); + _source->state = ECORE_X_DND_SOURCE_DRAGGING; + _source->time = _ecore_x_event_last_time; + + /* Default Accepted Action: ask */ + _source->action = ECORE_X_ATOM_XDND_ACTION_ASK; + _source->accepted_action = None; + return 1; +} + +void +ecore_x_dnd_drop(void) +{ + XEvent xev; + + 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; + } + 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; + } +} + +void +ecore_x_dnd_send_status(int will_accept, int suppress, Ecore_X_Rectangle rectangle, Ecore_X_Atom action) +{ + XEvent xev; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) + return; + + 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); +} + +void +ecore_x_dnd_send_finished(void) +{ + XEvent xev; + + if (_target->state == ECORE_X_DND_TARGET_IDLE) + return; + + 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; +} + +void +_ecore_x_dnd_drag(int x, int y) +{ + XEvent xev; + Ecore_X_Window win; + + 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 */ + win = ecore_x_window_at_xy_get(x, y); + while ((win) && !(ecore_x_dnd_version_get(win))) + win = ecore_x_window_parent_get(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, num; + 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; + } + + /* 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; + } + } + + _source->dest = win; +} + diff --git a/ecore/src/lib/ecore_x/ecore_x_e.c b/ecore/src/lib/ecore_x/ecore_x_e.c new file mode 100644 index 0000000..398f4cc --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_e.c @@ -0,0 +1,37 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +/* + * OLD E hints + */ +#include "config.h" +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +/* + * Convenience macros + */ +#define _ATOM_GET(name) \ + XInternAtom(_ecore_x_disp, name, False) + +Ecore_X_Atom ECORE_X_ATOM_E_FRAME_SIZE = 0; + +void +ecore_x_e_init(void) +{ + ECORE_X_ATOM_E_FRAME_SIZE = _ATOM_GET("_E_FRAME_SIZE"); +} + +void +ecore_x_e_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb) +{ + unsigned int frames[4]; + + 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); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_error.c b/ecore/src/lib/ecore_x/ecore_x_error.c new file mode 100644 index 0000000..4307da0 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_error.c @@ -0,0 +1,95 @@ +#include "ecore_private.h" +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" + +static void _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; + +/** + * 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 + */ +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 + */ +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 + */ +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 + */ +int +ecore_x_error_code_get(void) +{ + return _error_code; +} + +void +_ecore_x_error_handler_init(void) +{ + XSetErrorHandler((XErrorHandler)_ecore_x_error_handle); + XSetIOErrorHandler((XIOErrorHandler)_ecore_x_io_error_handle); +} + +static void +_ecore_x_error_handle(Display *d, XErrorEvent *ev) +{ + if (d == _ecore_x_disp) + { + _error_request_code = ev->request_code; + _error_code = ev->error_code; + if (_error_func) _error_func(_error_data); + } +} + +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/ecore/src/lib/ecore_x/ecore_x_events.c b/ecore/src/lib/ecore_x/ecore_x_events.c new file mode 100644 index 0000000..5668442 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_events.c @@ -0,0 +1,1565 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_private.h" +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +#if 0 +static void _ecore_x_event_free_window_prop_name_class_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_title_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev); +static void _ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev); +#endif +static void _ecore_x_event_free_key_down(void *data, void *ev); +static void _ecore_x_event_free_key_up(void *data, void *ev); + +void +ecore_x_event_mask_set(Ecore_X_Window w, Ecore_X_Event_Mask mask) +{ + XWindowAttributes attr; + XSetWindowAttributes s_attr; + + 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); +} + +void +ecore_x_event_mask_unset(Ecore_X_Window w, Ecore_X_Event_Mask mask) +{ + XWindowAttributes attr; + XSetWindowAttributes s_attr; + + 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); +} + +#if 0 +static void +_ecore_x_event_free_window_prop_name_class_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Name_Class_Change *e; + + e = ev; + if (e->name) free(e->name); + if (e->clas) free(e->clas); + free(e); +} + +static void +_ecore_x_event_free_window_prop_title_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Title_Change *e; + + e = ev; + if (e->title) free(e->title); + free(e); +} + +static void +_ecore_x_event_free_window_prop_visible_title_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Visible_Title_Change *e; + + e = ev; + if (e->title) free(e->title); + free(e); +} + +static void +_ecore_x_event_free_window_prop_icon_name_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Icon_Name_Change *e; + + e = ev; + if (e->name) free(e->name); + free(e); +} + +static void +_ecore_x_event_free_window_prop_visible_icon_name_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e; + + e = ev; + if (e->name) free(e->name); + free(e); +} + +static void +_ecore_x_event_free_window_prop_client_machine_change(void *data, void *ev) +{ + Ecore_X_Event_Window_Prop_Client_Machine_Change *e; + + e = ev; + if (e->name) free(e->name); + free(e); +} +#endif + +static void +_ecore_x_event_free_key_down(void *data __UNUSED__, void *ev) +{ + Ecore_X_Event_Key_Down *e; + + e = ev; + if (e->keyname) free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static void +_ecore_x_event_free_key_up(void *data __UNUSED__, void *ev) +{ + Ecore_X_Event_Key_Up *e; + + e = ev; + if (e->keyname) free(e->keyname); + if (e->keysymbol) free(e->keysymbol); + if (e->key_compose) free(e->key_compose); + free(e); +} + +static void +_ecore_x_event_free_xdnd_enter(void *data __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 __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); +} + +void +_ecore_x_event_handle_key_press(XEvent *xevent) +{ + Ecore_X_Event_Key_Down *e; + char *keyname; + int val; + char buf[256]; + KeySym sym; + XComposeStatus stat; + + e = calloc(1, sizeof(Ecore_X_Event_Key_Down)); + if (!e) return; + keyname = XKeysymToString(XKeycodeToKeysym(xevent->xkey.display, + xevent->xkey.keycode, 0)); + if (!keyname) + { + snprintf(buf, sizeof(buf), "Keycode-%i", xevent->xkey.keycode); + keyname = buf; + } + e->keyname = strdup(keyname); + if (!e->keyname) + { + free(e); + return; + } + val = XLookupString((XKeyEvent *)xevent, buf, sizeof(buf), &sym, &stat); + if (val > 0) + { + buf[val] = 0; + e->key_compose = ecore_txt_convert("LATIN1", "UTF-8", buf); + } + else e->key_compose = NULL; + keyname = XKeysymToString(sym); + if (keyname) e->keysymbol = strdup(keyname); + else e->keysymbol = strdup(e->keyname); + if (!e->keysymbol) + { + if (e->keyname) free(e->keyname); + if (e->key_compose) free(e->key_compose); + free(e); + return; + } + if (xevent->xkey.subwindow) e->win = xevent->xkey.subwindow; + else e->win = xevent->xkey.window; + e->event_win = xevent->xkey.window; + e->time = xevent->xkey.time; + e->modifiers = xevent->xkey.state; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_KEY_DOWN, e, _ecore_x_event_free_key_down, NULL); +} + +void +_ecore_x_event_handle_key_release(XEvent *xevent) +{ + Ecore_X_Event_Key_Up *e; + char *keyname; + int val; + char buf[256]; + KeySym sym; + XComposeStatus stat; + + e = calloc(1, sizeof(Ecore_X_Event_Key_Up)); + if (!e) return; + keyname = XKeysymToString(XKeycodeToKeysym(xevent->xkey.display, + xevent->xkey.keycode, 0)); + if (!keyname) + { + snprintf(buf, sizeof(buf), "Keycode-%i", xevent->xkey.keycode); + keyname = buf; + } + e->keyname = strdup(keyname); + if (!e->keyname) + { + free(e); + return; + } + val = XLookupString((XKeyEvent *)xevent, buf, sizeof(buf), &sym, &stat); + if (val > 0) + { + buf[val] = 0; + e->key_compose = ecore_txt_convert("LATIN1", "UTF-8", buf); + } + else e->key_compose = NULL; + keyname = XKeysymToString(sym); + if (keyname) e->keysymbol = strdup(keyname); + else e->keysymbol = strdup(e->keyname); + if (!e->keysymbol) + { + if (e->keyname) free(e->keyname); + if (e->key_compose) free(e->key_compose); + free(e); + return; + } + if (xevent->xkey.subwindow) e->win = xevent->xkey.subwindow; + else e->win = xevent->xkey.window; + e->event_win = xevent->xkey.window; + e->time = xevent->xkey.time; + e->modifiers = xevent->xkey.state; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_KEY_UP, e, _ecore_x_event_free_key_up, NULL); +} + +void +_ecore_x_event_handle_button_press(XEvent *xevent) +{ + static Window last_win = 0; + static Window last_last_win = 0; + static Window last_event_win = 0; + static Window last_last_event_win = 0; + static Time last_time = 0; + static Time last_last_time = 0; + int did_triple = 0; + int i; + + if ((xevent->xbutton.button > 3) && (xevent->xbutton.button < 6)) + { + Ecore_X_Event_Mouse_Wheel *e; + + e = malloc(sizeof(Ecore_X_Event_Mouse_Wheel)); + + if (!e) + return; + + e->modifiers = 0; + e->direction = 0; + e->z = 0; + if (xevent->xbutton.button == 4) e->z = -1; + else if (xevent->xbutton.button == 5) e->z = 1; + 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->win = xevent->xbutton.subwindow; + else + e->win = xevent->xbutton.window; + + e->event_win = xevent->xbutton.window; + e->time = xevent->xbutton.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_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)) + { + int replay = 0; + + if (_ecore_window_grab_replay_func) + replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data, + ECORE_X_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_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = xevent->xbutton.state; + 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->win = xevent->xbutton.subwindow; + else e->win = xevent->xbutton.window; + e->event_win = xevent->xbutton.window; + e->time = xevent->xbutton.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_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_Button_Down *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Button_Down)); + if (!e) return; + e->button = xevent->xbutton.button; + e->modifiers = xevent->xbutton.state; + 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->win = xevent->xbutton.subwindow; + else e->win = xevent->xbutton.window; + e->event_win = xevent->xbutton.window; + e->time = xevent->xbutton.time; + if (e->win == e->event_win) + { + if (((int)(e->time - last_time) <= + (int)(1000 * _ecore_x_double_click_time)) && + (e->win == last_win) + && (e->event_win == last_event_win) + ) + e->double_click = 1; + if (((int)(e->time - last_last_time) <= + (int)(2 * 1000 * _ecore_x_double_click_time)) && + (e->win == last_win) && (e->win == last_last_win) + && (e->event_win == last_event_win) && (e->event_win == last_last_event_win) + ) + { + did_triple = 1; + e->triple_click = 1; + } + } + _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_BUTTON_DOWN, 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)) + { + int replay = 0; + + if (_ecore_window_grab_replay_func) + replay = _ecore_window_grab_replay_func(_ecore_window_grab_replay_data, + ECORE_X_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; + } + } + if (e->win == e->event_win) + { + if (did_triple) + { + last_win = 0; + last_last_win = 0; + last_event_win = 0; + last_last_event_win = 0; + last_time = 0; + last_last_time = 0; + } + else + { + last_last_win = last_win; + if (xevent->xbutton.subwindow) + last_win = xevent->xbutton.subwindow; + else + last_win = xevent->xbutton.window; + last_last_event_win = last_event_win; + last_event_win = xevent->xbutton.window; + last_last_time = last_time; + last_time = xevent->xbutton.time; + } + } + } + } +} + +void +_ecore_x_event_handle_button_release(XEvent *xevent) +{ + /* filter out wheel buttons */ + if (xevent->xbutton.button <= 3) + { + { + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = xevent->xbutton.state; + 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->win = xevent->xbutton.subwindow; + else e->win = xevent->xbutton.window; + e->event_win = xevent->xbutton.window; + e->time = xevent->xbutton.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_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_Button_Up *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Button_Up)); + if (!e) return; + e->button = xevent->xbutton.button; + e->modifiers = xevent->xbutton.state; + 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->win = xevent->xbutton.subwindow; + else e->win = xevent->xbutton.window; + e->event_win = xevent->xbutton.window; + e->time = xevent->xbutton.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_BUTTON_UP, e, NULL, NULL); + } + } +} + +void +_ecore_x_event_handle_motion_notify(XEvent *xevent) +{ + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->modifiers = xevent->xmotion.state; + e->x = xevent->xmotion.x; + e->y = xevent->xmotion.y; + e->root.x = xevent->xmotion.x_root; + e->root.y = xevent->xmotion.y_root; + if (xevent->xmotion.subwindow) e->win = xevent->xmotion.subwindow; + else e->win = xevent->xmotion.window; + e->event_win = xevent->xmotion.window; + e->time = xevent->xmotion.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; + + /* Xdnd handling */ + _ecore_x_dnd_drag(e->root.x, e->root.y); + + ecore_event_add(ECORE_X_EVENT_MOUSE_MOVE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_enter_notify(XEvent *xevent) +{ + { + Ecore_X_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->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->event_win = xevent->xcrossing.window; + 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_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_In *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_In)); + if (!e) return; + e->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->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_Event_Mouse_Move *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Move)); + if (!e) return; + e->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->event_win = xevent->xcrossing.window; + 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_MOVE, e, NULL, NULL); + } + { + Ecore_X_Event_Mouse_Out *e; + + e = calloc(1, sizeof(Ecore_X_Event_Mouse_Out)); + if (!e) return; + e->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->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; + + 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; + + 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 __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_expose(XEvent *xevent) +{ + Ecore_X_Event_Window_Damage *e; + + 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; + 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; + + 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; + ecore_event_add(ECORE_X_EVENT_WINDOW_DAMAGE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_visibility_notify(XEvent *xevent) +{ + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Create)); + e->win = xevent->xcreatewindow.window; + if (xevent->xcreatewindow.override_redirect) + e->override = 1; + else + e->override = 0; + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Destroy)); + if (!e) return; + e->win = xevent->xdestroywindow.window; + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Hide)); + if (!e) return; + e->win = xevent->xunmap.window; + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Show)); + if (!e) return; + e->win = xevent->xmap.window; + 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; + + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Reparent)); + if (!e) return; + e->win = xevent->xreparent.window; + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Configure)); + if (!e) return; + e->win = xevent->xconfigure.window; + 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; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Configure_Request)); + if (!e) return; + e->win = xevent->xconfigurerequest.window; + 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 __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_resize_request(XEvent *xevent) +{ + Ecore_X_Event_Window_Resize_Request *e; + + 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 __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_circulate_request(XEvent *xevent __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_property_notify(XEvent *xevent) +{ +#if 0 /* for now i disabled this. nice idea though this is - it leaves a lot + * to be desired for efficiency that is better left to the app layer + */ + if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLASS) + { + Ecore_X_Event_Window_Prop_Name_Class_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Name_Class_Change)); + if (!e) return; + ecore_x_window_prop_name_class_get(xevent->xproperty.window, + &(e->name), &(e->clas)); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_NAME_CLASS_CHANGE, e, _ecore_x_event_free_window_prop_name_class_change, NULL); + } + else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_NAME)) + { + Ecore_X_Event_Window_Prop_Title_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Title_Change)); + if (!e) return; + e->title = ecore_x_window_prop_title_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_title_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_NAME) + { + Ecore_X_Event_Window_Prop_Visible_Title_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Title_Change)); + if (!e) return; + e->title = ecore_x_window_prop_visible_title_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_TITLE_CHANGE, e, _ecore_x_event_free_window_prop_visible_title_change, NULL); + } + else if ((xevent->xproperty.atom == ECORE_X_ATOM_WM_ICON_NAME) || (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_ICON_NAME)) + { + Ecore_X_Event_Window_Prop_Icon_Name_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Icon_Name_Change)); + if (!e) return; + e->name = ecore_x_window_prop_icon_name_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_icon_name_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME) + { + Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Visible_Icon_Name_Change)); + if (!e) return; + e->name = ecore_x_window_prop_visible_icon_name_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_VISIBLE_ICON_NAME_CHANGE, e, _ecore_x_event_free_window_prop_visible_icon_name_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_WM_CLIENT_MACHINE) + { + Ecore_X_Event_Window_Prop_Client_Machine_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Client_Machine_Change)); + if (!e) return; + e->name = ecore_x_window_prop_client_machine_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_CLIENT_MACHINE_CHANGE, e, _ecore_x_event_free_window_prop_client_machine_change, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_PID) + { + Ecore_X_Event_Window_Prop_Pid_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Pid_Change)); + if (!e) return; + e->pid = ecore_x_window_prop_pid_get(xevent->xproperty.window); + e->time = xevent->xproperty.time; + _ecore_x_event_last_time = e->time; + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL); + } + else if (xevent->xproperty.atom == ECORE_X_ATOM_NET_WM_DESKTOP) + { + Ecore_X_Event_Window_Prop_Desktop_Change *e; + + e = calloc(1, sizeof(Ecore_X_Event_Window_Prop_Desktop_Change)); + if (!e) return; + e->desktop = ecore_x_window_prop_desktop_get(xevent->xproperty.window); + ecore_event_add(ECORE_X_EVENT_WINDOW_PROP_PID_CHANGE, e, NULL, NULL); + } + else +#endif + { + 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; + + if (!(d = _ecore_x_selection_get(xevent->xselectionclear.selection))) + return; + if (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; + 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 + e->selection = ECORE_X_SELECTION_CLIPBOARD; + ecore_event_add(ECORE_X_EVENT_SELECTION_CLEAR, e, NULL, NULL); + +} + +void +_ecore_x_event_handle_selection_request(XEvent *xevent) +{ + Ecore_X_Selection_Intern *sd; + XSelectionEvent xnotify; + XEvent xev; + void *data; + + xnotify.type = SelectionNotify; + xnotify.display = xevent->xselectionrequest.display; + xnotify.requestor = xevent->xselectionrequest.requestor; + xnotify.selection = xevent->xselectionrequest.selection; + xnotify.target = xevent->xselectionrequest.target; + xnotify.time = CurrentTime; + xnotify.send_event = True; + xnotify.serial = 0; + + if ((sd = _ecore_x_selection_get(xnotify.selection)) + && (sd->win == xevent->xselectionrequest.owner)) + { + if (!_ecore_x_selection_convert(xnotify.selection, xnotify.target, + &data) == -1) + { + /* Refuse selection, conversion to requested target failed */ + xnotify.property = None; + } + else + { + /* FIXME: This does not properly handle large data transfers */ + ecore_x_window_prop_property_set(xevent->xselectionrequest.requestor, + xevent->xselectionrequest.property, + xevent->xselectionrequest.target, + 8, data, sd->length); + xnotify.property = xevent->xselectionrequest.property; + free(data); + } + } + else + { + xnotify.property = None; + return; + } + + xev.xselection = xnotify; + XSendEvent(xevent->xselectionrequest.display, + xevent->xselectionrequest.requestor, False, 0, &xev); +} + +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; + + selection = xevent->xselection.selection; + + if (xevent->xselection.target == ECORE_X_ATOM_SELECTION_TARGETS) + { + if (!ecore_x_window_prop_property_get(xevent->xselection.requestor, + xevent->xselection.property, + XA_ATOM, 32, &data, &num_ret)) + return; + } + else + { + if (!ecore_x_window_prop_property_get(xevent->xselection.requestor, + xevent->xselection.property, + AnyPropertyType, 8, &data, &num_ret)) + return; + } + + e = calloc(1, sizeof(Ecore_X_Event_Selection_Notify)); + e->win = xevent->xselection.requestor; + e->time = xevent->xselection.time; + 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 + { + free(e); + return; + } + e->data = _ecore_x_selection_parse(e->target, data, num_ret); + + 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; + + e = calloc(1,sizeof(Ecore_X_Event_Window_Colormap)); + e->win = xevent->xcolormap.window; + e->cmap = xevent->xcolormap.colormap; + e->time = _ecore_x_event_last_time; + if (xevent->xcolormap.state == ColormapInstalled) + e->installed = 1; + else + e->installed = 0; + ecore_event_add(ECORE_X_EVENT_WINDOW_COLORMAP, e, NULL, NULL); +} + +void +_ecore_x_event_handle_client_message(XEvent *xevent) +{ + /* 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; + unsigned long three; + + e = calloc(1, sizeof(Ecore_X_Event_Xdnd_Enter)); + if (!e) return; + + target = _ecore_x_dnd_target_get(); + target->state = ECORE_X_DND_TARGET_ENTERED; + + target = _ecore_x_dnd_target_get(); + 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) + { + printf("DND: Requested version %d, we only support up to %d\n", target->version, + ECORE_X_DND_VERSION); + return; + } + + if ((three = 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; + if (!(ecore_x_window_prop_property_get(target->source, + ECORE_X_ATOM_XDND_TYPE_LIST, + XA_ATOM, + 32, + &data, + &num_ret))) + { + printf("DND: Could not fetch data type list from source window, aborting.\n"); + return; + } + types = (Ecore_X_Atom *)data; + e->types = calloc(num_ret, sizeof(char *)); + 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 *)); + 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; + + target = _ecore_x_dnd_target_get(); + if ((target->source != 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; + + 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; + + target = _ecore_x_dnd_target_get(); + if ((target->source != 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; + + 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; + int completed = 1; + + 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)) + { + /* Target successfully performed drop action */ + ecore_x_selection_xdnd_clear(); + source->state = ECORE_X_DND_SOURCE_IDLE; + } + else + { + completed = 0; + 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; + } + e->state[0] = _ecore_x_netwm_state_get(xevent->xclient.data.l[1]); + if (e->state[0] == ECORE_X_WINDOW_STATE_UNKNOWN) + { + char *name; + name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[1]); + if (name) + printf("Unknown state: %s\n", 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; + name = XGetAtomName(_ecore_x_disp, xevent->xclient.data.l[2]); + if (name) + printf("Unknown state: %s\n", 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) + && (xevent->xclient.data.l[0] == ECORE_X_ATOM_NET_WM_PING) + && (xevent->xclient.format == 32)) + { + Ecore_X_Event_Ping *e; + + 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]; + + ecore_event_add(ECORE_X_EVENT_PING, e, NULL, NULL); + } + 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 __UNUSED__) +{ + /* FIXME: handle this event type */ +} + +void +_ecore_x_event_handle_shape_change(XEvent *xevent) +{ + XShapeEvent *shape_event; + Ecore_X_Event_Window_Shape *e; + + 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; + ecore_event_add(ECORE_X_EVENT_WINDOW_SHAPE, e, NULL, NULL); +} + +void +_ecore_x_event_handle_sync_counter(XEvent *xevent) +{ + XSyncCounterNotifyEvent *sync_counter_event; + Ecore_X_Event_Sync_Counter *e; + + 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; + + 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); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_gc.c b/ecore/src/lib/ecore_x/ecore_x_gc.c new file mode 100644 index 0000000..99ff0e1 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_gc.c @@ -0,0 +1,29 @@ +#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. + * @return The new default graphics context. + */ +Ecore_X_GC +ecore_x_gc_new(Ecore_X_Drawable draw) +{ + XGCValues gcv; + + if (!draw) draw = DefaultRootWindow(_ecore_x_disp); + return XCreateGC(_ecore_x_disp, draw, 0, &gcv); +} + +/** + * Deletes and frees the given graphics context. + * @param gc The given graphics context. + */ +void +ecore_x_gc_del(Ecore_X_GC gc) +{ + XFreeGC(_ecore_x_disp, gc); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_icccm.c b/ecore/src/lib/ecore_x/ecore_x_icccm.c new file mode 100644 index 0000000..a29a83a --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_icccm.c @@ -0,0 +1,1082 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +/* + * Various ICCCM related functions. + * + * This is ALL the code involving anything ICCCM related. for both WM and + * client. + */ +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +/* Atoms */ +Ecore_X_Atom ECORE_X_ATOM_WM_STATE = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_DELETE_WINDOW = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_TAKE_FOCUS = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_PROTOCOLS = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_CLASS = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_COMMAND = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_ICON_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_MACHINE = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_CHANGE_STATE = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_COLORMAP_WINDOWS = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_WINDOW_ROLE = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_HINTS = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_NORMAL_HINTS = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_CLIENT_LEADER = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_TRANSIENT_FOR = 0; +Ecore_X_Atom ECORE_X_ATOM_WM_SAVE_YOURSELF = 0; + +void +ecore_x_icccm_init(void) +{ + + ECORE_X_ATOM_WM_STATE = XInternAtom(_ecore_x_disp, "WM_STATE", False); + ECORE_X_ATOM_WM_DELETE_WINDOW = + XInternAtom(_ecore_x_disp, "WM_DELETE_WINDOW", False); + ECORE_X_ATOM_WM_TAKE_FOCUS = + XInternAtom(_ecore_x_disp, "WM_TAKE_FOCUS", False); + ECORE_X_ATOM_WM_PROTOCOLS = + XInternAtom(_ecore_x_disp, "WM_PROTOCOLS", False); + ECORE_X_ATOM_WM_CLASS = XInternAtom(_ecore_x_disp, "WM_CLASS", False); + ECORE_X_ATOM_WM_NAME = XInternAtom(_ecore_x_disp, "WM_NAME", False); + ECORE_X_ATOM_WM_COMMAND = XInternAtom(_ecore_x_disp, "WM_COMMAND", False); + ECORE_X_ATOM_WM_ICON_NAME = + XInternAtom(_ecore_x_disp, "WM_ICON_NAME", False); + ECORE_X_ATOM_WM_CLIENT_MACHINE = + XInternAtom(_ecore_x_disp, "WM_CLIENT_MACHINE", False); + ECORE_X_ATOM_WM_CHANGE_STATE = + XInternAtom(_ecore_x_disp, "WM_CHANGE_STATE", False); + ECORE_X_ATOM_WM_COLORMAP_WINDOWS = + XInternAtom(_ecore_x_disp, "WM_COLORMAP_WINDOWS", False); + ECORE_X_ATOM_WM_WINDOW_ROLE = + XInternAtom(_ecore_x_disp, "WM_WINDOW_ROLE", False); + ECORE_X_ATOM_WM_HINTS = XInternAtom(_ecore_x_disp, "WM_HINTS", False); + ECORE_X_ATOM_WM_NORMAL_HINTS = + XInternAtom(_ecore_x_disp, "WM_NORMAL_HINTS", False); + ECORE_X_ATOM_WM_CLIENT_LEADER = + XInternAtom(_ecore_x_disp, "WM_CLIENT_LEADER", False); + ECORE_X_ATOM_WM_TRANSIENT_FOR = + XInternAtom(_ecore_x_disp, "WM_TRANSIENT_FOR", False); + ECORE_X_ATOM_WM_SAVE_YOURSELF = + XInternAtom(_ecore_x_disp, "WM_SAVE_YOURSELF", False); +} + +void +ecore_x_icccm_state_set(Ecore_X_Window win, Ecore_X_Window_State_Hint state) +{ + unsigned long c[2]; + + 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); +} + +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; + + 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; +} + +void +ecore_x_icccm_delete_window_send(Ecore_X_Window win, Ecore_X_Time t) +{ + 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); +} + +void +ecore_x_icccm_take_focus_send(Ecore_X_Window win, Ecore_X_Time t) +{ + 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); +} + +void +ecore_x_icccm_save_yourself_send(Ecore_X_Window win, Ecore_X_Time t) +{ + 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); +} + +void +ecore_x_icccm_move_resize_send(Ecore_X_Window win, int x, int y, int w, int h) +{ + XEvent ev; + + 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); +} + +void +ecore_x_icccm_hints_set(Ecore_X_Window win, + int 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, int is_urgent) +{ + XWMHints *hints; + + hints = XAllocWMHints(); + if (!hints) + return; + + 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); +} + +int +ecore_x_icccm_hints_get(Ecore_X_Window win, + int *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, int *is_urgent) +{ + XWMHints *hints; + + if (accepts_focus) + *accepts_focus = 0; + 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 = 0; + hints = XGetWMHints(_ecore_x_disp, win); + if (hints) + { + if ((hints->flags & InputHint) && (accepts_focus)) + { + if (hints->input) + *accepts_focus = 1; + else + *accepts_focus = 0; + } + 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 = 1; + } + XFree(hints); + return 1; + } + return 0; +} + +void +ecore_x_icccm_size_pos_hints_set(Ecore_X_Window win, + int 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; + + 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); +} + +int +ecore_x_icccm_size_pos_hints_get(Ecore_X_Window win, + int *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; + + if (!XGetWMNormalHints(_ecore_x_disp, win, &hint, &mask)) + return 0; + + if ((hint.flags & USPosition) || ((hint.flags & PPosition))) + { + if (request_pos) + *request_pos = 1; + } + else + { + if (request_pos) + *request_pos = 0; + } + 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 1; +} + +void +ecore_x_icccm_title_set(Ecore_X_Window win, const char *t) +{ + char *list[1]; + XTextProperty xprop; + int ret; + + xprop.value = NULL; +#ifdef X_HAVE_UTF8_STRING + list[0] = strdup(t); + ret = + Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, XUTF8StringStyle, + &xprop); +#else + list[0] = strdup(t); + ret = + XmbTextListToTextProperty(_ecore_x_disp, list, 1, XStdICCTextStyle, + &xprop); +#endif + 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]); +} + +char * +ecore_x_icccm_title_get(Ecore_X_Window win) +{ + XTextProperty xprop; + + 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 + ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop, + &list, &num); +#endif + + 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 or unset a wm protocol property. + * @param win The Window + * @param protocol The protocol to enable/disable + * @param on On/Off + */ +void +ecore_x_icccm_protocol_set(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol, int 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; + + 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. + */ +int +ecore_x_icccm_protocol_isset(Ecore_X_Window win, Ecore_X_WM_Protocol protocol) +{ + Atom proto, *protos = NULL; + int i, ret = 0, protos_count = 0; + + /* check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return 0; + + proto = _ecore_x_atoms_wm_protocols[protocol]; + + if (!XGetWMProtocols(_ecore_x_disp, win, &protos, &protos_count)) + return 0; + + for (i = 0; i < protos_count; i++) + if (protos[i] == proto) + { + ret = 1; + 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 + */ +void +ecore_x_icccm_name_class_set(Ecore_X_Window win, const char *n, const char *c) +{ + XClassHint *xch; + + xch = XAllocClassHint(); + if (!xch) + return; + 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 + */ +void +ecore_x_icccm_name_class_get(Ecore_X_Window win, char **n, char **c) +{ + XClassHint xch; + + 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. + */ +char * +ecore_x_icccm_client_machine_get(Ecore_X_Window win) +{ + char *name; + + 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. + */ +void +ecore_x_icccm_command_set(Ecore_X_Window win, int argc, char **argv) +{ + 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. + */ +void +ecore_x_icccm_command_get(Ecore_X_Window win, int *argc, char ***argv) +{ + XGetCommand(_ecore_x_disp, win, argv, argc); +} + +/** + * Set a window icon name. + * @param win The window + * @param t The icon name string + * + * Set a window icon name + */ +void +ecore_x_icccm_icon_name_set(Ecore_X_Window win, const char *t) +{ + char *list[1]; + XTextProperty xprop; + int ret; + + xprop.value = NULL; +#ifdef X_HAVE_UTF8_STRING + list[0] = strdup(t); + ret = Xutf8TextListToTextProperty(_ecore_x_disp, list, 1, + XUTF8StringStyle, &xprop); +#else + list[0] = strdup(t); + ret = XmbTextListToTextProperty(_ecore_x_disp, list, 1, + XStdICCTextStyle, &xprop); +#endif + 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. + */ +char * +ecore_x_icccm_icon_name_get(Ecore_X_Window win) +{ + XTextProperty xprop; + + 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 + ret = XmbTextPropertyToTextList(_ecore_x_disp, &xprop, + &list, &num); +#endif + + 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 + */ +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; + + 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. + */ +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; + + 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 + */ +void +ecore_x_icccm_transient_for_set(Ecore_X_Window win, Ecore_X_Window forwin) +{ + XSetTransientForHint(_ecore_x_disp, win, forwin); +} + +/** + * Remove the transient_for setting from a window. + * @param The window + */ +void +ecore_x_icccm_transient_for_unset(Ecore_X_Window win) +{ + 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. + */ +Ecore_X_Window +ecore_x_icccm_transient_for_get(Ecore_X_Window win) +{ + Window forwin; + + 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 + */ +void +ecore_x_icccm_window_role_set(Ecore_X_Window win, const char *role) +{ + 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. + */ +char * +ecore_x_icccm_window_role_get(Ecore_X_Window win) +{ + 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. + */ +void +ecore_x_icccm_client_leader_set(Ecore_X_Window win, Ecore_X_Window l) +{ + ecore_x_window_prop_property_set(win, + ECORE_X_ATOM_WM_CLIENT_LEADER, + XA_WINDOW, 32, &l, 1); +} + +/** + * Get the window's client leader. + * @param win The window + * @return The window's client leader window, or 0 if unset */ +Ecore_X_Window +ecore_x_icccm_client_leader_get(Ecore_X_Window win) +{ + unsigned char *data; + int num; + + if (ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_WM_CLIENT_LEADER, + XA_WINDOW, 32, &data, &num)) + { + if (data) + { + Ecore_X_Window wlead; + + wlead = *((Ecore_X_Window *)data); + free(data); + return wlead; + } + } + return 0; +} + +void +ecore_x_icccm_iconic_request_send(Ecore_X_Window win, Ecore_X_Window root) +{ + XEvent xev; + + if (!win) return; + 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/ecore/src/lib/ecore_x/ecore_x_mwm.c b/ecore/src/lib/ecore_x/ecore_x_mwm.c new file mode 100644 index 0000000..caf9e49 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_mwm.c @@ -0,0 +1,93 @@ +/* + * Various MWM related functions. + * + * This is ALL the code involving anything MWM related. for both WM and + * client. + */ +#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; + +/* Atoms */ +Ecore_X_Atom ECORE_X_ATOM_MOTIF_WM_HINTS = 0; + +int +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; + int ret; + + ret = 0; + if (!ecore_x_window_prop_property_get(win, + ECORE_X_ATOM_MOTIF_WM_HINTS, + ECORE_X_ATOM_MOTIF_WM_HINTS, + 32, &p, &num)) + return 0; + 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 = 1; + } + free(mwmhints); + } + return ret; +} + +void +ecore_x_mwm_borderless_set(Ecore_X_Window win, int borderless) +{ + unsigned int data[5] = {0, 0, 0, 0, 0}; + + data[0] = 2; /* just set the decorations hint! */ + 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); +} + diff --git a/ecore/src/lib/ecore_x/ecore_x_netwm.c b/ecore/src/lib/ecore_x/ecore_x_netwm.c new file mode 100644 index 0000000..76d970e --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_netwm.c @@ -0,0 +1,1238 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +/* + * _NET_WM... aka Extended Window Manager Hint (EWMH) functions. + */ +#include "config.h" +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +/* + * Convenience macros + */ +#define _ATOM_GET(name) \ + XInternAtom(_ecore_x_disp, name, False) + +#define _ATOM_SET_UTF8_STRING(win, atom, string) \ + XChangeProperty(_ecore_x_disp, win, atom, ECORE_X_ATOM_UTF8_STRING, 8, PropModeReplace, \ + (unsigned char *)string, strlen(string)) +#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) +#define _ATOM_SET_WINDOW(win, atom, p_wins, cnt) \ + XChangeProperty(_ecore_x_disp, win, atom, XA_WINDOW, 32, PropModeReplace, \ + (unsigned char *)p_wins, cnt) +#define _ATOM_SET_ATOM(win, atom, p_atom, cnt) \ + XChangeProperty(_ecore_x_disp, win, atom, XA_ATOM, 32, PropModeReplace, \ + (unsigned char *)p_atom, cnt) +#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 UTF-8 string property + */ +static void +_ecore_x_window_prop_string_utf8_set(Ecore_X_Window win, Ecore_X_Atom atom, + const char *str) +{ + _ATOM_SET_UTF8_STRING(win, atom, 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; +} + +/* + * Root window NetWM hints. + */ +Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTED = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_VIRTUAL_ROOTS = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_NAMES = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_GEOMETRY = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_VIEWPORT = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_DESKTOP_LAYOUT = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WORKAREA = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_CURRENT_DESKTOP = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_SHOWING_DESKTOP = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_CLIENT_LIST_STACKING = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_ACTIVE_WINDOW = 0; + +/* + * Client message types. + */ +Ecore_X_Atom ECORE_X_ATOM_NET_CLOSE_WINDOW = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_MOVERESIZE = 0; + +/* + * Pagers + */ +Ecore_X_Atom ECORE_X_ATOM_NET_MOVERESIZE_WINDOW = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_RESTACK_WINDOW = 0; + +/* + * Application window specific NetWM hints. + */ +Ecore_X_Atom ECORE_X_ATOM_NET_WM_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_DESKTOP = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STRUT_PARTIAL = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON_GEOMETRY = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ICON = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_PID = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_HANDLED_ICONS = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_USER_TIME = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MOVE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_RESIZE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_SHADE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_STICK = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_ACTION_CLOSE = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MODAL = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_STICKY = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SHADED = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_HIDDEN = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_ABOVE = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_BELOW = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_WM_WINDOW_OPACITY = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_FRAME_EXTENTS = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS = 0; + +Ecore_X_Atom ECORE_X_ATOM_NET_WM_PING = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST = 0; +Ecore_X_Atom ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER = 0; + +void +ecore_x_netwm_init(void) +{ + ECORE_X_ATOM_NET_SUPPORTED = _ATOM_GET("_NET_SUPPORTED"); + ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK = _ATOM_GET("_NET_SUPPORTING_WM_CHECK"); + + ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS = _ATOM_GET("_NET_NUMBER_OF_DESKTOPS"); + ECORE_X_ATOM_NET_VIRTUAL_ROOTS = _ATOM_GET("_NET_VIRTUAL_ROOTS"); + ECORE_X_ATOM_NET_DESKTOP_NAMES = _ATOM_GET("_NET_DESKTOP_NAMES"); + ECORE_X_ATOM_NET_DESKTOP_GEOMETRY = _ATOM_GET("_NET_DESKTOP_GEOMETRY"); + ECORE_X_ATOM_NET_DESKTOP_VIEWPORT = _ATOM_GET("_NET_DESKTOP_VIEWPORT"); + ECORE_X_ATOM_NET_DESKTOP_LAYOUT = _ATOM_GET("_NET_DESKTOP_LAYOUT"); + ECORE_X_ATOM_NET_WORKAREA = _ATOM_GET("_NET_WORKAREA"); + + ECORE_X_ATOM_NET_CURRENT_DESKTOP = _ATOM_GET("_NET_CURRENT_DESKTOP"); + ECORE_X_ATOM_NET_SHOWING_DESKTOP = _ATOM_GET("_NET_SHOWING_DESKTOP"); + + ECORE_X_ATOM_NET_CLIENT_LIST = _ATOM_GET("_NET_CLIENT_LIST"); + ECORE_X_ATOM_NET_CLIENT_LIST_STACKING = + _ATOM_GET("_NET_CLIENT_LIST_STACKING"); + ECORE_X_ATOM_NET_ACTIVE_WINDOW = _ATOM_GET("_NET_ACTIVE_WINDOW"); + + ECORE_X_ATOM_NET_CLOSE_WINDOW = _ATOM_GET("_NET_CLOSE_WINDOW"); + ECORE_X_ATOM_NET_WM_MOVERESIZE = _ATOM_GET("_NET_WM_MOVERESIZE"); + + ECORE_X_ATOM_NET_MOVERESIZE_WINDOW = _ATOM_GET("_NET_MOVERESIZE_WINDOW"); + ECORE_X_ATOM_NET_RESTACK_WINDOW = _ATOM_GET("_NET_RESTACK_WINDOW"); + + ECORE_X_ATOM_NET_WM_NAME = _ATOM_GET("_NET_WM_NAME"); + ECORE_X_ATOM_NET_WM_VISIBLE_NAME = _ATOM_GET("_NET_WM_VISIBLE_NAME"); + ECORE_X_ATOM_NET_WM_ICON_NAME = _ATOM_GET("_NET_WM_ICON_NAME"); + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME = + _ATOM_GET("_NET_WM_VISIBLE_ICON_NAME"); + ECORE_X_ATOM_NET_WM_DESKTOP = _ATOM_GET("_NET_WM_DESKTOP"); + ECORE_X_ATOM_NET_WM_STRUT = _ATOM_GET("_NET_WM_STRUT"); + ECORE_X_ATOM_NET_WM_STRUT_PARTIAL = _ATOM_GET("_NET_WM_STRUT_PARTIAL"); + ECORE_X_ATOM_NET_WM_ICON_GEOMETRY = _ATOM_GET("_NET_WM_ICON_GEOMETRY"); + ECORE_X_ATOM_NET_WM_ICON = _ATOM_GET("_NET_WM_ICON"); + ECORE_X_ATOM_NET_WM_PID = _ATOM_GET("_NET_WM_PID"); + ECORE_X_ATOM_NET_WM_HANDLED_ICONS = _ATOM_GET("_NET_WM_HANDLED_ICONS"); + ECORE_X_ATOM_NET_WM_USER_TIME = _ATOM_GET("_NET_WM_USER_TIME"); + + ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS = _ATOM_GET("_NET_WM_ALLOWED_ACTIONS"); + ECORE_X_ATOM_NET_WM_ACTION_MOVE = _ATOM_GET("_NET_WM_ACTION_MOVE"); + ECORE_X_ATOM_NET_WM_ACTION_RESIZE = _ATOM_GET("_NET_WM_ACTION_RESIZE"); + ECORE_X_ATOM_NET_WM_ACTION_MINIMIZE = _ATOM_GET("_NET_WM_ACTION_MINIMIZE"); + ECORE_X_ATOM_NET_WM_ACTION_SHADE = _ATOM_GET("_NET_WM_ACTION_SHADE"); + ECORE_X_ATOM_NET_WM_ACTION_STICK = _ATOM_GET("_NET_WM_ACTION_STICK"); + ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_HORZ = _ATOM_GET("_NET_WM_ACTION_MAXIMIZE_HORZ"); + ECORE_X_ATOM_NET_WM_ACTION_MAXIMIZE_VERT = _ATOM_GET("_NET_WM_ACTION_MAXIMIZE_VERT"); + ECORE_X_ATOM_NET_WM_ACTION_FULLSCREEN = _ATOM_GET("_NET_WM_ACTION_FULLSCREEN"); + ECORE_X_ATOM_NET_WM_ACTION_CHANGE_DESKTOP = _ATOM_GET("_NET_WM_ACTION_CHANGE_DESKTOP"); + ECORE_X_ATOM_NET_WM_ACTION_CLOSE = _ATOM_GET("_NET_WM_ACTION_CLOSE"); + + ECORE_X_ATOM_NET_WM_WINDOW_TYPE = _ATOM_GET("_NET_WM_WINDOW_TYPE"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DESKTOP = + _ATOM_GET("_NET_WM_WINDOW_TYPE_DESKTOP"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DOCK = _ATOM_GET("_NET_WM_WINDOW_TYPE_DOCK"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = + _ATOM_GET("_NET_WM_WINDOW_TYPE_TOOLBAR"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_MENU = _ATOM_GET("_NET_WM_WINDOW_TYPE_MENU"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_UTILITY = + _ATOM_GET("_NET_WM_WINDOW_TYPE_UTILITY"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_SPLASH = + _ATOM_GET("_NET_WM_WINDOW_TYPE_SPLASH"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_DIALOG = + _ATOM_GET("_NET_WM_WINDOW_TYPE_DIALOG"); + ECORE_X_ATOM_NET_WM_WINDOW_TYPE_NORMAL = + _ATOM_GET("_NET_WM_WINDOW_TYPE_NORMAL"); + + ECORE_X_ATOM_NET_WM_STATE = _ATOM_GET("_NET_WM_STATE"); + ECORE_X_ATOM_NET_WM_STATE_MODAL = _ATOM_GET("_NET_WM_STATE_MODAL"); + ECORE_X_ATOM_NET_WM_STATE_STICKY = _ATOM_GET("_NET_WM_STATE_STICKY"); + ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_VERT = + _ATOM_GET("_NET_WM_STATE_MAXIMIZED_VERT"); + ECORE_X_ATOM_NET_WM_STATE_MAXIMIZED_HORZ = + _ATOM_GET("_NET_WM_STATE_MAXIMIZED_HORZ"); + ECORE_X_ATOM_NET_WM_STATE_SHADED = _ATOM_GET("_NET_WM_STATE_SHADED"); + ECORE_X_ATOM_NET_WM_STATE_SKIP_TASKBAR = + _ATOM_GET("_NET_WM_STATE_SKIP_TASKBAR"); + ECORE_X_ATOM_NET_WM_STATE_SKIP_PAGER = _ATOM_GET("_NET_WM_STATE_SKIP_PAGER"); + ECORE_X_ATOM_NET_WM_STATE_HIDDEN = _ATOM_GET("_NET_WM_STATE_HIDDEN"); + ECORE_X_ATOM_NET_WM_STATE_FULLSCREEN = _ATOM_GET("_NET_WM_STATE_FULLSCREEN"); + ECORE_X_ATOM_NET_WM_STATE_ABOVE = _ATOM_GET("_NET_WM_STATE_ABOVE"); + ECORE_X_ATOM_NET_WM_STATE_BELOW = _ATOM_GET("_NET_WM_STATE_BELOW"); + ECORE_X_ATOM_NET_WM_STATE_DEMANDS_ATTENTION = _ATOM_GET("_NET_WM_STATE_DEMANDS_ATTENTION"); + + ECORE_X_ATOM_NET_WM_WINDOW_OPACITY = _ATOM_GET("_NET_WM_WINDOW_OPACITY"); + + ECORE_X_ATOM_NET_FRAME_EXTENTS = _ATOM_GET("_NET_FRAME_EXTENTS"); + ECORE_X_ATOM_NET_REQUEST_FRAME_EXTENTS = _ATOM_GET("_NET_REQUEST_FRAME_EXTENTS"); + + ECORE_X_ATOM_NET_WM_PING = _ATOM_GET("_NET_WM_PING"); + ECORE_X_ATOM_NET_WM_SYNC_REQUEST = _ATOM_GET("_NET_WM_SYNC_REQUEST"); + ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER = _ATOM_GET("_NET_WM_SYNC_REQUEST_COUNTER"); +} + +/* + * WM identification + */ +void +ecore_x_netwm_wm_identify(Ecore_X_Window root, Ecore_X_Window check, + const char *wm_name) +{ + _ATOM_SET_WINDOW(root, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1); + _ATOM_SET_WINDOW(check, ECORE_X_ATOM_NET_SUPPORTING_WM_CHECK, &check, 1); + _ATOM_SET_UTF8_STRING(check, ECORE_X_ATOM_NET_WM_NAME, wm_name); + /* This one isn't mandatory */ + _ATOM_SET_UTF8_STRING(root, ECORE_X_ATOM_NET_WM_NAME, wm_name); +} + +/* + * Set supported atoms + */ +void +ecore_x_netwm_supported_set(Ecore_X_Window root, Ecore_X_Atom *supported, int num) +{ + _ATOM_SET_ATOM(root, ECORE_X_ATOM_NET_SUPPORTED, supported, num); +} + +int +ecore_x_netwm_supported_get(Ecore_X_Window root, Ecore_X_Atom **supported, int *num) +{ + int num_ret; + unsigned char *data; + + if (num) *num = 0; + if (supported) *supported = NULL; + + if (!ecore_x_window_prop_property_get(root, ECORE_X_ATOM_NET_SUPPORTED, + XA_ATOM, 32, &data, &num_ret)) + return 0; + + if ((!data) || (!num_ret)) return 0; + + if (num) *num = num_ret; + if (supported) *supported = (Ecore_X_Atom *)data; + return 1; +} + +/* + * Desktop configuration and status + */ +void +ecore_x_netwm_desk_count_set(Ecore_X_Window root, unsigned int n_desks) +{ + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_NUMBER_OF_DESKTOPS, + &n_desks, 1); +} + +void +ecore_x_netwm_desk_roots_set(Ecore_X_Window root, + Ecore_X_Window *vroots, unsigned int n_desks) +{ + _ATOM_SET_WINDOW(root, ECORE_X_ATOM_NET_VIRTUAL_ROOTS, vroots, n_desks); +} + +void +ecore_x_netwm_desk_names_set(Ecore_X_Window root, + const char **names, unsigned int n_desks) +{ + char ss[32], *buf; + const char *s; + unsigned int i; + int l, len; + + 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; + buf = realloc(buf, len + l); + memcpy(buf + len, s, l); + len += l; + } + + _ATOM_SET_UTF8_STRING_LIST(root, ECORE_X_ATOM_NET_DESKTOP_NAMES, buf, len); + + free(buf); +} + +void +ecore_x_netwm_desk_size_set(Ecore_X_Window root, unsigned int width, + unsigned int height) +{ + unsigned int size[2]; + + size[0] = width; + size[1] = height; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_GEOMETRY, size, + 2); +} + +void +ecore_x_netwm_desk_viewports_set(Ecore_X_Window root, + unsigned int *origins, unsigned int n_desks) +{ + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_DESKTOP_VIEWPORT, + origins, 2 * n_desks); +} + +void +ecore_x_netwm_desk_layout_set(Ecore_X_Window root, int orientation, + int columns, int rows, + int starting_corner) +{ + unsigned int layout[4]; + + 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); +} + +void +ecore_x_netwm_desk_workareas_set(Ecore_X_Window root, + unsigned int *areas, unsigned int n_desks) +{ + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_WORKAREA, areas, + 4 * n_desks); +} + +void +ecore_x_netwm_desk_current_set(Ecore_X_Window root, unsigned int desk) +{ + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_CURRENT_DESKTOP, &desk, + 1); +} + +void +ecore_x_netwm_showing_desktop_set(Ecore_X_Window root, int on) +{ + unsigned int val; + + val = (on) ? 1 : 0; + ecore_x_window_prop_card32_set(root, ECORE_X_ATOM_NET_SHOWING_DESKTOP, &val, + 1); +} + +/* + * Client status + */ + +/* Mapping order */ +void +ecore_x_netwm_client_list_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, unsigned int n_clients) +{ + _ATOM_SET_WINDOW(root, ECORE_X_ATOM_NET_CLIENT_LIST, p_clients, n_clients); +} + +/* Stacking order */ +void +ecore_x_netwm_client_list_stacking_set(Ecore_X_Window root, + Ecore_X_Window *p_clients, + unsigned int n_clients) +{ + _ATOM_SET_WINDOW(root, ECORE_X_ATOM_NET_CLIENT_LIST_STACKING, p_clients, + n_clients); +} + +void +ecore_x_netwm_client_active_set(Ecore_X_Window root, Ecore_X_Window win) +{ + _ATOM_SET_WINDOW(root, ECORE_X_ATOM_NET_ACTIVE_WINDOW, &win, 1); +} + +void +ecore_x_netwm_name_set(Ecore_X_Window win, const char *name) +{ + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_NAME, name); +} + +int +ecore_x_netwm_name_get(Ecore_X_Window win, char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(win, ECORE_X_ATOM_NET_WM_NAME); + return 1; +} + +void +ecore_x_netwm_visible_name_set(Ecore_X_Window win, const char *name) +{ + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_VISIBLE_NAME, + name); +} + +int +ecore_x_netwm_visible_name_get(Ecore_X_Window win, char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(win, + ECORE_X_ATOM_NET_WM_VISIBLE_NAME); + return 1; +} + +void +ecore_x_netwm_icon_name_set(Ecore_X_Window win, const char *name) +{ + _ecore_x_window_prop_string_utf8_set(win, ECORE_X_ATOM_NET_WM_ICON_NAME, + name); +} + +int +ecore_x_netwm_icon_name_get(Ecore_X_Window win, char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(win, + ECORE_X_ATOM_NET_WM_ICON_NAME); + return 1; +} + +void +ecore_x_netwm_visible_icon_name_set(Ecore_X_Window win, const char *name) +{ + _ecore_x_window_prop_string_utf8_set(win, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME, + name); +} + +int +ecore_x_netwm_visible_icon_name_get(Ecore_X_Window win, char **name) +{ + if (name) + *name = _ecore_x_window_prop_string_utf8_get(win, + ECORE_X_ATOM_NET_WM_VISIBLE_ICON_NAME); + return 1; +} + +void +ecore_x_netwm_desktop_set(Ecore_X_Window win, unsigned int desk) +{ + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_DESKTOP, &desk, 1); +} + +int +ecore_x_netwm_desktop_get(Ecore_X_Window win, unsigned int *desk) +{ + int ret; + unsigned int tmp; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_DESKTOP, + &tmp, 1); + + if (desk) *desk = tmp; + return ret == 1 ? 1 : 0; +} + +/* + * _NET_WM_STRUT is deprecated + */ +void +ecore_x_netwm_strut_set(Ecore_X_Window win, int left, int right, + int top, int bottom) +{ + unsigned int strut[4]; + + 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 + */ +int +ecore_x_netwm_strut_get(Ecore_X_Window win, int *left, int *right, + int *top, int *bottom) +{ + int ret = 0; + unsigned int strut[4]; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_STRUT, strut, 4); + if (ret != 4) + return 0; + + if (left) *left = strut[0]; + if (right) *right = strut[1]; + if (top) *top = strut[2]; + if (bottom) *bottom = strut[3]; + return 1; +} + +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]; + + 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); +} + +int +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]; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_STRUT_PARTIAL, strut, 12); + if (ret != 12) + return 0; + + 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 1; +} + +int +ecore_x_netwm_icon_get(Ecore_X_Window win, int *width, int *height, unsigned int **icon, int *num) +{ + unsigned char *data_ret; + unsigned int *data; + unsigned int *src; + int num_ret, len; + + if (width) *width = 0; + if (height) *height = 0; + if (num) *num = 0; + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_NET_WM_ICON, + XA_CARDINAL, 32, &data_ret, &num_ret)) + return 0; + data = (unsigned int *)data_ret; + + if (icon) + { + *icon = malloc((num_ret - 2) * sizeof(unsigned int)); + if (!(*icon)) return 0; + } + + if (num) *num = (num_ret - 2); + if (width) *width = data[0]; + if (height) *height = data[1]; + + len = data[0] * data[1]; + src = &(data[2]); + if (icon) + memcpy(*icon, &(data[2]), len * sizeof(unsigned int)); + free(data_ret); + + return 1; +} + +void +ecore_x_netwm_icon_geometry_set(Ecore_X_Window win, int x, int y, int width, int height) +{ + unsigned int geometry[4]; + + 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); +} + +int +ecore_x_netwm_icon_geometry_get(Ecore_X_Window win, int *x, int *y, int *width, int *height) +{ + int ret; + unsigned int geometry[4]; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_ICON_GEOMETRY, geometry, 4); + if (ret != 4) + return 0; + + if (x) *x = geometry[0]; + if (y) *y = geometry[1]; + if (width) *width = geometry[2]; + if (height) *height = geometry[3]; + return 1; +} + +void +ecore_x_netwm_pid_set(Ecore_X_Window win, int pid) +{ + unsigned int tmp; + + tmp = pid; + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_PID, + &tmp, 1); +} + +int +ecore_x_netwm_pid_get(Ecore_X_Window win, int *pid) +{ + int ret; + unsigned int tmp; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_PID, + &tmp, 1); + if (pid) *pid = tmp; + return ret == 1 ? 1 : 0; +} + +void +ecore_x_netwm_handled_icons_set(Ecore_X_Window win) +{ + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); +} + +int +ecore_x_netwm_handled_icons_get(Ecore_X_Window win) +{ + int ret = 0; + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_HANDLED_ICONS, + NULL, 0); + return ret == 0 ? 1 : 0; +} + +void +ecore_x_netwm_user_time_set(Ecore_X_Window win, unsigned int time) +{ + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_USER_TIME, + &time, 1); +} + +int +ecore_x_netwm_user_time_get(Ecore_X_Window win, unsigned int *time) +{ + int ret; + unsigned int tmp; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_USER_TIME, + &tmp, 1); + if (time) *time = tmp; + return ret == 1 ? 1 : 0; +} + +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; + } +} + +void +ecore_x_netwm_window_state_set(Ecore_X_Window win, Ecore_X_Window_State *state, unsigned int num) +{ + unsigned char *data; + Ecore_X_Atom *set; + int i; + + if (!num) + { + ecore_x_window_prop_property_del(win, ECORE_X_ATOM_NET_WM_STATE); + return; + } + + data = malloc(num * sizeof(Ecore_X_Atom)); + if (!data) return; + + set = (Ecore_X_Atom *) data; + for (i = 0; i < num; i++) + set[i] = _ecore_x_netwm_state_atom_get(state[i]); + + _ATOM_SET_ATOM(win, ECORE_X_ATOM_NET_WM_STATE, data, num); + + free(data); + return; +} + +int +ecore_x_netwm_window_state_get(Ecore_X_Window win, Ecore_X_Window_State **state, unsigned int *num) +{ + int num_ret, i; + unsigned char *data; + Ecore_X_Atom *atoms; + + if (num) *num = 0; + if (state) *state = NULL; + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_NET_WM_STATE, + XA_ATOM, 32, &data, &num_ret)) + return 0; + + if ((!data) || (!num_ret)) return 0; + + atoms = (Ecore_X_Atom *) data; + 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(data); + return 1; +} + +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 + 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; + 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 + */ +void +ecore_x_netwm_window_type_set(Ecore_X_Window win, Ecore_X_Window_Type type) +{ + Ecore_X_Atom atom; + + atom = _ecore_x_netwm_window_type_atom_get(type); + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + XA_ATOM, 32, (unsigned char *)&atom, 1); +} + +/* FIXME: Maybe return 0 on some conditions? */ +int +ecore_x_netwm_window_type_get(Ecore_X_Window win, Ecore_X_Window_Type *type) +{ + int num, i; + unsigned char *data; + Ecore_X_Atom *atoms; + + if (type) *type = ECORE_X_WINDOW_TYPE_NORMAL; + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + XA_ATOM, 32, &data, &num)) + { + /* Check if WM_TRANSIENT_FOR is set */ + if ((type) && (ecore_x_icccm_transient_for_get(win))) + *type = ECORE_X_WINDOW_TYPE_DIALOG; + return 1; + } + + atoms = (Ecore_X_Atom *) data; + + if (type) + { + for (i = 0; i < num; ++i) + { + *type = _ecore_x_netwm_window_type_type_get(atoms[i]); + if (*type != ECORE_X_WINDOW_TYPE_UNKNOWN) + break; + } + } + + free(data); + return 1; +} + +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; + default: + return 0; + } +} + +/* FIXME: Get complete list */ +int +ecore_x_netwm_allowed_action_isset(Ecore_X_Window win, Ecore_X_Action action) +{ + int num, i, ret = 0; + unsigned char *data; + Ecore_X_Atom *atoms, atom; + + if (!ecore_x_window_prop_property_get(win, ECORE_X_ATOM_NET_WM_WINDOW_TYPE, + XA_ATOM, 32, &data, &num)) + return ret; + + atom = _ecore_x_netwm_action_atom_get(action); + atoms = (Ecore_X_Atom *) data; + + for (i = 0; i < num; ++i) + { + if (atom == atoms[i]) + { + ret = 1; + break; + } + } + + free(data); + return ret; +} + +/* FIXME: Set complete list */ +void +ecore_x_netwm_allowed_action_set(Ecore_X_Window win, Ecore_X_Action action, int 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; + + atom = _ecore_x_netwm_action_atom_get(action); + + ecore_x_window_prop_property_get(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + XA_ATOM, 32, &old_data, &num); + oldset = (Ecore_X_Atom *) old_data; + + if (on) + { + for (i = 0; i < num; ++i) + { + if (oldset[i] == atom) + goto done; + } + + newset = calloc(num + 1, sizeof(Ecore_X_Atom)); + if (!newset) + goto done; + + data = (unsigned char *) newset; + for (i = 0; i < num; i++) + newset[i] = oldset[i]; + newset[num] = atom; + + ecore_x_window_prop_property_set(win, ECORE_X_ATOM_NET_WM_ALLOWED_ACTIONS, + XA_ATOM, 32, data, num + 1); + } + else + { + int has; + + has = 0; + for (i = 0; i < num; ++i) + { + if (oldset[i] == atom) + has = 1; + } + if (!has) + goto done; + + newset = calloc(num - 1, sizeof(Ecore_X_Atom)); + if (!newset) + goto done; + + 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_NET_WM_ALLOWED_ACTIONS, + XA_ATOM, 32, data, num - 1); + } + free(newset); +done: + free(oldset); +} + +void +ecore_x_netwm_opacity_set(Ecore_X_Window win, unsigned int opacity) +{ + ecore_x_window_prop_card32_set(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &opacity, 1); +} + +int +ecore_x_netwm_opacity_get(Ecore_X_Window win, unsigned int *opacity) +{ + int ret; + unsigned int tmp; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, + &tmp, 1); + if (opacity) *opacity = tmp; + return ret == 1 ? 1 : 0; +} + +void +ecore_x_netwm_frame_size_set(Ecore_X_Window win, int fl, int fr, int ft, int fb) +{ + unsigned int frames[4]; + + 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); +} + +int +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]; + + ret = ecore_x_window_prop_card32_get(win, ECORE_X_ATOM_NET_FRAME_EXTENTS, frames, 4); + if (ret != 4) + return 0; + + if (fl) *fl = frames[0]; + if (fr) *fr = frames[1]; + if (ft) *ft = frames[2]; + if (fb) *fb = frames[3]; + return 1; +} + +int +ecore_x_netwm_sync_counter_get(Ecore_X_Window win, Ecore_X_Sync_Counter *counter) +{ + int ret; + unsigned int tmp; + + 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 ? 1 : 0; +} + +void +ecore_x_netwm_ping_send(Ecore_X_Window win) +{ + XEvent xev; + + if (!win) return; + + 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] = CurrentTime; + xev.xclient.data.l[2] = win; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + xev.xclient.data.l[5] = 0; + + XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev); +} + +void +ecore_x_netwm_sync_request_send(Ecore_X_Window win, unsigned int serial) +{ + XSyncValue value; + XEvent xev; + + if (!win) return; + + XSyncIntToValue(&value, 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] = CurrentTime; + 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, 0, &xev); +} + +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, int set) +{ + XEvent xev; + + if (!win) return; + 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, 0, &xev); +} + +void +ecore_x_netwm_desktop_request_send(Ecore_X_Window win, Ecore_X_Window root, unsigned int desktop) +{ + XEvent xev; + + if (!win) return; + 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); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_pixmap.c b/ecore/src/lib/ecore_x/ecore_x_pixmap.c new file mode 100644 index 0000000..bfc96a2 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_pixmap.c @@ -0,0 +1,95 @@ +#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 + */ +Ecore_X_Pixmap +ecore_x_pixmap_new(Ecore_X_Window win, int w, int h, int dep) +{ + 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 + */ +void +ecore_x_pixmap_del(Ecore_X_Pixmap pmap) +{ + 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 + */ +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) +{ + 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 + */ +void +ecore_x_pixmap_geometry_get(Ecore_X_Pixmap pmap, int *x, int *y, int *w, int *h) +{ + 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 + */ +int +ecore_x_pixmap_depth_get(Ecore_X_Pixmap pmap) +{ + return ecore_x_drawable_depth_get(pmap); +} + diff --git a/ecore/src/lib/ecore_x/ecore_x_private.h b/ecore/src/lib/ecore_x/ecore_x_private.h new file mode 100644 index 0000000..bc9d87b --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_private.h @@ -0,0 +1,210 @@ +#ifndef _ECORE_X_PRIVATE_H +#define _ECORE_X_PRIVATE_H + +#include "config.h" + +#include <sys/param.h> +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +#define XK_MISCELLANY 1 +#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> +#ifdef ECORE_XCURSOR +#include <X11/Xcursor/Xcursor.h> +#endif +#ifdef ECORE_XPRINT +#include <X11/extensions/Print.h> +#endif +#ifdef ECORE_XINERAMA +#include <X11/extensions/Xinerama.h> +#endif + +#include "Ecore_X.h" + +/* FIXME: this is for simulation only */ +#include "Ecore_Job.h" +#include "Ecore_Txt.h" + +typedef struct _Ecore_X_Reply Ecore_X_Reply; + +struct _Ecore_X_Reply +{ +/* FIXME: this is for simulation only */ + Ecore_Job *job; + + void *reply_data; + void (*reply_data_free) (void *reply_data); + + void (*func) (void *data, Ecore_X_Reply *reply, void *reply_data); + void *data; +}; + +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; + int (*convert)(char *target, void *data, int size, + void **data_ret, int *size_ret); + 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, unsigned char *data, int size); + 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; + + 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 int _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 int (*_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_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_sync_counter(XEvent *xevent); +void _ecore_x_event_handle_sync_alarm(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); +int _ecore_x_selection_set(Window w, unsigned char *data, int len, Ecore_X_Atom selection); +int _ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret); +void *_ecore_x_selection_parse(const char *target, unsigned char *data, int size); + +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(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); + +/* from sync */ + +#endif diff --git a/ecore/src/lib/ecore_x/ecore_x_selection.c b/ecore/src/lib/ecore_x/ecore_x_selection.c new file mode 100644 index 0000000..5306219 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_selection.c @@ -0,0 +1,773 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "ecore_private.h" +#include "Ecore.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_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret); +static int _ecore_x_selection_data_default_free(void *data); +static void *_ecore_x_selection_parser_files(const char *target, unsigned char *data, int size); +static int _ecore_x_selection_data_files_free(void *data); +static void *_ecore_x_selection_parser_text(const char *target, unsigned char *data, int size); +static int _ecore_x_selection_data_text_free(void *data); +static void *_ecore_x_selection_parser_targets(const char *target, unsigned char *data, int size); +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 + 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; +} + +int +_ecore_x_selection_set(Window w, unsigned char *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 0; + + 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 0; + + 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); + 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 1; +} + +/** + * 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. + */ +int +ecore_x_selection_primary_set(Ecore_X_Window w, unsigned char *data, int size) +{ + 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. + * + */ +int +ecore_x_selection_primary_clear(void) +{ + 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. + */ +int +ecore_x_selection_secondary_set(Ecore_X_Window w, unsigned char *data, int size) +{ + 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. + * + */ +int +ecore_x_selection_secondary_clear(void) +{ + 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. + */ +int +ecore_x_selection_xdnd_set(Ecore_X_Window w, unsigned char *data, int size) +{ + 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. + * + */ +int +ecore_x_selection_xdnd_clear(void) +{ + 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. + */ +int +ecore_x_selection_clipboard_set(Ecore_X_Window w, unsigned char *data, int size) +{ + 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. + * + */ +int +ecore_x_selection_clipboard_clear(void) +{ + 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) +{ + 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, 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); +} + +void +ecore_x_selection_primary_request(Ecore_X_Window w, char *target) +{ + _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_PRIMARY, target); +} + +void +ecore_x_selection_secondary_request(Ecore_X_Window w, char *target) +{ + _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_SECONDARY, target); +} + +void +ecore_x_selection_xdnd_request(Ecore_X_Window w, char *target) +{ + Ecore_X_Atom atom; + Ecore_X_DND_Target *_target; + + _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); +} + +void +ecore_x_selection_clipboard_request(Ecore_X_Window w, char *target) +{ + _ecore_x_selection_request(w, ECORE_X_ATOM_SELECTION_CLIPBOARD, target); +} + +void +ecore_x_selection_converter_atom_add(Ecore_X_Atom target, + int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret)) +{ + Ecore_X_Selection_Converter *cnv; + + 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)); + cnv = cnv->next; + } + else + { + converters = calloc(1, sizeof(Ecore_X_Selection_Converter)); + cnv = converters; + } + cnv->target = target; + cnv->convert = func; +} + +void +ecore_x_selection_converter_add(char *target, + int (*func)(char *target, void *data, int size, void **data_ret, int *size_ret)) +{ + Ecore_X_Atom x_target; + + if (!func || !target) + return; + + x_target = _ecore_x_selection_target_atom_get(target); + + ecore_x_selection_converter_atom_add(x_target, func); +} + +void +ecore_x_selection_converter_atom_del(Ecore_X_Atom target) +{ + Ecore_X_Selection_Converter *cnv, *prev_cnv; + + 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; + } +} + +void +ecore_x_selection_converter_del(char *target) +{ + Ecore_X_Atom x_target; + + if (!target) + return; + + x_target = _ecore_x_selection_target_atom_get(target); + ecore_x_selection_converter_atom_del(x_target); +} + +/* Locate and run conversion callback for specified selection target */ +int +_ecore_x_selection_convert(Ecore_X_Atom selection, Ecore_X_Atom target, void **data_ret) +{ + Ecore_X_Selection_Intern *sel; + Ecore_X_Selection_Converter *cnv; + void *data; + int size; + char *tgt_str; + + 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); + free(tgt_str); + if (r) + { + *data_ret = data; + return r; + } + else + return 0; + } + } + + /* 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 */ +static int +_ecore_x_selection_converter_text(char *target, void *data, int size, void **data_ret, int *size_ret) +{ + XTextProperty text_prop; + char *mystr; + XICCEncodingStyle style; + + if (!data || !size) + return 0; + + 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 + else + return 0; + + if (!(mystr = strdup(data))) + return 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); + memcpy(*data_ret, text_prop.value, bufsize); + *size_ret = bufsize; + XFree(text_prop.value); + free(mystr); + return 1; + } +#else + if (XmbTextListToTextProperty(_ecore_x_disp, &mystr, 1, style, &text_prop) == Success) + { + int bufsize = strlen(text_prop.value) + 1; + *data_ret = malloc(bufsize); + memcpy(*data_ret, text_prop.value, bufsize); + *size_ret = bufsize; + XFree(text_prop.value); + free(mystr); + return 1; + } +#endif + else + { + free(mystr); + return 0; + } +} + +void +ecore_x_selection_parser_add(const char *target, + void *(*func)(const char *target, unsigned char *data, int size)) +{ + Ecore_X_Selection_Parser *prs; + + if (!target) + return; + + 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)); + prs = prs->next; + } + else + { + parsers = calloc(1, sizeof(Ecore_X_Selection_Parser)); + prs = parsers; + } + prs->target = strdup(target); + prs->parse = func; +} + +void +ecore_x_selection_parser_del(const char *target) +{ + Ecore_X_Selection_Parser *prs, *prev_prs; + + if (!target) + return; + + 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; + } +} + +/* Locate and run conversion callback for specified selection target */ +void * +_ecore_x_selection_parse(const char *target, unsigned char *data, int size) +{ + 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); + return sel; + } + } + + /* Default, just return the data */ + sel = calloc(1, sizeof(Ecore_X_Selection_Data)); + sel->free = _ecore_x_selection_data_default_free; + sel->length = size; + 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, unsigned char *data, int size) +{ + Ecore_X_Selection_Data_Files *sel; + int i, is; + char *tmp; + + if (strcmp(target, "text/uri-list") + && strcmp(target, "_NETSCAPE_URL")) + return NULL; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Files)); + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_files_free; + + if (data[size - 1]) + { + /* Isn't nul terminated */ + printf("BUG: isn't nul terminated!\n"); + size++; + data = realloc(data, size); + data[size - 1] = 0; + } + + tmp = malloc(size); + 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++; + sel->files = realloc(sel->files, sel->num_files * sizeof(char *)); + sel->files[sel->num_files - 1] = strdup(tmp); + tmp[0] = 0; + i = 0; + } + } + } + if (i > 0) + { + tmp[i] = 0; + sel->num_files++; + sel->files = realloc(sel->files, sel->num_files * sizeof(char *)); + sel->files[sel->num_files - 1] = strdup(tmp); + } + free(tmp); + free(data); + + 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 __UNUSED__, unsigned char *data, int size) +{ + Ecore_X_Selection_Data_Text *sel; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Text)); + + if (data[size - 1]) + { + /* Isn't nul terminated */ + printf("BUG: isn't nul terminated!\n"); + size++; + data = realloc(data, size); + data[size - 1] = 0; + } + + sel->text = (char *)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 __UNUSED__, unsigned char *data, int size) +{ + Ecore_X_Selection_Data_Targets *sel; + unsigned long *targets; + int i; + + sel = calloc(1, sizeof(Ecore_X_Selection_Data_Targets)); + targets = (unsigned long *)data; + + sel->num_targets = size - 2; + sel->targets = malloc((size - 2) * sizeof(char *)); + for (i = 2; i < size; i++) + sel->targets[i - 2] = XGetAtomName(_ecore_x_disp, targets[i]); + free(data); + + ECORE_X_SELECTION_DATA(sel)->free = _ecore_x_selection_data_targets_free; + 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(sel); + return 1; +} diff --git a/ecore/src/lib/ecore_x/ecore_x_sync.c b/ecore/src/lib/ecore_x/ecore_x_sync.c new file mode 100644 index 0000000..0b567bf --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_sync.c @@ -0,0 +1,48 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +/* + * XSync code + */ +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +Ecore_X_Sync_Alarm +ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter) +{ + Ecore_X_Sync_Alarm alarm; + XSyncAlarmAttributes values; + XSyncValue init; + + 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; +} + +int +ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm) +{ + return XSyncDestroyAlarm(_ecore_x_disp, alarm); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_window.c b/ecore/src/lib/ecore_x/ecore_x_window.c new file mode 100644 index 0000000..3577b74 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_window.c @@ -0,0 +1,768 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#include "Ecore.h" +#include "ecore_x_private.h" +#include "Ecore_X.h" +#include "Ecore_X_Atoms.h" + +/** + * @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 + */ +Ecore_X_Window +ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h) +{ + Window win; + XSetWindowAttributes attr; + + if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp); + attr.backing_store = NotUseful; + attr.override_redirect = False; + attr.colormap = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp)); + attr.border_pixel = 0; + attr.background_pixmap = None; + 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, + 0, /*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, + &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 + */ +Ecore_X_Window +ecore_x_window_override_new(Ecore_X_Window parent, int x, int y, int w, int h) +{ + Window win; + XSetWindowAttributes attr; + + if (parent == 0) parent = DefaultRootWindow(_ecore_x_disp); + attr.backing_store = NotUseful; + attr.override_redirect = True; + attr.colormap = DefaultColormap(_ecore_x_disp, DefaultScreen(_ecore_x_disp)); + attr.border_pixel = 0; + attr.background_pixmap = None; + 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, + 0, /*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, + &attr); + + if (parent == DefaultRootWindow(_ecore_x_disp)) ecore_x_window_defaults_set(win); + 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 + */ +Ecore_X_Window +ecore_x_window_input_new(Ecore_X_Window parent, int x, int y, int w, int h) +{ + Window win; + XSetWindowAttributes attr; + + 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, + 0, + InputOnly, + CopyFromParent, /*DefaultVisual(_ecore_x_disp, DefaultScreen(_ecore_x_disp)),*/ + CWOverrideRedirect | + CWDontPropagate | + CWEventMask, + &attr); + + if (parent == DefaultRootWindow(_ecore_x_disp)) + { + } + return win; +} + +/** + * @defgroup Evas_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 Evas_X_Window_Properties_Groups + */ +void +ecore_x_window_defaults_set(Ecore_X_Window win) +{ + long pid; + char buf[MAXHOSTNAMELEN]; + char *hostname[1]; + int argc; + char **argv; + XTextProperty xprop; + + /* + * 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); +} + +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; + + 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 Evas_X_Window_Destroy_Group X Window Destroy Functions + * + * Functions to destroy X windows. + */ + +/** + * Deletes the given window. + * @param win The given window. + * @ingroup Evas_X_Window_Destroy_Group + */ +void +ecore_x_window_del(Ecore_X_Window win) +{ + /* sorry sir, deleting the root window doesn't sound like + * a smart idea. + */ + if (win) + XDestroyWindow(_ecore_x_disp, win); +} + +/** + * Sends a delete request to the given window. + * @param win The given window. + * @ingroup Evas_X_Window_Destroy_Group + */ +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; + + 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 Evas_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 Evas_X_Window_Visibility + */ +void +ecore_x_window_show(Ecore_X_Window win) +{ + 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 Evas_X_Window_Visibility + */ +void +ecore_x_window_hide(Ecore_X_Window win) +{ + XUnmapWindow(_ecore_x_disp, win); +} + +/** + * @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 + */ +void +ecore_x_window_move(Ecore_X_Window win, int x, int y) +{ + 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 + */ +void +ecore_x_window_resize(Ecore_X_Window win, int w, int h) +{ + 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 + */ +void +ecore_x_window_move_resize(Ecore_X_Window win, int x, int y, int w, int h) +{ + 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 + */ +void +ecore_x_window_focus(Ecore_X_Window win) +{ + if (win == 0) win = DefaultRootWindow(_ecore_x_disp); +// XSetInputFocus(_ecore_x_disp, win, RevertToNone, CurrentTime); + XSetInputFocus(_ecore_x_disp, win, PointerRoot, 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 + */ +void +ecore_x_window_focus_at_time(Ecore_X_Window win, Ecore_X_Time t) +{ + if (win == 0) win = DefaultRootWindow(_ecore_x_disp); +// XSetInputFocus(_ecore_x_disp, win, RevertToNone, t); + XSetInputFocus(_ecore_x_disp, win, PointerRoot, t); +} + +/** + * gets the focus to the window @p win. + * @return The window that has focus. + * @ingroup Ecore_X_Window_Focus_Functions + */ +Ecore_X_Window +ecore_x_window_focus_get(void) +{ + Window win; + int revert_mode; + + 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 + */ +void +ecore_x_window_raise(Ecore_X_Window win) +{ + XRaiseWindow(_ecore_x_disp, win); +} + +/** + * Lowers the given window. + * @param win The window to lower. + * @ingroup Ecore_X_Window_Z_Order_Group + */ +void +ecore_x_window_lower(Ecore_X_Window win) +{ + 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 + */ +void +ecore_x_window_reparent(Ecore_X_Window win, Ecore_X_Window new_parent, int x, int y) +{ + 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 + */ +void +ecore_x_window_size_get(Ecore_X_Window win, int *w, int *h) +{ + int dummy_x, dummy_y; + + 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. + * @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 + */ +void +ecore_x_window_geometry_get(Ecore_X_Window win, int *x, int *y, int *w, int *h) +{ + 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 + */ +int +ecore_x_window_border_width_get(Ecore_X_Window win) +{ + /* 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 + */ +void +ecore_x_window_border_width_set(Ecore_X_Window win, int width) +{ + /* 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. + */ +int +ecore_x_window_depth_get(Ecore_X_Window win) +{ + return ecore_x_drawable_depth_get(win); +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +void +ecore_x_window_cursor_show(Ecore_X_Window win, int show) +{ + 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); + } +} + +void +ecore_x_window_cursor_set(Ecore_X_Window win, Ecore_X_Cursor c) +{ + 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 + */ +int +ecore_x_window_visible_get(Ecore_X_Window win) +{ + XWindowAttributes attr; + + return (XGetWindowAttributes(_ecore_x_disp, win, &attr) && + (attr.map_state == IsViewable)); +} + +static Window +_ecore_x_window_at_xy_get(Window base, int bx, int by, int x, int y) +{ + Window *list = NULL; + Window parent_win = 0, child = 0, root_win = 0; + int i, wx, wy, ww, wh; + unsigned int num; + + 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; + + if (!XQueryTree(_ecore_x_disp, base, &root_win, &parent_win, &list, &num)) + return base; + + if (list) + { + for (i = num - 1;; --i) + { + if ((child = _ecore_x_window_at_xy_get(list[i], wx, wy, x, y))) + { + XFree(list); + return child; + } + if (!i) + break; + } + 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 + */ +Ecore_X_Window +ecore_x_window_at_xy_get(int x, int y) +{ + Ecore_X_Window win, root; + + /* 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); + ecore_x_ungrab(); + + return win ? win : root; +} + +/** + * 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 + */ +Ecore_X_Window +ecore_x_window_parent_get(Ecore_X_Window win) +{ + Window root, parent, *children = NULL; + unsigned int num; + + 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 color The color to set to (i.e. 0xff0000) + */ +void +ecore_x_window_background_color_set(Ecore_X_Window win, unsigned short r, + unsigned short g, unsigned short b) +{ + XSetWindowAttributes attr; + XColor col; + + col.red = r; + col.green = g; + col.blue = b; + + XAllocColor(_ecore_x_disp, DefaultColormap(_ecore_x_disp, + DefaultScreen(_ecore_x_disp)), + &col); + + attr.background_pixel = col.pixel; + XChangeWindowAttributes(_ecore_x_disp, win, CWBackPixel, &attr); +} + +void +ecore_x_window_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav) +{ + XSetWindowAttributes att; + + att.win_gravity = grav; + XChangeWindowAttributes(_ecore_x_disp, win, CWWinGravity, &att); +} + +void +ecore_x_window_pixel_gravity_set(Ecore_X_Window win, Ecore_X_Gravity grav) +{ + XSetWindowAttributes att; + + att.bit_gravity = grav; + XChangeWindowAttributes(_ecore_x_disp, win, CWBitGravity, &att); +} + +void +ecore_x_window_pixmap_set(Ecore_X_Window win, Ecore_X_Pixmap pmap) +{ + XSetWindowBackgroundPixmap(_ecore_x_disp, win, pmap); +} + +void +ecore_x_window_area_clear(Ecore_X_Window win, int x, int y, int w, int h) +{ + XClearArea(_ecore_x_disp, win, x, y, w, h, False); +} + +void +ecore_x_window_area_expose(Ecore_X_Window win, int x, int y, int w, int h) +{ + XClearArea(_ecore_x_disp, win, x, y, w, h, True); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_window_prop.c b/ecore/src/lib/ecore_x/ecore_x_window_prop.c new file mode 100644 index 0000000..1c45607 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_window_prop.c @@ -0,0 +1,342 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ +#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 + */ +void +ecore_x_window_prop_card32_set(Ecore_X_Window win, Ecore_X_Atom atom, + unsigned int *val, unsigned int num) +{ +#if SIZEOF_INT == 4 + _ATOM_SET_CARD32(win, atom, val, num); +#else + CARD32 *c32; + unsigned int i; + + c32 = malloc(num * sizeof(CARD32)); + if (!c32) + return; + for (i = 0; i < num; i++) + c32[i] = val[i]; + _ATOM_SET_CARD32(win, atom, c32, num); + free(c32); +#endif +} + +/* + * 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. + */ +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; + + prop_ret = NULL; + XGetWindowProperty(_ecore_x_disp, win, atom, 0, 0x7fffffff, False, + XA_CARDINAL, &type_ret, &format_ret, &num_ret, + &bytes_after, &prop_ret); + if (prop_ret && type_ret == XA_CARDINAL && format_ret == 32) + { + if (num_ret < len) + len = num_ret; + for (i = 0; i < len; i++) + val[i] = ((unsigned long *)prop_ret)[i]; + num = len; + } + else + { + num = -1; + } + if (prop_ret) + XFree(prop_ret); + + return num; +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +Ecore_X_Atom +ecore_x_window_prop_any_type(void) +{ + return AnyPropertyType; +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +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) +{ + 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); + } + } +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +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) +{ + 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; + + 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 (size != size_ret || !num_ret) { + XFree(prop_ret); + return 0; + } + + if (!(*data = malloc(num_ret * size / 8))) { + XFree(prop_ret); + return 0; + } + + switch (size) { + case 8: + for (i = 0; i < num_ret; i++) + (*data)[i] = prop_ret[i]; + break; + case 16: + for (i = 0; i < num_ret; i++) + ((uint16_t *) *data)[i] = ((uint16_t *) prop_ret)[i]; + break; + case 32: + for (i = 0; i < num_ret; i++) + ((uint32_t *) *data)[i] = ((uint32_t *) prop_ret)[i]; + break; + } + + XFree(prop_ret); + + if (num) *num = num_ret; + return 1; +} + +void +ecore_x_window_prop_property_del(Ecore_X_Window win, Ecore_X_Atom property) +{ + XDeleteProperty(_ecore_x_disp, win, property); +} + +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; + + 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 + */ +void +ecore_x_window_prop_string_set(Ecore_X_Window win, Ecore_X_Atom type, const char *str) +{ + XTextProperty xtp; + + 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. + */ +char * +ecore_x_window_prop_string_get(Ecore_X_Window win, Ecore_X_Atom type) +{ + XTextProperty xtp; + char *str = NULL; + + 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 + s = XmbTextPropertyToTextList(_ecore_x_disp, &xtp, + &list, &items); +#endif + 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; +} + +int +ecore_x_window_prop_protocol_isset(Ecore_X_Window win, + Ecore_X_WM_Protocol protocol) +{ + Atom proto, *protos = NULL; + int i, ret = 0, protos_count = 0; + + /* check for invalid values */ + if (protocol >= ECORE_X_WM_PROTOCOL_NUM) + return 0; + + 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 = 1; + break; + } + + XFree(protos); + + return ret; +} + +/** + * To be documented. + * + * FIXME: To be fixed. + */ +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; + + 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/ecore/src/lib/ecore_x/ecore_x_window_shape.c b/ecore/src/lib/ecore_x/ecore_x_window_shape.c new file mode 100644 index 0000000..27ea707 --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_window_shape.c @@ -0,0 +1,159 @@ +#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 + */ +void +ecore_x_window_shape_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask) +{ + XShapeCombineMask(_ecore_x_disp, win, ShapeBounding, 0, 0, mask, ShapeSet); +} + +void +ecore_x_window_shape_window_set(Ecore_X_Window win, Ecore_X_Window shape_win) +{ + XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, 0, 0, shape_win, ShapeBounding, ShapeSet); +} + +void +ecore_x_window_shape_window_set_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y) +{ + XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, x, y, shape_win, ShapeBounding, ShapeSet); +} + +void +ecore_x_window_shape_rectangle_set(Ecore_X_Window win, int x, int y, int w, int h) +{ + XRectangle rect; + + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, Unsorted); +} + +void +ecore_x_window_shape_rectangles_set(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num) +{ + XRectangle *rect = NULL; + int i; + + if (num > 0) + { + rect = alloca(sizeof(XRectangle) * num); + 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); +} + +void +ecore_x_window_shape_window_add(Ecore_X_Window win, Ecore_X_Window shape_win) +{ + XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, 0, 0, shape_win, ShapeBounding, ShapeUnion); +} + +void +ecore_x_window_shape_window_add_xy(Ecore_X_Window win, Ecore_X_Window shape_win, int x, int y) +{ + XShapeCombineShape(_ecore_x_disp, win, ShapeBounding, x, y, shape_win, ShapeBounding, ShapeUnion); +} + +void +ecore_x_window_shape_rectangle_add(Ecore_X_Window win, int x, int y, int w, int h) +{ + XRectangle rect; + + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeUnion, Unsorted); +} + +void +ecore_x_window_shape_rectangle_clip(Ecore_X_Window win, int x, int y, int w, int h) +{ + XRectangle rect; + + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XShapeCombineRectangles(_ecore_x_disp, win, ShapeBounding, 0, 0, &rect, 1, ShapeIntersect, Unsorted); +} + +void +ecore_x_window_shape_rectangles_add(Ecore_X_Window win, Ecore_X_Rectangle *rects, int num) +{ + XRectangle *rect = NULL; + int i; + + if (num > 0) + { + rect = alloca(sizeof(XRectangle) * num); + 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); +} + +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; + + rect = XShapeGetRectangles(_ecore_x_disp, win, ShapeBounding, &num, &ord); + if (rect) + { + rects = malloc(sizeof(Ecore_X_Rectangle) * num); + if (rects) + { + 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; +} + +void +ecore_x_window_shape_events_select(Ecore_X_Window win, int on) +{ + if (on) + XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); + else + XShapeSelectInput(_ecore_x_disp, win, 0); +} diff --git a/ecore/src/lib/ecore_x/ecore_x_xinerama.c b/ecore/src/lib/ecore_x/ecore_x_xinerama.c new file mode 100644 index 0000000..d26d8aa --- /dev/null +++ b/ecore/src/lib/ecore_x/ecore_x_xinerama.c @@ -0,0 +1,54 @@ +/* + * Xinerama code + */ +#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 + +int +ecore_x_xinerama_screen_count_get(void) +{ +#ifdef ECORE_XINERAMA + if (_xin_info) XFree(_xin_info); + _xin_info = NULL; + _xin_info = XineramaQueryScreens(_ecore_x_disp, &_xin_scr_num); + if (_xin_info) return _xin_scr_num; + else return 0; +#else + return 0; +#endif +} + +int +ecore_x_xinerama_screen_geometry_get(int screen, int *x, int *y, int *w, int *h) +{ +#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 1; + } + } + } +#endif + 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 0; +} |