enlightenment/src/bin/e_border.c

10194 lines
323 KiB
C

#include "e.h"
//#define INOUTDEBUG_MOUSE 1
//#define INOUTDEBUG_FOCUS 1
/* local subsystem functions */
static void _e_border_pri_raise(E_Border *bd);
static void _e_border_pri_norm(E_Border *bd);
static void _e_border_free(E_Border *bd);
static void _e_border_del(E_Border *bd);
#ifdef PRINT_LOTS_OF_DEBUG
#define E_PRINT_BORDER_INFO(X) \
_e_border_print(X, __PRETTY_FUNC__)
static void _e_border_print(E_Border *bd,
const char *func);
#endif
static void _e_border_shadow(E_Border *bd);
/* FIXME: these likely belong in a separate icccm/client handler */
/* and the border needs to become a dumb object that just does what its */
/* told to do */
static Eina_Bool _e_border_cb_window_show_request(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_destroy(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_hide(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_reparent(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_configure_request(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_resize_request(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_gravity(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_stack_request(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_property(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_colormap(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_shape(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_focus_in(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_focus_out(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_client_message(void *data, int ev_type, void *ev);
static Eina_Bool _e_border_cb_window_state_request(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_window_move_resize_request(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_desktop_change(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_sync_alarm(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_efreet_cache_update(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_config_icon_theme(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_config_mode(void *data,
int ev_type,
void *ev);
static Eina_Bool _e_border_cb_pointer_warp(void *data,
int ev_type,
void *ev);
static void _e_border_cb_signal_bind(void *data,
Evas_Object *obj,
const char *emission,
const char *source);
static Eina_Bool _e_border_cb_grab_replay(void *data,
int type,
void *event);
static void _e_border_cb_drag_finished(E_Drag *drag,
int dropped);
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
static Eina_Bool _e_border_cb_desk_window_profile_change(void *data,
int ev_type,
void *ev);
#endif
static void _e_border_eval(E_Border *bd);
static void _e_border_eval0(E_Border *bd);
static void _e_border_container_layout_hook(E_Container *con);
static void _e_border_moveinfo_gather(E_Border *bd,
const char *source);
static void _e_border_resize_handle(E_Border *bd);
static Eina_Bool _e_border_shade_animator(void *data);
static void _e_border_event_border_add_free(void *data,
void *ev);
static void _e_border_event_border_remove_free(void *data,
void *ev);
static void _e_border_event_border_zone_set_free(void *data,
void *ev);
static void _e_border_event_border_desk_set_free(void *data,
void *ev);
static void _e_border_event_border_stack_free(void *data,
void *ev);
static void _e_border_event_border_icon_change_free(void *data,
void *ev);
static void _e_border_event_border_title_change_free(void *data,
void *ev);
static void _e_border_event_border_urgent_change_free(void *data,
void *ev);
static void _e_border_event_border_focus_in_free(void *data,
void *ev);
static void _e_border_event_border_focus_out_free(void *data,
void *ev);
static void _e_border_event_border_resize_free(void *data,
void *ev);
static void _e_border_event_border_move_free(void *data,
void *ev);
static void _e_border_event_border_show_free(void *data,
void *ev);
static void _e_border_event_border_hide_free(void *data,
void *ev);
static void _e_border_event_border_iconify_free(void *data,
void *ev);
static void _e_border_event_border_uniconify_free(void *data,
void *ev);
static void _e_border_event_border_stick_free(void *data,
void *ev);
static void _e_border_event_border_unstick_free(void *data,
void *ev);
static void _e_border_event_border_property_free(void *data,
void *ev);
static void _e_border_event_border_fullscreen_free(void *data,
void *ev);
static void _e_border_event_border_unfullscreen_free(void *data,
void *ev);
static void _e_border_zone_update(E_Border *bd);
static int _e_border_resize_begin(E_Border *bd);
static int _e_border_resize_end(E_Border *bd);
static void _e_border_resize_update(E_Border *bd);
static int _e_border_move_begin(E_Border *bd);
static int _e_border_move_end(E_Border *bd);
static void _e_border_move_update(E_Border *bd);
static Eina_Bool _e_border_cb_ping_poller(void *data);
static Eina_Bool _e_border_cb_kill_timer(void *data);
static void _e_border_hook_call(E_Border_Hook_Point hookpoint,
void *bd);
static void _e_border_client_move_resize_send(E_Border *bd);
static void _e_border_shape_input_rectangle_set(E_Border *bd);
static void _e_border_show(E_Border *bd);
static void _e_border_hide(E_Border *bd);
static void _e_border_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
static void _e_border_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
static void _e_border_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
static void _e_border_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
static void _e_border_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
static void _e_border_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info);
static Eina_Bool _e_border_cb_mouse_x_wheel(void *d EINA_UNUSED, int t, Ecore_Event_Mouse_Wheel *ev);
static Eina_Bool _e_border_cb_mouse_x_up(void *d EINA_UNUSED, int t, Ecore_Event_Mouse_Button *ev);
static Eina_Bool _e_border_cb_mouse_x_down(void *d EINA_UNUSED, int t, Ecore_Event_Mouse_Button *ev);
static Eina_Bool _e_border_cb_mouse_x_move(void *d, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev);
static Eina_Bool _e_border_cb_mouse_x_in(void *d, int t EINA_UNUSED, Ecore_X_Event_Mouse_In *ev);
static Eina_Bool _e_border_cb_mouse_x_out(void *d, int t EINA_UNUSED, Ecore_X_Event_Mouse_Out *ev);
static void _e_border_action_finish(void);
static void _e_border_move_lost_window_to_center(E_Border *bd);
static void _e_border_reset_lost_window(E_Border *bd);
static Eina_Bool _e_border_pointer_warp_to_center_timer(void *data);
/* local subsystem globals */
static Eina_List *handlers = NULL;
static Eina_List *borders = NULL;
static Eina_Hash *borders_hash = NULL;
static E_Border *focused = NULL;
static E_Border *focusing = NULL;
static Eina_List *focus_next = NULL;
static Ecore_X_Time focus_time = 0;
static E_Border *bdresize = NULL;
static E_Border *bdmove = NULL;
static E_Drag *drag_border = NULL;
static int grabbed = 0;
static Eina_List *focus_stack = NULL;
static Eina_List *raise_stack = NULL;
static E_Border *warp_timer_border = NULL;
static Eina_Bool focus_locked = EINA_FALSE;
static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
static int screen_size_index = -1;
static int focus_track_frozen = 0;
static int warp_to = 0;
static int warp_to_x = 0;
static int warp_to_y = 0;
static int warp_x[2] = {0}; //{cur,prev}
static int warp_y[2] = {0}; //{cur,prev}
static Ecore_X_Window warp_to_win;
static Ecore_Timer *warp_timer = NULL;
static Ecore_X_Window action_input_win = 0;
static E_Border *action_border = NULL;
static Ecore_Event_Handler *action_handler_key = NULL;
static Ecore_Event_Handler *action_handler_mouse = NULL;
static Ecore_Timer *action_timer = NULL;
static Ecore_X_Rectangle action_orig;
EAPI int E_EVENT_BORDER_ADD = 0;
EAPI int E_EVENT_BORDER_REMOVE = 0;
EAPI int E_EVENT_BORDER_ZONE_SET = 0;
EAPI int E_EVENT_BORDER_DESK_SET = 0;
EAPI int E_EVENT_BORDER_RESIZE = 0;
EAPI int E_EVENT_BORDER_MOVE = 0;
EAPI int E_EVENT_BORDER_SHOW = 0;
EAPI int E_EVENT_BORDER_HIDE = 0;
EAPI int E_EVENT_BORDER_ICONIFY = 0;
EAPI int E_EVENT_BORDER_UNICONIFY = 0;
EAPI int E_EVENT_BORDER_STICK = 0;
EAPI int E_EVENT_BORDER_UNSTICK = 0;
EAPI int E_EVENT_BORDER_STACK = 0;
EAPI int E_EVENT_BORDER_ICON_CHANGE = 0;
EAPI int E_EVENT_BORDER_TITLE_CHANGE = 0;
EAPI int E_EVENT_BORDER_URGENT_CHANGE = 0;
EAPI int E_EVENT_BORDER_FOCUS_IN = 0;
EAPI int E_EVENT_BORDER_FOCUS_OUT = 0;
EAPI int E_EVENT_BORDER_PROPERTY = 0;
EAPI int E_EVENT_BORDER_FULLSCREEN = 0;
EAPI int E_EVENT_BORDER_UNFULLSCREEN = 0;
#define GRAV_SET(bd, grav) \
ecore_x_window_gravity_set(bd->win, grav); \
if (bd->client.lock_win) ecore_x_window_gravity_set(bd->client.lock_win, grav); \
ecore_x_window_gravity_set(bd->client.win, grav);
static Eina_List *
_e_border_sub_borders_new(E_Border *bd)
{
Eina_List *list = NULL, *l;
E_Border *child;
EINA_LIST_FOREACH(bd->transients, l, child)
{
if (!eina_list_data_find(list, child))
list = eina_list_append(list, child);
}
return list;
}
/* externally accessible functions */
EINTERN int
e_border_init(void)
{
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHOW_REQUEST,
_e_border_cb_window_show_request, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_DESTROY,
_e_border_cb_window_destroy, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_HIDE,
_e_border_cb_window_hide, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_REPARENT,
_e_border_cb_window_reparent, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST,
_e_border_cb_window_configure_request, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_RESIZE_REQUEST,
_e_border_cb_window_resize_request, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_GRAVITY,
_e_border_cb_window_gravity, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STACK_REQUEST,
_e_border_cb_window_stack_request, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_PROPERTY,
_e_border_cb_window_property, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_COLORMAP,
_e_border_cb_window_colormap, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHAPE,
_e_border_cb_window_shape, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_FOCUS_IN,
_e_border_cb_window_focus_in, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_FOCUS_OUT,
_e_border_cb_window_focus_out, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_CLIENT_MESSAGE,
_e_border_cb_client_message, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STATE_REQUEST,
_e_border_cb_window_state_request, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST,
_e_border_cb_window_move_resize_request, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_DESKTOP_CHANGE,
_e_border_cb_desktop_change, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_SYNC_ALARM,
_e_border_cb_sync_alarm, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN,
_e_border_cb_mouse_x_down, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_UP,
_e_border_cb_mouse_x_up, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MOUSE_IN,
_e_border_cb_mouse_x_in, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MOUSE_OUT,
_e_border_cb_mouse_x_out, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_WHEEL,
_e_border_cb_mouse_x_wheel, NULL);
E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE,
_e_border_cb_mouse_x_move, NULL);
ecore_x_passive_grab_replay_func_set(_e_border_cb_grab_replay, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_POINTER_WARP,
_e_border_cb_pointer_warp, NULL);
E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_DESKTOP_CACHE_UPDATE,
_e_border_cb_efreet_cache_update, NULL);
E_LIST_HANDLER_APPEND(handlers, EFREET_EVENT_ICON_CACHE_UPDATE,
_e_border_cb_efreet_cache_update, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_CONFIG_ICON_THEME,
_e_border_cb_config_icon_theme, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_CONFIG_MODE_CHANGED,
_e_border_cb_config_mode, NULL);
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_WINDOW_PROFILE_CHANGE,
_e_border_cb_desk_window_profile_change, NULL);
#endif
if (!borders_hash) borders_hash = eina_hash_string_superfast_new(NULL);
E_EVENT_BORDER_ADD = ecore_event_type_new();
E_EVENT_BORDER_REMOVE = ecore_event_type_new();
E_EVENT_BORDER_DESK_SET = ecore_event_type_new();
E_EVENT_BORDER_ZONE_SET = ecore_event_type_new();
E_EVENT_BORDER_RESIZE = ecore_event_type_new();
E_EVENT_BORDER_MOVE = ecore_event_type_new();
E_EVENT_BORDER_SHOW = ecore_event_type_new();
E_EVENT_BORDER_HIDE = ecore_event_type_new();
E_EVENT_BORDER_ICONIFY = ecore_event_type_new();
E_EVENT_BORDER_UNICONIFY = ecore_event_type_new();
E_EVENT_BORDER_STICK = ecore_event_type_new();
E_EVENT_BORDER_UNSTICK = ecore_event_type_new();
E_EVENT_BORDER_STACK = ecore_event_type_new();
E_EVENT_BORDER_ICON_CHANGE = ecore_event_type_new();
E_EVENT_BORDER_TITLE_CHANGE = ecore_event_type_new();
E_EVENT_BORDER_URGENT_CHANGE = ecore_event_type_new();
E_EVENT_BORDER_FOCUS_IN = ecore_event_type_new();
E_EVENT_BORDER_FOCUS_OUT = ecore_event_type_new();
E_EVENT_BORDER_PROPERTY = ecore_event_type_new();
E_EVENT_BORDER_FULLSCREEN = ecore_event_type_new();
E_EVENT_BORDER_UNFULLSCREEN = ecore_event_type_new();
// e_init_undone();
return 1;
}
EINTERN int
e_border_shutdown(void)
{
E_FREE_LIST(handlers, ecore_event_handler_del);
if (borders_hash) eina_hash_free(borders_hash);
borders_hash = NULL;
e_int_border_menu_hooks_clear();
focus_locked = EINA_FALSE;
if (warp_timer) ecore_timer_del(warp_timer);
warp_timer = NULL;
warp_timer_border = NULL;
return 1;
}
EAPI void
e_border_focus_lock_set(Eina_Bool lock)
{
focus_locked = !!lock;
}
EAPI Eina_Bool
e_border_focus_lock_get(void)
{
return focus_locked;
}
EAPI E_Border *
e_border_new(E_Container *con, Ecore_X_Window win, int first_map, int internal)
{
E_Border *bd;
Ecore_X_Window_Attributes *att;
unsigned int managed, desk[2];
int deskx, desky;
if (eina_hash_find(borders_hash, e_util_winid_str_get(win))) return NULL;
bd = E_OBJECT_ALLOC(E_Border, E_BORDER_TYPE, _e_border_free);
if (!bd) return NULL;
ecore_x_window_shadow_tree_flush();
e_object_del_func_set(E_OBJECT(bd), E_OBJECT_CLEANUP_FUNC(_e_border_del));
bd->w = 1;
bd->h = 1;
/* FIXME: ewww - round trip */
bd->client.argb = ecore_x_window_argb_get(win);
/* match bd parent argbness */
if (bd->client.argb)
bd->win = ecore_x_window_manager_argb_new(con->win, 0, 0, bd->w, bd->h);
else
{
bd->win = ecore_x_window_override_new(con->win, 0, 0, bd->w, bd->h);
ecore_x_window_shape_events_select(bd->win, 1);
}
e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_focus_setup(bd);
/* FIXME: Round trip. XCB */
/* fetch needed to avoid grabbing the server as window may vanish */
att = &bd->client.initial_attributes;
if ((!ecore_x_window_attributes_get(win, att)) || (att->input_only))
{
// printf("##- ATTR FETCH FAILED/INPUT ONLY FOR 0x%x - ABORT MANAGE\n", win);
ecore_x_window_free(bd->win);
e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
ecore_x_window_free(bd->win);
free(bd);
return NULL;
}
ecore_x_window_container_manage(bd->win);
if (!internal) ecore_x_window_client_manage(win);
ecore_x_window_configure(bd->win,
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
win, ECORE_X_WINDOW_STACK_BELOW);
ecore_x_event_mask_set(bd->win, ECORE_X_EVENT_MASK_MOUSE_IN | ECORE_X_EVENT_MASK_MOUSE_OUT);
/* printf("##- ON MAP CLIENT 0x%x SIZE %ix%i %i:%i\n",
* bd->client.win, bd->client.w, bd->client.h, att->x, att->y); */
/* FIXME: if first_map is 1 then we should ignore the first hide event
* or ensure the window is already hidden and events flushed before we
* create a border for it */
if (first_map)
{
// printf("##- FIRST MAP\n");
bd->x = att->x;
bd->y = att->y;
bd->changes.pos = 1;
bd->re_manage = 1;
// needed to be 1 for internal windw and on restart.
// bd->ignore_first_unmap = 2;
}
bd->client.win = win;
bd->zone = e_zone_current_get(con);
_e_border_hook_call(E_BORDER_HOOK_NEW_BORDER, bd);
bd->client.icccm.title = NULL;
bd->client.icccm.name = NULL;
bd->client.icccm.class = NULL;
bd->client.icccm.icon_name = NULL;
bd->client.icccm.machine = NULL;
bd->client.icccm.min_w = 1;
bd->client.icccm.min_h = 1;
bd->client.icccm.max_w = 32767;
bd->client.icccm.max_h = 32767;
bd->client.icccm.base_w = 0;
bd->client.icccm.base_h = 0;
bd->client.icccm.step_w = -1;
bd->client.icccm.step_h = -1;
bd->client.icccm.min_aspect = 0.0;
bd->client.icccm.max_aspect = 0.0;
bd->client.icccm.accepts_focus = 1;
bd->client.netwm.pid = 0;
bd->client.netwm.name = NULL;
bd->client.netwm.icon_name = NULL;
bd->client.netwm.desktop = 0;
bd->client.netwm.state.modal = 0;
bd->client.netwm.state.sticky = 0;
bd->client.netwm.state.shaded = 0;
bd->client.netwm.state.hidden = 0;
bd->client.netwm.state.maximized_v = 0;
bd->client.netwm.state.maximized_h = 0;
bd->client.netwm.state.skip_taskbar = 0;
bd->client.netwm.state.skip_pager = 0;
bd->client.netwm.state.fullscreen = 0;
bd->client.netwm.state.stacking = E_STACKING_NONE;
bd->client.netwm.action.move = 0;
bd->client.netwm.action.resize = 0;
bd->client.netwm.action.minimize = 0;
bd->client.netwm.action.shade = 0;
bd->client.netwm.action.stick = 0;
bd->client.netwm.action.maximized_h = 0;
bd->client.netwm.action.maximized_v = 0;
bd->client.netwm.action.fullscreen = 0;
bd->client.netwm.action.change_desktop = 0;
bd->client.netwm.action.close = 0;
bd->client.netwm.opacity = 255;
bd->client.netwm.type = ECORE_X_WINDOW_TYPE_UNKNOWN;
{
int at_num = 0, i;
Ecore_X_Atom *atoms;
atoms = ecore_x_window_prop_list(bd->client.win, &at_num);
bd->client.icccm.fetch.command = 1;
if (atoms)
{
Eina_Bool video_parent = EINA_FALSE;
Eina_Bool video_position = EINA_FALSE;
/* icccm */
for (i = 0; i < at_num; i++)
{
if (atoms[i] == ECORE_X_ATOM_WM_NAME)
bd->client.icccm.fetch.title = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
bd->client.icccm.fetch.name_class = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
bd->client.icccm.fetch.icon_name = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
bd->client.icccm.fetch.machine = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
bd->client.icccm.fetch.hints = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
bd->client.icccm.fetch.size_pos_hints = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
bd->client.icccm.fetch.protocol = 1;
else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
bd->client.mwm.fetch.hints = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
{
bd->client.icccm.fetch.transient_for = 1;
bd->client.netwm.fetch.type = 1;
}
else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
bd->client.icccm.fetch.client_leader = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
bd->client.icccm.fetch.window_role = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_STATE)
bd->client.icccm.fetch.state = 1;
}
/* netwm, loop again, netwm will ignore some icccm, so we
* have to be sure that netwm is checked after */
for (i = 0; i < at_num; i++)
{
if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
{
/* Ignore icccm */
bd->client.icccm.fetch.title = 0;
bd->client.netwm.fetch.name = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
{
/* Ignore icccm */
bd->client.icccm.fetch.icon_name = 0;
bd->client.netwm.fetch.icon_name = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
{
bd->client.netwm.fetch.icon = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
{
bd->client.netwm.fetch.user_time = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
{
DBG("ECORE_X_ATOM_NET_WM_STRUT");
bd->client.netwm.fetch.strut = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
{
DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
bd->client.netwm.fetch.strut = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
{
/* Ignore mwm
bd->client.mwm.fetch.hints = 0;
*/
bd->client.netwm.fetch.type = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
{
bd->client.netwm.fetch.state = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
bd->client.netwm.fetch.opacity = 1;
}
/* other misc atoms */
for (i = 0; i < at_num; i++)
{
/* loop to check for own atoms */
if (atoms[i] == E_ATOM_WINDOW_STATE)
{
bd->client.e.fetch.state = 1;
}
/* loop to check for qtopia atoms */
if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
bd->client.qtopia.fetch.soft_menu = 1;
else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
bd->client.qtopia.fetch.soft_menus = 1;
/* loop to check for vkbd atoms */
else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
bd->client.vkbd.fetch.state = 1;
else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
bd->client.vkbd.fetch.vkbd = 1;
/* loop to check for illume atoms */
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
bd->client.illume.conformant.fetch.conformant = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
bd->client.illume.quickpanel.fetch.state = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
bd->client.illume.quickpanel.fetch.quickpanel = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
bd->client.illume.quickpanel.fetch.priority.major = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
bd->client.illume.quickpanel.fetch.priority.minor = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
bd->client.illume.quickpanel.fetch.zone = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
bd->client.illume.drag.fetch.locked = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
bd->client.illume.drag.fetch.drag = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
bd->client.illume.win_state.fetch.state = 1;
else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
video_parent = EINA_TRUE;
else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
video_position = EINA_TRUE;
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
/* loop to check for window profile list atom */
else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
bd->client.e.fetch.profile = 1;
#endif
}
if (video_position && video_parent)
{
bd->client.e.state.video = 1;
bd->client.e.fetch.video_parent = 1;
bd->client.e.fetch.video_position = 1;
ecore_x_window_lower(bd->win);
ecore_x_composite_window_events_disable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_TRUE);
fprintf(stderr, "We found a video window \\o/ %x\n", win);
}
free(atoms);
}
}
bd->client.border.changed = 1;
bd->client.w = att->w;
bd->client.h = att->h;
bd->w = bd->client.w;
bd->h = bd->client.h;
bd->resize_mode = E_POINTER_RESIZE_NONE;
bd->layer = 100;
bd->saved.layer = bd->layer;
bd->changes.icon = 1;
bd->changes.size = 1;
bd->changes.shape = 1;
bd->changes.shape_input = 1;
bd->offer_resistance = 1;
/* just to friggin make java happy - we're DELAYING the reparent until
* eval time...
*/
/* ecore_x_window_reparent(win, bd->win, 0, 0); */
bd->need_reparent = 1;
ecore_x_window_border_width_set(win, 0);
bd->shape = e_container_shape_add(con);
bd->take_focus = 1;
bd->new_client = 1;
BD_CHANGED(bd);
// bd->zone = e_zone_current_get(con);
bd->desk = e_desk_current_get(bd->zone);
e_container_border_add(bd);
borders = eina_list_append(borders, bd);
eina_hash_add(borders_hash, e_util_winid_str_get(bd->client.win), bd);
eina_hash_add(borders_hash, e_util_winid_str_get(bd->win), bd);
managed = 1;
ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
ecore_x_window_prop_card32_set(win, E_ATOM_CONTAINER, &bd->zone->container->num, 1);
ecore_x_window_prop_card32_set(win, E_ATOM_ZONE, &bd->zone->num, 1);
{
unsigned int zgeom[4];
zgeom[0] = bd->zone->x;
zgeom[1] = bd->zone->y;
zgeom[2] = bd->zone->w;
zgeom[3] = bd->zone->h;
ecore_x_window_prop_card32_set(win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
}
e_desk_xy_get(bd->desk, &deskx, &desky);
desk[0] = deskx;
desk[1] = desky;
ecore_x_window_prop_card32_set(win, E_ATOM_DESK, desk, 2);
focus_stack = eina_list_append(focus_stack, bd);
return bd;
}
EAPI void
e_border_res_change_geometry_save(E_Border *bd)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->pre_res_change.valid) return;
bd->pre_res_change.valid = 1;
bd->pre_res_change.x = bd->x;
bd->pre_res_change.y = bd->y;
bd->pre_res_change.w = bd->w;
bd->pre_res_change.h = bd->h;
bd->pre_res_change.saved.x = bd->saved.x;
bd->pre_res_change.saved.y = bd->saved.y;
bd->pre_res_change.saved.w = bd->saved.w;
bd->pre_res_change.saved.h = bd->saved.h;
}
EAPI void
e_border_res_change_geometry_restore(E_Border *bd)
{
struct
{
unsigned char valid : 1;
int x, y, w, h;
struct
{
int x, y, w, h;
} saved;
} pre_res_change;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!bd->pre_res_change.valid) return;
if (bd->new_client) return;
ecore_x_window_shadow_tree_flush();
memcpy(&pre_res_change, &bd->pre_res_change, sizeof(pre_res_change));
if (bd->fullscreen)
{
e_border_unfullscreen(bd);
e_border_fullscreen(bd, e_config->fullscreen_policy);
}
else if (bd->maximized != E_MAXIMIZE_NONE)
{
E_Maximize max;
max = bd->maximized;
e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
e_border_maximize(bd, max);
}
else
{
int x, y, w, h, zx, zy, zw, zh;
bd->saved.x = bd->pre_res_change.saved.x;
bd->saved.y = bd->pre_res_change.saved.y;
bd->saved.w = bd->pre_res_change.saved.w;
bd->saved.h = bd->pre_res_change.saved.h;
e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
if (bd->saved.w > zw)
bd->saved.w = zw;
if ((bd->saved.x + bd->saved.w) > (zx + zw))
bd->saved.x = zx + zw - bd->saved.w;
if (bd->saved.h > zh)
bd->saved.h = zh;
if ((bd->saved.y + bd->saved.h) > (zy + zh))
bd->saved.y = zy + zh - bd->saved.h;
x = bd->pre_res_change.x;
y = bd->pre_res_change.y;
w = bd->pre_res_change.w;
h = bd->pre_res_change.h;
if (w > zw)
w = zw;
if (h > zh)
h = zh;
if ((x + w) > (zx + zw))
x = zx + zw - w;
if ((y + h) > (zy + zh))
y = zy + zh - h;
e_border_move_resize(bd, x, y, w, h);
}
memcpy(&bd->pre_res_change, &pre_res_change, sizeof(pre_res_change));
}
EAPI void
e_border_zone_set(E_Border *bd,
E_Zone *zone)
{
E_Event_Border_Zone_Set *ev;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
E_OBJECT_CHECK(zone);
E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
if (!zone) return;
if (bd->zone == zone) return;
/* if the window does not lie in the new zone, move it so that it does */
if (!E_INTERSECTS(bd->x, bd->y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
{
int x, y;
/* first guess -- get offset from old zone, and apply to new zone */
x = zone->x + (bd->x - bd->zone->x);
y = zone->y + (bd->y - bd->zone->y);
/* keep window from hanging off bottom and left */
if (x + bd->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + bd->w);
if (y + bd->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + bd->h);
/* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
if (x < zone->x) x = zone->x;
if (y < zone->y) y = zone->y;
if (!E_INTERSECTS(x, y, bd->w, bd->h, zone->x, zone->y, zone->w, zone->h))
{
/* still not in zone at all, so just move it to closest edge */
if (x < zone->x) x = zone->x;
if (x >= zone->x + zone->w) x = zone->x + zone->w - bd->w;
if (y < zone->y) y = zone->y;
if (y >= zone->y + zone->h) y = zone->y + zone->h - bd->h;
}
e_border_move(bd, x, y);
}
bd->zone = zone;
if (bd->desk->zone != bd->zone)
e_border_desk_set(bd, e_desk_current_get(bd->zone));
ev = E_NEW(E_Event_Border_Zone_Set, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_zone_set_event");
ev->zone = zone;
e_object_ref(E_OBJECT(zone));
ecore_event_add(E_EVENT_BORDER_ZONE_SET, ev, _e_border_event_border_zone_set_free, NULL);
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE, &bd->zone->num, 1);
// XXXXXXXXXXXXXXXXXXXXXXXXX
// XXX ZZZZZZZZZZZZZZZZZZZzz
// need to adjust this if zone pos/size changes
{
unsigned int zgeom[4];
zgeom[0] = bd->zone->x;
zgeom[1] = bd->zone->y;
zgeom[2] = bd->zone->w;
zgeom[3] = bd->zone->h;
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_ZONE_GEOMETRY, zgeom, 4);
}
e_remember_update(bd);
e_border_res_change_geometry_save(bd);
e_border_res_change_geometry_restore(bd);
bd->pre_res_change.valid = 0;
}
EAPI void
e_border_desk_set(E_Border *bd,
E_Desk *desk)
{
E_Event_Border_Desk_Set *ev;
E_Desk *old_desk;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
E_OBJECT_CHECK(desk);
E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
if (bd->desk == desk) return;
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
if ((e_config->use_desktop_window_profile) &&
(bd->client.e.state.profile.use))
{
if (bd->client.e.state.profile.wait_for_done) return;
if (e_util_strcmp(bd->client.e.state.profile.name, desk->window_profile))
{
ecore_x_e_window_profile_change_request_send(bd->client.win,
desk->window_profile);
bd->client.e.state.profile.wait_for_done = 1;
return;
}
}
#endif
ecore_x_window_shadow_tree_flush();
if (bd->fullscreen)
{
bd->desk->fullscreen_borders--;
desk->fullscreen_borders++;
}
old_desk = bd->desk;
bd->desk = desk;
e_border_zone_set(bd, desk->zone);
_e_border_hook_call(E_BORDER_HOOK_SET_DESK, bd);
e_hints_window_desktop_set(bd);
ev = E_NEW(E_Event_Border_Desk_Set, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_desk_set_event");
ev->desk = old_desk;
e_object_ref(E_OBJECT(old_desk));
ecore_event_add(E_EVENT_BORDER_DESK_SET, ev, _e_border_event_border_desk_set_free, NULL);
if (bd->ignore_first_unmap != 1)
{
if ((bd->desk->visible) || (bd->sticky))
e_border_show(bd);
else
e_border_hide(bd, 1);
}
if (e_config->transient.desktop)
{
E_Border *child;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_FREE(list, child)
e_border_desk_set(child, bd->desk);
}
e_remember_update(bd);
}
EAPI void
e_border_show(E_Border *bd)
{
E_Event_Border_Show *ev;
unsigned int visible;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->visible) return;
ecore_x_window_shadow_tree_flush();
e_container_shape_show(bd->shape);
if (!bd->need_reparent)
ecore_x_window_show(bd->client.win);
e_hints_window_visible_set(bd);
bd->hidden = 0;
bd->visible = 1;
bd->changes.visible = 1;
visible = 1;
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
if (bd->new_client) return;
ev = E_NEW(E_Event_Border_Show, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_show_event");
ecore_event_add(E_EVENT_BORDER_SHOW, ev, _e_border_event_border_show_free, NULL);
}
EAPI void
e_border_hide(E_Border *bd,
int manage)
{
unsigned int visible;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!bd->visible) goto send_event;
ecore_x_window_shadow_tree_flush();
if (bd->moving)
_e_border_move_end(bd);
if (bd->resize_mode != E_POINTER_RESIZE_NONE)
_e_border_resize_end(bd);
if (action_border == bd)
_e_border_action_finish();
e_container_shape_hide(bd->shape);
if ((!bd->iconic) && (!bd->delete_requested))
e_hints_window_hidden_set(bd);
bd->visible = 0;
bd->changes.visible = 1;
if (!bd->need_reparent)
{
if (bd->focused)
{
e_border_focus_set(bd, 0, 1);
if (manage != 2)
{
E_Border *pbd;
E_Zone *zone;
E_Desk *desk;
zone = e_util_zone_current_get(e_manager_current_get());
desk = e_desk_current_get(zone);
if ((bd->parent) &&
(bd->parent->desk == desk) && (bd->parent->modal == bd))
e_border_focus_set(bd->parent, 1, 1);
else if (e_config->focus_revert_on_hide_or_close)
{
Eina_Bool unlock = bd->lock_focus_out;
bd->lock_focus_out = 1;
e_desk_last_focused_focus(desk);
bd->lock_focus_out = unlock;
}
else if (e_config->focus_policy == E_FOCUS_MOUSE)
{
pbd = e_border_under_pointer_get(desk, bd);
if (pbd)
e_border_focus_set(pbd, 1, 1);
}
}
}
switch (manage)
{
case 2: break;
case 3:
bd->hidden = 1;
case 1:
default:
if (!e_comp_evas_exists(bd))
{
/* Make sure that this border isn't deleted */
bd->await_hide_event++;
ecore_x_window_hide(bd->client.win);
}
}
}
if (!bd->delete_requested)
{
visible = 0;
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &visible, 1);
if (!manage)
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MANAGED, &visible, 1);
}
bd->post_show = 0;
send_event:
if (bd->new_client) return;
if (!stopping)
{
E_Event_Border_Hide *ev;
ev = E_NEW(E_Event_Border_Hide, 1);
ev->border = bd;
ev->manage = manage;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_hide_event");
ecore_event_add(E_EVENT_BORDER_HIDE, ev, _e_border_event_border_hide_free, NULL);
}
}
static void
_pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children)
{
int newpri = set;
if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj;
setpriority(PRIO_PROCESS, pid, newpri);
// shouldnt need to do this as default ionice class is "none" (0), and
// this inherits io priority FROM nice level
// ioprio_set(IOPRIO_WHO_PROCESS, pid,
// IOPRIO_PRIO_VALUE(2, 5));
if (do_children)
{
Eina_List *files;
char *file, buf[PATH_MAX];
FILE *f;
int pid2, ppid;
// yes - this is /proc specific... so this may not work on some
// os's - works on linux. too bad for others.
files = ecore_file_ls("/proc");
EINA_LIST_FREE(files, file)
{
if (isdigit(file[0]))
{
snprintf(buf, sizeof(buf), "/proc/%s/stat", file);
f = fopen(buf, "r");
if (f)
{
pid2 = -1;
ppid = -1;
if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2)
{
fclose(f);
if (ppid == pid)
{
if (adj_children)
_pri_adj(pid2, set, adj, EINA_TRUE,
adj_children, do_children);
else
_pri_adj(pid2, set, adj, use_adj,
adj_children, do_children);
}
}
else fclose(f);
}
}
free(file);
}
}
}
static void
_e_border_pri_raise(E_Border *bd)
{
if (bd->client.netwm.pid <= 0) return;
if (bd->client.netwm.pid == getpid()) return;
_pri_adj(bd->client.netwm.pid,
e_config->priority - 1, -1, EINA_FALSE,
// EINA_TRUE, EINA_TRUE);
EINA_TRUE, EINA_FALSE);
// printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n",
// bd->client.netwm.pid, e_border_name_get(bd));
}
static void
_e_border_pri_norm(E_Border *bd)
{
if (bd->client.netwm.pid <= 0) return;
if (bd->client.netwm.pid == getpid()) return;
_pri_adj(bd->client.netwm.pid,
e_config->priority, 1, EINA_FALSE,
// EINA_TRUE, EINA_TRUE);
EINA_TRUE, EINA_FALSE);
// printf("WIN: pid %i, title %s (NORMAL)\n",
// bd->client.netwm.pid, e_border_name_get(bd));
}
static void
_e_border_client_move_resize_send(E_Border *bd)
{
if (bd->internal_ecore_evas)
ecore_evas_managed_move(bd->internal_ecore_evas,
bd->client_inset.l,
bd->client_inset.t);
ecore_x_icccm_move_resize_send(bd->client.win,
bd->x + bd->client_inset.l,
bd->y + bd->client_inset.t,
bd->client.w,
bd->client.h);
}
static void
_e_border_pending_move_resize_add(E_Border *bd,
int move,
int resize,
int x,
int y,
int w,
int h,
Eina_Bool without_border,
unsigned int serial)
{
E_Border_Pending_Move_Resize *pnd;
pnd = E_NEW(E_Border_Pending_Move_Resize, 1);
if (!pnd) return;
pnd->resize = resize;
pnd->move = move;
pnd->without_border = without_border;
pnd->x = x;
pnd->y = y;
pnd->w = w;
pnd->h = h;
pnd->serial = serial;
bd->pending_move_resize = eina_list_append(bd->pending_move_resize, pnd);
}
static void
_e_border_move_internal(E_Border *bd,
int x,
int y,
Eina_Bool without_border)
{
E_Event_Border_Move *ev;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
if (bd->new_client)
{
_e_border_pending_move_resize_add(bd, 1, 0, x, y, 0, 0, without_border, 0);
return;
}
if (bd->maximized)
{
if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
{
if (e_config->allow_manip)
bd->maximized = 0;
if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
{
x = bd->x;
}
else
if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
{
y = bd->y;
}
}
else if (e_config->allow_manip)
bd->maximized = 0;
else
return;
}
if (without_border)
{
x -= bd->client_inset.l;
y -= bd->client_inset.t;
}
if (bd->move_intercept_cb)
{
int px, py;
px = bd->x, py = bd->y;
bd->move_intercept_cb(bd, x, y);
if ((bd->x == px) && (bd->y == py)) return;
}
else if ((x == bd->x) && (y == bd->y))
return;
bd->pre_res_change.valid = 0;
bd->x = x;
bd->y = y;
BD_CHANGED(bd);
bd->changes.pos = 1;
#if 0
if (bd->client.netwm.sync.request)
{
bd->client.netwm.sync.wait++;
ecore_x_netwm_sync_request_send(bd->client.win, bd->client.netwm.sync.serial++);
}
#endif
_e_border_client_move_resize_send(bd);
_e_border_move_update(bd);
ev = E_NEW(E_Event_Border_Move, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
_e_border_zone_update(bd);
}
/**
* Move window to coordinates that already account border decorations.
*
* This call will consider given position already accounts border
* decorations, so it will not be considered later. This will just
* work properly with borders that have being evaluated and border
* decorations are known (border->client_inset).
*
* @parm x horizontal position to place window.
* @parm y vertical position to place window.
*
* @see e_border_move_without_border()
*/
EAPI void
e_border_move(E_Border *bd,
int x,
int y)
{
if (bd->fullscreen)
return;
_e_border_move_internal(bd, x, y, 0);
}
/**
* Set a callback which will be called just prior to updating the
* move coordinates for a border
*/
EAPI void
e_border_move_intercept_cb_set(E_Border *bd, E_Border_Move_Intercept_Cb cb)
{
bd->move_intercept_cb = cb;
}
/**
* Move window to coordinates that do not account border decorations yet.
*
* This call will consider given position does not account border
* decoration, so these values (border->client_inset) will be
* accounted automatically. This is specially useful when it is a new
* client and has not be evaluated yet, in this case
* border->client_inset will be zeroed and no information is known. It
* will mark pending requests so border will be accounted on
* evalutation phase.
*
* @parm x horizontal position to place window.
* @parm y vertical position to place window.
*
* @see e_border_move()
*/
EAPI void
e_border_move_without_border(E_Border *bd,
int x,
int y)
{
if (bd->fullscreen)
return;
_e_border_move_internal(bd, x, y, 1);
}
EAPI void
e_border_center(E_Border *bd)
{
int x, y, w, h;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
e_zone_useful_geometry_get(bd->zone, &x, &y, &w, &h);
e_border_move(bd, x + (w - bd->w) / 2, y + (h - bd->h) / 2);
}
EAPI void
e_border_center_pos_get(E_Border *bd,
int *x,
int *y)
{
int zx, zy, zw, zh;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
if (x) *x = zx + (zw - bd->w) / 2;
if (y) *y = zy + (zh - bd->h) / 2;
}
static void
_e_border_move_resize_internal(E_Border *bd,
int x,
int y,
int w,
int h,
Eina_Bool without_border,
Eina_Bool move)
{
E_Event_Border_Move *mev;
E_Event_Border_Resize *rev;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
if (bd->new_client)
{
_e_border_pending_move_resize_add(bd, move, 1, x, y, w, h, without_border, 0);
return;
}
if (bd->maximized)
{
if ((bd->maximized & E_MAXIMIZE_DIRECTION) != E_MAXIMIZE_BOTH)
{
if (e_config->allow_manip)
bd->maximized = 0;
if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_HORIZONTAL)
{
x = bd->x;
w = bd->w;
}
else
if ((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_VERTICAL)
{
y = bd->y;
h = bd->h;
}
}
else
if (e_config->allow_manip)
bd->maximized = 0;
else
return;
}
if (without_border)
{
x -= bd->client_inset.l;
y -= bd->client_inset.t;
w += e_border_inset_width_get(bd);
h += e_border_inset_height_get(bd);
}
if ((!move || ((x == bd->x) && (y == bd->y))) &&
(w == bd->w) && (h == bd->h))
return;
bd->pre_res_change.valid = 0;
if (move)
{
bd->changes.pos = 1;
bd->x = x;
bd->y = y;
}
bd->w = w;
bd->h = h;
bd->client.w = bd->w - e_border_inset_width_get(bd);
bd->client.h = bd->h - e_border_inset_height_get(bd);
if (bd->client.shaped)
{
bd->need_shape_merge = 1;
bd->need_shape_export = 1;
}
if (bd->shaped_input)
{
bd->need_shape_merge = 1;
}
if (bd->internal_ecore_evas)
{
BD_CHANGED(bd);
bd->changes.size = 1;
}
else
{
if (bdresize && bd->client.netwm.sync.request)
{
bd->client.netwm.sync.wait++;
/* Don't use x and y as supplied to this function, as it is called with 0, 0
* when no move is intended. The border geometry is set above anyways.
*/
_e_border_pending_move_resize_add(bd, move, 1, bd->x, bd->y, bd->w, bd->h, without_border,
bd->client.netwm.sync.serial);
ecore_x_netwm_sync_request_send(bd->client.win,
bd->client.netwm.sync.serial++);
}
else
{
BD_CHANGED(bd);
bd->changes.size = 1;
}
}
_e_border_client_move_resize_send(bd);
_e_border_resize_update(bd);
if (move)
{
mev = E_NEW(E_Event_Border_Move, 1);
mev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_move_event");
ecore_event_add(E_EVENT_BORDER_MOVE, mev, _e_border_event_border_move_free, NULL);
}
rev = E_NEW(E_Event_Border_Resize, 1);
rev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
ecore_event_add(E_EVENT_BORDER_RESIZE, rev, _e_border_event_border_resize_free, NULL);
_e_border_zone_update(bd);
}
/**
* Move and resize window to values that already account border decorations.
*
* This call will consider given values already accounts border
* decorations, so it will not be considered later. This will just
* work properly with borders that have being evaluated and border
* decorations are known (border->client_inset).
*
* @parm x horizontal position to place window.
* @parm y vertical position to place window.
* @parm w horizontal window size.
* @parm h vertical window size.
*
* @see e_border_move_resize_without_border()
*/
EAPI void
e_border_move_resize(E_Border *bd,
int x,
int y,
int w,
int h)
{
if (bd->fullscreen)
return;
_e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
}
/**
* Move and resize window to values that do not account border decorations yet.
*
* This call will consider given values already accounts border
* decorations, so it will not be considered later. This will just
* work properly with borders that have being evaluated and border
* decorations are known (border->client_inset).
*
* @parm x horizontal position to place window.
* @parm y vertical position to place window.
* @parm w horizontal window size.
* @parm h vertical window size.
*
* @see e_border_move_resize()
*/
EAPI void
e_border_move_resize_without_border(E_Border *bd,
int x,
int y,
int w,
int h)
{
if (bd->fullscreen)
return;
_e_border_move_resize_internal(bd, x, y, w, h, 1, 1);
}
/**
* Resize window to values that already account border decorations.
*
* This call will consider given size already accounts border
* decorations, so it will not be considered later. This will just
* work properly with borders that have being evaluated and border
* decorations are known (border->client_inset).
*
* @parm w horizontal window size.
* @parm h vertical window size.
*
* @see e_border_resize_without_border()
*/
EAPI void
e_border_resize(E_Border *bd,
int w,
int h)
{
if (bd->fullscreen)
return;
_e_border_move_resize_internal(bd, 0, 0, w, h, 0, 0);
}
/**
* Resize window to values that do not account border decorations yet.
*
* This call will consider given size does not account border
* decoration, so these values (border->client_inset) will be
* accounted automatically. This is specially useful when it is a new
* client and has not be evaluated yet, in this case
* border->client_inset will be zeroed and no information is known. It
* will mark pending requests so border will be accounted on
* evalutation phase.
*
* @parm w horizontal window size.
* @parm h vertical window size.
*
* @see e_border_resize()
*/
EAPI void
e_border_resize_without_border(E_Border *bd,
int w,
int h)
{
if (bd->fullscreen)
return;
_e_border_move_resize_internal(bd, 0, 0, w, h, 1, 0);
}
EAPI void
e_border_layer_set(E_Border *bd,
E_Layer layer)
{
int oldraise;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
oldraise = e_config->transient.raise;
if (bd->fullscreen)
{
bd->saved.layer = layer;
return;
}
bd->layer = layer;
if (e_config->transient.layer)
{
E_Border *child;
Eina_List *list = _e_border_sub_borders_new(bd);
/* We need to set raise to one, else the child wont
* follow to the new layer. It should be like this,
* even if the user usually doesn't want to raise
* the transients.
*/
e_config->transient.raise = 1;
EINA_LIST_FREE(list, child)
e_border_layer_set(child, layer);
}
if ((!bd->modal) || (bd->modal->layer > bd->layer))
e_border_raise(bd);
else
e_border_stack_below(bd, bd->modal);
if (layer == E_LAYER_BELOW)
e_hints_window_stacking_set(bd, E_STACKING_BELOW);
else if (layer == E_LAYER_ABOVE)
e_hints_window_stacking_set(bd, E_STACKING_ABOVE);
else
e_hints_window_stacking_set(bd, E_STACKING_NONE);
e_config->transient.raise = oldraise;
}
EAPI void
e_border_raise(E_Border *bd)
{
E_Event_Border_Stack *ev;
E_Border *last = NULL, *child;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
if (e_config->transient.raise)
{
Eina_List *l, *l_prev;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_REVERSE_FOREACH_SAFE(list, l, l_prev, child)
{
/* Don't stack iconic transients. If the user wants these shown,
* thats another option.
*/
if (!child->iconic)
{
if (last)
e_border_stack_below(child, last);
else
{
E_Border *above;
/* First raise the border to find out which border we will end up above */
above = e_container_border_raise(child);
if (above)
{
/* We ended up above a border, now we must stack this border to
* generate the stacking event, and to check if this transient
* has other transients etc.
*/
e_border_stack_above(child, above);
}
else
{
/* If we didn't end up above any border, we are on the bottom! */
e_border_lower(child);
}
}
last = child;
}
list = eina_list_remove_list(list, l);
}
}
ev = E_NEW(E_Event_Border_Stack, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
if (last)
{
e_container_border_stack_below(bd, last);
ev->stack = last;
e_object_ref(E_OBJECT(last));
ev->type = E_STACKING_BELOW;
}
else
{
E_Border *above;
/* If we don't have any children, raise this border */
above = e_container_border_raise(bd);
e_border_raise_latest_set(bd);
if (above)
{
/* We ended up above a border */
ev->stack = above;
e_object_ref(E_OBJECT(above));
ev->type = E_STACKING_ABOVE;
}
else
{
/* No border to raise above, same as a lower! */
ev->stack = NULL;
ev->type = E_STACKING_ABOVE;
}
}
ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_lower(E_Border *bd)
{
E_Event_Border_Stack *ev;
E_Border *last = NULL, *child;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
if (e_config->transient.lower)
{
Eina_List *l, *l_prev;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_REVERSE_FOREACH_SAFE(list, l, l_prev, child)
{
/* Don't stack iconic transients. If the user wants these shown,
* thats another option.
*/
if (!child->iconic)
{
if (last)
e_border_stack_below(child, last);
else
{
E_Border *below;
/* First lower the border to find out which border we will end up below */
below = e_container_border_lower(child);
if (below)
{
/* We ended up below a border, now we must stack this border to
* generate the stacking event, and to check if this transient
* has other transients etc.
*/
e_border_stack_below(child, below);
}
else
{
/* If we didn't end up below any border, we are on top! */
e_border_raise(child);
}
}
last = child;
}
list = eina_list_remove_list(list, l);
}
}
ev = E_NEW(E_Event_Border_Stack, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
if (last)
{
e_container_border_stack_below(bd, last);
ev->stack = last;
e_object_ref(E_OBJECT(last));
ev->type = E_STACKING_BELOW;
}
else
{
E_Border *below;
/* If we don't have any children, lower this border */
below = e_container_border_lower(bd);
if (below)
{
/* We ended up below a border */
ev->stack = below;
e_object_ref(E_OBJECT(below));
ev->type = E_STACKING_BELOW;
}
else
{
/* No border to hide under, same as a raise! */
ev->stack = NULL;
ev->type = E_STACKING_BELOW;
}
}
ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_stack_above(E_Border *bd,
E_Border *above)
{
/* TODO: Should stack above allow the border to change level */
E_Event_Border_Stack *ev;
E_Border *last = NULL, *child;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
if (e_config->transient.raise)
{
Eina_List *l, *l_prev;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_REVERSE_FOREACH_SAFE(list, l, l_prev, child)
{
/* Don't stack iconic transients. If the user wants these shown,
* thats another option.
*/
if (!child->iconic)
{
if (last)
e_border_stack_below(child, last);
else
e_border_stack_above(child, above);
last = child;
}
list = eina_list_remove_list(list, l);
}
}
ev = E_NEW(E_Event_Border_Stack, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
if (last)
{
e_container_border_stack_below(bd, last);
ev->stack = last;
e_object_ref(E_OBJECT(last));
ev->type = E_STACKING_BELOW;
}
else
{
e_container_border_stack_above(bd, above);
ev->stack = above;
e_object_ref(E_OBJECT(above));
ev->type = E_STACKING_ABOVE;
}
ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_stack_below(E_Border *bd,
E_Border *below)
{
/* TODO: Should stack below allow the border to change level */
E_Event_Border_Stack *ev;
E_Border *last = NULL, *child;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
ecore_x_window_shadow_tree_flush();
if (e_config->transient.lower)
{
Eina_List *l, *l_prev;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_REVERSE_FOREACH_SAFE(list, l, l_prev, child)
{
/* Don't stack iconic transients. If the user wants these shown,
* thats another option.
*/
if (!child->iconic)
{
if (last)
e_border_stack_below(child, last);
else
e_border_stack_below(child, below);
last = child;
}
list = eina_list_remove_list(list, l);
}
}
ev = E_NEW(E_Event_Border_Stack, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
if (last)
{
e_container_border_stack_below(bd, last);
ev->stack = last;
e_object_ref(E_OBJECT(last));
ev->type = E_STACKING_BELOW;
}
else
{
e_container_border_stack_below(bd, below);
ev->stack = below;
e_object_ref(E_OBJECT(below));
ev->type = E_STACKING_BELOW;
}
ecore_event_add(E_EVENT_BORDER_STACK, ev, _e_border_event_border_stack_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_focus_latest_set(E_Border *bd)
{
focus_stack = eina_list_remove(focus_stack, bd);
focus_stack = eina_list_prepend(focus_stack, bd);
}
EAPI void
e_border_raise_latest_set(E_Border *bd)
{
raise_stack = eina_list_remove(raise_stack, bd);
raise_stack = eina_list_prepend(raise_stack, bd);
}
/*
* Sets the focus to the given border if necessary
* There are 3 cases of different focus_policy-configurations:
*
* - E_FOCUS_CLICK: just set the focus, the most simple one
*
* - E_FOCUS_MOUSE: focus is where the mouse is, so try to
* warp the pointer to the window. If this fails (because
* the pointer is already in the window), just set the focus.
*
* - E_FOCUS_SLOPPY: focus is where the mouse is or on the
* last window which was focused, if the mouse is on the
* desktop. So, we need to look if there is another window
* under the pointer and warp to pointer to the right
* one if so (also, we set the focus afterwards). In case
* there is no window under pointer, the pointer is on the
* desktop and so we just set the focus.
*
*
* This function is to be called when setting the focus was not
* explicitly triggered by the user (by moving the mouse or
* clicking for example), but implicitly (by closing a window,
* the last focused window should get focus).
*
*/
EAPI void
e_border_focus_set_with_pointer(E_Border *bd)
{
#ifdef PRINT_LOTS_OF_DEBUG
E_PRINT_BORDER_INFO(bd);
#endif
/* note: this is here as it seems there are enough apps that do not even
* expect us to emulate a look of focus but not actually set x input
* focus as we do - so simply abort any focuse set on such windows */
/* be strict about accepting focus hint */
if ((!bd->client.icccm.accepts_focus) &&
(!bd->client.icccm.take_focus)) return;
if (bd->lock_focus_out) return;
if (bd == focused) return;
e_border_focus_set(bd, 1, 1);
if (e_config->focus_policy == E_FOCUS_CLICK) return;
if (!bd->visible) return;
if (e_config->focus_policy == E_FOCUS_SLOPPY)
{
E_Border *pbd;
int ret = 0;
pbd = e_border_under_pointer_get(bd->desk, bd);
/* Do not slide pointer when disabled (probably breaks focus
* on sloppy/mouse focus but requested by users). */
if (e_config->pointer_slide && pbd && (pbd != bd))
ret = e_border_pointer_warp_to_center(bd);
if (!ret) e_border_focus_set(bd, 1, 0);
}
else
{
if (e_config->pointer_slide && (!e_border_pointer_warp_to_center(bd)))
e_border_focus_set(bd, 1, 0);
}
}
EAPI void
e_border_focus_set(E_Border *bd,
int focus,
int set)
{
E_Border *bd_unfocus = NULL;
Eina_Bool focus_changed = EINA_FALSE;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
/* note: this is here as it seems there are enough apps that do not even
* expect us to emulate a look of focus but not actually set x input
* focus as we do - so simply abort any focuse set on such windows */
/* be strict about accepting focus hint */
if ((!bd->client.icccm.accepts_focus) &&
(!bd->client.icccm.take_focus))
return;
if ((set) && (focus) && (bd->lock_focus_out)) return;
/* dont focus an iconified window. that's silly! */
if (focus)
{
if ((bd->iconic) && (!bd->deskshow))
{
e_border_uniconify(bd);
if (!focus_track_frozen)
e_border_focus_latest_set(bd);
return;
}
else if (!bd->visible)
{
return;
}
/* FIXME: hack for deskflip animation:
* dont update focus when sliding previous desk */
else if ((!bd->sticky) &&
(bd->desk != e_desk_current_get(bd->desk->zone)))
{
return;
}
}
if ((bd->modal) && (bd->modal != bd) && (bd->modal->visible))
{
e_border_focus_set(bd->modal, focus, set);
return;
}
else if ((bd->leader) && (bd->leader->modal) && (bd->leader->modal != bd))
{
e_border_focus_set(bd->leader->modal, focus, set);
return;
}
if (focus)
{
if (set)
{
if (bd->visible && bd->changes.visible)
{
bd->want_focus = 1;
BD_CHANGED(bd);
}
else if ((!bd->focused) ||
(focus_next && (bd != eina_list_data_get(focus_next))))
{
Eina_List *l;
if ((l = eina_list_data_find_list(focus_next, bd)))
focus_next = eina_list_promote_list(focus_next, l);
else
focus_next = eina_list_prepend(focus_next, bd);
}
if ((bd->client.icccm.take_focus) &&
(bd->client.icccm.accepts_focus))
{
e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
/* TODO what if the client didn't take focus ? */
}
else if (!bd->client.icccm.accepts_focus)
{
e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
}
else if (!bd->client.icccm.take_focus)
{
e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
/* e_border_focus_set(bd, 1, 0); */
}
return;
}
if (!bd->focused)
{
if (focused) bd_unfocus = focused;
if (focusing == bd) focusing = NULL;
bd->focused = 1;
focused = bd;
if ((!e_config->allow_above_fullscreen) && (!bd_unfocus))
{
Eina_List *l;
E_Border *bd2;
EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
{
if ((bd2->fullscreen) &&
(bd2 != bd) &&
(bd2->zone == bd->zone) &&
((bd2->desk == bd->desk) ||
(bd2->sticky) || (bd->sticky)))
{
Eina_Bool unfocus_is_parent = EINA_FALSE;
E_Border *bd_parent;
bd_parent = bd->parent;
while (bd_parent)
{
if (bd_parent == bd2)
{
unfocus_is_parent = EINA_TRUE;
break;
}
bd_parent = bd->parent;
}
if (!unfocus_is_parent)
e_border_unfullscreen(bd2);
}
}
}
focus_changed = EINA_TRUE;
}
}
else
{
bd->want_focus = 0;
focus_next = eina_list_remove(focus_next, bd);
if (bd == focusing) focusing = NULL;
if (bd->focused)
{
Eina_Bool wasfocused = EINA_FALSE;
bd_unfocus = bd;
/* should always be the case. anyway */
if (bd == focused)
{
focused = NULL;
wasfocused = EINA_TRUE;
}
if ((set) && (!focus_next) && (!focusing))
{
e_grabinput_focus(bd->zone->container->bg_win,
E_FOCUS_METHOD_PASSIVE);
}
if ((!e_config->allow_above_fullscreen) &&
(bd->fullscreen) && (wasfocused) &&
((bd->desk == e_desk_current_get(bd->zone)) || (bd->sticky)))
{
Eina_Bool have_vis_child = EINA_FALSE;
Eina_List *l;
E_Border *bd2;
EINA_LIST_FOREACH(e_border_client_list(), l, bd2)
{
if ((bd2 != bd) &&
(bd2->zone == bd->zone) &&
((bd2->desk == bd->desk) ||
(bd2->sticky) || (bd->sticky)))
{
if (bd2->parent == bd)
{
have_vis_child = EINA_TRUE;
break;
}
}
}
if (!have_vis_child)
e_border_unfullscreen(bd);
}
}
}
if ((bd_unfocus) &&
(!e_object_is_del(E_OBJECT(bd_unfocus)) &&
(e_object_ref_get(E_OBJECT(bd_unfocus)) > 0)))
{
E_Event_Border_Focus_Out *ev;
bd_unfocus->focused = 0;
e_focus_event_focus_out(bd_unfocus);
if (bd_unfocus->raise_timer)
ecore_timer_del(bd_unfocus->raise_timer);
bd_unfocus->raise_timer = NULL;
edje_object_signal_emit(bd_unfocus->bg_object, "e,state,unfocused", "e");
if (bd_unfocus->icon_object)
edje_object_signal_emit(bd_unfocus->icon_object, "e,state,unfocused", "e");
ev = E_NEW(E_Event_Border_Focus_Out, 1);
ev->border = bd_unfocus;
e_object_ref(E_OBJECT(bd_unfocus));
ecore_event_add(E_EVENT_BORDER_FOCUS_OUT, ev,
_e_border_event_border_focus_out_free, NULL);
if ((!e_config->allow_above_fullscreen) &&
(bd_unfocus->fullscreen) &&
(bd != bd_unfocus) &&
(bd->zone == bd_unfocus->zone) &&
((bd->desk == bd_unfocus->desk) ||
(bd->sticky) || (bd_unfocus->sticky)))
{
Eina_Bool unfocus_is_parent = EINA_FALSE;
E_Border *bd_parent;
bd_parent = bd->parent;
while (bd_parent)
{
if (bd_parent == bd_unfocus)
{
unfocus_is_parent = EINA_TRUE;
break;
}
bd_parent = bd->parent;
}
if (!unfocus_is_parent)
e_border_unfullscreen(bd_unfocus);
}
}
if (focus_changed)
{
E_Event_Border_Focus_In *ev;
e_focus_event_focus_in(bd);
if (!focus_track_frozen)
e_border_focus_latest_set(bd);
e_hints_active_window_set(bd->zone->container->manager, bd);
edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
if (bd->icon_object)
edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
ev = E_NEW(E_Event_Border_Focus_In, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_FOCUS_IN, ev,
_e_border_event_border_focus_in_free, NULL);
}
}
EAPI void
e_border_shade(E_Border *bd,
E_Direction dir)
{
E_Event_Border_Simple *ev;
Eina_List *l;
E_Border *tmp;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((bd->shaded) || (bd->shading) || (bd->fullscreen) ||
((bd->maximized) && (!e_config->allow_manip))) return;
if ((bd->client.border.name) &&
(!strcmp("borderless", bd->client.border.name))) return;
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
ecore_x_window_hide(tmp->win);
ecore_x_window_shadow_tree_flush();
bd->shade.x = bd->x;
bd->shade.y = bd->y;
bd->shade.dir = dir;
e_hints_window_shaded_set(bd, 1);
e_hints_window_shade_direction_set(bd, dir);
if (e_config->border_shade_animate && (!bd->new_client))
{
bd->shade.start = ecore_loop_time_get();
bd->shading = 1;
bd->changes.shading = 1;
BD_CHANGED(bd);
bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
edje_object_signal_emit(bd->bg_object, "e,state,shading", "e");
}
else
{
Eina_Bool move = EINA_FALSE;
if (bd->shade.dir == E_DIRECTION_UP)
{
bd->h = bd->client_inset.t;
}
else if (bd->shade.dir == E_DIRECTION_DOWN)
{
bd->h = bd->client_inset.t;
bd->y = bd->y + bd->client.h;
move = EINA_TRUE;
}
else if (bd->shade.dir == E_DIRECTION_LEFT)
{
bd->w = bd->client_inset.t;
}
else if (bd->shade.dir == E_DIRECTION_RIGHT)
{
bd->w = bd->client_inset.t;
bd->x = bd->x + bd->client.w;
move = EINA_TRUE;
}
if (bd->client.shaped)
{
bd->need_shape_merge = 1;
bd->need_shape_export = 1;
}
if (bd->shaped_input)
{
bd->need_shape_merge = 1;
}
bd->shaded = 1;
bd->changes.shaded = 1;
BD_CHANGED(bd);
edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
e_border_frame_recalc(bd);
if (move)
{
ev = E_NEW(E_Event_Border_Simple, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
e_container_shape_move(bd->shape, bd->x, bd->y);
}
e_container_shape_resize(bd->shape, bd->w, bd->h);
e_border_comp_hidden_set(bd, EINA_TRUE);
ev = E_NEW(E_Event_Border_Simple, 1);
ev->border = bd;
/* The resize is added in the animator when animation complete */
/* For non-animated, we add it immediately with the new size */
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
}
e_remember_update(bd);
}
EAPI void
e_border_unshade(E_Border *bd,
E_Direction dir)
{
E_Event_Border_Simple *ev;
Eina_List *l;
E_Border *tmp;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((!bd->shaded) || (bd->shading))
return;
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
ecore_x_window_show(tmp->win);
ecore_x_window_shadow_tree_flush();
bd->shade.dir = dir;
e_hints_window_shaded_set(bd, 0);
e_hints_window_shade_direction_set(bd, dir);
if (bd->shade.dir == E_DIRECTION_UP ||
bd->shade.dir == E_DIRECTION_LEFT)
{
bd->shade.x = bd->x;
bd->shade.y = bd->y;
}
else
{
bd->shade.x = bd->x - bd->client.w;
bd->shade.y = bd->y - bd->client.h;
}
if (e_config->border_shade_animate)
{
bd->shade.start = ecore_loop_time_get();
bd->shading = 1;
bd->changes.shading = 1;
BD_CHANGED(bd);
bd->shade.anim = ecore_animator_add(_e_border_shade_animator, bd);
edje_object_signal_emit(bd->bg_object, "e,state,unshading", "e");
}
else
{
Eina_Bool move = EINA_FALSE;
if (bd->shade.dir == E_DIRECTION_UP)
{
bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
}
else if (bd->shade.dir == E_DIRECTION_DOWN)
{
bd->h = bd->client_inset.t + bd->client.h + bd->client_inset.b;
bd->y = bd->y - bd->client.h;
move = EINA_TRUE;
}
else if (bd->shade.dir == E_DIRECTION_LEFT)
{
bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
}
else if (bd->shade.dir == E_DIRECTION_RIGHT)
{
bd->w = bd->client_inset.l + bd->client.w + bd->client_inset.r;
bd->x = bd->x - bd->client.w;
move = EINA_TRUE;
}
if (bd->client.shaped)
{
bd->need_shape_merge = 1;
bd->need_shape_export = 1;
}
if (bd->shaped_input)
{
bd->need_shape_merge = 1;
}
bd->shaded = 0;
bd->changes.shaded = 1;
BD_CHANGED(bd);
edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
e_border_frame_recalc(bd);
if (move)
{
ev = E_NEW(E_Event_Border_Simple, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
e_container_shape_move(bd->shape, bd->x, bd->y);
}
e_container_shape_resize(bd->shape, bd->w, bd->h);
e_border_comp_hidden_set(bd, EINA_FALSE);
ev = E_NEW(E_Event_Border_Simple, 1);
ev->border = bd;
/* The resize is added in the animator when animation complete */
/* For non-animated, we add it immediately with the new size */
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
}
e_remember_update(bd);
}
static void
_e_border_client_inset_calc(E_Border *bd)
{
int w, h, cx, cy, cw, ch;
if (bd->bg_object)
{
Evas_Object *layout;
layout = e_comp_get(bd)->layout;
if (layout) e_layout_freeze(layout);
evas_object_geometry_get(bd->bg_object, NULL, NULL, &w, &h);
evas_object_resize(bd->bg_object, MAX(w, 50), MAX(h, 50));
edje_object_message_signal_process(bd->bg_object);
edje_object_calc_force(bd->bg_object);
edje_object_part_geometry_get(bd->bg_object, "e.swallow.client", &cx, &cy, &cw, &ch);
bd->client_inset.l = cx;
bd->client_inset.r = MAX(w, 50) - (cx + cw);
bd->client_inset.t = cy;
bd->client_inset.b = MAX(h, 50) - (cy + ch);
evas_object_resize(bd->bg_object, w, h);
if (layout) e_layout_thaw(layout);
}
else
{
bd->client_inset.l = 0;
bd->client_inset.r = 0;
bd->client_inset.t = 0;
bd->client_inset.b = 0;
}
ecore_x_netwm_frame_size_set(bd->client.win,
bd->client_inset.l, bd->client_inset.r,
bd->client_inset.t, bd->client_inset.b);
ecore_x_e_frame_size_set(bd->client.win,
bd->client_inset.l, bd->client_inset.r,
bd->client_inset.t, bd->client_inset.b);
bd->client_inset.calc = 1;
}
static void
_e_border_maximize(E_Border *bd, E_Maximize max)
{
int x1, yy1, x2, y2;
int w, h, pw, ph;
int zx, zy, zw, zh;
zx = zy = zw = zh = 0;
switch (max & E_MAXIMIZE_TYPE)
{
case E_MAXIMIZE_NONE:
/* Ignore */
break;
case E_MAXIMIZE_FULLSCREEN:
w = bd->zone->w;
h = bd->zone->h;
if (bd->bg_object)
{
edje_object_signal_emit(bd->bg_object, "e,action,maximize,fullscreen", "e");
_e_border_client_inset_calc(bd);
}
e_border_resize_limit(bd, &w, &h);
/* center x-direction */
x1 = bd->zone->x + (bd->zone->w - w) / 2;
/* center y-direction */
yy1 = bd->zone->y + (bd->zone->h - h) / 2;
switch (max & E_MAXIMIZE_DIRECTION)
{
case E_MAXIMIZE_BOTH:
e_border_move_resize(bd, x1, yy1, w, h);
break;
case E_MAXIMIZE_VERTICAL:
e_border_move_resize(bd, bd->x, yy1, bd->w, h);
break;
case E_MAXIMIZE_HORIZONTAL:
e_border_move_resize(bd, x1, bd->y, w, bd->h);
break;
case E_MAXIMIZE_LEFT:
e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
break;
case E_MAXIMIZE_RIGHT:
e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
break;
}
break;
case E_MAXIMIZE_SMART:
case E_MAXIMIZE_EXPAND:
if (bd->zone)
e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
w = zw, h = zh;
if (bd->bg_object)
{
edje_object_signal_emit(bd->bg_object, "e,action,maximize", "e");
_e_border_client_inset_calc(bd);
}
e_border_resize_limit(bd, &w, &h);
if (bd->w < zw)
w = bd->w;
else
w = zw;
if (bd->h < zh)
h = bd->h;
else
h = zh;
if (bd->x < zx) // window left not useful coordinates
x1 = zx;
else if (bd->x + bd->w > zx + zw) // window right not useful coordinates
x1 = zx + zw - bd->w;
else // window normal position
x1 = bd->x;
if (bd->y < zy) // window top not useful coordinates
yy1 = zy;
else if (bd->y + bd->h > zy + zh) // window bottom not useful coordinates
yy1 = zy + zh - bd->h;
else // window normal position
yy1 = bd->y;
switch (max & E_MAXIMIZE_DIRECTION)
{
case E_MAXIMIZE_BOTH:
e_border_move_resize(bd, zx, zy, zw, zh);
break;
case E_MAXIMIZE_VERTICAL:
e_border_move_resize(bd, x1, zy, w, zh);
break;
case E_MAXIMIZE_HORIZONTAL:
e_border_move_resize(bd, zx, yy1, zw, h);
break;
case E_MAXIMIZE_LEFT:
e_border_move_resize(bd, zx, zy, zw / 2, zh);
break;
case E_MAXIMIZE_RIGHT:
e_border_move_resize(bd, zx + zw / 2, zy, zw / 2, zh);
break;
}
break;
case E_MAXIMIZE_FILL:
x1 = bd->zone->x;
yy1 = bd->zone->y;
x2 = bd->zone->x + bd->zone->w;
y2 = bd->zone->y + bd->zone->h;
/* walk through all shelves */
e_maximize_border_shelf_fill(bd, &x1, &yy1, &x2, &y2, max);
/* walk through all windows */
e_maximize_border_border_fill(bd, &x1, &yy1, &x2, &y2, max);
w = x2 - x1;
h = y2 - yy1;
pw = w;
ph = h;
e_border_resize_limit(bd, &w, &h);
/* center x-direction */
x1 = x1 + (pw - w) / 2;
/* center y-direction */
yy1 = yy1 + (ph - h) / 2;
switch (max & E_MAXIMIZE_DIRECTION)
{
case E_MAXIMIZE_BOTH:
e_border_move_resize(bd, x1, yy1, w, h);
break;
case E_MAXIMIZE_VERTICAL:
e_border_move_resize(bd, bd->x, yy1, bd->w, h);
break;
case E_MAXIMIZE_HORIZONTAL:
e_border_move_resize(bd, x1, bd->y, w, bd->h);
break;
case E_MAXIMIZE_LEFT:
e_border_move_resize(bd, bd->zone->x, bd->zone->y, w / 2, h);
break;
case E_MAXIMIZE_RIGHT:
e_border_move_resize(bd, x1, bd->zone->y, w / 2, h);
break;
}
break;
}
}
EAPI void
e_border_maximize(E_Border *bd,
E_Maximize max)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
if ((bd->shaded) || (bd->shading)) return;
ecore_x_window_shadow_tree_flush();
if (bd->fullscreen)
e_border_unfullscreen(bd);
/* Only allow changes in vertical/ horizontal maximization */
if (((bd->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION)) ||
((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_BOTH)) return;
if (bd->new_client)
{
bd->need_maximize = 1;
bd->maximized &= ~E_MAXIMIZE_TYPE;
bd->maximized |= max;
return;
}
bd->pre_res_change.valid = 0;
if (!(bd->maximized & E_MAXIMIZE_HORIZONTAL))
{
/* Horizontal hasn't been set */
bd->saved.x = bd->x - bd->zone->x;
bd->saved.w = bd->w;
}
if (!(bd->maximized & E_MAXIMIZE_VERTICAL))
{
/* Vertical hasn't been set */
bd->saved.y = bd->y - bd->zone->y;
bd->saved.h = bd->h;
}
bd->saved.zone = bd->zone->num;
e_hints_window_size_set(bd);
e_border_raise(bd);
_e_border_maximize(bd, max);
/* Remove previous type */
bd->maximized &= ~E_MAXIMIZE_TYPE;
/* Add new maximization. It must be added, so that VERTICAL + HORIZONTAL == BOTH */
bd->maximized |= max;
if ((bd->maximized & E_MAXIMIZE_DIRECTION) > E_MAXIMIZE_BOTH)
/* left/right maximize */
e_hints_window_maximized_set(bd, 0,
((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_LEFT) ||
((bd->maximized & E_MAXIMIZE_DIRECTION) == E_MAXIMIZE_RIGHT));
else
e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
bd->maximized & E_MAXIMIZE_VERTICAL);
e_remember_update(bd);
}
EAPI void
e_border_unmaximize(E_Border *bd,
E_Maximize max)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!(max & E_MAXIMIZE_DIRECTION))
{
CRI("BUG: Unmaximize call without direction!");
return;
}
if ((bd->shaded) || (bd->shading)) return;
ecore_x_window_shadow_tree_flush();
/* Remove directions not used */
max &= (bd->maximized & E_MAXIMIZE_DIRECTION);
/* Can only remove existing maximization directions */
if (!max) return;
if (bd->maximized & E_MAXIMIZE_TYPE)
{
bd->pre_res_change.valid = 0;
bd->need_maximize = 0;
if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
{
if (bd->bg_object)
{
edje_object_signal_emit(bd->bg_object, "e,action,unmaximize,fullscreen", "e");
_e_border_client_inset_calc(bd);
}
bd->maximized = E_MAXIMIZE_NONE;
_e_border_move_resize_internal(bd,
bd->zone->x + bd->saved.x,
bd->zone->y + bd->saved.y,
bd->saved.w, bd->saved.h, 0, 1);
bd->saved.x = bd->saved.y = bd->saved.w = bd->saved.h = 0;
e_hints_window_size_unset(bd);
}
else
{
int w, h, x, y;
w = bd->w;
h = bd->h;
x = bd->x;
y = bd->y;
if (((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_SMART) ||
((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_EXPAND))
{
if (bd->bg_object)
{
edje_object_signal_emit(bd->bg_object, "e,action,unmaximize,fullscreen", "e");
_e_border_client_inset_calc(bd);
}
}
if (max & E_MAXIMIZE_VERTICAL)
{
/* Remove vertical */
h = bd->saved.h;
y = bd->saved.y + bd->zone->y;
bd->saved.h = bd->saved.y = 0;
bd->maximized &= ~E_MAXIMIZE_VERTICAL;
bd->maximized &= ~E_MAXIMIZE_LEFT;
bd->maximized &= ~E_MAXIMIZE_RIGHT;
}
if (max & E_MAXIMIZE_HORIZONTAL)
{
/* Remove horizontal */
w = bd->saved.w;
x = bd->saved.x + bd->zone->x;
bd->saved.w = bd->saved.x = 0;
bd->maximized &= ~E_MAXIMIZE_HORIZONTAL;
}
e_border_resize_limit(bd, &w, &h);
if (!(bd->maximized & E_MAXIMIZE_DIRECTION))
{
bd->maximized = E_MAXIMIZE_NONE;
_e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
e_hints_window_size_unset(bd);
edje_object_signal_emit(bd->bg_object, "e,action,unmaximize", "e");
}
else
{
_e_border_move_resize_internal(bd, x, y, w, h, 0, 1);
e_hints_window_size_set(bd);
}
}
e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
bd->maximized & E_MAXIMIZE_VERTICAL);
}
e_remember_update(bd);
}
EAPI void
e_border_fullscreen(E_Border *bd,
E_Fullscreen policy)
{
E_Event_Border_Fullscreen *ev;
int x, y, w, h;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((bd->shaded) || (bd->shading)) return;
ecore_x_window_shadow_tree_flush();
if (bd->new_client)
{
bd->need_fullscreen = 1;
return;
}
if (!bd->fullscreen)
{
bd->pre_res_change.valid = 0;
if (bd->maximized)
{
x = bd->saved.x;
y = bd->saved.y;
w = bd->saved.w;
h = bd->saved.h;
}
else
{
bd->saved.x = bd->x - bd->zone->x;
bd->saved.y = bd->y - bd->zone->y;
bd->saved.w = bd->client.w;
bd->saved.h = bd->client.h;
}
bd->saved.maximized = bd->maximized;
bd->saved.zone = bd->zone->num;
if (bd->maximized)
{
e_border_unmaximize(bd, E_MAXIMIZE_BOTH);
bd->saved.x = x;
bd->saved.y = y;
bd->saved.w = w;
bd->saved.h = h;
}
e_hints_window_size_set(bd);
bd->client_inset.l = 0;
bd->client_inset.r = 0;
bd->client_inset.t = 0;
bd->client_inset.b = 0;
bd->desk->fullscreen_borders++;
/* e_zone_fullscreen_set(bd->zone, 1); */
bd->saved.layer = bd->layer;
if (!e_config->allow_above_fullscreen)
e_border_layer_set(bd, E_LAYER_FULLSCREEN);
else if (e_config->mode.presentation)
e_border_layer_set(bd, E_LAYER_TOP);
if ((eina_list_count(bd->zone->container->zones) > 1) ||
(policy == E_FULLSCREEN_RESIZE) || (!ecore_x_randr_query()))
{
e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
}
else if (policy == E_FULLSCREEN_ZOOM)
{
Ecore_X_Randr_Screen_Size_MM *sizes;
int num_sizes, i, best_size_index = 0;
ecore_x_randr_screen_primary_output_current_size_get(bd->zone->container->manager->root,
&screen_size.width,
&screen_size.height,
NULL, NULL, NULL);
sizes = ecore_x_randr_screen_primary_output_sizes_get(bd->zone->container->manager->root,
&num_sizes);
if (sizes)
{
Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
int best_dist = INT_MAX, dist;
for (i = 0; i < num_sizes; i++)
{
if ((sizes[i].width > bd->w) && (sizes[i].height > bd->h))
{
dist = (sizes[i].width * sizes[i].height) - (bd->w * bd->h);
if (dist < best_dist)
{
best_size.width = sizes[i].width;
best_size.height = sizes[i].height;
best_dist = dist;
best_size_index = i;
}
}
}
if (((best_size.width != -1) && (best_size.height != -1)) &&
((best_size.width != screen_size.width) ||
(best_size.height != screen_size.height)))
{
if (ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
best_size_index))
screen_size_index = best_size_index;
e_border_move_resize(bd, 0, 0, best_size.width, best_size.height);
}
else
{
screen_size.width = -1;
screen_size.height = -1;
e_border_move_resize(bd, 0, 0, bd->zone->w, bd->zone->h);
}
free(sizes);
}
else
e_border_move_resize(bd, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h);
}
bd->fullscreen = 1;
e_hints_window_fullscreen_set(bd, 1);
e_hints_window_size_unset(bd);
bd->client.border.changed = 1;
BD_CHANGED(bd);
}
bd->fullscreen_policy = policy;
_e_border_shadow(bd);
ev = E_NEW(E_Event_Border_Fullscreen, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_fullscreen_event");
ecore_event_add(E_EVENT_BORDER_FULLSCREEN, ev, _e_border_event_border_fullscreen_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_unfullscreen(E_Border *bd)
{
E_Event_Border_Unfullscreen *ev;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((bd->shaded) || (bd->shading)) return;
ecore_x_window_shadow_tree_flush();
if (bd->fullscreen)
{
bd->pre_res_change.valid = 0;
bd->fullscreen = 0;
bd->need_fullscreen = 0;
bd->desk->fullscreen_borders--;
if ((screen_size.width != -1) && (screen_size.height != -1))
{
ecore_x_randr_screen_primary_output_size_set(bd->zone->container->manager->root,
screen_size_index);
screen_size.width = -1;
screen_size.height = -1;
}
_e_border_move_resize_internal(bd,
bd->zone->x + bd->saved.x,
bd->zone->y + bd->saved.y,
bd->saved.w, bd->saved.h, 0, 1);
if (bd->saved.maximized)
e_border_maximize(bd, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
bd->saved.maximized);
e_border_layer_set(bd, bd->saved.layer);
e_hints_window_fullscreen_set(bd, 0);
bd->client.border.changed = 1;
BD_CHANGED(bd);
}
bd->fullscreen_policy = 0;
_e_border_shadow(bd);
ev = E_NEW(E_Event_Border_Unfullscreen, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_unfullscreen_event");
ecore_event_add(E_EVENT_BORDER_UNFULLSCREEN, ev, _e_border_event_border_unfullscreen_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_iconify(E_Border *bd)
{
E_Event_Border_Iconify *ev;
unsigned int iconic;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->shading) return;
ecore_x_window_shadow_tree_flush();
if (!bd->iconic)
{
bd->iconic = 1;
bd->take_focus = 0;
e_border_hide(bd, 1);
if (bd->fullscreen) bd->desk->fullscreen_borders--;
edje_object_signal_emit(bd->bg_object, "e,action,iconify", "e");
}
iconic = 1;
e_hints_window_iconic_set(bd);
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
ev = E_NEW(E_Event_Border_Iconify, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_iconify_event");
ecore_event_add(E_EVENT_BORDER_ICONIFY, ev, _e_border_event_border_iconify_free, NULL);
if (e_config->transient.iconify)
{
E_Border *child;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_FREE(list, child)
e_border_iconify(child);
}
e_remember_update(bd);
}
EAPI void
e_border_uniconify(E_Border *bd)
{
E_Desk *desk;
E_Event_Border_Uniconify *ev;
unsigned int iconic;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->shading) return;
ecore_x_window_shadow_tree_flush();
e_border_show(bd);
if (bd->iconic)
{
bd->iconic = 0;
if (bd->fullscreen) bd->desk->fullscreen_borders++;
desk = e_desk_current_get(bd->desk->zone);
e_border_desk_set(bd, desk);
e_border_raise(bd);
edje_object_signal_emit(bd->bg_object, "e,action,uniconify", "e");
}
iconic = 0;
ecore_x_window_prop_card32_set(bd->client.win, E_ATOM_MAPPED, &iconic, 1);
ev = E_NEW(E_Event_Border_Uniconify, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_uniconify_event");
ecore_event_add(E_EVENT_BORDER_UNICONIFY, ev, _e_border_event_border_uniconify_free, NULL);
if (e_config->transient.iconify)
{
E_Border *child;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_FREE(list, child)
e_border_uniconify(child);
}
e_remember_update(bd);
}
EAPI void
e_border_stick(E_Border *bd)
{
E_Event_Border_Stick *ev;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->sticky) return;
bd->sticky = 1;
e_hints_window_sticky_set(bd, 1);
e_border_show(bd);
if (e_config->transient.desktop)
{
E_Border *child;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_FREE(list, child)
{
child->sticky = 1;
e_hints_window_sticky_set(child, 1);
e_border_show(child);
}
}
edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
ev = E_NEW(E_Event_Border_Stick, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_stick_event");
ecore_event_add(E_EVENT_BORDER_STICK, ev, _e_border_event_border_stick_free, NULL);
e_remember_update(bd);
}
EAPI void
e_border_unstick(E_Border *bd)
{
E_Event_Border_Unstick *ev;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
/* Set the desk before we unstick the border */
if (!bd->sticky) return;
bd->sticky = 0;
e_hints_window_sticky_set(bd, 0);
if (e_config->transient.desktop)
{
E_Border *child;
Eina_List *list = _e_border_sub_borders_new(bd);
EINA_LIST_FREE(list, child)
{
child->sticky = 0;
e_hints_window_sticky_set(child, 0);
}
}
edje_object_signal_emit(bd->bg_object, "e,state,unsticky", "e");
ev = E_NEW(E_Event_Border_Unstick, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_unstick_event");
ecore_event_add(E_EVENT_BORDER_UNSTICK, ev, _e_border_event_border_unstick_free, NULL);
e_border_desk_set(bd, e_desk_current_get(bd->zone));
e_remember_update(bd);
}
EAPI void
e_border_pinned_set(E_Border *bd,
int set)
{
E_Layer layer;
if (bd)
{
bd->borderless = set;
bd->user_skip_winlist = set;
if (set)
layer = E_LAYER_BELOW;
else
layer = E_LAYER_NORMAL;
e_border_layer_set(bd, layer);
bd->client.border.changed = 1;
BD_CHANGED(bd);
}
}
EAPI E_Border *
e_border_find_by_client_window(Ecore_X_Window win)
{
E_Border *bd;
bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
(bd->client.win == win))
return bd;
return NULL;
}
EAPI E_Border *
e_border_find_all_by_client_window(Ecore_X_Window win)
{
E_Border *bd;
bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
if ((bd) && (bd->client.win == win))
return bd;
return NULL;
}
EAPI E_Border *
e_border_find_by_window(Ecore_X_Window win)
{
E_Border *bd;
bd = eina_hash_find(borders_hash, e_util_winid_str_get(win));
if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
((bd->win == win) || (bd->client.lock_win == win)))
return bd;
return NULL;
}
EAPI E_Border *
e_border_find_by_alarm(Ecore_X_Sync_Alarm al)
{
Eina_List *l;
E_Border *bd;
EINA_LIST_FOREACH(borders, l, bd)
{
if ((bd) && (!e_object_is_del(E_OBJECT(bd))) &&
(bd->client.netwm.sync.alarm == al))
return bd;
}
return NULL;
}
EAPI E_Border *
e_border_focused_get(void)
{
return focused;
}
static void
_e_border_shape_input_rectangle_set(E_Border *bd)
{
if (!bd) return;
if ((!bd->visible) || (!bd->shaped_input))
{
if (bd->visible) // not shaped input
{
if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
ecore_x_composite_window_events_enable(bd->win);
else
ecore_x_composite_window_events_disable(bd->win);
}
else
{
if (!e_comp_evas_exists(bd))
ecore_x_composite_window_events_enable(bd->win);
else
ecore_x_composite_window_events_disable(bd->win);
}
}
}
EAPI void
e_border_idler_before(void)
{
Eina_List *ml, *cl;
E_Manager *man;
E_Container *con;
if (!borders)
return;
EINA_LIST_FOREACH(e_manager_list(), ml, man)
{
EINA_LIST_FOREACH(man->containers, cl, con)
{
E_Border_List *bl;
E_Border *bd;
// pass 1 - eval0. fetch properties on new or on change and
// call hooks to decide what to do - maybe move/resize
bl = e_container_border_list_first(con);
while ((bd = e_container_border_list_next(bl)))
{
if (bd->changed) _e_border_eval0(bd);
}
e_container_border_list_free(bl);
// layout hook - this is where a hook gets to figure out what to
// do if anything.
_e_border_container_layout_hook(con);
// pass 2 - show windows needing show
bl = e_container_border_list_first(con);
while ((bd = e_container_border_list_next(bl)))
{
if ((bd->changes.visible) && (bd->visible) &&
(!bd->new_client) && (!bd->changes.pos) &&
(!bd->changes.size))
{
_e_border_show(bd);
bd->changes.visible = 0;
}
if (bd->zone && (!bd->new_client) &&
(!E_INSIDE(bd->x, bd->y, 0, 0, bd->zone->w - 5, bd->zone->h - 5)) &&
(!E_INSIDE(bd->x, bd->y, 0 - bd->w + 5, 0 - bd->h + 5, bd->zone->w - 5, bd->zone->h - 5))
)
{
if (e_config->screen_limits != E_SCREEN_LIMITS_COMPLETELY)
_e_border_move_lost_window_to_center(bd);
}
}
e_container_border_list_free(bl);
// pass 3 - hide windows needing hide and eval (main eval)
bl = e_container_border_list_first(con);
while ((bd = e_container_border_list_next(bl)))
{
if (e_object_is_del(E_OBJECT(bd))) continue;
if ((bd->changes.visible) && (!bd->visible))
{
_e_border_hide(bd);
bd->changes.visible = 0;
}
if (bd->changed) _e_border_eval(bd);
if ((bd->changes.visible) && (bd->visible))
{
_e_border_show(bd);
bd->changes.visible = 0;
}
}
e_container_border_list_free(bl);
}
}
if (focus_next)
{
E_Border *bd = NULL, *bd2;
EINA_LIST_FREE(focus_next, bd2)
if ((!bd) && (bd2->visible)) bd = bd2;
if (!bd)
{
/* TODO revert focus when lost here ? */
return;
}
#if 0
if (bd == focused)
{
/* already focused. but anyway dont be so strict, this
fcks up illume setting focus on internal windows */
return;
}
#endif
focus_time = ecore_x_current_time_get();
focusing = bd;
if ((bd->client.icccm.take_focus) &&
(bd->client.icccm.accepts_focus))
{
e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_LOCALLY_ACTIVE);
/* TODO what if the client didn't take focus ? */
}
else if (!bd->client.icccm.accepts_focus)
{
e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_GLOBALLY_ACTIVE);
}
else if (!bd->client.icccm.take_focus)
{
e_grabinput_focus(bd->client.win, E_FOCUS_METHOD_PASSIVE);
/* e_border_focus_set(bd, 1, 0); */
}
}
}
EAPI Eina_List *
e_border_client_list(void)
{
/* FIXME: This should be a somewhat ordered list */
return borders;
}
static void
_e_border_show(E_Border *bd)
{
Eina_List *l;
E_Border *tmp;
if (bd->post_job)
{
bd->post_show = 1;
return;
}
if (!((bd->comp_hidden) || (bd->tmp_input_hidden > 0)))
{
_e_border_shape_input_rectangle_set(bd);
// not anymore
// ecore_x_composite_window_events_enable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_FALSE);
}
ecore_x_window_show(bd->win);
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
ecore_x_window_show(tmp->win);
}
static void
_e_border_hide(E_Border *bd)
{
E_Border *tmp;
Eina_List *l;
if (!e_comp_evas_exists(bd))
{
ecore_x_window_hide(bd->win);
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
ecore_x_window_hide(tmp->win);
}
else
{
ecore_x_composite_window_events_disable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_TRUE);
}
}
static int
_e_border_action_input_win_del(void)
{
if (!action_input_win)
return 0;
e_grabinput_release(action_input_win, action_input_win);
action_input_win = 0;
return 1;
}
static int
_e_border_action_input_win_new(E_Border *bd)
{
if (!action_input_win)
action_input_win = e_comp_get(bd)->ee_win;
if (e_grabinput_get(action_input_win, 0, action_input_win))
return 1;
_e_border_action_input_win_del();
return 0;
}
static void
_e_border_action_finish(void)
{
_e_border_action_input_win_del();
if (action_timer)
{
ecore_timer_del(action_timer);
action_timer = NULL;
}
if (action_handler_key)
{
ecore_event_handler_del(action_handler_key);
action_handler_key = NULL;
}
if (action_handler_mouse)
{
ecore_event_handler_del(action_handler_mouse);
action_handler_mouse = NULL;
}
action_border = NULL;
}
static void
_e_border_action_init(E_Border *bd)
{
action_orig.x = bd->x;
action_orig.y = bd->y;
action_orig.width = bd->w;
action_orig.height = bd->h;
action_border = bd;
}
static void
_e_border_action_restore_orig(E_Border *bd)
{
if (action_border != bd)
return;
e_border_move_resize(bd, action_orig.x, action_orig.y, action_orig.width, action_orig.height);
}
static int
_e_border_key_down_modifier_apply(int modifier,
int value)
{
if (modifier & ECORE_EVENT_MODIFIER_CTRL)
return value * 2;
else if (modifier & ECORE_EVENT_MODIFIER_ALT)
{
value /= 2;
if (value)
return value;
else
return 1;
}
return value;
}
static Eina_Bool
_e_border_action_move_timeout(void *data __UNUSED__)
{
_e_border_move_end(action_border);
_e_border_action_finish();
return ECORE_CALLBACK_CANCEL;
}
static void
_e_border_action_move_timeout_add(void)
{
E_FREE_FUNC(action_timer, ecore_timer_del);
if (e_config->border_keyboard.timeout)
action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_move_timeout, NULL);
}
static Eina_Bool
_e_border_move_key_down(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_Event_Key *ev = event;
int x, y;
if (ev->event_window != action_input_win)
return ECORE_CALLBACK_PASS_ON;
if (!action_border)
{
fputs("ERROR: no action_border!\n", stderr);
goto stop;
}
x = action_border->x;
y = action_border->y;
if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
y -= _e_border_key_down_modifier_apply(ev->modifiers, MAX(e_config->border_keyboard.move.dy, 1));
else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
y += _e_border_key_down_modifier_apply(ev->modifiers, MAX(e_config->border_keyboard.move.dy, 1));
else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
x -= _e_border_key_down_modifier_apply(ev->modifiers, MAX(e_config->border_keyboard.move.dx, 1));
else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
x += _e_border_key_down_modifier_apply(ev->modifiers, MAX(e_config->border_keyboard.move.dx, 1));
else if (strcmp(ev->key, "Return") == 0)
goto stop;
else if (strcmp(ev->key, "Escape") == 0)
{
_e_border_action_restore_orig(action_border);
goto stop;
}
else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
(strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
goto stop;
e_border_move(action_border, x, y);
_e_border_action_move_timeout_add();
return ECORE_CALLBACK_PASS_ON;
stop:
_e_border_move_end(action_border);
_e_border_action_finish();
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_e_border_move_mouse_down(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_Event_Mouse_Button *ev = event;
if (ev->event_window != action_input_win)
return ECORE_CALLBACK_PASS_ON;
if (!action_border)
fputs("ERROR: no action_border!\n", stderr);
_e_border_move_end(action_border);
_e_border_action_finish();
return ECORE_CALLBACK_DONE;
}
EAPI void
e_border_act_move_keyboard(E_Border *bd)
{
if (!bd)
return;
if (!_e_border_move_begin(bd))
return;
if (!_e_border_action_input_win_new(bd))
{
_e_border_move_end(bd);
return;
}
_e_border_action_init(bd);
_e_border_action_move_timeout_add();
_e_border_move_update(bd);
if (action_handler_key)
ecore_event_handler_del(action_handler_key);
action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_move_key_down, NULL);
if (action_handler_mouse)
ecore_event_handler_del(action_handler_mouse);
action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_move_mouse_down, NULL);
}
static Eina_Bool
_e_border_action_resize_timeout(void *data __UNUSED__)
{
_e_border_resize_end(action_border);
_e_border_action_finish();
return ECORE_CALLBACK_CANCEL;
}
static void
_e_border_action_resize_timeout_add(void)
{
E_FREE_FUNC(action_timer, ecore_timer_del);
if (e_config->border_keyboard.timeout)
action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_border_action_resize_timeout, NULL);
}
static Eina_Bool
_e_border_resize_key_down(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_Event_Key *ev = event;
int w, h, dx, dy;
if (ev->event_window != action_input_win)
return ECORE_CALLBACK_PASS_ON;
if (!action_border)
{
fputs("ERROR: no action_border!\n", stderr);
goto stop;
}
w = action_border->w;
h = action_border->h;
dx = e_config->border_keyboard.resize.dx;
if (dx < action_border->client.icccm.step_w)
dx = action_border->client.icccm.step_w;
dx = _e_border_key_down_modifier_apply(ev->modifiers, dx);
if (dx < action_border->client.icccm.step_w)
dx = action_border->client.icccm.step_w;
dy = e_config->border_keyboard.resize.dy;
if (dy < action_border->client.icccm.step_h)
dy = action_border->client.icccm.step_h;
dy = _e_border_key_down_modifier_apply(ev->modifiers, dy);
if (dy < action_border->client.icccm.step_h)
dy = action_border->client.icccm.step_h;
if ((strcmp(ev->key, "Up") == 0) || (strcmp(ev->key, "k") == 0))
h -= dy;
else if ((strcmp(ev->key, "Down") == 0) || (strcmp(ev->key, "j") == 0))
h += dy;
else if ((strcmp(ev->key, "Left") == 0) || (strcmp(ev->key, "h") == 0))
w -= dx;
else if ((strcmp(ev->key, "Right") == 0) || (strcmp(ev->key, "l") == 0))
w += dx;
else if (strcmp(ev->key, "Return") == 0)
goto stop;
else if (strcmp(ev->key, "Escape") == 0)
{
_e_border_action_restore_orig(action_border);
goto stop;
}
else if ((strncmp(ev->key, "Control", sizeof("Control") - 1) != 0) &&
(strncmp(ev->key, "Alt", sizeof("Alt") - 1) != 0))
goto stop;
e_border_resize_limit(action_border, &w, &h);
e_border_resize(action_border, w, h);
_e_border_action_resize_timeout_add();
return ECORE_CALLBACK_PASS_ON;
stop:
_e_border_resize_end(action_border);
_e_border_action_finish();
return ECORE_CALLBACK_DONE;
}
static Eina_Bool
_e_border_resize_mouse_down(void *data __UNUSED__,
int type __UNUSED__,
void *event)
{
Ecore_Event_Mouse_Button *ev = event;
if (ev->event_window != action_input_win)
return ECORE_CALLBACK_PASS_ON;
if (!action_border)
fputs("ERROR: no action_border!\n", stderr);
_e_border_resize_end(action_border);
_e_border_action_finish();
return ECORE_CALLBACK_DONE;
}
EAPI void
e_border_act_resize_keyboard(E_Border *bd)
{
if (!bd)
return;
if (!_e_border_resize_begin(bd))
return;
_e_border_action_init(bd);
_e_border_action_resize_timeout_add();
_e_border_resize_update(bd);
if (action_handler_key)
ecore_event_handler_del(action_handler_key);
action_handler_key = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, _e_border_resize_key_down, NULL);
if (action_handler_mouse)
ecore_event_handler_del(action_handler_mouse);
action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_border_resize_mouse_down, NULL);
}
EAPI void
e_border_act_move_begin(E_Border *bd,
E_Binding_Event_Mouse_Button *ev)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((bd->resize_mode != E_POINTER_RESIZE_NONE) || (bd->moving)) return;
if (!_e_border_move_begin(bd))
return;
if (!_e_border_action_input_win_new(bd))
{
_e_border_move_end(bd);
return;
}
_e_border_action_init(bd);
e_zone_edge_disable();
bd->moving = 1;
e_pointer_mode_push(bd, E_POINTER_MOVE);
if (ev)
{
char source[256];
snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
_e_border_moveinfo_gather(bd, source);
}
}
EAPI void
e_border_act_move_end(E_Border *bd,
E_Binding_Event_Mouse_Button *ev __UNUSED__)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!bd->moving) return;
e_zone_edge_enable();
_e_border_move_end(bd);
e_zone_flip_coords_handle(bd->zone, -1, -1);
_e_border_action_finish();
}
EAPI void
e_border_act_resize_begin(E_Border *bd,
E_Binding_Event_Mouse_Button *ev)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->lock_user_size || bd->shaded || bd->shading) return;
if ((bd->resize_mode != E_POINTER_RESIZE_NONE) || (bd->moving)) return;
if (!_e_border_resize_begin(bd))
return;
_e_border_action_init(bd);
if (bd->mouse.current.mx < (bd->x + bd->w / 2))
{
if (bd->mouse.current.my < (bd->y + bd->h / 2))
{
bd->resize_mode = E_POINTER_RESIZE_TL;
GRAV_SET(bd, ECORE_X_GRAVITY_SE);
}
else
{
bd->resize_mode = E_POINTER_RESIZE_BL;
GRAV_SET(bd, ECORE_X_GRAVITY_NE);
}
}
else
{
if (bd->mouse.current.my < (bd->y + bd->h / 2))
{
bd->resize_mode = E_POINTER_RESIZE_TR;
GRAV_SET(bd, ECORE_X_GRAVITY_SW);
}
else
{
bd->resize_mode = E_POINTER_RESIZE_BR;
GRAV_SET(bd, ECORE_X_GRAVITY_NW);
}
}
e_pointer_mode_push(bd, bd->resize_mode);
if (ev)
{
char source[256];
snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
_e_border_moveinfo_gather(bd, source);
}
}
EAPI void
e_border_act_resize_end(E_Border *bd,
E_Binding_Event_Mouse_Button *ev __UNUSED__)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->resize_mode != E_POINTER_RESIZE_NONE)
{
_e_border_resize_end(bd);
bd->changes.reset_gravity = 1;
BD_CHANGED(bd);
}
_e_border_action_finish();
}
EAPI void
e_border_act_menu_begin(E_Border *bd,
E_Binding_Event_Mouse_Button *ev,
int key)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (ev)
e_int_border_menu_show(bd, ev->canvas.x, ev->canvas.y, key, ev->timestamp);
else
{
int x, y;
ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
e_int_border_menu_show(bd, x, y, key, 0);
}
}
EAPI void
e_border_act_close_begin(E_Border *bd)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->lock_close) return;
if (bd->client.icccm.delete_request)
{
bd->delete_requested = 1;
ecore_x_window_delete_request_send(bd->client.win);
if (bd->client.netwm.ping)
e_border_ping(bd);
}
else if (e_config->kill_if_close_not_possible)
{
e_border_act_kill_begin(bd);
}
}
EAPI void
e_border_act_kill_begin(E_Border *bd)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->internal) return;
if (bd->lock_close) return;
if ((bd->client.netwm.pid > 1) && (e_config->kill_process))
{
kill(bd->client.netwm.pid, SIGINT);
bd->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
_e_border_cb_kill_timer, bd);
}
else
{
if (!bd->internal) ecore_x_kill(bd->client.win);
}
}
EAPI Evas_Object *
e_border_icon_add(E_Border *bd,
Evas *evas)
{
Evas_Object *o;
E_OBJECT_CHECK_RETURN(bd, NULL);
E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, NULL);
o = NULL;
if (bd->internal)
{
if (!bd->internal_icon)
{
o = e_icon_add(evas);
e_util_icon_theme_set(o, "enlightenment");
}
else
{
if (!bd->internal_icon_key)
{
char *ext;
ext = strrchr(bd->internal_icon, '.');
if ((ext) && ((!strcmp(ext, ".edj"))))
{
o = edje_object_add(evas);
if (!edje_object_file_set(o, bd->internal_icon, "icon"))
e_util_icon_theme_set(o, "enlightenment");
}
else if (ext)
{
o = e_icon_add(evas);
e_icon_file_set(o, bd->internal_icon);
}
else
{
o = e_icon_add(evas);
if (!e_util_icon_theme_set(o, bd->internal_icon))
e_util_icon_theme_set(o, "enlightenment");
}
}
else
{
o = edje_object_add(evas);
edje_object_file_set(o, bd->internal_icon,
bd->internal_icon_key);
}
}
return o;
}
if ((e_config->use_app_icon) && (bd->icon_preference != E_ICON_PREF_USER))
{
if (bd->client.netwm.icons)
{
o = e_icon_add(evas);
e_icon_data_set(o, bd->client.netwm.icons[0].data,
bd->client.netwm.icons[0].width,
bd->client.netwm.icons[0].height);
e_icon_alpha_set(o, 1);
return o;
}
}
if (!o)
{
if ((bd->desktop) && (bd->icon_preference != E_ICON_PREF_NETWM))
{
o = e_icon_add(evas);
if (o)
{
e_icon_fdo_icon_set(o, bd->desktop->icon);
return o;
}
}
else if (bd->client.netwm.icons)
{
o = e_icon_add(evas);
e_icon_data_set(o, bd->client.netwm.icons[0].data,
bd->client.netwm.icons[0].width,
bd->client.netwm.icons[0].height);
e_icon_alpha_set(o, 1);
return o;
}
}
o = e_icon_add(evas);
e_util_icon_theme_set(o, "unknown");
return o;
}
EAPI void
e_border_button_bindings_ungrab_all(void)
{
Eina_List *l;
E_Border *bd;
EINA_LIST_FOREACH(borders, l, bd)
{
e_focus_setdown(bd);
e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
}
}
EAPI void
e_border_button_bindings_grab_all(void)
{
Eina_List *l;
E_Border *bd;
EINA_LIST_FOREACH(borders, l, bd)
{
e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_focus_setup(bd);
}
}
EAPI Eina_List *
e_border_focus_stack_get(void)
{
return focus_stack;
}
EAPI Eina_List *
e_border_raise_stack_get(void)
{
return raise_stack;
}
EAPI Eina_List *
e_border_lost_windows_get(E_Zone *zone)
{
Eina_List *list = NULL, *l;
E_Border *bd;
int loss_overlap = 5;
E_OBJECT_CHECK_RETURN(zone, NULL);
E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
EINA_LIST_FOREACH(borders, l, bd)
{
if (!bd->zone)
continue;
if ((bd->zone != zone) ||
(bd->zone->container != zone->container))
continue;
if (!E_INTERSECTS(bd->zone->x + loss_overlap,
bd->zone->y + loss_overlap,
bd->zone->w - (2 * loss_overlap),
bd->zone->h - (2 * loss_overlap),
bd->x, bd->y, bd->w, bd->h))
{
list = eina_list_append(list, bd);
}
}
return list;
}
static void
_e_border_zones_layout_calc(E_Border *bd, int *zx, int *zy, int *zw, int *zh)
{
int x, y, w, h;
E_Zone *zone_above, *zone_below, *zone_left, *zone_right;
x = bd->zone->x;
y = bd->zone->y;
w = bd->zone->w;
h = bd->zone->h;
if (eina_list_count(bd->zone->container->zones) == 1)
{
if (zx) *zx = x;
if (zy) *zy = y;
if (zw) *zw = w;
if (zh) *zh = h;
return;
}
zone_left = e_container_zone_at_point_get(bd->zone->container, (x - w + 5), y);
zone_right = e_container_zone_at_point_get(bd->zone->container, (x + w + 5), y);
zone_above = e_container_zone_at_point_get(bd->zone->container, x, (y - h + 5));
zone_below = e_container_zone_at_point_get(bd->zone->container, x, (y + h + 5));
if (!(zone_above) && (y))
zone_above = e_container_zone_at_point_get(bd->zone->container, x, (h - 5));
if (!(zone_left) && (x))
zone_left = e_container_zone_at_point_get(bd->zone->container, (x - 5), y);
if (zone_right)
w = zone_right->x + zone_right->w;
if (zone_left)
w = bd->zone->x + bd->zone->w;
if (zone_below)
h = zone_below->y + zone_below->h;
if (zone_above)
h = bd->zone->y + bd->zone->h;
if ((zone_left) && (zone_right))
w = bd->zone->w + zone_right->x;
if ((zone_above) && (zone_below))
h = bd->zone->h + zone_below->y;
if (x) x -= bd->zone->w;
if (y) y -= bd->zone->h;
if (zx) *zx = x > 0 ? x : 0;
if (zy) *zy = y > 0 ? y : 0;
if (zw) *zw = w;
if (zh) *zh = h;
}
static void
_e_border_move_lost_window_to_center(E_Border *bd)
{
int loss_overlap = 5;
int zw, zh, zx, zy;
if (bd->during_lost) return;
if (!(bd->zone)) return;
_e_border_zones_layout_calc(bd, &zx, &zy, &zw, &zh);
if (!E_INTERSECTS(zx + loss_overlap,
zy + loss_overlap,
zw - (2 * loss_overlap),
zh - (2 * loss_overlap),
bd->x, bd->y, bd->w, bd->h))
{
if (e_config->edge_flip_dragging)
{
Eina_Bool lf, rf, tf, bf;
lf = rf = tf = bf = EINA_TRUE;
if (bd->zone->desk_x_count <= 1) lf = rf = EINA_FALSE;
else if (!e_config->desk_flip_wrap)
{
if (bd->zone->desk_x_current == 0) lf = EINA_FALSE;
if (bd->zone->desk_x_current == (bd->zone->desk_x_count - 1)) rf = EINA_FALSE;
}
if (bd->zone->desk_y_count <= 1) tf = bf = EINA_FALSE;
else if (!e_config->desk_flip_wrap)
{
if (bd->zone->desk_y_current == 0) tf = EINA_FALSE;
if (bd->zone->desk_y_current == (bd->zone->desk_y_count - 1)) bf = EINA_FALSE;
}
if (!(lf) && (bd->x <= loss_overlap) && !(bd->zone->flip.switching))
_e_border_reset_lost_window(bd);
if (!(rf) && (bd->x >= (bd->zone->w - loss_overlap)) && !(bd->zone->flip.switching))
_e_border_reset_lost_window(bd);
if (!(tf) && (bd->y <= loss_overlap) && !(bd->zone->flip.switching))
_e_border_reset_lost_window(bd);
if (!(bf) && (bd->y >= (bd->zone->h - loss_overlap)) && !(bd->zone->flip.switching))
_e_border_reset_lost_window(bd);
}
if (!e_config->edge_flip_dragging)
_e_border_reset_lost_window(bd);
}
}
static void
_e_border_reset_lost_window(E_Border *bd)
{
E_OBJECT_CHECK(bd);
if (bd->during_lost) return;
bd->during_lost = EINA_TRUE;
if (bd->iconic) e_border_uniconify(bd);
if (!bd->moving) e_border_center(bd);
e_border_raise(bd);
if (!bd->lock_focus_out)
e_border_focus_set(bd, 1, 1);
e_border_pointer_warp_to_center(bd);
bd->during_lost = EINA_FALSE;
}
EAPI void
e_border_ping(E_Border *bd)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!e_config->ping_clients) return;
bd->ping_ok = 0;
ecore_x_netwm_ping_send(bd->client.win);
bd->ping = ecore_loop_time_get();
if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
bd->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
e_config->ping_clients_interval,
_e_border_cb_ping_poller, bd);
}
EAPI void
e_border_move_cancel(void)
{
if (bdmove)
{
if (bdmove->cur_mouse_action)
{
E_Border *bd;
bd = bdmove;
e_object_ref(E_OBJECT(bd));
if (bd->cur_mouse_action->func.end_mouse)
bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
else if (bd->cur_mouse_action->func.end)
bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
e_object_unref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action = NULL;
e_object_unref(E_OBJECT(bd));
}
else
_e_border_move_end(bdmove);
}
}
EAPI void
e_border_resize_cancel(void)
{
if (bdresize)
{
if (bdresize->cur_mouse_action)
{
E_Border *bd;
bd = bdresize;
e_object_ref(E_OBJECT(bd));
if (bd->cur_mouse_action->func.end_mouse)
bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", NULL);
else if (bd->cur_mouse_action->func.end)
bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
e_object_unref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action = NULL;
e_object_unref(E_OBJECT(bd));
}
else
{
_e_border_resize_end(bdresize);
}
}
}
EAPI void
e_border_frame_recalc(E_Border *bd)
{
int w, h;
if (!bd->bg_object) return;
w = bd->w, h = bd->h;
bd->w -= e_border_inset_width_get(bd);
bd->h -= e_border_inset_height_get(bd);
_e_border_client_inset_calc(bd);
bd->w += e_border_inset_width_get(bd);
bd->h += e_border_inset_height_get(bd);
if (bd->changes.shading || bd->changes.shaded) return;
if ((w != bd->w) || (h != bd->h))
{
BD_CHANGED(bd);
bd->changes.size = 1;
if (bd->client.shaped)
{
bd->need_shape_merge = 1;
bd->need_shape_export = 1;
}
if (bd->shaped_input)
{
bd->need_shape_merge = 1;
}
_e_border_client_move_resize_send(bd);
}
}
EAPI Eina_List *
e_border_immortal_windows_get(void)
{
Eina_List *list = NULL, *l;
E_Border *bd;
EINA_LIST_FOREACH(borders, l, bd)
{
if (bd->lock_life)
list = eina_list_append(list, bd);
}
return list;
}
EAPI const char *
e_border_name_get(const E_Border *bd)
{
E_OBJECT_CHECK_RETURN(bd, "");
E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, "");
if (bd->client.netwm.name)
return bd->client.netwm.name;
else if (bd->client.icccm.title)
return bd->client.icccm.title;
return "";
}
EAPI void
e_border_signal_move_begin(E_Border *bd,
const char *sig,
const char *src __UNUSED__)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((bd->resize_mode != E_POINTER_RESIZE_NONE) || (bd->moving)) return;
if (!_e_border_move_begin(bd)) return;
_e_border_action_init(bd);
bd->moving = 1;
e_pointer_mode_push(bd, E_POINTER_MOVE);
e_zone_edge_disable();
_e_border_moveinfo_gather(bd, sig);
if (bd->cur_mouse_action)
{
if ((!bd->cur_mouse_action->func.end_mouse) &&
(!bd->cur_mouse_action->func.end))
bd->cur_mouse_action = NULL;
else
e_object_unref(E_OBJECT(bd->cur_mouse_action));
}
bd->cur_mouse_action = e_action_find("window_move");
if (bd->cur_mouse_action)
e_object_ref(E_OBJECT(bd->cur_mouse_action));
}
EAPI void
e_border_signal_move_end(E_Border *bd,
const char *sig __UNUSED__,
const char *src __UNUSED__)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (!bd->moving) return;
e_zone_edge_enable();
_e_border_move_end(bd);
e_zone_flip_coords_handle(bd->zone, -1, -1);
}
EAPI int
e_border_resizing_get(E_Border *bd)
{
E_OBJECT_CHECK_RETURN(bd, 0);
E_OBJECT_TYPE_CHECK_RETURN(bd, E_BORDER_TYPE, 0);
if (bd->resize_mode == E_POINTER_RESIZE_NONE) return 0;
return 1;
}
EAPI void
e_border_signal_resize_begin(E_Border *bd,
const char *dir,
const char *sig,
const char *src __UNUSED__)
{
Ecore_X_Gravity grav = ECORE_X_GRAVITY_NW;
int resize_mode = E_POINTER_RESIZE_BR;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if ((bd->resize_mode != E_POINTER_RESIZE_NONE) || (bd->moving)) return;
if (!_e_border_resize_begin(bd))
return;
_e_border_action_init(bd);
if (!strcmp(dir, "tl"))
{
resize_mode = E_POINTER_RESIZE_TL;
grav = ECORE_X_GRAVITY_SE;
}
else if (!strcmp(dir, "t"))
{
resize_mode = E_POINTER_RESIZE_T;
grav = ECORE_X_GRAVITY_S;
}
else if (!strcmp(dir, "tr"))
{
resize_mode = E_POINTER_RESIZE_TR;
grav = ECORE_X_GRAVITY_SW;
}
else if (!strcmp(dir, "r"))
{
resize_mode = E_POINTER_RESIZE_R;
grav = ECORE_X_GRAVITY_W;
}
else if (!strcmp(dir, "br"))
{
resize_mode = E_POINTER_RESIZE_BR;
grav = ECORE_X_GRAVITY_NW;
}
else if (!strcmp(dir, "b"))
{
resize_mode = E_POINTER_RESIZE_B;
grav = ECORE_X_GRAVITY_N;
}
else if (!strcmp(dir, "bl"))
{
resize_mode = E_POINTER_RESIZE_BL;
grav = ECORE_X_GRAVITY_NE;
}
else if (!strcmp(dir, "l"))
{
resize_mode = E_POINTER_RESIZE_L;
grav = ECORE_X_GRAVITY_E;
}
bd->resize_mode = resize_mode;
e_pointer_mode_push(bd, bd->resize_mode);
_e_border_moveinfo_gather(bd, sig);
GRAV_SET(bd, grav);
if (bd->cur_mouse_action)
{
if ((!bd->cur_mouse_action->func.end_mouse) &&
(!bd->cur_mouse_action->func.end))
bd->cur_mouse_action = NULL;
else
e_object_unref(E_OBJECT(bd->cur_mouse_action));
}
bd->cur_mouse_action = e_action_find("window_resize");
if (bd->cur_mouse_action)
e_object_ref(E_OBJECT(bd->cur_mouse_action));
}
EAPI void
e_border_signal_resize_end(E_Border *bd,
const char *dir __UNUSED__,
const char *sig __UNUSED__,
const char *src __UNUSED__)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
if (bd->resize_mode == E_POINTER_RESIZE_NONE) return;
_e_border_resize_handle(bd);
_e_border_resize_end(bd);
bd->changes.reset_gravity = 1;
BD_CHANGED(bd);
}
EAPI void
e_border_resize_limit(E_Border *bd,
int *w,
int *h)
{
double a;
Eina_Bool inc_h;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
inc_h = (*h - bd->h > 0);
*w -= e_border_inset_width_get(bd);
*h -= e_border_inset_height_get(bd);
if (*h < 1) *h = 1;
if (*w < 1) *w = 1;
if ((bd->client.icccm.base_w >= 0) &&
(bd->client.icccm.base_h >= 0))
{
int tw, th;
tw = *w - bd->client.icccm.base_w;
th = *h - bd->client.icccm.base_h;
if (tw < 1) tw = 1;
if (th < 1) th = 1;
a = (double)(tw) / (double)(th);
if ((bd->client.icccm.min_aspect != 0.0) &&
(a < bd->client.icccm.min_aspect))
{
if (inc_h)
tw = th * bd->client.icccm.min_aspect;
else
th = tw / bd->client.icccm.max_aspect;
*w = tw + bd->client.icccm.base_w;
*h = th + bd->client.icccm.base_h;
}
else if ((bd->client.icccm.max_aspect != 0.0) &&
(a > bd->client.icccm.max_aspect))
{
tw = th * bd->client.icccm.max_aspect;
*w = tw + bd->client.icccm.base_w;
}
}
else
{
a = (double)*w / (double)*h;
if ((bd->client.icccm.min_aspect != 0.0) &&
(a < bd->client.icccm.min_aspect))
{
if (inc_h)
*w = *h * bd->client.icccm.min_aspect;
else
*h = *w / bd->client.icccm.min_aspect;
}
else if ((bd->client.icccm.max_aspect != 0.0) &&
(a > bd->client.icccm.max_aspect))
*w = *h * bd->client.icccm.max_aspect;
}
if (bd->client.icccm.step_w > 0)
{
if (bd->client.icccm.base_w >= 0)
*w = bd->client.icccm.base_w +
(((*w - bd->client.icccm.base_w) / bd->client.icccm.step_w) *
bd->client.icccm.step_w);
else
*w = bd->client.icccm.min_w +
(((*w - bd->client.icccm.min_w) / bd->client.icccm.step_w) *
bd->client.icccm.step_w);
}
if (bd->client.icccm.step_h > 0)
{
if (bd->client.icccm.base_h >= 0)
*h = bd->client.icccm.base_h +
(((*h - bd->client.icccm.base_h) / bd->client.icccm.step_h) *
bd->client.icccm.step_h);
else
*h = bd->client.icccm.min_h +
(((*h - bd->client.icccm.min_h) / bd->client.icccm.step_h) *
bd->client.icccm.step_h);
}
if (*h < 1) *h = 1;
if (*w < 1) *w = 1;
if (*w > bd->client.icccm.max_w) *w = bd->client.icccm.max_w;
else if (*w < bd->client.icccm.min_w)
*w = bd->client.icccm.min_w;
if (*h > bd->client.icccm.max_h) *h = bd->client.icccm.max_h;
else if (*h < bd->client.icccm.min_h)
*h = bd->client.icccm.min_h;
*w += e_border_inset_width_get(bd);
*h += e_border_inset_height_get(bd);
}
EAPI void
e_border_input_object_set(E_Border *bd, Evas_Object *input_obj)
{
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
bd->input_object = input_obj;
if (!bd->input_object) return;
evas_object_event_callback_add(bd->input_object, EVAS_CALLBACK_MOUSE_IN,
_e_border_cb_mouse_in, bd);
evas_object_event_callback_add(bd->input_object, EVAS_CALLBACK_MOUSE_MOVE,
_e_border_cb_mouse_move, bd);
evas_object_event_callback_add(bd->input_object, EVAS_CALLBACK_MOUSE_OUT,
_e_border_cb_mouse_out, bd);
evas_object_event_callback_add(bd->input_object, EVAS_CALLBACK_MOUSE_DOWN,
_e_border_cb_mouse_down, bd);
evas_object_event_callback_add(bd->input_object, EVAS_CALLBACK_MOUSE_UP,
_e_border_cb_mouse_up, bd);
evas_object_event_callback_add(bd->input_object, EVAS_CALLBACK_MOUSE_WHEEL,
_e_border_cb_mouse_wheel, bd);
bd->callbacks_set = EINA_TRUE;
}
/* local subsystem functions */
static void
_e_border_free(E_Border *bd)
{
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
if (bd->client.e.state.profile.use)
{
if (bd->client.e.state.profile.available_list)
{
int i;
for (i = 0; i < bd->client.e.state.profile.num; i++)
{
if (bd->client.e.state.profile.available_list[i])
{
eina_stringshare_del(bd->client.e.state.profile.available_list[i]);
bd->client.e.state.profile.available_list[i] = NULL;
}
}
E_FREE(bd->client.e.state.profile.available_list);
bd->client.e.state.profile.available_list = NULL;
}
bd->client.e.state.profile.num = 0;
if (bd->client.e.state.profile.name)
{
eina_stringshare_del(bd->client.e.state.profile.name);
bd->client.e.state.profile.name = NULL;
}
bd->client.e.state.profile.wait_for_done = 0;
bd->client.e.state.profile.use = 0;
}
#endif
if (bd->client.e.state.video_parent && bd->client.e.state.video_parent_border)
{
bd->client.e.state.video_parent_border->client.e.state.video_child =
eina_list_remove
(bd->client.e.state.video_parent_border->client.e.state.video_child,
bd);
}
if (bd->client.e.state.video_child)
{
E_Border *tmp;
EINA_LIST_FREE(bd->client.e.state.video_child, tmp)
{
tmp->client.e.state.video_parent_border = NULL;
}
}
if (bd->internal_ecore_evas)
{
e_canvas_del(bd->internal_ecore_evas);
ecore_evas_free(bd->internal_ecore_evas);
bd->internal_ecore_evas = NULL;
}
if (bd->desktop)
{
efreet_desktop_free(bd->desktop);
bd->desktop = NULL;
}
if (bd->post_job)
{
ecore_idle_enterer_del(bd->post_job);
bd->post_job = NULL;
}
if ((bdresize == bd) || (bd->resize_mode != E_POINTER_RESIZE_NONE))
_e_border_resize_end(bd);
if (bdmove == bd)
_e_border_move_end(bd);
/* TODO: Other states to end before dying? */
if (bd->cur_mouse_action)
{
e_object_unref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action = NULL;
}
/*
if (bd->dangling_ref_check)
{
ecore_timer_del(bd->dangling_ref_check);
bd->dangling_ref_check = NULL;
}
*/
if (bd->kill_timer)
{
ecore_timer_del(bd->kill_timer);
bd->kill_timer = NULL;
}
if (bd->ping_poller)
{
ecore_poller_del(bd->ping_poller);
bd->ping_poller = NULL;
}
E_FREE_LIST(bd->pending_move_resize, free);
if (bd->shade.anim) ecore_animator_del(bd->shade.anim);
if (bd->border_menu) e_menu_deactivate(bd->border_menu);
if (bd->border_locks_dialog)
{
e_object_del(E_OBJECT(bd->border_locks_dialog));
bd->border_locks_dialog = NULL;
}
if (bd->border_remember_dialog)
{
e_object_del(E_OBJECT(bd->border_remember_dialog));
bd->border_remember_dialog = NULL;
}
if (bd->border_border_dialog)
{
e_object_del(E_OBJECT(bd->border_border_dialog));
bd->border_border_dialog = NULL;
}
if (bd->border_prop_dialog)
{
e_object_del(E_OBJECT(bd->border_prop_dialog));
bd->border_prop_dialog = NULL;
}
e_int_border_menu_del(bd);
if (focusing == bd)
focusing = NULL;
focus_next = eina_list_remove(focus_next, bd);
if ((focused == bd) ||
(e_grabinput_last_focus_win_get() == bd->client.win))
{
if ((!focus_next) && (!focusing))
{
e_grabinput_focus(bd->zone->container->bg_win,
E_FOCUS_METHOD_PASSIVE);
e_hints_active_window_set(bd->zone->container->manager, NULL);
}
focused = NULL;
}
if (bd->remember)
{
E_Remember *rem;
rem = bd->remember;
bd->remember = NULL;
e_remember_unuse(rem);
}
if (!bd->already_unparented)
{
ecore_x_window_reparent(bd->client.win, bd->zone->container->manager->root,
bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
ecore_x_window_save_set_del(bd->client.win);
bd->already_unparented = 1;
}
if (bd->group) eina_list_free(bd->group);
bd->group = NULL;
if (bd->transients) eina_list_free(bd->transients);
bd->transients = NULL;
if (bd->stick_desks) eina_list_free(bd->stick_desks);
bd->stick_desks = NULL;
if (bd->client.netwm.icons)
{
int i;
for (i = 0; i < bd->client.netwm.num_icons; i++)
free(bd->client.netwm.icons[i].data);
free(bd->client.netwm.icons);
bd->client.netwm.icons = NULL;
}
free(bd->client.netwm.extra_types);
bd->client.netwm.extra_types = NULL;
if (bd->client.border.name)
eina_stringshare_del(bd->client.border.name);
bd->client.border.name = NULL;
if (bd->bordername)
eina_stringshare_del(bd->bordername);
bd->bordername = NULL;
if (bd->client.icccm.name)
eina_stringshare_del(bd->client.icccm.name);
bd->client.icccm.name = NULL;
if (bd->client.icccm.class)
{
if (bd->client.hacks.mapping_change)
e_bindings_mapping_change_enable(EINA_TRUE);
eina_stringshare_del(bd->client.icccm.class);
bd->client.icccm.class = NULL;
}
if (bd->client.icccm.title)
eina_stringshare_del(bd->client.icccm.title);
bd->client.icccm.title = NULL;
if (bd->client.icccm.icon_name)
eina_stringshare_del(bd->client.icccm.icon_name);
bd->client.icccm.icon_name = NULL;
if (bd->client.icccm.machine)
eina_stringshare_del(bd->client.icccm.machine);
bd->client.icccm.machine = NULL;
if (bd->client.icccm.window_role)
eina_stringshare_del(bd->client.icccm.window_role);
bd->client.icccm.window_role = NULL;
if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
{
int i;
for (i = 0; i < bd->client.icccm.command.argc; i++)
free(bd->client.icccm.command.argv[i]);
free(bd->client.icccm.command.argv);
bd->client.icccm.command.argv = NULL;
}
if (bd->client.netwm.name)
eina_stringshare_del(bd->client.netwm.name);
bd->client.netwm.name = NULL;
if (bd->client.netwm.icon_name)
eina_stringshare_del(bd->client.netwm.icon_name);
bd->client.netwm.icon_name = NULL;
if (bd->shape) e_object_del(E_OBJECT(bd->shape));
bd->shape = NULL;
if (bd->internal_icon) eina_stringshare_del(bd->internal_icon);
bd->internal_icon = NULL;
if (bd->internal_icon_key) eina_stringshare_del(bd->internal_icon_key);
bd->internal_icon_key = NULL;
if (bd->icon_object) evas_object_del(bd->icon_object);
bd->icon_object = NULL;
evas_object_del(bd->bg_object);
bd->bg_object = NULL;
e_focus_setdown(bd);
e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, bd->win);
eina_hash_del(borders_hash, e_util_winid_str_get(bd->client.win), bd);
eina_hash_del(borders_hash, e_util_winid_str_get(bd->win), bd);
ecore_x_window_free(bd->win);
bd->win = 0;
borders = eina_list_remove(borders, bd);
focus_stack = eina_list_remove(focus_stack, bd);
raise_stack = eina_list_remove(raise_stack, bd);
e_container_border_remove(bd);
free(bd);
}
/*
static int
_e_border_del_dangling_ref_check(void *data)
{
E_Border *bd;
bd = data;
printf("---\n");
printf("EEK EEK border still around 1 second after being deleted!\n");
printf("%p, %i, \"%s\" [\"%s\" \"%s\"]\n",
bd, e_object_ref_get(E_OBJECT(bd)), bd->client.icccm.title,
bd->client.icccm.name, bd->client.icccm.class);
// e_object_breadcrumb_debug(E_OBJECT(bd));
printf("---\n");
return 1;
}
*/
static void
_e_border_shadow(E_Border *bd)
{
if (!bd->bg_object) return;
if (e_util_border_shadow_state_get(bd))
edje_object_signal_emit(bd->bg_object, "e,state,shadow,on", "e");
else
edje_object_signal_emit(bd->bg_object, "e,state,shadow,off", "e");
}
static void
_e_border_del(E_Border *bd)
{
E_Event_Border_Remove *ev;
E_Border *child;
if (bd == focused)
{
focused = NULL;
}
if (bd == focusing)
focusing = NULL;
focus_next = eina_list_remove(focus_next, bd);
bd->changed = 0;
if (bd->exe_inst)
{
if (bd->exe_inst->phony && (eina_list_count(bd->exe_inst->borders) == 1))
e_exec_phony_del(bd->exe_inst);
else
bd->exe_inst->borders = eina_list_remove(bd->exe_inst->borders, bd);
bd->exe_inst = NULL;
}
if (bd->fullscreen) bd->desk->fullscreen_borders--;
if (bd->cur_mouse_action)
{
if (bd->cur_mouse_action->func.end)
bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
}
if (action_border == bd) _e_border_action_finish();
e_pointer_type_pop(e_comp_get(bd)->pointer, bd, NULL);
if (warp_timer_border == bd)
{
if (warp_timer) ecore_timer_del(warp_timer);
warp_timer = NULL;
warp_timer_border = NULL;
e_border_focus_lock_set(EINA_FALSE);
}
if ((drag_border) && (drag_border->data == bd))
{
e_object_del(E_OBJECT(drag_border));
drag_border = NULL;
}
if (bd->border_menu) e_menu_deactivate(bd->border_menu);
if (bd->border_locks_dialog)
{
e_object_del(E_OBJECT(bd->border_locks_dialog));
bd->border_locks_dialog = NULL;
}
if (bd->border_remember_dialog)
{
e_object_del(E_OBJECT(bd->border_remember_dialog));
bd->border_remember_dialog = NULL;
}
if (bd->border_border_dialog)
{
e_object_del(E_OBJECT(bd->border_border_dialog));
bd->border_border_dialog = NULL;
}
if (bd->border_prop_dialog)
{
e_object_del(E_OBJECT(bd->border_prop_dialog));
bd->border_prop_dialog = NULL;
}
e_int_border_menu_del(bd);
if (bd->raise_timer)
{
ecore_timer_del(bd->raise_timer);
bd->raise_timer = NULL;
}
if ((!bd->already_unparented) && (!bd->destroyed))
{
ecore_x_window_reparent(bd->client.win,
bd->zone->container->manager->root,
bd->x + bd->client_inset.l,
bd->y + bd->client_inset.t);
ecore_x_window_save_set_del(bd->client.win);
// bd->client.win = 0;
}
bd->already_unparented = 1;
if ((!bd->new_client) && (!stopping))
{
ev = E_NEW(E_Event_Border_Remove, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_remove_event");
ecore_event_add(E_EVENT_BORDER_REMOVE, ev, _e_border_event_border_remove_free, NULL);
}
if (bd->parent)
{
bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
if (bd->parent->modal == bd)
{
if (bd->parent->client.lock_win)
{
eina_hash_del_by_key(borders_hash, e_util_winid_str_get(bd->parent->client.lock_win));
ecore_x_window_hide(bd->parent->client.lock_win);
ecore_x_window_free(bd->parent->client.lock_win);
bd->parent->client.lock_win = 0;
}
bd->parent->lock_close = 0;
bd->parent->modal = NULL;
}
bd->parent = NULL;
}
EINA_LIST_FREE(bd->transients, child)
{
child->parent = NULL;
}
if (bd->leader)
{
bd->leader->group = eina_list_remove(bd->leader->group, bd);
if (bd->leader->modal == bd)
bd->leader->modal = NULL;
bd->leader = NULL;
}
EINA_LIST_FREE(bd->group, child)
{
child->leader = NULL;
}
}
#ifdef PRINT_LOTS_OF_DEBUG
static void
_e_border_print(E_Border *bd,
const char *func)
{
if (!bd) return;
DBG("*Window Info*"
"\tPointer: %p\n"
"\tName: %s\n"
"\tTitle: %s\n"
"\tBorderless: %s\n",
bd, bd->client.icccm.name, bd->client.icccm.title,
bd->borderless ? "TRUE" : "FALSE");
}
#endif
static Eina_Bool
_e_border_cb_window_show_request(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Show_Request *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
if (bd->iconic)
{
if (!bd->lock_client_iconify)
e_border_uniconify(bd);
}
else
{
/* FIXME: make border "urgent" for a bit - it wants attention */
/* e_border_show(bd); */
if (!bd->lock_client_stacking)
e_border_raise(bd);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_destroy(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Destroy *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
bd->destroyed = 1;
e_object_del(E_OBJECT(bd));
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_hide(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd = NULL;
Ecore_X_Event_Window_Hide *e;
e = ev;
// printf("HIDE: %x, event %x send: %i\n", e->win, e->event_win, e->send_event);
// not interested in hide events from windows other than the window in question
if (e->win != e->event_win)
{
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
if (!e->send_event) return ECORE_CALLBACK_PASS_ON;
else
{
if (!((bd->zone) &&
(bd->zone->container->manager->root == e->event_win)))
return ECORE_CALLBACK_PASS_ON;
}
#else
return ECORE_CALLBACK_PASS_ON;
#endif
}
if (!bd) bd = e_border_find_by_client_window(e->win);
// printf(" bd = %p\n", bd);
if (!bd) return ECORE_CALLBACK_PASS_ON;
// printf(" bd->ignore_first_unmap = %i\n", bd->ignore_first_unmap);
if (bd->ignore_first_unmap > 0)
{
bd->ignore_first_unmap--;
return ECORE_CALLBACK_PASS_ON;
}
/* Don't delete hidden or iconified windows */
if ((bd->iconic) || (bd->await_hide_event > 0))
{
// printf(" Don't delete hidden or iconified windows\n");
// printf(" bd->iconic = %i, bd->visible = %i, bd->new_client = %i, bd->await_hide_event = %i\n",
// bd->iconic, bd->visible, bd->new_client, bd->await_hide_event);
if (bd->await_hide_event > 0)
{
bd->await_hide_event--;
}
else
{
// printf(" hide really\n");
/* Only hide the border if it is visible */
if (bd->visible) e_border_hide(bd, 1);
}
}
else
{
// printf(" hide2\n");
if (bd->delete_requested)
bd->destroyed = 1;
e_border_hide(bd, 0);
e_object_del(E_OBJECT(bd));
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_reparent(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev __UNUSED__)
{
#if 0
E_Border *bd;
Ecore_X_Event_Window_Reparent *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return 1;
if (e->parent == bd->win) return 1;
if (ecore_x_window_parent_get(e->win) == bd->win)
{
return 1;
}
e_border_hide(bd, 0);
e_object_del(E_OBJECT(bd));
#endif
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_configure_request(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Configure_Request *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd)
{
if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
if (!e_util_container_window_find(e->win))
ecore_x_window_configure(e->win, e->value_mask,
e->x, e->y, e->w, e->h, e->border,
e->abovewin, e->detail);
return ECORE_CALLBACK_PASS_ON;
}
if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
(e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
{
int x, y;
x = bd->x;
y = bd->y;
if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
x = e->x;
if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
y = e->y;
if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
(e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
{
int w, h;
h = bd->h;
w = bd->w;
if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
w = e->w + e_border_inset_width_get(bd);
if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
h = e->h + e_border_inset_height_get(bd);
if ((!bd->lock_client_location) && (!bd->lock_client_size))
{
if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
{
bd->saved.x = x - bd->zone->x;
bd->saved.y = y - bd->zone->y;
bd->saved.w = w;
bd->saved.h = h;
}
else
e_border_move_resize(bd, x, y, w, h);
}
else if (!bd->lock_client_location)
{
if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
{
bd->saved.x = x - bd->zone->x;
bd->saved.y = y - bd->zone->y;
}
else
e_border_move(bd, x, y);
}
else if (!bd->lock_client_size)
{
if ((bd->shaded) || (bd->shading))
{
int pw, ph;
pw = bd->client.w;
ph = bd->client.h;
if ((bd->shade.dir == E_DIRECTION_UP) ||
(bd->shade.dir == E_DIRECTION_DOWN))
{
e_border_resize(bd, w, bd->h);
bd->client.h = ph;
}
else
{
e_border_resize(bd, bd->w, h);
bd->client.w = pw;
}
}
else
{
if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
{
bd->saved.w = w;
bd->saved.h = h;
}
else
e_border_resize(bd, w, h);
}
}
}
else
{
if (!bd->lock_client_location)
{
if ((bd->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
{
bd->saved.x = x - bd->zone->x;
bd->saved.y = y - bd->zone->y;
}
else
{
if ((e_config->screen_limits != E_SCREEN_LIMITS_COMPLETELY) && bd->zone &&
(!E_INSIDE(x, y, 0, 0, bd->zone->w - 5, bd->zone->h - 5)) &&
(!E_INSIDE(x, y, 0 - bd->w + 5, 0 - bd->h + 5, bd->zone->w - 5, bd->zone->h - 5))
)
_e_border_move_lost_window_to_center(bd);
else
e_border_move(bd, x, y);
}
}
}
}
else if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
(e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
{
int w, h;
h = bd->h;
w = bd->w;
if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
w = e->w + e_border_inset_width_get(bd);
if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
h = e->h + e_border_inset_height_get(bd);
if (!bd->lock_client_size)
{
if ((bd->shaded) || (bd->shading))
{
int pw, ph;
pw = bd->client.w;
ph = bd->client.h;
if ((bd->shade.dir == E_DIRECTION_UP) ||
(bd->shade.dir == E_DIRECTION_DOWN))
{
e_border_resize(bd, w, bd->h);
bd->client.h = ph;
}
else
{
e_border_resize(bd, bd->w, h);
bd->client.w = pw;
}
}
else
{
if ((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_NONE)
{
int zx, zy, zw, zh;
int rx = bd->x;
int ry = bd->y;
zx = zy = zw = zh = 0;
/*
* This code does resize and move a window on a
* X configure request into an useful geometry.
* This is really useful for size jumping file dialogs.
*/
if (bd->zone)
{
e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
if (e_config->geometry_auto_resize_limit == 1)
{
if (w > zw)
w = zw;
if (h > zh)
h = zh;
}
}
e_border_resize(bd, w, h);
if (e_config->geometry_auto_move == 1)
{
/* z{x,y,w,h} are only set here; FIXME! */
if (bd->zone)
{
// move window horizontal if resize to not useful geometry
if (bd->x + bd->w > zx + zw)
rx = zx + zw - bd->w;
else if (bd->x < zx)
rx = zx;
// move window vertical if resize to not useful geometry
if (bd->y + bd->h > zy + zh)
ry = zy + zh - bd->h;
else if (bd->y < zy)
ry = zy;
}
e_border_move(bd, rx, ry);
}
}
}
}
}
if (!bd->lock_client_stacking)
{
if ((e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
(e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
{
E_Border *obd;
if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
{
obd = e_border_find_by_client_window(e->abovewin);
if (obd)
{
e_border_stack_above(bd, obd);
}
else
{
ecore_x_window_configure(bd->win,
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
e->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
/* FIXME: need to rebuiuld border list from current stacking */
}
}
else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
{
obd = e_border_find_by_client_window(e->abovewin);
if (obd)
{
e_border_stack_below(bd, obd);
}
else
{
ecore_x_window_configure(bd->win,
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
e->abovewin, ECORE_X_WINDOW_STACK_BELOW);
/* FIXME: need to rebuiuld border list from current stacking */
}
}
else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
{
/* FIXME: do */
}
else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
{
/* FIXME: do */
}
else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
{
/* FIXME: do */
}
}
else if (e->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
{
if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
{
e_border_raise(bd);
}
else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
{
e_border_lower(bd);
}
else if (e->detail == ECORE_X_WINDOW_STACK_TOP_IF)
{
/* FIXME: do */
}
else if (e->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
{
/* FIXME: do */
}
else if (e->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
{
/* FIXME: do */
}
}
}
/* FIXME: need to send synthetic stacking event too as well as move/resize */
_e_border_client_move_resize_send(bd);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_resize_request(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Resize_Request *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd)
{
if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
ecore_x_window_resize(e->win, e->w, e->h);
return ECORE_CALLBACK_PASS_ON;
}
{
int w, h;
w = e->w + e_border_inset_width_get(bd);
h = e->h + e_border_inset_height_get(bd);
if ((bd->shaded) || (bd->shading))
{
int pw, ph;
pw = bd->client.w;
ph = bd->client.h;
if ((bd->shade.dir == E_DIRECTION_UP) ||
(bd->shade.dir == E_DIRECTION_DOWN))
{
e_border_resize(bd, w, bd->h);
bd->client.h = ph;
}
else
{
e_border_resize(bd, bd->w, h);
bd->client.w = pw;
}
}
else
e_border_resize(bd, w, h);
}
_e_border_client_move_resize_send(bd);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_gravity(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev __UNUSED__)
{
// E_Border *bd;
// Ecore_X_Event_Window_Gravity *e;
// e = ev;
// bd = e_border_find_by_client_window(e->win);
// if (!bd) return 1;
return 1;
}
static Eina_Bool
_e_border_cb_window_stack_request(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Stack_Request *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd)
{
if (e_stolen_win_get(e->win)) return ECORE_CALLBACK_PASS_ON;
if (!e_util_container_window_find(e->win))
{
if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
ecore_x_window_raise(e->win);
else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
ecore_x_window_lower(e->win);
}
return ECORE_CALLBACK_PASS_ON;
}
if (e->detail == ECORE_X_WINDOW_STACK_ABOVE)
e_border_raise(bd);
else if (e->detail == ECORE_X_WINDOW_STACK_BELOW)
e_border_lower(bd);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_property(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Property *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
if (e->atom == ECORE_X_ATOM_WM_NAME)
{
if ((!bd->client.netwm.name) &&
(!bd->client.netwm.fetch.name))
{
bd->client.icccm.fetch.title = 1;
BD_CHANGED(bd);
}
}
else if (e->atom == ECORE_X_ATOM_NET_WM_NAME)
{
bd->client.netwm.fetch.name = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_CLASS)
{
bd->client.icccm.fetch.name_class = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_ICON_NAME)
{
if ((!bd->client.netwm.icon_name) &&
(!bd->client.netwm.fetch.icon_name))
{
bd->client.icccm.fetch.icon_name = 1;
BD_CHANGED(bd);
}
}
else if (e->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
{
bd->client.netwm.fetch.icon_name = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
{
bd->client.icccm.fetch.machine = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_PROTOCOLS)
{
bd->client.icccm.fetch.protocol = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_HINTS)
{
bd->client.icccm.fetch.hints = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
{
bd->client.icccm.fetch.size_pos_hints = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
{
/*
if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_UNKNOWN) &&
(!bd->client.netwm.fetch.type))
{
*/
bd->client.mwm.fetch.hints = 1;
BD_CHANGED(bd);
/*
}
*/
}
else if (e->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
{
bd->client.icccm.fetch.transient_for = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
{
bd->client.icccm.fetch.client_leader = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
{
bd->client.icccm.fetch.window_role = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_NET_WM_ICON)
{
bd->client.netwm.fetch.icon = 1;
BD_CHANGED(bd);
}
else if (e->atom == ATM__QTOPIA_SOFT_MENU)
{
bd->client.qtopia.fetch.soft_menu = 1;
BD_CHANGED(bd);
}
else if (e->atom == ATM__QTOPIA_SOFT_MENUS)
{
bd->client.qtopia.fetch.soft_menus = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
{
bd->client.vkbd.fetch.state = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
{
bd->client.vkbd.fetch.vkbd = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
{
bd->client.illume.conformant.fetch.conformant = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
{
bd->client.illume.quickpanel.fetch.state = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
{
bd->client.illume.quickpanel.fetch.quickpanel = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
{
bd->client.illume.quickpanel.fetch.priority.major = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
{
bd->client.illume.quickpanel.fetch.priority.minor = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
{
bd->client.illume.quickpanel.fetch.zone = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
{
bd->client.illume.drag.fetch.locked = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
{
bd->client.illume.drag.fetch.drag = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
{
bd->client.illume.win_state.fetch.state = 1;
BD_CHANGED(bd);
}
/*
else if (e->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
{
bd->client.netwm.fetch.user_time = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT)
{
bd->client.netwm.fetch.strut = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
{
bd->client.netwm.fetch.strut = 1;
BD_CHANGED(bd);
}
*/
else if (e->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
{
//printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
}
else if (e->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
{
bd->client.e.fetch.video_position = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
{
bd->client.e.fetch.video_parent = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_NET_WM_STATE)
{
bd->client.netwm.fetch.state = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
{
if (bd->client.netwm.opacity_changed)
bd->client.netwm.opacity_changed = 0;
else
{
bd->client.netwm.fetch.opacity = 1;
BD_CHANGED(bd);
}
}
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
else if (e->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
{
bd->client.e.fetch.profile = 1;
BD_CHANGED(bd);
}
else if (e->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_AVAILABLE_LIST)
{
bd->client.e.fetch.profile = 1;
BD_CHANGED(bd);
}
#endif
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_colormap(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Colormap *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_shape(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Shape *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (e->type == ECORE_X_SHAPE_INPUT)
{
if (bd)
{
bd->need_shape_merge = 1;
// YYY bd->shaped_input = 1;
bd->changes.shape_input = 1;
BD_CHANGED(bd);
}
return ECORE_CALLBACK_PASS_ON;
}
if (bd)
{
bd->changes.shape = 1;
BD_CHANGED(bd);
return ECORE_CALLBACK_PASS_ON;
}
bd = e_border_find_by_window(e->win);
if (bd)
{
bd->need_shape_export = 1;
BD_CHANGED(bd);
return ECORE_CALLBACK_PASS_ON;
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_focus_in(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Focus_In *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
/* block refocus attempts on iconic windows
* these result from iconifying a window during a grab */
if (bd->iconic) return ECORE_CALLBACK_RENEW;
#ifdef INOUTDEBUG_FOCUS
{
time_t t;
char *ct;
const char *modes[] = {
"MODE_NORMAL",
"MODE_WHILE_GRABBED",
"MODE_GRAB",
"MODE_UNGRAB"
};
const char *details[] = {
"DETAIL_ANCESTOR",
"DETAIL_VIRTUAL",
"DETAIL_INFERIOR",
"DETAIL_NON_LINEAR",
"DETAIL_NON_LINEAR_VIRTUAL",
"DETAIL_POINTER",
"DETAIL_POINTER_ROOT",
"DETAIL_DETAIL_NONE"
};
t = time(NULL);
ct = ctime(&t);
ct[strlen(ct) - 1] = 0;
DBG("FF ->IN %i 0x%x %s md=%s dt=%s\n",
e->time,
e->win,
ct,
modes[e->mode],
details[e->detail]);
DBG("%s cb focus in %d %d\n",
e_border_name_get(bd),
bd->client.icccm.accepts_focus,
bd->client.icccm.take_focus);
}
#endif
_e_border_pri_raise(bd);
if (e->mode == ECORE_X_EVENT_MODE_GRAB)
{
if (e->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
}
else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
{
/* this seems to break winlist...
if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
*/
return ECORE_CALLBACK_PASS_ON;
}
/* ignore focus in from !take_focus windows, we just gave it em */
/* if (!bd->client.icccm.take_focus)
* return ECORE_CALLBACK_PASS_ON; */
/* should be equal, maybe some clients dont reply with the proper timestamp ? */
if (e->time >= focus_time)
e_border_focus_set(bd, 1, 0);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_focus_out(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Focus_Out *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
#ifdef INOUTDEBUG_FOCUS
{
time_t t;
char *ct;
const char *modes[] = {
"MODE_NORMAL",
"MODE_WHILE_GRABBED",
"MODE_GRAB",
"MODE_UNGRAB"
};
const char *details[] = {
"DETAIL_ANCESTOR",
"DETAIL_VIRTUAL",
"DETAIL_INFERIOR",
"DETAIL_NON_LINEAR",
"DETAIL_NON_LINEAR_VIRTUAL",
"DETAIL_POINTER",
"DETAIL_POINTER_ROOT",
"DETAIL_DETAIL_NONE"
};
t = time(NULL);
ct = ctime(&t);
ct[strlen(ct) - 1] = 0;
DBG("FF <-OUT %i 0x%x %s md=%s dt=%s",
e->time,
e->win,
ct,
modes[e->mode],
details[e->detail]);
DBG("%s cb focus out %d %d",
e_border_name_get(bd),
bd->client.icccm.accepts_focus,
bd->client.icccm.take_focus);
}
#endif
_e_border_pri_norm(bd);
if (e->mode == ECORE_X_EVENT_MODE_NORMAL)
{
if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
return ECORE_CALLBACK_PASS_ON;
}
else if (e->mode == ECORE_X_EVENT_MODE_GRAB)
{
if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
return ECORE_CALLBACK_PASS_ON;
}
else if (e->mode == ECORE_X_EVENT_MODE_UNGRAB)
{
/* for firefox/thunderbird (xul) menu walking */
/* NB: why did i disable this before? */
if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_POINTER)
return ECORE_CALLBACK_PASS_ON;
}
else if (e->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
{
if (e->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
return ECORE_CALLBACK_PASS_ON;
else if (e->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
return ECORE_CALLBACK_PASS_ON;
}
e_border_focus_set(bd, 0, 0);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_client_message(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
{
E_Border *bd;
Ecore_X_Event_Client_Message *e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
if (e->message_type == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
{
bd->client.netwm.fetch.opacity = 1;
BD_CHANGED(bd);
}
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
else if (e->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE)
{
if (bd->client.e.state.profile.use)
{
char *profile;
profile = ecore_x_atom_name_get(e->data.l[1]);
ecore_x_e_window_profile_change_request_send(bd->client.win,
profile);
bd->client.e.state.profile.wait_for_done = 1;
free(profile);
}
}
else if (e->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_DONE)
{
if ((bd->client.e.state.profile.use) &&
(bd->client.e.state.profile.wait_for_done))
{
E_Container *con = bd->zone->container;
E_Desk *desk = NULL;
char *profile;
profile = ecore_x_atom_name_get(e->data.l[1]);
if (profile)
eina_stringshare_replace(&bd->client.e.state.profile.name, profile);
bd->client.e.state.profile.wait_for_done = 0;
desk = e_container_desk_window_profile_get(con, profile);
if ((desk) && (bd->desk != desk))
e_border_desk_set(bd, desk);
free(profile);
}
}
#endif
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_state_request(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_State_Request *e;
int i;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
for (i = 0; i < 2; i++)
e_hints_window_state_update(bd, e->state[i], e->action);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_window_move_resize_request(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Window_Move_Resize_Request *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (!bd) return ECORE_CALLBACK_PASS_ON;
if ((bd->shaded) || (bd->shading) ||
(bd->fullscreen) || (bd->moving) ||
(bd->resize_mode != E_POINTER_RESIZE_NONE))
return ECORE_CALLBACK_PASS_ON;
if ((e->button >= 1) && (e->button <= 3))
{
bd->mouse.last_down[e->button - 1].mx = e->x;
bd->mouse.last_down[e->button - 1].my = e->y;
bd->mouse.last_down[e->button - 1].x = bd->x;
bd->mouse.last_down[e->button - 1].y = bd->y;
bd->mouse.last_down[e->button - 1].w = bd->w;
bd->mouse.last_down[e->button - 1].h = bd->h;
}
else
{
bd->moveinfo.down.x = bd->x;
bd->moveinfo.down.y = bd->y;
bd->moveinfo.down.w = bd->w;
bd->moveinfo.down.h = bd->h;
}
bd->mouse.current.mx = e->x;
bd->mouse.current.my = e->y;
bd->moveinfo.down.button = e->button;
bd->moveinfo.down.mx = e->x;
bd->moveinfo.down.my = e->y;
grabbed = 1;
if (!bd->lock_user_stacking)
e_border_raise(bd);
if (e->direction == E_POINTER_MOVE)
{
bd->cur_mouse_action = e_action_find("window_move");
if (bd->cur_mouse_action)
{
if ((!bd->cur_mouse_action->func.end_mouse) &&
(!bd->cur_mouse_action->func.end))
bd->cur_mouse_action = NULL;
if (bd->cur_mouse_action)
{
e_object_ref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
}
}
return ECORE_CALLBACK_PASS_ON;
}
bd->cur_mouse_action = e_action_find("window_resize");
if (bd->cur_mouse_action)
{
if ((!bd->cur_mouse_action->func.end_mouse) &&
(!bd->cur_mouse_action->func.end))
bd->cur_mouse_action = NULL;
}
if (!bd->cur_mouse_action) return ECORE_CALLBACK_RENEW;
e_object_ref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
switch (e->direction)
{
case E_POINTER_RESIZE_TL:
bd->resize_mode = E_POINTER_RESIZE_TL;
GRAV_SET(bd, ECORE_X_GRAVITY_SE);
break;
case E_POINTER_RESIZE_T:
bd->resize_mode = E_POINTER_RESIZE_T;
GRAV_SET(bd, ECORE_X_GRAVITY_S);
break;
case E_POINTER_RESIZE_TR:
bd->resize_mode = E_POINTER_RESIZE_TR;
GRAV_SET(bd, ECORE_X_GRAVITY_SW);
break;
case E_POINTER_RESIZE_R:
bd->resize_mode = E_POINTER_RESIZE_R;
GRAV_SET(bd, ECORE_X_GRAVITY_W);
break;
case E_POINTER_RESIZE_BR:
bd->resize_mode = E_POINTER_RESIZE_BR;
GRAV_SET(bd, ECORE_X_GRAVITY_NW);
break;
case E_POINTER_RESIZE_B:
bd->resize_mode = E_POINTER_RESIZE_B;
GRAV_SET(bd, ECORE_X_GRAVITY_N);
break;
case E_POINTER_RESIZE_BL:
bd->resize_mode = E_POINTER_RESIZE_BL;
GRAV_SET(bd, ECORE_X_GRAVITY_NE);
break;
case E_POINTER_RESIZE_L:
bd->resize_mode = E_POINTER_RESIZE_L;
GRAV_SET(bd, ECORE_X_GRAVITY_E);
break;
default:
return ECORE_CALLBACK_PASS_ON;
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_desktop_change(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Desktop_Change *e;
e = ev;
bd = e_border_find_by_client_window(e->win);
if (bd)
{
if (e->desk == 0xffffffff)
e_border_stick(bd);
else if ((int)e->desk < (bd->zone->desk_x_count * bd->zone->desk_y_count))
{
E_Desk *desk;
desk = e_desk_at_pos_get(bd->zone, e->desk);
if (desk)
e_border_desk_set(bd, desk);
}
}
else
{
ecore_x_netwm_desktop_set(e->win, e->desk);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_sync_alarm(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Border *bd;
Ecore_X_Event_Sync_Alarm *e;
unsigned int serial;
e = ev;
bd = e_border_find_by_alarm(e->alarm);
if (!bd) return ECORE_CALLBACK_PASS_ON;
if (bd->client.netwm.sync.wait)
bd->client.netwm.sync.wait--;
if (ecore_x_sync_counter_query(bd->client.netwm.sync.counter, &serial))
{
E_Border_Pending_Move_Resize *pnd = NULL;
/* skip pending for which we didn't get a reply */
while (bd->pending_move_resize)
{
pnd = bd->pending_move_resize->data;
bd->pending_move_resize = eina_list_remove(bd->pending_move_resize, pnd);
if (serial == pnd->serial)
break;
E_FREE(pnd);
}
if (pnd)
{
bd->x = pnd->x;
bd->y = pnd->y;
bd->w = pnd->w;
bd->h = pnd->h;
bd->client.w = bd->w - (e_border_inset_width_get(bd));
bd->client.h = bd->h - (e_border_inset_height_get(bd));
E_FREE(pnd);
}
}
bd->changes.size = 1;
bd->changes.pos = 1;
_e_border_eval(bd);
ecore_x_pointer_xy_get(e_manager_current_get()->root,
&bd->mouse.current.mx,
&bd->mouse.current.my);
bd->client.netwm.sync.send_time = ecore_loop_time_get();
_e_border_resize_handle(bd);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_efreet_cache_update(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev __UNUSED__)
{
Eina_List *l;
E_Border *bd;
/* mark all borders for desktop/icon updates */
EINA_LIST_FOREACH(borders, l, bd)
{
if (e_object_is_del(E_OBJECT(bd))) continue;
if (bd->desktop)
{
efreet_desktop_free(bd->desktop);
bd->desktop = NULL;
}
bd->changes.icon = 1;
BD_CHANGED(bd);
}
/*
e_init_status_set(_("Desktop files scan done"));
e_init_done();
*/
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_config_icon_theme(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev __UNUSED__)
{
Eina_List *l;
E_Border *bd;
/* mark all borders for desktop/icon updates */
EINA_LIST_FOREACH(borders, l, bd)
{
bd->changes.icon = 1;
BD_CHANGED(bd);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_config_mode(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev __UNUSED__)
{
Eina_List *l;
E_Border *bd;
/* move fullscreen borders above everything */
if (e_config->mode.presentation)
{
EINA_LIST_FOREACH(borders, l, bd)
{
if ((bd->fullscreen) || (bd->need_fullscreen))
{
bd->fullscreen = 0;
e_border_layer_set(bd, E_LAYER_TOP);
bd->fullscreen = 1;
}
}
}
else if (!e_config->allow_above_fullscreen)
{
EINA_LIST_FOREACH(borders, l, bd)
{
if ((bd->fullscreen) || (bd->need_fullscreen))
{
bd->fullscreen = 0;
e_border_layer_set(bd, E_LAYER_FULLSCREEN);
bd->fullscreen = 1;
}
}
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_border_cb_pointer_warp(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev)
{
E_Event_Pointer_Warp *e;
e = ev;
if (!bdmove) return ECORE_CALLBACK_PASS_ON;
e_border_move(bdmove, bdmove->x + (e->curr.x - e->prev.x), bdmove->y + (e->curr.y - e->prev.y));
return ECORE_CALLBACK_PASS_ON;
}
static void
_e_border_cb_signal_bind(void *data,
Evas_Object *obj __UNUSED__,
const char *emission,
const char *source)
{
E_Border *bd;
bd = data;
if (e_dnd_active()) return;
e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd),
emission, source);
}
static void
_e_border_cb_mouse_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_In *ev = event_info;
E_Border *bd = data;
if (grabbed) return;
if (focus_locked && (bd != warp_timer_border)) return;
if (e_object_is_del(E_OBJECT(bd))) return;
if (bd->desk && bd->desk->animate_count) return;
bd->mouse.current.mx = ev->output.x;
bd->mouse.current.my = ev->output.y;
if (!bd->iconic)
e_focus_event_mouse_in(bd);
}
static Eina_Bool
_e_border_cb_mouse_x_in(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Mouse_In *ev)
{
E_Border *bd;
if (grabbed) return ECORE_CALLBACK_RENEW;
bd = e_border_find_by_window(ev->event_win);
if (!bd) return ECORE_CALLBACK_RENEW;
if (bd->input_object) return ECORE_CALLBACK_RENEW;
if (focus_locked && (bd != warp_timer_border)) return ECORE_CALLBACK_RENEW;
if (e_object_is_del(E_OBJECT(bd))) return ECORE_CALLBACK_RENEW;
if (bd->desk && bd->desk->animate_count) return ECORE_CALLBACK_RENEW;
bd->mouse.current.mx = ev->root.x;
bd->mouse.current.my = ev->root.y;
if (!bd->iconic)
e_focus_event_mouse_in(bd);
return ECORE_CALLBACK_RENEW;
}
static void
_e_border_cb_mouse_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Out *ev = event_info;
E_Border *bd = data;
if (grabbed) return;
if (bd->fullscreen) return;
if ((bd != focused) && (bd == focusing)) return;
if (e_object_is_del(E_OBJECT(bd))) return;
if (bd->desk && bd->desk->animate_count) return;
if (!bd->input_object)
if (E_INSIDE(ev->output.x, ev->output.y, bd->x, bd->y, bd->w, bd->h)) return;
bd->mouse.current.mx = ev->output.x;
bd->mouse.current.my = ev->output.y;
if (!bd->iconic)
e_focus_event_mouse_out(bd);
}
static Eina_Bool
_e_border_cb_mouse_x_out(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Mouse_Out *ev)
{
E_Border *bd;
if (grabbed) return ECORE_CALLBACK_RENEW;
bd = e_border_find_by_window(ev->event_win);
if (!bd) return ECORE_CALLBACK_RENEW;
if (bd->input_object) return ECORE_CALLBACK_RENEW;
if (bd->fullscreen) return ECORE_CALLBACK_RENEW;
if ((bd != focused) && (bd == focusing)) return ECORE_CALLBACK_RENEW;
if (e_object_is_del(E_OBJECT(bd))) return ECORE_CALLBACK_RENEW;
if (bd->desk && bd->desk->animate_count) return ECORE_CALLBACK_RENEW;
if (E_INSIDE(ev->root.x, ev->root.y, bd->x, bd->y, bd->w, bd->h)) return ECORE_CALLBACK_RENEW;
if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
(ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
return ECORE_CALLBACK_PASS_ON;
if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
return ECORE_CALLBACK_PASS_ON;
if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
(ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
return ECORE_CALLBACK_PASS_ON;
bd->mouse.current.mx = ev->root.x;
bd->mouse.current.my = ev->root.y;
if (!bd->iconic)
e_focus_event_mouse_out(bd);
return ECORE_CALLBACK_RENEW;
}
static void
_e_border_cb_mouse_wheel_helper(E_Border *bd, Evas_Point *output, E_Binding_Event_Wheel *ev)
{
bd->mouse.current.mx = output->x;
bd->mouse.current.my = output->y;
if (!bd->cur_mouse_action)
{
e_bindings_wheel_event_handle(E_BINDING_CONTEXT_WINDOW,
E_OBJECT(bd), ev);
}
}
static Eina_Bool
_e_border_cb_mouse_x_wheel(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Wheel *ev)
{
E_Border *bd;
E_Binding_Event_Wheel ev2;
if (action_input_win)
bd = action_border;
else
{
bd = e_border_find_by_client_window(ev->window);
if (!bd) bd = e_border_find_by_window(ev->window);
if (!bd) return ECORE_CALLBACK_RENEW;
/* event_window here should be bd->win if it isn't the same as window, not sure if this can NOT happen */
if ((ev->window != ev->event_window) && (bd->win != ev->event_window) && (bd->client.lock_win != ev->event_window))
return ECORE_CALLBACK_RENEW;
}
e_bindings_ecore_event_mouse_wheel_convert(ev, &ev2);
_e_border_cb_mouse_wheel_helper(bd, (Evas_Point*)&ev->root, &ev2);
return ECORE_CALLBACK_RENEW;
}
static void
_e_border_cb_mouse_wheel(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Wheel *ev = event_info;
E_Border *bd = data;
E_Binding_Event_Wheel ev2;
if (action_border) return; // already existing border doing something
e_bindings_evas_event_mouse_wheel_convert(ev, &ev2);
_e_border_cb_mouse_wheel_helper(bd, &ev->output, &ev2);
}
static void
_e_border_cb_mouse_down_helper(E_Border *bd, int button, Evas_Point *output, E_Binding_Event_Mouse_Button *ev)
{
if ((button >= 1) && (button <= 3))
{
bd->mouse.last_down[button - 1].mx = output->x;
bd->mouse.last_down[button - 1].my = output->y;
bd->mouse.last_down[button - 1].x = bd->x;
bd->mouse.last_down[button - 1].y = bd->y;
bd->mouse.last_down[button - 1].w = bd->w;
bd->mouse.last_down[button - 1].h = bd->h;
}
else
{
bd->moveinfo.down.x = bd->x;
bd->moveinfo.down.y = bd->y;
bd->moveinfo.down.w = bd->w;
bd->moveinfo.down.h = bd->h;
}
bd->mouse.current.mx = output->x;
bd->mouse.current.my = output->y;
if (!bd->cur_mouse_action)
{
bd->cur_mouse_action =
e_bindings_mouse_down_event_handle(E_BINDING_CONTEXT_WINDOW,
E_OBJECT(bd), ev);
if (bd->cur_mouse_action)
{
if ((!bd->cur_mouse_action->func.end_mouse) &&
(!bd->cur_mouse_action->func.end))
bd->cur_mouse_action = NULL;
if (bd->cur_mouse_action)
e_object_ref(E_OBJECT(bd->cur_mouse_action));
}
}
e_focus_event_mouse_down(bd);
if ((button >= 1) && (button <= 3))
{
bd->mouse.last_down[button - 1].mx = output->x;
bd->mouse.last_down[button - 1].my = output->y;
bd->mouse.last_down[button - 1].x = bd->x;
bd->mouse.last_down[button - 1].y = bd->y;
bd->mouse.last_down[button - 1].w = bd->w;
bd->mouse.last_down[button - 1].h = bd->h;
}
else
{
bd->moveinfo.down.x = bd->x;
bd->moveinfo.down.y = bd->y;
bd->moveinfo.down.w = bd->w;
bd->moveinfo.down.h = bd->h;
}
bd->mouse.current.mx = output->x;
bd->mouse.current.my = output->y;
/*
if (bd->moving)
{
}
else if (bd->resize_mode != E_POINTER_RESIZE_NONE)
{
}
else
*/
}
static Eina_Bool
_e_border_cb_mouse_x_down(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
{
E_Border *bd;
E_Binding_Event_Mouse_Button ev2;
if (action_input_win)
bd = action_border;
else
{
bd = e_border_find_by_client_window(ev->window);
if (!bd) bd = e_border_find_by_window(ev->window);
if (!bd) return ECORE_CALLBACK_RENEW;
/* event_window here should be bd->win if it isn't the same as window, not sure if this can NOT happen */
if ((ev->window != ev->event_window) && (bd->win != ev->event_window) && (bd->client.lock_win != ev->event_window))
return ECORE_CALLBACK_RENEW;
}
e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
_e_border_cb_mouse_down_helper(bd, ev->buttons, (Evas_Point*)&ev->root, &ev2);
return ECORE_CALLBACK_RENEW;
}
static void
_e_border_cb_mouse_down(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Down *ev = event_info;
E_Border *bd = data;
E_Binding_Event_Mouse_Button ev2;
if (action_border) return; // already existing border doing something
e_bindings_evas_event_mouse_button_convert(ev, &ev2);
_e_border_cb_mouse_down_helper(bd, ev->button, &ev->output, &ev2);
}
static void
_e_border_cb_mouse_up_helper(E_Border *bd, int button, Evas_Point *output, E_Binding_Event_Mouse_Button* ev)
{
if ((button >= 1) && (button <= 3))
{
bd->mouse.last_up[button - 1].mx = output->x;
bd->mouse.last_up[button - 1].my = output->y;
bd->mouse.last_up[button - 1].x = bd->x;
bd->mouse.last_up[button - 1].y = bd->y;
}
bd->mouse.current.mx = output->x;
bd->mouse.current.my = output->y;
/* also we dont pass the same params that went in - then again that */
/* should be ok as we are just ending the action if it has an end */
if (bd->cur_mouse_action)
{
if (bd->cur_mouse_action->func.end_mouse)
bd->cur_mouse_action->func.end_mouse(E_OBJECT(bd), "", ev);
else if (bd->cur_mouse_action->func.end)
bd->cur_mouse_action->func.end(E_OBJECT(bd), "");
e_object_unref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action = NULL;
}
else
{
if (!e_bindings_mouse_up_event_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(bd), ev))
e_focus_event_mouse_up(bd);
}
if ((button >= 1) && (button <= 3))
{
bd->mouse.last_up[button - 1].mx = output->x;
bd->mouse.last_up[button - 1].my = output->y;
bd->mouse.last_up[button - 1].x = bd->x;
bd->mouse.last_up[button - 1].y = bd->y;
}
bd->drag.start = 0;
}
static Eina_Bool
_e_border_cb_mouse_x_up(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
{
E_Border *bd;
E_Binding_Event_Mouse_Button ev2;
if (action_input_win)
bd = action_border;
else
{
bd = e_border_find_by_client_window(ev->window);
if (!bd) bd = e_border_find_by_window(ev->window);
if (!bd) return ECORE_CALLBACK_RENEW;
/* event_window here should be bd->win if it isn't the same as window, not sure if this can NOT happen */
if ((ev->window != ev->event_window) && (bd->win != ev->event_window) && (bd->client.lock_win != ev->event_window))
return ECORE_CALLBACK_RENEW;
}
e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
_e_border_cb_mouse_up_helper(bd, ev->buttons, (Evas_Point*)&ev->root, &ev2);
return ECORE_CALLBACK_RENEW;
}
static void
_e_border_cb_mouse_up(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Down *ev = event_info;
E_Border *bd = data;
E_Binding_Event_Mouse_Button ev2;
if (action_border) return; // already existing border doing something
e_bindings_evas_event_mouse_button_convert(ev, &ev2);
_e_border_cb_mouse_up_helper(bd, ev->button, &ev->output, &ev2);
}
static void
_e_border_stay_within_container(E_Border *bd, int x, int y, int *new_x, int *new_y)
{
int new_x_max, new_y_max;
int zw, zh;
Eina_Bool lw, lh;
if (!bd->zone)
{
if (new_x) *new_x = x;
if (new_y) *new_y = y;
return;
}
_e_border_zones_layout_calc(bd, NULL, NULL, &zw, &zh);
new_x_max = zw - bd->w;
new_y_max = zh - bd->h;
lw = bd->w > zw ? EINA_TRUE : EINA_FALSE;
lh = bd->h > zh ? EINA_TRUE : EINA_FALSE;
if (lw)
{
if (x <= new_x_max)
*new_x = new_x_max;
else if (x >= 0)
*new_x = 0;
}
else
{
if (x >= new_x_max)
*new_x = new_x_max;
else if (x <= 0)
*new_x = 0;
}
if (lh)
{
if (y <= new_y_max)
*new_y = new_y_max;
else if (y >= 0)
*new_y = 0;
}
else
{
if (y >= new_y_max)
*new_y = new_y_max;
else if (y <= 0)
*new_y = 0;
}
}
static void
_e_border_cb_mouse_move_helper(E_Border *bd, Evas_Point *output)
{
bd->mouse.current.mx = output->x;
bd->mouse.current.my = output->y;
if (bd->moving)
{
int x, y, new_x, new_y;
int new_w, new_h;
Eina_List *skiplist = NULL;
#if 0
// FIXME: remove? sync what for when only moving?
if ((ecore_loop_time_get() - bd->client.netwm.sync.time) > 0.5)
bd->client.netwm.sync.wait = 0;
if ((bd->client.netwm.sync.request) &&
(bd->client.netwm.sync.alarm) &&
(bd->client.netwm.sync.wait > 1)) return;
#endif
if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
{
x = bd->mouse.last_down[bd->moveinfo.down.button - 1].x +
(bd->mouse.current.mx - bd->moveinfo.down.mx);
y = bd->mouse.last_down[bd->moveinfo.down.button - 1].y +
(bd->mouse.current.my - bd->moveinfo.down.my);
}
else
{
x = bd->moveinfo.down.x +
(bd->mouse.current.mx - bd->moveinfo.down.mx);
y = bd->moveinfo.down.y +
(bd->mouse.current.my - bd->moveinfo.down.my);
}
new_x = x;
new_y = y;
skiplist = eina_list_append(skiplist, bd);
e_resist_container_border_position(bd->zone->container, skiplist,
bd->x, bd->y, bd->w, bd->h,
x, y, bd->w, bd->h,
&new_x, &new_y, &new_w, &new_h);
eina_list_free(skiplist);
if (e_config->screen_limits == E_SCREEN_LIMITS_WITHIN)
_e_border_stay_within_container(bd, x, y, &new_x, &new_y);
bd->shelf_fix.x = 0;
bd->shelf_fix.y = 0;
bd->shelf_fix.modified = 0;
e_border_move(bd, new_x, new_y);
e_zone_flip_coords_handle(bd->zone, output->x, output->y);
}
else if (bd->resize_mode != E_POINTER_RESIZE_NONE)
{
if ((bd->client.netwm.sync.request) &&
(bd->client.netwm.sync.alarm))
{
if ((ecore_loop_time_get() - bd->client.netwm.sync.send_time) > 0.5)
{
E_Border_Pending_Move_Resize *pnd;
if (bd->pending_move_resize)
{
bd->changes.pos = 1;
bd->changes.size = 1;
BD_CHANGED(bd);
_e_border_client_move_resize_send(bd);
}
EINA_LIST_FREE(bd->pending_move_resize, pnd)
E_FREE(pnd);
bd->client.netwm.sync.wait = 0;
}
/* sync.wait is incremented when resize_handle sends
* sync-request and decremented by sync-alarm cb. so
* we resize here either on initial resize, timeout or
* when no new resize-request was added by sync-alarm cb.
*/
if (!bd->client.netwm.sync.wait)
_e_border_resize_handle(bd);
}
else
_e_border_resize_handle(bd);
}
else if (bd->drag.start)
{
if ((bd->drag.x == -1) && (bd->drag.y == -1))
{
bd->drag.x = output->x;
bd->drag.y = output->y;
}
else
{
int dx, dy;
dx = bd->drag.x - output->x;
dy = bd->drag.y - output->y;
if (((dx * dx) + (dy * dy)) >
(e_config->drag_resist * e_config->drag_resist))
{
/* start drag! */
if (bd->icon_object)
{
Evas_Object *o = NULL;
Evas_Coord x, y, w, h;
const char *drag_types[] = { "enlightenment/border" };
e_object_ref(E_OBJECT(bd));
evas_object_geometry_get(bd->icon_object,
&x, &y, &w, &h);
drag_border = e_drag_new(bd->zone->container,
x, y,
drag_types, 1, bd, -1,
NULL,
_e_border_cb_drag_finished);
o = e_border_icon_add(bd, drag_border->evas);
if (!o)
{
/* FIXME: fallback icon for drag */
o = evas_object_rectangle_add(drag_border->evas);
evas_object_color_set(o, 255, 255, 255, 255);
}
e_drag_object_set(drag_border, o);
e_drag_resize(drag_border, w, h);
e_drag_start(drag_border, bd->drag.x, bd->drag.y);
}
bd->drag.start = 0;
}
}
}
}
static Eina_Bool
_e_border_cb_mouse_x_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
{
if (!action_border) return ECORE_CALLBACK_RENEW;
_e_border_cb_mouse_move_helper(action_border, (Evas_Point*)&ev->root);
return ECORE_CALLBACK_RENEW;
}
static void
_e_border_cb_mouse_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info)
{
Evas_Event_Mouse_Move *ev = event_info;
E_Border *bd = data;
if (action_border) return; // already existing border doing something
_e_border_cb_mouse_move_helper(bd, &ev->cur.output);
}
static Eina_Bool
_e_border_cb_grab_replay(void *data __UNUSED__,
int type,
void *event)
{
Ecore_Event_Mouse_Button *ev;
if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
ev = event;
if ((e_config->pass_click_on)
|| (e_config->always_click_to_raise) // this works even if not on click-to-focus
|| (e_config->always_click_to_focus) // this works even if not on click-to-focus
)
{
E_Border *bd;
bd = e_border_find_by_window(ev->event_window);
if (bd)
{
if (bd->cur_mouse_action)
return ECORE_CALLBACK_DONE;
if (ev->event_window == bd->win)
{
E_Binding_Event_Mouse_Button ev2;
e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
if (!e_bindings_mouse_button_find(E_BINDING_CONTEXT_WINDOW,
&ev2, NULL))
return ECORE_CALLBACK_PASS_ON;
}
}
}
return ECORE_CALLBACK_DONE;
}
static void
_e_border_cb_drag_finished(E_Drag *drag,
int dropped __UNUSED__)
{
E_Border *bd;
bd = drag->data;
e_object_unref(E_OBJECT(bd));
drag_border = NULL;
}
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
static Eina_Bool
_e_border_cb_desk_window_profile_change(void *data __UNUSED__,
int ev_type __UNUSED__,
void *ev __UNUSED__)
{
// E_Event_Desk_Window_Profile_Change *e = ev;
Eina_List *l = NULL;
E_Border *bd;
EINA_LIST_FOREACH(borders, l, bd)
{
if (!e_object_is_del(E_OBJECT(bd)))
{
bd->client.e.fetch.profile = 1;
BD_CHANGED(bd);
}
}
return ECORE_CALLBACK_PASS_ON;
}
#endif
static Eina_Bool
_e_border_post_move_resize_job(void *data)
{
E_Border *bd;
bd = (E_Border *)data;
if (bd->post_move)
{
E_Border *tmp;
Eina_List *l;
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
ecore_x_window_move(tmp->win,
bd->x +
bd->client_inset.l +
tmp->client.e.state.video_position.x,
bd->y +
bd->client_inset.t +
tmp->client.e.state.video_position.y);
}
if (bd->client.e.state.video)
{
E_Border *parent;
parent = bd->client.e.state.video_parent_border;
ecore_x_window_move(bd->win,
parent->x +
parent->client_inset.l +
bd->client.e.state.video_position.x,
parent->y +
parent->client_inset.t +
bd->client.e.state.video_position.y);
}
else if ((bd->post_move) && (bd->post_resize))
{
ecore_x_window_move_resize(bd->win,
bd->x + bd->client_inset.l,
bd->y + bd->client_inset.t,
bd->w - (e_border_inset_width_get(bd)),
bd->h - (e_border_inset_height_get(bd)));
}
else if (bd->post_move)
{
ecore_x_window_move(bd->win, bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
}
else if (bd->post_resize)
{
ecore_x_window_resize(bd->win,
bd->w - (e_border_inset_width_get(bd)),
bd->h - (e_border_inset_height_get(bd)));
}
if (bd->client.e.state.video)
{
fprintf(stderr, "%x: [%i, %i] [%i, %i]\n",
bd->win,
bd->client.e.state.video_parent_border->x +
bd->client.e.state.video_parent_border->client_inset.l +
bd->client.e.state.video_position.x,
bd->client.e.state.video_parent_border->y +
bd->client.e.state.video_parent_border->client_inset.t +
bd->client.e.state.video_position.y,
bd->w, bd->h);
}
if (bd->post_show)
{
if (bd->visible)
{
bd->post_job = NULL;
_e_border_show(bd);
}
}
bd->post_show = 0;
bd->post_move = 0;
bd->post_resize = 0;
bd->post_job = NULL;
return ECORE_CALLBACK_CANCEL;
}
static void
_e_border_container_layout_hook(E_Container *con)
{
_e_border_hook_call(E_BORDER_HOOK_CONTAINER_LAYOUT, con);
}
static void
_e_border_eval0(E_Border *bd)
{
int change_urgent = 0;
int rem_change = 0;
int title_change = 0;
Eina_Bool new_cw = !bd->cw;
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
Eina_Bool need_desk_set = EINA_FALSE;
#endif
if (e_object_is_del(E_OBJECT(bd)))
{
CRI("_e_border_eval(%p) with deleted border!\n", bd);
bd->changed = 0;
return;
}
_e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_FETCH, bd);
bd->changes.border = 0;
/* fetch any info queued to be fetched */
if (bd->changes.prop || bd->client.netwm.fetch.state)
{
e_hints_window_state_get(bd);
bd->client.netwm.fetch.state = 0;
rem_change = 1;
}
if (bd->client.icccm.fetch.client_leader)
{
/* TODO: What do to if the client leader isn't mapped yet? */
E_Border *bd_leader = NULL;
bd->client.icccm.client_leader = ecore_x_icccm_client_leader_get(bd->client.win);
if (bd->client.icccm.client_leader)
bd_leader = e_border_find_by_client_window(bd->client.icccm.client_leader);
if (bd->leader)
{
if (bd->leader != bd_leader)
{
bd->leader->group = eina_list_remove(bd->leader->group, bd);
if (bd->leader->modal == bd) bd->leader->modal = NULL;
bd->leader = NULL;
}
else
bd_leader = NULL;
}
/* If this border is the leader of the group, don't register itself */
if ((bd_leader) && (bd_leader != bd))
{
bd_leader->group = eina_list_append(bd_leader->group, bd);
bd->leader = bd_leader;
/* Only set the window modal to the leader it there is no parent */
if ((bd->client.netwm.state.modal) &&
((!bd->parent) || (bd->parent->modal != bd)))
{
bd->leader->modal = bd;
if (bd->leader->focused)
e_border_focus_set(bd, 1, 1);
else
{
Eina_List *l;
E_Border *child;
EINA_LIST_FOREACH(bd->leader->group, l, child)
{
if ((child != bd) && (child->focused))
e_border_focus_set(bd, 1, 1);
}
}
}
}
bd->client.icccm.fetch.client_leader = 0;
rem_change = 1;
}
if (bd->client.icccm.fetch.title)
{
char *title = ecore_x_icccm_title_get(bd->client.win);
eina_stringshare_replace(&bd->client.icccm.title, title);
free(title);
if (bd->bg_object)
edje_object_part_text_set(bd->bg_object, "e.text.title",
bd->client.icccm.title);
bd->client.icccm.fetch.title = 0;
rem_change = 1;
title_change = 1;
}
if (bd->client.netwm.fetch.name)
{
char *name;
ecore_x_netwm_name_get(bd->client.win, &name);
eina_stringshare_replace(&bd->client.netwm.name, name);
free(name);
bd->client.hacks.iconic_shading =
((bd->client.netwm.icon_name == bd->client.netwm.name) &&
(!e_util_strcmp(bd->client.netwm.name, "QEMU")));
if (bd->bg_object)
edje_object_part_text_set(bd->bg_object, "e.text.title",
bd->client.netwm.name);
bd->client.netwm.fetch.name = 0;
rem_change = 1;
title_change = 1;
}
if (title_change)
{
E_Event_Border_Title_Change *ev;
ev = E_NEW(E_Event_Border_Title_Change, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_TITLE_CHANGE, ev,
_e_border_event_border_title_change_free, NULL);
}
if (bd->client.icccm.fetch.name_class)
{
const char *pname, *pclass;
char *nname, *nclass;
ecore_x_icccm_name_class_get(bd->client.win, &nname, &nclass);
pname = bd->client.icccm.name;
pclass = bd->client.icccm.class;
bd->client.icccm.name = eina_stringshare_add(nname);
bd->client.icccm.class = eina_stringshare_add(nclass);
bd->client.hacks.mapping_change =
((!e_util_strcasecmp(bd->client.icccm.class, "vmplayer")) ||
(!e_util_strcasecmp(bd->client.icccm.class, "vmware")));
if (bd->client.hacks.mapping_change)
e_bindings_mapping_change_enable(EINA_FALSE);
free(nname);
free(nclass);
if (!((bd->client.icccm.name == pname) &&
(bd->client.icccm.class == pclass)))
{
bd->changes.icon = 1;
rem_change = 1;
}
eina_stringshare_del(pname);
eina_stringshare_del(pclass);
bd->client.icccm.fetch.name_class = 0;
}
if (bd->changes.prop || bd->client.icccm.fetch.state)
{
bd->client.icccm.state = ecore_x_icccm_state_get(bd->client.win);
bd->client.icccm.fetch.state = 0;
rem_change = 1;
}
if (bd->changes.prop || bd->client.e.fetch.state)
{
e_hints_window_e_state_get(bd);
bd->client.e.fetch.state = 0;
rem_change = 1;
}
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
if (bd->client.e.fetch.profile)
{
const char **list = NULL;
int n, i, res;
unsigned int use;
if (bd->client.e.state.profile.name)
{
eina_stringshare_del(bd->client.e.state.profile.name);
bd->client.e.state.profile.name = NULL;
}
if (bd->client.e.state.profile.available_list)
{
for (i = 0; i < bd->client.e.state.profile.num; i++)
{
if (bd->client.e.state.profile.available_list[i])
{
eina_stringshare_del(bd->client.e.state.profile.available_list[i]);
bd->client.e.state.profile.available_list[i] = NULL;
}
}
E_FREE(bd->client.e.state.profile.available_list);
bd->client.e.state.profile.available_list = NULL;
}
bd->client.e.state.profile.num = 0;
res = ecore_x_window_prop_card32_get(bd->client.win,
ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED,
&use,
1);
if ((res == 1) && (use == 1))
{
Ecore_X_Atom val;
res = ecore_x_window_prop_atom_get(bd->client.win,
ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE,
&val, 1);
if (res == 1)
{
char *name = ecore_x_atom_name_get(val);
if (name)
{
bd->client.e.state.profile.name = eina_stringshare_add(name);
free(name);
}
}
if (ecore_x_e_window_available_profiles_get(bd->client.win, &list, &n))
{
bd->client.e.state.profile.available_list = E_NEW(const char *, n);
for (i = 0; i < n; i++)
bd->client.e.state.profile.available_list[i] = eina_stringshare_add(list[i]);
bd->client.e.state.profile.num = n;
}
need_desk_set = EINA_TRUE;
bd->client.e.state.profile.use = 1;
free(list);
}
bd->client.e.fetch.profile = 0;
}
#endif
if (bd->changes.prop || bd->client.netwm.fetch.type)
{
e_hints_window_type_get(bd);
if ((!bd->lock_border) || (!bd->client.border.name))
bd->client.border.changed = 1;
if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DOCK)
{
if (!bd->client.netwm.state.skip_pager)
{
bd->client.netwm.state.skip_pager = 1;
bd->client.netwm.update.state = 1;
}
if (!bd->client.netwm.state.skip_taskbar)
{
bd->client.netwm.state.skip_taskbar = 1;
bd->client.netwm.update.state = 1;
}
}
bd->client.netwm.fetch.type = 0;
}
if (bd->client.icccm.fetch.machine)
{
char *machine = ecore_x_icccm_client_machine_get(bd->client.win);
if ((!machine) && (bd->client.icccm.client_leader))
machine = ecore_x_icccm_client_machine_get(bd->client.icccm.client_leader);
eina_stringshare_replace(&bd->client.icccm.machine, machine);
free(machine);
bd->client.icccm.fetch.machine = 0;
rem_change = 1;
}
if (bd->client.icccm.fetch.command)
{
if ((bd->client.icccm.command.argc > 0) && (bd->client.icccm.command.argv))
{
int i;
for (i = 0; i < bd->client.icccm.command.argc; i++)
free(bd->client.icccm.command.argv[i]);
free(bd->client.icccm.command.argv);
}
bd->client.icccm.command.argc = 0;
bd->client.icccm.command.argv = NULL;
ecore_x_icccm_command_get(bd->client.win,
&(bd->client.icccm.command.argc),
&(bd->client.icccm.command.argv));
if ((bd->client.icccm.client_leader) &&
(!bd->client.icccm.command.argv))
ecore_x_icccm_command_get(bd->client.icccm.client_leader,
&(bd->client.icccm.command.argc),
&(bd->client.icccm.command.argv));
bd->client.icccm.fetch.command = 0;
rem_change = 1;
}
if (bd->changes.prop || bd->client.icccm.fetch.hints)
{
Eina_Bool accepts_focus, is_urgent;
accepts_focus = EINA_TRUE;
is_urgent = EINA_FALSE;
bd->client.icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
if (ecore_x_icccm_hints_get(bd->client.win,
&accepts_focus,
&bd->client.icccm.initial_state,
&bd->client.icccm.icon_pixmap,
&bd->client.icccm.icon_mask,
&bd->client.icccm.icon_window,
&bd->client.icccm.window_group,
&is_urgent))
{
bd->client.icccm.accepts_focus = accepts_focus;
if ((bd->client.icccm.urgent != is_urgent) && ((!bd->focused) || (!is_urgent)))
change_urgent = 1;
bd->client.icccm.urgent = is_urgent;
/* If this is a new window, set the state as requested. */
if ((bd->new_client) &&
(bd->client.icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
{
e_border_iconify(bd);
e_border_hide(bd, 1);
}
}
bd->client.icccm.fetch.hints = 0;
rem_change = 1;
}
if (bd->changes.prop || bd->client.icccm.fetch.size_pos_hints)
{
Eina_Bool request_pos;
request_pos = EINA_FALSE;
if (ecore_x_icccm_size_pos_hints_get(bd->client.win,
&request_pos,
&bd->client.icccm.gravity,
&bd->client.icccm.min_w,
&bd->client.icccm.min_h,
&bd->client.icccm.max_w,
&bd->client.icccm.max_h,
&bd->client.icccm.base_w,
&bd->client.icccm.base_h,
&bd->client.icccm.step_w,
&bd->client.icccm.step_h,
&bd->client.icccm.min_aspect,
&bd->client.icccm.max_aspect))
{
bd->client.icccm.request_pos = request_pos;
}
else
{
}
if (bd->client.icccm.min_w > 32767) bd->client.icccm.min_w = 32767;
if (bd->client.icccm.min_h > 32767) bd->client.icccm.min_h = 32767;
if (bd->client.icccm.max_w > 32767) bd->client.icccm.max_w = 32767;
if (bd->client.icccm.max_h > 32767) bd->client.icccm.max_h = 32767;
if (bd->client.icccm.base_w > 32767) bd->client.icccm.base_w = 32767;
if (bd->client.icccm.base_h > 32767) bd->client.icccm.base_h = 32767;
// if (bd->client.icccm.step_w < 1) bd->client.icccm.step_w = 1;
// if (bd->client.icccm.step_h < 1) bd->client.icccm.step_h = 1;
// if doing a resize, fix it up
if (bd->resize_mode != E_POINTER_RESIZE_NONE)
{
int x, y, w, h, new_w, new_h;
x = bd->x;
y = bd->y;
w = bd->w;
h = bd->h;
new_w = w;
new_h = h;
e_border_resize_limit(bd, &new_w, &new_h);
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_L) ||
(bd->resize_mode == E_POINTER_RESIZE_BL))
x += (w - new_w);
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_T) ||
(bd->resize_mode == E_POINTER_RESIZE_TR))
y += (h - new_h);
e_border_move_resize(bd, x, y, new_w, new_h);
}
bd->client.icccm.fetch.size_pos_hints = 0;
rem_change = 1;
}
if (bd->client.icccm.fetch.protocol)
{
int i, num;
Ecore_X_WM_Protocol *proto;
proto = ecore_x_window_prop_protocol_list_get(bd->client.win, &num);
if (proto)
{
for (i = 0; i < num; i++)
{
if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
bd->client.icccm.delete_request = 1;
else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
bd->client.icccm.take_focus = 1;
else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
bd->client.netwm.ping = 1;
else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
{
bd->client.netwm.sync.request = 1;
if (!ecore_x_netwm_sync_counter_get(bd->client.win,
&bd->client.netwm.sync.counter))
bd->client.netwm.sync.request = 0;
}
}
free(proto);
}
if (bd->client.netwm.ping)
e_border_ping(bd);
else
{
if (bd->ping_poller) ecore_poller_del(bd->ping_poller);
bd->ping_poller = NULL;
}
bd->client.icccm.fetch.protocol = 0;
}
if (bd->client.icccm.fetch.transient_for)
{
/* TODO: What do to if the transient for isn't mapped yet? */
E_Border *bd_parent = NULL;
bd->client.icccm.transient_for = ecore_x_icccm_transient_for_get(bd->client.win);
if (bd->client.icccm.transient_for)
bd_parent = e_border_find_by_client_window(bd->client.icccm.transient_for);
/* If we already have a parent, remove it */
if (bd->parent)
{
if (bd_parent != bd->parent)
{
bd->parent->transients = eina_list_remove(bd->parent->transients, bd);
if (bd->parent->modal == bd) bd->parent->modal = NULL;
bd->parent = NULL;
}
else
bd_parent = NULL;
}
if ((bd_parent) && (bd_parent != bd) &&
(eina_list_data_find(bd->transients, bd_parent) != bd_parent))
{
bd_parent->transients = eina_list_append(bd_parent->transients, bd);
bd->parent = bd_parent;
}
if (bd->parent)
{
if (bd->parent->layer != bd->layer)
e_border_layer_set(bd, bd->parent->layer);
if (bd->client.netwm.state.modal)
{
bd->parent->modal = bd;
bd->parent->lock_close = 1;
if (!bd->parent->client.lock_win)
{
bd->parent->client.lock_win = ecore_x_window_input_new(bd->parent->win, 0, 0, bd->parent->client.w, bd->parent->client.h);
e_comp_ignore_win_add(bd->parent->client.lock_win);
eina_hash_add(borders_hash, e_util_winid_str_get(bd->parent->client.lock_win), bd->parent);
ecore_x_window_show(bd->parent->client.lock_win);
ecore_x_icccm_name_class_set(bd->parent->client.lock_win, "lock_win", "lock_win");
}
}
if (e_config->focus_setting == E_FOCUS_NEW_DIALOG ||
(bd->parent->focused && (e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))
bd->take_focus = 1;
}
bd->client.icccm.fetch.transient_for = 0;
rem_change = 1;
}
if (bd->client.icccm.fetch.window_role)
{
char *role = ecore_x_icccm_window_role_get(bd->client.win);
eina_stringshare_replace(&bd->client.icccm.window_role, role);
free(role);
bd->client.icccm.fetch.window_role = 0;
rem_change = 1;
}
if (bd->client.icccm.fetch.icon_name)
{
char *icon_name = ecore_x_icccm_icon_name_get(bd->client.win);
eina_stringshare_replace(&bd->client.icccm.icon_name, icon_name);
free(icon_name);
bd->client.hacks.iconic_shading =
((bd->client.netwm.icon_name == bd->client.netwm.name) &&
(!e_util_strcmp(bd->client.netwm.icon_name, "QEMU")));
bd->client.icccm.fetch.icon_name = 0;
rem_change = 1;
}
if (bd->client.netwm.fetch.icon_name)
{
char *icon_name;
ecore_x_netwm_icon_name_get(bd->client.win, &icon_name);
eina_stringshare_replace(&bd->client.netwm.icon_name, icon_name);
free(icon_name);
bd->client.netwm.fetch.icon_name = 0;
rem_change = 1;
}
if (bd->client.netwm.fetch.opacity)
{
unsigned int val;
if (ecore_x_window_prop_card32_get(bd->client.win, ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, &val, 1) > 0)
bd->client.netwm.opacity = (val >> 24);
}
if (bd->client.netwm.fetch.icon)
{
int i;
if (bd->client.netwm.icons)
{
for (i = 0; i < bd->client.netwm.num_icons; i++)
{
free(bd->client.netwm.icons[i].data);
bd->client.netwm.icons[i].data = NULL;
}
free(bd->client.netwm.icons);
}
bd->client.netwm.icons = NULL;
bd->client.netwm.num_icons = 0;
if (ecore_x_netwm_icons_get(bd->client.win,
&bd->client.netwm.icons,
&bd->client.netwm.num_icons))
{
// unless the rest of e17 uses border icons OTHER than icon #0
// then free the rest that we don't need anymore.
for (i = 1; i < bd->client.netwm.num_icons; i++)
{
free(bd->client.netwm.icons[i].data);
bd->client.netwm.icons[i].data = NULL;
}
bd->client.netwm.num_icons = 1;
bd->changes.icon = 1;
}
bd->client.netwm.fetch.icon = 0;
}
if (bd->client.netwm.fetch.user_time)
{
ecore_x_netwm_user_time_get(bd->client.win, &bd->client.netwm.user_time);
bd->client.netwm.fetch.user_time = 0;
}
if (bd->client.netwm.fetch.strut)
{
if (!ecore_x_netwm_strut_partial_get(bd->client.win,
&bd->client.netwm.strut.left,
&bd->client.netwm.strut.right,
&bd->client.netwm.strut.top,
&bd->client.netwm.strut.bottom,
&bd->client.netwm.strut.left_start_y,
&bd->client.netwm.strut.left_end_y,
&bd->client.netwm.strut.right_start_y,
&bd->client.netwm.strut.right_end_y,
&bd->client.netwm.strut.top_start_x,
&bd->client.netwm.strut.top_end_x,
&bd->client.netwm.strut.bottom_start_x,
&bd->client.netwm.strut.bottom_end_x))
{
ecore_x_netwm_strut_get(bd->client.win,
&bd->client.netwm.strut.left, &bd->client.netwm.strut.right,
&bd->client.netwm.strut.top, &bd->client.netwm.strut.bottom);
bd->client.netwm.strut.left_start_y = 0;
bd->client.netwm.strut.left_end_y = 0;
bd->client.netwm.strut.right_start_y = 0;
bd->client.netwm.strut.right_end_y = 0;
bd->client.netwm.strut.top_start_x = 0;
bd->client.netwm.strut.top_end_x = 0;
bd->client.netwm.strut.bottom_start_x = 0;
bd->client.netwm.strut.bottom_end_x = 0;
}
bd->client.netwm.fetch.strut = 0;
}
if (bd->client.qtopia.fetch.soft_menu)
{
e_hints_window_qtopia_soft_menu_get(bd);
bd->client.qtopia.fetch.soft_menu = 0;
rem_change = 1;
}
if (bd->client.qtopia.fetch.soft_menus)
{
e_hints_window_qtopia_soft_menus_get(bd);
bd->client.qtopia.fetch.soft_menus = 0;
rem_change = 1;
}
if (bd->client.vkbd.fetch.state)
{
e_hints_window_virtual_keyboard_state_get(bd);
bd->client.vkbd.fetch.state = 0;
rem_change = 1;
}
if (bd->client.vkbd.fetch.vkbd)
{
e_hints_window_virtual_keyboard_get(bd);
bd->client.vkbd.fetch.vkbd = 0;
rem_change = 1;
}
if (bd->client.illume.conformant.fetch.conformant)
{
bd->client.illume.conformant.conformant =
ecore_x_e_illume_conformant_get(bd->client.win);
bd->client.illume.conformant.fetch.conformant = 0;
}
if (bd->client.illume.quickpanel.fetch.state)
{
bd->client.illume.quickpanel.state =
ecore_x_e_illume_quickpanel_state_get(bd->client.win);
bd->client.illume.quickpanel.fetch.state = 0;
}
if (bd->client.illume.quickpanel.fetch.quickpanel)
{
bd->client.illume.quickpanel.quickpanel =
ecore_x_e_illume_quickpanel_get(bd->client.win);
bd->client.illume.quickpanel.fetch.quickpanel = 0;
}
if (bd->client.illume.quickpanel.fetch.priority.major)
{
bd->client.illume.quickpanel.priority.major =
ecore_x_e_illume_quickpanel_priority_major_get(bd->client.win);
bd->client.illume.quickpanel.fetch.priority.major = 0;
}
if (bd->client.illume.quickpanel.fetch.priority.minor)
{
bd->client.illume.quickpanel.priority.minor =
ecore_x_e_illume_quickpanel_priority_minor_get(bd->client.win);
bd->client.illume.quickpanel.fetch.priority.minor = 0;
}
if (bd->client.illume.quickpanel.fetch.zone)
{
bd->client.illume.quickpanel.zone =
ecore_x_e_illume_quickpanel_zone_get(bd->client.win);
bd->client.illume.quickpanel.fetch.zone = 0;
}
if (bd->client.illume.drag.fetch.drag)
{
bd->client.illume.drag.drag =
ecore_x_e_illume_drag_get(bd->client.win);
bd->client.illume.drag.fetch.drag = 0;
}
if (bd->client.illume.drag.fetch.locked)
{
bd->client.illume.drag.locked =
ecore_x_e_illume_drag_locked_get(bd->client.win);
bd->client.illume.drag.fetch.locked = 0;
}
if (bd->client.illume.win_state.fetch.state)
{
bd->client.illume.win_state.state =
ecore_x_e_illume_window_state_get(bd->client.win);
bd->client.illume.win_state.fetch.state = 0;
}
if (bd->changes.shape)
{
Ecore_X_Rectangle *rects;
int num;
bd->changes.shape = 0;
rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
if (rects)
{
int cw = 0, ch = 0;
/* This doesn't fix the race, but makes it smaller. we detect
* this and if cw and ch != client w/h then mark this as needing
* a shape change again to fixup next event loop.
*/
ecore_x_window_size_get(bd->client.win, &cw, &ch);
if ((cw != bd->client.w) || (ch != bd->client.h))
bd->changes.shape = 1;
if ((num == 1) &&
(rects[0].x == 0) &&
(rects[0].y == 0) &&
((int)rects[0].width == cw) &&
((int)rects[0].height == ch))
{
if (bd->client.shaped)
{
bd->client.shaped = 0;
if (!bd->bordername)
bd->client.border.changed = 1;
}
}
else
{
if (!bd->client.shaped)
{
bd->client.shaped = 1;
if (!bd->bordername)
bd->client.border.changed = 1;
}
ecore_x_window_shape_rectangles_set(bd->win, rects, num);
bd->changes.shape_input = 0;
e_container_shape_input_rects_set(bd->shape, NULL, 0);
}
free(rects);
}
else
{
// FIXME: no rects i think can mean... totally empty window
bd->client.shaped = 0;
if (!bd->bordername)
bd->client.border.changed = 1;
}
bd->need_shape_merge = 1;
}
if (bd->changes.shape_input)
{
Ecore_X_Rectangle *rects;
int num;
bd->changes.shape_input = 0;
rects = ecore_x_window_shape_input_rectangles_get(bd->client.win, &num);
if (rects)
{
int cw = 0, ch = 0;
/* This doesn't fix the race, but makes it smaller. we detect
* this and if cw and ch != client w/h then mark this as needing
* a shape change again to fixup next event loop.
*/
ecore_x_window_size_get(bd->client.win, &cw, &ch);
if ((cw != bd->client.w) || (ch != bd->client.h))
bd->changes.shape_input = 1;
if ((num == 1) &&
(rects[0].x == 0) &&
(rects[0].y == 0) &&
((int)rects[0].width == cw) &&
((int)rects[0].height == ch))
{
if (bd->shaped_input)
{
bd->shaped_input = 0;
if (!bd->bordername)
bd->client.border.changed = 1;
}
free(rects);
}
else
{
if (!bd->shaped_input)
{
bd->shaped_input = 1;
if (!bd->bordername)
bd->client.border.changed = 1;
}
ecore_x_window_shape_input_rectangles_set(bd->win, rects, num);
e_container_shape_input_rects_set(bd->shape, (Eina_Rectangle *)rects, num);
}
}
else
{
bd->shaped_input = 1;
if (!bd->bordername)
bd->client.border.changed = 1;
}
bd->need_shape_merge = 1;
}
if (bd->changes.prop || bd->client.mwm.fetch.hints)
{
int pb;
bd->client.mwm.exists =
ecore_x_mwm_hints_get(bd->client.win,
&bd->client.mwm.func,
&bd->client.mwm.decor,
&bd->client.mwm.input);
pb = bd->client.mwm.borderless;
bd->client.mwm.borderless = 0;
if (bd->client.mwm.exists)
{
if ((!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
(!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
(!(bd->client.mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
bd->client.mwm.borderless = 1;
}
if (bd->client.mwm.borderless != pb)
{
if ((!bd->lock_border) || (!bd->client.border.name))
bd->client.border.changed = 1;
}
bd->client.mwm.fetch.hints = 0;
rem_change = 1;
}
if (bd->client.e.fetch.video_parent)
{
/* unlinking child/parent */
if (bd->client.e.state.video_parent_border != NULL)
{
bd->client.e.state.video_parent_border->client.e.state.video_child =
eina_list_remove
(bd->client.e.state.video_parent_border->client.e.state.video_child,
bd);
}
ecore_x_window_prop_card32_get(bd->client.win,
ECORE_X_ATOM_E_VIDEO_PARENT,
&bd->client.e.state.video_parent,
1);
/* linking child/parent */
if (bd->client.e.state.video_parent != 0)
{
E_Border *tmp;
Eina_List *l;
EINA_LIST_FOREACH(borders, l, tmp)
if (tmp->client.win == bd->client.e.state.video_parent)
{
/* fprintf(stderr, "child added to parent \\o/\n"); */
bd->client.e.state.video_parent_border = tmp;
tmp->client.e.state.video_child = eina_list_append(tmp->client.e.state.video_child,
bd);
if (bd->desk != tmp->desk)
e_border_desk_set(bd, tmp->desk);
break;
}
}
/* fprintf(stderr, "new parent %x => %p\n", bd->client.e.state.video_parent, bd->client.e.state.video_parent_border); */
if (bd->client.e.state.video_parent_border) bd->client.e.fetch.video_parent = 0;
rem_change = 1;
}
if (bd->client.e.fetch.video_position && bd->client.e.fetch.video_parent == 0)
{
unsigned int xy[2];
ecore_x_window_prop_card32_get(bd->client.win,
ECORE_X_ATOM_E_VIDEO_POSITION,
xy,
2);
bd->client.e.state.video_position.x = xy[0];
bd->client.e.state.video_position.y = xy[1];
bd->client.e.state.video_position.updated = 1;
bd->client.e.fetch.video_position = 0;
bd->x = bd->client.e.state.video_position.x;
bd->y = bd->client.e.state.video_position.y;
fprintf(stderr, "internal position has been updated [%i, %i]\n", bd->client.e.state.video_position.x, bd->client.e.state.video_position.y);
}
if (bd->changes.prop || bd->client.netwm.update.state)
{
e_hints_window_state_set(bd);
/* Some stats might change the border, like modal */
if (((!bd->lock_border) || (!bd->client.border.name)) &&
(!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
{
bd->client.border.changed = 1;
}
if (bd->parent)
{
if (bd->client.netwm.state.modal)
{
bd->parent->modal = bd;
if (bd->parent->focused)
e_border_focus_set(bd, 1, 1);
}
}
else if (bd->leader)
{
if (bd->client.netwm.state.modal)
{
bd->leader->modal = bd;
if (bd->leader->focused)
e_border_focus_set(bd, 1, 1);
else
{
Eina_List *l;
E_Border *child;
EINA_LIST_FOREACH(bd->leader->group, l, child)
{
if ((child != bd) && (child->focused))
e_border_focus_set(bd, 1, 1);
}
}
}
}
bd->client.netwm.update.state = 0;
}
#if (ECORE_VERSION_MAJOR > 1) || (ECORE_VERSION_MINOR >= 8)
if ((e_config->use_desktop_window_profile) && (need_desk_set))
{
if (!(bd->client.e.state.profile.name) &&
(bd->client.e.state.profile.num >= 1))
{
const char *p = NULL;
int i;
for (i = 0; i < bd->client.e.state.profile.num; i++)
{
if (!bd->client.e.state.profile.available_list[i])
continue;
p = bd->client.e.state.profile.available_list[i];
if (strcmp(bd->desk->window_profile, p) == 0)
{
bd->client.e.state.profile.name = eina_stringshare_add(bd->desk->window_profile);
break;
}
}
if (!bd->client.e.state.profile.name)
{
E_Container *con = bd->zone->container;
E_Desk *desk = NULL;
for (i = 0; i < bd->client.e.state.profile.num; i++)
{
if (!bd->client.e.state.profile.available_list[i])
continue;
p = bd->client.e.state.profile.available_list[i];
desk = e_container_desk_window_profile_get(con, p);
if ((desk) && (bd->desk != desk))
{
bd->client.e.state.profile.name = eina_stringshare_add(p);
break;
}
}
}
}
if (!bd->client.e.state.profile.name)
{
bd->client.e.state.profile.name = eina_stringshare_add(bd->desk->window_profile);
}
ecore_x_e_window_profile_change_request_send(bd->client.win,
bd->client.e.state.profile.name);
bd->client.e.state.profile.wait_for_done = 1;
}
#endif
if (bd->new_client)
{
E_Event_Border_Add *ev;
E_Exec_Instance *inst;
ev = E_NEW(E_Event_Border_Add, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_add_event");
ecore_event_add(E_EVENT_BORDER_ADD, ev, _e_border_event_border_add_free, NULL);
if ((!bd->lock_border) || (!bd->client.border.name))
bd->client.border.changed = 1;
{
char *str = NULL;
if ((ecore_x_netwm_startup_id_get(bd->client.win, &str) && (str)) ||
((bd->client.icccm.client_leader > 0) &&
ecore_x_netwm_startup_id_get(bd->client.icccm.client_leader, &str) && (str))
)
{
if (!strncmp(str, "E_START|", 8))
{
int id;
id = atoi(str + 8);
if (id > 0) bd->client.netwm.startup_id = id;
}
free(str);
}
}
/* It's ok not to have fetch flag, should only be set on startup
* * and not changed. */
if (!ecore_x_netwm_pid_get(bd->client.win, &bd->client.netwm.pid))
{
if (bd->client.icccm.client_leader)
{
if (!ecore_x_netwm_pid_get(bd->client.icccm.client_leader, &bd->client.netwm.pid))
bd->client.netwm.pid = -1;
}
else
bd->client.netwm.pid = -1;
}
if (bd->re_manage)
e_exec_phony(bd);
else
{
inst = e_exec_startup_id_pid_instance_find(bd->client.netwm.startup_id,
bd->client.netwm.pid);
if (inst)
{
Eina_Bool found;
if (inst->used == 0)
{
E_Zone *zone;
E_Desk *desk;
inst->used++;
zone = e_container_zone_number_get(bd->zone->container,
inst->screen);
if (zone) e_border_zone_set(bd, zone);
desk = e_desk_at_xy_get(bd->zone, inst->desk_x,
inst->desk_y);
if (desk) e_border_desk_set(bd, desk);
if (bd->client.netwm.pid != ecore_exe_pid_get(inst->exe))
{
/* most likely what has happened here is that the .desktop launcher
* has spawned a process which then created this border, meaning the
* E_Exec instance will be deleted in a moment, and we will be unable to track it.
* to prevent this, we convert our instance to a phony
*/
inst->phony = 1;
}
}
found = !!inst->borders;
e_exec_instance_client_add(inst, bd);
if (!found)
e_exec_instance_found(inst);
}
else if (!inst)
e_exec_phony(bd);
if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
{
E_Border *bdl = NULL;
bdl = bd->parent;
if (!bdl)
{
if (bd->leader) bdl = bd->leader;
}
if (!bdl)
{
E_Border *child;
E_Border_List *bl;
bl = e_container_border_list_first(bd->zone->container);
while ((child = e_container_border_list_next(bl)))
{
if (child == bd) continue;
if (e_object_is_del(E_OBJECT(child))) continue;
if ((bd->client.icccm.client_leader) &&
(child->client.icccm.client_leader ==
bd->client.icccm.client_leader))
{
bdl = child;
break;
}
}
e_container_border_list_free(bl);
}
if (bdl)
{
if (bdl->zone)
e_border_zone_set(bd, bdl->zone);
if (bdl->desk)
e_border_desk_set(bd, bdl->desk);
else
e_border_stick(bd);
}
}
}
}
/* PRE_POST_FETCH calls e_remember apply for new client */
_e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_POST_FETCH, bd);
_e_border_hook_call(E_BORDER_HOOK_EVAL_POST_FETCH, bd);
_e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_BORDER_ASSIGN, bd);
if (bd->need_reparent)
{
if (!bd->internal)
ecore_x_window_save_set_add(bd->client.win);
ecore_x_window_reparent(bd->client.win, bd->win, bd->client_inset.l, bd->client_inset.t);
if (bd->visible)
{
if ((bd->new_client) && (bd->internal) &&
(bd->internal_ecore_evas))
ecore_evas_show(bd->internal_ecore_evas);
}
if (bd->new_client)
{
ecore_x_window_show(bd->client.win);
_e_border_show(bd);
}
bd->need_reparent = 0;
}
if ((bd->client.border.changed) && (!bd->shaded) &&
(!(((bd->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))))
{
const char *bordername;
if (bd->fullscreen || bd->borderless)
bordername = "borderless";
else if (bd->bordername)
bordername = bd->bordername;
else if ((bd->client.mwm.borderless) || (bd->borderless))
bordername = "borderless";
else if (((bd->client.icccm.transient_for != 0) ||
(bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)) &&
(bd->client.icccm.min_w == bd->client.icccm.max_w) &&
(bd->client.icccm.min_h == bd->client.icccm.max_h))
bordername = "noresize_dialog";
else if ((bd->client.icccm.min_w == bd->client.icccm.max_w) &&
(bd->client.icccm.min_h == bd->client.icccm.max_h))
bordername = "noresize";
else if (bd->client.shaped)
bordername = "shaped";
else if ((!bd->client.icccm.accepts_focus) &&
(!bd->client.icccm.take_focus))
bordername = "nofocus";
else if (bd->client.icccm.urgent)
bordername = "urgent";
else if ((bd->client.icccm.transient_for != 0) ||
(bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
bordername = "dialog";
else if (bd->client.netwm.state.modal)
bordername = "modal";
else if ((bd->client.netwm.state.skip_taskbar) ||
(bd->client.netwm.state.skip_pager))
bordername = "skipped";
/*
else if ((bd->internal) && (bd->client.icccm.class) &&
(!strncmp(bd->client.icccm.class, "e_fwin", 6)))
bordername = "internal_fileman";
*/
else
bordername = e_config->theme_default_border_style;
if (!bordername) bordername = "default";
if ((!bd->client.border.name) || (strcmp(bd->client.border.name, bordername)))
{
Evas_Object *o, *pbg = bd->bg_object;
char buf[4096];
int ok;
bd->changes.border = 1;
eina_stringshare_replace(&bd->client.border.name, bordername);
if (bd->bg_object)
{
int w, h;
w = bd->w, h = bd->h;
bd->w -= (e_border_inset_width_get(bd));
bd->h -= (e_border_inset_height_get(bd));
if ((bd->w != w) || (h != bd->h)) bd->changes.size = 1;
evas_object_del(bd->bg_object);
}
o = edje_object_add(e_comp_get(bd)->evas);
snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", bd->client.border.name);
ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
if ((!ok) && (strcmp(bd->client.border.name, "borderless")))
{
if (bd->client.border.name != e_config->theme_default_border_style)
{
snprintf(buf, sizeof(buf), "e/widgets/border/%s/border", e_config->theme_default_border_style);
ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
}
if (!ok)
{
ok = e_theme_edje_object_set(o, "base/theme/borders",
"e/widgets/border/default/border");
if (ok)
{
/* Reset default border style to default */
eina_stringshare_replace(&e_config->theme_default_border_style, "default");
e_config_save_queue();
}
}
}
if (ok)
{
bd->bg_object = o;
evas_object_name_set(o, "bd->bg_object");
if (bd->client.netwm.name)
edje_object_part_text_set(o, "e.text.title",
bd->client.netwm.name);
else if (bd->client.icccm.title)
edje_object_part_text_set(o, "e.text.title",
bd->client.icccm.title);
bd->theme_shadow = !!edje_object_data_get(o, "shadow");
_e_border_shadow(bd);
if (pbg)
{
if (bd->icon_object)
edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
}
else bd->changes.icon = 1;
}
else
{
if (strcmp(bordername, "borderless"))
/* it should never happen that a theme fails to set the edje
* unless it's using borderless
*/
CRI("USER IS USING A SHITTY THEME! ABORT!!!!");
evas_object_del(o);
bd->bg_object = NULL;
E_FREE_FUNC(bd->icon_object, evas_object_del);
o = bd->cw ? bd->cw->obj : NULL;
}
if (bd->cw) e_comp_win_reshadow(bd->cw);
/* FIXME: it's theoretically possible that o is NULL here if first border eval occurs for a fullscreen
* borderless window before its comp win has been set up;
* E19 material imo
*/
{
// previously calculated
Eina_Bool calc = bd->client_inset.calc;
// previously was borderless
Eina_Bool inset, pinset = !!(e_border_inset_width_get(bd) + e_border_inset_height_get(bd));
_e_border_client_inset_calc(bd);
inset = !!(e_border_inset_width_get(bd) + e_border_inset_height_get(bd));
if (calc && (inset != pinset) && (pbg || (!bd->bg_object)))
{
if (inset)
bd->x -= bd->client_inset.l, bd->y -= bd->client_inset.t;
else
bd->x += bd->client_inset.l, bd->y += bd->client_inset.t;
}
}
bd->w += (e_border_inset_width_get(bd));
bd->h += (e_border_inset_height_get(bd));
bd->changes.size = 1;
if (bd->maximized != E_MAXIMIZE_NONE)
{
E_Maximize maximized = bd->maximized;
/* to force possible resizes */
bd->maximized = E_MAXIMIZE_NONE;
_e_border_maximize(bd, maximized);
/* restore maximized state */
bd->maximized = maximized;
e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_HORIZONTAL,
bd->maximized & E_MAXIMIZE_VERTICAL);
}
if (bd->bg_object)
{
edje_object_signal_callback_add(bd->bg_object, "*", "*",
_e_border_cb_signal_bind, bd);
if (bd->focused)
{
edje_object_signal_emit(bd->bg_object, "e,state,focused", "e");
if (bd->icon_object)
edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
}
if (bd->shaded)
edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
if (bd->sticky)
edje_object_signal_emit(bd->bg_object, "e,state,sticky", "e");
if (bd->hung)
edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
// FIXME: in eval -do differently
// edje_object_message_signal_process(bd->bg_object);
// e_border_frame_recalc(bd);
}
rem_change = 1;
}
bd->client.border.changed = 0;
}
bd->changes.prop = 0;
if (rem_change) e_remember_update(bd);
/* the below function updates the border's remember
* and relevant netwm atom
* ...eventually
*/
if (bd->cw) e_comp_win_opacity_set(bd->cw, bd->client.netwm.opacity);
if (change_urgent)
{
E_Event_Border_Urgent_Change *ev;
if (bd->client.icccm.urgent)
edje_object_signal_emit(bd->bg_object, "e,state,urgent", "e");
else
edje_object_signal_emit(bd->bg_object, "e,state,not_urgent", "e");
ev = E_NEW(E_Event_Border_Urgent_Change, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_URGENT_CHANGE, ev,
_e_border_event_border_urgent_change_free, NULL);
}
_e_border_hook_call(E_BORDER_HOOK_EVAL_POST_BORDER_ASSIGN, bd);
if (!new_cw) return;
evas_object_event_callback_add(bd->cw->effect_obj, EVAS_CALLBACK_MOUSE_IN, _e_border_cb_mouse_in, bd);
evas_object_event_callback_add(bd->cw->effect_obj, EVAS_CALLBACK_MOUSE_MOVE, _e_border_cb_mouse_move, bd);
evas_object_event_callback_add(bd->cw->effect_obj, EVAS_CALLBACK_MOUSE_OUT, _e_border_cb_mouse_out, bd);
evas_object_event_callback_add(bd->cw->effect_obj, EVAS_CALLBACK_MOUSE_DOWN, _e_border_cb_mouse_down, bd);
evas_object_event_callback_add(bd->cw->effect_obj, EVAS_CALLBACK_MOUSE_UP, _e_border_cb_mouse_up, bd);
evas_object_event_callback_add(bd->cw->effect_obj, EVAS_CALLBACK_MOUSE_WHEEL, _e_border_cb_mouse_wheel, bd);
}
static void
_e_border_eval(E_Border *bd)
{
E_Event_Border_Property *event;
E_Border_Pending_Move_Resize *pnd;
int rem_change = 0;
int send_event = 1;
if (e_object_is_del(E_OBJECT(bd)))
{
CRI("_e_border_eval(%p) with deleted border! - %d\n", bd, bd->new_client);
bd->changed = 0;
return;
}
_e_border_hook_call(E_BORDER_HOOK_EVAL_PRE_NEW_BORDER, bd);
if (bd->new_client)
{
int zx = 0, zy = 0, zw = 0, zh = 0;
if (bd->zone)
e_zone_useful_geometry_get(bd->zone, &zx, &zy, &zw, &zh);
/*
* Limit maximum size of windows to useful geometry
*/
// TODO: temoporary limited maximize algorithm
// ->
/*if (bd->w > zw)
rw = zw;
else
rw = bd->w;
if (bd->h > zh)
rh = zh;
else
rh = bd->h;
if ((rw != bd->w) || (rh != bd->h))
{
bd->w = rw;
bd->h = rh;
e_border_resize (bd, bd->w, bd->h);
}*/
// <-
if (bd->re_manage)
{
int x = bd->x, y = bd->y;
if (bd->x) bd->x -= bd->client_inset.l;
if (bd->y) bd->y -= bd->client_inset.t;
if ((x != bd->x) || (y != bd->y)) bd->changes.pos = 1;
bd->placed = 1;
}
else if ((!bd->placed) && (bd->client.icccm.request_pos))
{
Ecore_X_Window_Attributes *att;
int bw;
att = &bd->client.initial_attributes;
bw = att->border * 2;
switch (bd->client.icccm.gravity)
{
case ECORE_X_GRAVITY_N:
bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
bd->y = att->y;
break;
case ECORE_X_GRAVITY_NE:
bd->x = (att->x - (bw)) - (bd->client_inset.l);
bd->y = att->y;
break;
case ECORE_X_GRAVITY_E:
bd->x = (att->x - (bw)) - (bd->client_inset.l);
bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
break;
case ECORE_X_GRAVITY_SE:
bd->x = (att->x - (bw)) - (bd->client_inset.l);
bd->y = (att->y - (bw)) - (bd->client_inset.t);
break;
case ECORE_X_GRAVITY_S:
bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
bd->y = (att->y - (bw)) - (bd->client_inset.t);
break;
case ECORE_X_GRAVITY_SW:
bd->x = att->x;
bd->y = (att->y - (bw)) - (bd->client_inset.t);
break;
case ECORE_X_GRAVITY_W:
bd->x = att->x;
bd->y = (att->y - (bw)) - (bd->client_inset.t);
break;
case ECORE_X_GRAVITY_CENTER:
bd->x = (att->x - (bw / 2)) - (bd->client_inset.l / 2);
bd->y = (att->y - (bw / 2)) - (bd->client_inset.t / 2);
break;
case ECORE_X_GRAVITY_NW:
default:
bd->x = att->x;
bd->y = att->y;
}
/*
* This ensures that windows that like to open with a x/y
* position smaller than returned by e_zone_useful_geometry_get()
* are moved to useful positions.
*/
// ->
if (e_config->geometry_auto_move)
{
if (bd->x < zx)
bd->x = zx;
if (bd->y < zy)
bd->y = zy;
/* ensure we account for windows which already have client_inset;
* fixes lots of wine placement issues
*/
if (bd->x - bd->client_inset.l >= zx)
bd->x -= bd->client_inset.l;
if (bd->y - bd->client_inset.t >= zy)
bd->y -= bd->client_inset.t;
if (bd->x + bd->w > zx + zw)
bd->x = zx + zw - bd->w;
if (bd->y + bd->h > zy + zh)
bd->y = zy + zh - bd->h;
// <--
if (bd->zone && e_container_zone_at_point_get(bd->zone->container, bd->x, bd->y))
{
if (!E_INSIDE(bd->x, bd->y, bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
{
bd->x = E_CLAMP(bd->x, bd->zone->x, bd->zone->x + bd->zone->w);
bd->y = E_CLAMP(bd->y, bd->zone->y, bd->zone->y + bd->zone->h);
}
/* some application failing to correctly center a window */
if (eina_list_count(bd->zone->container->zones) > 1)
{
if (((abs((bd->zone->container->w / 2) - bd->x) < 3) || //bd->x is center of container
((abs((bd->zone->container->w / 2) - bd->x - bd->w) < 3) || //bd->x - bd->w is center of container
(abs((bd->zone->container->w / 2) - bd->x - (bd->w / 2)) < 3))) || //bd->x - bd->w/2 is center of container
((abs((bd->zone->container->h / 2) - bd->y) < 3) || //bd->y is center of container
((abs((bd->zone->container->h / 2) - bd->y - bd->h) < 3) || //bd->y - bd->h is center of container
(abs((bd->zone->container->h / 2) - bd->y - (bd->h / 2)) < 3))) //bd->y - bd->h/2 is center of container
)
e_border_center(bd);
}
bd->changes.pos = 1;
bd->placed = 1;
}
}
else
{
bd->changes.pos = 1;
bd->placed = 1;
}
}
if (!bd->placed)
{
/* FIXME: special placement for dialogs etc. etc. etc goes
* here */
/* FIXME: what if parent is not on this desktop - or zone? */
if ((bd->parent) && (bd->parent->visible))
{
bd->x = bd->parent->x + ((bd->parent->w - bd->w) / 2);
bd->y = bd->parent->y + ((bd->parent->h - bd->h) / 2);
bd->changes.pos = 1;
bd->placed = 1;
}
#if 0
else if ((bd->leader) && (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))
{
/* TODO: Place in center of group */
}
#endif
else if (bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG)
{
bd->x = zx + ((zw - bd->w) / 2);
bd->y = zy + ((zh - bd->h) / 2);
bd->changes.pos = 1;
bd->placed = 1;
}
}
if (!bd->placed)
{
Eina_List *skiplist = NULL;
int new_x, new_y;
if (zw > bd->w)
new_x = zx + (rand() % (zw - bd->w));
else
new_x = zx;
if (zh > bd->h)
new_y = zy + (rand() % (zh - bd->h));
else
new_y = zy;
if ((e_config->window_placement_policy == E_WINDOW_PLACEMENT_SMART) || (e_config->window_placement_policy == E_WINDOW_PLACEMENT_ANTIGADGET))
{
skiplist = eina_list_append(skiplist, bd);
if (bd->desk)
e_place_desk_region_smart(bd->desk, skiplist,
bd->x, bd->y, bd->w, bd->h,
&new_x, &new_y);
else
e_place_zone_region_smart(bd->zone, skiplist,
bd->x, bd->y, bd->w, bd->h,
&new_x, &new_y);
eina_list_free(skiplist);
}
else if (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL)
{
e_place_zone_manual(bd->zone, bd->w, bd->client_inset.t,
&new_x, &new_y);
}
else
{
e_place_zone_cursor(bd->zone, bd->x, bd->y, bd->w, bd->h,
bd->client_inset.t, &new_x, &new_y);
}
bd->x = new_x;
bd->y = new_y;
bd->changes.pos = 1;
}
EINA_LIST_FREE(bd->pending_move_resize, pnd)
{
if ((!bd->lock_client_location) && (pnd->move))
{
bd->x = pnd->x;
bd->y = pnd->y;
bd->changes.pos = 1;
bd->placed = 1;
if (pnd->without_border)
{
bd->x -= bd->client_inset.l;
bd->y -= bd->client_inset.t;
}
}
if ((!bd->lock_client_size) && (pnd->resize))
{
bd->w = pnd->w + (e_border_inset_width_get(bd));
bd->h = pnd->h + (e_border_inset_height_get(bd));
bd->client.w = pnd->w;
bd->client.h = pnd->h;
bd->changes.size = 1;
}
free(pnd);
}
/* Recreate state */
e_hints_window_init(bd);
if ((bd->client.e.state.centered) &&
((!bd->remember) ||
((bd->remember) && (!(bd->remember->apply & E_REMEMBER_APPLY_POS)))))
{
bd->x = zx + (zw - bd->w) / 2;
bd->y = zy + (zh - bd->h) / 2;
bd->changes.pos = 1;
bd->placed = 1;
}
_e_border_client_move_resize_send(bd);
/* if the explicit geometry request asks for the app to be
* in another zone - well move it there */
{
E_Zone *zone;
zone = e_container_zone_at_point_get(bd->zone->container,
bd->x + (bd->w / 2),
bd->y + (bd->h / 2));
if (!zone)
zone = e_container_zone_at_point_get(bd->zone->container,
bd->x,
bd->y);
if (!zone)
zone = e_container_zone_at_point_get(bd->zone->container,
bd->x + bd->w - 1,
bd->y);
if (!zone)
zone = e_container_zone_at_point_get(bd->zone->container,
bd->x + bd->w - 1,
bd->y + bd->h - 1);
if (!zone)
zone = e_container_zone_at_point_get(bd->zone->container,
bd->x,
bd->y + bd->h - 1);
if ((zone) && (zone != bd->zone))
e_border_zone_set(bd, zone);
}
}
_e_border_hook_call(E_BORDER_HOOK_EVAL_POST_NEW_BORDER, bd);
/* effect changes to the window border itself */
if ((bd->changes.shading))
{
/* show at start of unshade (but don't hide until end of shade) */
//if (bd->shaded)
//ecore_x_window_raise(bd->win);
bd->changes.shading = 0;
send_event = 0;
rem_change = 1;
}
if (bd->changes.shaded) send_event = 0;
if ((bd->changes.shaded) && (bd->changes.pos) && (bd->changes.size))
{
//if (bd->shaded)
//ecore_x_window_lower(bd->win);
//else
//ecore_x_window_raise(bd->win);
bd->changes.shaded = 0;
rem_change = 1;
}
else if ((bd->changes.shaded) && (bd->changes.pos))
{
//if (bd->shaded)
//ecore_x_window_lower(bd->win);
//else
//ecore_x_window_raise(bd->win);
bd->changes.size = 1;
bd->changes.shaded = 0;
rem_change = 1;
}
else if ((bd->changes.shaded) && (bd->changes.size))
{
//if (bd->shaded)
//ecore_x_window_lower(bd->win);
//else
//ecore_x_window_raise(bd->win);
bd->changes.shaded = 0;
rem_change = 1;
}
else if (bd->changes.shaded)
{
//if (bd->shaded)
//ecore_x_window_lower(bd->win);
//else
//ecore_x_window_raise(bd->win);
bd->changes.shaded = 0;
rem_change = 1;
}
if (bd->changes.size)
{
int x, y, w = 0, h = 0;
x = bd->x + bd->client_inset.l;
y = bd->y + bd->client_inset.t;
if ((!bd->shaded) || (bd->shading))
{
w = bd->w - (e_border_inset_width_get(bd));
h = bd->h - (e_border_inset_height_get(bd));
if (bd->shading)
{
if (bd->shade.dir == E_DIRECTION_UP)
{
y = h - bd->client.h;
}
else if (bd->shade.dir == E_DIRECTION_LEFT)
{
x = w - bd->client.w;
}
}
}
if (bd->client.e.state.video)
{
if (bd->client.e.state.video_position.updated)
{
ecore_x_window_move(bd->win,
bd->client.e.state.video_parent_border->x +
bd->client.e.state.video_parent_border->client_inset.l +
bd->client.e.state.video_position.x,
bd->client.e.state.video_parent_border->y +
bd->client.e.state.video_parent_border->client_inset.t +
bd->client.e.state.video_position.y);
bd->client.e.state.video_position.updated = 0;
}
}
else if (!bd->changes.pos)
{
if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
bd->post_resize = 1;
}
else
{
E_Border *tmp;
Eina_List *l;
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
ecore_x_window_move(tmp->win,
bd->x + bd->client_inset.l + tmp->client.e.state.video_position.x,
bd->y + bd->client_inset.t + tmp->client.e.state.video_position.y);
}
if ((!bd->shaded) && (!bd->shading))
{
ecore_x_window_move_resize(bd->win, x, y, w, h);
if (bd->internal_ecore_evas)
ecore_evas_move_resize(bd->internal_ecore_evas, 0, 0, w, h);
else if (!bd->client.e.state.video)
{
ecore_x_window_move_resize(bd->client.win, 0, 0, bd->client.w, bd->client.h);
if (bd->client.lock_win)
ecore_x_window_move_resize(bd->client.lock_win, 0, 0, bd->client.w, bd->client.h);
}
_e_border_client_move_resize_send(bd);
}
else if (bd->changes.pos)
ecore_x_window_move(bd->win, x, y);
e_container_shape_resize(bd->shape, w, h);
if (bd->changes.pos)
e_container_shape_move(bd->shape, x, y);
bd->changes.pos = 0;
bd->changes.size = 0;
rem_change = 1;
}
else if (bd->changes.pos)
{
if (bd->post_job) ecore_idle_enterer_del(bd->post_job);
bd->post_job = ecore_idle_enterer_add(_e_border_post_move_resize_job, bd);
bd->post_move = 1;
e_container_shape_move(bd->shape, bd->x + bd->client_inset.l, bd->y + bd->client_inset.t);
_e_border_client_move_resize_send(bd);
bd->changes.pos = 0;
rem_change = 1;
}
if (bd->changes.reset_gravity)
{
GRAV_SET(bd, ECORE_X_GRAVITY_NW);
bd->changes.reset_gravity = 0;
rem_change = 1;
}
if (bd->need_shape_merge)
{
_e_border_shape_input_rectangle_set(bd);
if (!bd->client.shaped)
ecore_x_window_shape_mask_set(bd->win, 0);
//bd->need_shape_export = 1;
bd->need_shape_merge = 0;
}
if (bd->need_shape_export)
{
Ecore_X_Rectangle *rects, *orects;
int num;
rects = ecore_x_window_shape_rectangles_get(bd->client.win, &num);
if (rects)
{
int changed;
changed = 1;
if ((num == bd->shape->shape_rects_num) && (bd->shape->shape_rects))
{
int i;
orects = (Ecore_X_Rectangle*)bd->shape->shape_rects;
changed = 0;
for (i = 0; i < num; i++)
{
if (rects[i].x < 0)
{
rects[i].width -= rects[i].x;
rects[i].x = 0;
}
if ((rects[i].x + (int)rects[i].width) > bd->w)
rects[i].width = rects[i].width - rects[i].x;
if (rects[i].y < 0)
{
rects[i].height -= rects[i].y;
rects[i].y = 0;
}
if ((rects[i].y + (int)rects[i].height) > bd->h)
rects[i].height = rects[i].height - rects[i].y;
if ((orects[i].x != rects[i].x) ||
(orects[i].y != rects[i].y) ||
(orects[i].width != rects[i].width) ||
(orects[i].height != rects[i].height))
{
changed = 1;
break;
}
}
}
if (changed)
{
if (bd->client.shaped)
e_container_shape_solid_rect_set(bd->shape, 0, 0, 0, 0);
e_container_shape_rects_set(bd->shape, (Eina_Rectangle*)rects, num);
}
else
free(rects);
}
else
{
e_container_shape_rects_set(bd->shape, NULL, 0);
}
bd->need_shape_export = 0;
}
if ((bd->changes.visible) && (bd->visible) && (bd->new_client))
{
int x, y;
ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
if ((!bd->placed) && (!bd->re_manage) &&
(e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
(!((bd->client.icccm.transient_for != 0) ||
(bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) &&
(!bdmove) && (!bdresize))
{
/* Set this window into moving state */
bd->cur_mouse_action = e_action_find("window_move");
if (bd->cur_mouse_action)
{
if ((!bd->cur_mouse_action->func.end_mouse) &&
(!bd->cur_mouse_action->func.end))
bd->cur_mouse_action = NULL;
if (bd->cur_mouse_action)
{
bd->x = x - (bd->w >> 1);
bd->y = y - (bd->client_inset.t >> 1);
BD_CHANGED(bd);
bd->changes.pos = 1;
_e_border_client_move_resize_send(bd);
}
}
}
_e_border_show(bd);
if (bd->cur_mouse_action)
{
bd->moveinfo.down.x = bd->x;
bd->moveinfo.down.y = bd->y;
bd->moveinfo.down.w = bd->w;
bd->moveinfo.down.h = bd->h;
bd->mouse.current.mx = x;
bd->mouse.current.my = y;
bd->moveinfo.down.button = 0;
bd->moveinfo.down.mx = x;
bd->moveinfo.down.my = y;
grabbed = 1;
e_object_ref(E_OBJECT(bd->cur_mouse_action));
bd->cur_mouse_action->func.go(E_OBJECT(bd), NULL);
if (e_config->border_raise_on_mouse_action)
e_border_raise(bd);
e_border_focus_set(bd, 1, 1);
}
bd->changes.visible = 0;
rem_change = 1;
{
E_Event_Border_Show *ev;
ev = E_NEW(E_Event_Border_Show, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_show_event");
ecore_event_add(E_EVENT_BORDER_SHOW, ev, _e_border_event_border_show_free, NULL);
}
}
else if ((bd->changes.visible) && (bd->new_client))
{
bd->changes.visible = 0;
{
E_Event_Border_Hide *ev;
ev = E_NEW(E_Event_Border_Hide, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_hide_event");
ecore_event_add(E_EVENT_BORDER_HIDE, ev, _e_border_event_border_hide_free, NULL);
}
}
if (bd->changes.icon)
{
if (bd->desktop)
{
efreet_desktop_free(bd->desktop);
bd->desktop = NULL;
}
if (bd->icon_object)
{
evas_object_del(bd->icon_object);
bd->icon_object = NULL;
}
if (bd->remember && bd->remember->prop.desktop_file)
{
const char *desktop = bd->remember->prop.desktop_file;
bd->desktop = efreet_desktop_get(desktop);
if (!bd->desktop)
bd->desktop = efreet_util_desktop_name_find(desktop);
}
if (!bd->desktop)
{
if ((bd->client.icccm.name) && (bd->client.icccm.class))
bd->desktop = efreet_util_desktop_wm_class_find(bd->client.icccm.name,
bd->client.icccm.class);
}
if (!bd->desktop)
{
/* libreoffice and maybe others match window class
with .desktop file name */
if (bd->client.icccm.class)
{
char buf[128];
snprintf(buf, sizeof(buf), "%s.desktop", bd->client.icccm.class);
bd->desktop = efreet_util_desktop_file_id_find(buf);
}
}
if (!bd->desktop)
{
bd->desktop = e_exec_startup_id_pid_find(bd->client.netwm.startup_id,
bd->client.netwm.pid);
if (bd->desktop) efreet_desktop_ref(bd->desktop);
}
if (!bd->desktop && bd->client.icccm.name)
{
/* this works for most cases as fallback. useful when app is
run from a shell */
bd->desktop = efreet_util_desktop_exec_find(bd->client.icccm.name);
}
if (!bd->desktop && bd->client.icccm.transient_for)
{
E_Border *bd2 = e_border_find_by_client_window(bd->client.icccm.transient_for);
if (bd2 && bd2->desktop)
{
efreet_desktop_ref(bd2->desktop);
bd->desktop = bd2->desktop;
}
}
if (bd->desktop)
{
ecore_x_window_prop_string_set(bd->client.win, E_ATOM_DESKTOP_FILE,
bd->desktop->orig_path);
}
bd->icon_object = e_border_icon_add(bd, e_comp_get(bd)->evas);
if ((bd->focused) && (bd->icon_object))
edje_object_signal_emit(bd->icon_object, "e,state,focused", "e");
if (bd->bg_object)
{
evas_object_show(bd->icon_object);
edje_object_part_swallow(bd->bg_object, "e.swallow.icon", bd->icon_object);
}
else
evas_object_hide(bd->icon_object);
{
E_Event_Border_Icon_Change *ev;
ev = E_NEW(E_Event_Border_Icon_Change, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_icon_change_event");
ecore_event_add(E_EVENT_BORDER_ICON_CHANGE, ev,
_e_border_event_border_icon_change_free, NULL);
}
bd->changes.icon = 0;
}
bd->new_client = 0;
bd->changed = 0;
bd->changes.stack = 0;
if ((bd->take_focus) || (bd->want_focus))
{
bd->take_focus = 0;
if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) || (bd->want_focus))
{
bd->want_focus = 0;
e_border_focus_set_with_pointer(bd);
}
else if ((bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG) ||
(bd->parent && (bd->parent->modal == bd)))
{
if ((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
((e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED) &&
(e_border_find_by_client_window(bd->client.icccm.transient_for) ==
e_border_focused_get())))
{
e_border_focus_set_with_pointer(bd);
}
}
else
{
/* focus window by default when it is the only one on desk */
E_Border *bd2 = NULL;
Eina_List *l;
EINA_LIST_FOREACH(focus_stack, l, bd2)
{
if (bd == bd2) continue;
if ((!bd2->iconic) && (bd2->visible) &&
((bd->desk == bd2->desk) || bd2->sticky))
break;
}
if (!bd2)
{
e_border_focus_set_with_pointer(bd);
}
}
}
if (bd->need_maximize)
{
E_Maximize max;
max = bd->maximized;
bd->maximized = E_MAXIMIZE_NONE;
e_border_maximize(bd, max);
bd->need_maximize = 0;
}
if (bd->need_fullscreen)
{
e_border_fullscreen(bd, e_config->fullscreen_policy);
bd->need_fullscreen = 0;
}
if (rem_change)
e_remember_update(bd);
if (send_event) // FIXME: send only if a property changed - above need to
{ // check on that. for now - always send.
event = E_NEW(E_Event_Border_Property, 1);
event->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_PROPERTY, event, _e_border_event_border_property_free, NULL);
}
_e_border_hook_call(E_BORDER_HOOK_EVAL_END, bd);
}
static void
_e_border_moveinfo_gather(E_Border *bd,
const char *source)
{
if (e_util_glob_match(source, "mouse,*,1")) bd->moveinfo.down.button = 1;
else if (e_util_glob_match(source, "mouse,*,2"))
bd->moveinfo.down.button = 2;
else if (e_util_glob_match(source, "mouse,*,3"))
bd->moveinfo.down.button = 3;
else bd->moveinfo.down.button = 0;
if ((bd->moveinfo.down.button >= 1) && (bd->moveinfo.down.button <= 3))
{
bd->moveinfo.down.mx = bd->mouse.last_down[bd->moveinfo.down.button - 1].mx;
bd->moveinfo.down.my = bd->mouse.last_down[bd->moveinfo.down.button - 1].my;
}
else
{
bd->moveinfo.down.mx = bd->mouse.current.mx;
bd->moveinfo.down.my = bd->mouse.current.my;
}
}
static void
_e_border_resize_handle(E_Border *bd)
{
int x, y, w, h;
int new_x, new_y, new_w, new_h;
int tw, th;
Eina_List *skiplist = NULL;
x = bd->x;
y = bd->y;
w = bd->w;
h = bd->h;
if ((bd->resize_mode == E_POINTER_RESIZE_TR) ||
(bd->resize_mode == E_POINTER_RESIZE_R) ||
(bd->resize_mode == E_POINTER_RESIZE_BR))
{
if ((bd->moveinfo.down.button >= 1) &&
(bd->moveinfo.down.button <= 3))
w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w +
(bd->mouse.current.mx - bd->moveinfo.down.mx);
else
w = bd->moveinfo.down.w + (bd->mouse.current.mx - bd->moveinfo.down.mx);
}
else if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_L) ||
(bd->resize_mode == E_POINTER_RESIZE_BL))
{
if ((bd->moveinfo.down.button >= 1) &&
(bd->moveinfo.down.button <= 3))
w = bd->mouse.last_down[bd->moveinfo.down.button - 1].w -
(bd->mouse.current.mx - bd->moveinfo.down.mx);
else
w = bd->moveinfo.down.w - (bd->mouse.current.mx - bd->moveinfo.down.mx);
}
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_T) ||
(bd->resize_mode == E_POINTER_RESIZE_TR))
{
if ((bd->moveinfo.down.button >= 1) &&
(bd->moveinfo.down.button <= 3))
h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h -
(bd->mouse.current.my - bd->moveinfo.down.my);
else
h = bd->moveinfo.down.h - (bd->mouse.current.my - bd->moveinfo.down.my);
}
else if ((bd->resize_mode == E_POINTER_RESIZE_BL) ||
(bd->resize_mode == E_POINTER_RESIZE_B) ||
(bd->resize_mode == E_POINTER_RESIZE_BR))
{
if ((bd->moveinfo.down.button >= 1) &&
(bd->moveinfo.down.button <= 3))
h = bd->mouse.last_down[bd->moveinfo.down.button - 1].h +
(bd->mouse.current.my - bd->moveinfo.down.my);
else
h = bd->moveinfo.down.h + (bd->mouse.current.my - bd->moveinfo.down.my);
}
tw = bd->w;
th = bd->h;
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_L) ||
(bd->resize_mode == E_POINTER_RESIZE_BL))
x += (tw - w);
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_T) ||
(bd->resize_mode == E_POINTER_RESIZE_TR))
y += (th - h);
skiplist = eina_list_append(skiplist, bd);
e_resist_container_border_position(bd->zone->container, skiplist,
bd->x, bd->y, bd->w, bd->h,
x, y, w, h,
&new_x, &new_y, &new_w, &new_h);
eina_list_free(skiplist);
w = new_w;
h = new_h;
e_border_resize_limit(bd, &new_w, &new_h);
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_L) ||
(bd->resize_mode == E_POINTER_RESIZE_BL))
new_x += (w - new_w);
if ((bd->resize_mode == E_POINTER_RESIZE_TL) ||
(bd->resize_mode == E_POINTER_RESIZE_T) ||
(bd->resize_mode == E_POINTER_RESIZE_TR))
new_y += (h - new_h);
e_border_move_resize(bd, new_x, new_y, new_w, new_h);
}
static Eina_Bool
_e_border_shade_animator(void *data)
{
E_Border *bd = data;
E_Event_Border_Simple *ev;
Eina_Bool move = EINA_FALSE;
double dt, val;
double dur = bd->client.h / e_config->border_shade_speed;
dt = ecore_loop_time_get() - bd->shade.start;
val = dt / dur;
if (val < 0.0) val = 0.0;
else if (val > 1.0)
val = 1.0;
if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL, 0.0, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE, 0.0, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_LINEAR)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_ACCELERATE_LOTS)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_ACCELERATE_FACTOR, 1.7, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_DECELERATE_LOTS)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_DECELERATE_FACTOR, 1.7, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_SINUSOIDAL_LOTS)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_SINUSOIDAL_FACTOR, 1.7, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 3.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else if (e_config->border_shade_transition == E_TRANSITION_BOUNCE_LOTS)
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_BOUNCE, 1.2, 5.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
else
{
bd->shade.val =
ecore_animator_pos_map(val, ECORE_POS_MAP_LINEAR, 0.0, 0.0);
if (!bd->shaded) bd->shade.val = 1.0 - bd->shade.val;
}
/* due to M_PI's innacuracy, cos(M_PI/2) != 0.0, so we need this */
if (bd->shade.val < 0.001) bd->shade.val = 0.0;
else if (bd->shade.val > .999)
bd->shade.val = 1.0;
if (bd->shade.dir == E_DIRECTION_UP)
bd->h = bd->client_inset.t + bd->client.h * bd->shade.val;
else if (bd->shade.dir == E_DIRECTION_DOWN)
{
bd->h = bd->client_inset.t + bd->client.h * bd->shade.val;
bd->y = bd->shade.y + bd->client.h * (1 - bd->shade.val);
move = EINA_TRUE;
}
else if (bd->shade.dir == E_DIRECTION_LEFT)
bd->w = bd->client_inset.t + bd->client.w * bd->shade.val;
else if (bd->shade.dir == E_DIRECTION_RIGHT)
{
bd->w = bd->client_inset.t + bd->client.w * bd->shade.val;
bd->x = bd->shade.x + bd->client.w * (1 - bd->shade.val);
move = EINA_TRUE;
}
if (bd->client.shaped)
{
bd->need_shape_merge = 1;
bd->need_shape_export = 1;
}
if (bd->shaped_input)
{
bd->need_shape_merge = 1;
}
BD_CHANGED(bd);
/* we're done */
if (val == 1)
{
bd->shading = 0;
bd->shaded = !(bd->shaded);
bd->changes.shaded = 1;
bd->changes.shading = 1;
bd->shade.anim = NULL;
if (bd->shaded)
edje_object_signal_emit(bd->bg_object, "e,state,shaded", "e");
else
edje_object_signal_emit(bd->bg_object, "e,state,unshaded", "e");
edje_object_message_signal_process(bd->bg_object);
e_border_frame_recalc(bd);
e_border_comp_hidden_set(bd, bd->shaded);
}
if (move)
{
ev = E_NEW(E_Event_Border_Simple, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
ecore_event_add(E_EVENT_BORDER_MOVE, ev, _e_border_event_border_move_free, NULL);
e_container_shape_move(bd->shape, bd->x, bd->y);
}
e_container_shape_resize(bd->shape, bd->w, bd->h);
ev = E_NEW(E_Event_Border_Simple, 1);
ev->border = bd;
e_object_ref(E_OBJECT(bd));
// e_object_breadcrumb_add(E_OBJECT(bd), "border_resize_event");
ecore_event_add(E_EVENT_BORDER_RESIZE, ev, _e_border_event_border_resize_free, NULL);
return (val != 1);
}
static void
_e_border_event_border_resize_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Resize *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_resize_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_move_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Move *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_move_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_add_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Add *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_add_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_remove_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Remove *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_remove_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_show_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Show *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_show_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_hide_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Hide *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_hide_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_iconify_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Iconify *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_iconify_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_uniconify_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Uniconify *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_uniconify_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_stick_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Stick *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_stick_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_unstick_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Unstick *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_unstick_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_zone_set_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Zone_Set *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_zone_set_event");
e_object_unref(E_OBJECT(e->border));
e_object_unref(E_OBJECT(e->zone));
E_FREE(e);
}
static void
_e_border_event_border_desk_set_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Desk_Set *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_desk_set_event");
e_object_unref(E_OBJECT(e->border));
e_object_unref(E_OBJECT(e->desk));
E_FREE(e);
}
static void
_e_border_event_border_stack_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Stack *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_raise_event");
e_object_unref(E_OBJECT(e->border));
if (e->stack)
{
// e_object_breadcrumb_del(E_OBJECT(e->above), "border_raise_event.above");
e_object_unref(E_OBJECT(e->stack));
}
E_FREE(e);
}
static void
_e_border_event_border_icon_change_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Icon_Change *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_title_change_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Title_Change *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_icon_change_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_urgent_change_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Urgent_Change *e;
e = ev;
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_focus_in_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Focus_In *e;
e = ev;
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_focus_out_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Focus_Out *e;
e = ev;
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_property_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Property *e;
e = ev;
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_fullscreen_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Fullscreen *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_fullscreen_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_event_border_unfullscreen_free(void *data __UNUSED__,
void *ev)
{
E_Event_Border_Unfullscreen *e;
e = ev;
// e_object_breadcrumb_del(E_OBJECT(e->border), "border_unfullscreen_event");
e_object_unref(E_OBJECT(e->border));
E_FREE(e);
}
static void
_e_border_zone_update(E_Border *bd)
{
E_Container *con;
Eina_List *l;
E_Zone *zone;
/* still within old zone - leave it there */
if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
bd->zone->x, bd->zone->y, bd->zone->w, bd->zone->h))
return;
/* find a new zone */
con = bd->zone->container;
EINA_LIST_FOREACH(con->zones, l, zone)
{
if (E_INTERSECTS(bd->x, bd->y, bd->w, bd->h,
zone->x, zone->y, zone->w, zone->h))
{
e_border_zone_set(bd, zone);
return;
}
}
}
static int
_e_border_resize_begin(E_Border *bd)
{
if (!bd->lock_user_stacking)
{
if (e_config->border_raise_on_mouse_action)
e_border_raise(bd);
}
if ((bd->shaded) || (bd->shading) ||
(bd->fullscreen) || (bd->lock_user_size))
return 0;
if (!_e_border_action_input_win_new(bd))
{
grabbed = 0;
return 0;
}
if (bd->client.netwm.sync.request)
{
bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
bd->client.netwm.sync.serial = 1;
bd->client.netwm.sync.wait = 0;
bd->client.netwm.sync.send_time = ecore_loop_time_get();
}
_e_border_hook_call(E_BORDER_HOOK_RESIZE_BEGIN, bd);
bdresize = bd;
return 1;
}
static int
_e_border_resize_end(E_Border *bd)
{
if (grabbed)
{
e_grabinput_release(bd->win, bd->win);
grabbed = 0;
}
if (bd->client.netwm.sync.alarm)
{
E_Border_Pending_Move_Resize *pnd;
ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
bd->client.netwm.sync.alarm = 0;
/* resize to last geometry if sync alarm for it was not yet handled */
if (bd->pending_move_resize)
{
BD_CHANGED(bd);
bd->changes.pos = 1;
bd->changes.size = 1;
_e_border_client_move_resize_send(bd);
}
EINA_LIST_FREE(bd->pending_move_resize, pnd)
E_FREE(pnd);
}
e_pointer_mode_pop(bd, bd->resize_mode);
bd->resize_mode = E_POINTER_RESIZE_NONE;
_e_border_hook_call(E_BORDER_HOOK_RESIZE_END, bd);
bdresize = NULL;
/* If this border was maximized, we need to unset Maximized state or
* on restart, E still thinks it's maximized */
if (bd->maximized != E_MAXIMIZE_NONE)
e_hints_window_maximized_set(bd, bd->maximized & E_MAXIMIZE_NONE,
bd->maximized & E_MAXIMIZE_NONE);
return 1;
}
static void
_e_border_resize_update(E_Border *bd)
{
_e_border_hook_call(E_BORDER_HOOK_RESIZE_UPDATE, bd);
}
static int
_e_border_move_begin(E_Border *bd)
{
if (!bd->lock_user_stacking)
{
if (e_config->border_raise_on_mouse_action)
e_border_raise(bd);
}
if ((bd->fullscreen) || (bd->lock_user_location))
return 0;
if (grabbed && !e_grabinput_get(bd->win, 0, bd->win))
{
grabbed = 0;
return 0;
}
#if 0
if (bd->client.netwm.sync.request)
{
bd->client.netwm.sync.alarm = ecore_x_sync_alarm_new(bd->client.netwm.sync.counter);
bd->client.netwm.sync.serial = 0;
bd->client.netwm.sync.wait = 0;
bd->client.netwm.sync.time = ecore_loop_time_get();
}
#endif
_e_border_hook_call(E_BORDER_HOOK_MOVE_BEGIN, bd);
bdmove = bd;
return 1;
}
static int
_e_border_move_end(E_Border *bd)
{
if (grabbed)
{
e_grabinput_release(bd->win, bd->win);
grabbed = 0;
}
#if 0
if (bd->client.netwm.sync.alarm)
{
ecore_x_sync_alarm_free(bd->client.netwm.sync.alarm);
bd->client.netwm.sync.alarm = 0;
}
#endif
e_pointer_mode_pop(bd, E_POINTER_MOVE);
bd->moving = 0;
_e_border_hook_call(E_BORDER_HOOK_MOVE_END, bd);
bdmove = NULL;
return 1;
}
static void
_e_border_move_update(E_Border *bd)
{
_e_border_hook_call(E_BORDER_HOOK_MOVE_UPDATE, bd);
}
static Eina_Bool
_e_border_cb_ping_poller(void *data)
{
E_Border *bd;
bd = data;
if (bd->ping_ok)
{
if (bd->hung)
{
bd->hung = 0;
edje_object_signal_emit(bd->bg_object, "e,state,unhung", "e");
if (bd->kill_timer)
{
ecore_timer_del(bd->kill_timer);
bd->kill_timer = NULL;
}
}
}
else
{
/* if time between last ping and now is greater
* than half the ping interval... */
if ((ecore_loop_time_get() - bd->ping) >
((e_config->ping_clients_interval *
ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
{
if (!bd->hung)
{
bd->hung = 1;
edje_object_signal_emit(bd->bg_object, "e,state,hung", "e");
/* FIXME: if below dialog is up - hide it now */
}
if (bd->delete_requested)
{
/* FIXME: pop up dialog saying app is hung - kill client, or pid */
e_border_act_kill_begin(bd);
}
}
}
bd->ping_poller = NULL;
e_border_ping(bd);
return ECORE_CALLBACK_CANCEL;
}
static Eina_Bool
_e_border_cb_kill_timer(void *data)
{
E_Border *bd;
bd = data;
// dont wait until it's hung -
// if (bd->hung)
// {
if (bd->client.netwm.pid > 1)
kill(bd->client.netwm.pid, SIGKILL);
// }
bd->kill_timer = NULL;
return ECORE_CALLBACK_CANCEL;
}
static Eina_List *_e_border_hooks = NULL;
static int _e_border_hooks_delete = 0;
static int _e_border_hooks_walking = 0;
static void
_e_border_hooks_clean(void)
{
Eina_List *l, *ln;
E_Border_Hook *bh;
EINA_LIST_FOREACH_SAFE(_e_border_hooks, l, ln, bh)
{
if (bh->delete_me)
{
_e_border_hooks = eina_list_remove_list(_e_border_hooks, l);
free(bh);
}
}
}
static void
_e_border_hook_call(E_Border_Hook_Point hookpoint,
void *bd)
{
Eina_List *l;
E_Border_Hook *bh;
_e_border_hooks_walking++;
EINA_LIST_FOREACH(_e_border_hooks, l, bh)
{
if (bh->delete_me) continue;
if (bh->hookpoint == hookpoint) bh->func(bh->data, bd);
}
_e_border_hooks_walking--;
if ((_e_border_hooks_walking == 0) && (_e_border_hooks_delete > 0))
_e_border_hooks_clean();
}
EAPI E_Border_Hook *
e_border_hook_add(E_Border_Hook_Point hookpoint,
void (*func)(void *data,
void *bd),
void *data)
{
E_Border_Hook *bh;
bh = E_NEW(E_Border_Hook, 1);
if (!bh) return NULL;
bh->hookpoint = hookpoint;
bh->func = func;
bh->data = data;
_e_border_hooks = eina_list_append(_e_border_hooks, bh);
return bh;
}
EAPI void
e_border_hook_del(E_Border_Hook *bh)
{
bh->delete_me = 1;
if (_e_border_hooks_walking == 0)
{
_e_border_hooks = eina_list_remove(_e_border_hooks, bh);
free(bh);
}
else
_e_border_hooks_delete++;
}
EAPI void
e_border_focus_track_freeze(void)
{
focus_track_frozen++;
}
EAPI void
e_border_focus_track_thaw(void)
{
focus_track_frozen--;
}
static E_Border *
_e_border_under_pointer_helper(E_Desk *desk, E_Border *exclude, int x, int y)
{
E_Border *bd = NULL, *cbd;
Eina_List *l;
EINA_LIST_FOREACH(e_border_raise_stack_get(), l, cbd)
{
if (!cbd) continue;
/* If a border was specified which should be excluded from the list
* (because it will be closed shortly for example), skip */
if ((exclude) && (cbd == exclude)) continue;
if ((desk) && (cbd->desk != desk)) continue;
if (!E_INSIDE(x, y, cbd->x, cbd->y, cbd->w, cbd->h))
continue;
/* If the layer is higher, the position of the window is higher
* (always on top vs always below) */
if (!bd || (cbd->layer > bd->layer))
{
bd = cbd;
break;
}
}
return bd;
}
EAPI E_Border *
e_border_under_pointer_get(E_Desk *desk,
E_Border *exclude)
{
int x, y;
/* We need to ensure that we can get the container window for the
* zone of either the given desk or the desk of the excluded
* window, so return if neither is given */
if (desk)
ecore_x_pointer_xy_get(desk->zone->container->win, &x, &y);
else if (exclude)
ecore_x_pointer_xy_get(exclude->desk->zone->container->win, &x, &y);
else
return NULL;
return _e_border_under_pointer_helper(desk, exclude, x, y);
}
static Eina_Bool
_e_border_pointer_warp_to_center_timer(void *data __UNUSED__)
{
if (warp_to)
{
int x, y;
double spd;
ecore_x_pointer_xy_get(warp_to_win, &x, &y);
/* move hasn't happened yet */
if ((x == warp_x[1]) && (y == warp_y[1]))
return EINA_TRUE;
if ((abs(x - warp_x[0]) > 5) || (abs(y - warp_y[0]) > 5))
{
/* User moved the mouse, so stop warping */
warp_to = 0;
goto cleanup;
}
spd = e_config->pointer_warp_speed;
warp_x[1] = x = warp_x[0];
warp_y[1] = y = warp_y[0];
warp_x[0] = (x * (1.0 - spd)) + (warp_to_x * spd);
warp_y[0] = (y * (1.0 - spd)) + (warp_to_y * spd);
if ((warp_x[0] == x) && (warp_y[0] == y))
{
warp_x[0] = warp_to_x;
warp_y[0] = warp_to_y;
warp_to = 0;
goto cleanup;
}
ecore_x_pointer_warp(warp_to_win, warp_x[0], warp_y[0]);
return ECORE_CALLBACK_RENEW;
}
cleanup:
if (warp_timer) ecore_timer_del(warp_timer);
warp_timer = NULL;
e_border_focus_lock_set(EINA_FALSE);
if (warp_timer_border)
{
warp_x[0] = warp_x[1] = warp_y[0] = warp_y[1] = -1;
if (warp_timer_border->modal)
{
/* got a modal dialog during pointer warp...whoops */
e_border_raise(warp_timer_border->modal);
warp_timer_border = NULL;
return ECORE_CALLBACK_CANCEL;
}
e_focus_event_mouse_in(warp_timer_border);
if (warp_timer_border->iconic)
{
if (!warp_timer_border->lock_user_iconify)
e_border_uniconify(warp_timer_border);
}
if (warp_timer_border->shaded)
{
if (!warp_timer_border->lock_user_shade)
e_border_unshade(warp_timer_border, warp_timer_border->shade.dir);
}
if (!warp_timer_border->lock_user_stacking)
e_border_raise(warp_timer_border);
if (!warp_timer_border->lock_focus_out)
{
e_border_focus_set(warp_timer_border, 1, 1);
e_border_focus_latest_set(warp_timer_border);
}
warp_timer_border = NULL;
}
return ECORE_CALLBACK_CANCEL;
}
EAPI int
e_border_pointer_warp_to_center_now(E_Border *bd)
{
if (e_config->disable_all_pointer_warps) return 0;
if (warp_timer_border == bd)
{
ecore_x_pointer_warp(warp_to_win, warp_to_x, warp_to_y);
warp_to = 0;
}
else
{
if (e_border_pointer_warp_to_center(bd))
e_border_pointer_warp_to_center_now(bd);
}
return 1;
}
EAPI int
e_border_pointer_warp_to_center(E_Border *bd)
{
int x, y;
E_Border *cbd = NULL;
if (e_config->disable_all_pointer_warps) return 0;
/* Only warp the pointer if it is not already in the area of
* the given border */
ecore_x_pointer_xy_get(bd->zone->container->win, &x, &y);
if ((x >= bd->x) && (x <= (bd->x + bd->w)) &&
(y >= bd->y) && (y <= (bd->y + bd->h)))
{
cbd = _e_border_under_pointer_helper(bd->desk, bd, x, y);
if (cbd == bd) return 0;
}
warp_to_x = bd->x + (bd->w / 2);
if (warp_to_x < (bd->zone->x + 1))
warp_to_x = bd->zone->x + ((bd->x + bd->w - bd->zone->x) / 2);
else if (warp_to_x > (bd->zone->x + bd->zone->w))
warp_to_x = (bd->zone->x + bd->zone->w + bd->x) / 2;
warp_to_y = bd->y + (bd->h / 2);
if (warp_to_y < (bd->zone->y + 1))
warp_to_y = bd->zone->y + ((bd->y + bd->h - bd->zone->y) / 2);
else if (warp_to_y > (bd->zone->y + bd->zone->h))
warp_to_y = (bd->zone->y + bd->zone->h + bd->y) / 2;
/* TODO: handle case where another border is over the exact center,
* find a place where the requested border is not overlapped?
*
if (!cbd) cbd = _e_border_under_pointer_helper(bd->desk, bd, x, y);
if (cbd != bd)
{
}
*/
warp_to = 1;
warp_to_win = bd->zone->container->win;
ecore_x_pointer_xy_get(bd->zone->container->win, &warp_x[0], &warp_y[0]);
if (warp_timer) ecore_timer_del(warp_timer);
warp_timer = ecore_timer_add(0.01, _e_border_pointer_warp_to_center_timer, bd);
warp_timer_border = bd;
e_border_focus_lock_set(EINA_TRUE);
return 1;
}
EAPI void
e_border_comp_hidden_set(E_Border *bd,
Eina_Bool hidden)
{
E_Border *tmp;
Eina_List *l;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
{
if (hidden)
ecore_x_window_hide(tmp->win);
else
ecore_x_window_show(tmp->win);
}
if (bd->comp_hidden == hidden) return;
bd->comp_hidden = hidden;
if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
{
ecore_x_composite_window_events_disable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_TRUE);
}
else
{
ecore_x_composite_window_events_enable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_FALSE);
}
}
EAPI void
e_border_tmp_input_hidden_push(E_Border *bd)
{
E_Border *tmp;
Eina_List *l;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
e_border_tmp_input_hidden_push(tmp);
bd->tmp_input_hidden++;
if (bd->tmp_input_hidden != 1) return;
if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
{
ecore_x_composite_window_events_disable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_TRUE);
}
else
{
_e_border_shape_input_rectangle_set(bd);
ecore_x_window_ignore_set(bd->win, EINA_FALSE);
}
}
EAPI void
e_border_tmp_input_hidden_pop(E_Border *bd)
{
E_Border *tmp;
Eina_List *l;
E_OBJECT_CHECK(bd);
E_OBJECT_TYPE_CHECK(bd, E_BORDER_TYPE);
EINA_LIST_FOREACH(bd->client.e.state.video_child, l, tmp)
e_border_tmp_input_hidden_pop(tmp);
bd->tmp_input_hidden--;
if (bd->tmp_input_hidden != 0) return;
if ((bd->comp_hidden) || (bd->tmp_input_hidden > 0))
{
ecore_x_composite_window_events_disable(bd->win);
ecore_x_window_ignore_set(bd->win, EINA_TRUE);
}
else
{
_e_border_shape_input_rectangle_set(bd);
ecore_x_window_ignore_set(bd->win, EINA_FALSE);
}
}
EAPI void
e_border_activate(E_Border *bd, Eina_Bool just_do_it)
{
if ((e_config->focus_setting == E_FOCUS_NEW_WINDOW) ||
((bd->parent) &&
((e_config->focus_setting == E_FOCUS_NEW_DIALOG) ||
((bd->parent->focused) &&
(e_config->focus_setting == E_FOCUS_NEW_DIALOG_IF_OWNER_FOCUSED)))) ||
(just_do_it))
{
if (bd->iconic)
{
if (e_config->clientlist_warp_to_iconified_desktop == 1)
e_desk_show(bd->desk);
if (!bd->lock_user_iconify)
e_border_uniconify(bd);
}
if ((!bd->iconic) && (!bd->sticky))
e_desk_show(bd->desk);
if (!bd->lock_user_stacking) e_border_raise(bd);
if (!bd->lock_focus_out)
{
/* XXX ooffice does send this request for
config dialogs when the main window gets focus.
causing the pointer to jump back and forth. */
if ((e_config->focus_policy != E_FOCUS_CLICK) && (!bd->new_client) &&
(!e_config->disable_all_pointer_warps) &&
!(bd->client.icccm.name && !strcmp(bd->client.icccm.name, "VCLSalFrame")))
ecore_x_pointer_warp(bd->zone->container->win,
bd->x + (bd->w / 2), bd->y + (bd->h / 2));
e_border_focus_set(bd, 1, 1);
}
}
}
/*vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0*/