#ifdef HAVE_CONFIG_H # include #endif /* ifdef HAVE_CONFIG_H */ #include #include #include //#define LOGRT 1 #ifdef LOGRT #include #endif /* ifdef LOGRT */ #include "Ecore.h" #include "ecore_private.h" #include "ecore_x_private.h" #include "Ecore_X.h" #include "Ecore_X_Atoms.h" #include "Ecore_Input.h" static Eina_Bool _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler); static Eina_Bool _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler); static int _ecore_x_key_mask_get(KeySym sym); static int _ecore_x_event_modifier(unsigned int state); static Ecore_Fd_Handler *_ecore_x_fd_handler_handle = NULL; static const int AnyXEvent = 0; /* 0 can be used as there are no event types * with index 0 and 1 as they are used for * errors */ static int _ecore_x_event_shape_id = 0; static int _ecore_x_event_screensaver_id = 0; static int _ecore_x_event_sync_id = 0; int _ecore_xlib_log_dom = -1; #ifdef ECORE_XRANDR static int _ecore_x_event_randr_id = 0; #endif /* ifdef ECORE_XRANDR */ #ifdef ECORE_XFIXES static int _ecore_x_event_fixes_selection_id = 0; #endif /* ifdef ECORE_XFIXES */ #ifdef ECORE_XDAMAGE static int _ecore_x_event_damage_id = 0; #endif /* ifdef ECORE_XDAMAGE */ #ifdef ECORE_XGESTURE static int _ecore_x_event_gesture_id = 0; #endif /* ifdef ECORE_XGESTURE */ static int _ecore_x_event_handlers_num = 0; static void (**_ecore_x_event_handlers) (XEvent * event) = NULL; static int _ecore_x_init_count = 0; static int _ecore_x_grab_count = 0; Display *_ecore_x_disp = NULL; double _ecore_x_double_click_time = 0.25; Time _ecore_x_event_last_time = 0; Window _ecore_x_event_last_win = 0; int _ecore_x_event_last_root_x = 0; int _ecore_x_event_last_root_y = 0; Eina_Bool _ecore_x_xcursor = EINA_FALSE; Ecore_X_Window _ecore_x_private_win = 0; Ecore_X_Atom _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_NUM]; EAPI int ECORE_X_EVENT_ANY = 0; EAPI int ECORE_X_EVENT_MOUSE_IN = 0; EAPI int ECORE_X_EVENT_MOUSE_OUT = 0; EAPI int ECORE_X_EVENT_WINDOW_FOCUS_IN = 0; EAPI int ECORE_X_EVENT_WINDOW_FOCUS_OUT = 0; EAPI int ECORE_X_EVENT_WINDOW_KEYMAP = 0; EAPI int ECORE_X_EVENT_WINDOW_DAMAGE = 0; EAPI int ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = 0; EAPI int ECORE_X_EVENT_WINDOW_CREATE = 0; EAPI int ECORE_X_EVENT_WINDOW_DESTROY = 0; EAPI int ECORE_X_EVENT_WINDOW_HIDE = 0; EAPI int ECORE_X_EVENT_WINDOW_SHOW = 0; EAPI int ECORE_X_EVENT_WINDOW_SHOW_REQUEST = 0; EAPI int ECORE_X_EVENT_WINDOW_REPARENT = 0; EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE = 0; EAPI int ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = 0; EAPI int ECORE_X_EVENT_WINDOW_GRAVITY = 0; EAPI int ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = 0; EAPI int ECORE_X_EVENT_WINDOW_STACK = 0; EAPI int ECORE_X_EVENT_WINDOW_STACK_REQUEST = 0; EAPI int ECORE_X_EVENT_WINDOW_PROPERTY = 0; EAPI int ECORE_X_EVENT_WINDOW_COLORMAP = 0; EAPI int ECORE_X_EVENT_WINDOW_MAPPING = 0; EAPI int ECORE_X_EVENT_MAPPING_CHANGE = 0; EAPI int ECORE_X_EVENT_SELECTION_CLEAR = 0; EAPI int ECORE_X_EVENT_SELECTION_REQUEST = 0; EAPI int ECORE_X_EVENT_SELECTION_NOTIFY = 0; EAPI int ECORE_X_EVENT_FIXES_SELECTION_NOTIFY = 0; EAPI int ECORE_X_EVENT_CLIENT_MESSAGE = 0; EAPI int ECORE_X_EVENT_WINDOW_SHAPE = 0; EAPI int ECORE_X_EVENT_SCREENSAVER_NOTIFY = 0; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_FLICK; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PAN; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAP; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_HOLD; EAPI int ECORE_X_EVENT_GESTURE_NOTIFY_GROUP; EAPI int ECORE_X_EVENT_SYNC_COUNTER = 0; EAPI int ECORE_X_EVENT_SYNC_ALARM = 0; EAPI int ECORE_X_EVENT_SCREEN_CHANGE = 0; EAPI int ECORE_X_EVENT_DAMAGE_NOTIFY = 0; EAPI int ECORE_X_EVENT_RANDR_CRTC_CHANGE = 0; EAPI int ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = 0; EAPI int ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = 0; EAPI int ECORE_X_EVENT_WINDOW_DELETE_REQUEST = 0; EAPI int ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = 0; EAPI int ECORE_X_EVENT_WINDOW_STATE_REQUEST = 0; EAPI int ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = 0; EAPI int ECORE_X_EVENT_PING = 0; EAPI int ECORE_X_EVENT_DESKTOP_CHANGE = 0; EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = 0; EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = 0; EAPI int ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = 0; EAPI int ECORE_X_EVENT_GENERIC = 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; EAPI int ECORE_X_LOCK_SCROLL = 0; EAPI int ECORE_X_LOCK_NUM = 0; EAPI int ECORE_X_LOCK_CAPS = 0; EAPI int ECORE_X_LOCK_SHIFT = 0; #ifdef LOGRT static double t0 = 0.0; static Status (*_logrt_real_reply)(Display *disp, void *rep, int extra, Bool discard) = NULL; static void _logrt_init(void) { void *lib; lib = dlopen("libX11.so", RTLD_GLOBAL | RTLD_LAZY); if (!lib) lib = dlopen("libX11.so.6", RTLD_GLOBAL | RTLD_LAZY); if (!lib) lib = dlopen("libX11.so.6.3", RTLD_GLOBAL | RTLD_LAZY); if (!lib) lib = dlopen("libX11.so.6.3.0", RTLD_GLOBAL | RTLD_LAZY); _logrt_real_reply = dlsym(lib, "_XReply"); t0 = ecore_time_get(); } Status _XReply(Display *disp, void *rep, int extra, Bool discard) { void *bt[128]; int i, n; char **sym; n = backtrace(bt, 128); if (n > 0) { sym = backtrace_symbols(bt, n); printf("ROUNDTRIP: %4.4f :", ecore_time_get() - t0); if (sym) { for (i = n - 1; i > 0; i--) { char *fname = strchr(sym[i], '('); if (fname) { char *tsym = alloca(strlen(fname) + 1); char *end; strcpy(tsym, fname + 1); end = strchr(tsym, '+'); if (end) { *end = 0; printf("%s", tsym); } else printf("???"); } else printf("???"); if (i > 1) printf(" > "); } printf("\n"); } } // fixme: logme return _logrt_real_reply(disp, rep, extra, discard); } #endif /* ifdef LOGRT */ void _ecore_x_modifiers_get(void) { /* everything has these... unless its like a pda... :) */ ECORE_X_MODIFIER_SHIFT = _ecore_x_key_mask_get(XK_Shift_L); ECORE_X_MODIFIER_CTRL = _ecore_x_key_mask_get(XK_Control_L); /* apple's xdarwin has no alt!!!! */ ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Alt_L); if (!ECORE_X_MODIFIER_ALT) ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Meta_L); if (!ECORE_X_MODIFIER_ALT) ECORE_X_MODIFIER_ALT = _ecore_x_key_mask_get(XK_Super_L); /* the windows key... a valid modifier :) */ ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Super_L); if (!ECORE_X_MODIFIER_WIN) ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Mode_switch); if (!ECORE_X_MODIFIER_WIN) ECORE_X_MODIFIER_WIN = _ecore_x_key_mask_get(XK_Meta_L); if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT) ECORE_X_MODIFIER_WIN = 0; if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL) ECORE_X_MODIFIER_ALT = 0; ECORE_X_LOCK_SCROLL = _ecore_x_key_mask_get(XK_Scroll_Lock); ECORE_X_LOCK_NUM = _ecore_x_key_mask_get(XK_Num_Lock); ECORE_X_LOCK_CAPS = _ecore_x_key_mask_get(XK_Caps_Lock); ECORE_X_LOCK_SHIFT = _ecore_x_key_mask_get(XK_Shift_Lock); } /** * @defgroup Ecore_X_Init_Group X Library Init and Shutdown Functions * * Functions that start and shut down the Ecore X Library. */ /** * Initialize the X display connection to the given display. * * @param name Display target name. If @c NULL, the default display is * assumed. * @return The number of times the library has been initialized without * being shut down. 0 is returned if an error occurs. * @ingroup Ecore_X_Init_Group */ EAPI int ecore_x_init(const char *name) { int shape_base = 0; int shape_err_base = 0; #ifdef ECORE_XSS int screensaver_base = 0; int screensaver_err_base = 0; #endif /* ifdef ECORE_XSS */ int sync_base = 0; int sync_err_base = 0; #ifdef ECORE_XRANDR int randr_base = 0; int randr_err_base = 0; #endif /* ifdef ECORE_XRANDR */ #ifdef ECORE_XFIXES int fixes_base = 0; int fixes_err_base = 0; #endif /* ifdef ECORE_XFIXES */ #ifdef ECORE_XDAMAGE int damage_base = 0; int damage_err_base = 0; #endif /* ifdef ECORE_XDAMAGE */ #ifdef ECORE_XGESTURE int gesture_base = 0; int gesture_err_base = 0; #endif /* ifdef ECORE_XGESTURE */ if (++_ecore_x_init_count != 1) return _ecore_x_init_count; LOGFN(__FILE__, __LINE__, __FUNCTION__); #ifdef LOGRT _logrt_init(); #endif /* ifdef LOGRT */ eina_init(); _ecore_xlib_log_dom = eina_log_domain_register ("ecore_x", ECORE_XLIB_DEFAULT_LOG_COLOR); if(_ecore_xlib_log_dom < 0) { EINA_LOG_ERR( "Impossible to create a log domain for the Ecore Xlib module."); return --_ecore_x_init_count; } if (!ecore_init()) goto shutdown_eina; if (!ecore_event_init()) goto shutdown_ecore; #ifdef EVAS_FRAME_QUEUING XInitThreads(); #endif /* ifdef EVAS_FRAME_QUEUING */ _ecore_x_disp = XOpenDisplay((char *)name); if (!_ecore_x_disp) goto shutdown_ecore_event; _ecore_x_error_handler_init(); _ecore_x_event_handlers_num = LASTEvent; #define ECORE_X_EVENT_HANDLERS_GROW(ext_base, ext_num_events) \ do { \ if (_ecore_x_event_handlers_num < (ext_base + ext_num_events)) { \ _ecore_x_event_handlers_num = (ext_base + ext_num_events); } \ } while (0) if (XShapeQueryExtension(_ecore_x_disp, &shape_base, &shape_err_base)) _ecore_x_event_shape_id = shape_base; ECORE_X_EVENT_HANDLERS_GROW(shape_base, ShapeNumberEvents); #ifdef ECORE_XSS if (XScreenSaverQueryExtension(_ecore_x_disp, &screensaver_base, &screensaver_err_base)) _ecore_x_event_screensaver_id = screensaver_base; ECORE_X_EVENT_HANDLERS_GROW(screensaver_base, ScreenSaverNumberEvents); #endif /* ifdef ECORE_XSS */ if (XSyncQueryExtension(_ecore_x_disp, &sync_base, &sync_err_base)) { int major, minor; _ecore_x_event_sync_id = sync_base; if (!XSyncInitialize(_ecore_x_disp, &major, &minor)) _ecore_x_event_sync_id = 0; } ECORE_X_EVENT_HANDLERS_GROW(sync_base, XSyncNumberEvents); #ifdef ECORE_XRANDR if (XRRQueryExtension(_ecore_x_disp, &randr_base, &randr_err_base)) _ecore_x_event_randr_id = randr_base; ECORE_X_EVENT_HANDLERS_GROW(randr_base, RRNumberEvents); #endif /* ifdef ECORE_XRANDR */ #ifdef ECORE_XFIXES if (XFixesQueryExtension(_ecore_x_disp, &fixes_base, &fixes_err_base)) _ecore_x_event_fixes_selection_id = fixes_base; ECORE_X_EVENT_HANDLERS_GROW(fixes_base, XFixesNumberEvents); #endif /* ifdef ECORE_XFIXES */ #ifdef ECORE_XDAMAGE if (XDamageQueryExtension(_ecore_x_disp, &damage_base, &damage_err_base)) _ecore_x_event_damage_id = damage_base; ECORE_X_EVENT_HANDLERS_GROW(damage_base, XDamageNumberEvents); #endif /* ifdef ECORE_XDAMAGE */ #ifdef ECORE_XGESTURE if (XGestureQueryExtension(_ecore_x_disp, &gesture_base, &gesture_err_base)) _ecore_x_event_gesture_id = gesture_base; ECORE_X_EVENT_HANDLERS_GROW(gesture_base, GestureNumberEvents); #endif /* ifdef ECORE_XGESTURE */ _ecore_x_event_handlers = calloc(_ecore_x_event_handlers_num, sizeof(void *)); if (!_ecore_x_event_handlers) goto close_display; #ifdef ECORE_XCURSOR _ecore_x_xcursor = XcursorSupportsARGB(_ecore_x_disp) ? EINA_TRUE : EINA_FALSE; #endif /* ifdef ECORE_XCURSOR */ _ecore_x_event_handlers[AnyXEvent] = _ecore_x_event_handle_any_event; _ecore_x_event_handlers[KeyPress] = _ecore_x_event_handle_key_press; _ecore_x_event_handlers[KeyRelease] = _ecore_x_event_handle_key_release; _ecore_x_event_handlers[ButtonPress] = _ecore_x_event_handle_button_press; _ecore_x_event_handlers[ButtonRelease] = _ecore_x_event_handle_button_release; _ecore_x_event_handlers[MotionNotify] = _ecore_x_event_handle_motion_notify; _ecore_x_event_handlers[EnterNotify] = _ecore_x_event_handle_enter_notify; _ecore_x_event_handlers[LeaveNotify] = _ecore_x_event_handle_leave_notify; _ecore_x_event_handlers[FocusIn] = _ecore_x_event_handle_focus_in; _ecore_x_event_handlers[FocusOut] = _ecore_x_event_handle_focus_out; _ecore_x_event_handlers[KeymapNotify] = _ecore_x_event_handle_keymap_notify; _ecore_x_event_handlers[Expose] = _ecore_x_event_handle_expose; _ecore_x_event_handlers[GraphicsExpose] = _ecore_x_event_handle_graphics_expose; _ecore_x_event_handlers[VisibilityNotify] = _ecore_x_event_handle_visibility_notify; _ecore_x_event_handlers[CreateNotify] = _ecore_x_event_handle_create_notify; _ecore_x_event_handlers[DestroyNotify] = _ecore_x_event_handle_destroy_notify; _ecore_x_event_handlers[UnmapNotify] = _ecore_x_event_handle_unmap_notify; _ecore_x_event_handlers[MapNotify] = _ecore_x_event_handle_map_notify; _ecore_x_event_handlers[MapRequest] = _ecore_x_event_handle_map_request; _ecore_x_event_handlers[ReparentNotify] = _ecore_x_event_handle_reparent_notify; _ecore_x_event_handlers[ConfigureNotify] = _ecore_x_event_handle_configure_notify; _ecore_x_event_handlers[ConfigureRequest] = _ecore_x_event_handle_configure_request; _ecore_x_event_handlers[GravityNotify] = _ecore_x_event_handle_gravity_notify; _ecore_x_event_handlers[ResizeRequest] = _ecore_x_event_handle_resize_request; _ecore_x_event_handlers[CirculateNotify] = _ecore_x_event_handle_circulate_notify; _ecore_x_event_handlers[CirculateRequest] = _ecore_x_event_handle_circulate_request; _ecore_x_event_handlers[PropertyNotify] = _ecore_x_event_handle_property_notify; _ecore_x_event_handlers[SelectionClear] = _ecore_x_event_handle_selection_clear; _ecore_x_event_handlers[SelectionRequest] = _ecore_x_event_handle_selection_request; _ecore_x_event_handlers[SelectionNotify] = _ecore_x_event_handle_selection_notify; _ecore_x_event_handlers[ColormapNotify] = _ecore_x_event_handle_colormap_notify; _ecore_x_event_handlers[ClientMessage] = _ecore_x_event_handle_client_message; _ecore_x_event_handlers[MappingNotify] = _ecore_x_event_handle_mapping_notify; #ifdef GenericEvent _ecore_x_event_handlers[GenericEvent] = _ecore_x_event_handle_generic_event; #endif /* ifdef GenericEvent */ if (_ecore_x_event_shape_id) _ecore_x_event_handlers[_ecore_x_event_shape_id] = _ecore_x_event_handle_shape_change; if (_ecore_x_event_screensaver_id) _ecore_x_event_handlers[_ecore_x_event_screensaver_id] = _ecore_x_event_handle_screensaver_notify; if (_ecore_x_event_sync_id) { _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncCounterNotify] = _ecore_x_event_handle_sync_counter; _ecore_x_event_handlers[_ecore_x_event_sync_id + XSyncAlarmNotify] = _ecore_x_event_handle_sync_alarm; } #ifdef ECORE_XRANDR if (_ecore_x_event_randr_id) { _ecore_x_event_handlers[_ecore_x_event_randr_id + RRScreenChangeNotify] = _ecore_x_event_handle_randr_change; _ecore_x_event_handlers[_ecore_x_event_randr_id + RRNotify] = _ecore_x_event_handle_randr_notify; } #endif /* ifdef ECORE_XRANDR */ #ifdef ECORE_XFIXES if (_ecore_x_event_fixes_selection_id) _ecore_x_event_handlers[_ecore_x_event_fixes_selection_id] = _ecore_x_event_handle_fixes_selection_notify; #endif /* ifdef ECORE_XFIXES */ #ifdef ECORE_XDAMAGE if (_ecore_x_event_damage_id) _ecore_x_event_handlers[_ecore_x_event_damage_id] = _ecore_x_event_handle_damage_notify; #endif /* ifdef ECORE_XDAMAGE */ #ifdef ECORE_XKB // set x autorepeat detection to on. that means instead of // press-release-press-release-press-release // you get // press-press-press-press-press-release do { Bool works = 0; XkbSetDetectableAutoRepeat(_ecore_x_disp, 1, &works); } while (0); #endif /* ifdef ECORE_XKB */ #ifdef ECORE_XGESTURE if (_ecore_x_event_gesture_id) { _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyFlick] = _ecore_x_event_handle_gesture_notify_flick; _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyPan] = _ecore_x_event_handle_gesture_notify_pan; _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyPinchRotation] = _ecore_x_event_handle_gesture_notify_pinchrotation; _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyTap] = _ecore_x_event_handle_gesture_notify_tap; _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyTapNHold] = _ecore_x_event_handle_gesture_notify_tapnhold; _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyHold] = _ecore_x_event_handle_gesture_notify_hold; _ecore_x_event_handlers[_ecore_x_event_gesture_id + GestureNotifyGroup] = _ecore_x_event_handle_gesture_notify_group; } #endif /* ifdef ECORE_XGESTURE */ if (!ECORE_X_EVENT_ANY) { ECORE_X_EVENT_ANY = ecore_event_type_new(); ECORE_X_EVENT_MOUSE_IN = ecore_event_type_new(); ECORE_X_EVENT_MOUSE_OUT = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_FOCUS_IN = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_FOCUS_OUT = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_KEYMAP = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_DAMAGE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_VISIBILITY_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_CREATE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_DESTROY = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_HIDE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_SHOW = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_SHOW_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_REPARENT = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_CONFIGURE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_GRAVITY = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_RESIZE_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_STACK = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_STACK_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_PROPERTY = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_COLORMAP = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_MAPPING = ecore_event_type_new(); ECORE_X_EVENT_MAPPING_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_SELECTION_CLEAR = ecore_event_type_new(); ECORE_X_EVENT_SELECTION_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_SELECTION_NOTIFY = ecore_event_type_new(); ECORE_X_EVENT_CLIENT_MESSAGE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_SHAPE = ecore_event_type_new(); ECORE_X_EVENT_SCREENSAVER_NOTIFY = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_FLICK = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_PAN = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_PINCHROTATION = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_TAP = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_TAPNHOLD = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_HOLD = ecore_event_type_new(); ECORE_X_EVENT_GESTURE_NOTIFY_GROUP = ecore_event_type_new(); ECORE_X_EVENT_SYNC_COUNTER = ecore_event_type_new(); ECORE_X_EVENT_SYNC_ALARM = ecore_event_type_new(); ECORE_X_EVENT_SCREEN_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_RANDR_CRTC_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_RANDR_OUTPUT_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY = ecore_event_type_new(); ECORE_X_EVENT_DAMAGE_NOTIFY = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_DELETE_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_DESKTOP_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_WINDOW_STATE_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_FRAME_EXTENTS_REQUEST = ecore_event_type_new(); ECORE_X_EVENT_PING = ecore_event_type_new(); ECORE_X_EVENT_STARTUP_SEQUENCE_NEW = ecore_event_type_new(); ECORE_X_EVENT_STARTUP_SEQUENCE_CHANGE = ecore_event_type_new(); ECORE_X_EVENT_STARTUP_SEQUENCE_REMOVE = ecore_event_type_new(); ECORE_X_EVENT_GENERIC = ecore_event_type_new(); } _ecore_x_modifiers_get(); _ecore_x_fd_handler_handle = ecore_main_fd_handler_add(ConnectionNumber(_ecore_x_disp), ECORE_FD_READ, _ecore_x_fd_handler, _ecore_x_disp, _ecore_x_fd_handler_buf, _ecore_x_disp); if (!_ecore_x_fd_handler_handle) goto free_event_handlers; _ecore_x_atoms_init(); /* Set up the ICCCM hints */ ecore_x_icccm_init(); /* Set up the _NET_... hints */ ecore_x_netwm_init(); /* old e hints init */ ecore_x_e_init(); /* This is just to be anal about naming conventions */ _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_DELETE_REQUEST] = ECORE_X_ATOM_WM_DELETE_WINDOW; _ecore_x_atoms_wm_protocols[ECORE_X_WM_PROTOCOL_TAKE_FOCUS] = ECORE_X_ATOM_WM_TAKE_FOCUS; _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_PING] = ECORE_X_ATOM_NET_WM_PING; _ecore_x_atoms_wm_protocols[ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST] = ECORE_X_ATOM_NET_WM_SYNC_REQUEST; _ecore_x_selection_data_init(); _ecore_x_dnd_init(); _ecore_x_fixes_init(); _ecore_x_damage_init(); _ecore_x_composite_init(); _ecore_x_dpms_init(); _ecore_x_randr_init(); _ecore_x_gesture_init(); _ecore_x_input_init(); _ecore_x_events_init(); _ecore_x_private_win = ecore_x_window_override_new(0, -77, -777, 123, 456); return _ecore_x_init_count; free_event_handlers: free(_ecore_x_event_handlers); _ecore_x_event_handlers = NULL; close_display: XCloseDisplay(_ecore_x_disp); _ecore_x_fd_handler_handle = NULL; _ecore_x_disp = NULL; shutdown_ecore_event: ecore_event_shutdown(); shutdown_ecore: ecore_shutdown(); shutdown_eina: eina_log_domain_unregister(_ecore_xlib_log_dom); _ecore_xlib_log_dom = -1; eina_shutdown(); return --_ecore_x_init_count; } static int _ecore_x_shutdown(int close_display) { if (--_ecore_x_init_count != 0) return _ecore_x_init_count; if (!_ecore_x_disp) return _ecore_x_init_count; LOGFN(__FILE__, __LINE__, __FUNCTION__); ecore_main_fd_handler_del(_ecore_x_fd_handler_handle); if (close_display) XCloseDisplay(_ecore_x_disp); else { close(ConnectionNumber(_ecore_x_disp)); // FIXME: may have to clean up x display internal here // getting segv here? hmmm. odd. disable // XFree(_ecore_x_disp); } free(_ecore_x_event_handlers); _ecore_x_fd_handler_handle = NULL; _ecore_x_disp = NULL; _ecore_x_event_handlers = NULL; _ecore_x_events_shutdown(); _ecore_x_input_shutdown(); _ecore_x_selection_shutdown(); _ecore_x_dnd_shutdown(); ecore_x_netwm_shutdown(); ecore_event_shutdown(); ecore_shutdown(); eina_log_domain_unregister(_ecore_xlib_log_dom); _ecore_xlib_log_dom = -1; eina_shutdown(); return _ecore_x_init_count; } /** * Shuts down the Ecore X library. * * In shutting down the library, the X display connection is terminated * and any event handlers for it are removed. * * @return The number of times the library has been initialized without * being shut down. * @ingroup Ecore_X_Init_Group */ EAPI int ecore_x_shutdown(void) { return _ecore_x_shutdown(1); } /** * Shuts down the Ecore X library. * * As ecore_x_shutdown, except do not close Display, only connection. * * @ingroup Ecore_X_Init_Group */ EAPI int ecore_x_disconnect(void) { return _ecore_x_shutdown(0); } /** * @defgroup Ecore_X_Display_Attr_Group X Display Attributes * * Functions that set and retrieve X display attributes. */ /** * Retrieves the Ecore_X_Display handle used for the current X connection. * @return The current X display. * @ingroup Ecore_X_Display_Attr_Group */ EAPI Ecore_X_Display * ecore_x_display_get(void) { return (Ecore_X_Display *)_ecore_x_disp; } /** * Retrieves the X display file descriptor. * @return The current X display file descriptor. * @ingroup Ecore_X_Display_Attr_Group */ EAPI int ecore_x_fd_get(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return ConnectionNumber(_ecore_x_disp); } /** * Retrieves the Ecore_X_Screen handle used for the current X connection. * @return The current default screen. * @ingroup Ecore_X_Display_Attr_Group */ EAPI Ecore_X_Screen * ecore_x_default_screen_get(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return (Ecore_X_Screen *)DefaultScreenOfDisplay(_ecore_x_disp); } /** * Retrieves the size of an Ecore_X_Screen. * @param screen the handle to the screen to query. * @param w where to return the width. May be NULL. Returns 0 on errors. * @param h where to return the height. May be NULL. Returns 0 on errors. * @ingroup Ecore_X_Display_Attr_Group * @see ecore_x_default_screen_get() * * @since 1.1 */ EAPI void ecore_x_screen_size_get(const Ecore_X_Screen *screen, int *w, int *h) { Screen *s = (Screen *)screen; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (w) *w = 0; if (h) *h = 0; if (!s) return; if (w) *w = s->width; if (h) *h = s->height; } /** * Retrieves the number of screens. * * @return The count of the number of screens. * @ingroup Ecore_X_Display_Attr_Group * * @since 1.1 */ EAPI int ecore_x_screen_count_get(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return ScreenCount(_ecore_x_disp); } /** * Retrieves the index number of the given screen. * * @return The index number of the screen. * @ingroup Ecore_X_Display_Attr_Group * * @since 1.1 */ EAPI int ecore_x_screen_index_get(const Ecore_X_Screen *screen) { return XScreenNumberOfScreen((Screen *)screen); } /** * Retrieves the screen based on index number. * * @return The Ecore_X_Screen at this index. * @ingroup Ecore_X_Display_Attr_Group * * @since 1.1 */ EAPI Ecore_X_Screen * ecore_x_screen_get(int idx) { return XScreenOfDisplay(_ecore_x_disp, idx); } /** * Sets the timeout for a double and triple clicks to be flagged. * * This sets the time between clicks before the double_click flag is * set in a button down event. If 3 clicks occur within double this * time, the triple_click flag is also set. * * @param t The time in seconds * @ingroup Ecore_X_Display_Attr_Group */ EAPI void ecore_x_double_click_time_set(double t) { if (t < 0.0) t = 0.0; _ecore_x_double_click_time = t; } /** * Retrieves the double and triple click flag timeout. * * See @ref ecore_x_double_click_time_set for more information. * * @return The timeout for double clicks in seconds. * @ingroup Ecore_X_Display_Attr_Group */ EAPI double ecore_x_double_click_time_get(void) { return _ecore_x_double_click_time; } /** * @defgroup Ecore_X_Flush_Group X Synchronization Functions * * Functions that ensure that all commands that have been issued by the * Ecore X library have been sent to the server. */ /** * Sends all X commands in the X Display buffer. * @ingroup Ecore_X_Flush_Group */ EAPI void ecore_x_flush(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XFlush(_ecore_x_disp); } /** * Flushes the command buffer and waits until all requests have been * processed by the server. * @ingroup Ecore_X_Flush_Group */ EAPI void ecore_x_sync(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XSync(_ecore_x_disp, False); } /** * Kill all clients with subwindows under a given window. * * You can kill all clients connected to the X server by using * @ref ecore_x_window_root_list to get a list of root windows, and * then passing each root window to this function. * * @param root The window whose children will be killed. */ EAPI void ecore_x_killall(Ecore_X_Window root) { unsigned int j; Window root_r; Window parent_r; Window *children_r = NULL; unsigned int num_children = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); XGrabServer(_ecore_x_disp); /* Tranverse window tree starting from root, and drag each * before the firing squad */ while (XQueryTree(_ecore_x_disp, root, &root_r, &parent_r, &children_r, &num_children) && (num_children > 0)) { for (j = 0; j < num_children; ++j) { XKillClient(_ecore_x_disp, children_r[j]); } XFree(children_r); } XUngrabServer(_ecore_x_disp); XSync(_ecore_x_disp, False); } /** * Kill a specific client * * You can kill a specific client owning window @p win * * @param win Window of the client to be killed */ EAPI void ecore_x_kill(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XKillClient(_ecore_x_disp, win); } /** * Return the last event time */ EAPI Ecore_X_Time ecore_x_current_time_get(void) { return _ecore_x_event_last_time; } /** * Return the screen DPI * * This is a simplistic call to get DPI. It does not account for differing * DPI in the x amd y axes nor does it accoutn for multihead or xinerama and * xrander where different parts of the screen may have differen DPI etc. * * @return the general screen DPI (dots/pixels per inch). */ EAPI int ecore_x_dpi_get(void) { Screen *s; LOGFN(__FILE__, __LINE__, __FUNCTION__); s = DefaultScreenOfDisplay(_ecore_x_disp); if (s->mwidth <= 0) return 75; return (((s->width * 254) / s->mwidth) + 5) / 10; } /** * Invoke the standard system beep to alert users * * @param percent The volume at which the bell rings. Must be in the range * [-100,+100]. If percent >= 0, the final volume will be: * base - [(base * percent) / 100] + percent * Otherwise, it's calculated as: * base + [(base * percent) / 100] * where @c base is the bell's base volume as set by XChangeKeyboardControl(3). * * @returns EINA_TRUE on success, EINA_FALSE otherwise. */ EAPI Eina_Bool ecore_x_bell(int percent) { int ret; ret = XBell(_ecore_x_disp, percent); if (ret == BadValue) return EINA_FALSE; return EINA_TRUE; } static Eina_Bool _ecore_x_fd_handler(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) { Display *d; d = data; while (XPending(d)) { XEvent ev; XNextEvent(d, &ev); #ifdef ENABLE_XIM /* Filter event for XIM */ if (XFilterEvent(&ev, ev.xkey.window)) continue; #endif /* ifdef ENABLE_XIM */ if ((ev.type >= 0) && (ev.type < _ecore_x_event_handlers_num)) { if (_ecore_x_event_handlers[AnyXEvent]) _ecore_x_event_handlers[AnyXEvent] (&ev); if (_ecore_x_event_handlers[ev.type]) _ecore_x_event_handlers[ev.type] (&ev); } } return ECORE_CALLBACK_RENEW; } static Eina_Bool _ecore_x_fd_handler_buf(void *data, Ecore_Fd_Handler *fd_handler __UNUSED__) { Display *d; d = data; if (XPending(d)) return ECORE_CALLBACK_RENEW; return ECORE_CALLBACK_CANCEL; } static int _ecore_x_key_mask_get(KeySym sym) { XModifierKeymap *mod; KeySym sym2; int i, j; const int masks[8] = { ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; mod = XGetModifierMapping(_ecore_x_disp); if ((mod) && (mod->max_keypermod > 0)) for (i = 0; i < (8 * mod->max_keypermod); i++) { for (j = 0; j < 8; j++) { sym2 = XKeycodeToKeysym(_ecore_x_disp, mod->modifiermap[i], j); if (sym2 != 0) break; } if (sym2 == sym) { int mask; mask = masks[i / mod->max_keypermod]; if (mod->modifiermap) XFree(mod->modifiermap); XFree(mod); return mask; } } if (mod) { if (mod->modifiermap) XFree(mod->modifiermap); XFree(mod); } return 0; } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ /* FIXME: these funcs need categorising */ /*****************************************************************************/ /** * Get a list of all the root windows on the server. * * @note The returned array will need to be freed after use. * @param num_ret Pointer to integer to put number of windows returned in. * @return An array of all the root windows. @c NULL is returned if memory * could not be allocated for the list, or if @p num_ret is @c NULL. */ EAPI Ecore_X_Window * ecore_x_window_root_list(int *num_ret) { int num, i; Ecore_X_Window *roots; #ifdef ECORE_XPRINT int xp_base, xp_err_base; #endif /* ifdef ECORE_XPRINT */ if (!num_ret) return NULL; *num_ret = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); #ifdef ECORE_XPRINT num = ScreenCount(_ecore_x_disp); if (XpQueryExtension(_ecore_x_disp, &xp_base, &xp_err_base)) { Screen **ps = NULL; int psnum = 0; ps = XpQueryScreens(_ecore_x_disp, &psnum); if (ps) { int overlap, j; overlap = 0; for (i = 0; i < num; i++) { for (j = 0; j < psnum; j++) { if (ScreenOfDisplay(_ecore_x_disp, i) == ps[j]) overlap++; } } roots = malloc((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 { roots = malloc(num * sizeof(Window)); if (!roots) return NULL; *num_ret = num; for (i = 0; i < num; i++) roots[i] = RootWindow(_ecore_x_disp, i); } #else /* ifdef ECORE_XPRINT */ num = ScreenCount(_ecore_x_disp); roots = malloc(num * sizeof(Window)); if (!roots) return NULL; *num_ret = num; for (i = 0; i < num; i++) roots[i] = RootWindow(_ecore_x_disp, i); #endif /* ifdef ECORE_XPRINT */ return roots; } EAPI Ecore_X_Window ecore_x_window_root_first_get(void) { return RootWindow(_ecore_x_disp, 0); /* int num; Ecore_X_Window root, *roots = NULL; LOGFN(__FILE__, __LINE__, __FUNCTION__); roots = ecore_x_window_root_list(&num); if (!(roots)) return 0; if (num > 0) root = roots[0]; else root = 0; free(roots); return root; */ } static void _ecore_x_window_manage_error(void *data); static int _ecore_x_window_manage_failed = 0; static void _ecore_x_window_manage_error(void *data __UNUSED__) { if ((ecore_x_error_request_get() == X_ChangeWindowAttributes) && (ecore_x_error_code_get() == BadAccess)) _ecore_x_window_manage_failed = 1; } EAPI Eina_Bool ecore_x_window_manage(Ecore_X_Window win) { XWindowAttributes att; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (XGetWindowAttributes(_ecore_x_disp, win, &att) != True) return EINA_FALSE; ecore_x_sync(); _ecore_x_window_manage_failed = 0; ecore_x_error_handler_set(_ecore_x_window_manage_error, NULL); XSelectInput(_ecore_x_disp, win, EnterWindowMask | LeaveWindowMask | PropertyChangeMask | ResizeRedirectMask | SubstructureRedirectMask | SubstructureNotifyMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask | att.your_event_mask); ecore_x_sync(); ecore_x_error_handler_set(NULL, NULL); if (_ecore_x_window_manage_failed) { _ecore_x_window_manage_failed = 0; return EINA_FALSE; } return EINA_TRUE; } EAPI void ecore_x_window_container_manage(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XSelectInput(_ecore_x_disp, win, SubstructureRedirectMask | SubstructureNotifyMask); } EAPI void ecore_x_window_client_manage(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XSelectInput(_ecore_x_disp, win, PropertyChangeMask | // ResizeRedirectMask | FocusChangeMask | ColormapChangeMask | VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask ); XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); } EAPI void ecore_x_window_sniff(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XSelectInput(_ecore_x_disp, win, PropertyChangeMask | SubstructureNotifyMask); } EAPI void ecore_x_window_client_sniff(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XSelectInput(_ecore_x_disp, win, PropertyChangeMask | FocusChangeMask | ColormapChangeMask | VisibilityChangeMask | StructureNotifyMask | SubstructureNotifyMask); XShapeSelectInput(_ecore_x_disp, win, ShapeNotifyMask); } EAPI Eina_Bool ecore_x_window_attributes_get(Ecore_X_Window win, Ecore_X_Window_Attributes *att_ret) { XWindowAttributes att; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!XGetWindowAttributes(_ecore_x_disp, win, &att)) return EINA_FALSE; memset(att_ret, 0, sizeof(Ecore_X_Window_Attributes)); att_ret->root = att.root; att_ret->x = att.x; att_ret->y = att.y; att_ret->w = att.width; att_ret->h = att.height; att_ret->border = att.border_width; att_ret->depth = att.depth; if (att.map_state != IsUnmapped) att_ret->visible = 1; if (att.map_state == IsViewable) att_ret->viewable = 1; if (att.override_redirect) att_ret->override = 1; if (att.class == InputOnly) att_ret->input_only = 1; if (att.save_under) att_ret->save_under = 1; att_ret->event_mask.mine = att.your_event_mask; att_ret->event_mask.all = att.all_event_masks; att_ret->event_mask.no_propagate = att.do_not_propagate_mask; att_ret->window_gravity = att.win_gravity; att_ret->pixel_gravity = att.bit_gravity; att_ret->colormap = att.colormap; att_ret->visual = att.visual; return EINA_TRUE; } EAPI void ecore_x_window_save_set_add(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XAddToSaveSet(_ecore_x_disp, win); } EAPI void ecore_x_window_save_set_del(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XRemoveFromSaveSet(_ecore_x_disp, win); } EAPI Ecore_X_Window * ecore_x_window_children_get(Ecore_X_Window win, int *num) { Ecore_X_Window *windows = NULL; Window root_ret = 0, parent_ret = 0, *children_ret = NULL; unsigned int children_ret_num = 0; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!XQueryTree(_ecore_x_disp, win, &root_ret, &parent_ret, &children_ret, &children_ret_num)) return NULL; if (children_ret) { windows = malloc(children_ret_num * sizeof(Ecore_X_Window)); if (windows) { unsigned int i; for (i = 0; i < children_ret_num; i++) windows[i] = children_ret[i]; *num = children_ret_num; } XFree(children_ret); } return windows; } EAPI Eina_Bool ecore_x_pointer_control_set(int accel_num, int accel_denom, int threshold) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return XChangePointerControl(_ecore_x_disp, 1, 1, accel_num, accel_denom, threshold) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_pointer_control_get(int *accel_num, int *accel_denom, int *threshold) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return XGetPointerControl(_ecore_x_disp, accel_num, accel_denom, threshold) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_pointer_mapping_set(unsigned char *map, int nmap) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return XSetPointerMapping(_ecore_x_disp, map, nmap) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_pointer_mapping_get(unsigned char *map, int nmap) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return XGetPointerMapping(_ecore_x_disp, map, nmap) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_pointer_grab(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (XGrabPointer(_ecore_x_disp, win, False, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime) == GrabSuccess) return EINA_TRUE; return EINA_FALSE; } EAPI Eina_Bool ecore_x_pointer_confine_grab(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (XGrabPointer(_ecore_x_disp, win, False, ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, win, None, CurrentTime) == GrabSuccess) return EINA_TRUE; return EINA_FALSE; } EAPI void ecore_x_pointer_ungrab(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XUngrabPointer(_ecore_x_disp, CurrentTime); } EAPI Eina_Bool ecore_x_pointer_warp(Ecore_X_Window win, int x, int y) { LOGFN(__FILE__, __LINE__, __FUNCTION__); return XWarpPointer(_ecore_x_disp, None, win, 0, 0, 0, 0, x, y) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_keyboard_grab(Ecore_X_Window win) { LOGFN(__FILE__, __LINE__, __FUNCTION__); if (XGrabKeyboard(_ecore_x_disp, win, False, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) return EINA_TRUE; return EINA_FALSE; } EAPI void ecore_x_keyboard_ungrab(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XUngrabKeyboard(_ecore_x_disp, CurrentTime); } EAPI void ecore_x_grab(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); _ecore_x_grab_count++; if (_ecore_x_grab_count == 1) XGrabServer(_ecore_x_disp); } EAPI void ecore_x_ungrab(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); _ecore_x_grab_count--; if (_ecore_x_grab_count < 0) _ecore_x_grab_count = 0; if (_ecore_x_grab_count == 0) XUngrabServer(_ecore_x_disp); } int _ecore_window_grabs_num = 0; Window *_ecore_window_grabs = NULL; Eina_Bool (*_ecore_window_grab_replay_func)(void *data, int event_type, void *event); void *_ecore_window_grab_replay_data; EAPI void ecore_x_passive_grab_replay_func_set(Eina_Bool (*func)(void *data, int event_type, void *event), void *data) { LOGFN(__FILE__, __LINE__, __FUNCTION__); _ecore_window_grab_replay_func = func; _ecore_window_grab_replay_data = data; } EAPI void ecore_x_window_button_grab(Ecore_X_Window win, int button, Ecore_X_Event_Mask event_mask, int mod, int any_mod) { unsigned int b; unsigned int m; unsigned int locks[8]; int i, ev; Window *t; LOGFN(__FILE__, __LINE__, __FUNCTION__); b = button; if (b == 0) b = AnyButton; m = _ecore_x_event_modifier(mod); if (any_mod) m = AnyModifier; locks[0] = 0; locks[1] = ECORE_X_LOCK_CAPS; locks[2] = ECORE_X_LOCK_NUM; locks[3] = ECORE_X_LOCK_SCROLL; locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; ev = event_mask; for (i = 0; i < 8; i++) XGrabButton(_ecore_x_disp, b, m | locks[i], win, False, ev, GrabModeSync, GrabModeAsync, None, None); _ecore_window_grabs_num++; t = realloc(_ecore_window_grabs, _ecore_window_grabs_num * sizeof(Window)); if (!t) return; _ecore_window_grabs = t; _ecore_window_grabs[_ecore_window_grabs_num - 1] = win; } void _ecore_x_sync_magic_send(int val, Ecore_X_Window swin) { XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.display = _ecore_x_disp; xev.xclient.window = _ecore_x_private_win; xev.xclient.format = 32; xev.xclient.message_type = 27777; xev.xclient.data.l[0] = 0x7162534; xev.xclient.data.l[1] = 0x10000000 + val; xev.xclient.data.l[2] = swin; XSendEvent(_ecore_x_disp, _ecore_x_private_win, False, NoEventMask, &xev); } void _ecore_x_window_grab_remove(Ecore_X_Window win) { int i, shuffle = 0; Window *t; if (_ecore_window_grabs_num > 0) { for (i = 0; i < _ecore_window_grabs_num; i++) { if (shuffle) _ecore_window_grabs[i - 1] = _ecore_window_grabs[i]; if ((!shuffle) && (_ecore_window_grabs[i] == win)) shuffle = 1; } if (shuffle) { _ecore_window_grabs_num--; if (_ecore_window_grabs_num <= 0) { free(_ecore_window_grabs); _ecore_window_grabs = NULL; return; } t = realloc(_ecore_window_grabs, _ecore_window_grabs_num * sizeof(Window)); if (!t) return; _ecore_window_grabs = t; } } } EAPI void ecore_x_window_button_ungrab(Ecore_X_Window win, int button, int mod, int any_mod) { unsigned int b; unsigned int m; unsigned int locks[8]; int i; LOGFN(__FILE__, __LINE__, __FUNCTION__); b = button; if (b == 0) b = AnyButton; m = _ecore_x_event_modifier(mod); if (any_mod) m = AnyModifier; locks[0] = 0; locks[1] = ECORE_X_LOCK_CAPS; locks[2] = ECORE_X_LOCK_NUM; locks[3] = ECORE_X_LOCK_SCROLL; locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; for (i = 0; i < 8; i++) XUngrabButton(_ecore_x_disp, b, m | locks[i], win); _ecore_x_sync_magic_send(1, win); } int _ecore_key_grabs_num = 0; Window *_ecore_key_grabs = NULL; EAPI void ecore_x_window_key_grab(Ecore_X_Window win, const char *key, int mod, int any_mod) { KeyCode keycode = 0; KeySym keysym; unsigned int m; unsigned int locks[8]; int i; Window *t; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!strncmp(key, "Keycode-", 8)) keycode = atoi(key + 8); else { keysym = XStringToKeysym(key); if (keysym == NoSymbol) return; keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key)); } if (keycode == 0) return; m = _ecore_x_event_modifier(mod); if (any_mod) m = AnyModifier; locks[0] = 0; locks[1] = ECORE_X_LOCK_CAPS; locks[2] = ECORE_X_LOCK_NUM; locks[3] = ECORE_X_LOCK_SCROLL; locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; for (i = 0; i < 8; i++) XGrabKey(_ecore_x_disp, keycode, m | locks[i], win, False, GrabModeSync, GrabModeAsync); _ecore_key_grabs_num++; t = realloc(_ecore_key_grabs, _ecore_key_grabs_num * sizeof(Window)); if (!t) return; _ecore_key_grabs = t; _ecore_key_grabs[_ecore_key_grabs_num - 1] = win; } void _ecore_x_key_grab_remove(Ecore_X_Window win) { int i, shuffle = 0; Window *t; if (_ecore_key_grabs_num > 0) { for (i = 0; i < _ecore_key_grabs_num; i++) { if (shuffle) _ecore_key_grabs[i - 1] = _ecore_key_grabs[i]; if ((!shuffle) && (_ecore_key_grabs[i] == win)) shuffle = 1; } if (shuffle) { _ecore_key_grabs_num--; if (_ecore_key_grabs_num <= 0) { free(_ecore_key_grabs); _ecore_key_grabs = NULL; return; } t = realloc(_ecore_key_grabs, _ecore_key_grabs_num * sizeof(Window)); if (!t) return; _ecore_key_grabs = t; } } } EAPI void ecore_x_window_key_ungrab(Ecore_X_Window win, const char *key, int mod, int any_mod) { KeyCode keycode = 0; KeySym keysym; unsigned int m; unsigned int locks[8]; int i; LOGFN(__FILE__, __LINE__, __FUNCTION__); if (!strncmp(key, "Keycode-", 8)) keycode = atoi(key + 8); else { keysym = XStringToKeysym(key); if (keysym == NoSymbol) return; keycode = XKeysymToKeycode(_ecore_x_disp, XStringToKeysym(key)); } if (keycode == 0) return; m = _ecore_x_event_modifier(mod); if (any_mod) m = AnyModifier; locks[0] = 0; locks[1] = ECORE_X_LOCK_CAPS; locks[2] = ECORE_X_LOCK_NUM; locks[3] = ECORE_X_LOCK_SCROLL; locks[4] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM; locks[5] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_SCROLL; locks[6] = ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; locks[7] = ECORE_X_LOCK_CAPS | ECORE_X_LOCK_NUM | ECORE_X_LOCK_SCROLL; for (i = 0; i < 8; i++) XUngrabKey(_ecore_x_disp, keycode, m | locks[i], win); _ecore_x_sync_magic_send(2, win); } /** * Send client message with given type and format 32. * * @param win The window the message is sent to. * @param type The client message type. * @param 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 EINA_TRUE on success EINA_FALSE otherwise. */ EAPI Eina_Bool ecore_x_client_message32_send(Ecore_X_Window win, Ecore_X_Atom type, Ecore_X_Event_Mask mask, long d0, long d1, long d2, long d3, long d4) { XEvent xev; LOGFN(__FILE__, __LINE__, __FUNCTION__); xev.xclient.window = win; xev.xclient.type = ClientMessage; xev.xclient.message_type = type; xev.xclient.format = 32; xev.xclient.data.l[0] = d0; xev.xclient.data.l[1] = d1; xev.xclient.data.l[2] = d2; xev.xclient.data.l[3] = d3; xev.xclient.data.l[4] = d4; return XSendEvent(_ecore_x_disp, win, False, mask, &xev) ? EINA_TRUE : EINA_FALSE; } /** * Send client message with given type and format 8. * * @param win The window the message is sent to. * @param type The client message type. * @param data Data to be sent. * @param len Number of data bytes, max 20. * * @return EINA_TRUE on success EINA_FALSE otherwise. */ EAPI Eina_Bool ecore_x_client_message8_send(Ecore_X_Window win, Ecore_X_Atom type, const void *data, int len) { XEvent xev; LOGFN(__FILE__, __LINE__, __FUNCTION__); xev.xclient.window = win; xev.xclient.type = ClientMessage; xev.xclient.message_type = type; xev.xclient.format = 8; if (len > 20) len = 20; memcpy(xev.xclient.data.b, data, len); memset(xev.xclient.data.b + len, 0, 20 - len); return XSendEvent(_ecore_x_disp, win, False, NoEventMask, &xev) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_mouse_move_send(Ecore_X_Window win, int x, int y) { XEvent xev; XWindowAttributes att; Window tw; int rx, ry; LOGFN(__FILE__, __LINE__, __FUNCTION__); XGetWindowAttributes(_ecore_x_disp, win, &att); XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); xev.xmotion.type = MotionNotify; xev.xmotion.window = win; xev.xmotion.root = att.root; xev.xmotion.subwindow = win; xev.xmotion.time = _ecore_x_event_last_time; xev.xmotion.x = x; xev.xmotion.y = y; xev.xmotion.x_root = rx; xev.xmotion.y_root = ry; xev.xmotion.state = 0; xev.xmotion.is_hint = 0; xev.xmotion.same_screen = 1; return XSendEvent(_ecore_x_disp, win, True, PointerMotionMask, &xev) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_mouse_down_send(Ecore_X_Window win, int x, int y, int b) { XEvent xev; XWindowAttributes att; Window tw; int rx, ry; LOGFN(__FILE__, __LINE__, __FUNCTION__); XGetWindowAttributes(_ecore_x_disp, win, &att); XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); xev.xbutton.type = ButtonPress; xev.xbutton.window = win; xev.xbutton.root = att.root; xev.xbutton.subwindow = win; xev.xbutton.time = _ecore_x_event_last_time; xev.xbutton.x = x; xev.xbutton.y = y; xev.xbutton.x_root = rx; xev.xbutton.y_root = ry; xev.xbutton.state = 1 << b; xev.xbutton.button = b; xev.xbutton.same_screen = 1; return XSendEvent(_ecore_x_disp, win, True, ButtonPressMask, &xev) ? EINA_TRUE : EINA_FALSE; } EAPI Eina_Bool ecore_x_mouse_up_send(Ecore_X_Window win, int x, int y, int b) { XEvent xev; XWindowAttributes att; Window tw; int rx, ry; LOGFN(__FILE__, __LINE__, __FUNCTION__); XGetWindowAttributes(_ecore_x_disp, win, &att); XTranslateCoordinates(_ecore_x_disp, win, att.root, x, y, &rx, &ry, &tw); xev.xbutton.type = ButtonRelease; xev.xbutton.window = win; xev.xbutton.root = att.root; xev.xbutton.subwindow = win; xev.xbutton.time = _ecore_x_event_last_time; xev.xbutton.x = x; xev.xbutton.y = y; xev.xbutton.x_root = rx; xev.xbutton.y_root = ry; xev.xbutton.state = 0; xev.xbutton.button = b; xev.xbutton.same_screen = 1; return XSendEvent(_ecore_x_disp, win, True, ButtonReleaseMask, &xev) ? EINA_TRUE : EINA_FALSE; } EAPI void ecore_x_focus_reset(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XSetInputFocus(_ecore_x_disp, PointerRoot, RevertToPointerRoot, CurrentTime); } EAPI void ecore_x_events_allow_all(void) { LOGFN(__FILE__, __LINE__, __FUNCTION__); XAllowEvents(_ecore_x_disp, AsyncBoth, CurrentTime); } EAPI void ecore_x_pointer_last_xy_get(int *x, int *y) { if (x) *x = _ecore_x_event_last_root_x; if (y) *y = _ecore_x_event_last_root_y; } EAPI void ecore_x_pointer_xy_get(Ecore_X_Window win, int *x, int *y) { Window rwin, cwin; int rx, ry, wx, wy, ret; unsigned int mask; LOGFN(__FILE__, __LINE__, __FUNCTION__); ret = XQueryPointer(_ecore_x_disp, win, &rwin, &cwin, &rx, &ry, &wx, &wy, &mask); if (!ret) wx = wy = -1; if (x) *x = wx; if (y) *y = wy; } /** * Retrieve the Visual ID from a given Visual. * * @param visual The Visual to get the ID for. * * @return The visual id. * @since 1.1.0 */ EAPI unsigned int ecore_x_visual_id_get(Ecore_X_Visual visual) { return XVisualIDFromVisual(visual); } /** * Retrieve the default Visual. * * @param disp The Display to get the Default Visual from * @param screen The Screen. * * @return The default visual. * @since 1.1.0 */ EAPI Ecore_X_Visual ecore_x_default_visual_get(Ecore_X_Display *disp, Ecore_X_Screen *screen) { return DefaultVisual(disp, ecore_x_screen_index_get(screen)); } /** * Retrieve the default Colormap. * * @param disp The Display to get the Default Colormap from * @param screen The Screen. * * @return The default colormap. * @since 1.1.0 */ EAPI Ecore_X_Colormap ecore_x_default_colormap_get(Ecore_X_Display *disp, Ecore_X_Screen *screen) { return DefaultColormap(disp, ecore_x_screen_index_get(screen)); } /** * Retrieve the default depth. * * @param disp The Display to get the Default Depth from * @param screen The Screen. * * @return The default depth. * @since 1.1.0 */ EAPI int ecore_x_default_depth_get(Ecore_X_Display *disp, Ecore_X_Screen *screen) { return DefaultDepth(disp, ecore_x_screen_index_get(screen)); } /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ static int _ecore_x_event_modifier(unsigned int state) { int xmodifiers = 0; if (state & ECORE_EVENT_MODIFIER_SHIFT) xmodifiers |= ECORE_X_MODIFIER_SHIFT; if (state & ECORE_EVENT_MODIFIER_CTRL) xmodifiers |= ECORE_X_MODIFIER_CTRL; if (state & ECORE_EVENT_MODIFIER_ALT) xmodifiers |= ECORE_X_MODIFIER_ALT; if (state & ECORE_EVENT_MODIFIER_WIN) xmodifiers |= ECORE_X_MODIFIER_WIN; if (state & ECORE_EVENT_LOCK_SCROLL) xmodifiers |= ECORE_X_LOCK_SCROLL; if (state & ECORE_EVENT_LOCK_NUM) xmodifiers |= ECORE_X_LOCK_NUM; if (state & ECORE_EVENT_LOCK_CAPS) xmodifiers |= ECORE_X_LOCK_CAPS; if (state & ECORE_EVENT_LOCK_SHIFT) xmodifiers |= ECORE_X_LOCK_SHIFT; return xmodifiers; }