add hooking for WL_SURFACE_ID atom on XWayland windows and composite them

in order to maximize the amount of reused code the following details the current
process for xwayland compositing:

* get map request from window
* force reparenting
* show window
* await WL_SURFACE_ID x11 message
* move x11 client data + pixmap onto corresponding wayland client
* business as usual with wayland compositing

this is pretty similar to the method of the reference code in weston,
except that there's no x11 compositor in weston
devs/stefan/wl-session-recovery
Mike Blumenkrantz 8 years ago
parent c8bdacc727
commit 2b38147c43
  1. 21
      src/bin/e_comp_wl.c
  2. 34
      src/bin/e_comp_wl.h
  3. 119
      src/bin/e_comp_x.c
  4. 8
      src/bin/e_comp_x.h

@ -40,7 +40,7 @@ _e_comp_wl_focus_check(void)
if (stopping) return;
ec = e_client_focused_get();
if ((!ec) || (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL))
if ((!ec) || e_pixmap_is_x(ec->pixmap))
e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
}
@ -1442,7 +1442,8 @@ static void
_e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
{
struct wl_resource *res;
E_Client *ec = NULL;
E_Client *wc, *ec = NULL;
Eina_List *l;
pid_t pid;
DBG("Compositor Cb Surface Create: %d", id);
@ -1491,7 +1492,15 @@ _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_reso
/* set reference to pixmap so we can fetch it later */
wl_resource_set_user_data(res, ec);
#ifndef HAVE_WAYLAND_ONLY
EINA_LIST_FOREACH(e_comp->wl_comp_data->xwl_pending, l, wc)
{
if (!e_pixmap_is_x(wc->pixmap)) continue;
if (wl_resource_get_id(res) != ((E_Comp_X_Client_Data*)ec->comp_data)->surface_id) continue;
e_comp_x_xwayland_client_setup(wc, ec);
break;
}
#endif
/* emit surface create signal */
wl_signal_emit(&e_comp->wl_comp_data->signals.surface.create, res);
}
@ -2964,3 +2973,9 @@ e_comp_wl_output_remove(const char *id)
/* free(output); */
}
}
EINTERN void
e_comp_wl_xwayland_client_queue(E_Client *ec)
{
e_comp->wl_comp_data->xwl_pending = eina_list_append(e_comp->wl_comp_data->xwl_pending, ec);
}

@ -1,5 +1,7 @@
#ifdef E_TYPEDEFS
# ifndef HAVE_WAYLAND_ONLY
# include "e_comp_x.h"
# endif
#else
# ifndef E_COMP_WL_H
# define E_COMP_WL_H
@ -13,6 +15,10 @@
# include <xkbcommon/xkbcommon.h>
# ifndef HAVE_WAYLAND_ONLY
# include "e_comp_x.h"
# endif
/* # ifdef HAVE_WAYLAND_EGL */
/* # include <EGL/egl.h> */
/* # define GL_GLEXT_PROTOTYPES */
@ -211,6 +217,7 @@ struct _E_Comp_Wl_Data
Ecore_Idler *idler;
struct wl_client *xwl_client;
Eina_List *xwl_pending;
/* Eina_List *retry_clients; */
/* Ecore_Timer *retry_timer; */
@ -254,6 +261,10 @@ struct _E_Comp_Wl_Client_Data
{
int32_t x, y;
} popup;
#ifndef HAVE_WAYLAND_ONLY
E_Pixmap *xwayland_pixmap;
E_Comp_X_Client_Data *xwayland_data;
#endif
Eina_Bool keep_buffer : 1;
Eina_Bool mapped : 1;
@ -294,6 +305,27 @@ E_API struct wl_signal e_comp_wl_surface_create_signal_get(void);
E_API double e_comp_wl_idle_time_get(void);
E_API Eina_Bool e_comp_wl_output_init(const char *id, const char *make, const char *model, int x, int y, int w, int h, int pw, int ph, unsigned int refresh, unsigned int subpixel, unsigned int transform);
E_API void e_comp_wl_output_remove(const char *id);
# ifndef HAVE_WAYLAND_ONLY
EINTERN void e_comp_wl_xwayland_client_queue(E_Client *ec);
static inline E_Comp_X_Client_Data *
e_comp_wl_client_xwayland_data(const E_Client *ec)
{
return ec->comp_data ? ((E_Comp_Wl_Client_Data*)ec->comp_data)->xwayland_data : NULL;
}
static inline E_Pixmap *
e_comp_wl_client_xwayland_pixmap(const E_Client *ec)
{
return ((E_Comp_Wl_Client_Data*)ec->comp_data)->xwayland_pixmap;
}
static inline void
e_comp_wl_client_xwayland_setup(E_Client *ec, E_Comp_X_Client_Data *cd, E_Pixmap *ep)
{
((E_Comp_Wl_Client_Data*)ec->comp_data)->xwayland_data = cd;
((E_Comp_Wl_Client_Data*)ec->comp_data)->xwayland_pixmap = ep;
e_comp->wl_comp_data->xwl_pending = eina_list_remove(e_comp->wl_comp_data->xwl_pending, ec);
}
# endif
# endif
#endif

@ -57,6 +57,8 @@ static Eina_Bool screensaver_dimmed = EINA_FALSE;
static Ecore_X_Atom backlight_atom = 0;
extern double e_bl_val;
static void _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec);
static Eina_Bool
_e_comp_x_flusher(void *data EINA_UNUSED)
{
@ -1142,6 +1144,15 @@ _e_comp_x_show_request(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Eve
ecore_x_window_show(ev->win);
return ECORE_CALLBACK_RENEW;
}
if ((e_comp->comp_type != E_PIXMAP_TYPE_X) && ec->ignored)
{
ec->visible = 1;
if (ec->comp_data->need_reparent)
_e_comp_x_hook_client_pre_frame_assign(NULL, ec);
else
ecore_x_window_show(ev->win);
return ECORE_CALLBACK_RENEW;
}
if ((!ec->comp_data->reparented) && (!e_client_util_ignored_get(ec)))
{
@ -1395,7 +1406,7 @@ _e_comp_x_configure(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_
EINA_RECTANGLE_SET(&ec->client, ev->x, ev->y, ev->w, ev->h);
if (move)
evas_object_move(ec->frame, ev->x, ev->y);
if (resize)
if (resize && e_pixmap_is_x(ec->pixmap))
{
e_pixmap_dirty(ec->pixmap);
evas_object_resize(ec->frame, ev->w, ev->h);
@ -1993,6 +2004,25 @@ _e_comp_x_message(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Cl
break;
}
}
#ifdef HAVE_WAYLAND
else if (ev->message_type == WL_SURFACE_ID)
{
void *res;
E_Client *wc = NULL;
if (e_comp->comp_type != E_PIXMAP_TYPE_WL) return ECORE_CALLBACK_RENEW;
res = wl_client_get_object(e_comp->wl_comp_data->xwl_client, ev->data.l[0]);
if (res)
wc = wl_resource_get_user_data(res);
if (wc)
e_comp_x_xwayland_client_setup(ec, wc);
else
{
ec->comp_data->surface_id = ev->data.l[0];
e_comp_wl_xwayland_client_queue(ec);
}
}
#endif
return ECORE_CALLBACK_PASS_ON;
}
@ -2737,7 +2767,10 @@ _e_comp_x_hook_client_pre_frame_assign(void *d EINA_UNUSED, E_Client *ec)
ECORE_X_WINDOW_CONFIGURE_MASK_STACK_MODE,
0, 0, 0, 0, 0,
win, ECORE_X_WINDOW_STACK_ABOVE);
ecore_x_event_mask_set(pwin, ECORE_X_EVENT_MASK_MOUSE_IN | ECORE_X_EVENT_MASK_MOUSE_OUT);
ecore_x_event_mask_set(pwin, ECORE_X_EVENT_MASK_KEY_DOWN | ECORE_X_EVENT_MASK_KEY_UP |
ECORE_X_EVENT_MASK_MOUSE_MOVE | ECORE_X_EVENT_MASK_MOUSE_DOWN |
ECORE_X_EVENT_MASK_MOUSE_UP | ECORE_X_EVENT_MASK_MOUSE_WHEEL |
ECORE_X_EVENT_MASK_MOUSE_IN | ECORE_X_EVENT_MASK_MOUSE_OUT);
ecore_x_window_border_width_set(win, 0);
ec->border_size = 0;
@ -4090,6 +4123,7 @@ _e_comp_x_hook_client_new(void *d EINA_UNUSED, E_Client *ec)
ec->icccm.state = ECORE_X_WINDOW_STATE_HINT_NONE;
if (!_e_comp_x_client_new_helper(ec)) return;
ec->ignored |= e_comp->comp_type == E_PIXMAP_TYPE_WL;
ec->comp_data->first_damage = ec->internal;
@ -4561,16 +4595,19 @@ _e_comp_x_randr_change(void *data EINA_UNUSED, int ev_type EINA_UNUSED, void *ev
if ((e_comp->w != e_randr2->w) ||
(e_comp->h != e_randr2->h))
{
e_comp_canvas_resize(e_randr2->w, e_randr2->h);
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
e_comp_canvas_resize(e_randr2->w, e_randr2->h);
}
else
{
E_Client *ec;
ecore_x_netwm_desk_size_set(e_comp->root, e_comp->w, e_comp->h);
e_randr2_screens_setup(e_comp->w, e_comp->h);
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
e_randr2_screens_setup(e_comp->w, e_comp->h);
e_comp_canvas_update();
if (e_comp->comp_type == E_PIXMAP_TYPE_X)
e_comp_canvas_update();
E_CLIENT_FOREACH(ec)
{
if (!e_client_util_ignored_get(ec))
@ -4891,6 +4928,7 @@ _e_comp_x_setup(Ecore_X_Window root, int w, int h)
e_hints_init(root, e_comp->cm_selection);
ecore_x_window_background_color_set(root, 0, 0, 0);
ecore_x_screen_is_composited_set(0, e_comp->cm_selection);
ecore_x_selection_owner_set(e_comp->cm_selection, ecore_x_atom_get("WM_S0"), ecore_x_current_time_get());
e_comp->win = ecore_x_composite_render_window_enable(root);
if (!e_comp->win)
@ -4937,7 +4975,10 @@ _e_comp_x_setup(Ecore_X_Window root, int w, int h)
e_comp->bindings_grab_cb = _e_comp_x_bindings_grab_cb;
e_comp->bindings_ungrab_cb = _e_comp_x_bindings_ungrab_cb;
if (!e_comp_canvas_init(w, h)) return EINA_FALSE;
if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
{
if (!e_comp_canvas_init(w, h)) return EINA_FALSE;
}
e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
@ -4959,6 +5000,7 @@ _e_comp_x_setup(Ecore_X_Window root, int w, int h)
ec->lock_client_stacking = 1;
ec->internal = 1;
ec->visible = 1;
evas_object_del(e_comp->layers[i].obj);
e_comp->layers[i].obj = ec->frame;
evas_object_layer_set(ec->frame, e_comp_canvas_layer_map_to(i));
evas_object_pass_events_set(ec->frame, 1);
@ -4968,11 +5010,14 @@ _e_comp_x_setup(Ecore_X_Window root, int w, int h)
ecore_x_window_lower(e_comp->layers[i].win);
ecore_evas_lower(e_comp->ee);
e_comp->pointer = e_pointer_window_new(e_comp->root, 0);
e_comp->pointer->color = ecore_x_cursor_color_supported_get();
e_pointer_type_push(e_comp->pointer, e_comp->pointer, "default");
if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
{
e_comp->pointer = e_pointer_window_new(e_comp->root, 0);
e_comp->pointer->color = ecore_x_cursor_color_supported_get();
e_pointer_type_push(e_comp->pointer, e_comp->pointer, "default");
ecore_x_icccm_state_set(ecore_evas_window_get(e_comp->ee), ECORE_X_WINDOW_STATE_HINT_NORMAL);
}
_e_comp_x_manage_windows();
ecore_x_icccm_state_set(ecore_evas_window_get(e_comp->ee), ECORE_X_WINDOW_STATE_HINT_NORMAL);
{
E_Client *ec;
@ -4994,8 +5039,11 @@ _e_comp_x_screens_setup(void)
Ecore_X_Window root;
int rw, rh;
e_comp_x_randr_screen_iface_set();
if (!e_randr2_init()) return 0;
if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
{
e_comp_x_randr_screen_iface_set();
if (!e_randr2_init()) return 0;
}
root = ecore_x_window_root_first_get();
if (!root)
{
@ -5003,11 +5051,12 @@ _e_comp_x_screens_setup(void)
return 0;
}
ecore_x_window_size_get(root, &rw, &rh);
e_randr2_screens_setup(rw, rh);
if (e_comp->comp_type == E_PIXMAP_TYPE_NONE)
e_randr2_screens_setup(rw, rh);
return _e_comp_x_setup(root, rw, rh);
}
EINTERN Eina_Bool
E_API Eina_Bool
e_comp_x_init(void)
{
if (!ecore_x_init(NULL))
@ -5143,7 +5192,7 @@ e_comp_x_init(void)
return EINA_TRUE;
}
EINTERN void
E_API void
e_comp_x_shutdown(void)
{
E_FREE_LIST(handlers, ecore_event_handler_del);
@ -5170,3 +5219,43 @@ e_comp_x_nocomp_end(void)
ecore_x_composite_redirect_subwindows(e_comp->root, ECORE_X_COMPOSITE_UPDATE_MANUAL);
_e_comp_x_focus_check();
}
#ifdef HAVE_WAYLAND
EINTERN void
e_comp_x_xwayland_client_setup(E_Client *ec, E_Client *wc)
{
Ecore_X_Window win;
E_Comp_X_Client_Data *cd;
win = e_client_util_win_get(ec);
cd = ec->comp_data;
e_comp_wl_client_xwayland_setup(wc, cd, e_pixmap_ref(ec->pixmap));
eina_hash_del(damages_hash, &cd->damage, ec);
ecore_x_damage_free(cd->damage);
E_FREE_FUNC(cd->first_draw_delay, ecore_timer_del);
cd->damage = 0;
ec->comp_data = NULL;
cd->evas_init = 0;
_e_comp_x_client_evas_init(wc);
wc->borderless = ec->borderless;
wc->border.changed = 1;
EC_CHANGED(wc);
wc->depth = ec->depth;
wc->override = ec->override;
wc->placed = ec->placed;
wc->input_only = ec->input_only;
wc->border_size = ec->border_size;
memcpy(&wc->icccm, &ec->icccm, sizeof(ec->icccm));
memcpy(&wc->netwm, &ec->netwm, sizeof(ec->netwm));
memcpy(&wc->e, &ec->e, sizeof(ec->e));
ec->new_client = 1;
e_comp->new_clients++;
eina_hash_set(clients_win_hash, &win, wc);
wc->visible = 1;
evas_object_show(wc->frame);
e_object_del(E_OBJECT(ec));
e_hints_window_visible_set(wc);
_e_comp_x_client_stack(wc);
}
#endif

@ -87,6 +87,9 @@ struct _E_Comp_X_Client_Data
Ecore_X_Illume_Window_State state;
} win_state;
} illume;
#ifdef HAVE_WAYLAND
uint32_t surface_id;
#endif
Eina_Bool moving : 1;
Eina_Bool first_map : 1;
@ -102,10 +105,11 @@ struct _E_Comp_X_Client_Data
Eina_Bool unredirected_single : 1;
};
EINTERN Eina_Bool e_comp_x_init(void);
EINTERN void e_comp_x_shutdown(void);
E_API Eina_Bool e_comp_x_init(void);
E_API void e_comp_x_shutdown(void);
E_API void e_alert_composite_win(Ecore_X_Window root, Ecore_X_Window win);
EINTERN void e_comp_x_nocomp_end(void);
EINTERN void e_comp_x_xwayland_client_setup(E_Client *ec, E_Client *wc);
# endif
#endif

Loading…
Cancel
Save