You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

6335 lines
217 KiB

#define EXECUTIVE_MODE_ENABLED
#define E_COMP_X
#include "e.h"
#define RANDR_VERSION_1_3 ((1 << 16) | 3)
#define RANDR_VERSION_1_4 ((1 << 16) | 4)
#define GRAV_SET(ec, grav) \
ecore_x_window_gravity_set(e_client_util_pwin_get(ec), grav); \
if (_e_comp_x_client_data_get(ec)->lock_win) ecore_x_window_gravity_set(_e_comp_x_client_data_get(ec)->lock_win, grav);
#ifdef HAVE_WAYLAND
# define E_COMP_X_PIXMAP_CHECK if ((e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) && (!e_client_has_xwindow(ec))) return
#else
# define E_COMP_X_PIXMAP_CHECK if (!e_pixmap_is_x(ec->pixmap)) return
#endif
/* maybe make configurable?
* not sure why anyone would want to change it...
*/
#define MOVE_COUNTER_LIMIT 50
#define PARENT_ACTIVATE_TIME 200
#define PARENT_ACTIVATE_LIMIT 2
EINTERN void _e_main_cb_x_fatal(void *data EINA_UNUSED);
typedef struct _Frame_Extents Frame_Extents;
struct _Frame_Extents
{
int l, r, t, b;
};
struct _E_Comp_X_Data
{
Ecore_X_Window lock_grab_break_wnd;
Eina_List *retry_clients;
Ecore_Timer *retry_timer;
Eina_Bool restack E_BITFIELD;
};
typedef struct Pending_Configure
{
Evas_Point point;
Ecore_X_Window win;
Ecore_Timer *timer;
} Pending_Configure;
static Eina_Hash *pending_configures;
static unsigned int focus_time = 0;
static unsigned int focus_canvas_time = 0;
static Ecore_Timer *focus_timer;
static E_Client *mouse_client;
static Eina_List *handlers = NULL;
static Eina_Hash *clients_win_hash = NULL;
static Eina_Hash *damages_hash = NULL;
static Eina_Hash *frame_extents = NULL;
static Eina_Hash *alarm_hash = NULL;
static Evas_Point mouse_in_coords = {-1, -1};
static Ecore_Job *mouse_in_job;
static E_Client *focus_job_client;
static Ecore_Job *focus_job;
static E_Client *unfocus_job_client;
static Ecore_Job *unfocus_job;
static Ecore_Idle_Enterer *_e_comp_x_post_client_idler = NULL;
static Ecore_Idle_Enterer *_x_idle_flush = NULL;
static Eina_List *post_clients = NULL;
static int _e_comp_x_mapping_change_disabled = 0;
static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
static int screen_size_index = -1;
static Ecore_X_Atom backlight_atom = 0;
static Ecore_Timer *mouse_in_fix_check_timer = NULL;
static Eina_Hash *dead_wins;
static Ecore_Window _e_comp_x_suspend_grabbed; // window grabber for suspending pointer
static void _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec);
static inline E_Comp_X_Client_Data *
_e_comp_x_client_data_get(const E_Client *ec)
{
#ifdef HAVE_WAYLAND
if (!e_pixmap_is_x(ec->pixmap))
return e_comp_wl_client_xwayland_data(ec);
#endif
return ec->comp_data;
}
static Eina_Bool
_e_comp_x_flusher(void *data EINA_UNUSED)
{
ecore_x_flush();
return ECORE_CALLBACK_RENEW;
}
static inline Ecore_X_Window
_e_comp_x_client_window_get(const E_Client *ec)
{
E_Comp_X_Client_Data *cd = _e_comp_x_client_data_get(ec);
if (cd && cd->reparented)
return e_client_util_pwin_get(ec);
return e_client_util_win_get(ec);
}
static void
_e_comp_x_client_damage_add(E_Client *ec)
{
Ecore_X_Window win;
if (_e_comp_x_client_data_get(ec)->damage) return;
win = _e_comp_x_client_window_get(ec);
_e_comp_x_client_data_get(ec)->damage = ecore_x_damage_new(win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
eina_hash_add(damages_hash, &_e_comp_x_client_data_get(ec)->damage, ec);
}
static void
_e_comp_x_focus_check(void)
{
E_Client *focused;
if (stopping || e_comp->nocomp) return;
focused = e_client_focused_get();
/* if there is no new focused or it is a non-X client,
* focus comp canvas on focus-out */
if ((!focused) || (!e_client_has_xwindow(focused)))
{
focus_canvas_time = ecore_x_current_time_get();
focus_time = 0;
if (e_comp->comp_type != E_PIXMAP_TYPE_X)
e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
// this breaks Qt because it seems to create override-redirect popup windows
// that it FOCUSES instead of grabbking the kbd like most other menu windows
// so this causes the parent window to lose focus in a way that then causes
// the popups to dismiss instantly
// e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
// This might be more specific a workaround bit might miss other cases, so keep
// here as an idea and for future reference
else
{
Ecore_X_Window focus_win = ecore_x_window_focus_get();
if (focus_win)
{
if ((ecore_x_window_root_get(focus_win) == focus_win) ||
(!ecore_x_icccm_transient_for_get(focus_win)))
e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
}
else
e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
}
}
}
static void
_e_comp_x_client_modal_setup(E_Client *ec)
{
E_Comp_X_Client_Data *pcd;
ec->parent->modal = ec;
ec->parent->lock_close = 1;
pcd = _e_comp_x_client_data_get(ec->parent);
if (!pcd->lock_win)
{
eina_hash_add(clients_win_hash, &pcd->lock_win, ec->parent);
pcd->lock_win = ecore_x_window_input_new(e_client_util_pwin_get(ec->parent), 0, 0, ec->parent->w, ec->parent->h);
e_comp_ignore_win_add(E_PIXMAP_TYPE_X, pcd->lock_win);
ecore_x_window_show(pcd->lock_win);
ecore_x_icccm_name_class_set(pcd->lock_win, "comp_data->lock_win", "comp_data->lock_win");
}
}
static void
_e_comp_x_client_frame_update(E_Client *ec, int l, int r, int t, int b)
{
ecore_x_netwm_frame_size_set(e_client_util_win_get(ec), l, r, t, b);
ecore_x_e_frame_size_set(e_client_util_win_get(ec), l, r, t, b);
_e_comp_x_client_data_get(ec)->frame_update = 0;
}
static Eina_List *iconshare = NULL;
typedef struct _E_Client_Icon_Entry E_Client_Icon_Entry;
struct _E_Client_Icon_Entry
{
Ecore_X_Icon *icons;
int num_icons;
int ref;
};
static Ecore_X_Icon *
_e_comp_x_client_icon_deduplicate(Ecore_X_Icon *icons, int num_icons)
{
int i;
Eina_List *l;
E_Client_Icon_Entry *ie;
// unless the rest of e uses border icons OTHER than icon #0
// then free the rest that we don't need anymore.
for (i = 1; i < num_icons; i++)
{
E_FREE(icons[i].data);
}
// lookup icon data in icons cache/share
EINA_LIST_FOREACH(iconshare, l, ie)
{
if ((ie->num_icons == num_icons) &&
(num_icons > 0) &&
(ie->icons[0].width == icons[0].width) &&
(ie->icons[0].height == icons[0].height) &&
(!memcmp(ie->icons[0].data, icons[0].data,
icons[0].width * icons[0].height * 4)))
{
// found so free the input icons
for (i = 0; i < num_icons; i++)
free(icons[i].data);
free(icons);
// ref the shared/cached one
ie->ref++;
iconshare = eina_list_promote_list(iconshare, l);
// and return that
return ie->icons;
}
}
// no hit - new entry to cache. add it
ie = calloc(1, sizeof(E_Client_Icon_Entry));
if (ie)
{
ie->icons = icons;
ie->num_icons = num_icons;
ie->ref = 1;
iconshare = eina_list_prepend(iconshare, ie);
}
return icons;
}
static void
_e_comp_x_client_icon_free(Ecore_X_Icon *icons, int num_icons)
{
int i;
Eina_List *l;
E_Client_Icon_Entry *ie;
// lookup in icon share cache
EINA_LIST_FOREACH(iconshare, l, ie)
{
if ((ie->num_icons == num_icons) &&
(num_icons > 0) &&
(ie->icons[0].width == icons[0].width) &&
(ie->icons[0].height == icons[0].height) &&
(!memcmp(ie->icons[0].data, icons[0].data,
icons[0].width * icons[0].height * 4)))
{
// found so deref
ie->ref--;
if (ie->ref <= 0)
{
// no refs left - free the icon from the share/cache
iconshare = eina_list_remove_list(iconshare, l);
for (i = 0; i < ie->num_icons; i++)
free(ie->icons[i].data);
free(ie->icons);
free(ie);
}
return;
}
}
// not found - so just free it ... odd - we should never be here
for (i = 0; i < num_icons; i++)
free(icons[i].data);
free(icons);
}
static void
_e_comp_x_client_event_free(void *d EINA_UNUSED, void *e)
{
E_Event_Client *ev = e;
UNREFD(ev->ec, 1);
e_object_unref(E_OBJECT(ev->ec));
free(ev);
}
static void
_e_comp_x_print_win(Ecore_X_Window win)
{
int x, y, w, h;
Eina_Bool vis;
ecore_x_window_geometry_get(win, &x, &y, &w, &h);
vis = ecore_x_window_visible_get(win);
fprintf(stderr, "%s 0x%x: %d,%d @ %dx%d\n", vis ? "VIS" : "HID", win, x, y, w, h);
}
static void
_e_comp_x_focus_grab(E_Client *ec)
{
if (ec->internal_elm_win) return;
ecore_x_window_button_grab(e_client_util_win_get(ec), 1,
ECORE_X_EVENT_MASK_MOUSE_DOWN |
ECORE_X_EVENT_MASK_MOUSE_UP |
ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
ecore_x_window_button_grab(e_client_util_win_get(ec), 2,
ECORE_X_EVENT_MASK_MOUSE_DOWN |
ECORE_X_EVENT_MASK_MOUSE_UP |
ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
ecore_x_window_button_grab(e_client_util_win_get(ec), 3,
ECORE_X_EVENT_MASK_MOUSE_DOWN |
ECORE_X_EVENT_MASK_MOUSE_UP |
ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
_e_comp_x_client_data_get(ec)->button_grabbed = 1;
}
static void
_e_comp_x_focus_init(E_Client *ec)
{
if (_e_comp_x_client_data_get(ec)->button_grabbed) return;
if (!((e_client_focus_policy_click(ec)) ||
(e_config->always_click_to_raise) ||
(e_config->always_click_to_focus))) return;
_e_comp_x_focus_grab(ec);
}
static void
_e_comp_x_focus_setup(E_Client *ec)
{
if (_e_comp_x_client_data_get(ec)->button_grabbed) return;
if ((!e_client_focus_policy_click(ec)) ||
(e_config->always_click_to_raise) ||
(e_config->always_click_to_focus)) return;
_e_comp_x_focus_grab(ec);
}
static void
_e_comp_x_focus_setdown(E_Client *ec)
{
Ecore_X_Window win, pwin;
if (!_e_comp_x_client_data_get(ec)->button_grabbed) return;
if ((!e_client_focus_policy_click(ec)) ||
(e_config->always_click_to_raise) ||
(e_config->always_click_to_focus)) return;
win = e_client_util_win_get(ec);
pwin = e_client_util_pwin_get(ec);
e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
ecore_x_window_button_ungrab(win, 1, 0, 1);
ecore_x_window_button_ungrab(win, 2, 0, 1);
ecore_x_window_button_ungrab(win, 3, 0, 1);
e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
_e_comp_x_client_data_get(ec)->button_grabbed = 0;
}
static Eina_Bool
_e_comp_x_client_new_helper(E_Client *ec)
{
Ecore_X_Window win = e_client_util_win_get(ec);
int at_num = 0, i;
Ecore_X_Atom *atoms;
if (!ecore_x_window_attributes_get(win, &ec->comp_data->initial_attributes))
{
//CRI("OUCH! FIX THIS!");
DELD(ec, 1);
e_object_del(E_OBJECT(ec));
return EINA_FALSE;
}
if (ec->re_manage && (!ec->comp_data->initial_attributes.visible))
{
/* ain't gonna be no hidden clients on my watch! */
DELD(ec, 1);
e_object_del(E_OBJECT(ec));
return EINA_FALSE;
}
ec->depth = ec->comp_data->initial_attributes.depth;
ec->override = ec->comp_data->initial_attributes.override;
ec->placed |= ec->override;
ec->input_only = ec->comp_data->initial_attributes.input_only;
ec->border_size = ec->comp_data->initial_attributes.border;
ec->icccm.accepts_focus = (!ec->override) && (!ec->input_only);
//INF("NEW CLIENT: %d,%d -> %d,%d", ec->x, ec->y, ec->comp_data->initial_attributes.x, ec->comp_data->initial_attributes.y);
ec->x = ec->client.x = ec->comp_data->initial_attributes.x;
ec->y = ec->client.y = ec->comp_data->initial_attributes.y;
if (ec->override && ((ec->x == -77) && (ec->y == -777)))
{
/* this is the ecore-x private window :/ */
e_comp_ignore_win_add(E_PIXMAP_TYPE_X, win);
DELD(ec, 1);
e_object_del(E_OBJECT(ec));
return EINA_FALSE;
}
if ((!e_client_util_ignored_get(ec)) && (!ec->internal) && (!ec->internal_elm_win))
{
ec->comp_data->need_reparent = 1;
EC_CHANGED(ec);
ec->take_focus = !starting;
}
ec->new_client ^= ec->override;
if (!ec->new_client)
e_comp->new_clients--;
ec->w = ec->client.w = ec->comp_data->initial_attributes.w;
ec->h = ec->client.h = ec->comp_data->initial_attributes.h;
if (!ec->internal)
{
ec->comp_data->pw = ec->w;
ec->comp_data->ph = ec->h;
}
ec->changes.size = 1;
e_pixmap_visual_cmap_set(ec->pixmap, ec->comp_data->initial_attributes.visual, ec->comp_data->initial_attributes.colormap);
if (ec->override && (!ec->internal))
ecore_x_window_shape_events_select(win, 1);
if (ec->override && (!(ec->comp_data->initial_attributes.event_mask.mine & ECORE_X_EVENT_MASK_WINDOW_PROPERTY)))
ecore_x_event_mask_set(win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
atoms = ecore_x_window_prop_list(win, &at_num);
ec->icccm.fetch.command = 1;
if (atoms)
{
Eina_Bool video_parent = EINA_FALSE;
Eina_Bool video_position = EINA_FALSE;
Eina_Bool found_desk = EINA_FALSE;
Eina_Bool found_zone = EINA_FALSE;
/* icccm */
for (i = 0; i < at_num; i++)
{
if (atoms[i] == ECORE_X_ATOM_WM_NAME)
ec->icccm.fetch.title = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
ec->icccm.fetch.name_class = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
ec->icccm.fetch.icon_name = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
ec->icccm.fetch.machine = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
ec->icccm.fetch.hints = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
ec->icccm.fetch.size_pos_hints = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
ec->icccm.fetch.protocol = 1;
else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
ec->mwm.fetch.hints = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
{
ec->icccm.fetch.transient_for = 1;
ec->netwm.fetch.type = 1;
}
else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
ec->icccm.fetch.client_leader = 1;
else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
ec->icccm.fetch.window_role = 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 */
ec->icccm.fetch.title = 0;
ec->netwm.fetch.name = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
{
/* Ignore icccm */
ec->icccm.fetch.icon_name = 0;
ec->netwm.fetch.icon_name = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
{
ec->netwm.fetch.icon = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
{
ec->netwm.fetch.user_time = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
{
DBG("ECORE_X_ATOM_NET_WM_STRUT");
ec->netwm.fetch.strut = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
{
DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
ec->netwm.fetch.strut = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
{
/* Ignore mwm
ec->mwm.fetch.hints = 0;
*/
ec->netwm.fetch.type = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
{
ec->netwm.fetch.state = 1;
}
else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
ec->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)
{
ec->e.fetch.state = 1;
}
/* loop to check for qtopia atoms */
if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
ec->qtopia.fetch.soft_menu = 1;
else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
ec->qtopia.fetch.soft_menus = 1;
/* loop to check for vkbd atoms */
else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
ec->vkbd.fetch.state = 1;
else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
ec->vkbd.fetch.vkbd = 1;
/* loop to check for illume atoms */
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
ec->comp_data->illume.conformant.fetch.conformant = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
ec->comp_data->illume.quickpanel.fetch.state = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
ec->comp_data->illume.quickpanel.fetch.quickpanel = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
ec->comp_data->illume.quickpanel.fetch.priority.major = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
ec->comp_data->illume.quickpanel.fetch.priority.minor = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
ec->comp_data->illume.quickpanel.fetch.zone = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
ec->comp_data->illume.drag.fetch.locked = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
ec->comp_data->illume.drag.fetch.drag = 1;
else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
ec->comp_data->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;
/* loop to check for window profile list atom */
else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
ec->e.fetch.profile = 1;
else if (atoms[i] == ECORE_X_ATOM_E_STACK_TYPE)
ec->e.fetch.stack = 1;
else if (atoms[i] == ATM_GTK_FRAME_EXTENTS)
ec->comp_data->fetch_gtk_frame_extents = 1;
else if (atoms[i] == ATM_STEAM_GAME)
e_hints_window_steam_game_get(ec);
else if (ec->re_manage)
{
if (atoms[i] == E_ATOM_DESKTOP_FILE)
{
char *path = ecore_x_window_prop_string_get(win,
E_ATOM_DESKTOP_FILE);
if (path)
{
ec->desktop = efreet_desktop_get(path);
free(path);
}
}
else if (atoms[i] == E_ATOM_DESK)
found_desk = 1;
else if (atoms[i] == E_ATOM_ZONE)
found_zone = 1;
}
}
if (video_position && video_parent)
{
ec->e.state.video = 1;
ec->e.fetch.video_parent = 1;
ec->e.fetch.video_position = 1;
fprintf(stderr, "We found a video window \\o/ %x\n", win);
}
free(atoms);
if (ec->re_manage && found_desk && found_zone)
{
E_Zone *zone = NULL;
E_Desk *desk = NULL;
unsigned int id, deskxy[2];
int ret;
/* get all information from window before it is
* reset by e_client_new */
ret = ecore_x_window_prop_card32_get(win,
E_ATOM_ZONE,
&id, 1);
if (ret == 1)
zone = e_comp_zone_number_get(id);
if (!zone)
zone = e_zone_current_get();
ret = ecore_x_window_prop_card32_get(win,
E_ATOM_DESK,
deskxy, 2);
if (ret == 2)
desk = e_desk_at_xy_get(zone,
deskxy[0],
deskxy[1]);
if (desk) e_client_desk_set(ec, desk);
}
}
return EINA_TRUE;
}
static E_Client *
_e_comp_x_client_find_by_damage(Ecore_X_Damage damage)
{
return eina_hash_find(damages_hash, &damage);
}
static E_Client *
_e_comp_x_client_find_by_window(Ecore_X_Window win)
{
E_Client *ec;
ec = eina_hash_find(clients_win_hash, &win);
if (ec && e_object_is_del(E_OBJECT(ec))) ec = NULL;
return ec;
}
/*
static E_Client *
_e_comp_x_client_find_all_by_window(Ecore_X_Window win)
{
return eina_hash_find(clients_win_hash, &win);
}
*/
static void
_e_comp_x_add_fail_job(void *d EINA_UNUSED)
{
e_util_dialog_internal
(_("Compositor Warning"),
_("Your display driver does not support OpenGL, GLSL<ps/>"
"shaders or no OpenGL engines were compiled or installed<ps/>"
"for Evas or Ecore-Evas. Falling back to software engine.<ps/>"
"<ps/>"
"You will need an OpenGL 2.0 (or OpenGL ES 2.0) capable<ps/>"
"GPU to use OpenGL with compositing."));
}
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);
// shouldn't 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 E_Client *
_e_comp_x_client_find_by_alarm(Ecore_X_Sync_Alarm al)
{
return eina_hash_find(alarm_hash, &al);
}
static void
_e_comp_x_client_move_resize_send(E_Client *ec)
{
if (ec->internal_elm_win)
ecore_evas_managed_move(e_win_ee_get(ec->internal_elm_win), ec->client.x - ec->x, ec->client.y - ec->y);
ecore_x_icccm_move_resize_send(e_client_util_win_get(ec), ec->client.x, ec->client.y, ec->client.w, ec->client.h);
}
static Eina_Bool
_e_comp_x_post_client_idler_cb(void *d EINA_UNUSED)
{
E_Client *ec;
//INF("POST IDLER");
EINA_LIST_FREE(post_clients, ec)
{
Ecore_X_Window win, twin;
if (e_object_is_del(E_OBJECT(ec)) || (!_e_comp_x_client_data_get(ec))) continue;
win = _e_comp_x_client_window_get(ec);
if (ec->post_move)
{
E_Client *tmp;
Eina_List *l;
EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
{
twin = _e_comp_x_client_window_get(tmp);
ecore_x_window_move(twin,
ec->client.x +
tmp->e.state.video_position.x,
ec->client.y +
tmp->e.state.video_position.y);
}
}
if (ec->e.state.video)
{
E_Client *parent;
parent = ec->e.state.video_parent_client;
twin = _e_comp_x_client_window_get(parent);
ecore_x_window_move(twin,
parent->client.x +
ec->e.state.video_position.x,
parent->client.y +
ec->e.state.video_position.y);
}
else if (ec->shading)
{
// do nothing
}
else if ((ec->post_move) && (ec->post_resize))
{
//INF("X MVRSZ");
ecore_x_window_move_resize(win,
ec->client.x,
ec->client.y,
ec->client.w,
ec->client.h);
if (_e_comp_x_client_data_get(ec)->reparented)
ecore_x_window_move_resize(e_client_util_win_get(ec), 0, 0,
ec->client.w,
ec->client.h);
}
else if (ec->post_move)
{
//INF("X MV");
ecore_x_window_move(win, ec->client.x, ec->client.y);
}
else if (ec->post_resize)
{
//INF("X RSZ: %dx%d (REAL: %dx%d)", ec->client.w, ec->client.h, ec->w, ec->h);
ecore_x_window_resize(win,
ec->client.w, ec->client.h);
if (_e_comp_x_client_data_get(ec)->reparented)
ecore_x_window_move_resize(e_client_util_win_get(ec), 0, 0,
ec->client.w, ec->client.h);
}
if ((!ec->shading) && (!ec->shaded))
{
if (ec->post_resize)
{
if (ec->netwm.sync.request && (e_comp->comp_type == E_PIXMAP_TYPE_X))
{
//INF("NETWM SYNC: %p", ec);
ec->netwm.sync.wait++;
ecore_x_netwm_sync_request_send(e_client_util_win_get(ec),
ec->netwm.sync.serial++);
}
}
if (ec->post_move || ec->post_resize)
_e_comp_x_client_move_resize_send(ec);
}
if (ec->e.state.video)
{
fprintf(stderr, "VIDEO %p: [%i, %i] [%i, %i]\n",
ec,
ec->e.state.video_parent_client->client.x +
ec->e.state.video_position.x,
ec->e.state.video_parent_client->client.y +
ec->e.state.video_position.y,
ec->w, ec->h);
}
if (ec->netwm.opacity_changed)
{
unsigned int opacity;
int op;
evas_object_color_get(ec->frame, NULL, NULL, NULL, &op);
ec->netwm.opacity = op;
opacity = (op << 24) | (op << 16) | (op << 8) | op;
ecore_x_window_prop_card32_set(e_client_util_win_get(ec), ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, &opacity, 1);
/* flag gets unset in property cb to avoid fetching opacity after we just set it */
}
if (e_pixmap_is_x(ec->pixmap) && ec->post_resize)
{
e_pixmap_dirty(ec->pixmap);
e_comp_object_render_update_del(ec->frame);
if (!ec->internal)
{
_e_comp_x_client_data_get(ec)->pw = ec->client.w;
_e_comp_x_client_data_get(ec)->ph = ec->client.h;
}
}
ec->post_move = 0;
ec->post_resize = 0;
}
if (e_comp_x->restack && (!e_comp->new_clients))
{
e_hints_client_stacking_set();
e_comp_x->restack = 0;
}
_e_comp_x_post_client_idler = NULL;
return EINA_FALSE;
}
static void
_e_comp_x_post_client_idler_add(E_Client *ec)
{
if (!_e_comp_x_post_client_idler)
_e_comp_x_post_client_idler = ecore_idle_enterer_add(_e_comp_x_post_client_idler_cb, NULL);
if (!ec) CRI("ACK!");
//INF("POST IDLE: %p", ec);
if (!eina_list_data_find(post_clients, ec))
post_clients = eina_list_append(post_clients, ec);
}
static void
_e_comp_x_client_stack(E_Client *ec)
{
E_Client *ec2;
Ecore_X_Window_Stack_Mode mode = ECORE_X_WINDOW_STACK_BELOW;
Ecore_X_Window cwin, win = 0;
Eina_List *l;
if (ec->override && (!ec->internal)) return; //can't restack these
if (e_client_is_stacking(ec)) return;
if (!_e_comp_x_client_data_get(ec)) return;
if (_e_comp_x_client_data_get(ec)->unredirected_single) return;
cwin = _e_comp_x_client_window_get(ec);
ecore_x_window_shadow_tree_flush();
/* try stacking below */
if (e_comp->nocomp_ec && e_comp->nocomp_ec->comp_data && (ec != e_comp->nocomp_ec))
win = _e_comp_x_client_window_get(e_comp->nocomp_ec);
else
{
ec2 = ec;
do
{
ec2 = e_client_above_get(ec2);
if (ec2 && e_client_has_xwindow(ec2) && ec2->comp_data && (!ec2->new_client) &&
(e_client_is_stacking(ec2) || ((!ec2->override) || ec2->internal)))
{
if (ec2->layer != ec->layer) break;
if (_e_comp_x_client_data_get(ec2)->need_reparent && (!_e_comp_x_client_data_get(ec2)->reparented)) continue;
win = _e_comp_x_client_window_get(ec2);
}
} while (ec2 && (!win));
}
/* try stacking above */
if (!win)
{
ec2 = ec;
do
{
ec2 = e_client_below_get(ec2);
if (ec2 && e_client_has_xwindow(ec2) && ec2->comp_data && (!ec2->new_client) &&
(e_client_is_stacking(ec2) || ((!ec2->override) || ec2->internal)))
{
if (ec2->layer != ec->layer) break;
if (_e_comp_x_client_data_get(ec2)->need_reparent && (!_e_comp_x_client_data_get(ec2)->reparented)) continue;
win = _e_comp_x_client_window_get(ec2);
mode = ECORE_X_WINDOW_STACK_ABOVE;
}
} while (ec2 && (!win));
}
/* just layer stack */
if (!win)
{
win = e_comp->layers[e_comp_canvas_layer_map(ec->layer)].win;
mode = ECORE_X_WINDOW_STACK_BELOW;
}
ecore_x_window_configure(cwin,
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0, win, mode);
_e_comp_x_post_client_idler_add(ec);
e_comp_x->restack = 1;
EINA_LIST_FOREACH(ec->e.state.video_child, l, ec2)
evas_object_stack_below(ec2->frame, ec->frame);
}
static E_Client *
_e_comp_x_client_new(Ecore_X_Window win, Eina_Bool first)
{
E_Pixmap *cp;
E_Client *ec;
cp = e_pixmap_new(E_PIXMAP_TYPE_X, win);
EINA_SAFETY_ON_NULL_RETURN_VAL(cp, NULL);
ec = e_client_new(cp, first, 0);
return ec;
}
static void
_e_comp_x_client_pri_raise(E_Client *ec)
{
if (ec->netwm.pid <= 0) return;
if (ec->netwm.pid == getpid()) return;
_pri_adj(ec->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",
// ec->netwm.pid, e_client_util_name_get(ec));
}
static void
_e_comp_x_client_pri_norm(E_Client *ec)
{
if (ec->netwm.pid <= 0) return;
if (ec->netwm.pid == getpid()) return;
_pri_adj(ec->netwm.pid,
e_config->priority, 1, EINA_FALSE,
// EINA_TRUE, EINA_TRUE);
EINA_TRUE, EINA_FALSE);
// printf("WIN: pid %i, title %s (NORMAL)\n",
// ec->netwm.pid, e_client_util_name_get(ec));
}
static void
_e_comp_x_client_shape_input_rectangle_set(E_Client *ec)
{
Ecore_X_Window win = e_client_util_pwin_get(ec);
if (ec->override || (!_e_comp_x_client_data_get(ec)->reparented)) return;
if (ec->visible && (!ec->comp_hidden))
ecore_x_composite_window_events_enable(win);
else
ecore_x_composite_window_events_disable(win);
}
static void
_e_comp_x_evas_color_set_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
int a;
if (!_e_comp_x_client_data_get(ec)) return;
evas_object_color_get(obj, NULL, NULL, NULL, &a);
if (a == ec->netwm.opacity) return;
ec->netwm.opacity_changed = 1;
_e_comp_x_post_client_idler_add(ec);
}
static void
_e_comp_x_evas_ping_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
ecore_x_netwm_ping_send(e_client_util_win_get(ec));
}
static void
_e_comp_x_evas_kill_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
ecore_x_kill(e_client_util_win_get(ec));
}
static void
_e_comp_x_evas_delete_request_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
if (ec->netwm.ping)
e_client_ping(ec);
ecore_x_window_delete_request_send(e_client_util_win_get(ec));
}
static void
_e_comp_x_evas_comp_hidden_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *tmp, *ec = data;
Eina_List *l;
Ecore_X_Window win;
if (!_e_comp_x_client_data_get(ec)) return;
if (_e_comp_x_client_data_get(ec)->need_reparent) return;
win = _e_comp_x_client_window_get(ec);
EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
{
Ecore_X_Window cwin;
cwin = _e_comp_x_client_window_get(tmp);
if (ec->comp_hidden)
ecore_x_window_hide(cwin);
else
ecore_x_window_show(cwin);
}
if ((ec->internal) && (win == e_client_util_win_get(ec))) return;
if (!ec->override)
{
if (ec->comp_hidden)
ecore_x_composite_window_events_disable(win);
else
ecore_x_composite_window_events_enable(win);
}
ecore_x_window_ignore_set(win, ec->comp_hidden);
}
static void
_e_comp_x_evas_shade_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
Eina_List *l;
E_Client *tmp;
if (!_e_comp_x_client_data_get(ec)) return;
EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
ecore_x_window_hide(e_client_util_pwin_get(tmp));
ecore_x_window_shadow_tree_flush();
}
static void
_e_comp_x_evas_frame_recalc_cb(void *data, Evas_Object *obj, void *event_info)
{
E_Client *ec = data;
E_Comp_Object_Frame *fr = event_info;
if (!_e_comp_x_client_data_get(ec)) return;
if (evas_object_visible_get(obj))
_e_comp_x_client_frame_update(ec, fr->l, fr->r, fr->t, fr->b);
else
_e_comp_x_client_data_get(ec)->frame_update = 1;
ec->post_move = ec->post_resize = 1;
_e_comp_x_post_client_idler_add(ec);
}
static void
_e_comp_x_evas_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
if (_e_comp_x_client_data_get(ec)->moving && (!_e_comp_x_client_data_get(ec)->unredirected_single))
{
if (_e_comp_x_client_data_get(ec)->move_counter++ < MOVE_COUNTER_LIMIT) return;
_e_comp_x_client_data_get(ec)->move_counter = 0;
}
ecore_x_window_shadow_tree_flush();
ec->post_move = 1;
_e_comp_x_post_client_idler_add(ec);
}
static void
_e_comp_x_evas_resize_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
if (ec->shading || ec->shaded) return;
if (!e_pixmap_size_changed(ec->pixmap, ec->client.w, ec->client.h)) return;
ecore_x_window_shadow_tree_flush();
if (ec->e.state.video)
{
if (ec->e.state.video_position.updated)
{
ecore_x_window_move(e_client_util_pwin_get(ec),
ec->e.state.video_parent_client->client.x +
ec->e.state.video_position.x,
ec->e.state.video_parent_client->client.y +
ec->e.state.video_position.y);
ec->e.state.video_position.updated = 0;
}
}
else if (ec->changes.pos)
{
E_Client *tmp;
Eina_List *l;
EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
ecore_x_window_move(e_client_util_pwin_get(tmp),
ec->client.x + tmp->e.state.video_position.x,
ec->client.y + tmp->e.state.video_position.y);
}
ec->post_resize = 1;
if (e_pixmap_is_x(ec->pixmap))
e_comp_object_render_update_del(ec->frame);
_e_comp_x_post_client_idler_add(ec);
}
static void
_e_comp_x_client_hide(E_Client *ec)
{
unsigned int visible = 0;
ecore_x_window_shadow_tree_flush();
if ((!ec->iconic) && (!ec->override))
ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_MAPPED, &visible, 1);
_e_comp_x_client_data_get(ec)->iconic = ec->iconic
// XXX: if we tell apps they are iconic.. they may stop rendering and this
// means our miniatures we use in ibar, ibox and winlist alt-tab dont udpate
// ... we could i guess setn fake wm state changes to normal when these are
// visible and then toggle iconic on and off while still visually hiding
// the client... but clients that assume they will be iconic when they ask
// are mistaken ... so for now disable this until we have a debate on it
// && (!e_comp_object_mirror_visibility_check(ec->frame))
;
ec->netwm.state.hidden = 1;
e_hints_window_state_set(ec);
if (ec->unredirected_single || _e_comp_x_client_data_get(ec)->iconic)
ecore_x_window_hide(_e_comp_x_client_window_get(ec));
if (_e_comp_x_client_data_get(ec)->iconic)
e_hints_window_iconic_set(ec);
}
static void
_e_comp_x_evas_hide_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data, *tmp;
Eina_List *l;
if (ec == mouse_client)
{
mouse_client = NULL;
E_FREE_FUNC(mouse_in_job, ecore_job_del);
}
if (!_e_comp_x_client_data_get(ec)) return; // already deleted, happens with internal wins
_e_comp_x_client_hide(ec);
EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
evas_object_hide(tmp->frame);
if (e_comp_config_get()->send_flush)
ecore_x_e_comp_flush_send(e_client_util_win_get(ec));
if (e_comp_config_get()->send_dump)
ecore_x_e_comp_dump_send(e_client_util_win_get(ec));
}
static void
_e_comp_x_client_show(E_Client *ec)
{
unsigned int visible = 1;
Ecore_X_Window win;
win = e_client_util_win_get(ec);
ecore_x_window_shadow_tree_flush();
if ((!_e_comp_x_client_data_get(ec)->need_reparent) && (!ec->override))
ecore_x_window_show(win);
if (ec->unredirected_single || _e_comp_x_client_data_get(ec)->iconic)
{
e_pixmap_clear(ec->pixmap);
ecore_x_window_show(_e_comp_x_client_window_get(ec));
_e_comp_x_client_data_get(ec)->iconic = 0;
}
ec->netwm.state.hidden = 0;
e_hints_window_state_set(ec);
if (!ec->override)
e_hints_window_visible_set(ec);
ecore_x_window_prop_card32_set(win, E_ATOM_MAPPED, &visible, 1);
ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
}
static void
_e_comp_x_evas_show_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data, *tmp;
Eina_List *l;
if (!_e_comp_x_client_data_get(ec)) return;
_e_comp_x_client_show(ec);
if (_e_comp_x_client_data_get(ec)->frame_update)
{
int ll, r, t, b;
e_comp_object_frame_geometry_get(obj, &ll, &r, &t, &b);
_e_comp_x_client_frame_update(ec, ll, r, t, b);
}
EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
{
evas_object_show(tmp->frame);
ecore_x_window_show(e_client_util_pwin_get(tmp));
}
}
static void
_e_comp_x_evas_stack_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
{
if (evas_object_data_get(obj, "client_restack"))
_e_comp_x_client_stack(data);
}
static void
_e_comp_x_evas_unfullscreen_zoom_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
if ((screen_size.width != -1) && (screen_size.height != -1))
{
ecore_x_randr_screen_primary_output_size_set(e_comp->root,
screen_size_index);
screen_size.width = -1;
screen_size.height = -1;
}
}
static void
_e_comp_x_evas_fullscreen_zoom_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
Ecore_X_Randr_Screen_Size_MM *sizes;
int num_sizes, i, best_size_index = 0;
ecore_x_randr_screen_primary_output_current_size_get(e_comp->root,
&screen_size.width,
&screen_size.height,
NULL, NULL, NULL);
sizes = ecore_x_randr_screen_primary_output_sizes_get(e_comp->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 > ec->w) && (sizes[i].height > ec->h))
{
dist = (sizes[i].width * sizes[i].height) - (ec->w * ec->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(e_comp->root,
best_size_index))
screen_size_index = best_size_index;
evas_object_geometry_set(ec->frame, 0, 0, best_size.width, best_size.height);
}
else
{
screen_size.width = -1;
screen_size.height = -1;
evas_object_geometry_set(ec->frame, 0, 0, ec->zone->w, ec->zone->h);
}
free(sizes);
}
else
{
evas_object_geometry_set(ec->frame, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h);
}
}
static Eina_Bool
_e_comp_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Destroy *ev)
{
E_Client *ec;
//INF("X DESTROY: %u", ev->win);
e_comp_ignore_win_del(E_PIXMAP_TYPE_X, ev->win);
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec)
{
if (!e_comp_x->retry_clients) return ECORE_CALLBACK_RENEW;
e_comp_x->retry_clients = eina_list_remove(e_comp_x->retry_clients, (uintptr_t*)(unsigned long)ev->win);
if (!e_comp_x->retry_clients)
E_FREE_FUNC(e_comp_x->retry_timer, ecore_timer_del);
return ECORE_CALLBACK_PASS_ON;
}
if (_e_comp_x_client_data_get(ec))
{
if (_e_comp_x_client_data_get(ec)->reparented)
e_client_comp_hidden_set(ec, 1);
evas_object_pass_events_set(ec->frame, 1);
evas_object_hide(ec->frame);
_e_comp_x_client_data_get(ec)->deleted = 1;
DELD(ec, 2);
e_object_del(E_OBJECT(ec));
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Resize_Request *ev)
{
E_Client *ec;
int w, h;
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec)
{
if (!e_comp_find_by_window(ev->win)) ecore_x_window_resize(ev->win, ev->w, ev->h);
return ECORE_CALLBACK_PASS_ON;
}
w = ev->w, h = ev->h;
if (ec->zone && (e_config->geometry_auto_resize_limit == 1))
{
int zx, zy, zw, zh;
e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
if (w > zw)
w = zw;
if (h > zh)
h = zh;
}
if ((w != ec->w) || (h != ec->h))
{
evas_object_resize(ec->frame, w, h);
}
return ECORE_CALLBACK_RENEW;
}
static void
_e_comp_x_evas_mirror_hidden(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
if ((!ec->iconic) || (!_e_comp_x_client_data_get(ec)->iconic)) return;
_e_comp_x_client_hide(ec);
}
static void
_e_comp_x_evas_mirror_visible(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
E_Client *ec = data;
if (!_e_comp_x_client_data_get(ec)) return;
if ((!ec->iconic) || _e_comp_x_client_data_get(ec)->iconic) return;
_e_comp_x_client_show(ec);
}
static void
_e_comp_x_client_evas_init(E_Client *ec)
{
if (_e_comp_x_client_data_get(ec)->evas_init) return;
_e_comp_x_client_data_get(ec)->evas_init = 1;
evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_comp_x_evas_stack_cb, ec);
evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_comp_x_evas_show_cb, ec);
evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_comp_x_evas_hide_cb, ec);
if (!ec->override)
{
evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_comp_x_evas_move_cb, ec);
evas_object_smart_callback_add(ec->frame, "client_resize", _e_comp_x_evas_resize_cb, ec);
}
evas_object_smart_callback_add(ec->frame, "frame_recalc_done", _e_comp_x_evas_frame_recalc_cb, ec);
evas_object_smart_callback_add(ec->frame, "shade_done", _e_comp_x_evas_shade_cb, ec);
evas_object_smart_callback_add(ec->frame, "comp_hidden", _e_comp_x_evas_comp_hidden_cb, ec);
evas_object_smart_callback_add(ec->frame, "delete_request", _e_comp_x_evas_delete_request_cb, ec);
evas_object_smart_callback_add(ec->frame, "kill_request", _e_comp_x_evas_kill_cb, ec);
evas_object_smart_callback_add(ec->frame, "ping", _e_comp_x_evas_ping_cb, ec);
evas_object_smart_callback_add(ec->frame, "color_set", _e_comp_x_evas_color_set_cb, ec);
evas_object_smart_callback_add(ec->frame, "fullscreen_zoom", _e_comp_x_evas_fullscreen_zoom_cb, ec);
evas_object_smart_callback_add(ec->frame, "unfullscreen_zoom", _e_comp_x_evas_unfullscreen_zoom_cb, ec);
evas_object_smart_callback_add(ec->frame, "visibility_force", _e_comp_x_evas_mirror_visible, ec);
evas_object_smart_callback_add(ec->frame, "visibility_normal", _e_comp_x_evas_mirror_hidden, ec);
/* force apply this since we haven't set up our smart cb previously */
_e_comp_x_evas_comp_hidden_cb(ec, NULL, NULL);
}
static Eina_Bool
_e_comp_x_object_add(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
{
E_Client *ec;
ec = e_comp_object_client_get(ev->comp_object);
if ((!ec) || e_object_is_del(E_OBJECT(ec)) || ec->re_manage) return ECORE_CALLBACK_RENEW;
E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
_e_comp_x_client_evas_init(ec);
_e_comp_x_client_stack(ec);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_comp_x_show_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Show_Request *ev)
{
E_Client *ec;
//INF("X SHOW REQ: %u", ev->win);
ec = _e_comp_x_client_find_by_window(ev->win);
if (e_comp_ignore_win_find(ev->win) ||
(ec && (ec->ignored || ec->override)) ||
(!e_comp_find_by_window(ev->parent)) ||
(ev->parent != e_comp->root))
{
if ((!ec) && (!eina_hash_find(dead_wins, &ev->parent)))
{
ecore_x_window_show(ev->win);
return ECORE_CALLBACK_RENEW;
}
}
if (!ec)
ec = _e_comp_x_client_new(ev->win, 0);
if (!ec)
{
ecore_x_window_show(ev->win);
return ECORE_CALLBACK_RENEW;
}
if ((e_comp->comp_type != E_PIXMAP_TYPE_X) && ec->ignored)
{
ec->visible = 1;
if (ec->comp_data->need_reparent)
_e_comp_x_hook_client_pre_frame_assign(NULL, ec);
else
ecore_x_window_show(ev->win);
return ECORE_CALLBACK_RENEW;
}
if ((!_e_comp_x_client_data_get(ec)->reparented) && (!e_client_util_ignored_get(ec)))
{
if (!ec->override)
_e_comp_x_client_data_get(ec)->need_reparent = 1;
ec->visible = 1;
EC_CHANGED(ec);
return ECORE_CALLBACK_RENEW;
}
if (ec->iconic)
{
if (!ec->lock_client_iconify)
e_client_uniconify(ec);
}
else
{
/* FIXME: make client "urgent" for a bit - it wants attention */
/* e_client_show(ec); */
if (!ec->lock_client_stacking)
evas_object_raise(ec->frame);
}
return ECORE_CALLBACK_RENEW;
}
static void
_e_comp_x_show_helper(E_Client *ec)
{
if ((!ec->override) && (!ec->re_manage) && (!_e_comp_x_client_data_get(ec)->first_map) &&
(!_e_comp_x_client_data_get(ec)->reparented) && (!_e_comp_x_client_data_get(ec)->need_reparent))
{
/* this is most likely an internal window */
_e_comp_x_client_data_get(ec)->need_reparent = 1;
ec->visible = 1;
if (ec->internal_elm_win)
ec->take_focus = 1;
EC_CHANGED(ec);
}
else if (ec->override)
{
if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
{
ec->visible = 1;
return;
}
ec->redirected = !ec->input_only;
ec->changes.visible = ec->visible = 1;
EC_CHANGED(ec);
if (!_e_comp_x_client_data_get(ec)->first_map)
_e_comp_x_client_evas_init(ec);
}
if (!ec->input_only)
_e_comp_x_client_damage_add(ec);
if (!_e_comp_x_client_data_get(ec)->need_reparent)
{
e_pixmap_usable_set(ec->pixmap, 1);
if (ec->hidden || ec->iconic)
{
evas_object_hide(ec->frame);
e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
}
else if (ec->override || (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
evas_object_show(ec->frame);
_e_comp_x_client_data_get(ec)->first_map = 1;
if (ec->internal_elm_win)
{
_e_comp_x_post_client_idler_add(ec);
ec->post_move = 1;
ec->post_resize = 1;
e_comp_x->restack = 1;
}
}
}
static Eina_Bool
_e_comp_x_show_retry(void *data EINA_UNUSED)
{
uintptr_t *win;
EINA_LIST_FREE(e_comp_x->retry_clients, win)
{
E_Client *ec;
ec = _e_comp_x_client_new((Ecore_X_Window)(uintptr_t)win, 0);
if (ec) _e_comp_x_show_helper(ec);
}
e_comp_x->retry_timer = NULL;
return EINA_FALSE;
}
static Eina_Bool
_e_comp_x_show(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Show *ev)
{
E_Client *ec;
//INF("X SHOW: %u", ev->win);
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec)
{
E_Comp *c;
if (e_comp_ignore_win_find(ev->win)) return ECORE_CALLBACK_RENEW;
c = e_comp_find_by_window(ev->event_win);
if (!c) return ECORE_CALLBACK_RENEW;
if (ev->event_win != e_comp->root) return ECORE_CALLBACK_RENEW;
if ((c->win == ev->win) || (c->ee_win == ev->win) ||
(c->root == ev->win) || (c->cm_selection == ev->win)) return ECORE_CALLBACK_RENEW;
/* some window which we haven't made a client for yet but need to */
ec = _e_comp_x_client_new(ev->win, 0);
if (!ec)
{
if (c->x_comp_data->retry_timer)
ecore_timer_loop_reset(c->x_comp_data->retry_timer);
else
c->x_comp_data->retry_timer = ecore_timer_loop_add(0.02, _e_comp_x_show_retry, c);
c->x_comp_data->retry_clients = eina_list_append(c->x_comp_data->retry_clients, (uintptr_t*)(unsigned long)ev->win);
return ECORE_CALLBACK_RENEW;
}
}
else if (e_object_is_del(E_OBJECT(ec)) || ec->already_unparented)
return ECORE_CALLBACK_RENEW;
_e_comp_x_show_helper(ec);
if (ec->internal || (!ec->override))
_e_comp_x_client_stack(ec);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_comp_x_hide(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Hide *ev)
{
E_Client *ec;
Eina_Bool hid = EINA_FALSE;
//INF("X HIDE: %u", ev->win);
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec)
{
if (!e_comp_x->retry_clients) return ECORE_CALLBACK_RENEW;
e_comp_x->retry_clients = eina_list_remove(e_comp_x->retry_clients, (uintptr_t*)(unsigned long)ev->win);
if (!e_comp_x->retry_clients)
E_FREE_FUNC(e_comp_x->retry_timer, ecore_timer_del);
return ECORE_CALLBACK_PASS_ON;
}
if ((!ec->visible) || (ec->hidden && ec->unredirected_single))
{
//INF("IGNORED");
return ECORE_CALLBACK_PASS_ON;
}
if (ev->win != ev->event_win)
{
if ((!ec->override) && (!ev->send_event)) return ECORE_CALLBACK_PASS_ON;
}
if (ec->ignore_first_unmap > 0)
{
ec->ignore_first_unmap--;
return ECORE_CALLBACK_PASS_ON;
}
/* Don't delete hidden or iconified windows */
if (ec->iconic)
{
/* Only hide the border if it is visible */
hid = EINA_TRUE;
evas_object_hide(ec->frame);
}
else
{
hid = EINA_TRUE;
evas_object_hide(ec->frame);
if (ec->internal)
e_hints_window_hidden_set(ec);
else
{
if (ec->exe_inst && ec->exe_inst->exe)
ec->exe_inst->phony = 0;
DELD(ec, 3);
e_object_del(E_OBJECT(ec));
}
}
if (hid)
_e_comp_x_focus_check();
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_reparent(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Reparent *ev)
{
E_Client *ec;
ec = _e_comp_x_client_find_by_window(ev->win);
if ((!ec) || (ev->win == e_client_util_pwin_get(ec))) return ECORE_CALLBACK_PASS_ON;
DBG("== repar [%u] to [%u]", ev->win, ev->parent);
/* FIXME: this is almost definitely wrong */
if (ev->parent != e_client_util_pwin_get(ec))
{
e_pixmap_parent_window_set(ec->pixmap, ev->parent);
if (!e_object_is_del(E_OBJECT(ec)))
e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure *ev)
{
E_Client *ec;
Eina_Bool move, resize;
if (e_comp_find_by_window(ev->win))
{
// do not handle this here - use randr events
//e_comp_canvas_resize(ev->w, ev->h);
return ECORE_CALLBACK_RENEW;
}
ec = _e_comp_x_client_find_by_window(ev->win);
if ((!ec) || (!ec->override) || (!ev->override) || e_client_is_stacking(ec)) return ECORE_CALLBACK_PASS_ON;
//INF("configure %p: %d,%d %dx%d", ec, ev->x, ev->y, ev->w, ev->h);
if (ev->abovewin == 0)
{
// forcibly lower the window as it's not above anything
if (e_client_below_get(ec)) evas_object_lower(ec->frame);
}
else
{
E_Client *ec_above = _e_comp_x_client_find_by_window(ev->abovewin);
// if we find the client the window is above
if (ec_above)
{
// if the window to stack above is a layer marker window/client
// then we need to find the next one up and stack below that
// because the ec_above will be one layer below as layer marker
// is at the top of a layer
if (e_client_is_stacking(ec_above))
{
E_Client *ec_next_up = e_client_above_get(ec_above);
// stacking under the next win up == above ec_above
if (ec_next_up)
{
evas_object_layer_set(ec->frame, ec_next_up->layer);
evas_object_stack_below(ec->frame, ec_next_up->frame);
}
else // no marker above, so live on the same layer - on top
{
evas_object_layer_set(ec->frame, ec_above->layer);
}
}
// if it's above is a regular win
else
{
// if the layer obj is not right below already...
evas_object_layer_set(ec->frame, ec_above->layer);
evas_object_stack_above(ec->frame, ec_above->frame);
}
}
// we didnt find the client it's above - so stuff this on top
else
{
evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO);
}
}
move = (ec->client.x != ev->x) || (ec->client.y != ev->y);
resize = (ec->client.w != ev->w) || (ec->client.h != ev->h);
if (!ec->internal)
_e_comp_x_client_data_get(ec)->pw = ev->w, _e_comp_x_client_data_get(ec)->ph = ev->h;
EINA_RECTANGLE_SET(&ec->client, ev->x, ev->y, ev->w, ev->h);
if (move)
evas_object_move(ec->frame, ev->x, ev->y);
if (resize && e_pixmap_is_x(ec->pixmap))
{
e_pixmap_dirty(ec->pixmap);
evas_object_resize(ec->frame, ev->w, ev->h);
}
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_comp_x_configure_request_timer(void *d)
{
Pending_Configure *pc = d;
eina_hash_list_remove(pending_configures, &pc->win, pc);
free(pc);
return EINA_FALSE;
}
static Eina_Bool
_e_comp_x_configure_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure_Request *ev)
{
E_Client *ec;
Eina_Bool move = EINA_FALSE, resize = EINA_FALSE;
int ox, oy, ow, oh;
int x, y, w, h;
// printf("configure request {0x%08x} %4i,%4i %4ix%4i b=%i [%c%c%c%c]\n",
// ev->win, ev->x, ev->y, ev->w, ev->h, ev->border,
// ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X ? 'x' : ' ',
// ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y ? 'y' : ' ',
// ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W ? 'w' : ' ',
// ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H ? 'h' : ' ');
if (e_comp_find_by_window(ev->win)) return ECORE_CALLBACK_RENEW;
ec = _e_comp_x_client_find_by_window(ev->win);
/* pass through requests for windows we haven't/won't reparent yet */
if (ec && (!_e_comp_x_client_data_get(ec)->need_reparent) && (!_e_comp_x_client_data_get(ec)->reparented))
{
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
_e_comp_x_client_data_get(ec)->initial_attributes.x = ev->x;
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
_e_comp_x_client_data_get(ec)->initial_attributes.y = ev->y;
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
ec->w = ec->client.w = _e_comp_x_client_data_get(ec)->initial_attributes.w = ev->w;
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
ec->h = ec->client.h = _e_comp_x_client_data_get(ec)->initial_attributes.h = ev->h;
ec->border_size = ev->border;
ec->changes.size = 1;
ec = NULL;
}
if (!ec)
{
if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
(ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
{
Pending_Configure *pc = E_NEW(Pending_Configure, 1);
pc->point.x = ev->x;
pc->point.y = ev->y;
pc->timer = ecore_timer_loop_add(5.0, _e_comp_x_configure_request_timer, pc);
pc->win = ev->win;
eina_hash_list_append(pending_configures, &ev->win, pc);
}
ecore_x_window_configure(ev->win, ev->value_mask,
ev->x, ev->y, ev->w, ev->h, ev->border,
ev->abovewin, ev->detail);
return ECORE_CALLBACK_PASS_ON;
}
x = ox = ec->client.x;
y = oy = ec->client.y;
w = ow = ec->client.w;
h = oh = ec->client.h;
if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
(ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
{
int zx, zy, zw, zh;
e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
{
_e_comp_x_client_data_get(ec)->initial_attributes.x = ev->x;
if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
x = E_CLAMP(ev->x, zx, zx + zw - ec->w);
else
x = ev->x;
}
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
{
_e_comp_x_client_data_get(ec)->initial_attributes.y = ev->y;
if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
y = E_CLAMP(ev->y, zy, zy + zh - ec->h);
else
y = ev->y;
}
}
if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
(ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
{
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
w = ev->w, _e_comp_x_client_data_get(ec)->initial_attributes.w = ev->w;
if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
h = ev->h, _e_comp_x_client_data_get(ec)->initial_attributes.h = ev->h;
}
e_comp_object_frame_xy_adjust(ec->frame, x, y, &x, &y);
e_comp_object_frame_wh_adjust(ec->frame, w, h, &w, &h);
if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
(ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
move = (x != ec->x) || (y != ec->y);
if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
(ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
resize = (w != ec->w) || (h != ec->h);
if (move && (!ec->lock_client_location))
{
if ((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
{
E_Zone *zone;
e_comp_object_frame_xy_unadjust(ec->frame, x, y, &ec->saved.x, &ec->saved.y);
zone = e_comp_zone_xy_get(x, y);
if (zone && (zone->x || zone->y))
{
ec->saved.x -= zone->x;
ec->saved.y -= zone->y;
}
}
else if (!ec->maximize_override)
{
/* client is completely outside the screen, policy does not allow */
if (((!E_INTERSECTS(x, y, ec->w, ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
(e_config->screen_limits != E_CLIENT_OFFSCREEN_LIMIT_ALLOW_FULL)) ||
/* client is partly outside the zone, policy does not allow */
(((!E_INSIDE(x, y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
(!E_INSIDE(x + ec->w, y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
(!E_INSIDE(x, y + ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
(!E_INSIDE(x + ec->w, y + ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5))) &&
(e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE))
)
e_comp_object_util_center(ec->frame);
else
{
evas_object_move(ec->frame, x, y);
}
}
}
if (resize && (!ec->lock_client_size) && (move || ((!ec->maximized) && (!ec->fullscreen))))
{
if (ec->shaded || ((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE))
e_comp_object_frame_wh_unadjust(ec->frame, w, h, &ec->saved.w, &ec->saved.h);
else if (!ec->maximize_override)
{
evas_object_resize(ec->frame, w, h);
}
}
if (!ec->lock_client_stacking)
{
if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
(ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
{
E_Client *oec;
if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
{
oec = _e_comp_x_client_find_by_window(ev->abovewin);
if (oec)
{
evas_object_stack_above(ec->frame, oec->frame);
}
else
{
ecore_x_window_configure(e_client_util_pwin_get(ec),
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
ev->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
}
}
else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
{
oec = _e_comp_x_client_find_by_window(ev->abovewin);
if (oec)
{
evas_object_stack_below(ec->frame, oec->frame);
}
else
{
ecore_x_window_configure(e_client_util_pwin_get(ec),
ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
ev->abovewin, ECORE_X_WINDOW_STACK_BELOW);
}
}
else if (ev->detail == ECORE_X_WINDOW_STACK_TOP_IF)
{
/* FIXME: do */
}
else if (ev->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
{
/* FIXME: do */
}
else if (ev->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
{
/* FIXME: do */
}
}
else if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
{
if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
{
evas_object_raise(ec->frame);
}
else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
{
evas_object_lower(ec->frame);
}
else if (ev->detail == ECORE_X_WINDOW_STACK_TOP_IF)
{
/* FIXME: do */
}
else if (ev->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
{
/* FIXME: do */
}
else if (ev->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
{
/* FIXME: do */
}
}
}
/* FIXME: need to send synthetic stacking event to, as well as move/resize */
if ((((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE) && (move || resize)) ||
((!move) && (!resize)))
{
_e_comp_x_client_move_resize_send(ec);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_stack_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Stack_Request *ev)
{
E_Client *ec;
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec) return ECORE_CALLBACK_RENEW;
if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
evas_object_raise(ec->frame);
else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
evas_object_lower(ec->frame);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_stack(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Stack *ev)
{
E_Client *ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec) return ECORE_CALLBACK_PASS_ON;
if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE) evas_object_raise(ec->frame);
else evas_object_lower(ec->frame);
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_property(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Property *ev)
{
E_Client *ec;
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec) return ECORE_CALLBACK_PASS_ON;
if (ev->atom == ECORE_X_ATOM_WM_NAME)
{
if ((!ec->netwm.name) &&
(!ec->netwm.fetch.name))
{
ec->icccm.fetch.title = 1;
EC_CHANGED(ec);
}
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_NAME)
{
ec->netwm.fetch.name = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_CLASS)
{
ec->icccm.fetch.name_class = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_ICON_NAME)
{
if ((!ec->netwm.icon_name) &&
(!ec->netwm.fetch.icon_name))
{
ec->icccm.fetch.icon_name = 1;
EC_CHANGED(ec);
}
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
{
ec->netwm.fetch.icon_name = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
{
ec->icccm.fetch.machine = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_PROTOCOLS)
{
ec->icccm.fetch.protocol = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_HINTS)
{
ec->icccm.fetch.hints = 1;
EC_CHANGED(ec);
if (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
ec->ignored = 0;
}
else if (ev->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
{
if (_e_comp_x_client_data_get(ec)->internal_props_set)
_e_comp_x_client_data_get(ec)->internal_props_set--;
else
{
ec->icccm.fetch.size_pos_hints = 1;
EC_CHANGED(ec);
}
}
else if (ev->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
{
/*
if ((ec->netwm.type == E_WINDOW_TYPE_UNKNOWN) &&
(!ec->netwm.fetch.type))
{
*/
ec->mwm.fetch.hints = 1;
EC_CHANGED(ec);
/*
}
*/
}
else if (ev->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
{
ec->icccm.fetch.transient_for = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
{
ec->icccm.fetch.client_leader = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
{
ec->icccm.fetch.window_role = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_ICON)
{
ec->netwm.fetch.icon = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ATM__QTOPIA_SOFT_MENU)
{
ec->qtopia.fetch.soft_menu = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ATM__QTOPIA_SOFT_MENUS)
{
ec->qtopia.fetch.soft_menus = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
{
ec->vkbd.fetch.state = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
{
ec->vkbd.fetch.vkbd = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
{
_e_comp_x_client_data_get(ec)->illume.conformant.fetch.conformant = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
{
_e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.state = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
{
_e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.quickpanel = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
{
_e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.priority.major = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
{
_e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.priority.minor = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
{
_e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.zone = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
{
_e_comp_x_client_data_get(ec)->illume.drag.fetch.locked = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
{
_e_comp_x_client_data_get(ec)->illume.drag.fetch.drag = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
{
_e_comp_x_client_data_get(ec)->illume.win_state.fetch.state = 1;
EC_CHANGED(ec);
}
/*
else if (ev->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
{
ec->netwm.fetch.user_time = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_STRUT)
{
ec->netwm.fetch.strut = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
{
ec->netwm.fetch.strut = 1;
EC_CHANGED(ec);
}
*/
else if (ev->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
{
//printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
}
else if (ev->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
{
ec->e.fetch.video_position = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
{
ec->e.fetch.video_parent = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_STATE)
{
ec->netwm.fetch.state = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
{
if (ec->netwm.opacity_changed)
ec->netwm.opacity_changed = 0;
else
{
ec->netwm.fetch.opacity = 1;
EC_CHANGED(ec);
}
}
else if (ev->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
{
ec->e.fetch.profile = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_AVAILABLE_LIST)
{
ec->e.fetch.profile = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ATM_GTK_FRAME_EXTENTS)
{
_e_comp_x_client_data_get(ec)->fetch_gtk_frame_extents = 1;
EC_CHANGED(ec);
}
else if (ev->atom == ATM_STEAM_GAME)
{
e_hints_window_steam_game_get(ec);
ec->changes.icon = 1;
EC_CHANGED(ec);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Client_Message *ev)
{
E_Client *ec;
ec = _e_comp_x_client_find_by_window(ev->win);
if (!ec)