1 #define EXECUTIVE_MODE_ENABLED
2 #define E_COMP_X
3 #include "e.h"
4
5 #define RANDR_VERSION_1_3 ((1 << 16) | 3)
6 #define RANDR_VERSION_1_4 ((1 << 16) | 4)
7
8 #define GRAV_SET(ec, grav) \
9 ecore_x_window_gravity_set(e_client_util_pwin_get(ec), grav); \
10 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);
11
12 #ifdef HAVE_WAYLAND
13 # define E_COMP_X_PIXMAP_CHECK if ((e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) && (!e_client_has_xwindow(ec))) return
14 #else
15 # define E_COMP_X_PIXMAP_CHECK if (!e_pixmap_is_x(ec->pixmap)) return
16 #endif
17 /* maybe make configurable?
18 * not sure why anyone would want to change it...
19 */
20 #define MOVE_COUNTER_LIMIT 50
21
22 #define PARENT_ACTIVATE_TIME 200
23 #define PARENT_ACTIVATE_LIMIT 2
24
25 EINTERN void _e_main_cb_x_fatal(void *data EINA_UNUSED);
26
27 typedef struct _Frame_Extents Frame_Extents;
28
29 struct _Frame_Extents
30 {
31 int l, r, t, b;
32 };
33
34 struct _E_Comp_X_Data
35 {
36 Ecore_X_Window lock_grab_break_wnd;
37
38 Eina_List *retry_clients;
39 Ecore_Timer *retry_timer;
40 Eina_Bool restack E_BITFIELD;
41 };
42
43 typedef struct Pending_Configure
44 {
45 Evas_Point point;
46 Ecore_X_Window win;
47 Ecore_Timer *timer;
48 } Pending_Configure;
49
50 static Eina_Hash *pending_configures;
51
52 static unsigned int focus_time = 0;
53 static unsigned int focus_canvas_time = 0;
54 static Ecore_Timer *focus_timer;
55 static E_Client *mouse_client;
56 static Eina_List *handlers = NULL;
57 static Eina_Hash *clients_win_hash = NULL;
58 static Eina_Hash *damages_hash = NULL;
59 static Eina_Hash *frame_extents = NULL;
60 static Eina_Hash *alarm_hash = NULL;
61
62 static Evas_Point mouse_in_coords = {-1, -1};
63 static Ecore_Job *mouse_in_job;
64 static E_Client *focus_job_client;
65 static Ecore_Job *focus_job;
66 static E_Client *unfocus_job_client;
67 static Ecore_Job *unfocus_job;
68 static Ecore_Idle_Enterer *_e_comp_x_post_client_idler = NULL;
69 static Ecore_Idle_Enterer *_x_idle_flush = NULL;
70 static Eina_List *post_clients = NULL;
71
72 static int _e_comp_x_mapping_change_disabled = 0;
73
74 static Ecore_X_Randr_Screen_Size screen_size = { -1, -1 };
75 static int screen_size_index = -1;
76
77 static Ecore_X_Atom backlight_atom = 0;
78
79 static Ecore_Timer *mouse_in_fix_check_timer = NULL;
80
81 static Eina_Hash *dead_wins;
82
83 static Ecore_Window _e_comp_x_suspend_grabbed; // window grabber for suspending pointer
84
85 static void _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec);
86
87 static inline E_Comp_X_Client_Data *
_e_comp_x_client_data_get(const E_Client * ec)88 _e_comp_x_client_data_get(const E_Client *ec)
89 {
90 #ifdef HAVE_WAYLAND
91 if (!e_pixmap_is_x(ec->pixmap))
92 return e_comp_wl_client_xwayland_data(ec);
93 #endif
94 return ec->comp_data;
95 }
96
97 static Eina_Bool
_e_comp_x_flusher(void * data EINA_UNUSED)98 _e_comp_x_flusher(void *data EINA_UNUSED)
99 {
100 ecore_x_flush();
101 return ECORE_CALLBACK_RENEW;
102 }
103
104 static inline Ecore_X_Window
_e_comp_x_client_window_get(const E_Client * ec)105 _e_comp_x_client_window_get(const E_Client *ec)
106 {
107 E_Comp_X_Client_Data *cd = _e_comp_x_client_data_get(ec);
108 if (cd && cd->reparented)
109 return e_client_util_pwin_get(ec);
110 return e_client_util_win_get(ec);
111 }
112
113 static void
_e_comp_x_client_damage_add(E_Client * ec)114 _e_comp_x_client_damage_add(E_Client *ec)
115 {
116 Ecore_X_Window win;
117
118 if (_e_comp_x_client_data_get(ec)->damage) return;
119 win = _e_comp_x_client_window_get(ec);
120 _e_comp_x_client_data_get(ec)->damage = ecore_x_damage_new(win, ECORE_X_DAMAGE_REPORT_DELTA_RECTANGLES);
121 eina_hash_add(damages_hash, &_e_comp_x_client_data_get(ec)->damage, ec);
122 }
123
124 static void
_e_comp_x_focus_check(void)125 _e_comp_x_focus_check(void)
126 {
127 E_Client *focused;
128
129 if (stopping || e_comp->nocomp) return;
130 focused = e_client_focused_get();
131 /* if there is no new focused or it is a non-X client,
132 * focus comp canvas on focus-out */
133 if ((!focused) || (!e_client_has_xwindow(focused)))
134 {
135 focus_canvas_time = ecore_x_current_time_get();
136 focus_time = 0;
137 if (e_comp->comp_type != E_PIXMAP_TYPE_X)
138 e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
139 // this breaks Qt because it seems to create override-redirect popup windows
140 // that it FOCUSES instead of grabbking the kbd like most other menu windows
141 // so this causes the parent window to lose focus in a way that then causes
142 // the popups to dismiss instantly
143 // e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
144 // This might be more specific a workaround bit might miss other cases, so keep
145 // here as an idea and for future reference
146 else
147 {
148 Ecore_X_Window focus_win = ecore_x_window_focus_get();
149 if (focus_win)
150 {
151 if ((ecore_x_window_root_get(focus_win) == focus_win) ||
152 (!ecore_x_icccm_transient_for_get(focus_win)))
153 e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
154 }
155 else
156 e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
157 }
158 }
159 }
160
161 static void
_e_comp_x_client_modal_setup(E_Client * ec)162 _e_comp_x_client_modal_setup(E_Client *ec)
163 {
164 E_Comp_X_Client_Data *pcd;
165
166 ec->parent->modal = ec;
167 ec->parent->lock_close = 1;
168 pcd = _e_comp_x_client_data_get(ec->parent);
169 if (!pcd->lock_win)
170 {
171 eina_hash_add(clients_win_hash, &pcd->lock_win, ec->parent);
172 pcd->lock_win = ecore_x_window_input_new(e_client_util_pwin_get(ec->parent), 0, 0, ec->parent->w, ec->parent->h);
173 e_comp_ignore_win_add(E_PIXMAP_TYPE_X, pcd->lock_win);
174 ecore_x_window_show(pcd->lock_win);
175 ecore_x_icccm_name_class_set(pcd->lock_win, "comp_data->lock_win", "comp_data->lock_win");
176 }
177 }
178
179 static void
_e_comp_x_client_frame_update(E_Client * ec,int l,int r,int t,int b)180 _e_comp_x_client_frame_update(E_Client *ec, int l, int r, int t, int b)
181 {
182 ecore_x_netwm_frame_size_set(e_client_util_win_get(ec), l, r, t, b);
183 ecore_x_e_frame_size_set(e_client_util_win_get(ec), l, r, t, b);
184 _e_comp_x_client_data_get(ec)->frame_update = 0;
185 }
186
187 static Eina_List *iconshare = NULL;
188
189 typedef struct _E_Client_Icon_Entry E_Client_Icon_Entry;
190
191 struct _E_Client_Icon_Entry
192 {
193 Ecore_X_Icon *icons;
194 int num_icons;
195 int ref;
196 };
197
198 static Ecore_X_Icon *
_e_comp_x_client_icon_deduplicate(Ecore_X_Icon * icons,int num_icons)199 _e_comp_x_client_icon_deduplicate(Ecore_X_Icon *icons, int num_icons)
200 {
201 int i;
202 Eina_List *l;
203 E_Client_Icon_Entry *ie;
204
205 // unless the rest of e uses border icons OTHER than icon #0
206 // then free the rest that we don't need anymore.
207 for (i = 1; i < num_icons; i++)
208 {
209 E_FREE(icons[i].data);
210 }
211 // lookup icon data in icons cache/share
212 EINA_LIST_FOREACH(iconshare, l, ie)
213 {
214 if ((ie->num_icons == num_icons) &&
215 (num_icons > 0) &&
216 (ie->icons[0].width == icons[0].width) &&
217 (ie->icons[0].height == icons[0].height) &&
218 (!memcmp(ie->icons[0].data, icons[0].data,
219 icons[0].width * icons[0].height * 4)))
220 {
221 // found so free the input icons
222 for (i = 0; i < num_icons; i++)
223 free(icons[i].data);
224 free(icons);
225 // ref the shared/cached one
226 ie->ref++;
227 iconshare = eina_list_promote_list(iconshare, l);
228 // and return that
229 return ie->icons;
230 }
231 }
232 // no hit - new entry to cache. add it
233 ie = calloc(1, sizeof(E_Client_Icon_Entry));
234 if (ie)
235 {
236 ie->icons = icons;
237 ie->num_icons = num_icons;
238 ie->ref = 1;
239 iconshare = eina_list_prepend(iconshare, ie);
240 }
241 return icons;
242 }
243
244 static void
_e_comp_x_client_icon_free(Ecore_X_Icon * icons,int num_icons)245 _e_comp_x_client_icon_free(Ecore_X_Icon *icons, int num_icons)
246 {
247 int i;
248 Eina_List *l;
249 E_Client_Icon_Entry *ie;
250
251 // lookup in icon share cache
252 EINA_LIST_FOREACH(iconshare, l, ie)
253 {
254 if ((ie->num_icons == num_icons) &&
255 (num_icons > 0) &&
256 (ie->icons[0].width == icons[0].width) &&
257 (ie->icons[0].height == icons[0].height) &&
258 (!memcmp(ie->icons[0].data, icons[0].data,
259 icons[0].width * icons[0].height * 4)))
260 {
261 // found so deref
262 ie->ref--;
263 if (ie->ref <= 0)
264 {
265 // no refs left - free the icon from the share/cache
266 iconshare = eina_list_remove_list(iconshare, l);
267 for (i = 0; i < ie->num_icons; i++)
268 free(ie->icons[i].data);
269 free(ie->icons);
270 free(ie);
271 }
272 return;
273 }
274 }
275 // not found - so just free it ... odd - we should never be here
276 for (i = 0; i < num_icons; i++)
277 free(icons[i].data);
278 free(icons);
279 }
280
281 static void
_e_comp_x_client_event_free(void * d EINA_UNUSED,void * e)282 _e_comp_x_client_event_free(void *d EINA_UNUSED, void *e)
283 {
284 E_Event_Client *ev = e;
285
286 UNREFD(ev->ec, 1);
287 e_object_unref(E_OBJECT(ev->ec));
288 free(ev);
289 }
290
291 static void
_e_comp_x_print_win(Ecore_X_Window win)292 _e_comp_x_print_win(Ecore_X_Window win)
293 {
294 int x, y, w, h;
295 Eina_Bool vis;
296
297 ecore_x_window_geometry_get(win, &x, &y, &w, &h);
298 vis = ecore_x_window_visible_get(win);
299 fprintf(stderr, "%s 0x%x: %d,%d @ %dx%d\n", vis ? "VIS" : "HID", win, x, y, w, h);
300 }
301
302 static void
_e_comp_x_focus_grab(E_Client * ec)303 _e_comp_x_focus_grab(E_Client *ec)
304 {
305 if (ec->internal_elm_win) return;
306 ecore_x_window_button_grab(e_client_util_win_get(ec), 1,
307 ECORE_X_EVENT_MASK_MOUSE_DOWN |
308 ECORE_X_EVENT_MASK_MOUSE_UP |
309 ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
310 ecore_x_window_button_grab(e_client_util_win_get(ec), 2,
311 ECORE_X_EVENT_MASK_MOUSE_DOWN |
312 ECORE_X_EVENT_MASK_MOUSE_UP |
313 ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
314 ecore_x_window_button_grab(e_client_util_win_get(ec), 3,
315 ECORE_X_EVENT_MASK_MOUSE_DOWN |
316 ECORE_X_EVENT_MASK_MOUSE_UP |
317 ECORE_X_EVENT_MASK_MOUSE_MOVE, 0, 1);
318 _e_comp_x_client_data_get(ec)->button_grabbed = 1;
319 }
320
321 static void
_e_comp_x_focus_init(E_Client * ec)322 _e_comp_x_focus_init(E_Client *ec)
323 {
324 if (_e_comp_x_client_data_get(ec)->button_grabbed) return;
325 if (!((e_client_focus_policy_click(ec)) ||
326 (e_config->always_click_to_raise) ||
327 (e_config->always_click_to_focus))) return;
328 _e_comp_x_focus_grab(ec);
329 }
330
331 static void
_e_comp_x_focus_setup(E_Client * ec)332 _e_comp_x_focus_setup(E_Client *ec)
333 {
334 if (_e_comp_x_client_data_get(ec)->button_grabbed) return;
335 if ((!e_client_focus_policy_click(ec)) ||
336 (e_config->always_click_to_raise) ||
337 (e_config->always_click_to_focus)) return;
338 _e_comp_x_focus_grab(ec);
339 }
340
341
342 static void
_e_comp_x_focus_setdown(E_Client * ec)343 _e_comp_x_focus_setdown(E_Client *ec)
344 {
345 Ecore_X_Window win, pwin;
346
347 if (!_e_comp_x_client_data_get(ec)->button_grabbed) return;
348 if ((!e_client_focus_policy_click(ec)) ||
349 (e_config->always_click_to_raise) ||
350 (e_config->always_click_to_focus)) return;
351 win = e_client_util_win_get(ec);
352 pwin = e_client_util_pwin_get(ec);
353 e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
354 e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
355 ecore_x_window_button_ungrab(win, 1, 0, 1);
356 ecore_x_window_button_ungrab(win, 2, 0, 1);
357 ecore_x_window_button_ungrab(win, 3, 0, 1);
358 e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
359 e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
360 _e_comp_x_client_data_get(ec)->button_grabbed = 0;
361 }
362
363 static Eina_Bool
_e_comp_x_client_new_helper(E_Client * ec)364 _e_comp_x_client_new_helper(E_Client *ec)
365 {
366 Ecore_X_Window win = e_client_util_win_get(ec);
367 int at_num = 0, i;
368 Ecore_X_Atom *atoms;
369
370 if (!ecore_x_window_attributes_get(win, &ec->comp_data->initial_attributes))
371 {
372 //CRI("OUCH! FIX THIS!");
373 DELD(ec, 1);
374 e_object_del(E_OBJECT(ec));
375 return EINA_FALSE;
376 }
377 if (ec->re_manage && (!ec->comp_data->initial_attributes.visible))
378 {
379 /* ain't gonna be no hidden clients on my watch! */
380 DELD(ec, 1);
381 e_object_del(E_OBJECT(ec));
382 return EINA_FALSE;
383 }
384 ec->depth = ec->comp_data->initial_attributes.depth;
385 ec->override = ec->comp_data->initial_attributes.override;
386 ec->placed |= ec->override;
387 ec->input_only = ec->comp_data->initial_attributes.input_only;
388 ec->border_size = ec->comp_data->initial_attributes.border;
389 ec->icccm.accepts_focus = (!ec->override) && (!ec->input_only);
390 //INF("NEW CLIENT: %d,%d -> %d,%d", ec->x, ec->y, ec->comp_data->initial_attributes.x, ec->comp_data->initial_attributes.y);
391 ec->x = ec->client.x = ec->comp_data->initial_attributes.x;
392 ec->y = ec->client.y = ec->comp_data->initial_attributes.y;
393 if (ec->override && ((ec->x == -77) && (ec->y == -777)))
394 {
395 /* this is the ecore-x private window :/ */
396 e_comp_ignore_win_add(E_PIXMAP_TYPE_X, win);
397 DELD(ec, 1);
398 e_object_del(E_OBJECT(ec));
399 return EINA_FALSE;
400 }
401 if ((!e_client_util_ignored_get(ec)) && (!ec->internal) && (!ec->internal_elm_win))
402 {
403 ec->comp_data->need_reparent = 1;
404 EC_CHANGED(ec);
405 ec->take_focus = !starting;
406 }
407 ec->new_client ^= ec->override;
408 if (!ec->new_client)
409 e_comp->new_clients--;
410
411 ec->w = ec->client.w = ec->comp_data->initial_attributes.w;
412 ec->h = ec->client.h = ec->comp_data->initial_attributes.h;
413 if (!ec->internal)
414 {
415 ec->comp_data->pw = ec->w;
416 ec->comp_data->ph = ec->h;
417 }
418 ec->changes.size = 1;
419
420
421 e_pixmap_visual_cmap_set(ec->pixmap, ec->comp_data->initial_attributes.visual, ec->comp_data->initial_attributes.colormap);
422 if (ec->override && (!ec->internal))
423 ecore_x_window_shape_events_select(win, 1);
424 if (ec->override && (!(ec->comp_data->initial_attributes.event_mask.mine & ECORE_X_EVENT_MASK_WINDOW_PROPERTY)))
425 ecore_x_event_mask_set(win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
426
427 atoms = ecore_x_window_prop_list(win, &at_num);
428 ec->icccm.fetch.command = 1;
429
430 if (atoms)
431 {
432 Eina_Bool video_parent = EINA_FALSE;
433 Eina_Bool video_position = EINA_FALSE;
434 Eina_Bool found_desk = EINA_FALSE;
435 Eina_Bool found_zone = EINA_FALSE;
436
437 /* icccm */
438 for (i = 0; i < at_num; i++)
439 {
440 if (atoms[i] == ECORE_X_ATOM_WM_NAME)
441 ec->icccm.fetch.title = 1;
442 else if (atoms[i] == ECORE_X_ATOM_WM_CLASS)
443 ec->icccm.fetch.name_class = 1;
444 else if (atoms[i] == ECORE_X_ATOM_WM_ICON_NAME)
445 ec->icccm.fetch.icon_name = 1;
446 else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_MACHINE)
447 ec->icccm.fetch.machine = 1;
448 else if (atoms[i] == ECORE_X_ATOM_WM_HINTS)
449 ec->icccm.fetch.hints = 1;
450 else if (atoms[i] == ECORE_X_ATOM_WM_NORMAL_HINTS)
451 ec->icccm.fetch.size_pos_hints = 1;
452 else if (atoms[i] == ECORE_X_ATOM_WM_PROTOCOLS)
453 ec->icccm.fetch.protocol = 1;
454 else if (atoms[i] == ECORE_X_ATOM_MOTIF_WM_HINTS)
455 ec->mwm.fetch.hints = 1;
456 else if (atoms[i] == ECORE_X_ATOM_WM_TRANSIENT_FOR)
457 {
458 ec->icccm.fetch.transient_for = 1;
459 ec->netwm.fetch.type = 1;
460 }
461 else if (atoms[i] == ECORE_X_ATOM_WM_CLIENT_LEADER)
462 ec->icccm.fetch.client_leader = 1;
463 else if (atoms[i] == ECORE_X_ATOM_WM_WINDOW_ROLE)
464 ec->icccm.fetch.window_role = 1;
465 }
466 /* netwm, loop again, netwm will ignore some icccm, so we
467 * have to be sure that netwm is checked after */
468 for (i = 0; i < at_num; i++)
469 {
470 if (atoms[i] == ECORE_X_ATOM_NET_WM_NAME)
471 {
472 /* Ignore icccm */
473 ec->icccm.fetch.title = 0;
474 ec->netwm.fetch.name = 1;
475 }
476 else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON_NAME)
477 {
478 /* Ignore icccm */
479 ec->icccm.fetch.icon_name = 0;
480 ec->netwm.fetch.icon_name = 1;
481 }
482 else if (atoms[i] == ECORE_X_ATOM_NET_WM_ICON)
483 {
484 ec->netwm.fetch.icon = 1;
485 }
486 else if (atoms[i] == ECORE_X_ATOM_NET_WM_USER_TIME)
487 {
488 ec->netwm.fetch.user_time = 1;
489 }
490 else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT)
491 {
492 DBG("ECORE_X_ATOM_NET_WM_STRUT");
493 ec->netwm.fetch.strut = 1;
494 }
495 else if (atoms[i] == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
496 {
497 DBG("ECORE_X_ATOM_NET_WM_STRUT_PARTIAL");
498 ec->netwm.fetch.strut = 1;
499 }
500 else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_TYPE)
501 {
502 /* Ignore mwm
503 ec->mwm.fetch.hints = 0;
504 */
505 ec->netwm.fetch.type = 1;
506 }
507 else if (atoms[i] == ECORE_X_ATOM_NET_WM_STATE)
508 {
509 ec->netwm.fetch.state = 1;
510 }
511 else if (atoms[i] == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
512 ec->netwm.fetch.opacity = 1;
513 }
514 /* other misc atoms */
515 for (i = 0; i < at_num; i++)
516 {
517 /* loop to check for own atoms */
518 if (atoms[i] == E_ATOM_WINDOW_STATE)
519 {
520 ec->e.fetch.state = 1;
521 }
522 /* loop to check for qtopia atoms */
523 if (atoms[i] == ATM__QTOPIA_SOFT_MENU)
524 ec->qtopia.fetch.soft_menu = 1;
525 else if (atoms[i] == ATM__QTOPIA_SOFT_MENUS)
526 ec->qtopia.fetch.soft_menus = 1;
527 /* loop to check for vkbd atoms */
528 else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
529 ec->vkbd.fetch.state = 1;
530 else if (atoms[i] == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
531 ec->vkbd.fetch.vkbd = 1;
532 /* loop to check for illume atoms */
533 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
534 ec->comp_data->illume.conformant.fetch.conformant = 1;
535 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
536 ec->comp_data->illume.quickpanel.fetch.state = 1;
537 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
538 ec->comp_data->illume.quickpanel.fetch.quickpanel = 1;
539 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
540 ec->comp_data->illume.quickpanel.fetch.priority.major = 1;
541 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
542 ec->comp_data->illume.quickpanel.fetch.priority.minor = 1;
543 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
544 ec->comp_data->illume.quickpanel.fetch.zone = 1;
545 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
546 ec->comp_data->illume.drag.fetch.locked = 1;
547 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_DRAG)
548 ec->comp_data->illume.drag.fetch.drag = 1;
549 else if (atoms[i] == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
550 ec->comp_data->illume.win_state.fetch.state = 1;
551 else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_PARENT)
552 video_parent = EINA_TRUE;
553 else if (atoms[i] == ECORE_X_ATOM_E_VIDEO_POSITION)
554 video_position = EINA_TRUE;
555 /* loop to check for window profile list atom */
556 else if (atoms[i] == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
557 ec->e.fetch.profile = 1;
558 else if (atoms[i] == ECORE_X_ATOM_E_STACK_TYPE)
559 ec->e.fetch.stack = 1;
560 else if (atoms[i] == ATM_GTK_FRAME_EXTENTS)
561 ec->comp_data->fetch_gtk_frame_extents = 1;
562 else if (atoms[i] == ATM_STEAM_GAME)
563 e_hints_window_steam_game_get(ec);
564 else if (ec->re_manage)
565 {
566 if (atoms[i] == E_ATOM_DESKTOP_FILE)
567 {
568 char *path = ecore_x_window_prop_string_get(win,
569 E_ATOM_DESKTOP_FILE);
570 if (path)
571 {
572 ec->desktop = efreet_desktop_get(path);
573 free(path);
574 }
575 }
576 else if (atoms[i] == E_ATOM_DESK)
577 found_desk = 1;
578 else if (atoms[i] == E_ATOM_ZONE)
579 found_zone = 1;
580 }
581 }
582 if (video_position && video_parent)
583 {
584 ec->e.state.video = 1;
585 ec->e.fetch.video_parent = 1;
586 ec->e.fetch.video_position = 1;
587 fprintf(stderr, "We found a video window \\o/ %x\n", win);
588 }
589 free(atoms);
590
591 if (ec->re_manage && found_desk && found_zone)
592 {
593 E_Zone *zone = NULL;
594 E_Desk *desk = NULL;
595 unsigned int id, deskxy[2];
596 int ret;
597
598 /* get all information from window before it is
599 * reset by e_client_new */
600 ret = ecore_x_window_prop_card32_get(win,
601 E_ATOM_ZONE,
602 &id, 1);
603 if (ret == 1)
604 zone = e_comp_zone_number_get(id);
605 if (!zone)
606 zone = e_zone_current_get();
607 ret = ecore_x_window_prop_card32_get(win,
608 E_ATOM_DESK,
609 deskxy, 2);
610 if (ret == 2)
611 desk = e_desk_at_xy_get(zone,
612 deskxy[0],
613 deskxy[1]);
614
615 if (desk) e_client_desk_set(ec, desk);
616
617 }
618 }
619
620 return EINA_TRUE;
621 }
622
623 static E_Client *
_e_comp_x_client_find_by_damage(Ecore_X_Damage damage)624 _e_comp_x_client_find_by_damage(Ecore_X_Damage damage)
625 {
626 return eina_hash_find(damages_hash, &damage);
627 }
628
629 static E_Client *
_e_comp_x_client_find_by_window(Ecore_X_Window win)630 _e_comp_x_client_find_by_window(Ecore_X_Window win)
631 {
632 E_Client *ec;
633
634 ec = eina_hash_find(clients_win_hash, &win);
635 if (ec && e_object_is_del(E_OBJECT(ec))) ec = NULL;
636 return ec;
637 }
638
639 /*
640 static E_Client *
641 _e_comp_x_client_find_all_by_window(Ecore_X_Window win)
642 {
643 return eina_hash_find(clients_win_hash, &win);
644 }
645 */
646
647 static void
_e_comp_x_add_fail_job(void * d EINA_UNUSED)648 _e_comp_x_add_fail_job(void *d EINA_UNUSED)
649 {
650 e_util_dialog_internal
651 (_("Compositor Warning"),
652 _("Your display driver does not support OpenGL, GLSL<ps/>"
653 "shaders or no OpenGL engines were compiled or installed<ps/>"
654 "for Evas or Ecore-Evas. Falling back to software engine.<ps/>"
655 "<ps/>"
656 "You will need an OpenGL 2.0 (or OpenGL ES 2.0) capable<ps/>"
657 "GPU to use OpenGL with compositing."));
658 }
659
660 static void
_pri_adj(int pid,int set,int adj,Eina_Bool use_adj,Eina_Bool adj_children,Eina_Bool do_children)661 _pri_adj(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_children, Eina_Bool do_children)
662 {
663 int newpri = set;
664
665 if (use_adj) newpri = getpriority(PRIO_PROCESS, pid) + adj;
666 setpriority(PRIO_PROCESS, pid, newpri);
667 // shouldn't need to do this as default ionice class is "none" (0), and
668 // this inherits io priority FROM nice level
669 // ioprio_set(IOPRIO_WHO_PROCESS, pid,
670 // IOPRIO_PRIO_VALUE(2, 5));
671 if (do_children)
672 {
673 Eina_List *files;
674 char *file, buf[PATH_MAX];
675 FILE *f;
676 int pid2, ppid;
677
678 // yes - this is /proc specific... so this may not work on some
679 // os's - works on linux. too bad for others.
680 files = ecore_file_ls("/proc");
681 EINA_LIST_FREE(files, file)
682 {
683 if (isdigit(file[0]))
684 {
685 snprintf(buf, sizeof(buf), "/proc/%s/stat", file);
686 f = fopen(buf, "r");
687 if (f)
688 {
689 pid2 = -1;
690 ppid = -1;
691 if (fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid) == 2)
692 {
693 fclose(f);
694 if (ppid == pid)
695 {
696 if (adj_children)
697 _pri_adj(pid2, set, adj, EINA_TRUE,
698 adj_children, do_children);
699 else
700 _pri_adj(pid2, set, adj, use_adj,
701 adj_children, do_children);
702 }
703 }
704 else fclose(f);
705 }
706 }
707 free(file);
708 }
709 }
710 }
711
712 static E_Client *
_e_comp_x_client_find_by_alarm(Ecore_X_Sync_Alarm al)713 _e_comp_x_client_find_by_alarm(Ecore_X_Sync_Alarm al)
714 {
715 return eina_hash_find(alarm_hash, &al);
716 }
717
718 static void
_e_comp_x_client_move_resize_send(E_Client * ec)719 _e_comp_x_client_move_resize_send(E_Client *ec)
720 {
721 if (ec->internal_elm_win)
722 ecore_evas_managed_move(e_win_ee_get(ec->internal_elm_win), ec->client.x - ec->x, ec->client.y - ec->y);
723
724 ecore_x_icccm_move_resize_send(e_client_util_win_get(ec), ec->client.x, ec->client.y, ec->client.w, ec->client.h);
725 }
726
727 static Eina_Bool
_e_comp_x_post_client_idler_cb(void * d EINA_UNUSED)728 _e_comp_x_post_client_idler_cb(void *d EINA_UNUSED)
729 {
730 E_Client *ec;
731
732 //INF("POST IDLER");
733 EINA_LIST_FREE(post_clients, ec)
734 {
735 Ecore_X_Window win, twin;
736
737 if (e_object_is_del(E_OBJECT(ec)) || (!_e_comp_x_client_data_get(ec))) continue;
738 win = _e_comp_x_client_window_get(ec);
739 if (ec->post_move)
740 {
741 E_Client *tmp;
742 Eina_List *l;
743
744 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
745 {
746 twin = _e_comp_x_client_window_get(tmp);
747 ecore_x_window_move(twin,
748 ec->client.x +
749 tmp->e.state.video_position.x,
750 ec->client.y +
751 tmp->e.state.video_position.y);
752 }
753 }
754 if (ec->e.state.video)
755 {
756 E_Client *parent;
757
758 parent = ec->e.state.video_parent_client;
759 twin = _e_comp_x_client_window_get(parent);
760 ecore_x_window_move(twin,
761 parent->client.x +
762 ec->e.state.video_position.x,
763 parent->client.y +
764 ec->e.state.video_position.y);
765 }
766 else if (ec->shading)
767 {
768 // do nothing
769 }
770 else if ((ec->post_move) && (ec->post_resize))
771 {
772 //INF("X MVRSZ");
773 ecore_x_window_move_resize(win,
774 ec->client.x,
775 ec->client.y,
776 ec->client.w,
777 ec->client.h);
778 if (_e_comp_x_client_data_get(ec)->reparented)
779 ecore_x_window_move_resize(e_client_util_win_get(ec), 0, 0,
780 ec->client.w,
781 ec->client.h);
782 }
783 else if (ec->post_move)
784 {
785 //INF("X MV");
786 ecore_x_window_move(win, ec->client.x, ec->client.y);
787 }
788 else if (ec->post_resize)
789 {
790 //INF("X RSZ: %dx%d (REAL: %dx%d)", ec->client.w, ec->client.h, ec->w, ec->h);
791 ecore_x_window_resize(win,
792 ec->client.w, ec->client.h);
793 if (_e_comp_x_client_data_get(ec)->reparented)
794 ecore_x_window_move_resize(e_client_util_win_get(ec), 0, 0,
795 ec->client.w, ec->client.h);
796 }
797 if ((!ec->shading) && (!ec->shaded))
798 {
799 if (ec->post_resize)
800 {
801 if (ec->netwm.sync.request && (e_comp->comp_type == E_PIXMAP_TYPE_X))
802 {
803 //INF("NETWM SYNC: %p", ec);
804 ec->netwm.sync.wait++;
805 ecore_x_netwm_sync_request_send(e_client_util_win_get(ec),
806 ec->netwm.sync.serial++);
807 }
808 }
809
810 if (ec->post_move || ec->post_resize)
811 _e_comp_x_client_move_resize_send(ec);
812 }
813
814 if (ec->e.state.video)
815 {
816 fprintf(stderr, "VIDEO %p: [%i, %i] [%i, %i]\n",
817 ec,
818 ec->e.state.video_parent_client->client.x +
819 ec->e.state.video_position.x,
820 ec->e.state.video_parent_client->client.y +
821 ec->e.state.video_position.y,
822 ec->w, ec->h);
823 }
824 if (ec->netwm.opacity_changed)
825 {
826 unsigned int opacity;
827 int op;
828
829 evas_object_color_get(ec->frame, NULL, NULL, NULL, &op);
830 ec->netwm.opacity = op;
831 opacity = (op << 24) | (op << 16) | (op << 8) | op;
832 ecore_x_window_prop_card32_set(e_client_util_win_get(ec), ECORE_X_ATOM_NET_WM_WINDOW_OPACITY, &opacity, 1);
833 /* flag gets unset in property cb to avoid fetching opacity after we just set it */
834 }
835 if (e_pixmap_is_x(ec->pixmap) && ec->post_resize)
836 {
837 e_pixmap_dirty(ec->pixmap);
838 e_comp_object_render_update_del(ec->frame);
839 if (!ec->internal)
840 {
841 _e_comp_x_client_data_get(ec)->pw = ec->client.w;
842 _e_comp_x_client_data_get(ec)->ph = ec->client.h;
843 }
844 }
845 ec->post_move = 0;
846 ec->post_resize = 0;
847 }
848 if (e_comp_x->restack && (!e_comp->new_clients))
849 {
850 e_hints_client_stacking_set();
851 e_comp_x->restack = 0;
852 }
853 _e_comp_x_post_client_idler = NULL;
854 return EINA_FALSE;
855 }
856
857 static void
_e_comp_x_post_client_idler_add(E_Client * ec)858 _e_comp_x_post_client_idler_add(E_Client *ec)
859 {
860 if (!_e_comp_x_post_client_idler)
861 _e_comp_x_post_client_idler = ecore_idle_enterer_add(_e_comp_x_post_client_idler_cb, NULL);
862 if (!ec) CRI("ACK!");
863 //INF("POST IDLE: %p", ec);
864 if (!eina_list_data_find(post_clients, ec))
865 post_clients = eina_list_append(post_clients, ec);
866 }
867
868 static void
_e_comp_x_client_stack(E_Client * ec)869 _e_comp_x_client_stack(E_Client *ec)
870 {
871 E_Client *ec2;
872 Ecore_X_Window_Stack_Mode mode = ECORE_X_WINDOW_STACK_BELOW;
873 Ecore_X_Window cwin, win = 0;
874 Eina_List *l;
875
876 if (ec->override && (!ec->internal)) return; //can't restack these
877 if (e_client_is_stacking(ec)) return;
878 if (!_e_comp_x_client_data_get(ec)) return;
879 if (_e_comp_x_client_data_get(ec)->unredirected_single) return;
880
881 cwin = _e_comp_x_client_window_get(ec);
882
883 ecore_x_window_shadow_tree_flush();
884
885 /* try stacking below */
886 if (e_comp->nocomp_ec && e_comp->nocomp_ec->comp_data && (ec != e_comp->nocomp_ec))
887 win = _e_comp_x_client_window_get(e_comp->nocomp_ec);
888 else
889 {
890 ec2 = ec;
891 do
892 {
893 ec2 = e_client_above_get(ec2);
894 if (ec2 && e_client_has_xwindow(ec2) && ec2->comp_data && (!ec2->new_client) &&
895 (e_client_is_stacking(ec2) || ((!ec2->override) || ec2->internal)))
896 {
897 if (ec2->layer != ec->layer) break;
898 if (_e_comp_x_client_data_get(ec2)->need_reparent && (!_e_comp_x_client_data_get(ec2)->reparented)) continue;
899 win = _e_comp_x_client_window_get(ec2);
900 }
901 } while (ec2 && (!win));
902 }
903
904 /* try stacking above */
905 if (!win)
906 {
907 ec2 = ec;
908 do
909 {
910 ec2 = e_client_below_get(ec2);
911 if (ec2 && e_client_has_xwindow(ec2) && ec2->comp_data && (!ec2->new_client) &&
912 (e_client_is_stacking(ec2) || ((!ec2->override) || ec2->internal)))
913 {
914 if (ec2->layer != ec->layer) break;
915 if (_e_comp_x_client_data_get(ec2)->need_reparent && (!_e_comp_x_client_data_get(ec2)->reparented)) continue;
916 win = _e_comp_x_client_window_get(ec2);
917 mode = ECORE_X_WINDOW_STACK_ABOVE;
918 }
919 } while (ec2 && (!win));
920 }
921
922 /* just layer stack */
923 if (!win)
924 {
925 win = e_comp->layers[e_comp_canvas_layer_map(ec->layer)].win;
926 mode = ECORE_X_WINDOW_STACK_BELOW;
927 }
928 ecore_x_window_configure(cwin,
929 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
930 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
931 0, 0, 0, 0, 0, win, mode);
932 _e_comp_x_post_client_idler_add(ec);
933 e_comp_x->restack = 1;
934 EINA_LIST_FOREACH(ec->e.state.video_child, l, ec2)
935 evas_object_stack_below(ec2->frame, ec->frame);
936 }
937
938 static E_Client *
_e_comp_x_client_new(Ecore_X_Window win,Eina_Bool first)939 _e_comp_x_client_new(Ecore_X_Window win, Eina_Bool first)
940 {
941 E_Pixmap *cp;
942 E_Client *ec;
943
944 cp = e_pixmap_new(E_PIXMAP_TYPE_X, win);
945 EINA_SAFETY_ON_NULL_RETURN_VAL(cp, NULL);
946
947 ec = e_client_new(cp, first, 0);
948 return ec;
949 }
950
951 static void
_e_comp_x_client_pri_raise(E_Client * ec)952 _e_comp_x_client_pri_raise(E_Client *ec)
953 {
954 if (ec->netwm.pid <= 0) return;
955 if (ec->netwm.pid == getpid()) return;
956 _pri_adj(ec->netwm.pid,
957 e_config->priority - 1, -1, EINA_FALSE,
958 // EINA_TRUE, EINA_TRUE);
959 EINA_TRUE, EINA_FALSE);
960 // printf("WIN: pid %i, title %s (HI!!!!!!!!!!!!!!!!!!)\n",
961 // ec->netwm.pid, e_client_util_name_get(ec));
962 }
963
964 static void
_e_comp_x_client_pri_norm(E_Client * ec)965 _e_comp_x_client_pri_norm(E_Client *ec)
966 {
967 if (ec->netwm.pid <= 0) return;
968 if (ec->netwm.pid == getpid()) return;
969 _pri_adj(ec->netwm.pid,
970 e_config->priority, 1, EINA_FALSE,
971 // EINA_TRUE, EINA_TRUE);
972 EINA_TRUE, EINA_FALSE);
973 // printf("WIN: pid %i, title %s (NORMAL)\n",
974 // ec->netwm.pid, e_client_util_name_get(ec));
975 }
976
977 static void
_e_comp_x_client_shape_input_rectangle_set(E_Client * ec)978 _e_comp_x_client_shape_input_rectangle_set(E_Client *ec)
979 {
980 Ecore_X_Window win = e_client_util_pwin_get(ec);
981
982 if (ec->override || (!_e_comp_x_client_data_get(ec)->reparented)) return;
983
984 if (ec->visible && (!ec->comp_hidden))
985 ecore_x_composite_window_events_enable(win);
986 else
987 ecore_x_composite_window_events_disable(win);
988 }
989
990 static void
_e_comp_x_evas_color_set_cb(void * data,Evas_Object * obj,void * event_info EINA_UNUSED)991 _e_comp_x_evas_color_set_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
992 {
993 E_Client *ec = data;
994 int a;
995
996 if (!_e_comp_x_client_data_get(ec)) return;
997 evas_object_color_get(obj, NULL, NULL, NULL, &a);
998 if (a == ec->netwm.opacity) return;
999 ec->netwm.opacity_changed = 1;
1000 _e_comp_x_post_client_idler_add(ec);
1001 }
1002
1003 static void
_e_comp_x_evas_ping_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1004 _e_comp_x_evas_ping_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1005 {
1006 E_Client *ec = data;
1007
1008 if (!_e_comp_x_client_data_get(ec)) return;
1009 ecore_x_netwm_ping_send(e_client_util_win_get(ec));
1010 }
1011
1012 static void
_e_comp_x_evas_kill_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1013 _e_comp_x_evas_kill_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1014 {
1015 E_Client *ec = data;
1016
1017 if (!_e_comp_x_client_data_get(ec)) return;
1018 ecore_x_kill(e_client_util_win_get(ec));
1019 }
1020
1021 static void
_e_comp_x_evas_delete_request_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1022 _e_comp_x_evas_delete_request_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1023 {
1024 E_Client *ec = data;
1025
1026 if (!_e_comp_x_client_data_get(ec)) return;
1027 if (ec->netwm.ping)
1028 e_client_ping(ec);
1029 ecore_x_window_delete_request_send(e_client_util_win_get(ec));
1030 }
1031
1032 static void
_e_comp_x_evas_comp_hidden_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1033 _e_comp_x_evas_comp_hidden_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1034 {
1035 E_Client *tmp, *ec = data;
1036 Eina_List *l;
1037 Ecore_X_Window win;
1038
1039 if (!_e_comp_x_client_data_get(ec)) return;
1040 if (_e_comp_x_client_data_get(ec)->need_reparent) return;
1041 win = _e_comp_x_client_window_get(ec);
1042
1043 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1044 {
1045 Ecore_X_Window cwin;
1046
1047 cwin = _e_comp_x_client_window_get(tmp);
1048 if (ec->comp_hidden)
1049 ecore_x_window_hide(cwin);
1050 else
1051 ecore_x_window_show(cwin);
1052 }
1053
1054 if ((ec->internal) && (win == e_client_util_win_get(ec))) return;
1055 if (ec->comp_hidden)
1056 ecore_x_composite_window_events_disable(win);
1057 else
1058 ecore_x_composite_window_events_enable(win);
1059 ecore_x_window_ignore_set(win, ec->comp_hidden);
1060 }
1061
1062 static void
_e_comp_x_evas_shade_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1063 _e_comp_x_evas_shade_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1064 {
1065 E_Client *ec = data;
1066 Eina_List *l;
1067 E_Client *tmp;
1068
1069 if (!_e_comp_x_client_data_get(ec)) return;
1070 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1071 ecore_x_window_hide(e_client_util_pwin_get(tmp));
1072
1073 ecore_x_window_shadow_tree_flush();
1074 }
1075
1076 static void
_e_comp_x_evas_frame_recalc_cb(void * data,Evas_Object * obj,void * event_info)1077 _e_comp_x_evas_frame_recalc_cb(void *data, Evas_Object *obj, void *event_info)
1078 {
1079 E_Client *ec = data;
1080 E_Comp_Object_Frame *fr = event_info;
1081
1082 if (!_e_comp_x_client_data_get(ec)) return;
1083 if (evas_object_visible_get(obj))
1084 _e_comp_x_client_frame_update(ec, fr->l, fr->r, fr->t, fr->b);
1085 else
1086 _e_comp_x_client_data_get(ec)->frame_update = 1;
1087 ec->post_move = ec->post_resize = 1;
1088 _e_comp_x_post_client_idler_add(ec);
1089 }
1090
1091 static void
_e_comp_x_evas_move_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1092 _e_comp_x_evas_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1093 {
1094 E_Client *ec = data;
1095
1096 if (!_e_comp_x_client_data_get(ec)) return;
1097 if (_e_comp_x_client_data_get(ec)->moving && (!_e_comp_x_client_data_get(ec)->unredirected_single))
1098 {
1099 if (_e_comp_x_client_data_get(ec)->move_counter++ < MOVE_COUNTER_LIMIT) return;
1100 _e_comp_x_client_data_get(ec)->move_counter = 0;
1101 }
1102
1103 ecore_x_window_shadow_tree_flush();
1104 ec->post_move = 1;
1105 _e_comp_x_post_client_idler_add(ec);
1106 }
1107
1108 static void
_e_comp_x_evas_resize_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1109 _e_comp_x_evas_resize_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1110 {
1111 E_Client *ec = data;
1112
1113 if (!_e_comp_x_client_data_get(ec)) return;
1114 if (ec->shading || ec->shaded) return;
1115 if (!e_pixmap_size_changed(ec->pixmap, ec->client.w, ec->client.h)) return;
1116
1117 ecore_x_window_shadow_tree_flush();
1118
1119 if (ec->e.state.video)
1120 {
1121 if (ec->e.state.video_position.updated)
1122 {
1123 ecore_x_window_move(e_client_util_pwin_get(ec),
1124 ec->e.state.video_parent_client->client.x +
1125 ec->e.state.video_position.x,
1126 ec->e.state.video_parent_client->client.y +
1127 ec->e.state.video_position.y);
1128 ec->e.state.video_position.updated = 0;
1129 }
1130 }
1131 else if (ec->changes.pos)
1132 {
1133 E_Client *tmp;
1134 Eina_List *l;
1135
1136 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1137 ecore_x_window_move(e_client_util_pwin_get(tmp),
1138 ec->client.x + tmp->e.state.video_position.x,
1139 ec->client.y + tmp->e.state.video_position.y);
1140 }
1141
1142 ec->post_resize = 1;
1143 if (e_pixmap_is_x(ec->pixmap))
1144 e_comp_object_render_update_del(ec->frame);
1145 _e_comp_x_post_client_idler_add(ec);
1146 }
1147
1148 static void
_e_comp_x_client_hide(E_Client * ec)1149 _e_comp_x_client_hide(E_Client *ec)
1150 {
1151 unsigned int visible = 0;
1152
1153 ecore_x_window_shadow_tree_flush();
1154 if ((!ec->iconic) && (!ec->override))
1155 ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_MAPPED, &visible, 1);
1156
1157 _e_comp_x_client_data_get(ec)->iconic = ec->iconic && (!e_comp_object_mirror_visibility_check(ec->frame));
1158 if (ec->unredirected_single || _e_comp_x_client_data_get(ec)->iconic)
1159 ecore_x_window_hide(_e_comp_x_client_window_get(ec));
1160 if (_e_comp_x_client_data_get(ec)->iconic)
1161 e_hints_window_iconic_set(ec);
1162 }
1163
1164 static void
_e_comp_x_evas_hide_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1165 _e_comp_x_evas_hide_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1166 {
1167 E_Client *ec = data, *tmp;
1168 Eina_List *l;
1169
1170 if (ec == mouse_client)
1171 {
1172 mouse_client = NULL;
1173 E_FREE_FUNC(mouse_in_job, ecore_job_del);
1174 }
1175
1176 if (!_e_comp_x_client_data_get(ec)) return; // already deleted, happens with internal wins
1177 _e_comp_x_client_hide(ec);
1178
1179 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1180 evas_object_hide(tmp->frame);
1181
1182 if (e_comp_config_get()->send_flush)
1183 ecore_x_e_comp_flush_send(e_client_util_win_get(ec));
1184 if (e_comp_config_get()->send_dump)
1185 ecore_x_e_comp_dump_send(e_client_util_win_get(ec));
1186 }
1187
1188 static void
_e_comp_x_client_show(E_Client * ec)1189 _e_comp_x_client_show(E_Client *ec)
1190 {
1191 unsigned int visible = 1;
1192 Ecore_X_Window win;
1193
1194 win = e_client_util_win_get(ec);
1195 ecore_x_window_shadow_tree_flush();
1196 if ((!_e_comp_x_client_data_get(ec)->need_reparent) && (!ec->override))
1197 ecore_x_window_show(win);
1198 if (ec->unredirected_single || _e_comp_x_client_data_get(ec)->iconic)
1199 {
1200 e_pixmap_clear(ec->pixmap);
1201 ecore_x_window_show(_e_comp_x_client_window_get(ec));
1202 _e_comp_x_client_data_get(ec)->iconic = 0;
1203 }
1204 if (!ec->override)
1205 e_hints_window_visible_set(ec);
1206
1207 ecore_x_window_prop_card32_set(win, E_ATOM_MAPPED, &visible, 1);
1208 ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
1209 }
1210
1211 static void
_e_comp_x_evas_show_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1212 _e_comp_x_evas_show_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1213 {
1214 E_Client *ec = data, *tmp;
1215 Eina_List *l;
1216
1217 if (!_e_comp_x_client_data_get(ec)) return;
1218 _e_comp_x_client_show(ec);
1219
1220 if (_e_comp_x_client_data_get(ec)->frame_update)
1221 {
1222 int ll, r, t, b;
1223
1224 e_comp_object_frame_geometry_get(obj, &ll, &r, &t, &b);
1225 _e_comp_x_client_frame_update(ec, ll, r, t, b);
1226 }
1227
1228 EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
1229 {
1230 evas_object_show(tmp->frame);
1231 ecore_x_window_show(e_client_util_pwin_get(tmp));
1232 }
1233 }
1234
1235 static void
_e_comp_x_evas_stack_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj,void * event_info EINA_UNUSED)1236 _e_comp_x_evas_stack_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1237 {
1238 if (evas_object_data_get(obj, "client_restack"))
1239 _e_comp_x_client_stack(data);
1240 }
1241
1242 static void
_e_comp_x_evas_unfullscreen_zoom_cb(void * data EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1243 _e_comp_x_evas_unfullscreen_zoom_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1244 {
1245 if ((screen_size.width != -1) && (screen_size.height != -1))
1246 {
1247 ecore_x_randr_screen_primary_output_size_set(e_comp->root,
1248 screen_size_index);
1249 screen_size.width = -1;
1250 screen_size.height = -1;
1251 }
1252 }
1253
1254 static void
_e_comp_x_evas_fullscreen_zoom_cb(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1255 _e_comp_x_evas_fullscreen_zoom_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1256 {
1257 E_Client *ec = data;
1258 Ecore_X_Randr_Screen_Size_MM *sizes;
1259 int num_sizes, i, best_size_index = 0;
1260
1261 ecore_x_randr_screen_primary_output_current_size_get(e_comp->root,
1262 &screen_size.width,
1263 &screen_size.height,
1264 NULL, NULL, NULL);
1265 sizes = ecore_x_randr_screen_primary_output_sizes_get(e_comp->root,
1266 &num_sizes);
1267 if (sizes)
1268 {
1269 Ecore_X_Randr_Screen_Size best_size = { -1, -1 };
1270 int best_dist = INT_MAX, dist;
1271
1272 for (i = 0; i < num_sizes; i++)
1273 {
1274 if ((sizes[i].width > ec->w) && (sizes[i].height > ec->h))
1275 {
1276 dist = (sizes[i].width * sizes[i].height) - (ec->w * ec->h);
1277 if (dist < best_dist)
1278 {
1279 best_size.width = sizes[i].width;
1280 best_size.height = sizes[i].height;
1281 best_dist = dist;
1282 best_size_index = i;
1283 }
1284 }
1285 }
1286 if (((best_size.width != -1) && (best_size.height != -1)) &&
1287 ((best_size.width != screen_size.width) ||
1288 (best_size.height != screen_size.height)))
1289 {
1290 if (ecore_x_randr_screen_primary_output_size_set(e_comp->root,
1291 best_size_index))
1292 screen_size_index = best_size_index;
1293 evas_object_geometry_set(ec->frame, 0, 0, best_size.width, best_size.height);
1294 }
1295 else
1296 {
1297 screen_size.width = -1;
1298 screen_size.height = -1;
1299 evas_object_geometry_set(ec->frame, 0, 0, ec->zone->w, ec->zone->h);
1300 }
1301 free(sizes);
1302 }
1303 else
1304 {
1305 evas_object_geometry_set(ec->frame, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h);
1306 }
1307 }
1308
1309 static Eina_Bool
_e_comp_x_destroy(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Destroy * ev)1310 _e_comp_x_destroy(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Destroy *ev)
1311 {
1312 E_Client *ec;
1313
1314 //INF("X DESTROY: %u", ev->win);
1315 e_comp_ignore_win_del(E_PIXMAP_TYPE_X, ev->win);
1316 ec = _e_comp_x_client_find_by_window(ev->win);
1317 if (!ec)
1318 {
1319 if (!e_comp_x->retry_clients) return ECORE_CALLBACK_RENEW;
1320 e_comp_x->retry_clients = eina_list_remove(e_comp_x->retry_clients, (uintptr_t*)(unsigned long)ev->win);
1321 if (!e_comp_x->retry_clients)
1322 E_FREE_FUNC(e_comp_x->retry_timer, ecore_timer_del);
1323 return ECORE_CALLBACK_PASS_ON;
1324 }
1325 if (_e_comp_x_client_data_get(ec))
1326 {
1327 if (_e_comp_x_client_data_get(ec)->reparented)
1328 e_client_comp_hidden_set(ec, 1);
1329 evas_object_pass_events_set(ec->frame, 1);
1330 evas_object_hide(ec->frame);
1331 _e_comp_x_client_data_get(ec)->deleted = 1;
1332 DELD(ec, 2);
1333 e_object_del(E_OBJECT(ec));
1334 }
1335 return ECORE_CALLBACK_PASS_ON;
1336 }
1337
1338 static Eina_Bool
_e_comp_x_resize_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Resize_Request * ev)1339 _e_comp_x_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Resize_Request *ev)
1340 {
1341 E_Client *ec;
1342 int w, h;
1343
1344 ec = _e_comp_x_client_find_by_window(ev->win);
1345 if (!ec)
1346 {
1347 if (!e_comp_find_by_window(ev->win)) ecore_x_window_resize(ev->win, ev->w, ev->h);
1348 return ECORE_CALLBACK_PASS_ON;
1349 }
1350 w = ev->w, h = ev->h;
1351 if (ec->zone && (e_config->geometry_auto_resize_limit == 1))
1352 {
1353 int zx, zy, zw, zh;
1354
1355 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
1356 if (w > zw)
1357 w = zw;
1358
1359 if (h > zh)
1360 h = zh;
1361 }
1362 if ((w != ec->w) || (h != ec->h))
1363 {
1364 evas_object_resize(ec->frame, w, h);
1365 }
1366 return ECORE_CALLBACK_RENEW;
1367 }
1368
1369 static void
_e_comp_x_evas_mirror_hidden(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1370 _e_comp_x_evas_mirror_hidden(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1371 {
1372 E_Client *ec = data;
1373
1374 if (!_e_comp_x_client_data_get(ec)) return;
1375 if ((!ec->iconic) || (!_e_comp_x_client_data_get(ec)->iconic)) return;
1376 _e_comp_x_client_hide(ec);
1377 }
1378
1379 static void
_e_comp_x_evas_mirror_visible(void * data,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)1380 _e_comp_x_evas_mirror_visible(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1381 {
1382 E_Client *ec = data;
1383
1384 if (!_e_comp_x_client_data_get(ec)) return;
1385 if ((!ec->iconic) || _e_comp_x_client_data_get(ec)->iconic) return;
1386 _e_comp_x_client_show(ec);
1387 }
1388
1389 static void
_e_comp_x_client_evas_init(E_Client * ec)1390 _e_comp_x_client_evas_init(E_Client *ec)
1391 {
1392 if (_e_comp_x_client_data_get(ec)->evas_init) return;
1393 _e_comp_x_client_data_get(ec)->evas_init = 1;
1394 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_comp_x_evas_stack_cb, ec);
1395 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_comp_x_evas_show_cb, ec);
1396 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_comp_x_evas_hide_cb, ec);
1397 if (!ec->override)
1398 {
1399 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_comp_x_evas_move_cb, ec);
1400 evas_object_smart_callback_add(ec->frame, "client_resize", _e_comp_x_evas_resize_cb, ec);
1401 }
1402 evas_object_smart_callback_add(ec->frame, "frame_recalc_done", _e_comp_x_evas_frame_recalc_cb, ec);
1403 evas_object_smart_callback_add(ec->frame, "shade_done", _e_comp_x_evas_shade_cb, ec);
1404 evas_object_smart_callback_add(ec->frame, "comp_hidden", _e_comp_x_evas_comp_hidden_cb, ec);
1405 evas_object_smart_callback_add(ec->frame, "delete_request", _e_comp_x_evas_delete_request_cb, ec);
1406 evas_object_smart_callback_add(ec->frame, "kill_request", _e_comp_x_evas_kill_cb, ec);
1407 evas_object_smart_callback_add(ec->frame, "ping", _e_comp_x_evas_ping_cb, ec);
1408 evas_object_smart_callback_add(ec->frame, "color_set", _e_comp_x_evas_color_set_cb, ec);
1409 evas_object_smart_callback_add(ec->frame, "fullscreen_zoom", _e_comp_x_evas_fullscreen_zoom_cb, ec);
1410 evas_object_smart_callback_add(ec->frame, "unfullscreen_zoom", _e_comp_x_evas_unfullscreen_zoom_cb, ec);
1411 evas_object_smart_callback_add(ec->frame, "visibility_force", _e_comp_x_evas_mirror_visible, ec);
1412 evas_object_smart_callback_add(ec->frame, "visibility_normal", _e_comp_x_evas_mirror_hidden, ec);
1413 /* force apply this since we haven't set up our smart cb previously */
1414 _e_comp_x_evas_comp_hidden_cb(ec, NULL, NULL);
1415 }
1416
1417 static Eina_Bool
_e_comp_x_object_add(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Comp_Object * ev)1418 _e_comp_x_object_add(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Comp_Object *ev)
1419 {
1420 E_Client *ec;
1421
1422 ec = e_comp_object_client_get(ev->comp_object);
1423 if ((!ec) || e_object_is_del(E_OBJECT(ec)) || ec->re_manage) return ECORE_CALLBACK_RENEW;
1424 E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
1425 _e_comp_x_client_evas_init(ec);
1426 _e_comp_x_client_stack(ec);
1427 return ECORE_CALLBACK_RENEW;
1428 }
1429
1430 static Eina_Bool
_e_comp_x_show_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Show_Request * ev)1431 _e_comp_x_show_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Show_Request *ev)
1432 {
1433 E_Client *ec;
1434
1435 //INF("X SHOW REQ: %u", ev->win);
1436 ec = _e_comp_x_client_find_by_window(ev->win);
1437 if (e_comp_ignore_win_find(ev->win) ||
1438 (ec && (ec->ignored || ec->override)) ||
1439 (!e_comp_find_by_window(ev->parent)) ||
1440 (ev->parent != e_comp->root))
1441 {
1442 if ((!ec) && (!eina_hash_find(dead_wins, &ev->parent)))
1443 {
1444 ecore_x_window_show(ev->win);
1445 return ECORE_CALLBACK_RENEW;
1446 }
1447 }
1448 if (!ec)
1449 ec = _e_comp_x_client_new(ev->win, 0);
1450 if (!ec)
1451 {
1452 ecore_x_window_show(ev->win);
1453 return ECORE_CALLBACK_RENEW;
1454 }
1455 if ((e_comp->comp_type != E_PIXMAP_TYPE_X) && ec->ignored)
1456 {
1457 ec->visible = 1;
1458 if (ec->comp_data->need_reparent)
1459 _e_comp_x_hook_client_pre_frame_assign(NULL, ec);
1460 else
1461 ecore_x_window_show(ev->win);
1462 return ECORE_CALLBACK_RENEW;
1463 }
1464
1465 if ((!_e_comp_x_client_data_get(ec)->reparented) && (!e_client_util_ignored_get(ec)))
1466 {
1467 if (!ec->override)
1468 _e_comp_x_client_data_get(ec)->need_reparent = 1;
1469 ec->visible = 1;
1470 EC_CHANGED(ec);
1471 return ECORE_CALLBACK_RENEW;
1472 }
1473 if (ec->iconic)
1474 {
1475 if (!ec->lock_client_iconify)
1476 e_client_uniconify(ec);
1477 }
1478 else
1479 {
1480 /* FIXME: make client "urgent" for a bit - it wants attention */
1481 /* e_client_show(ec); */
1482 if (!ec->lock_client_stacking)
1483 evas_object_raise(ec->frame);
1484 }
1485 return ECORE_CALLBACK_RENEW;
1486 }
1487
1488 static void
_e_comp_x_show_helper(E_Client * ec)1489 _e_comp_x_show_helper(E_Client *ec)
1490 {
1491 if ((!ec->override) && (!ec->re_manage) && (!_e_comp_x_client_data_get(ec)->first_map) &&
1492 (!_e_comp_x_client_data_get(ec)->reparented) && (!_e_comp_x_client_data_get(ec)->need_reparent))
1493 {
1494 /* this is most likely an internal window */
1495 _e_comp_x_client_data_get(ec)->need_reparent = 1;
1496 ec->visible = 1;
1497 if (ec->internal_elm_win)
1498 ec->take_focus = 1;
1499 EC_CHANGED(ec);
1500 }
1501 else if (ec->override)
1502 {
1503 if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
1504 {
1505 ec->visible = 1;
1506 return;
1507 }
1508 ec->redirected = !ec->input_only;
1509 ec->changes.visible = ec->visible = 1;
1510 EC_CHANGED(ec);
1511 if (!_e_comp_x_client_data_get(ec)->first_map)
1512 _e_comp_x_client_evas_init(ec);
1513 }
1514 if (!ec->input_only)
1515 _e_comp_x_client_damage_add(ec);
1516 if (!_e_comp_x_client_data_get(ec)->need_reparent)
1517 {
1518 e_pixmap_usable_set(ec->pixmap, 1);
1519 if (ec->hidden || ec->iconic)
1520 {
1521 evas_object_hide(ec->frame);
1522 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1523 }
1524 else if (ec->override || (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
1525 evas_object_show(ec->frame);
1526 _e_comp_x_client_data_get(ec)->first_map = 1;
1527 if (ec->internal_elm_win)
1528 {
1529 _e_comp_x_post_client_idler_add(ec);
1530 ec->post_move = 1;
1531 ec->post_resize = 1;
1532 e_comp_x->restack = 1;
1533 }
1534 }
1535 }
1536
1537 static Eina_Bool
_e_comp_x_show_retry(void * data EINA_UNUSED)1538 _e_comp_x_show_retry(void *data EINA_UNUSED)
1539 {
1540 uintptr_t *win;
1541
1542 EINA_LIST_FREE(e_comp_x->retry_clients, win)
1543 {
1544 E_Client *ec;
1545
1546 ec = _e_comp_x_client_new((Ecore_X_Window)(uintptr_t)win, 0);
1547 if (ec) _e_comp_x_show_helper(ec);
1548 }
1549
1550 e_comp_x->retry_timer = NULL;
1551 return EINA_FALSE;
1552 }
1553
1554 static Eina_Bool
_e_comp_x_show(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Show * ev)1555 _e_comp_x_show(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Show *ev)
1556 {
1557 E_Client *ec;
1558
1559 //INF("X SHOW: %u", ev->win);
1560 ec = _e_comp_x_client_find_by_window(ev->win);
1561 if (!ec)
1562 {
1563 E_Comp *c;
1564
1565 if (e_comp_ignore_win_find(ev->win)) return ECORE_CALLBACK_RENEW;
1566 c = e_comp_find_by_window(ev->event_win);
1567 if (!c) return ECORE_CALLBACK_RENEW;
1568 if (ev->event_win != e_comp->root) return ECORE_CALLBACK_RENEW;
1569 if ((c->win == ev->win) || (c->ee_win == ev->win) ||
1570 (c->root == ev->win) || (c->cm_selection == ev->win)) return ECORE_CALLBACK_RENEW;
1571 /* some window which we haven't made a client for yet but need to */
1572 ec = _e_comp_x_client_new(ev->win, 0);
1573 if (!ec)
1574 {
1575 if (c->x_comp_data->retry_timer)
1576 ecore_timer_loop_reset(c->x_comp_data->retry_timer);
1577 else
1578 c->x_comp_data->retry_timer = ecore_timer_loop_add(0.02, _e_comp_x_show_retry, c);
1579 c->x_comp_data->retry_clients = eina_list_append(c->x_comp_data->retry_clients, (uintptr_t*)(unsigned long)ev->win);
1580 return ECORE_CALLBACK_RENEW;
1581 }
1582 }
1583 else if (e_object_is_del(E_OBJECT(ec)) || ec->already_unparented)
1584 return ECORE_CALLBACK_RENEW;
1585 _e_comp_x_show_helper(ec);
1586 if (ec->internal || (!ec->override))
1587 _e_comp_x_client_stack(ec);
1588 return ECORE_CALLBACK_RENEW;
1589 }
1590
1591 static Eina_Bool
_e_comp_x_hide(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Hide * ev)1592 _e_comp_x_hide(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Hide *ev)
1593 {
1594 E_Client *ec;
1595 Eina_Bool hid = EINA_FALSE;
1596
1597 //INF("X HIDE: %u", ev->win);
1598 ec = _e_comp_x_client_find_by_window(ev->win);
1599 if (!ec)
1600 {
1601 if (!e_comp_x->retry_clients) return ECORE_CALLBACK_RENEW;
1602 e_comp_x->retry_clients = eina_list_remove(e_comp_x->retry_clients, (uintptr_t*)(unsigned long)ev->win);
1603 if (!e_comp_x->retry_clients)
1604 E_FREE_FUNC(e_comp_x->retry_timer, ecore_timer_del);
1605 return ECORE_CALLBACK_PASS_ON;
1606 }
1607 if ((!ec->visible) || (ec->hidden && ec->unredirected_single))
1608 {
1609 //INF("IGNORED");
1610 return ECORE_CALLBACK_PASS_ON;
1611 }
1612
1613 if (ev->win != ev->event_win)
1614 {
1615 if ((!ec->override) && (!ev->send_event)) return ECORE_CALLBACK_PASS_ON;
1616 }
1617 if (ec->ignore_first_unmap > 0)
1618 {
1619 ec->ignore_first_unmap--;
1620 return ECORE_CALLBACK_PASS_ON;
1621 }
1622 /* Don't delete hidden or iconified windows */
1623 if (ec->iconic)
1624 {
1625 /* Only hide the border if it is visible */
1626 hid = EINA_TRUE;
1627 evas_object_hide(ec->frame);
1628 }
1629 else
1630 {
1631 hid = EINA_TRUE;
1632 evas_object_hide(ec->frame);
1633 if (ec->internal)
1634 e_hints_window_hidden_set(ec);
1635 else
1636 {
1637 if (ec->exe_inst && ec->exe_inst->exe)
1638 ec->exe_inst->phony = 0;
1639 DELD(ec, 3);
1640 e_object_del(E_OBJECT(ec));
1641 }
1642 }
1643 if (hid)
1644 _e_comp_x_focus_check();
1645 return ECORE_CALLBACK_PASS_ON;
1646 }
1647
1648 static Eina_Bool
_e_comp_x_reparent(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Reparent * ev)1649 _e_comp_x_reparent(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Reparent *ev)
1650 {
1651 E_Client *ec;
1652
1653 ec = _e_comp_x_client_find_by_window(ev->win);
1654 if ((!ec) || (ev->win == e_client_util_pwin_get(ec))) return ECORE_CALLBACK_PASS_ON;
1655 DBG("== repar [%u] to [%u]", ev->win, ev->parent);
1656 /* FIXME: this is almost definitely wrong */
1657 if (ev->parent != e_client_util_pwin_get(ec))
1658 {
1659 e_pixmap_parent_window_set(ec->pixmap, ev->parent);
1660 if (!e_object_is_del(E_OBJECT(ec)))
1661 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
1662 }
1663 return ECORE_CALLBACK_PASS_ON;
1664 }
1665
1666 static Eina_Bool
_e_comp_x_configure(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Configure * ev)1667 _e_comp_x_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure *ev)
1668 {
1669 E_Client *ec;
1670 Eina_Bool move, resize;
1671
1672 if (e_comp_find_by_window(ev->win))
1673 {
1674 // do not handle this here - use randr events
1675 //e_comp_canvas_resize(ev->w, ev->h);
1676 return ECORE_CALLBACK_RENEW;
1677 }
1678 ec = _e_comp_x_client_find_by_window(ev->win);
1679 if ((!ec) || (!ec->override) || (!ev->override) || e_client_is_stacking(ec)) return ECORE_CALLBACK_PASS_ON;
1680
1681 //INF("configure %p: %d,%d %dx%d", ec, ev->x, ev->y, ev->w, ev->h);
1682 if (ev->abovewin == 0)
1683 {
1684 if (e_client_below_get(ec))
1685 evas_object_lower(ec->frame);
1686 }
1687 else
1688 {
1689 E_Client *ec2 = _e_comp_x_client_find_by_window(ev->abovewin);
1690
1691 if (ec2)
1692 {
1693 /* client(ec) wants to be above a layer client(ec2) */
1694 if (e_client_is_stacking(ec2)) //is it a stacking placeholder window?
1695 {
1696 E_Client *ec3;
1697
1698 ec3 = e_client_above_get(ec2);
1699 /* stack under next client(ec3) */
1700 if (ec3)
1701 {
1702 evas_object_layer_set(ec->frame, ec3->layer);
1703 if (!e_client_is_stacking(ec3))
1704 evas_object_stack_below(ec->frame, ec3->frame);
1705 }
1706 else //force override to obey our stacking
1707 evas_object_layer_set(ec->frame, ec2->layer);
1708 }
1709 else
1710 {
1711 evas_object_layer_set(ec->frame, ec2->layer);
1712 evas_object_stack_above(ec->frame, ec2->frame);
1713 }
1714 }
1715 else
1716 evas_object_layer_set(ec->frame, E_LAYER_CLIENT_PRIO);
1717 }
1718 move = (ec->client.x != ev->x) || (ec->client.y != ev->y);
1719 resize = (ec->client.w != ev->w) || (ec->client.h != ev->h);
1720 if (!ec->internal)
1721 _e_comp_x_client_data_get(ec)->pw = ev->w, _e_comp_x_client_data_get(ec)->ph = ev->h;
1722 EINA_RECTANGLE_SET(&ec->client, ev->x, ev->y, ev->w, ev->h);
1723 if (move)
1724 evas_object_move(ec->frame, ev->x, ev->y);
1725 if (resize && e_pixmap_is_x(ec->pixmap))
1726 {
1727 e_pixmap_dirty(ec->pixmap);
1728 evas_object_resize(ec->frame, ev->w, ev->h);
1729 }
1730 return ECORE_CALLBACK_RENEW;
1731 }
1732
1733 static Eina_Bool
_e_comp_x_configure_request_timer(void * d)1734 _e_comp_x_configure_request_timer(void *d)
1735 {
1736 Pending_Configure *pc = d;
1737 eina_hash_list_remove(pending_configures, &pc->win, pc);
1738 free(pc);
1739 return EINA_FALSE;
1740 }
1741
1742 static Eina_Bool
_e_comp_x_configure_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Configure_Request * ev)1743 _e_comp_x_configure_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Configure_Request *ev)
1744 {
1745 E_Client *ec;
1746 Eina_Bool move = EINA_FALSE, resize = EINA_FALSE;
1747 int ox, oy, ow, oh;
1748 int x, y, w, h;
1749
1750 // printf("configure request {0x%08x} %4i,%4i %4ix%4i b=%i [%c%c%c%c]\n",
1751 // ev->win, ev->x, ev->y, ev->w, ev->h, ev->border,
1752 // ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X ? 'x' : ' ',
1753 // ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y ? 'y' : ' ',
1754 // ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W ? 'w' : ' ',
1755 // ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H ? 'h' : ' ');
1756 if (e_comp_find_by_window(ev->win)) return ECORE_CALLBACK_RENEW;
1757 ec = _e_comp_x_client_find_by_window(ev->win);
1758
1759 /* pass through requests for windows we haven't/won't reparent yet */
1760 if (ec && (!_e_comp_x_client_data_get(ec)->need_reparent) && (!_e_comp_x_client_data_get(ec)->reparented))
1761 {
1762 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
1763 _e_comp_x_client_data_get(ec)->initial_attributes.x = ev->x;
1764 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
1765 _e_comp_x_client_data_get(ec)->initial_attributes.y = ev->y;
1766 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
1767 ec->w = ec->client.w = _e_comp_x_client_data_get(ec)->initial_attributes.w = ev->w;
1768 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
1769 ec->h = ec->client.h = _e_comp_x_client_data_get(ec)->initial_attributes.h = ev->h;
1770 ec->border_size = ev->border;
1771 ec->changes.size = 1;
1772 ec = NULL;
1773 }
1774 if (!ec)
1775 {
1776 if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
1777 (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
1778 {
1779 Pending_Configure *pc = E_NEW(Pending_Configure, 1);
1780 pc->point.x = ev->x;
1781 pc->point.y = ev->y;
1782 pc->timer = ecore_timer_loop_add(5.0, _e_comp_x_configure_request_timer, pc);
1783 pc->win = ev->win;
1784 eina_hash_list_append(pending_configures, &ev->win, pc);
1785 }
1786 ecore_x_window_configure(ev->win, ev->value_mask,
1787 ev->x, ev->y, ev->w, ev->h, ev->border,
1788 ev->abovewin, ev->detail);
1789 return ECORE_CALLBACK_PASS_ON;
1790 }
1791
1792 x = ox = ec->client.x;
1793 y = oy = ec->client.y;
1794 w = ow = ec->client.w;
1795 h = oh = ec->client.h;
1796
1797 if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
1798 (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
1799 {
1800 int zx, zy, zw, zh;
1801
1802 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
1803 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X)
1804 {
1805 _e_comp_x_client_data_get(ec)->initial_attributes.x = ev->x;
1806 if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1807 x = E_CLAMP(ev->x, zx, zx + zw - ec->w);
1808 else
1809 x = ev->x;
1810 }
1811 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y)
1812 {
1813 _e_comp_x_client_data_get(ec)->initial_attributes.y = ev->y;
1814 if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1815 y = E_CLAMP(ev->y, zy, zy + zh - ec->h);
1816 else
1817 y = ev->y;
1818 }
1819 }
1820
1821 if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
1822 (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
1823 {
1824 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W)
1825 w = ev->w, _e_comp_x_client_data_get(ec)->initial_attributes.w = ev->w;
1826 if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H)
1827 h = ev->h, _e_comp_x_client_data_get(ec)->initial_attributes.h = ev->h;
1828 }
1829
1830 e_comp_object_frame_xy_adjust(ec->frame, x, y, &x, &y);
1831 e_comp_object_frame_wh_adjust(ec->frame, w, h, &w, &h);
1832
1833 if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_X) ||
1834 (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_Y))
1835 move = (x != ec->x) || (y != ec->y);
1836 if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_W) ||
1837 (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_H))
1838 resize = (w != ec->w) || (h != ec->h);
1839
1840 if (move && (!ec->lock_client_location))
1841 {
1842 if ((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE)
1843 {
1844 E_Zone *zone;
1845
1846 e_comp_object_frame_xy_unadjust(ec->frame, x, y, &ec->saved.x, &ec->saved.y);
1847
1848 zone = e_comp_zone_xy_get(x, y);
1849 if (zone && (zone->x || zone->y))
1850 {
1851 ec->saved.x -= zone->x;
1852 ec->saved.y -= zone->y;
1853 }
1854 }
1855 else if (!ec->maximize_override)
1856 {
1857 /* client is completely outside the screen, policy does not allow */
1858 if (((!E_INTERSECTS(x, y, ec->w, ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1859 (e_config->screen_limits != E_CLIENT_OFFSCREEN_LIMIT_ALLOW_FULL)) ||
1860 /* client is partly outside the zone, policy does not allow */
1861 (((!E_INSIDE(x, y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1862 (!E_INSIDE(x + ec->w, y, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1863 (!E_INSIDE(x, y + ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5)) &&
1864 (!E_INSIDE(x + ec->w, y + ec->h, 0, 0, e_comp->w - 5, e_comp->h - 5))) &&
1865 (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE))
1866 )
1867 e_comp_object_util_center(ec->frame);
1868 else
1869 {
1870 evas_object_move(ec->frame, x, y);
1871 }
1872 }
1873 }
1874
1875 if (resize && (!ec->lock_client_size) && (move || ((!ec->maximized) && (!ec->fullscreen))))
1876 {
1877 if (ec->shaded || ((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE))
1878 e_comp_object_frame_wh_unadjust(ec->frame, w, h, &ec->saved.w, &ec->saved.h);
1879 else if (!ec->maximize_override)
1880 {
1881 evas_object_resize(ec->frame, w, h);
1882 }
1883 }
1884 if (!ec->lock_client_stacking)
1885 {
1886 if ((ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE) &&
1887 (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING))
1888 {
1889 E_Client *oec;
1890
1891 if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
1892 {
1893 oec = _e_comp_x_client_find_by_window(ev->abovewin);
1894 if (oec)
1895 {
1896 evas_object_stack_above(ec->frame, oec->frame);
1897 }
1898 else
1899 {
1900 ecore_x_window_configure(e_client_util_pwin_get(ec),
1901 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1902 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1903 0, 0, 0, 0, 0,
1904 ev->abovewin, ECORE_X_WINDOW_STACK_ABOVE);
1905 }
1906 }
1907 else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
1908 {
1909 oec = _e_comp_x_client_find_by_window(ev->abovewin);
1910 if (oec)
1911 {
1912 evas_object_stack_below(ec->frame, oec->frame);
1913 }
1914 else
1915 {
1916 ecore_x_window_configure(e_client_util_pwin_get(ec),
1917 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
1918 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
1919 0, 0, 0, 0, 0,
1920 ev->abovewin, ECORE_X_WINDOW_STACK_BELOW);
1921 }
1922 }
1923 else if (ev->detail == ECORE_X_WINDOW_STACK_TOP_IF)
1924 {
1925 /* FIXME: do */
1926 }
1927 else if (ev->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
1928 {
1929 /* FIXME: do */
1930 }
1931 else if (ev->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
1932 {
1933 /* FIXME: do */
1934 }
1935 }
1936 else if (ev->value_mask & ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE)
1937 {
1938 if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
1939 {
1940 evas_object_raise(ec->frame);
1941 }
1942 else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
1943 {
1944 evas_object_lower(ec->frame);
1945 }
1946 else if (ev->detail == ECORE_X_WINDOW_STACK_TOP_IF)
1947 {
1948 /* FIXME: do */
1949 }
1950 else if (ev->detail == ECORE_X_WINDOW_STACK_BOTTOM_IF)
1951 {
1952 /* FIXME: do */
1953 }
1954 else if (ev->detail == ECORE_X_WINDOW_STACK_OPPOSITE)
1955 {
1956 /* FIXME: do */
1957 }
1958 }
1959 }
1960
1961 /* FIXME: need to send synthetic stacking event to, as well as move/resize */
1962 if ((((ec->maximized & E_MAXIMIZE_TYPE) != E_MAXIMIZE_NONE) && (move || resize)) ||
1963 ((!move) && (!resize)))
1964 {
1965 _e_comp_x_client_move_resize_send(ec);
1966 }
1967 return ECORE_CALLBACK_PASS_ON;
1968 }
1969
1970 static Eina_Bool
_e_comp_x_stack_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Stack_Request * ev)1971 _e_comp_x_stack_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Stack_Request *ev)
1972 {
1973 E_Client *ec;
1974
1975 ec = _e_comp_x_client_find_by_window(ev->win);
1976 if (!ec) return ECORE_CALLBACK_RENEW;
1977 if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE)
1978 evas_object_raise(ec->frame);
1979 else if (ev->detail == ECORE_X_WINDOW_STACK_BELOW)
1980 evas_object_lower(ec->frame);
1981 return ECORE_CALLBACK_PASS_ON;
1982 }
1983
1984 static Eina_Bool
_e_comp_x_stack(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Stack * ev)1985 _e_comp_x_stack(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Stack *ev)
1986 {
1987 E_Client *ec = _e_comp_x_client_find_by_window(ev->win);
1988 if (!ec) return ECORE_CALLBACK_PASS_ON;
1989 if (ev->detail == ECORE_X_WINDOW_STACK_ABOVE) evas_object_raise(ec->frame);
1990 else evas_object_lower(ec->frame);
1991 return ECORE_CALLBACK_PASS_ON;
1992 }
1993
1994 static Eina_Bool
_e_comp_x_property(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Property * ev)1995 _e_comp_x_property(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Property *ev)
1996 {
1997 E_Client *ec;
1998
1999 ec = _e_comp_x_client_find_by_window(ev->win);
2000 if (!ec) return ECORE_CALLBACK_RENEW;
2001
2002 if (ev->atom == ECORE_X_ATOM_WM_NAME)
2003 {
2004 if ((!ec->netwm.name) &&
2005 (!ec->netwm.fetch.name))
2006 {
2007 ec->icccm.fetch.title = 1;
2008 EC_CHANGED(ec);
2009 }
2010 }
2011 else if (ev->atom == ECORE_X_ATOM_NET_WM_NAME)
2012 {
2013 ec->netwm.fetch.name = 1;
2014 EC_CHANGED(ec);
2015 }
2016 else if (ev->atom == ECORE_X_ATOM_WM_CLASS)
2017 {
2018 ec->icccm.fetch.name_class = 1;
2019 EC_CHANGED(ec);
2020 }
2021 else if (ev->atom == ECORE_X_ATOM_WM_ICON_NAME)
2022 {
2023 if ((!ec->netwm.icon_name) &&
2024 (!ec->netwm.fetch.icon_name))
2025 {
2026 ec->icccm.fetch.icon_name = 1;
2027 EC_CHANGED(ec);
2028 }
2029 }
2030 else if (ev->atom == ECORE_X_ATOM_NET_WM_ICON_NAME)
2031 {
2032 ec->netwm.fetch.icon_name = 1;
2033 EC_CHANGED(ec);
2034 }
2035 else if (ev->atom == ECORE_X_ATOM_WM_CLIENT_MACHINE)
2036 {
2037 ec->icccm.fetch.machine = 1;
2038 EC_CHANGED(ec);
2039 }
2040 else if (ev->atom == ECORE_X_ATOM_WM_PROTOCOLS)
2041 {
2042 ec->icccm.fetch.protocol = 1;
2043 EC_CHANGED(ec);
2044 }
2045 else if (ev->atom == ECORE_X_ATOM_WM_HINTS)
2046 {
2047 ec->icccm.fetch.hints = 1;
2048 EC_CHANGED(ec);
2049 if (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
2050 ec->ignored = 0;
2051 }
2052 else if (ev->atom == ECORE_X_ATOM_WM_NORMAL_HINTS)
2053 {
2054 if (_e_comp_x_client_data_get(ec)->internal_props_set)
2055 _e_comp_x_client_data_get(ec)->internal_props_set--;
2056 else
2057 {
2058 ec->icccm.fetch.size_pos_hints = 1;
2059 EC_CHANGED(ec);
2060 }
2061 }
2062 else if (ev->atom == ECORE_X_ATOM_MOTIF_WM_HINTS)
2063 {
2064 /*
2065 if ((ec->netwm.type == E_WINDOW_TYPE_UNKNOWN) &&
2066 (!ec->netwm.fetch.type))
2067 {
2068 */
2069 ec->mwm.fetch.hints = 1;
2070 EC_CHANGED(ec);
2071 /*
2072 }
2073 */
2074 }
2075 else if (ev->atom == ECORE_X_ATOM_WM_TRANSIENT_FOR)
2076 {
2077 ec->icccm.fetch.transient_for = 1;
2078 EC_CHANGED(ec);
2079 }
2080 else if (ev->atom == ECORE_X_ATOM_WM_CLIENT_LEADER)
2081 {
2082 ec->icccm.fetch.client_leader = 1;
2083 EC_CHANGED(ec);
2084 }
2085 else if (ev->atom == ECORE_X_ATOM_WM_WINDOW_ROLE)
2086 {
2087 ec->icccm.fetch.window_role = 1;
2088 EC_CHANGED(ec);
2089 }
2090 else if (ev->atom == ECORE_X_ATOM_NET_WM_ICON)
2091 {
2092 ec->netwm.fetch.icon = 1;
2093 EC_CHANGED(ec);
2094 }
2095 else if (ev->atom == ATM__QTOPIA_SOFT_MENU)
2096 {
2097 ec->qtopia.fetch.soft_menu = 1;
2098 EC_CHANGED(ec);
2099 }
2100 else if (ev->atom == ATM__QTOPIA_SOFT_MENUS)
2101 {
2102 ec->qtopia.fetch.soft_menus = 1;
2103 EC_CHANGED(ec);
2104 }
2105 else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
2106 {
2107 ec->vkbd.fetch.state = 1;
2108 EC_CHANGED(ec);
2109 }
2110 else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD)
2111 {
2112 ec->vkbd.fetch.vkbd = 1;
2113 EC_CHANGED(ec);
2114 }
2115 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CONFORMANT)
2116 {
2117 _e_comp_x_client_data_get(ec)->illume.conformant.fetch.conformant = 1;
2118 EC_CHANGED(ec);
2119 }
2120 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_STATE)
2121 {
2122 _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.state = 1;
2123 EC_CHANGED(ec);
2124 }
2125 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL)
2126 {
2127 _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.quickpanel = 1;
2128 EC_CHANGED(ec);
2129 }
2130 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MAJOR)
2131 {
2132 _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.priority.major = 1;
2133 EC_CHANGED(ec);
2134 }
2135 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_PRIORITY_MINOR)
2136 {
2137 _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.priority.minor = 1;
2138 EC_CHANGED(ec);
2139 }
2140 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_QUICKPANEL_ZONE)
2141 {
2142 _e_comp_x_client_data_get(ec)->illume.quickpanel.fetch.zone = 1;
2143 EC_CHANGED(ec);
2144 }
2145 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_DRAG_LOCKED)
2146 {
2147 _e_comp_x_client_data_get(ec)->illume.drag.fetch.locked = 1;
2148 EC_CHANGED(ec);
2149 }
2150 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_DRAG)
2151 {
2152 _e_comp_x_client_data_get(ec)->illume.drag.fetch.drag = 1;
2153 EC_CHANGED(ec);
2154 }
2155 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_WINDOW_STATE)
2156 {
2157 _e_comp_x_client_data_get(ec)->illume.win_state.fetch.state = 1;
2158 EC_CHANGED(ec);
2159 }
2160 /*
2161 else if (ev->atom == ECORE_X_ATOM_NET_WM_USER_TIME)
2162 {
2163 ec->netwm.fetch.user_time = 1;
2164 EC_CHANGED(ec);
2165 }
2166 else if (ev->atom == ECORE_X_ATOM_NET_WM_STRUT)
2167 {
2168 ec->netwm.fetch.strut = 1;
2169 EC_CHANGED(ec);
2170 }
2171 else if (ev->atom == ECORE_X_ATOM_NET_WM_STRUT_PARTIAL)
2172 {
2173 ec->netwm.fetch.strut = 1;
2174 EC_CHANGED(ec);
2175 }
2176 */
2177 else if (ev->atom == ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER)
2178 {
2179 //printf("ECORE_X_ATOM_NET_WM_SYNC_REQUEST_COUNTER\n");
2180 }
2181 else if (ev->atom == ECORE_X_ATOM_E_VIDEO_POSITION)
2182 {
2183 ec->e.fetch.video_position = 1;
2184 EC_CHANGED(ec);
2185 }
2186 else if (ev->atom == ECORE_X_ATOM_E_VIDEO_PARENT)
2187 {
2188 ec->e.fetch.video_parent = 1;
2189 EC_CHANGED(ec);
2190 }
2191 else if (ev->atom == ECORE_X_ATOM_NET_WM_STATE)
2192 {
2193 ec->netwm.fetch.state = 1;
2194 EC_CHANGED(ec);
2195 }
2196 else if (ev->atom == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
2197 {
2198 if (ec->netwm.opacity_changed)
2199 ec->netwm.opacity_changed = 0;
2200 else
2201 {
2202 ec->netwm.fetch.opacity = 1;
2203 EC_CHANGED(ec);
2204 }
2205 }
2206 else if (ev->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED)
2207 {
2208 ec->e.fetch.profile = 1;
2209 EC_CHANGED(ec);
2210 }
2211 else if (ev->atom == ECORE_X_ATOM_E_WINDOW_PROFILE_AVAILABLE_LIST)
2212 {
2213 ec->e.fetch.profile = 1;
2214 EC_CHANGED(ec);
2215 }
2216 else if (ev->atom == ATM_GTK_FRAME_EXTENTS)
2217 {
2218 _e_comp_x_client_data_get(ec)->fetch_gtk_frame_extents = 1;
2219 EC_CHANGED(ec);
2220 }
2221 else if (ev->atom == ATM_STEAM_GAME)
2222 {
2223 e_hints_window_steam_game_get(ec);
2224 ec->changes.icon = 1;
2225 EC_CHANGED(ec);
2226 }
2227
2228 return ECORE_CALLBACK_RENEW;
2229 }
2230
2231 static Eina_Bool
_e_comp_x_message(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Client_Message * ev)2232 _e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Client_Message *ev)
2233 {
2234 E_Client *ec;
2235
2236 ec = _e_comp_x_client_find_by_window(ev->win);
2237 if (!ec)
2238 {
2239 char *name;
2240
2241 if (!eina_log_domain_level_check(e_log_dom, EINA_LOG_LEVEL_DBG)) return ECORE_CALLBACK_RENEW;
2242 name = ecore_x_atom_name_get(ev->message_type);
2243 DBG("missed client message '%s' for %u", name, ev->win);
2244 free(name);
2245 return ECORE_CALLBACK_RENEW;
2246 }
2247 if (ev->message_type == ECORE_X_ATOM_NET_WM_WINDOW_OPACITY)
2248 {
2249 ec->netwm.fetch.opacity = 1;
2250 EC_CHANGED(ec);
2251 }
2252 else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE)
2253 {
2254 if (ec->e.state.profile.use)
2255 {
2256 char *p = ecore_x_atom_name_get(ev->data.l[1]);
2257 if (e_client_desk_window_profile_available_check(ec, p))
2258 {
2259 if (e_util_strcmp(p, ec->desk->window_profile))
2260 {
2261 E_Desk *old_desk = ec->desk;
2262 E_Desk *desk = e_comp_desk_window_profile_get(p);
2263 Eina_Bool was_focused = e_client_stack_focused_get(ec);
2264
2265 if ((desk) && (desk != old_desk))
2266 {
2267 e_client_desk_set(ec, desk);
2268 if (was_focused)
2269 e_desk_last_focused_focus(old_desk);
2270 }
2271 }
2272 }
2273 free(p);
2274 }
2275 }
2276 else if (ev->message_type == ECORE_X_ATOM_NET_ACTIVE_WINDOW)
2277 {
2278 #if 0 /* notes */
2279 if (e->data.l[0] == 0 /* 0 == old, 1 == client, 2 == pager */)
2280 {
2281 }
2282 timestamp = e->data.l[1];
2283 requestor_id e->data.l[2];
2284 #endif
2285 switch (e_config->window_activehint_policy)
2286 {
2287 case 0: break;
2288
2289 case 1:
2290 e_client_urgent_set(ec, 1);
2291 break;
2292
2293 default:
2294 if (e_client_action_get() || e_comp->nocomp)
2295 {
2296 /* be helpful and ignore activates during window actions, but still set urgent */
2297 e_client_urgent_set(ec, 1);
2298 break;
2299 }
2300 if ((!starting) && (!ec->focused))
2301 {
2302 if ((e_config->window_activehint_policy == E_ACTIVEHINT_POLICY_ACTIVATE_EXCLUDE) &&
2303 (!ec->desk->visible))
2304 e_client_urgent_set(ec, 1);
2305 else
2306 {
2307 /* some apps, eg. libreoffice, create "modal" windows which
2308 * do not have the netwm modal state set. instead, attempting to
2309 * focus the parent window results in the app immediately trying to
2310 * activate the "modal" window, triggering an infinite loop.
2311 *
2312 * by treating this "modal" window as a genuine modal window,
2313 * we (eventually) can ignore this type of bad behavior and
2314 * give the application/user the expected behavior
2315 */
2316 if (ec->parent && (!ec->parent->modal) && (e_client_focused_get() == ec->parent) &&
2317 (ev->time - focus_time < PARENT_ACTIVATE_TIME))
2318 {
2319 E_Comp_X_Client_Data *cd;
2320
2321 cd = _e_comp_x_client_data_get(ec);
2322 if (cd)
2323 {
2324 cd->parent_activate_count++;
2325 if (cd->parent_activate_count >= PARENT_ACTIVATE_LIMIT)
2326 _e_comp_x_client_modal_setup(ec);
2327 }
2328 }
2329 e_client_activate(ec, EINA_TRUE);
2330 }
2331 }
2332 else
2333 evas_object_raise(ec->frame);
2334 }
2335 }
2336 else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE_DONE)
2337 {
2338 if ((ec->e.state.profile.use) &&
2339 (ec->e.state.profile.wait_for_done))
2340 {
2341 char *p = ecore_x_atom_name_get(ev->data.l[1]);
2342 if (!e_util_strcmp(ec->e.state.profile.wait, p))
2343 {
2344 E_Desk *old_desk = ec->desk;
2345 E_Desk *desk = ec->e.state.profile.wait_desk;
2346 Eina_Bool was_focused = e_client_stack_focused_get(ec);
2347
2348 eina_stringshare_replace(&ec->e.state.profile.wait, NULL);
2349 ec->e.state.profile.wait_for_done = 0;
2350 if ((desk) && (desk != old_desk))
2351 {
2352 eina_stringshare_replace(&ec->e.state.profile.name,
2353 desk->window_profile);
2354 e_client_desk_set(ec, desk);
2355 if (was_focused)
2356 e_desk_last_focused_focus(old_desk);
2357 }
2358 e_client_desk_window_profile_wait_desk_set(ec, NULL);
2359 }
2360 free(p);
2361 }
2362 }
2363 else if (ev->message_type == ATM_NETWM_SHOW_WINDOW_MENU)
2364 {
2365 /*
2366 message_type = _NET_WM_SHOW_WINDOW_MENU
2367 window = window for which the menu should be shown
2368 format = 32
2369 data.l[0] = xinput2_device_id
2370 data.l[1] = root_x
2371 data.l[2] = root_y
2372 other data.l[] elements = 0
2373 */
2374
2375 int x, y;
2376
2377 x = ev->data.l[1];
2378 y = ev->data.l[2];
2379 e_int_client_menu_show(ec,
2380 e_comp_canvas_x_root_adjust(x),
2381 e_comp_canvas_y_root_adjust(y),
2382 0, 0);
2383 }
2384 else if (ev->message_type == ATM_NETWM_PERFORM_BUTTON_ACTION)
2385 {
2386 char emission[128];
2387 /*
2388 message_type = _NET_WM_PERFORM_BUTTON_ACTION
2389 window = window for which the action should be performed
2390 format = 32
2391 data.l[0] = xinput2_device_id
2392 data.l[1] = root_x
2393 data.l[2] = root_y
2394 data.l[3] = button
2395 data.l[4] = timestamp
2396 */
2397 if (e_dnd_active() || ec->iconic) return ECORE_CALLBACK_RENEW;
2398 switch (ev->data.l[3])
2399 {
2400 case 1:
2401 case 2:
2402 case 3:
2403 snprintf(emission, sizeof(emission), "mouse,down,%d", (int)ev->data.l[3]);
2404 e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(ec), emission, "e.event.titlebar");
2405 break;
2406 case 4:
2407 e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(ec), "mouse,wheel,?,-1", "e.event.titlebar");
2408 break;
2409 case 5:
2410 e_bindings_signal_handle(E_BINDING_CONTEXT_WINDOW, E_OBJECT(ec), "mouse,wheel,?,1", "e.event.titlebar");
2411 break;
2412 }
2413 }
2414 #ifdef HAVE_WAYLAND
2415 else if (ev->message_type == WL_SURFACE_ID)
2416 {
2417 void *res;
2418 E_Client *wc = NULL;
2419
2420 if (e_comp->comp_type != E_PIXMAP_TYPE_WL) return ECORE_CALLBACK_RENEW;
2421 res = wl_client_get_object(e_comp_wl->xwl_client, ev->data.l[0]);
2422 if (res)
2423 wc = wl_resource_get_user_data(res);
2424 if (wc)
2425 {
2426 if (wc->internal)
2427 {
2428 e_object_del(E_OBJECT(wc));
2429 e_object_del(E_OBJECT(ec));
2430 /* this is an xwayland bug. somehow the wrong surface is being passed
2431 * and it's an internal surface--internal surfaces are NEVER
2432 * xwayland clients.
2433 *
2434 * ever.
2435 */
2436 return ECORE_CALLBACK_RENEW;
2437 }
2438 e_comp_x_xwayland_client_setup(ec, wc);
2439 }
2440 else
2441 {
2442 ec->comp_data->surface_id = ev->data.l[0];
2443 e_comp_wl_xwayland_client_queue(ec);
2444 }
2445 }
2446 #endif
2447 else
2448 {
2449 char *name;
2450
2451 if (!eina_log_domain_level_check(e_log_dom, EINA_LOG_LEVEL_DBG)) return ECORE_CALLBACK_RENEW;
2452 name = ecore_x_atom_name_get(ev->message_type);
2453 DBG("missed client message '%s' for %u", name, ev->win);
2454 free(name);
2455 }
2456 return ECORE_CALLBACK_PASS_ON;
2457 }
2458
2459 static Eina_Bool
_e_comp_x_state_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_State_Request * ev)2460 _e_comp_x_state_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_State_Request *ev)
2461 {
2462 int i;
2463 E_Client *ec;
2464 int max;
2465
2466 ec = _e_comp_x_client_find_by_window(ev->win);
2467 if (!ec) return ECORE_CALLBACK_RENEW;
2468
2469 max = (1 << ev->state[0]) | (1 << ev->state[1]);
2470 if ((max & (1 << ECORE_X_WINDOW_STATE_MAXIMIZED_VERT)) &&
2471 (max & (1 << ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ)))
2472 e_hints_window_state_update(ec, INT_MAX, ev->action);
2473 else
2474 {
2475 for (i = 0; i < 2; i++)
2476 e_hints_window_state_update(ec, ev->state[i], ev->action);
2477 }
2478
2479 return ECORE_CALLBACK_RENEW;
2480 }
2481
2482 static Eina_Bool
_e_comp_x_mapping_change(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Mapping_Change * ev EINA_UNUSED)2483 _e_comp_x_mapping_change(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Mapping_Change *ev EINA_UNUSED)
2484 {
2485 const Eina_List *l;
2486 E_Client *ec;
2487
2488 if (_e_comp_x_mapping_change_disabled) return ECORE_CALLBACK_RENEW;
2489 e_comp_canvas_keys_ungrab();
2490 EINA_LIST_FOREACH(e_comp->clients, l, ec)
2491 {
2492 if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) continue;
2493 if ((!_e_comp_x_client_data_get(ec)->first_map) || (!_e_comp_x_client_data_get(ec)->reparented)) continue;
2494 if (ec->focused)
2495 {
2496 _e_comp_x_focus_setup(ec);
2497 _e_comp_x_focus_setdown(ec);
2498 }
2499 else
2500 {
2501 _e_comp_x_focus_setdown(ec);
2502 _e_comp_x_focus_setup(ec);
2503 e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
2504 e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
2505 }
2506 }
2507 e_comp_canvas_keys_grab();
2508 return ECORE_CALLBACK_PASS_ON;
2509 }
2510
2511 static void
_e_comp_x_mouse_in_job(void * d EINA_UNUSED)2512 _e_comp_x_mouse_in_job(void *d EINA_UNUSED)
2513 {
2514 if (mouse_client)
2515 e_client_mouse_in(mouse_client, e_comp_canvas_x_root_adjust(mouse_in_coords.x), e_comp_canvas_y_root_adjust(mouse_in_coords.y));
2516 mouse_in_job = NULL;
2517 }
2518
2519 static Eina_Bool
_e_comp_x_mouse_in_fix_check_timer_cb(void * data EINA_UNUSED)2520 _e_comp_x_mouse_in_fix_check_timer_cb(void *data EINA_UNUSED)
2521 {
2522 E_Client *ec = NULL, *cec;
2523 int x, y;
2524
2525 mouse_in_fix_check_timer = NULL;
2526 if (e_grabinput_key_win_get() || e_grabinput_mouse_win_get())
2527 return EINA_FALSE;
2528 ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
2529 E_CLIENT_REVERSE_FOREACH(cec)
2530 {
2531 /* If a border was specified which should be excluded from the list
2532 * (because it will be closed shortly for example), skip */
2533 if ((!e_client_util_desk_visible(cec, e_desk_current_get(e_zone_current_get())))) continue;
2534 if (!evas_object_visible_get(cec->frame)) continue;
2535 if (!E_INSIDE(x, y, cec->x, cec->y, cec->w, cec->h))
2536 continue;
2537 /* If the layer is higher, the position of the window is higher
2538 * (always on top vs always below) */
2539 if (!ec || (cec->layer > ec->layer))
2540 ec = cec;
2541 }
2542 if (ec)
2543 {
2544 mouse_client = ec;
2545 if (mouse_in_job) ecore_job_del(mouse_in_job);
2546 mouse_in_job = ecore_job_add(_e_comp_x_mouse_in_job, NULL);
2547 }
2548 return EINA_FALSE;
2549 }
2550
2551 static Eina_Bool
_e_comp_x_mouse_in(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Mouse_In * ev)2552 _e_comp_x_mouse_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Mouse_In *ev)
2553 {
2554 E_Client *ec;
2555
2556 if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2557 ec = _e_comp_x_client_find_by_window(ev->win);
2558 if (!ec) goto done;
2559 if (ev->mode == ECORE_X_EVENT_MODE_NORMAL)
2560 {
2561 if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2562 {
2563 if (ev->win != e_client_util_pwin_get(ec)) goto done;
2564 if (ev->event_win != e_client_util_win_get(ec)) goto done;
2565 }
2566 if (ev->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
2567 {
2568 if (ev->win != e_client_util_win_get(ec)) goto done;
2569 if (ev->event_win != e_client_util_pwin_get(ec)) goto done;
2570 }
2571 if (!evas_object_visible_get(ec->frame)) goto done;
2572 }
2573 if (_e_comp_x_client_data_get(ec)->deleted) goto done;
2574 mouse_client = ec;
2575 if (mouse_in_job) ecore_job_del(mouse_in_job);
2576 mouse_in_job = ecore_job_add(_e_comp_x_mouse_in_job, NULL);
2577 mouse_in_coords.x = ev->root.x;
2578 mouse_in_coords.y = ev->root.y;
2579 done:
2580 E_FREE_FUNC(mouse_in_fix_check_timer, ecore_timer_del);
2581 if ((!e_grabinput_mouse_win_get()) && (!e_grabinput_key_win_get()))
2582 mouse_in_fix_check_timer =
2583 ecore_timer_add(0.1, _e_comp_x_mouse_in_fix_check_timer_cb, NULL);
2584 return ECORE_CALLBACK_RENEW;
2585 }
2586
2587 static Eina_Bool
_e_comp_x_mouse_out(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Mouse_In * ev)2588 _e_comp_x_mouse_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Mouse_In *ev)
2589 {
2590 E_Client *ec;
2591
2592 if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2593 if ((ev->mode == ECORE_X_EVENT_MODE_UNGRAB) &&
2594 (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
2595 return ECORE_CALLBACK_PASS_ON;
2596 if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
2597 return ECORE_CALLBACK_PASS_ON;
2598 if ((ev->mode == ECORE_X_EVENT_MODE_NORMAL) &&
2599 (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR))
2600 return ECORE_CALLBACK_PASS_ON;
2601 ec = _e_comp_x_client_find_by_window(ev->win);
2602 if (!ec) return ECORE_CALLBACK_RENEW;
2603 if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2604 if (mouse_client == ec)
2605 {
2606 mouse_client = NULL;
2607 E_FREE_FUNC(mouse_in_job, ecore_job_del);
2608 }
2609 if (ec->mouse.in)
2610 e_client_mouse_out(ec, e_comp_canvas_x_root_adjust(ev->root.x), e_comp_canvas_y_root_adjust(ev->root.y));
2611 return ECORE_CALLBACK_RENEW;
2612 }
2613
2614 static Eina_Bool
_e_comp_x_mouse_wheel(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Wheel * ev)2615 _e_comp_x_mouse_wheel(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Wheel *ev)
2616 {
2617 E_Client *ec;
2618 E_Binding_Event_Wheel ev2;
2619
2620 if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2621 //if (action_input_win)
2622 //ec = action_border;
2623 //else
2624 {
2625 ec = _e_comp_x_client_find_by_window(ev->window);
2626 if ((!ec) && (ev->window != ev->event_window))
2627 ec = _e_comp_x_client_find_by_window(ev->event_window);
2628 if (!ec) return ECORE_CALLBACK_RENEW;
2629 }
2630 if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2631 e_bindings_ecore_event_mouse_wheel_convert(ev, &ev2);
2632 e_client_mouse_wheel(ec, (Evas_Point*)&ev->root, &ev2);
2633 return ECORE_CALLBACK_RENEW;
2634 }
2635
2636
2637 static Eina_Bool
_e_comp_x_mouse_up(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev)2638 _e_comp_x_mouse_up(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2639 {
2640 E_Client *ec;
2641 E_Binding_Event_Mouse_Button ev2;
2642
2643 if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2644 //if (action_input_win)
2645 //ec = action_border;
2646 //else
2647 {
2648 ec = _e_comp_x_client_find_by_window(ev->window);
2649 if ((!ec) && (ev->window != ev->event_window))
2650 ec = _e_comp_x_client_find_by_window(ev->event_window);
2651 if (!ec)
2652 {
2653 if (e_client_comp_grabbed_get())
2654 ec = e_client_action_get();
2655 if (!ec) return ECORE_CALLBACK_RENEW;
2656 }
2657 if ((!ec) || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2658 }
2659 if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2660 e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
2661 e_client_mouse_up(ec, ev->buttons, (Evas_Point*)&ev->root, &ev2);
2662 return ECORE_CALLBACK_RENEW;
2663 }
2664
2665 static Eina_Bool
_e_comp_x_mouse_down(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Button * ev)2666 _e_comp_x_mouse_down(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2667 {
2668 E_Client *ec;
2669 E_Binding_Event_Mouse_Button ev2;
2670
2671 if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2672 if (e_client_action_get()) return ECORE_CALLBACK_RENEW; //block extra mouse buttons during action
2673 //if (action_input_win)
2674 //ec = action_border;
2675 //else
2676 {
2677 ec = _e_comp_x_client_find_by_window(ev->window);
2678 if ((!ec) && (ev->window != ev->event_window))
2679 ec = _e_comp_x_client_find_by_window(ev->event_window);
2680 if ((!ec) || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2681 }
2682 if (_e_comp_x_client_data_get(ec)->deleted) return ECORE_CALLBACK_RENEW;
2683 e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
2684 e_client_mouse_down(ec, ev->buttons, (Evas_Point*)&ev->root, &ev2);
2685 return ECORE_CALLBACK_RENEW;
2686 }
2687
2688 static Eina_Bool
_e_comp_x_mouse_move(void * d EINA_UNUSED,int t EINA_UNUSED,Ecore_Event_Mouse_Move * ev)2689 _e_comp_x_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
2690 {
2691 E_Client *ec;
2692
2693 if (e_comp->comp_type != E_PIXMAP_TYPE_X) return ECORE_CALLBACK_RENEW;
2694 ec = e_client_action_get();
2695 if (!ec)
2696 {
2697 ec = _e_comp_x_client_find_by_window(ev->window);
2698 if ((!ec) && (ev->window != ev->event_window))
2699 ec = _e_comp_x_client_find_by_window(ev->event_window);
2700 if ((!ec) || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2701 if ((!ec->mouse.in) && evas_object_visible_get(ec->frame) && (!ec->desk->animate_count))
2702 {
2703 E_Client *tec;
2704 Ecore_Window top = e_comp_top_window_at_xy_get(ev->root.x, ev->root.y);
2705 int x, y;
2706 if (top == e_comp->ee_win) return ECORE_CALLBACK_RENEW;
2707
2708 x = e_comp_canvas_x_root_adjust(ev->root.x);
2709 y = e_comp_canvas_y_root_adjust(ev->root.y);
2710 for (tec = e_client_above_get(ec); tec; tec = e_client_above_get(tec))
2711 {
2712 if (!evas_object_visible_get(tec->frame)) continue;
2713 if (E_INSIDE(x, y, tec->x, tec->y, tec->w, tec->h)) return ECORE_CALLBACK_RENEW;
2714 }
2715 if (!mouse_in_job)
2716 e_client_mouse_in(ec, x, y);
2717 }
2718 return ECORE_CALLBACK_RENEW;
2719 }
2720 E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
2721 if (_e_comp_x_client_data_get(ec)->deleted || e_client_util_ignored_get(ec)) return ECORE_CALLBACK_RENEW;
2722 if (e_client_util_resizing_get(ec) && (e_comp->comp_type == E_PIXMAP_TYPE_X) &&
2723 ec->netwm.sync.request &&
2724 _e_comp_x_client_data_get(ec)->alarm
2725 )
2726 {
2727 if ((ecore_loop_time_get() - ec->netwm.sync.send_time) > 0.5)
2728 {
2729 if (ec->pending_resize)
2730 {
2731 ec->changes.pos = 1;
2732 ec->changes.size = 1;
2733 EC_CHANGED(ec);
2734 _e_comp_x_client_move_resize_send(ec);
2735 }
2736 E_FREE_LIST(ec->pending_resize, free);
2737
2738 ec->netwm.sync.wait = 0;
2739 /* sync.wait is incremented when resize_handle sends
2740 * sync-request and decremented by sync-alarm cb. so
2741 * we resize here either on initial resize, timeout or
2742 * when no new resize-request was added by sync-alarm cb.
2743 */
2744 }
2745 }
2746 e_client_mouse_move(ec, (Evas_Point*)&ev->root);
2747 return ECORE_CALLBACK_RENEW;
2748 }
2749
2750 static Eina_Bool
_e_comp_x_focus_out(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Focus_Out * ev)2751 _e_comp_x_focus_out(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Focus_Out *ev)
2752 {
2753 E_Client *ec;
2754
2755 ec = _e_comp_x_client_find_by_window(ev->win);
2756 if (!ec) return ECORE_CALLBACK_RENEW;
2757
2758 _e_comp_x_client_pri_norm(ec);
2759 if (ev->mode == ECORE_X_EVENT_MODE_NORMAL)
2760 {
2761 if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2762 return ECORE_CALLBACK_PASS_ON;
2763 else if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
2764 return ECORE_CALLBACK_PASS_ON;
2765 else if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
2766 return ECORE_CALLBACK_PASS_ON;
2767 }
2768 else if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
2769 {
2770 if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR)
2771 return ECORE_CALLBACK_PASS_ON;
2772 else if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2773 return ECORE_CALLBACK_PASS_ON;
2774 else if (ev->detail == ECORE_X_EVENT_DETAIL_NON_LINEAR_VIRTUAL)
2775 return ECORE_CALLBACK_PASS_ON;
2776 else if (ev->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
2777 return ECORE_CALLBACK_PASS_ON;
2778 else if (ev->detail == ECORE_X_EVENT_DETAIL_VIRTUAL)
2779 return ECORE_CALLBACK_PASS_ON;
2780 }
2781 else if (ev->mode == ECORE_X_EVENT_MODE_UNGRAB)
2782 {
2783 /* for firefox/thunderbird (xul) menu walking */
2784 /* NB: why did i disable this before? */
2785 if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2786 return ECORE_CALLBACK_PASS_ON;
2787 else if (ev->detail == ECORE_X_EVENT_DETAIL_POINTER)
2788 return ECORE_CALLBACK_PASS_ON;
2789 }
2790 else if (ev->mode == ECORE_X_EVENT_MODE_WHILE_GRABBED)
2791 {
2792 if (ev->detail == ECORE_X_EVENT_DETAIL_ANCESTOR)
2793 return ECORE_CALLBACK_PASS_ON;
2794 else if (ev->detail == ECORE_X_EVENT_DETAIL_INFERIOR)
2795 return ECORE_CALLBACK_PASS_ON;
2796 }
2797 evas_object_focus_set(ec->frame, 0);
2798 return ECORE_CALLBACK_PASS_ON;
2799 }
2800
2801 static Eina_Bool
_e_comp_x_client_property(void * d EINA_UNUSED,int t EINA_UNUSED,E_Event_Client_Property * ev)2802 _e_comp_x_client_property(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Property *ev)
2803 {
2804 if ((ev->property & E_CLIENT_PROPERTY_ICON) && ev->ec->desktop)
2805 ecore_x_window_prop_string_set(e_client_util_win_get(ev->ec), E_ATOM_DESKTOP_FILE,
2806 ev->ec->desktop->orig_path);
2807 return ECORE_CALLBACK_RENEW;
2808 }
2809
2810 static void
_e_comp_x_client_zone_geometry_set(E_Client * ec)2811 _e_comp_x_client_zone_geometry_set(E_Client *ec)
2812 {
2813 unsigned int zgeom[4];
2814
2815 E_COMP_X_PIXMAP_CHECK;
2816 zgeom[0] = ec->zone->x;
2817 zgeom[1] = ec->zone->y;
2818 zgeom[2] = ec->zone->w;
2819 zgeom[3] = ec->zone->h;
2820 ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_ZONE_GEOMETRY, zgeom, 4);
2821 }
2822
2823 static Eina_Bool
_e_comp_x_client_zone_set(void * data EINA_UNUSED,int type EINA_UNUSED,E_Event_Client * ev)2824 _e_comp_x_client_zone_set(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Client *ev)
2825 {
2826 E_Client *ec = ev->ec;
2827
2828 if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_RENEW;
2829 E_COMP_X_PIXMAP_CHECK ECORE_CALLBACK_RENEW;
2830 ecore_x_window_prop_card32_set(e_client_util_win_get(ev->ec), E_ATOM_ZONE, &ev->ec->zone->num, 1);
2831 _e_comp_x_client_zone_geometry_set(ev->ec);
2832 return ECORE_CALLBACK_RENEW;
2833 }
2834
2835 static Eina_Bool
_e_comp_x_sync_alarm(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Sync_Alarm * ev)2836 _e_comp_x_sync_alarm(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Sync_Alarm *ev)
2837 {
2838 unsigned int serial;
2839 E_Client *ec;
2840 // Eina_Bool resize = EINA_FALSE;
2841
2842 ec = _e_comp_x_client_find_by_alarm(ev->alarm);
2843 if ((!ec) || e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_RENEW;
2844
2845 if (ec->netwm.sync.wait)
2846 ec->netwm.sync.wait--;
2847
2848 if (ecore_x_sync_counter_query(_e_comp_x_client_data_get(ec)->sync_counter, &serial))
2849 {
2850 E_Client_Pending_Resize *pnd = NULL;
2851
2852 /* skip pending for which we didn't get a reply */
2853 while (ec->pending_resize)
2854 {
2855 pnd = ec->pending_resize->data;
2856 ec->pending_resize = eina_list_remove(ec->pending_resize, pnd);
2857
2858 if (serial == pnd->serial)
2859 break;
2860
2861 E_FREE(pnd);
2862 }
2863
2864 if (pnd)
2865 {
2866 // disable this as it just seems to cause mis-sizing and issues...
2867 // resize = ((ec->w != pnd->w) || (ec->h != pnd->h));
2868 // e_comp_object_frame_wh_adjust(ec->frame, pnd->w, pnd->h, &ec->w, &ec->h);
2869 E_FREE(pnd);
2870 }
2871 }
2872
2873 // this too... as above
2874 // if (resize)
2875 // {
2876 // evas_object_resize(ec->frame, ec->w, ec->h);
2877 // if (ec->internal_elm_win)
2878 // evas_object_resize(ec->internal_elm_win, ec->client.w, ec->client.h);
2879 // }
2880
2881 ec->netwm.sync.send_time = ecore_loop_time_get();
2882 // this too - as above
2883 // if (resize)
2884 // {
2885 // ecore_x_pointer_xy_get(e_comp->root,
2886 // &ec->mouse.current.mx,
2887 // &ec->mouse.current.my);
2888 // e_client_mouse_move(ec, &(Evas_Point){ec->mouse.current.mx, ec->mouse.current.my});
2889 // }
2890 return ECORE_CALLBACK_RENEW;
2891 }
2892
2893 static Eina_Bool
_e_comp_x_desktop_change(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Desktop_Change * ev)2894 _e_comp_x_desktop_change(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Desktop_Change *ev)
2895 {
2896 E_Client *ec;
2897
2898 ec = _e_comp_x_client_find_by_window(ev->win);
2899 if (ec)
2900 {
2901 if (ev->desk == 0xffffffff)
2902 e_client_stick(ec);
2903 else if ((int)ev->desk < (ec->zone->desk_x_count * ec->zone->desk_y_count))
2904 {
2905 E_Desk *desk;
2906
2907 desk = e_desk_at_pos_get(ec->zone, ev->desk);
2908 if (desk)
2909 e_client_desk_set(ec, desk);
2910 }
2911 }
2912 else
2913 ecore_x_netwm_desktop_set(ev->win, ev->desk);
2914 return ECORE_CALLBACK_RENEW;
2915 }
2916
2917 static Eina_Bool
_e_comp_x_move_resize_request(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Move_Resize_Request * ev)2918 _e_comp_x_move_resize_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Move_Resize_Request *ev)
2919 {
2920 E_Client *ec;
2921
2922 ec = _e_comp_x_client_find_by_window(ev->win);
2923 if (!ec) return ECORE_CALLBACK_RENEW;
2924
2925 if ((ec->shaded) || (ec->shading) ||
2926 (ec->fullscreen) || (ec->moving) ||
2927 (ec->resize_mode != E_POINTER_RESIZE_NONE))
2928 return ECORE_CALLBACK_PASS_ON;
2929
2930 if ((ev->button >= 1) && (ev->button <= 3))
2931 {
2932 ec->mouse.last_down[ev->button - 1].mx = ev->x;
2933 ec->mouse.last_down[ev->button - 1].my = ev->y;
2934 ec->mouse.last_down[ev->button - 1].x = ec->x;
2935 ec->mouse.last_down[ev->button - 1].y = ec->y;
2936 ec->mouse.last_down[ev->button - 1].w = ec->w;
2937 ec->mouse.last_down[ev->button - 1].h = ec->h;
2938 }
2939 else
2940 {
2941 ec->moveinfo.down.x = ec->x;
2942 ec->moveinfo.down.y = ec->y;
2943 ec->moveinfo.down.w = ec->w;
2944 ec->moveinfo.down.h = ec->h;
2945 }
2946 ec->mouse.current.mx = ev->x;
2947 ec->mouse.current.my = ev->y;
2948 ec->moveinfo.down.button = ev->button;
2949 ec->moveinfo.down.mx = ev->x;
2950 ec->moveinfo.down.my = ev->y;
2951
2952 if (!ec->lock_user_stacking)
2953 evas_object_raise(ec->frame);
2954
2955 if (ev->direction == E_POINTER_MOVE)
2956 {
2957 ec->cur_mouse_action = e_action_find("window_move");
2958 if (ec->cur_mouse_action)
2959 {
2960 if ((!ec->cur_mouse_action->func.end_mouse) &&
2961 (!ec->cur_mouse_action->func.end))
2962 ec->cur_mouse_action = NULL;
2963 if (ec->cur_mouse_action)
2964 {
2965 e_object_ref(E_OBJECT(ec->cur_mouse_action));
2966 ec->cur_mouse_action->func.go(E_OBJECT(ec), NULL);
2967 }
2968 }
2969 return ECORE_CALLBACK_PASS_ON;
2970 }
2971
2972 ec->cur_mouse_action = e_action_find("window_resize");
2973 if (ec->cur_mouse_action)
2974 {
2975 if ((!ec->cur_mouse_action->func.end_mouse) &&
2976 (!ec->cur_mouse_action->func.end))
2977 ec->cur_mouse_action = NULL;
2978 }
2979 if (!ec->cur_mouse_action) return ECORE_CALLBACK_RENEW;
2980 e_object_ref(E_OBJECT(ec->cur_mouse_action));
2981 ec->cur_mouse_action->func.go(E_OBJECT(ec), NULL);
2982
2983 if (ev->direction != E_POINTER_RESIZE_NONE)
2984 {
2985 e_pointer_mode_pop(ec, ec->resize_mode);
2986 ec->resize_mode = ev->direction;
2987 e_pointer_mode_push(ec, ec->resize_mode);
2988 }
2989 switch (ev->direction)
2990 {
2991 case E_POINTER_RESIZE_TL:
2992 GRAV_SET(ec, ECORE_X_GRAVITY_SE);
2993 break;
2994
2995 case E_POINTER_RESIZE_T:
2996 GRAV_SET(ec, ECORE_X_GRAVITY_S);
2997 break;
2998
2999 case E_POINTER_RESIZE_TR:
3000 GRAV_SET(ec, ECORE_X_GRAVITY_SW);
3001 break;
3002
3003 case E_POINTER_RESIZE_R:
3004 GRAV_SET(ec, ECORE_X_GRAVITY_W);
3005 break;
3006
3007 case E_POINTER_RESIZE_BR:
3008 GRAV_SET(ec, ECORE_X_GRAVITY_NW);
3009 break;
3010
3011 case E_POINTER_RESIZE_B:
3012 GRAV_SET(ec, ECORE_X_GRAVITY_N);
3013 break;
3014
3015 case E_POINTER_RESIZE_BL:
3016 GRAV_SET(ec, ECORE_X_GRAVITY_NE);
3017 break;
3018
3019 case E_POINTER_RESIZE_L:
3020 GRAV_SET(ec, ECORE_X_GRAVITY_E);
3021 break;
3022
3023 default:
3024 return ECORE_CALLBACK_PASS_ON;
3025 }
3026
3027 return ECORE_CALLBACK_RENEW;
3028 }
3029
3030 static Eina_Bool
_e_comp_x_focus_timer_cb(void * d EINA_UNUSED)3031 _e_comp_x_focus_timer_cb(void *d EINA_UNUSED)
3032 {
3033 E_Client *focused;
3034
3035 /* if mouse-based focus policy clients exist for [focused] and [mouse_client],
3036 * [mouse_client] should have focus here.
3037 * race conditions in x11 focus setting can result in a scenario such that:
3038 * -> set focus on A
3039 * -> set focus on B
3040 * -> receive focus event on A
3041 * -> re-set focus on A
3042 * -> receive focus event on B
3043 * -> receive focus event on A
3044 * ...
3045 * where the end state is that the cursor is over a client which does not have focus.
3046 * this timer is triggered only when such eventing occurs in order to adjust the focused
3047 * client as necessary
3048 */
3049 focused = e_client_focused_get();
3050 if (mouse_client && focused && (!e_client_focus_policy_click(focused)) && (mouse_client != focused))
3051 {
3052 int x, y;
3053
3054 ecore_evas_pointer_xy_get(e_comp->ee, &x, &y);
3055 if (E_INSIDE(x, y, mouse_client->x, mouse_client->y, mouse_client->w, mouse_client->h))
3056 {
3057 if (!_e_comp_x_client_data_get(mouse_client)->deleted)
3058 e_client_mouse_in(mouse_client, x, y);
3059 }
3060 }
3061 focus_timer = NULL;
3062 return EINA_FALSE;
3063 }
3064
3065 static void
_e_comp_x_focus_timer(void)3066 _e_comp_x_focus_timer(void)
3067 {
3068 if (focus_timer)
3069 ecore_timer_loop_reset(focus_timer);
3070 else /* focus has changed twice in .002 seconds; .01 seconds should be more than enough delay */
3071 focus_timer = ecore_timer_loop_add(0.01, _e_comp_x_focus_timer_cb, NULL);
3072 }
3073
3074 static Eina_Bool
_e_comp_x_focus_in(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Focus_In * ev)3075 _e_comp_x_focus_in(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Focus_In *ev)
3076 {
3077 E_Client *ec, *focused;
3078
3079 ec = _e_comp_x_client_find_by_window(ev->win);
3080
3081 if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
3082 {
3083 focused = e_client_focused_get();
3084 if (ec && focused)
3085 {
3086 if ((!ec->override) && (ec != focused))
3087 {
3088 ecore_x_window_focus(e_client_util_win_get(focused));
3089 ecore_x_icccm_take_focus_send(e_client_util_win_get(focused), ecore_x_current_time_get());
3090 }
3091 }
3092 else
3093 ecore_x_window_focus(e_comp->root);
3094 return ECORE_CALLBACK_RENEW;
3095 }
3096 if (!ec)
3097 {
3098 if ((ev->win == e_comp->ee_win) && (ev->time >= focus_canvas_time) && (!focus_time))
3099 {
3100 focused = e_client_focused_get();
3101 if (focused)
3102 evas_object_focus_set(focused->frame, 0);
3103 focus_canvas_time = 0;
3104 }
3105 return ECORE_CALLBACK_RENEW;
3106 }
3107
3108 /* block refocus attempts on iconic clients
3109 * these result from iconifying a client during a grab */
3110 if (ec->iconic) return ECORE_CALLBACK_RENEW;
3111
3112 focused = e_client_focused_get();
3113
3114 _e_comp_x_client_pri_raise(ec);
3115 if (ev->mode == ECORE_X_EVENT_MODE_GRAB)
3116 {
3117 if (ev->detail == ECORE_X_EVENT_DETAIL_POINTER) return ECORE_CALLBACK_PASS_ON;
3118 }
3119 else if (ev->mode == ECORE_X_EVENT_MODE_UNGRAB)
3120 {
3121 /* this seems to break winlist...
3122 if (ev->detail == ECORE_X_EVENT_DETAIL_POINTER)
3123 */
3124
3125 /* we're getting a non-linear focus re-set on a visible
3126 * window on current desk when no other client is focused;
3127 * this is probably when we're trying to reapply focus after
3128 * unfocusing some comp canvas widget
3129 */
3130 if ((ev->detail != ECORE_X_EVENT_DETAIL_NON_LINEAR) ||
3131 focused ||
3132 (!e_client_util_desk_visible(ec, e_desk_current_get(ec->zone))))
3133 return ECORE_CALLBACK_PASS_ON;
3134 }
3135
3136 /* ignore focus in from !take_focus windows, we just gave it em */
3137 /* if (!ec->icccm.take_focus)
3138 * return ECORE_CALLBACK_PASS_ON; */
3139
3140 /* should be equal, maybe some clients don't reply with the proper timestamp ? */
3141 if (ev->time >= focus_time)
3142 evas_object_focus_set(ec->frame, 1);
3143 /* handle case of someone trying to benchmark focus handling */
3144 if ((!e_client_focus_policy_click(ec)) && (focused && (!e_client_focus_policy_click(focused))) &&
3145 (ev->time - focus_time <= 2))
3146 _e_comp_x_focus_timer();
3147 return ECORE_CALLBACK_PASS_ON;
3148 }
3149
3150 static Eina_Bool
_e_comp_x_shape(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Shape * ev)3151 _e_comp_x_shape(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Shape *ev)
3152 {
3153 E_Client *ec;
3154 Eina_Bool pshaped;
3155 //const char *txt[] =
3156 //{
3157 //[ECORE_X_SHAPE_BOUNDING] = "BOUNDING",
3158 //[ECORE_X_SHAPE_INPUT] = "INPUT",
3159 //[ECORE_X_SHAPE_CLIP] = "CLIP",
3160 //};
3161
3162 ec = _e_comp_x_client_find_by_window(ev->win);
3163 if (!ec) return ECORE_CALLBACK_RENEW;
3164 pshaped = ec->shaped;
3165 //INF("%p(%s): %d,%d %dx%d || %d", ec, txt[ev->type], ev->x, ev->y, ev->w, ev->h, ev->shaped);
3166 if (ev->win == e_client_util_win_get(ec))
3167 {
3168 if (ev->type == ECORE_X_SHAPE_INPUT)
3169 {
3170 ec->changes.shape_input = 1;
3171 ec->need_shape_merge = 1;
3172 }
3173 else
3174 {
3175 if ((_e_comp_x_client_data_get(ec)->shape.x != ev->x) ||
3176 (_e_comp_x_client_data_get(ec)->shape.y != ev->y) ||
3177 (_e_comp_x_client_data_get(ec)->shape.w != ev->w) ||
3178 (_e_comp_x_client_data_get(ec)->shape.h != ev->h))
3179 {
3180 /* bounding box changed, need export for rendering */
3181 EINA_RECTANGLE_SET(&_e_comp_x_client_data_get(ec)->shape, ev->x, ev->y, ev->w, ev->h);
3182 ec->need_shape_export = !ec->override;
3183 }
3184 ec->changes.shape = 1;
3185 }
3186 }
3187 else if (ec->shaped) //shape change on parent window only valid if window is known to be shaped
3188 ec->need_shape_export = 1;
3189 if (ec->changes.shape)
3190 {
3191 if ((ev->type == ECORE_X_SHAPE_BOUNDING) && (ec->shaped || (pshaped != ec->shaped)))
3192 {
3193 if (ec->shape_rects || (!ec->shaped))
3194 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
3195 }
3196 }
3197 EC_CHANGED(ec);
3198 return ECORE_CALLBACK_PASS_ON;
3199 }
3200
3201 static Eina_Bool
_e_comp_x_damage(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Damage * ev)3202 _e_comp_x_damage(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Damage *ev)
3203 {
3204 E_Client *ec;
3205 Ecore_X_Rectangle *rects = NULL;
3206 int n = 0;
3207 Eina_Bool skip;
3208
3209 ec = _e_comp_x_client_find_by_damage(ev->damage);
3210 if ((!ec) || e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
3211 skip = ec->shape_rects_num > 50;
3212 if (_e_comp_x_client_data_get(ec)->damage)
3213 {
3214 Ecore_X_Region parts;
3215 Ecore_X_Rectangle bounds;
3216
3217 parts = ecore_x_region_new(NULL, 0);
3218 ecore_x_damage_subtract(_e_comp_x_client_data_get(ec)->damage, 0, parts);
3219 if (!skip)
3220 rects = ecore_x_region_fetch(parts, &n, &bounds);
3221 ecore_x_region_free(parts);
3222 }
3223 //WRN("DAMAGE %p: %dx%d", ec, ev->area.width, ev->area.height);
3224
3225 if (e_comp->nocomp)
3226 e_pixmap_dirty(ec->pixmap);
3227 else if (skip)
3228 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
3229 else
3230 {
3231 int i;
3232
3233 for (i = 0; i < n; i++)
3234 e_comp_object_damage(ec->frame, rects[i].x, rects[i].y, rects[i].width, rects[i].height);
3235 }
3236 free(rects);
3237 if ((!ec->re_manage) && (!ec->override) && (!_e_comp_x_client_data_get(ec)->first_damage))
3238 e_comp_object_render_update_del(ec->frame);
3239 else
3240 E_FREE_FUNC(_e_comp_x_client_data_get(ec)->first_draw_delay, ecore_timer_del);
3241 _e_comp_x_client_data_get(ec)->first_damage = 1;
3242 return ECORE_CALLBACK_RENEW;
3243 }
3244
3245 static Eina_Bool
_e_comp_x_damage_win(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Window_Damage * ev)3246 _e_comp_x_damage_win(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Window_Damage *ev)
3247 {
3248 if (e_comp_find_by_window(ev->win)) e_comp_render_queue();
3249 return ECORE_CALLBACK_PASS_ON;
3250 }
3251
3252 static Eina_Bool
_e_comp_x_grab_replay(void * data EINA_UNUSED,int type,void * event)3253 _e_comp_x_grab_replay(void *data EINA_UNUSED, int type, void *event)
3254 {
3255 Ecore_Event_Mouse_Button *ev = event;
3256 E_Binding_Event_Mouse_Button ev2;
3257 E_Client *ec;
3258
3259 if (type != ECORE_EVENT_MOUSE_BUTTON_DOWN) return ECORE_CALLBACK_DONE;
3260 if ((!e_config->pass_click_on) &&
3261 (!e_config->always_click_to_raise) && // this works even if not on click-to-focus
3262 (!e_config->always_click_to_focus) // this works even if not on click-to-focus
3263 )
3264 return ECORE_CALLBACK_DONE;
3265 ec = _e_comp_x_client_find_by_window(ev->event_window);
3266 if (!ec) return ECORE_CALLBACK_DONE;
3267 if (ec->cur_mouse_action) return ECORE_CALLBACK_DONE;
3268 if (ev->event_window != e_client_util_win_get(ec)) return ECORE_CALLBACK_DONE;
3269 e_bindings_ecore_event_mouse_button_convert(ev, &ev2);
3270 return !e_bindings_mouse_button_find(E_BINDING_CONTEXT_WINDOW,
3271 &ev2, NULL);
3272 }
3273
3274 static void
_e_comp_x_hook_client_eval_end(void * d EINA_UNUSED,E_Client * ec)3275 _e_comp_x_hook_client_eval_end(void *d EINA_UNUSED, E_Client *ec)
3276 {
3277 E_COMP_X_PIXMAP_CHECK;
3278 if (e_comp_x->restack && (!e_comp->new_clients))
3279 {
3280 e_hints_client_stacking_set();
3281 e_comp_x->restack = 0;
3282 }
3283 }
3284
3285 static Eina_Bool
_e_comp_x_client_shape_rects_check(E_Client * ec,Ecore_X_Rectangle * rects,int num)3286 _e_comp_x_client_shape_rects_check(E_Client *ec, Ecore_X_Rectangle *rects, int num)
3287 {
3288 Eina_Bool changed = 1;
3289 Ecore_X_Rectangle *orects;
3290
3291 if (((unsigned int)num == ec->shape_rects_num) && (ec->shape_rects))
3292 {
3293 int i;
3294
3295 orects = (Ecore_X_Rectangle*)ec->shape_rects;
3296 changed = 0;
3297 for (i = 0; i < num; i++)
3298 {
3299 E_RECTS_CLIP_TO_RECT(rects[i].x, rects[i].y,
3300 rects[i].width, rects[i].height, 0, 0, ec->client.w, ec->client.h);
3301
3302 if ((orects[i].x != rects[i].x) ||
3303 (orects[i].y != rects[i].y) ||
3304 (orects[i].width != rects[i].width) ||
3305 (orects[i].height != rects[i].height))
3306 {
3307 changed = 1;
3308 break;
3309 }
3310 }
3311 }
3312 if ((changed) && (rects))
3313 {
3314 E_FREE(ec->shape_rects);
3315 ec->shape_rects = (Eina_Rectangle*)rects;
3316 ec->shape_rects_num = num;
3317 ec->shape_changed = 1;
3318 e_comp_shape_queue();
3319 }
3320 else
3321 free(rects);
3322 return changed;
3323 }
3324
3325 static void
_e_comp_x_hook_client_post_new_client(void * d EINA_UNUSED,E_Client * ec)3326 _e_comp_x_hook_client_post_new_client(void *d EINA_UNUSED, E_Client *ec)
3327 {
3328 E_COMP_X_PIXMAP_CHECK;
3329 if (ec->changes.reset_gravity)
3330 {
3331 GRAV_SET(ec, ECORE_X_GRAVITY_NW);
3332 }
3333
3334 if (ec->need_shape_merge)
3335 {
3336 _e_comp_x_client_shape_input_rectangle_set(ec);
3337 if ((!ec->shaped) && _e_comp_x_client_data_get(ec)->reparented)
3338 ecore_x_window_shape_mask_set(e_client_util_pwin_get(ec), 0);
3339 ec->need_shape_merge = 0;
3340 }
3341
3342 if (ec->changes.internal_state)
3343 {
3344 Ecore_X_Atom state[1];
3345 int num = 0;
3346
3347 if (e_win_centered_get(ec->internal_elm_win))
3348 state[num++] = E_ATOM_WINDOW_STATE_CENTERED;
3349
3350 if (num)
3351 ecore_x_window_prop_card32_set(elm_win_window_id_get(ec->internal_elm_win), E_ATOM_WINDOW_STATE, state, num);
3352 else
3353 ecore_x_window_prop_property_del(elm_win_window_id_get(ec->internal_elm_win), E_ATOM_WINDOW_STATE);
3354 ec->changes.internal_state = 0;
3355 }
3356
3357 if (ec->need_shape_export)
3358 {
3359 Ecore_X_Rectangle *rects;
3360 int num;
3361
3362 rects = ecore_x_window_shape_rectangles_get(e_client_util_win_get(ec), &num);
3363 if (rects)
3364 _e_comp_x_client_shape_rects_check(ec, rects, num);
3365 else
3366 {
3367 E_FREE(ec->shape_rects);
3368 ec->shape_rects_num = 0;
3369 }
3370 ec->need_shape_export = 0;
3371 }
3372 }
3373
3374 static void
_e_comp_x_hook_client_pre_frame_assign(void * d EINA_UNUSED,E_Client * ec)3375 _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec)
3376 {
3377 Ecore_X_Window win, pwin;
3378 int w, h;
3379 E_Pixmap *ep;
3380 E_Comp_X_Client_Data *cd;
3381
3382 E_COMP_X_PIXMAP_CHECK;
3383 ep = e_comp_x_client_pixmap_get(ec);
3384 win = e_client_util_win_get(ec);
3385 cd = _e_comp_x_client_data_get(ec);
3386 if (!cd->need_reparent) return;
3387 w = MAX(ec->client.w, 1);
3388 h = MAX(ec->client.h, 1);
3389 /* match ec parent argbness */
3390 if (ec->argb)
3391 pwin = ecore_x_window_manager_argb_new(e_comp->root, ec->client.x, ec->client.y, w, h);
3392 else
3393 {
3394 pwin = ecore_x_window_override_new(e_comp->root, ec->client.x, ec->client.y, w, h);
3395 ecore_x_window_shape_events_select(pwin, !ec->internal); //let's just agree never to do this with our own windows...
3396 }
3397
3398 if (ec->client.w && ec->client.h)
3399 /* force a resize here (no-op most of the time)
3400 * prevents mismatch between remembered window size and current size
3401 */
3402 ecore_x_window_resize(win, ec->client.w, ec->client.h);
3403 ecore_x_window_container_manage(pwin);
3404 if (!ec->internal) ecore_x_window_client_manage(win);
3405 ecore_x_window_configure(pwin,
3406 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
3407 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
3408 0, 0, 0, 0, 0,
3409 win, ECORE_X_WINDOW_STACK_ABOVE);
3410 ecore_x_event_mask_set(pwin, ECORE_X_EVENT_MASK_KEY_DOWN | ECORE_X_EVENT_MASK_KEY_UP |
3411 ECORE_X_EVENT_MASK_MOUSE_MOVE | ECORE_X_EVENT_MASK_MOUSE_DOWN |
3412 ECORE_X_EVENT_MASK_MOUSE_UP |
3413 ECORE_X_EVENT_MASK_MOUSE_IN | ECORE_X_EVENT_MASK_MOUSE_OUT);
3414 ecore_x_window_border_width_set(win, 0);
3415 ec->border_size = 0;
3416
3417 if (ec->e.state.video)
3418 {
3419 ecore_x_window_lower(pwin);
3420 ecore_x_composite_window_events_disable(pwin);
3421 ecore_x_window_ignore_set(pwin, EINA_TRUE);
3422 }
3423 if (!ec->internal)
3424 ecore_x_window_save_set_add(win);
3425 ecore_x_window_reparent(win, pwin, 0, 0);
3426 e_pixmap_alias(ep, E_PIXMAP_TYPE_X, pwin);
3427
3428 {
3429 unsigned int managed = 1;
3430 ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &managed, 1);
3431 }
3432 e_pixmap_parent_window_set(ep, pwin);
3433 ec->border.changed = 1;
3434 if (!ec->shaped)
3435 ecore_x_window_shape_mask_set(pwin, 0);
3436 if (ec->shaped_input)
3437 ecore_x_window_shape_input_rectangles_set(pwin, (Ecore_X_Rectangle*)ec->shape_input_rects, ec->shape_input_rects_num);
3438 ec->changes.shape = 1;
3439 ec->changes.shape_input = 1;
3440 if (ec->internal_elm_win)
3441 {
3442 ecore_x_window_gravity_set(win, ECORE_X_GRAVITY_NW);
3443 ec->changes.reset_gravity = 1;
3444 }
3445 EC_CHANGED(ec);
3446
3447 eina_hash_add(clients_win_hash, &pwin, ec);
3448
3449 if (ec->visible)
3450 {
3451 if (cd->set_win_type && ec->internal_elm_win)
3452 {
3453 if (ec->dialog)
3454 ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_DIALOG);
3455 else
3456 ecore_x_netwm_window_type_set(win, ECORE_X_WINDOW_TYPE_NORMAL);
3457 cd->set_win_type = 0;
3458 }
3459 }
3460 ecore_x_window_show(win);
3461 if (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
3462 ecore_x_window_show(pwin);
3463
3464 _e_comp_x_focus_init(ec);
3465 e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3466 e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3467 _e_comp_x_client_evas_init(ec);
3468 if (ec->netwm.ping && (!ec->ping_poller))
3469 e_client_ping(ec);
3470 if (ec->visible && (ec->icccm.state != ECORE_X_WINDOW_STATE_HINT_WITHDRAWN))
3471 evas_object_show(ec->frame);
3472 cd->need_reparent = 0;
3473 ec->redirected = 1;
3474 if (cd->change_icon)
3475 {
3476 ec->changes.icon = 1;
3477 EC_CHANGED(ec);
3478 }
3479 cd->change_icon = 0;
3480 cd->reparented = 1;
3481 _e_comp_x_evas_comp_hidden_cb(ec, NULL, NULL);
3482 }
3483
3484 static void
_e_comp_x_hook_client_fetch(void * d EINA_UNUSED,E_Client * ec)3485 _e_comp_x_hook_client_fetch(void *d EINA_UNUSED, E_Client *ec)
3486 {
3487 Ecore_X_Window win, pwin;
3488 int rem_change = 0;
3489 Eina_Bool need_desk_set = EINA_FALSE;
3490 E_Comp_X_Client_Data *cd;
3491
3492 E_COMP_X_PIXMAP_CHECK;
3493 win = e_client_util_win_get(ec);
3494 pwin = e_client_util_pwin_get(ec);
3495 cd = _e_comp_x_client_data_get(ec);
3496 if (ec->changes.visible)
3497 _e_comp_x_client_shape_input_rectangle_set(ec);
3498 /* fetch any info queued to be fetched */
3499 if (ec->changes.prop || ec->netwm.fetch.state)
3500 {
3501 e_hints_window_state_get(ec);
3502 ec->netwm.fetch.state = 0;
3503 rem_change = 1;
3504 }
3505 if (ec->icccm.fetch.client_leader)
3506 {
3507 /* TODO: What do to if the client leader isn't mapped yet? */
3508 E_Client *ec_leader = NULL;
3509
3510 ec->icccm.client_leader = ecore_x_icccm_client_leader_get(win);
3511 if (ec->icccm.client_leader)
3512 ec_leader = _e_comp_x_client_find_by_window(ec->icccm.client_leader);
3513 if (ec->leader)
3514 {
3515 if (ec->leader != ec_leader)
3516 {
3517 ec->leader->group = eina_list_remove(ec->leader->group, ec);
3518 if (ec->leader->modal == ec) ec->leader->modal = NULL;
3519 ec->leader = NULL;
3520 }
3521 else
3522 ec_leader = NULL;
3523 }
3524 /* If this client is the leader of the group, don't register itself */
3525 if ((ec_leader) && (ec_leader != ec))
3526 {
3527 ec_leader->group = eina_list_append(ec_leader->group, ec);
3528 ec->leader = ec_leader;
3529 /* Only set the window modal to the leader it there is no parent */
3530 if ((ec->netwm.state.modal) &&
3531 ((!ec->parent) || (ec->parent->modal != ec)))
3532 {
3533 ec->leader->modal = ec;
3534 if (ec->leader->focused)
3535 evas_object_focus_set(ec->frame, 1);
3536 else
3537 {
3538 Eina_List *l;
3539 E_Client *child;
3540
3541 EINA_LIST_FOREACH(ec->leader->group, l, child)
3542 {
3543 if ((child != ec) && (child->focused))
3544 evas_object_focus_set(ec->frame, 1);
3545 }
3546 }
3547 }
3548 }
3549 ec->icccm.fetch.client_leader = 0;
3550 rem_change = 1;
3551 }
3552 if (ec->icccm.fetch.title)
3553 {
3554 char *title = ecore_x_icccm_title_get(win);
3555 eina_stringshare_replace(&ec->icccm.title, title);
3556 free(title);
3557
3558 e_comp_object_frame_title_set(ec->frame, ec->icccm.title);
3559
3560 ec->icccm.fetch.title = 0;
3561 rem_change = 1;
3562 }
3563 if (ec->netwm.fetch.name)
3564 {
3565 char *name;
3566 ecore_x_netwm_name_get(win, &name);
3567 eina_stringshare_replace(&ec->netwm.name, name);
3568 free(name);
3569
3570 ec->hacks.iconic_shading =
3571 ((ec->netwm.icon_name == ec->netwm.name) &&
3572 (!e_util_strcmp(ec->netwm.name, "QEMU")));
3573
3574 e_comp_object_frame_title_set(ec->frame, ec->netwm.name);
3575
3576 ec->netwm.fetch.name = 0;
3577 rem_change = 1;
3578 }
3579
3580 if (ec->icccm.fetch.name_class)
3581 {
3582 const char *pname, *pclass;
3583 char *nname, *nclass;
3584
3585 ecore_x_icccm_name_class_get(win, &nname, &nclass);
3586 pname = ec->icccm.name;
3587 pclass = ec->icccm.class;
3588 ec->icccm.name = eina_stringshare_add(nname);
3589 ec->icccm.class = eina_stringshare_add(nclass);
3590 ec->hacks.mapping_change =
3591 ((!e_util_strcasecmp(ec->icccm.class, "vmplayer")) ||
3592 (!e_util_strcasecmp(ec->icccm.class, "vmware")));
3593 if (ec->hacks.mapping_change)
3594 _e_comp_x_mapping_change_disabled++;
3595 _e_comp_x_mapping_change_disabled = MIN(_e_comp_x_mapping_change_disabled, 0);
3596 free(nname);
3597 free(nclass);
3598
3599 if (!((ec->icccm.name == pname) &&
3600 (ec->icccm.class == pclass)))
3601 {
3602 ec->changes.icon = 1;
3603 rem_change = 1;
3604 }
3605
3606 eina_stringshare_del(pname);
3607 eina_stringshare_del(pclass);
3608 ec->icccm.fetch.name_class = 0;
3609 }
3610 if (ec->changes.prop || ec->e.fetch.state)
3611 {
3612 e_hints_window_e_state_get(ec);
3613 ec->e.fetch.state = 0;
3614 rem_change = 1;
3615 }
3616 if (ec->e.fetch.stack)
3617 {
3618 cd->stack = ecore_x_e_stack_type_get(win);
3619 ec->e.state.stack = !!cd->stack;
3620 ec->e.fetch.stack = 0;
3621 }
3622 if (ec->e.fetch.profile)
3623 {
3624 const char **list = NULL;
3625 int n, i, res;
3626 unsigned int use;
3627
3628 ec->e.state.profile.use = 0;
3629
3630 if (ec->e.state.profile.name)
3631 {
3632 eina_stringshare_del(ec->e.state.profile.name);
3633 ec->e.state.profile.name = NULL;
3634 }
3635
3636 if (ec->e.state.profile.available_list)
3637 {
3638 for (i = 0; i < ec->e.state.profile.num; i++)
3639 {
3640 if (ec->e.state.profile.available_list[i])
3641 {
3642 eina_stringshare_del(ec->e.state.profile.available_list[i]);
3643 ec->e.state.profile.available_list[i] = NULL;
3644 }
3645 }
3646 E_FREE(ec->e.state.profile.available_list);
3647 ec->e.state.profile.available_list = NULL;
3648 }
3649 ec->e.state.profile.num = 0;
3650
3651 res = ecore_x_window_prop_card32_get(win,
3652 ECORE_X_ATOM_E_WINDOW_PROFILE_SUPPORTED,
3653 &use,
3654 1);
3655 if ((res == 1) && (use == 1))
3656 {
3657 Ecore_X_Atom val;
3658 res = ecore_x_window_prop_atom_get(win,
3659 ECORE_X_ATOM_E_WINDOW_PROFILE_CHANGE,
3660 &val, 1);
3661 if (res == 1)
3662 {
3663 char *name = ecore_x_atom_name_get(val);
3664 if (name)
3665 {
3666 ec->e.state.profile.set = eina_stringshare_add(name);
3667 free(name);
3668 }
3669 }
3670
3671 if (ecore_x_e_window_available_profiles_get(win, &list, &n))
3672 {
3673 ec->e.state.profile.available_list = E_NEW(const char *, n);
3674 for (i = 0; i < n; i++)
3675 ec->e.state.profile.available_list[i] = eina_stringshare_add(list[i]);
3676 ec->e.state.profile.num = n;
3677 }
3678 need_desk_set = EINA_TRUE;
3679 ec->e.state.profile.use = 1;
3680 free(list);
3681 }
3682
3683 ec->e.fetch.profile = 0;
3684 }
3685 if (ec->changes.prop || ec->netwm.fetch.type)
3686 {
3687 unsigned int type = ec->netwm.type;
3688 e_hints_window_type_get(ec);
3689 if (((!ec->lock_border) || (!ec->border.name) || (type != ec->netwm.type)) && (cd->reparented || ec->internal))
3690 {
3691 ec->border.changed = 1;
3692 EC_CHANGED(ec);
3693 }
3694
3695 if ((ec->netwm.type == E_WINDOW_TYPE_DOCK) || ec->tooltip)
3696 {
3697 if (!ec->netwm.state.skip_pager)
3698 {
3699 ec->netwm.state.skip_pager = 1;
3700 ec->netwm.update.state = 1;
3701 }
3702 if (!ec->netwm.state.skip_taskbar)
3703 {
3704 ec->netwm.state.skip_taskbar = 1;
3705 ec->netwm.update.state = 1;
3706 }
3707 }
3708 else if (ec->netwm.type == E_WINDOW_TYPE_DESKTOP)
3709 {
3710 ec->focus_policy_override = E_FOCUS_CLICK;
3711 _e_comp_x_focus_setdown(ec);
3712 _e_comp_x_focus_setup(ec);
3713 e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3714 e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, pwin);
3715 if (!ec->netwm.state.skip_pager)
3716 {
3717 ec->netwm.state.skip_pager = 1;
3718 ec->netwm.update.state = 1;
3719 }
3720 if (!ec->netwm.state.skip_taskbar)
3721 {
3722 ec->netwm.state.skip_taskbar = 1;
3723 ec->netwm.update.state = 1;
3724 }
3725 if (!e_client_util_ignored_get(ec))
3726 ec->border.changed = ec->borderless = 1;
3727 }
3728 if (ec->tooltip)
3729 {
3730 ec->icccm.accepts_focus = 0;
3731 eina_stringshare_replace(&ec->bordername, "borderless");
3732 }
3733 {
3734 E_Event_Client_Property *ev;
3735
3736 ev = E_NEW(E_Event_Client_Property, 1);
3737 ev->ec = ec;
3738 REFD(ec, 1);
3739 e_object_ref(E_OBJECT(ec));
3740 ev->property = E_CLIENT_PROPERTY_NETWM_STATE;
3741 ecore_event_add(E_EVENT_CLIENT_PROPERTY, ev, _e_comp_x_client_event_free, NULL);
3742 }
3743 ec->netwm.fetch.type = 0;
3744 }
3745 if (ec->icccm.fetch.machine)
3746 {
3747 char *machine = ecore_x_icccm_client_machine_get(win);
3748
3749 if ((!machine) && (ec->icccm.client_leader))
3750 machine = ecore_x_icccm_client_machine_get(ec->icccm.client_leader);
3751
3752 eina_stringshare_replace(&ec->icccm.machine, machine);
3753 free(machine);
3754
3755 ec->icccm.fetch.machine = 0;
3756 rem_change = 1;
3757 }
3758 if (ec->icccm.fetch.command)
3759 {
3760 if ((ec->icccm.command.argc > 0) && (ec->icccm.command.argv))
3761 {
3762 int i;
3763
3764 for (i = 0; i < ec->icccm.command.argc; i++)
3765 free(ec->icccm.command.argv[i]);
3766 free(ec->icccm.command.argv);
3767 }
3768 ec->icccm.command.argc = 0;
3769 ec->icccm.command.argv = NULL;
3770 ecore_x_icccm_command_get(win,
3771 &(ec->icccm.command.argc),
3772 &(ec->icccm.command.argv));
3773 if ((ec->icccm.client_leader) &&
3774 (!ec->icccm.command.argv))
3775 ecore_x_icccm_command_get(ec->icccm.client_leader,
3776 &(ec->icccm.command.argc),
3777 &(ec->icccm.command.argv));
3778 ec->icccm.fetch.command = 0;
3779 rem_change = 1;
3780 }
3781 if (ec->changes.prop || ec->icccm.fetch.hints)
3782 {
3783 Eina_Bool accepts_focus, is_urgent;
3784 Ecore_X_Window_State_Hint state = ec->icccm.state;
3785
3786 accepts_focus = EINA_TRUE;
3787 is_urgent = EINA_FALSE;
3788 ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_NORMAL;
3789 if (ecore_x_icccm_hints_get(win,
3790 &accepts_focus,
3791 &ec->icccm.state,
3792 &ec->icccm.icon_pixmap,
3793 &ec->icccm.icon_mask,
3794 (Ecore_X_Window*)&ec->icccm.icon_window,
3795 (Ecore_X_Window*)&ec->icccm.window_group,
3796 &is_urgent))
3797 {
3798 if (ec->new_client)
3799 {
3800 /* clients may unset iconic state when no wm is present */
3801 if (ec->netwm.state.hidden && (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
3802 ec->icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_ICONIC;
3803 else
3804 ec->icccm.initial_state = ec->icccm.state;
3805 }
3806 if (state != ec->icccm.state)
3807 {
3808 if (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_WITHDRAWN)
3809 ec->ignored = 1, ec->visible = 0;
3810 else
3811 {
3812 ec->visible = 1;
3813 ec->changes.visible = ec->new_client;
3814 if ((!ec->new_client) &&
3815 (ec->icccm.state == ECORE_X_WINDOW_STATE_HINT_NORMAL))
3816 evas_object_show(ec->frame);
3817 }
3818 }
3819 ec->icccm.accepts_focus = accepts_focus;
3820 ec->icccm.urgent = is_urgent;
3821 e_client_urgent_set(ec, is_urgent);
3822
3823 /* If this is a new window, set the state as requested. */
3824 if ((ec->new_client) &&
3825 (ec->icccm.initial_state == ECORE_X_WINDOW_STATE_HINT_ICONIC))
3826 e_client_iconify(ec);
3827 }
3828 ec->icccm.fetch.hints = 0;
3829 rem_change = 1;
3830 }
3831 if (ec->override) ec->placed = EINA_TRUE;
3832 if (ec->changes.prop || ec->icccm.fetch.size_pos_hints)
3833 {
3834 Eina_Bool request_pos;
3835
3836 request_pos = EINA_FALSE;
3837 if (ecore_x_icccm_size_pos_hints_get(win,
3838 &request_pos,
3839 &ec->icccm.gravity,
3840 &ec->icccm.min_w,
3841 &ec->icccm.min_h,
3842 &ec->icccm.max_w,
3843 &ec->icccm.max_h,
3844 &ec->icccm.base_w,
3845 &ec->icccm.base_h,
3846 &ec->icccm.step_w,
3847 &ec->icccm.step_h,
3848 &ec->icccm.min_aspect,
3849 &ec->icccm.max_aspect))
3850 {
3851 ec->icccm.request_pos = request_pos;
3852 if (request_pos && (!ec->placed) && (!ec->re_manage))
3853 {
3854 Ecore_X_Window_Attributes *att;
3855 int bw;
3856 int l, r, t, b;
3857 int zx = 0, zy = 0, zw = 0, zh = 0;
3858
3859 if (ec->zone)
3860 e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
3861 e_comp_object_frame_geometry_get(ec->frame, &l, &r, &t, &b);
3862 att = &cd->initial_attributes;
3863 bw = att->border * 2;
3864 switch (ec->icccm.gravity)
3865 {
3866 case ECORE_X_GRAVITY_N:
3867 ec->x = (att->x - (bw / 2)) - (l / 2);
3868 ec->y = att->y;
3869 break;
3870
3871 case ECORE_X_GRAVITY_NE:
3872 ec->x = (att->x - (bw)) - (l);
3873 ec->y = att->y;
3874 break;
3875
3876 case ECORE_X_GRAVITY_E:
3877 ec->x = (att->x - (bw)) - (l);
3878 ec->y = (att->y - (bw / 2)) - (t / 2);
3879 break;
3880
3881 case ECORE_X_GRAVITY_SE:
3882 ec->x = (att->x - (bw)) - (l);
3883 ec->y = (att->y - (bw)) - (t);
3884 break;
3885
3886 case ECORE_X_GRAVITY_S:
3887 ec->x = (att->x - (bw / 2)) - (l / 2);
3888 ec->y = (att->y - (bw)) - (t);
3889 break;
3890
3891 case ECORE_X_GRAVITY_SW:
3892 ec->x = att->x;
3893 ec->y = (att->y - (bw)) - (t);
3894 break;
3895
3896 case ECORE_X_GRAVITY_W:
3897 ec->x = att->x;
3898 ec->y = (att->y - (bw)) - (t);
3899 break;
3900
3901 case ECORE_X_GRAVITY_CENTER:
3902 ec->x = (att->x - (bw / 2)) - (l / 2);
3903 ec->y = (att->y - (bw / 2)) - (t / 2);
3904 break;
3905
3906 case ECORE_X_GRAVITY_NW:
3907 default:
3908 ec->x = att->x;
3909 ec->y = att->y;
3910 }
3911
3912 /*
3913 * This ensures that windows that like to open with a x/y
3914 * position smaller than returned by e_zone_useful_geometry_get()
3915 * are moved to useful positions.
3916 */
3917 // ->
3918 if (e_config->geometry_auto_move)
3919 {
3920 if (ec->x < zx)
3921 ec->x = zx;
3922
3923 if (ec->y < zy)
3924 ec->y = zy;
3925
3926 /* ensure we account for windows which already have client_inset;
3927 * fixes lots of wine placement issues
3928 */
3929 if (ec->x - l >= zx)
3930 ec->x -= l;
3931 if (ec->y - t >= zy)
3932 ec->y -= t;
3933
3934 if (ec->x + ec->w > zx + zw)
3935 ec->x = zx + zw - ec->w;
3936
3937 if (ec->y + ec->h > zy + zh)
3938 ec->y = zy + zh - ec->h;
3939
3940 // <--
3941 if (e_comp_zone_xy_get(ec->x, ec->y))
3942 {
3943 if (!E_INSIDE(ec->x, ec->y, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
3944 {
3945 ec->x = E_CLAMP(ec->x, ec->zone->x, ec->zone->x + ec->zone->w);
3946 ec->y = E_CLAMP(ec->y, ec->zone->y, ec->zone->y + ec->zone->h);
3947 }
3948 /* some application failing to correctly center a window */
3949 if (eina_list_count(e_comp->zones) > 1)
3950 {
3951 if (abs((e_comp->w / 2) - ec->x - (ec->w / 2)) < 3)
3952 ec->x = ((ec->zone->x + ec->zone->w) / 2) - (ec->w / 2);
3953 if (abs((e_comp->h / 2) - ec->y - (ec->h / 2)) < 3)
3954 ec->y = ((ec->zone->y + ec->zone->h) / 2) - (ec->h / 2);
3955 }
3956 ec->changes.pos = 1;
3957 ec->placed = 1;
3958 }
3959 }
3960 else
3961 {
3962 ec->changes.pos = 1;
3963 ec->placed = 1;
3964 }
3965 }
3966 if (ec->placed && (!e_client_util_resizing_get(ec)) && (!ec->override))
3967 {
3968 if (ec->fullscreen || ec->maximized)
3969 e_client_rescale(ec);
3970 else
3971 {
3972 int rw = ec->w, rh = ec->h;
3973
3974 e_client_resize_limit(ec, &rw, &rh);
3975 evas_object_resize(ec->frame, rw, rh);
3976 }
3977 }
3978 }
3979 if (ec->icccm.min_w > 32767) ec->icccm.min_w = 32767;
3980 if (ec->icccm.min_h > 32767) ec->icccm.min_h = 32767;
3981 if (ec->icccm.max_w > 32767) ec->icccm.max_w = 32767;
3982 if (ec->icccm.max_h > 32767) ec->icccm.max_h = 32767;
3983 if (ec->icccm.base_w > 32767) ec->icccm.base_w = 32767;
3984 if (ec->icccm.base_h > 32767) ec->icccm.base_h = 32767;
3985 // if (ec->icccm.step_w < 1) ec->icccm.step_w = 1;
3986 // if (ec->icccm.step_h < 1) ec->icccm.step_h = 1;
3987 // if doing a resize, fix it up
3988 if (e_client_util_resizing_get(ec))
3989 {
3990 int x, y, w, h, new_w, new_h;
3991
3992 x = ec->x;
3993 y = ec->y;
3994 w = ec->w;
3995 h = ec->h;
3996 new_w = w;
3997 new_h = h;
3998 e_client_resize_limit(ec, &new_w, &new_h);
3999 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
4000 (ec->resize_mode == E_POINTER_RESIZE_L) ||
4001 (ec->resize_mode == E_POINTER_RESIZE_BL))
4002 x += (w - new_w);
4003 if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
4004 (ec->resize_mode == E_POINTER_RESIZE_T) ||
4005 (ec->resize_mode == E_POINTER_RESIZE_TR))
4006 y += (h - new_h);
4007 evas_object_geometry_set(ec->frame, x, y, new_w, new_h);
4008 }
4009 ec->icccm.fetch.size_pos_hints = 0;
4010 rem_change = 1;
4011 }
4012 if (ec->icccm.fetch.protocol)
4013 {
4014 int i, num;
4015 Ecore_X_WM_Protocol *proto;
4016
4017 proto = ecore_x_window_prop_protocol_list_get(win, &num);
4018 if (proto)
4019 {
4020 for (i = 0; i < num; i++)
4021 {
4022 if (proto[i] == ECORE_X_WM_PROTOCOL_DELETE_REQUEST)
4023 ec->icccm.delete_request = 1;
4024 else if (proto[i] == ECORE_X_WM_PROTOCOL_TAKE_FOCUS)
4025 ec->icccm.take_focus = 1;
4026 else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_PING)
4027 ec->netwm.ping = 1;
4028 else if (proto[i] == ECORE_X_NET_WM_PROTOCOL_SYNC_REQUEST)
4029 {
4030 ec->netwm.sync.request = 1;
4031 if (!ecore_x_netwm_sync_counter_get(win,
4032 &cd->sync_counter))
4033 ec->netwm.sync.request = 0;
4034 }
4035 }
4036 free(proto);
4037 }
4038 if (ec->netwm.ping && cd->evas_init)
4039 e_client_ping(ec);
4040 else
4041 E_FREE_FUNC(ec->ping_poller, ecore_poller_del);
4042 ec->icccm.fetch.protocol = 0;
4043 }
4044 if (ec->icccm.fetch.transient_for)
4045 {
4046 /* TODO: What do to if the transient for isn't mapped yet? */
4047 E_Client *ec_parent = NULL;
4048
4049 ec->icccm.transient_for = ecore_x_icccm_transient_for_get(win);
4050 if (ec->icccm.transient_for)
4051 ec_parent = _e_comp_x_client_find_by_window(ec->icccm.transient_for);
4052
4053 e_client_parent_set(ec, ec_parent);
4054 if (ec->parent && (!e_client_util_ignored_get(ec)) && ec->netwm.state.modal)
4055 _e_comp_x_client_modal_setup(ec);
4056 if ((ec_parent) && (cd->stack != ECORE_X_STACK_NONE))
4057 {
4058 E_Client *ec2;
4059
4060 // find last one
4061 for (ec2 = ec_parent; ec2->stack.next; ec2 = ec2->stack.next);
4062 ec->stack.prev = ec2;
4063 ec->stack.next = NULL;
4064 ec->stack.prev->stack.next = ec;
4065 }
4066 ec->icccm.fetch.transient_for = 0;
4067 rem_change = 1;
4068 }
4069 if (ec->icccm.fetch.window_role)
4070 {
4071 char *role = ecore_x_icccm_window_role_get(win);
4072 eina_stringshare_replace(&ec->icccm.window_role, role);
4073 free(role);
4074
4075 ec->icccm.fetch.window_role = 0;
4076 rem_change = 1;
4077 }
4078 if (ec->icccm.fetch.icon_name)
4079 {
4080 char *icon_name = ecore_x_icccm_icon_name_get(win);
4081 eina_stringshare_replace(&ec->icccm.icon_name, icon_name);
4082 free(icon_name);
4083
4084 ec->hacks.iconic_shading =
4085 ((ec->netwm.icon_name == ec->netwm.name) &&
4086 (!e_util_strcmp(ec->netwm.icon_name, "QEMU")));
4087
4088 ec->icccm.fetch.icon_name = 0;
4089 rem_change = 1;
4090 }
4091 if (ec->netwm.fetch.icon_name)
4092 {
4093 char *icon_name;
4094 ecore_x_netwm_icon_name_get(win, &icon_name);
4095 eina_stringshare_replace(&ec->netwm.icon_name, icon_name);
4096 free(icon_name);
4097
4098 ec->netwm.fetch.icon_name = 0;
4099 rem_change = 1;
4100 }
4101 if (ec->netwm.fetch.opacity)
4102 {
4103 unsigned int val;
4104
4105 if (ecore_x_netwm_opacity_get(win, &val))
4106 {
4107 val >>= 24;
4108 if (ec->netwm.opacity != val)
4109 {
4110 ec->netwm.opacity = val;
4111 evas_object_color_set(ec->frame, val, val, val, val);
4112 rem_change = 1;
4113 }
4114 ec->netwm.fetch.opacity = !ec->netwm.opacity;
4115 }
4116 else
4117 ec->netwm.fetch.opacity = 0;
4118 }
4119 if (ec->netwm.fetch.icon)
4120 {
4121 _e_comp_x_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
4122 ec->netwm.icons = NULL;
4123 ec->netwm.num_icons = 0;
4124 if (ecore_x_netwm_icons_get(win,
4125 &ec->netwm.icons,
4126 &ec->netwm.num_icons))
4127 {
4128 if (ec->netwm.icons)
4129 ec->netwm.icons = _e_comp_x_client_icon_deduplicate
4130 (ec->netwm.icons, ec->netwm.num_icons);
4131 ec->changes.icon = 1;
4132 }
4133 ec->netwm.fetch.icon = 0;
4134 }
4135 if (ec->netwm.fetch.user_time)
4136 {
4137 ecore_x_netwm_user_time_get(win, &ec->netwm.user_time);
4138 ec->netwm.fetch.user_time = 0;
4139 }
4140 if (ec->netwm.fetch.strut)
4141 {
4142 if (!ecore_x_netwm_strut_partial_get(win,
4143 &ec->netwm.strut.left,
4144 &ec->netwm.strut.right,
4145 &ec->netwm.strut.top,
4146 &ec->netwm.strut.bottom,
4147 &ec->netwm.strut.left_start_y,
4148 &ec->netwm.strut.left_end_y,
4149 &ec->netwm.strut.right_start_y,
4150 &ec->netwm.strut.right_end_y,
4151 &ec->netwm.strut.top_start_x,
4152 &ec->netwm.strut.top_end_x,
4153 &ec->netwm.strut.bottom_start_x,
4154 &ec->netwm.strut.bottom_end_x))
4155 {
4156 ecore_x_netwm_strut_get(win,
4157 &ec->netwm.strut.left, &ec->netwm.strut.right,
4158 &ec->netwm.strut.top, &ec->netwm.strut.bottom);
4159
4160 ec->netwm.strut.left_start_y = 0;
4161 ec->netwm.strut.left_end_y = 0;
4162 ec->netwm.strut.right_start_y = 0;
4163 ec->netwm.strut.right_end_y = 0;
4164 ec->netwm.strut.top_start_x = 0;
4165 ec->netwm.strut.top_end_x = 0;
4166 ec->netwm.strut.bottom_start_x = 0;
4167 ec->netwm.strut.bottom_end_x = 0;
4168 }
4169 ec->netwm.fetch.strut = 0;
4170 }
4171 if (ec->qtopia.fetch.soft_menu)
4172 {
4173 e_hints_window_qtopia_soft_menu_get(ec);
4174 ec->qtopia.fetch.soft_menu = 0;
4175 rem_change = 1;
4176 }
4177 if (ec->qtopia.fetch.soft_menus)
4178 {
4179 e_hints_window_qtopia_soft_menus_get(ec);
4180 ec->qtopia.fetch.soft_menus = 0;
4181 rem_change = 1;
4182 }
4183 if (ec->vkbd.fetch.state)
4184 {
4185 e_hints_window_virtual_keyboard_state_get(ec);
4186 ec->vkbd.fetch.state = 0;
4187 rem_change = 1;
4188 }
4189 if (ec->vkbd.fetch.vkbd)
4190 {
4191 e_hints_window_virtual_keyboard_get(ec);
4192 ec->vkbd.fetch.vkbd = 0;
4193 rem_change = 1;
4194 }
4195 if (cd->illume.conformant.fetch.conformant)
4196 {
4197 cd->illume.conformant.conformant =
4198 ecore_x_e_illume_conformant_get(win);
4199 cd->illume.conformant.fetch.conformant = 0;
4200 }
4201 if (cd->illume.quickpanel.fetch.state)
4202 {
4203 cd->illume.quickpanel.state =
4204 ecore_x_e_illume_quickpanel_state_get(win);
4205 cd->illume.quickpanel.fetch.state = 0;
4206 }
4207 if (cd->illume.quickpanel.fetch.quickpanel)
4208 {
4209 cd->illume.quickpanel.quickpanel =
4210 ecore_x_e_illume_quickpanel_get(win);
4211 cd->illume.quickpanel.fetch.quickpanel = 0;
4212 }
4213 if (cd->illume.quickpanel.fetch.priority.major)
4214 {
4215 cd->illume.quickpanel.priority.major =
4216 ecore_x_e_illume_quickpanel_priority_major_get(win);
4217 cd->illume.quickpanel.fetch.priority.major = 0;
4218 }
4219 if (cd->illume.quickpanel.fetch.priority.minor)
4220 {
4221 cd->illume.quickpanel.priority.minor =
4222 ecore_x_e_illume_quickpanel_priority_minor_get(win);
4223 cd->illume.quickpanel.fetch.priority.minor = 0;
4224 }
4225 if (cd->illume.quickpanel.fetch.zone)
4226 {
4227 cd->illume.quickpanel.zone =
4228 ecore_x_e_illume_quickpanel_zone_get(win);
4229 cd->illume.quickpanel.fetch.zone = 0;
4230 }
4231 if (cd->illume.drag.fetch.drag)
4232 {
4233 cd->illume.drag.drag =
4234 ecore_x_e_illume_drag_get(win);
4235 cd->illume.drag.fetch.drag = 0;
4236 }
4237 if (cd->illume.drag.fetch.locked)
4238 {
4239 cd->illume.drag.locked =
4240 ecore_x_e_illume_drag_locked_get(win);
4241 cd->illume.drag.fetch.locked = 0;
4242 }
4243 if (cd->illume.win_state.fetch.state)
4244 {
4245 cd->illume.win_state.state =
4246 ecore_x_e_illume_window_state_get(win);
4247 cd->illume.win_state.fetch.state = 0;
4248 }
4249 if (ec->changes.shape)
4250 {
4251 Ecore_X_Rectangle *rects;
4252 int num;
4253 Eina_Bool pshaped = ec->shaped;
4254
4255 ec->changes.shape = 0;
4256 rects = ecore_x_window_shape_rectangles_get(win, &num);
4257 if (rects && num)
4258 {
4259 int cw = 0, ch = 0;
4260
4261 /* This doesn't fix the race, but makes it smaller. we detect
4262 * this and if cw and ch != client w/h then mark this as needing
4263 * a shape change again to fixup next event loop.
4264 */
4265 ecore_x_window_size_get(win, &cw, &ch);
4266 /* normalize for client window dead zone */
4267 if (ec->border_size && (num == 1))
4268 {
4269 rects[0].x += ec->border_size;
4270 rects[0].y += ec->border_size;
4271 rects[0].width -= ec->border_size;
4272 rects[0].height -= ec->border_size;
4273 }
4274 if ((cw != ec->client.w) || (ch != ec->client.h))
4275 {
4276 ec->changes.shape = 1;
4277 EC_CHANGED(ec);
4278 }
4279 if ((num == 1) &&
4280 (rects[0].x == 0) &&
4281 (rects[0].y == 0) &&
4282 ((int)rects[0].width == cw) &&
4283 ((int)rects[0].height == ch))
4284 {
4285 if (ec->shaped)
4286 {
4287 ec->shaped = 0;
4288 if (cd->reparented && (!ec->bordername))
4289 {
4290 ec->border.changed = 1;
4291 EC_CHANGED(ec);
4292 }
4293 }
4294 }
4295 else
4296 {
4297 if (cd->reparented)
4298 {
4299 ecore_x_window_shape_rectangles_set(pwin, rects, num);
4300 if ((!ec->shaped) && (!ec->bordername))
4301 {
4302 ec->border.changed = 1;
4303 EC_CHANGED(ec);
4304 }
4305 }
4306 else
4307 {
4308 if (_e_comp_x_client_shape_rects_check(ec, rects, num))
4309 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
4310 }
4311 ec->shaped = 1;
4312 ec->changes.shape_input = 0;
4313 E_FREE(ec->shape_input_rects);
4314 ec->shape_input_rects_num = 0;
4315 }
4316 if (cd->reparented || (!ec->shaped))
4317 free(rects);
4318 if (ec->shape_changed)
4319 e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
4320 evas_object_pass_events_set(ec->frame, ec->netwm.type == E_WINDOW_TYPE_DND);
4321 }
4322 else
4323 {
4324 ec->shaped = 1;
4325 E_FREE(ec->shape_rects);
4326 ec->shape_rects_num = 0;
4327 E_FREE(ec->shape_input_rects);
4328 ec->shape_input_rects_num = 0;
4329 e_comp_object_frame_theme_set(ec->frame, E_COMP_OBJECT_FRAME_RESHADOW);
4330 if (ec->shaped && cd->reparented && (!ec->bordername))
4331 {
4332 ec->border.changed = 1;
4333 EC_CHANGED(ec);
4334 }
4335 evas_object_pass_events_set(ec->frame, 1);
4336 }
4337 if (ec->shaped != pshaped)
4338 {
4339 _e_comp_x_client_shape_input_rectangle_set(ec);
4340 if ((!ec->shaped) && cd->reparented)
4341 ecore_x_window_shape_mask_set(pwin, 0);
4342 }
4343 ec->need_shape_merge = 1;
4344 }
4345 if (ec->changes.shape_input)
4346 {
4347 Ecore_X_Rectangle *rects;
4348 Eina_Bool pshaped = ec->shaped_input, changed = EINA_FALSE;
4349 int num;
4350
4351 ec->changes.shape_input = 0;
4352 rects = ecore_x_window_shape_input_rectangles_get(win, &num);
4353 if (rects && num)
4354 {
4355 int cw = 0, ch = 0;
4356
4357 /* This doesn't fix the race, but makes it smaller. we detect
4358 * this and if cw and ch != client w/h then mark this as needing
4359 * a shape change again to fixup next event loop.
4360 */
4361 ecore_x_window_size_get(win, &cw, &ch);
4362 /* normalize for client window dead zone */
4363 if (ec->border_size && (num == 1))
4364 {
4365 rects[0].x += ec->border_size;
4366 rects[0].y += ec->border_size;
4367 rects[0].width -= ec->border_size;
4368 rects[0].height -= ec->border_size;
4369 }
4370 if ((cw != ec->client.w) || (ch != ec->client.h))
4371 ec->changes.shape_input = 1;
4372 if (num == 1)
4373 E_RECTS_CLIP_TO_RECT(rects[0].x, rects[0].y, rects[0].width, rects[0].height, 0, 0, cw, ch);
4374 if ((num == 1) &&
4375 (rects[0].x == 0) &&
4376 (rects[0].y == 0) &&
4377 ((int)rects[0].width == cw) &&
4378 ((int)rects[0].height == ch))
4379 {
4380 ec->shaped_input = 0;
4381 free(rects);
4382 }
4383 else
4384 {
4385 ec->shaped_input = 1;
4386 if (cd->reparented)
4387 ecore_x_window_shape_input_rectangles_set(pwin, rects, num);
4388 changed = EINA_TRUE;
4389 free(ec->shape_input_rects);
4390 ec->shape_input_rects = (Eina_Rectangle*)rects;
4391 ec->shape_input_rects_num = num;
4392 }
4393 evas_object_pass_events_set(ec->frame, ec->netwm.type == E_WINDOW_TYPE_DND);
4394 }
4395 else
4396 {
4397 ec->shaped_input = 1;
4398 if (cd->reparented)
4399 ecore_x_window_shape_input_rectangles_set(pwin, rects, num);
4400 changed = EINA_TRUE;
4401 evas_object_pass_events_set(ec->frame, 1);
4402 free(ec->shape_input_rects);
4403 ec->shape_input_rects = NULL;
4404 ec->shape_input_rects_num = 0;
4405 }
4406 if (changed || (pshaped != ec->shaped_input))
4407 {
4408 ec->need_shape_merge = 1;
4409 e_comp_shape_queue();
4410 }
4411 }
4412 if (ec->changes.prop || ec->mwm.fetch.hints)
4413 {
4414 int pb;
4415
4416 ec->mwm.exists =
4417 ecore_x_mwm_hints_get(win,
4418 &ec->mwm.func,
4419 &ec->mwm.decor,
4420 &ec->mwm.input);
4421 pb = ec->mwm.borderless;
4422 ec->mwm.borderless = 0;
4423 if (ec->mwm.exists)
4424 {
4425 if ((!(ec->mwm.decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
4426 (!(ec->mwm.decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
4427 (!(ec->mwm.decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
4428 ec->mwm.borderless = 1;
4429 }
4430 if (ec->mwm.borderless != pb)
4431 {
4432 if ((ec->internal || cd->reparented) && ((!ec->lock_border) || (!ec->border.name)))
4433 {
4434 ec->border.changed = 1;
4435 EC_CHANGED(ec);
4436 }
4437 }
4438 ec->mwm.fetch.hints = 0;
4439 rem_change = 1;
4440 }
4441 if (ec->e.fetch.video_parent)
4442 {
4443 /* unlinking child/parent */
4444 if (ec->e.state.video_parent_client != NULL)
4445 {
4446 ec->e.state.video_parent_client->e.state.video_child =
4447 eina_list_remove(ec->e.state.video_parent_client->e.state.video_child, ec);
4448 }
4449
4450 ecore_x_window_prop_card32_get(win,
4451 ECORE_X_ATOM_E_VIDEO_PARENT,
4452 (Ecore_X_Window*)&ec->e.state.video_parent, 1);
4453
4454 /* linking child/parent */
4455 if (ec->e.state.video_parent != 0)
4456 {
4457 E_Client *tmp;
4458
4459 tmp = _e_comp_x_client_find_by_window(ec->e.state.video_parent);
4460 if (tmp)
4461 {
4462 /* fprintf(stderr, "child added to parent \\o/\n"); */
4463 ec->e.state.video_parent_client = tmp;
4464 tmp->e.state.video_child = eina_list_append(tmp->e.state.video_child, ec);
4465 if (ec->desk != tmp->desk)
4466 e_client_desk_set(ec, tmp->desk);
4467 }
4468 }
4469
4470 /* fprintf(stderr, "new parent %x => %p\n", ec->e.state.video_parent, ec->e.state.video_parent_client); */
4471
4472 if (ec->e.state.video_parent_client) ec->e.fetch.video_parent = 0;
4473 rem_change = 1;
4474 }
4475 if (ec->e.fetch.video_position && ec->e.fetch.video_parent == 0)
4476 {
4477 unsigned int xy[2];
4478
4479 ecore_x_window_prop_card32_get(win,
4480 ECORE_X_ATOM_E_VIDEO_POSITION,
4481 xy, 2);
4482 ec->e.state.video_position.x = xy[0];
4483 ec->e.state.video_position.y = xy[1];
4484 ec->e.state.video_position.updated = 1;
4485 ec->e.fetch.video_position = 0;
4486 ec->x = ec->e.state.video_position.x;
4487 ec->y = ec->e.state.video_position.y;
4488
4489 fprintf(stderr, "internal position has been updated [%i, %i]\n", ec->e.state.video_position.x, ec->e.state.video_position.y);
4490 }
4491 if (ec->changes.prop || ec->netwm.update.state)
4492 {
4493 e_hints_window_state_set(ec);
4494 /* Some stats might change the border, like modal */
4495 if (((!ec->lock_border) || (!ec->border.name)) &&
4496 (!(((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN))) &&
4497 (ec->internal || cd->reparented))
4498 {
4499 ec->border.changed = 1;
4500 EC_CHANGED(ec);
4501 }
4502 if (ec->parent)
4503 {
4504 if (ec->netwm.state.modal)
4505 {
4506 ec->parent->modal = ec;
4507 if (ec->parent->focused)
4508 evas_object_focus_set(ec->frame, 1);
4509 }
4510 }
4511 else if (ec->leader)
4512 {
4513 if (ec->netwm.state.modal)
4514 {
4515 ec->leader->modal = ec;
4516 if (ec->leader->focused)
4517 evas_object_focus_set(ec->frame, 1);
4518 else
4519 {
4520 Eina_List *l;
4521 E_Client *child;
4522
4523 EINA_LIST_FOREACH(ec->leader->group, l, child)
4524 {
4525 if ((child != ec) && (child->focused))
4526 evas_object_focus_set(ec->frame, 1);
4527 }
4528 }
4529 }
4530 }
4531 ec->netwm.update.state = 0;
4532 }
4533
4534 if (cd->fetch_exe)
4535 {
4536 E_Exec_Instance *inst;
4537
4538 if (((!ec->lock_border) || (!ec->border.name)) &&
4539 (ec->internal || cd->reparented))
4540 {
4541 ec->border.changed = 1;
4542 EC_CHANGED(ec);
4543 }
4544
4545 {
4546 char *str = NULL;
4547
4548 if ((!ec->internal) &&
4549 ((ecore_x_netwm_startup_id_get(win, &str) && (str)) ||
4550 ((ec->icccm.client_leader > 0) &&
4551 ecore_x_netwm_startup_id_get(ec->icccm.client_leader, &str) && (str)))
4552 )
4553 {
4554 if (!strncmp(str, "E_START|", 8))
4555 {
4556 int id;
4557
4558 id = atoi(str + 8);
4559 if (id > 0) ec->netwm.startup_id = id;
4560 }
4561 free(str);
4562 }
4563 }
4564 /* It's ok not to have fetch flag, should only be set on startup
4565 * and not changed. */
4566 if (!ecore_x_netwm_pid_get(win, &ec->netwm.pid))
4567 {
4568 if (ec->icccm.client_leader)
4569 {
4570 if (!ecore_x_netwm_pid_get(ec->icccm.client_leader, &ec->netwm.pid))
4571 ec->netwm.pid = -1;
4572 }
4573 else
4574 ec->netwm.pid = -1;
4575 }
4576
4577 if (!e_client_util_ignored_get(ec))
4578 {
4579 inst = e_exec_startup_id_pid_instance_find(ec->netwm.startup_id,
4580 ec->netwm.pid);
4581 if (inst)
4582 {
4583 Eina_Bool found;
4584
4585 if (inst->used == 0)
4586 {
4587 inst->used++;
4588 if ((!ec->remember) || !(ec->remember->apply & E_REMEMBER_APPLY_DESKTOP))
4589 {
4590 E_Zone *zone;
4591 E_Desk *desk;
4592
4593 zone = e_comp_zone_number_get(inst->screen);
4594 if (zone) e_client_zone_set(ec, zone);
4595 desk = e_desk_at_xy_get(ec->zone, inst->desk_x,
4596 inst->desk_y);
4597 if (desk) e_client_desk_set(ec, desk);
4598 }
4599 if (ec->netwm.pid != ecore_exe_pid_get(inst->exe))
4600 {
4601 /* most likely what has happened here is that the .desktop launcher
4602 * has spawned a process which then created this border, meaning the
4603 * E_Exec instance will be deleted in a moment, and we will be unable to track it.
4604 * to prevent this, we convert our instance to a phony
4605 */
4606 inst->phony = 1;
4607 }
4608 }
4609 found = !!inst->clients;
4610 e_exec_instance_client_add(inst, ec);
4611 if (!found)
4612 e_exec_instance_found(inst);
4613 }
4614
4615 if (e_config->window_grouping) // FIXME: We may want to make the border "urgent" so that the user knows it appeared.
4616 {
4617 E_Client *ecl = NULL;
4618
4619 ecl = ec->parent;
4620 if (!ecl)
4621 ecl = ec->leader;
4622 if (!ecl)
4623 {
4624 E_Client *child;
4625
4626 E_CLIENT_FOREACH(child)
4627 {
4628 if (child == ec) continue;
4629 if (e_object_is_del(E_OBJECT(child))) continue;
4630 if ((ec->icccm.client_leader) &&
4631 (child->icccm.client_leader ==
4632 ec->icccm.client_leader))
4633 {
4634 ecl = child;
4635 break;
4636 }
4637 }
4638 }
4639 if (ecl)
4640 {
4641 if (ecl->zone)
4642 e_client_zone_set(ec, ecl->zone);
4643 if (ecl->desk)
4644 e_client_desk_set(ec, ecl->desk);
4645 else
4646 e_client_stick(ec);
4647 }
4648 }
4649 }
4650 cd->fetch_exe = 0;
4651 }
4652
4653 if (need_desk_set)
4654 {
4655 E_Desk *desk = NULL;
4656 const char *p, *p2;
4657 Eina_Bool set = EINA_FALSE;
4658 int i;
4659
4660 /* set desktop using given initial profile */
4661 p = ec->e.state.profile.set;
4662 if (p)
4663 {
4664 if (!e_util_strcmp(p, ec->desk->window_profile))
4665 {
4666 e_client_desk_window_profile_wait_desk_set(ec, ec->desk);
4667 set = EINA_TRUE;
4668 }
4669 else
4670 {
4671 desk = e_comp_desk_window_profile_get(p);
4672 if (desk)
4673 {
4674 e_client_desk_set(ec, desk);
4675 set = EINA_TRUE;
4676 }
4677 }
4678 }
4679
4680 if (!set)
4681 {
4682 /* try to find desktop using available profile list */
4683 for (i = 0; i < ec->e.state.profile.num; i++)
4684 {
4685 p2 = ec->e.state.profile.available_list[i];
4686 if (!e_util_strcmp(p2, ec->desk->window_profile))
4687 {
4688 eina_stringshare_replace(&ec->e.state.profile.set, p2);
4689 e_client_desk_window_profile_wait_desk_set(ec, ec->desk);
4690 set = EINA_TRUE;
4691 break;
4692 }
4693 }
4694 if (!set)
4695 {
4696 for (i = 0; i < ec->e.state.profile.num; i++)
4697 {
4698 p2 = ec->e.state.profile.available_list[i];
4699 desk = e_comp_desk_window_profile_get(p2);
4700 if (desk)
4701 {
4702 e_client_desk_set(ec, desk);
4703 set = EINA_TRUE;
4704 break;
4705 }
4706 }
4707 }
4708 }
4709
4710 if ((!set) && ec->desk)
4711 {
4712 eina_stringshare_replace(&ec->e.state.profile.set, ec->desk->window_profile);
4713 e_client_desk_window_profile_wait_desk_set(ec, ec->desk);
4714 }
4715 }
4716
4717 if (ec->e.state.profile.set)
4718 {
4719 printf("E: sent profile set req to 0x%x [%s]\n", win, ec->e.state.profile.set);
4720 ecore_x_e_window_profile_change_request_send(win,
4721 ec->e.state.profile.set);
4722 eina_stringshare_replace(&ec->e.state.profile.wait, ec->e.state.profile.set);
4723 ec->e.state.profile.wait_for_done = 1;
4724 eina_stringshare_replace(&ec->e.state.profile.set, NULL);
4725 }
4726 if (cd->fetch_gtk_frame_extents)
4727 {
4728 unsigned int *extents;
4729 int count;
4730
4731 if (ecore_x_window_prop_property_get(win,
4732 ATM_GTK_FRAME_EXTENTS,
4733 ECORE_X_ATOM_CARDINAL, 32,
4734 (void *)(&extents), &count))
4735 {
4736 /* _GTK_FRAME_EXTENTS describes a region l/r/t/b pixels
4737 * from the "window" object in which shadows will be drawn.
4738 * this area should not be accounted for in sizing or
4739 * placement calculations.
4740 */
4741 e_comp_object_frame_geometry_set(ec->frame,
4742 -extents[0], -extents[1], -extents[2], -extents[3]);
4743 if (ec->override &&
4744 (ec->x == ec->comp_data->initial_attributes.x) &&
4745 (ec->y == ec->comp_data->initial_attributes.y))
4746 e_comp_object_frame_xy_adjust(ec->frame, ec->x, ec->y, &ec->x, &ec->y);
4747 free(extents);
4748 }
4749 cd->fetch_gtk_frame_extents = 0;
4750 }
4751 ec->changes.prop = 0;
4752 if (rem_change) e_remember_update(ec);
4753 if ((!cd->reparented) && (!ec->internal)) ec->changes.border = 0;
4754 if (ec->changes.icon)
4755 {
4756 /* don't create an icon until we need it */
4757 if (cd->reparented) return;
4758 cd->change_icon = 1;
4759 ec->changes.icon = 0;
4760 }
4761 }
4762
4763 static Eina_Bool
_e_comp_x_first_draw_delay_cb(void * data)4764 _e_comp_x_first_draw_delay_cb(void *data)
4765 {
4766 E_Client *ec = data;
4767
4768 _e_comp_x_client_data_get(ec)->first_draw_delay = NULL;
4769 if (ec->shape_rects || (!ec->shaped))
4770 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
4771 return EINA_FALSE;
4772 }
4773
4774 static void
_e_comp_x_hook_client_new(void * d EINA_UNUSED,E_Client * ec)4775 _e_comp_x_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
4776 {
4777 Ecore_X_Window win;
4778 Eina_List *pending;
4779 Pending_Configure *pc;
4780
4781 E_COMP_X_PIXMAP_CHECK;
4782 win = e_pixmap_window_get(ec->pixmap);
4783 ec->ignored = e_comp_ignore_win_find(win);
4784
4785 ec->comp_data = E_NEW(E_Comp_Client_Data, 1);
4786 ec->comp_data->set_win_type = ec->comp_data->fetch_exe = 1;
4787
4788 /* FIXME: ewww - round trip */
4789 ec->argb = ecore_x_window_argb_get(win);
4790 ec->changes.shape = 1;
4791 ec->changes.shape_input = 1;
4792
4793 ec->netwm.type = E_WINDOW_TYPE_UNKNOWN;
4794 ec->icccm.state = ec->icccm.initial_state = ECORE_X_WINDOW_STATE_HINT_NONE;
4795
4796 if (!_e_comp_x_client_new_helper(ec)) return;
4797 ec->ignored |= e_comp->comp_type == E_PIXMAP_TYPE_WL;
4798 pending = eina_hash_set(pending_configures, &win, NULL);
4799 if (pending)
4800 {
4801 Eina_Bool request_pos = EINA_FALSE;
4802
4803 /* UGLY: round trip, but necessary to work around bad clients
4804 * positioning windows anyway AND libreoffice trying to hack
4805 * getting its windows across multiple screens this way
4806 * which isn't really right either... */
4807 ecore_x_icccm_size_pos_hints_get(win,
4808 &request_pos,
4809 &ec->icccm.gravity,
4810 &ec->icccm.min_w,
4811 &ec->icccm.min_h,
4812 &ec->icccm.max_w,
4813 &ec->icccm.max_h,
4814 &ec->icccm.base_w,
4815 &ec->icccm.base_h,
4816 &ec->icccm.step_w,
4817 &ec->icccm.step_h,
4818 &ec->icccm.min_aspect,
4819 &ec->icccm.max_aspect);
4820 if (request_pos)
4821 {
4822 Eina_List *l;
4823 E_Zone *zone;
4824 pc = eina_list_last_data_get(pending);
4825 EINA_LIST_FOREACH(e_comp->zones, l, zone)
4826 {
4827 if (E_INTERSECTS(pc->point.x, pc->point.y, ec->w, ec->h,
4828 zone->x, zone->y, zone->w, zone->h))
4829 {
4830 e_client_zone_set(ec, zone);
4831 break;
4832 }
4833 }
4834 }
4835 }
4836 EINA_LIST_FREE(pending, pc)
4837 {
4838 ecore_timer_del(pc->timer);
4839 free(pc);
4840 }
4841
4842 ec->comp_data->first_damage = ec->internal;
4843
4844 eina_hash_add(clients_win_hash, &win, ec);
4845 if (!ec->input_only)
4846 ec->comp_data->first_draw_delay = ecore_timer_loop_add(e_comp_config_get()->first_draw_delay, _e_comp_x_first_draw_delay_cb, ec);
4847 }
4848
4849 static void
_e_comp_x_hook_client_focus_unset_job(void * d EINA_UNUSED)4850 _e_comp_x_hook_client_focus_unset_job(void *d EINA_UNUSED)
4851 {
4852 E_Client *ec = unfocus_job_client;
4853 unfocus_job = NULL;
4854 if (!unfocus_job_client) return;
4855 unfocus_job_client = NULL;
4856 E_COMP_X_PIXMAP_CHECK;
4857 _e_comp_x_focus_setup(ec);
4858 _e_comp_x_focus_check();
4859 }
4860
4861 static void
_e_comp_x_hook_client_focus_unset(void * d EINA_UNUSED,E_Client * ec)4862 _e_comp_x_hook_client_focus_unset(void *d EINA_UNUSED, E_Client *ec)
4863 {
4864 if (focus_job_client == ec)
4865 {
4866 focus_job_client = NULL;
4867 E_FREE_FUNC(focus_job, ecore_job_del);
4868 }
4869 if (ec->override) return;
4870 unfocus_job_client = ec;
4871 if (!unfocus_job)
4872 unfocus_job = ecore_job_add(_e_comp_x_hook_client_focus_unset_job, NULL);
4873 }
4874
4875 static void
_e_comp_x_hook_client_focus_set_job(void * d EINA_UNUSED)4876 _e_comp_x_hook_client_focus_set_job(void *d EINA_UNUSED)
4877 {
4878 E_Client *ec = focus_job_client;
4879 focus_job = NULL;
4880 if (!focus_job_client) return;
4881 focus_job_client = NULL;
4882 focus_time = ecore_x_current_time_get();
4883 focus_canvas_time = 0;
4884 if (!e_client_has_xwindow(ec))
4885 {
4886 e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
4887 return;
4888 }
4889 _e_comp_x_focus_setdown(ec);
4890
4891 if ((ec->icccm.take_focus) && (ec->icccm.accepts_focus))
4892 {
4893 e_grabinput_focus(e_client_util_win_get(ec), E_FOCUS_METHOD_LOCALLY_ACTIVE);
4894 /* TODO what if the client didn't take focus ? */
4895 }
4896 else if (!ec->icccm.accepts_focus)
4897 {
4898 e_grabinput_focus(e_client_util_win_get(ec), E_FOCUS_METHOD_GLOBALLY_ACTIVE);
4899 }
4900 else if (!ec->icccm.take_focus)
4901 {
4902 e_grabinput_focus(e_client_util_win_get(ec), E_FOCUS_METHOD_PASSIVE);
4903 }
4904 }
4905
4906 static void
_e_comp_x_hook_client_focus_set(void * d EINA_UNUSED,E_Client * ec)4907 _e_comp_x_hook_client_focus_set(void *d EINA_UNUSED, E_Client *ec)
4908 {
4909 if (unfocus_job_client == ec)
4910 {
4911 unfocus_job_client = NULL;
4912 E_FREE_FUNC(unfocus_job, ecore_job_del);
4913 }
4914 if (ec->override) return;
4915 focus_job_client = ec;
4916 if (!focus_job)
4917 focus_job = ecore_job_add(_e_comp_x_hook_client_focus_set_job, NULL);
4918 }
4919
4920 static void
_e_comp_x_hook_client_redirect(void * d EINA_UNUSED,E_Client * ec)4921 _e_comp_x_hook_client_redirect(void *d EINA_UNUSED, E_Client *ec)
4922 {
4923 E_COMP_X_PIXMAP_CHECK;
4924 if (_e_comp_x_client_data_get(ec)->unredirected_single)
4925 {
4926 ecore_x_composite_redirect_window(_e_comp_x_client_window_get(ec), ECORE_X_COMPOSITE_UPDATE_MANUAL);
4927 _e_comp_x_client_data_get(ec)->unredirected_single = 0;
4928 }
4929 else if (e_comp->nocomp)
4930 {
4931 /* first window */
4932 e_comp_x_nocomp_end();
4933 ecore_x_window_reparent(_e_comp_x_client_window_get(ec), e_comp->root, ec->client.x, ec->client.y);
4934 _e_comp_x_client_stack(ec);
4935 }
4936 if (!_e_comp_x_client_data_get(ec)->damage)
4937 _e_comp_x_client_damage_add(ec);
4938 }
4939
4940 static void
_e_comp_x_hook_client_unredirect(void * d EINA_UNUSED,E_Client * ec)4941 _e_comp_x_hook_client_unredirect(void *d EINA_UNUSED, E_Client *ec)
4942 {
4943 Ecore_X_Region parts;
4944
4945 E_COMP_X_PIXMAP_CHECK;
4946 eina_hash_del(damages_hash, &_e_comp_x_client_data_get(ec)->damage, ec);
4947 parts = ecore_x_region_new(NULL, 0);
4948 ecore_x_damage_subtract(_e_comp_x_client_data_get(ec)->damage, 0, parts);
4949 ecore_x_region_free(parts);
4950 ecore_x_damage_free(_e_comp_x_client_data_get(ec)->damage);
4951 _e_comp_x_client_data_get(ec)->damage = 0;
4952
4953 if (ec->unredirected_single && (!_e_comp_x_client_data_get(ec)->unredirected_single))
4954 {
4955 ecore_x_composite_unredirect_window(_e_comp_x_client_window_get(ec), ECORE_X_COMPOSITE_UPDATE_MANUAL);
4956 ecore_x_window_reparent(_e_comp_x_client_window_get(ec), e_comp->win, ec->client.x, ec->client.y);
4957 ecore_x_window_raise(_e_comp_x_client_window_get(ec));
4958 _e_comp_x_client_data_get(ec)->unredirected_single = 1;
4959 }
4960 if (!e_comp->nocomp) return; //wait for it...
4961 ecore_x_composite_unredirect_subwindows(e_comp->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
4962 ecore_x_window_hide(e_comp->win);
4963 }
4964
4965 static Eina_Bool
_e_comp_x_dead_win_timer(void * d)4966 _e_comp_x_dead_win_timer(void *d)
4967 {
4968 uint32_t pwin = (uintptr_t)(uintptr_t*)d;
4969
4970 eina_hash_del_by_key(dead_wins, &pwin);
4971 return EINA_FALSE;
4972 }
4973
4974 static void
_e_comp_x_hook_client_del(void * d EINA_UNUSED,E_Client * ec)4975 _e_comp_x_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
4976 {
4977 Ecore_X_Window win, pwin;
4978 unsigned int visible = 0;
4979 E_Comp_X_Client_Data *cd;
4980
4981 E_COMP_X_PIXMAP_CHECK;
4982 win = e_client_util_win_get(ec);
4983 pwin = e_client_util_pwin_get(ec);
4984 cd = _e_comp_x_client_data_get(ec);
4985
4986 if (mouse_client == ec) mouse_client = NULL;
4987 if (focus_job_client == ec) focus_job_client = NULL;
4988 if (unfocus_job_client == ec) unfocus_job_client = NULL;
4989 if ((!stopping) && cd && (!cd->deleted))
4990 ecore_x_window_prop_card32_set(win, E_ATOM_MANAGED, &visible, 1);
4991 if (stopping && ec->iconic)
4992 {
4993 e_hints_window_iconic_set(ec);
4994 e_hints_window_state_set(ec);
4995 }
4996 if ((!ec->already_unparented) && cd && cd->reparented)
4997 {
4998 _e_comp_x_focus_setdown(ec);
4999 e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
5000 e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, pwin);
5001 if (!cd->deleted)
5002 {
5003 if (stopping)
5004 {
5005 ecore_x_window_reparent(win, e_comp->root,
5006 ec->client.x, ec->client.y);
5007 ecore_x_window_configure(win,
5008 ECORE_X_WINDOW_CONFIGURE_MASK_SIBLING |
5009 ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
5010 0, 0, 0, 0, 0, pwin,
5011 ECORE_X_WINDOW_STACK_BELOW);
5012 }
5013
5014 else
5015 /* put the window back where we found it to prevent annoying dancing windows */
5016 ecore_x_window_reparent(win, e_comp->root,
5017 cd->initial_attributes.x,
5018 cd->initial_attributes.y);
5019 if (!ec->internal)
5020 ecore_x_window_save_set_del(win);
5021 }
5022 e_pixmap_alias(NULL, E_PIXMAP_TYPE_X, pwin);
5023 }
5024 ec->already_unparented = 1;
5025 if (cd)
5026 eina_hash_del_by_key(clients_win_hash, &win);
5027 if (cd && cd->damage)
5028 {
5029 eina_hash_del(damages_hash, &cd->damage, ec);
5030 ecore_x_damage_free(cd->damage);
5031 cd->damage = 0;
5032 }
5033 if (cd && cd->reparented)
5034 {
5035 eina_hash_del_by_key(clients_win_hash, &pwin);
5036 e_pixmap_parent_window_set(e_comp_x_client_pixmap_get(ec), 0);
5037 ecore_x_window_free(pwin);
5038 eina_hash_add(dead_wins, &pwin, (void*)1);
5039 ecore_timer_add(0.5, _e_comp_x_dead_win_timer, (uintptr_t*)(uintptr_t)pwin);
5040 }
5041
5042 if (ec->hacks.mapping_change)
5043 _e_comp_x_mapping_change_disabled--;
5044 if (ec->parent && (ec->parent->modal == ec))
5045 {
5046 E_Comp_X_Client_Data *pcd;
5047
5048 pcd = _e_comp_x_client_data_get(ec->parent);
5049 if (pcd->lock_win)
5050 {
5051 eina_hash_del_by_key(clients_win_hash, &pcd->lock_win);
5052 ecore_x_window_hide(pcd->lock_win);
5053 ecore_x_window_free(pcd->lock_win);
5054 pcd->lock_win = 0;
5055 }
5056 ec->parent->lock_close = 0;
5057 ec->parent->modal = NULL;
5058 }
5059 if (cd)
5060 E_FREE_FUNC(cd->first_draw_delay, ecore_timer_del);
5061 #ifdef HAVE_WAYLAND
5062 if (e_comp->comp_type == E_PIXMAP_TYPE_WL)
5063 {
5064 if (e_pixmap_is_x(ec->pixmap))
5065 e_comp_wl_client_xwayland_setup(ec, NULL, NULL);
5066 else
5067 {
5068 e_pixmap_alias(NULL, E_PIXMAP_TYPE_X, win);
5069 free(cd);
5070 e_pixmap_free(e_comp_x_client_pixmap_get(ec));
5071 }
5072 }
5073 else
5074 #endif
5075 {
5076 if (e_pixmap_free(ec->pixmap))
5077 e_pixmap_client_set(ec->pixmap, NULL);
5078 ec->pixmap = NULL;
5079 }
5080 if (ec->netwm.icons)
5081 {
5082 _e_comp_x_client_icon_free(ec->netwm.icons, ec->netwm.num_icons);
5083 ec->netwm.icons = NULL;
5084 ec->netwm.num_icons = 0;
5085 }
5086
5087 if (post_clients)
5088 post_clients = eina_list_remove(post_clients, ec);
5089
5090 _e_comp_x_focus_check();
5091 }
5092
5093 static void
_e_comp_x_hook_client_move_end(void * d EINA_UNUSED,E_Client * ec)5094 _e_comp_x_hook_client_move_end(void *d EINA_UNUSED, E_Client *ec)
5095 {
5096 E_COMP_X_PIXMAP_CHECK;
5097 _e_comp_x_client_data_get(ec)->moving = 0;
5098 if (!_e_comp_x_client_data_get(ec)->move_counter) return;
5099 _e_comp_x_client_data_get(ec)->move_counter = 0;
5100 ec->post_move = 1;
5101 _e_comp_x_post_client_idler_add(ec);
5102 }
5103
5104 static void
_e_comp_x_hook_client_move_begin(void * d EINA_UNUSED,E_Client * ec)5105 _e_comp_x_hook_client_move_begin(void *d EINA_UNUSED, E_Client *ec)
5106 {
5107 E_COMP_X_PIXMAP_CHECK;
5108 _e_comp_x_client_data_get(ec)->moving = 1;
5109 }
5110
5111 static void
_e_comp_x_hook_client_resize_end(void * d EINA_UNUSED,E_Client * ec)5112 _e_comp_x_hook_client_resize_end(void *d EINA_UNUSED, E_Client *ec)
5113 {
5114 E_COMP_X_PIXMAP_CHECK;
5115 if (_e_comp_x_client_data_get(ec)->alarm)
5116 {
5117 eina_hash_del_by_key(alarm_hash, &_e_comp_x_client_data_get(ec)->alarm);
5118 ecore_x_sync_alarm_free(_e_comp_x_client_data_get(ec)->alarm);
5119 _e_comp_x_client_data_get(ec)->alarm = 0;
5120 }
5121 ec->netwm.sync.alarm = 0;
5122 /* resize to last geometry if sync alarm for it was not yet handled */
5123 if (ec->pending_resize)
5124 {
5125 EC_CHANGED(ec);
5126 ec->changes.pos = 1;
5127 ec->changes.size = 1;
5128 }
5129
5130 E_FREE_LIST(ec->pending_resize, free);
5131 }
5132
5133 static void
_e_comp_x_hook_client_resize_begin(void * d EINA_UNUSED,E_Client * ec)5134 _e_comp_x_hook_client_resize_begin(void *d EINA_UNUSED, E_Client *ec)
5135 {
5136 E_COMP_X_PIXMAP_CHECK;
5137 if (!ec->netwm.sync.request) return;
5138 if (e_comp->comp_type == E_PIXMAP_TYPE_X)
5139 {
5140 _e_comp_x_client_data_get(ec)->alarm = ecore_x_sync_alarm_new(_e_comp_x_client_data_get(ec)->sync_counter);
5141 eina_hash_add(alarm_hash, &_e_comp_x_client_data_get(ec)->alarm, ec);
5142 }
5143 ec->netwm.sync.alarm = ec->netwm.sync.serial = 1;
5144 ec->netwm.sync.wait = 0;
5145 ec->netwm.sync.send_time = ecore_loop_time_get();
5146 }
5147
5148 static void
_e_comp_x_hook_client_desk_set(void * d EINA_UNUSED,E_Client * ec)5149 _e_comp_x_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec)
5150 {
5151 unsigned int num[2];
5152 int x, y;
5153
5154 E_COMP_X_PIXMAP_CHECK;
5155 e_desk_xy_get(ec->desk, &x, &y);
5156 num[0] = x, num[1] = y;
5157 ecore_x_window_prop_card32_set(e_client_util_win_get(ec), E_ATOM_DESK, num, 2);
5158 }
5159
5160 static Eina_Bool
_e_comp_x_cb_ping(void * data EINA_UNUSED,int ev_type EINA_UNUSED,Ecore_X_Event_Ping * ev)5161 _e_comp_x_cb_ping(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_X_Event_Ping *ev)
5162 {
5163 E_Client *ec;
5164
5165 ec = _e_comp_x_client_find_by_window(ev->event_win);
5166 if (ec) ec->ping_ok = 1;
5167 return ECORE_CALLBACK_PASS_ON;
5168 }
5169
5170 static void
_e_comp_pointer_grab(void)5171 _e_comp_pointer_grab(void)
5172 {
5173 if (_e_comp_x_suspend_grabbed) ecore_x_window_free(_e_comp_x_suspend_grabbed);
5174 _e_comp_x_suspend_grabbed = ecore_x_window_input_new(e_comp->root, 0, 0, 1, 1);
5175 ecore_x_window_show(_e_comp_x_suspend_grabbed);
5176 if (!e_grabinput_get(_e_comp_x_suspend_grabbed, 0, 0))
5177 {
5178 ecore_x_window_free(_e_comp_x_suspend_grabbed);
5179 _e_comp_x_suspend_grabbed = 0;
5180 }
5181 }
5182
5183 static void
_e_comp_pointer_ungrab(void)5184 _e_comp_pointer_ungrab(void)
5185 {
5186 if (!_e_comp_x_suspend_grabbed) return;
5187 e_grabinput_release(_e_comp_x_suspend_grabbed, 0);
5188 ecore_x_window_free(_e_comp_x_suspend_grabbed);
5189 _e_comp_x_suspend_grabbed = 0;
5190 }
5191
5192 static void
_e_comp_cb_pointer_suspend_resume_done(void * data,Evas_Object * obj,const char * emission,const char * source)5193 _e_comp_cb_pointer_suspend_resume_done(void *data, Evas_Object *obj, const char *emission, const char *source)
5194 {
5195 edje_object_signal_callback_del(obj, emission, source,
5196 _e_comp_cb_pointer_suspend_resume_done);
5197 if (!data)
5198 {
5199 _e_comp_pointer_ungrab();
5200 e_pointer_grab_set(e_comp->pointer, EINA_FALSE);
5201 }
5202 }
5203
5204 EINTERN Eina_Bool
_e_comp_x_screensaver_on()5205 _e_comp_x_screensaver_on()
5206 {
5207 const char *s;
5208
5209 if ((!e_comp->pointer) || (!e_comp->pointer->o_ptr)) return ECORE_CALLBACK_RENEW;
5210 s = edje_object_data_get(e_comp->pointer->o_ptr, "can_suspend");
5211
5212 if ((s) && (atoi(s) == 1))
5213 {
5214 if (!e_desklock_state_get())
5215 {
5216 _e_comp_pointer_ungrab();
5217 e_pointer_grab_set(e_comp->pointer, EINA_FALSE);
5218 e_pointer_grab_set(e_comp->pointer, EINA_TRUE);
5219 _e_comp_pointer_grab();
5220 if (!_e_comp_x_suspend_grabbed) return ECORE_CALLBACK_RENEW;
5221 }
5222 edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5223 "e,state,mouse,suspend,done", "e",
5224 _e_comp_cb_pointer_suspend_resume_done);
5225 edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5226 "e,state,mouse,resume,done", "e",
5227 _e_comp_cb_pointer_suspend_resume_done);
5228 edje_object_signal_callback_add(e_comp->pointer->o_ptr,
5229 "e,state,mouse,suspend,done",
5230 "e",
5231 _e_comp_cb_pointer_suspend_resume_done,
5232 e_comp);
5233 edje_object_signal_emit(e_comp->pointer->o_ptr,
5234 "e,state,mouse,suspend", "e");
5235 }
5236 return ECORE_CALLBACK_RENEW;
5237 }
5238
5239 EINTERN Eina_Bool
_e_comp_x_screensaver_off()5240 _e_comp_x_screensaver_off()
5241 {
5242 const char *s;
5243
5244 _e_comp_pointer_ungrab();
5245 e_pointer_grab_set(e_comp->pointer, EINA_FALSE);
5246 if ((!e_comp->pointer) || (!e_comp->pointer->o_ptr)) return ECORE_CALLBACK_RENEW;
5247 s = edje_object_data_get(e_comp->pointer->o_ptr, "can_suspend");
5248
5249 if ((s) && (atoi(s) == 1))
5250 {
5251 if (!e_desklock_state_get())
5252 {
5253 e_pointer_grab_set(e_comp->pointer, EINA_TRUE);
5254 _e_comp_pointer_grab();
5255 if (!_e_comp_x_suspend_grabbed) return ECORE_CALLBACK_RENEW;
5256 }
5257 edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5258 "e,state,mouse,suspend,done", "e",
5259 _e_comp_cb_pointer_suspend_resume_done);
5260 edje_object_signal_callback_del(e_comp->pointer->o_ptr,
5261 "e,state,mouse,resume,done", "e",
5262 _e_comp_cb_pointer_suspend_resume_done);
5263 edje_object_signal_callback_add(e_comp->pointer->o_ptr,
5264 "e,state,mouse,resume,done",
5265 "e",
5266 _e_comp_cb_pointer_suspend_resume_done,
5267 NULL);
5268 edje_object_signal_emit(e_comp->pointer->o_ptr,
5269 "e,state,mouse,resume", "e");
5270 }
5271 return ECORE_CALLBACK_RENEW;
5272 }
5273
5274 static Ecore_Timer *screensaver_eval_timer = NULL;
5275 static Ecore_Animator *screensaver_eval_animator = NULL;
5276 static Eina_Bool saver_on = EINA_FALSE;
5277
5278 static Eina_Bool
_e_comp_x_screensaver_eval_cb(void * d EINA_UNUSED)5279 _e_comp_x_screensaver_eval_cb(void *d EINA_UNUSED)
5280 {
5281 E_FREE_FUNC(screensaver_eval_animator, ecore_animator_del);
5282 screensaver_eval_timer = NULL;
5283 e_screensaver_eval(saver_on);
5284 return EINA_FALSE;
5285 }
5286
5287 static Eina_Bool
_e_comp_x_screensaver_pre_eval_cb(void * d EINA_UNUSED)5288 _e_comp_x_screensaver_pre_eval_cb(void *d EINA_UNUSED)
5289 {
5290 E_FREE_FUNC(screensaver_eval_timer, ecore_timer_del);
5291 screensaver_eval_animator = NULL;
5292 screensaver_eval_timer = ecore_timer_loop_add(0.3, _e_comp_x_screensaver_eval_cb, NULL);
5293 e_screensaver_eval(saver_on);
5294 return EINA_FALSE;
5295 }
5296
5297 static Eina_Bool
_e_comp_x_screensaver_notify_cb(void * data EINA_UNUSED,int type EINA_UNUSED,Ecore_X_Event_Screensaver_Notify * ev)5298 _e_comp_x_screensaver_notify_cb(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Screensaver_Notify *ev)
5299 {
5300 if (e_screensaver_ignore_get()) return ECORE_CALLBACK_PASS_ON;
5301 if ((ev->on) && (!saver_on))
5302 {
5303 saver_on = EINA_TRUE;
5304 E_FREE_FUNC(screensaver_eval_timer, ecore_timer_del);
5305 E_FREE_FUNC(screensaver_eval_animator, ecore_animator_del);
5306 screensaver_eval_timer = ecore_timer_loop_add(0.3, _e_comp_x_screensaver_eval_cb, NULL);
5307 }
5308 else if ((!ev->on) && (saver_on))
5309 {
5310 saver_on = EINA_FALSE;
5311 E_FREE_FUNC(screensaver_eval_timer, ecore_timer_del);
5312 E_FREE_FUNC(screensaver_eval_animator, ecore_animator_del);
5313 screensaver_eval_animator = ecore_animator_add(_e_comp_x_screensaver_pre_eval_cb, NULL);
5314 }
5315 return ECORE_CALLBACK_PASS_ON;
5316 }
5317
5318 static Eina_Bool
_e_comp_x_backlight_notify_cb(void * data EINA_UNUSED,int t EINA_UNUSED,Ecore_X_Event_Randr_Output_Property_Notify * ev)5319 _e_comp_x_backlight_notify_cb(void *data EINA_UNUSED, int t EINA_UNUSED, Ecore_X_Event_Randr_Output_Property_Notify *ev)
5320 {
5321 if (ev->property != backlight_atom) return ECORE_CALLBACK_RENEW;
5322 e_backlight_update();
5323 return ECORE_CALLBACK_RENEW;
5324 }
5325
5326 static Eina_Bool
_e_comp_x_cb_frame_extents_request(void * data EINA_UNUSED,int ev_type EINA_UNUSED,Ecore_X_Event_Frame_Extents_Request * ev)5327 _e_comp_x_cb_frame_extents_request(void *data EINA_UNUSED, int ev_type EINA_UNUSED, Ecore_X_Event_Frame_Extents_Request *ev)
5328 {
5329 Ecore_X_Window_Type type;
5330 Ecore_X_MWM_Hint_Decor decor;
5331 Ecore_X_Window_State *state;
5332 Ecore_X_Window win;
5333 Frame_Extents *extents;
5334 const char *border, *sig, *key;
5335 int ok;
5336 unsigned int i, num;
5337
5338 win = ecore_x_window_parent_get(ev->win);
5339 if (win != e_comp->root) return ECORE_CALLBACK_PASS_ON;
5340
5341 /* TODO:
5342 * * We need to check if we remember this window, and border locking is set
5343 */
5344 border = "default";
5345 key = border;
5346 ok = ecore_x_mwm_hints_get(ev->win, NULL, &decor, NULL);
5347 if ((ok) &&
5348 (!(decor & ECORE_X_MWM_HINT_DECOR_ALL)) &&
5349 (!(decor & ECORE_X_MWM_HINT_DECOR_TITLE)) &&
5350 (!(decor & ECORE_X_MWM_HINT_DECOR_BORDER)))
5351 {
5352 border = "borderless";
5353 key = border;
5354 }
5355
5356 ok = ecore_x_netwm_window_type_get(ev->win, &type);
5357 if ((ok) &&
5358 ((type == ECORE_X_WINDOW_TYPE_DESKTOP) ||
5359 (type == ECORE_X_WINDOW_TYPE_DOCK)))
5360 {
5361 border = "borderless";
5362 key = border;
5363 }
5364
5365 sig = NULL;
5366 ecore_x_netwm_window_state_get(ev->win, &state, &num);
5367 if (state)
5368 {
5369 int maximized = 0;
5370
5371 for (i = 0; i < num; i++)
5372 {
5373 switch (state[i])
5374 {
5375 case ECORE_X_WINDOW_STATE_MAXIMIZED_VERT:
5376 maximized++;
5377 break;
5378
5379 case ECORE_X_WINDOW_STATE_MAXIMIZED_HORZ:
5380 maximized++;
5381 break;
5382
5383 case ECORE_X_WINDOW_STATE_FULLSCREEN:
5384 border = "borderless";
5385 key = border;
5386 break;
5387
5388 case ECORE_X_WINDOW_STATE_SHADED:
5389 case ECORE_X_WINDOW_STATE_SKIP_TASKBAR:
5390 case ECORE_X_WINDOW_STATE_SKIP_PAGER:
5391 case ECORE_X_WINDOW_STATE_HIDDEN:
5392 case ECORE_X_WINDOW_STATE_ICONIFIED:
5393 case ECORE_X_WINDOW_STATE_MODAL:
5394 case ECORE_X_WINDOW_STATE_STICKY:
5395 case ECORE_X_WINDOW_STATE_ABOVE:
5396 case ECORE_X_WINDOW_STATE_BELOW:
5397 case ECORE_X_WINDOW_STATE_DEMANDS_ATTENTION:
5398 case ECORE_X_WINDOW_STATE_UNKNOWN:
5399 break;
5400 }
5401 }
5402 if ((maximized == 2) &&
5403 (e_config->maximize_policy == E_MAXIMIZE_FULLSCREEN))
5404 {
5405 sig = "ev,action,maximize,fullscreen";
5406 key = "maximize,fullscreen";
5407 }
5408 free(state);
5409 }
5410
5411 extents = eina_hash_find(frame_extents, key);
5412 if (!extents)
5413 {
5414 Evas_Object *o;
5415 char buf[1024];
5416
5417 extents = E_NEW(Frame_Extents, 1);
5418 if (!extents) return ECORE_CALLBACK_RENEW;
5419
5420 o = edje_object_add(e_comp->evas);
5421 snprintf(buf, sizeof(buf), "ev/widgets/border/%s/border", border);
5422 ok = e_theme_edje_object_set(o, "base/theme/borders", buf);
5423 if (ok)
5424 {
5425 Evas_Coord x, y, w, h;
5426
5427 if (sig)
5428 {
5429 edje_object_signal_emit(o, sig, "ev");
5430 edje_object_message_signal_process(o);
5431 }
5432
5433 evas_object_resize(o, 1000, 1000);
5434 edje_object_calc_force(o);
5435 edje_object_part_geometry_get(o, "ev.swallow.client",
5436 &x, &y, &w, &h);
5437 extents->l = x;
5438 extents->r = 1000 - (x + w);
5439 extents->t = y;
5440 extents->b = 1000 - (y + h);
5441 }
5442 else
5443 {
5444 extents->l = 0;
5445 extents->r = 0;
5446 extents->t = 0;
5447 extents->b = 0;
5448 }
5449 evas_object_del(o);
5450 eina_hash_add(frame_extents, key, extents);
5451 }
5452
5453 if (extents)
5454 ecore_x_netwm_frame_size_set(ev->win, extents->l, extents->r, extents->t, extents->b);
5455
5456 return ECORE_CALLBACK_RENEW;
5457 }
5458
5459 static Eina_Bool
_e_comp_x_randr_change(void * data EINA_UNUSED,int ev_type EINA_UNUSED,void * event_info EINA_UNUSED)5460 _e_comp_x_randr_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *event_info EINA_UNUSED)
5461 {
5462 E_Client *ec;
5463
5464 ecore_x_netwm_desk_size_set(e_comp->root, e_comp->w, e_comp->h);
5465 E_CLIENT_FOREACH(ec)
5466 {
5467 if (!e_client_util_ignored_get(ec))
5468 _e_comp_x_client_zone_geometry_set(ec);
5469 }
5470 return ECORE_CALLBACK_RENEW;
5471 }
5472
5473 static void
_e_comp_x_del(E_Comp * c)5474 _e_comp_x_del(E_Comp *c)
5475 {
5476 unsigned int i;
5477
5478 if (!e_comp_wl)
5479 ecore_x_window_key_ungrab(c->root, "F", ECORE_EVENT_MODIFIER_SHIFT |
5480 ECORE_EVENT_MODIFIER_CTRL |
5481 ECORE_EVENT_MODIFIER_ALT, 0);
5482 if (ecore_x_display_get())
5483 {
5484 if (c->grabbed)
5485 {
5486 c->grabbed = 0;
5487 ecore_x_ungrab();
5488 ecore_x_sync();
5489 }
5490
5491 if (restart)
5492 {
5493 Ecore_X_Atom a;
5494 Ecore_X_Window blackwin;
5495
5496 a = ecore_x_atom_get("E_COMP_BLACK_WIN");
5497 blackwin = ecore_x_window_permanent_new(c->root, a);
5498 ecore_x_window_ignore_set(blackwin, 1);
5499 ecore_x_window_override_set(blackwin, EINA_TRUE);
5500 ecore_x_window_move_resize(blackwin, 0, 0, e_comp->w, e_comp->h);
5501 ecore_x_window_background_color_set(blackwin, 0, 0, 0);
5502 ecore_x_window_show(blackwin);
5503 ecore_x_window_prop_window_set(c->root, a, &blackwin, 1);
5504 ecore_x_sync();
5505 }
5506
5507 for (i = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); i <= e_comp_canvas_layer_map(E_LAYER_CLIENT_PRIO); i++)
5508 ecore_x_window_free(c->layers[i].win);
5509
5510 ecore_x_composite_unredirect_subwindows
5511 (c->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
5512 if (c->block_win) ecore_x_window_free(c->block_win);
5513 ecore_x_composite_render_window_disable(c->win);
5514 e_alert_composite_win(c->root, 0);
5515
5516 ecore_x_window_free(c->cm_selection);
5517 ecore_x_screen_is_composited_set(0, 0);
5518 }
5519
5520 eina_list_free(c->x_comp_data->retry_clients);
5521 ecore_timer_del(c->x_comp_data->retry_timer);
5522 E_FREE_FUNC(mouse_in_job, ecore_job_del);
5523 E_FREE_FUNC(focus_job, ecore_job_del);
5524 E_FREE_FUNC(unfocus_job, ecore_job_del);
5525 free(c->x_comp_data);
5526 c->x_comp_data = e_comp_x = NULL;
5527 c->root = 0;
5528 }
5529
5530 static void
_e_comp_x_manage_windows(void)5531 _e_comp_x_manage_windows(void)
5532 {
5533 Ecore_X_Window *windows;
5534 int wnum;
5535 int i;
5536 const char *atom_names[] =
5537 {
5538 "_XEMBED_INFO",
5539 "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR",
5540 "KWM_DOCKWINDOW"
5541 };
5542 Ecore_X_Atom atoms[3];
5543 Ecore_X_Atom atom_xmbed, atom_kde_netwm_systray, atom_kwm_dockwindow;
5544 int count;
5545
5546 /* a manager is designated for each root. lets get all the windows in
5547 the managers root */
5548 windows = ecore_x_window_children_get(e_comp->root, &wnum);
5549 if (!windows) return;
5550
5551 ecore_x_atoms_get(atom_names, 3, atoms);
5552 atom_xmbed = atoms[0];
5553 atom_kde_netwm_systray = atoms[1];
5554 atom_kwm_dockwindow = atoms[2];
5555 for (i = 0; i < wnum; i++)
5556 {
5557 unsigned int ret_val;
5558 unsigned char *data = NULL;
5559 int ret;
5560 E_Client *ec = NULL;
5561
5562 if ((e_comp->win == windows[i]) || (e_comp->ee_win == windows[i]) ||
5563 (e_comp->root == windows[i]) || (e_comp->cm_selection == windows[i]))
5564 continue;
5565 if (_e_comp_x_client_find_by_window(windows[i]))
5566 continue;
5567 if (!ecore_x_window_prop_property_get(windows[i],
5568 atom_kde_netwm_systray,
5569 atom_xmbed, 32,
5570 &data, &count))
5571 data = NULL;
5572
5573 if (!data)
5574 {
5575 if (!ecore_x_window_prop_property_get(windows[i],
5576 atom_kwm_dockwindow,
5577 atom_kwm_dockwindow, 32,
5578 &data, &count))
5579 data = NULL;
5580 }
5581 if (data)
5582 {
5583 E_FREE(data);
5584 continue;
5585 }
5586 ret = ecore_x_window_prop_card32_get(windows[i],
5587 E_ATOM_MANAGED,
5588 &ret_val, 1);
5589
5590 ec = _e_comp_x_client_new(windows[i], (ret > -1) && (ret_val == 1));
5591 if (ec && (!_e_comp_x_client_data_get(ec)->initial_attributes.visible))
5592 {
5593 DELD(ec, 3);
5594 E_FREE_FUNC(ec, e_object_del);
5595 }
5596 if (ec)
5597 {
5598 if (ec->override || (!ec->icccm.fetch.hints))
5599 {
5600 _e_comp_x_client_evas_init(ec);
5601 if (!ec->input_only)
5602 _e_comp_x_client_damage_add(ec);
5603 e_pixmap_usable_set(ec->pixmap, 1);
5604 _e_comp_x_client_data_get(ec)->first_map = 1;
5605 evas_object_geometry_set(ec->frame, ec->client.x, ec->client.y, ec->client.w, ec->client.h);
5606 }
5607 ec->ignore_first_unmap = 1;
5608 if (ec->override || (!ec->icccm.fetch.hints))
5609 evas_object_show(ec->frame);
5610 _e_comp_x_client_stack(ec);
5611 }
5612 }
5613 free(windows);
5614 }
5615
5616 static void
_e_comp_x_bindings_grab_cb(void)5617 _e_comp_x_bindings_grab_cb(void)
5618 {
5619 Eina_List *l;
5620 E_Client *ec;
5621
5622 EINA_LIST_FOREACH(e_comp->clients, l, ec)
5623 {
5624 if (e_client_util_ignored_get(ec)) continue;
5625 _e_comp_x_focus_init(ec);
5626 if (ec->focused)
5627 _e_comp_x_focus_setdown(ec);
5628 else
5629 {
5630 _e_comp_x_focus_setup(ec);
5631 e_bindings_mouse_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5632 e_bindings_wheel_grab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5633 }
5634 }
5635 }
5636
5637 static void
_e_comp_x_bindings_ungrab_cb(void)5638 _e_comp_x_bindings_ungrab_cb(void)
5639 {
5640 Eina_List *l;
5641 E_Client *ec;
5642
5643 EINA_LIST_FOREACH(e_comp->clients, l, ec)
5644 {
5645 Ecore_X_Window win;
5646
5647 if (e_client_util_ignored_get(ec)) continue;
5648 win = e_client_util_win_get(ec);
5649 ecore_x_window_button_ungrab(win, 1, 0, 1);
5650 ecore_x_window_button_ungrab(win, 2, 0, 1);
5651 ecore_x_window_button_ungrab(win, 3, 0, 1);
5652 e_bindings_mouse_ungrab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5653 e_bindings_wheel_ungrab(E_BINDING_CONTEXT_WINDOW, e_client_util_pwin_get(ec));
5654 _e_comp_x_client_data_get(ec)->button_grabbed = 0;
5655 }
5656 }
5657
5658 static void
_e_comp_x_desklock_hide(void)5659 _e_comp_x_desklock_hide(void)
5660 {
5661 e_comp_ungrab_input(1, 1);
5662
5663 if (e_comp_x->lock_grab_break_wnd)
5664 ecore_x_window_show(e_comp_x->lock_grab_break_wnd);
5665 e_comp_x->lock_grab_break_wnd = 0;
5666 e_comp_override_del();
5667 }
5668
5669 static Eina_Bool
_e_comp_x_desklock_show(void)5670 _e_comp_x_desklock_show(void)
5671 {
5672 if (!e_comp_grab_input(1, 1))
5673 {
5674 Ecore_X_Window *windows;
5675 int wnum, i;
5676
5677 windows = ecore_x_window_children_get(e_comp->root, &wnum);
5678 if (!windows) goto fail;
5679 for (i = 0; i < wnum; i++)
5680 {
5681 Ecore_X_Window_Attributes att;
5682
5683 memset(&att, 0, sizeof(Ecore_X_Window_Attributes));
5684 ecore_x_window_attributes_get(windows[i], &att);
5685 if (att.visible)
5686 {
5687 ecore_x_window_hide(windows[i]);
5688 if (e_comp_grab_input(1, 1))
5689 {
5690 e_comp_x->lock_grab_break_wnd = windows[i];
5691 free(windows);
5692 goto works;
5693 }
5694 ecore_x_window_show(windows[i]);
5695 }
5696 }
5697 free(windows);
5698 }
5699 works:
5700 e_comp_override_add();
5701
5702 return EINA_TRUE;
5703 fail:
5704 /* everything failed - can't lock */
5705 e_util_dialog_show(_("Lock Failed"),
5706 _("Locking the desktop failed because some application<ps/>"
5707 "has grabbed either the keyboard or the mouse or both<ps/>"
5708 "and their grab is unable to be broken."));
5709 return EINA_FALSE;
5710 }
5711
5712 static Eina_Bool
_e_comp_x_setup(Ecore_X_Window root,int w,int h)5713 _e_comp_x_setup(Ecore_X_Window root, int w, int h)
5714 {
5715 Ecore_X_Window_Attributes att;
5716 Ecore_X_Atom a;
5717 Ecore_X_Window blackwin = 0;
5718 Eina_Bool res;
5719 unsigned int i;
5720
5721 res = ecore_x_screen_is_composited(0);
5722 if (res)
5723 {
5724 ERR(_("Another compositor is already running on your display server."));
5725 return EINA_FALSE;
5726 }
5727 if (!ecore_x_window_manage(root)) return EINA_FALSE;
5728
5729 a = ecore_x_atom_get("E_COMP_BLACK_WIN");
5730 if (ecore_x_window_prop_window_get(root, a, &blackwin, 1) == 1)
5731 {
5732 ecore_x_window_ignore_set(blackwin, 1);
5733 }
5734
5735 e_comp_x = e_comp->x_comp_data = E_NEW(E_Comp_X_Data, 1);
5736 ecore_x_e_window_profile_supported_set(root, EINA_TRUE);
5737 e_comp->cm_selection = ecore_x_window_input_new(root, 0, 0, 1, 1);
5738 if (!e_comp->cm_selection) return EINA_FALSE;
5739 ecore_x_icccm_name_class_set(e_comp->cm_selection, "comp", "cm_selection");
5740 e_comp_ignore_win_add(E_PIXMAP_TYPE_X, e_comp->cm_selection);
5741 e_hints_init(root, e_comp->cm_selection);
5742 ecore_x_window_background_color_set(root, 0, 0, 0);
5743 ecore_x_screen_is_composited_set(0, e_comp->cm_selection);
5744 ecore_x_selection_owner_set(e_comp->cm_selection, ecore_x_atom_get("WM_S0"), ecore_x_current_time_get());
5745
5746 e_comp->win = ecore_x_composite_render_window_enable(root);
5747 if (!e_comp->win)
5748 {
5749 ERR(_("Your display server does not support the compositor overlay window.\n"
5750 "This is needed for Enlightenment to function."));
5751 return EINA_FALSE;
5752 }
5753 e_comp->root = root;
5754
5755 memset((&att), 0, sizeof(Ecore_X_Window_Attributes));
5756 ecore_x_window_attributes_get(e_comp->win, &att);
5757
5758 if ((att.depth != 24) && (att.depth != 32))
5759 {
5760 /*
5761 e_util_dialog_internal
5762 (_("Compositor Error"), _("Your screen is not in 24/32bit display mode.<ps/>"
5763 "This is required to be your default depth<ps/>"
5764 "setting for the compositor to work properly."));
5765 ecore_x_composite_render_window_disable(e_comp->win);
5766 free(e_comp);
5767 return NULL;
5768 */
5769 }
5770 e_alert_composite_win(root, e_comp->win);
5771
5772 if (!e_comp->ee)
5773 {
5774 if (!e_comp_x_randr_canvas_new(e_comp->win, w, h))
5775 ecore_job_add(_e_comp_x_add_fail_job, NULL);
5776 }
5777
5778 ecore_x_composite_redirect_subwindows(root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
5779
5780 ecore_evas_data_set(e_comp->ee, "comp", e_comp);
5781 e_comp->bindings_grab_cb = _e_comp_x_bindings_grab_cb;
5782 e_comp->bindings_ungrab_cb = _e_comp_x_bindings_ungrab_cb;
5783
5784 if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5785 {
5786 if (!e_comp_canvas_init(w, h)) return EINA_FALSE;
5787 ecore_x_window_key_grab(root, "F", ECORE_EVENT_MODIFIER_SHIFT |
5788 ECORE_EVENT_MODIFIER_CTRL |
5789 ECORE_EVENT_MODIFIER_ALT, 0);
5790 }
5791
5792 if (e_comp->comp_type == E_PIXMAP_TYPE_X)
5793 e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
5794 else
5795 e_grabinput_focus(e_comp->root, E_FOCUS_METHOD_PASSIVE);
5796
5797 /* init layers */
5798 for (i = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); i <= e_comp_canvas_layer_map(E_LAYER_CLIENT_PRIO); i++)
5799 {
5800 char buf[64];
5801 E_Client *ec;
5802
5803 e_comp->layers[i].win = ecore_x_window_input_new(root, 0, 0, 1, 1);
5804 ecore_x_window_show(e_comp->layers[i].win);
5805 snprintf(buf, sizeof(buf), "%d", e_comp_canvas_layer_map_to(i));
5806 ecore_x_icccm_name_class_set(e_comp->layers[i].win, buf, "e_layer_win");
5807
5808 if (i >= e_comp_canvas_layer_map(E_LAYER_CLIENT_ABOVE))
5809 ecore_x_window_raise(e_comp->layers[i].win);
5810 ec = _e_comp_x_client_new(e_comp->layers[i].win, 0);
5811 if (!ec) continue;
5812 evas_object_name_set(ec->frame, "layer_obj");
5813 ec->lock_client_stacking = 1;
5814 ec->internal = 1;
5815 ec->visible = 1;
5816 evas_object_del(e_comp->layers[i].obj);
5817 e_comp->layers[i].obj = ec->frame;
5818 evas_object_layer_set(ec->frame, e_comp_canvas_layer_map_to(i));
5819 evas_object_pass_events_set(ec->frame, 1);
5820 evas_object_show(ec->frame);
5821 }
5822 for (i = e_comp_canvas_layer_map(E_LAYER_CLIENT_NORMAL); i >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); i--)
5823 ecore_x_window_lower(e_comp->layers[i].win);
5824
5825 ecore_evas_lower(e_comp->ee);
5826 if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5827 {
5828 e_comp->pointer = e_pointer_window_new(e_comp->root, 0);
5829 e_comp->pointer->color = ecore_x_cursor_color_supported_get();
5830 e_pointer_type_push(e_comp->pointer, e_comp->pointer, "default");
5831 ecore_x_icccm_state_set(ecore_evas_window_get(e_comp->ee), ECORE_X_WINDOW_STATE_HINT_NORMAL);
5832 e_startup();
5833 }
5834 else
5835 e_pointer_window_add(e_comp->pointer, e_comp->root);
5836 _e_comp_x_manage_windows();
5837
5838 if (blackwin)
5839 {
5840 ecore_x_window_free(blackwin);
5841 ecore_x_window_prop_property_del(root, a);
5842 ecore_x_window_ignore_set(blackwin, 0);
5843 }
5844
5845 return !!e_comp->canvas->resize_object;
5846 }
5847
5848 static Eina_Bool
_e_comp_x_screens_setup(void)5849 _e_comp_x_screens_setup(void)
5850 {
5851 Ecore_X_Window root;
5852 int rw, rh;
5853 Eina_Bool ret;
5854
5855 if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5856 {
5857 e_comp_x_randr_screen_iface_set();
5858 if (!e_randr2_init()) return 0;
5859 }
5860 root = ecore_x_window_root_first_get();
5861 if (!root)
5862 {
5863 e_error_message_show("X reports there are no root windows!\n");
5864 return 0;
5865 }
5866 ecore_x_window_size_get(root, &rw, &rh);
5867 if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
5868 e_randr2_screens_setup(rw, rh);
5869 ret = _e_comp_x_setup(root, rw, rh);
5870 if (ret) return EINA_TRUE;
5871 e_randr2_shutdown();
5872 e_xinerama_screens_set(NULL);
5873 e_comp->screen = NULL;
5874 return EINA_FALSE;
5875 }
5876
5877 E_API Eina_Bool
e_comp_x_init(void)5878 e_comp_x_init(void)
5879 {
5880 Eina_List *h = NULL;
5881 if (!ecore_x_init(NULL))
5882 {
5883 fprintf(stderr, _("Enlightenment cannot initialize X Connection...\n"));
5884 return EINA_FALSE;
5885 }
5886
5887 if (e_comp->comp_type == E_PIXMAP_TYPE_X)
5888 ecore_x_io_error_handler_set(_e_main_cb_x_fatal, NULL);
5889
5890 if (!ecore_x_composite_query())
5891 {
5892 _e_comp_x_print_win(0);
5893 ecore_x_shutdown();
5894 e_error_message_show
5895 (_("Your display server does not support XComposite, "
5896 "or Ecore-X was built without XComposite support. "
5897 "Note that for composite support you will also need "
5898 "XRender and XFixes support in X11 and Ecore."));
5899 return EINA_FALSE;
5900 }
5901 if (!ecore_x_damage_query())
5902 {
5903 e_error_message_show
5904 (_("Your display server does not support XDamage "
5905 "or Ecore was built without XDamage support."));
5906 return EINA_FALSE;
5907 }
5908 if (!e_atoms_init()) return 0;
5909
5910 clients_win_hash = eina_hash_int32_new(NULL);
5911 damages_hash = eina_hash_int32_new(NULL);
5912 alarm_hash = eina_hash_int32_new(NULL);
5913 dead_wins = eina_hash_int32_new(NULL);
5914 pending_configures = eina_hash_int32_new(NULL);
5915 frame_extents = eina_hash_string_superfast_new(free);
5916
5917 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_DESK_SET, _e_comp_x_hook_client_desk_set, NULL));
5918 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_RESIZE_BEGIN, _e_comp_x_hook_client_resize_begin, NULL));
5919 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_RESIZE_END, _e_comp_x_hook_client_resize_end, NULL));
5920 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_MOVE_BEGIN, _e_comp_x_hook_client_move_begin, NULL));
5921 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_MOVE_END, _e_comp_x_hook_client_move_end, NULL));
5922 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_DEL, _e_comp_x_hook_client_del, NULL));
5923 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT, _e_comp_x_hook_client_new, NULL));
5924 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_FETCH, _e_comp_x_hook_client_fetch, NULL));
5925 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_PRE_FRAME_ASSIGN, _e_comp_x_hook_client_pre_frame_assign, NULL));
5926 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_UNREDIRECT, _e_comp_x_hook_client_unredirect, NULL));
5927 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_REDIRECT, _e_comp_x_hook_client_redirect, NULL));
5928 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT, _e_comp_x_hook_client_post_new_client, NULL));
5929 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_FOCUS_SET, _e_comp_x_hook_client_focus_set, NULL));
5930 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_FOCUS_UNSET, _e_comp_x_hook_client_focus_unset, NULL));
5931 h = eina_list_append(h, e_client_hook_add(E_CLIENT_HOOK_EVAL_END, _e_comp_x_hook_client_eval_end, NULL));
5932
5933 if (!_e_comp_x_screens_setup())
5934 {
5935 e_atoms_shutdown();
5936 E_FREE_LIST(h, e_client_hook_del);
5937 E_FREE_FUNC(clients_win_hash, eina_hash_free);
5938 E_FREE_FUNC(damages_hash, eina_hash_free);
5939 E_FREE_FUNC(alarm_hash, eina_hash_free);
5940 E_FREE_FUNC(frame_extents, eina_hash_free);
5941 return 0;
5942 }
5943
5944 E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD, _e_comp_x_object_add, NULL);
5945
5946 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_DESTROY, _e_comp_x_destroy, NULL);
5947 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHOW, _e_comp_x_show, NULL);
5948 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHOW_REQUEST, _e_comp_x_show_request, NULL);
5949 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_RESIZE_REQUEST, _e_comp_x_resize_request, NULL);
5950 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_HIDE, _e_comp_x_hide, NULL);
5951 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_REPARENT, _e_comp_x_reparent, NULL);
5952 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_CONFIGURE, _e_comp_x_configure, NULL);
5953 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_CONFIGURE_REQUEST, _e_comp_x_configure_request, NULL);
5954 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STATE_REQUEST, _e_comp_x_state_request, NULL);
5955 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STACK, _e_comp_x_stack, NULL);
5956 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_STACK_REQUEST, _e_comp_x_stack_request, NULL);
5957 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_CLIENT_MESSAGE, _e_comp_x_message, NULL);
5958 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_PROPERTY, _e_comp_x_property, NULL);
5959 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_SHAPE, _e_comp_x_shape, NULL);
5960 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_DAMAGE_NOTIFY, _e_comp_x_damage, NULL);
5961 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_DAMAGE, _e_comp_x_damage_win, NULL);
5962
5963 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MAPPING_CHANGE, _e_comp_x_mapping_change, NULL);
5964
5965 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_FOCUS_IN, _e_comp_x_focus_in, NULL);
5966 if (e_comp->comp_type != E_PIXMAP_TYPE_WL)
5967 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_FOCUS_OUT, _e_comp_x_focus_out, NULL);
5968
5969 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_WINDOW_MOVE_RESIZE_REQUEST,
5970 _e_comp_x_move_resize_request, NULL);
5971 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_DESKTOP_CHANGE,
5972 _e_comp_x_desktop_change, NULL);
5973 if (e_comp->comp_type != E_PIXMAP_TYPE_WL)
5974 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_SYNC_ALARM,
5975 _e_comp_x_sync_alarm, NULL);
5976
5977 E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_DOWN,
5978 _e_comp_x_mouse_down, NULL);
5979 E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_UP,
5980 _e_comp_x_mouse_up, NULL);
5981 E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_WHEEL,
5982 _e_comp_x_mouse_wheel, NULL);
5983 E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE,
5984 _e_comp_x_mouse_move, NULL);
5985 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MOUSE_IN,
5986 _e_comp_x_mouse_in, NULL);
5987 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_MOUSE_OUT,
5988 _e_comp_x_mouse_out, NULL);
5989
5990 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ZONE_SET,
5991 _e_comp_x_client_zone_set, NULL);
5992 E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY,
5993 _e_comp_x_client_property, NULL);
5994
5995 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_FRAME_EXTENTS_REQUEST,
5996 _e_comp_x_cb_frame_extents_request, NULL);
5997 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_PING,
5998 _e_comp_x_cb_ping, NULL);
5999 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_RANDR_OUTPUT_PROPERTY_NOTIFY, _e_comp_x_backlight_notify_cb, NULL);
6000 if (ecore_x_randr_version_get() >= RANDR_VERSION_1_3)
6001 backlight_atom = ecore_x_atom_get("Backlight");
6002
6003 if (!backlight_atom)
6004 backlight_atom = ecore_x_atom_get("BACKLIGHT");
6005
6006 ecore_x_passive_grab_replay_func_set(_e_comp_x_grab_replay, NULL);
6007
6008 if (!e_xsettings_init())
6009 e_error_message_show(_("Enlightenment cannot initialize the XSettings system.\n"));
6010 E_LIST_HANDLER_APPEND(handlers, E_EVENT_RANDR_CHANGE, _e_comp_x_randr_change, NULL);
6011
6012 ecore_x_sync();
6013 _x_idle_flush = ecore_idle_enterer_add(_e_comp_x_flusher, NULL);
6014
6015 if (e_comp->comp_type != E_PIXMAP_TYPE_WL)
6016 {
6017 ecore_x_screensaver_event_listen_set(1);
6018 E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_ON, _e_comp_x_screensaver_on, NULL);
6019 E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREENSAVER_OFF, _e_comp_x_screensaver_off, NULL);
6020 E_LIST_HANDLER_APPEND(handlers, ECORE_X_EVENT_SCREENSAVER_NOTIFY, _e_comp_x_screensaver_notify_cb, NULL);
6021 ecore_x_screensaver_custom_blanking_enable();
6022
6023 e_screensaver_attrs_set(ecore_x_screensaver_timeout_get(),
6024 ecore_x_screensaver_blank_get(),
6025 ecore_x_screensaver_expose_get());
6026 e_desklock_show_hook_add(_e_comp_x_desklock_show);
6027 e_desklock_hide_hook_add(_e_comp_x_desklock_hide);
6028 int timeout = e_screensaver_timeout_get(EINA_TRUE);
6029 ecore_x_screensaver_set(timeout + 10,
6030 0,
6031 !e_config->screensaver_blanking,
6032 !e_config->screensaver_expose);
6033 ecore_x_screensaver_set(timeout,
6034 0,
6035 e_config->screensaver_blanking,
6036 e_config->screensaver_expose);
6037 }
6038 else
6039 e_dnd_init();
6040 eina_list_free(h);
6041 return EINA_TRUE;
6042 }
6043
6044 E_API void
e_comp_x_shutdown(void)6045 e_comp_x_shutdown(void)
6046 {
6047 _e_comp_x_del(e_comp);
6048 E_FREE_LIST(handlers, ecore_event_handler_del);
6049 E_FREE_FUNC(clients_win_hash, eina_hash_free);
6050 E_FREE_FUNC(damages_hash, eina_hash_free);
6051 E_FREE_FUNC(alarm_hash, eina_hash_free);
6052 E_FREE_FUNC(pending_configures, eina_hash_free);
6053 E_FREE_FUNC(frame_extents, eina_hash_free);
6054 E_FREE_FUNC(mouse_in_fix_check_timer, ecore_timer_del);
6055 e_xsettings_shutdown();
6056 if (x_fatal) return;
6057 if (e_comp->comp_type == E_PIXMAP_TYPE_X)
6058 ecore_x_screensaver_custom_blanking_disable();
6059 e_atoms_shutdown();
6060 /* ecore_x_ungrab(); */
6061 ecore_x_focus_reset();
6062 ecore_x_events_allow_all();
6063 ecore_x_shutdown();
6064 }
6065
6066 EINTERN void
e_comp_x_nocomp_end(void)6067 e_comp_x_nocomp_end(void)
6068 {
6069 e_comp->nocomp = 0;
6070 ecore_x_window_show(e_comp->win);
6071 ecore_x_composite_redirect_subwindows(e_comp->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
6072 _e_comp_x_focus_check();
6073 }
6074
6075 #ifdef HAVE_WAYLAND
6076 EINTERN void
e_comp_x_xwayland_client_setup(E_Client * ec,E_Client * wc)6077 e_comp_x_xwayland_client_setup(E_Client *ec, E_Client *wc)
6078 {
6079 Ecore_X_Window win, pwin;
6080 E_Comp_X_Client_Data *cd;
6081 Eina_Bool placed;
6082
6083 win = e_client_util_win_get(ec);
6084 pwin = e_client_util_pwin_get(ec);
6085 cd = ec->comp_data;
6086 e_comp_wl_client_xwayland_setup(wc, cd, e_pixmap_ref(ec->pixmap));
6087 eina_hash_del(damages_hash, &cd->damage, ec);
6088 ecore_x_damage_free(cd->damage);
6089 E_FREE_FUNC(cd->first_draw_delay, ecore_timer_del);
6090 cd->damage = 0;
6091 ec->comp_data = NULL;
6092 cd->evas_init = 0;
6093 _e_comp_x_client_evas_init(wc);
6094 if (!e_comp_object_frame_exists(ec->frame))
6095 {
6096 int l, r, t, b;
6097
6098 e_comp_object_frame_geometry_get(ec->frame, &l, &r, &t, &b);
6099 e_comp_object_frame_geometry_set(wc->frame, l, r, t, b);
6100 }
6101 wc->borderless = ec->borderless;
6102 wc->border.changed = 1;
6103 EC_CHANGED(wc);
6104 wc->depth = ec->depth;
6105 wc->override = ec->override;
6106 placed = ec->placed;
6107 wc->input_only = ec->input_only;
6108 wc->border_size = ec->border_size;
6109 wc->no_shape_cut = 0;
6110 memcpy(&wc->icccm, &ec->icccm, sizeof(ec->icccm));
6111 memcpy(&wc->netwm, &ec->netwm, sizeof(ec->netwm));
6112 memcpy(&wc->e, &ec->e, sizeof(ec->e));
6113 wc->new_client = !wc->override;
6114 if (wc->new_client)
6115 e_comp->new_clients++;
6116
6117 eina_hash_set(clients_win_hash, &win, wc);
6118 if (pwin)
6119 eina_hash_set(clients_win_hash, &pwin, wc);
6120 wc->visible = 1;
6121 if (wc->ignored)
6122 e_client_unignore(wc);
6123 if (ec->override)
6124 e_client_focus_stack_set(eina_list_remove(e_client_focus_stack_get(), wc));
6125 evas_object_name_set(wc->frame, evas_object_name_get(ec->frame));
6126 wc->x = ec->x, wc->y = ec->y;
6127 wc->client.x = ec->client.x, wc->client.y = ec->client.y;
6128 wc->w = ec->w, wc->h = ec->h;
6129 wc->client.w = ec->client.w, wc->client.h = ec->client.h;
6130 wc->layer = ec->layer;
6131 wc->netwm.sync.request = 1;
6132 evas_object_layer_set(wc->frame, evas_object_layer_get(ec->frame));
6133 evas_object_geometry_set(wc->frame, ec->x, ec->y, ec->w, ec->h);
6134 evas_object_show(wc->frame);
6135 e_pixmap_alias(wc->pixmap, E_PIXMAP_TYPE_X, e_pixmap_window_get(ec->pixmap));
6136 e_object_del(E_OBJECT(ec));
6137 e_hints_window_visible_set(wc);
6138 _e_comp_x_client_stack(wc);
6139 wc->placed = placed;
6140 if (!placed) wc->changes.pos = 0;
6141 }
6142 #endif
6143
6144 E_API inline E_Pixmap *
e_comp_x_client_pixmap_get(const E_Client * ec)6145 e_comp_x_client_pixmap_get(const E_Client *ec)
6146 {
6147 #ifdef HAVE_WAYLAND
6148 if ((!e_pixmap_is_x(ec->pixmap)) && e_client_has_xwindow(ec))
6149 return e_comp_wl_client_xwayland_pixmap(ec);
6150 #endif
6151 return ec->pixmap;
6152 }
6153