enlightenment/src/bin/e_comp_wl.c

2890 lines
90 KiB
C
Raw Normal View History

#include "e.h"
#include "e_comp_wl.h"
#include <sys/mman.h>
#define e_pixmap_parent_window_set(X, Y) e_pixmap_parent_window_set(X, (Ecore_Window)(uintptr_t)Y)
/* compositor function prototypes */
static void _seat_send_updated_caps(struct wl_seat *seat);
static void _move_resources(struct wl_list *dest, struct wl_list *src);
static void _move_resources_for_client(struct wl_list *dest, struct wl_list *src, struct wl_client *client);
static struct wl_resource *_find_resource_for_surface(struct wl_list *list, struct wl_resource *surface);
static void _default_grab_focus(struct wl_pointer_grab *grab, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y);
static void _default_grab_motion(struct wl_pointer_grab *grab, uint32_t timestamp, wl_fixed_t x, wl_fixed_t y);
static void _default_grab_button(struct wl_pointer_grab *grab, uint32_t timestamp, uint32_t button, uint32_t state_w);
static void _default_grab_touch_down(struct wl_touch_grab *grab, uint32_t timestamp, int touch_id, wl_fixed_t sx, wl_fixed_t sy);
static void _default_grab_touch_up(struct wl_touch_grab *grab, uint32_t timestamp, int touch_id);
static void _default_grab_touch_motion(struct wl_touch_grab *grab, uint32_t timestamp, int touch_id, wl_fixed_t sx, wl_fixed_t sy);
static void _data_offer_accept(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *mime_type);
static void _data_offer_receive(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *mime_type, int32_t fd);
static void _data_offer_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource);
static void _destroy_data_offer(struct wl_resource *resource);
static void _destroy_offer_data_source(struct wl_listener *listener, void *data EINA_UNUSED);
static void _create_data_source(struct wl_client *client, struct wl_resource *resource, uint32_t id);
static void _get_data_device(struct wl_client *client, struct wl_resource *manager_resource EINA_UNUSED, uint32_t id, struct wl_resource *seat_resource);
static void _current_surface_destroy(struct wl_listener *listener, void *data EINA_UNUSED);
static void _bind_manager(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id);
static void _default_grab_key(struct wl_keyboard_grab *grab, uint32_t timestamp, uint32_t key, uint32_t state);
static void _default_grab_modifiers(struct wl_keyboard_grab *grab, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
static void _data_device_start_drag(struct wl_client *client, struct wl_resource *resource, struct wl_resource *source_resource, struct wl_resource *origin_resource EINA_UNUSED, struct wl_resource *icon_resource, uint32_t serial EINA_UNUSED);
static void _data_device_set_selection(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *source_resource, uint32_t serial);
static void _destroy_data_device_icon(struct wl_listener *listener, void *data EINA_UNUSED);
static void _destroy_selection_data_source(struct wl_listener *listener, void *data EINA_UNUSED);
static void _data_source_offer(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *type);
static void _data_source_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource);
static void _destroy_data_source(struct wl_resource *resource);
static void _destroy_data_device_source(struct wl_listener *listener, void *data EINA_UNUSED);
static void _data_device_end_drag_grab(struct wl_seat *seat);
static void _drag_grab_button(struct wl_pointer_grab *grab, uint32_t timestamp EINA_UNUSED, uint32_t button, uint32_t state_w);
static void _drag_grab_motion(struct wl_pointer_grab *grab, uint32_t timestamp, wl_fixed_t x, wl_fixed_t y);
static void _destroy_drag_focus(struct wl_listener *listener, void *data EINA_UNUSED);
static void _drag_grab_focus(struct wl_pointer_grab *grab, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y);
static void _client_source_accept(struct wl_data_source *source, uint32_t timestamp EINA_UNUSED, const char *mime_type);
static void _client_source_send(struct wl_data_source *source, const char *mime_type, int32_t fd);
static void _client_source_cancel(struct wl_data_source *source);
static void _e_comp_wl_cb_bind(struct wl_client *client, void *data, unsigned int version, unsigned int id);
static Eina_Bool _e_comp_wl_cb_read(void *data EINA_UNUSED, Ecore_Fd_Handler *hdl EINA_UNUSED);
static Eina_Bool _e_comp_wl_cb_idle(void *data EINA_UNUSED);
static Eina_Bool _e_comp_wl_cb_module_idle(void *data EINA_UNUSED);
/* compositor interface prototypes */
static void _e_comp_wl_cb_surface_create(struct wl_client *client, struct wl_resource *resource, unsigned int id);
static void _e_comp_wl_cb_surface_destroy(struct wl_resource *resource);
static void _e_comp_wl_cb_region_create(struct wl_client *client, struct wl_resource *resource, unsigned int id);
static void _e_comp_wl_cb_region_destroy(struct wl_resource *resource);
/* input function prototypes */
static Eina_Bool _e_comp_wl_input_init(void);
static void _e_comp_wl_input_shutdown(void);
static void _e_comp_wl_input_cb_bind(struct wl_client *client, void *data, unsigned int version EINA_UNUSED, unsigned int id);
static void _e_comp_wl_input_cb_unbind(struct wl_resource *resource);
static struct xkb_keymap *_e_comp_wl_input_keymap_get(void);
static int _e_comp_wl_input_keymap_fd_get(off_t size);
static E_Wayland_Keyboard_Info *_e_comp_wl_input_keyboard_info_get(struct xkb_keymap *keymap);
/* input interface prototypes */
static void _e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, unsigned int id);
static void _e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, unsigned int id);
static void _e_comp_wl_input_cb_touch_get(struct wl_client *client, struct wl_resource *resource, unsigned int id);
/* pointer function prototypes */
static void _e_comp_wl_pointer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED);
static void _e_comp_wl_pointer_configure(E_Wayland_Surface *ews, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
static void _e_comp_wl_pointer_unmap(E_Wayland_Surface *ews);
/* pointer interface prototypes */
static void _e_comp_wl_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource, unsigned int serial, struct wl_resource *surface_resource, int x, int y);
static void _e_comp_wl_pointer_cb_release(struct wl_client *client, struct wl_resource *resource);
/* keyboard interface prototypes */
static void _e_comp_wl_keyboard_cb_release(struct wl_client *client, struct wl_resource *resource);
/* touch interface prototypes */
static void _e_comp_wl_touch_cb_release(struct wl_client *client, struct wl_resource *resource);
/* region interface prototypes */
static void _e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource);
static void _e_comp_wl_region_cb_add(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h);
static void _e_comp_wl_region_cb_subtract(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h);
/* surface function prototypes */
static void _e_comp_wl_surface_cb_pending_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED);
static void _e_comp_wl_surface_cb_frame_destroy(struct wl_resource *resource);
static void _e_comp_wl_surface_buffer_reference(E_Wayland_Buffer_Reference *ref, E_Wayland_Buffer *buffer);
static void _e_comp_wl_surface_buffer_reference_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED);
static E_Wayland_Buffer *_e_comp_wl_surface_buffer_resource(struct wl_resource *resource);
static void _e_comp_wl_surface_buffer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED);
/* surface interface prototypes */
static void _e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource);
static void _e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *buffer_resource, int x, int y);
static void _e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h);
static void _e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, unsigned int callback);
static void _e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource);
static void _e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource);
static void _e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource);
static void _e_comp_wl_surface_cb_buffer_transform_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, int transform EINA_UNUSED);
static void _e_comp_wl_surface_cb_buffer_scale_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, int scale EINA_UNUSED);
/* local wayland interfaces */
static const struct wl_compositor_interface _e_compositor_interface =
{
_e_comp_wl_cb_surface_create,
_e_comp_wl_cb_region_create
};
static const struct wl_seat_interface _e_input_interface =
{
_e_comp_wl_input_cb_pointer_get,
_e_comp_wl_input_cb_keyboard_get,
_e_comp_wl_input_cb_touch_get,
};
static const struct wl_pointer_interface _e_pointer_interface =
{
_e_comp_wl_pointer_cb_cursor_set,
_e_comp_wl_pointer_cb_release
};
static const struct wl_keyboard_interface _e_keyboard_interface =
{
_e_comp_wl_keyboard_cb_release
};
static const struct wl_touch_interface _e_touch_interface =
{
_e_comp_wl_touch_cb_release
};
static const struct wl_region_interface _e_region_interface =
{
_e_comp_wl_region_cb_destroy,
_e_comp_wl_region_cb_add,
_e_comp_wl_region_cb_subtract
};
static const struct wl_surface_interface _e_surface_interface =
{
_e_comp_wl_surface_cb_destroy,
_e_comp_wl_surface_cb_attach,
_e_comp_wl_surface_cb_damage,
_e_comp_wl_surface_cb_frame,
_e_comp_wl_surface_cb_opaque_region_set,
_e_comp_wl_surface_cb_input_region_set,
_e_comp_wl_surface_cb_commit,
_e_comp_wl_surface_cb_buffer_transform_set,
_e_comp_wl_surface_cb_buffer_scale_set
};
static const struct wl_pointer_grab_interface _e_pointer_grab_interface =
{
_default_grab_focus,
_default_grab_motion,
_default_grab_button
};
static const struct wl_keyboard_grab_interface _e_default_keyboard_grab_interface =
{
_default_grab_key,
_default_grab_modifiers,
};
static const struct wl_data_offer_interface _e_data_offer_interface =
{
_data_offer_accept,
_data_offer_receive,
_data_offer_destroy,
};
static const struct wl_data_device_manager_interface _e_manager_interface =
{
_create_data_source,
_get_data_device
};
static const struct wl_data_device_interface _e_data_device_interface =
{
_data_device_start_drag,
_data_device_set_selection,
};
static const struct wl_touch_grab_interface _e_default_touch_grab_interface =
{
_default_grab_touch_down,
_default_grab_touch_up,
_default_grab_touch_motion
};
static struct wl_data_source_interface _e_data_source_interface =
{
_data_source_offer,
_data_source_destroy
};
static const struct wl_pointer_grab_interface _e_drag_grab_interface =
{
_drag_grab_focus,
_drag_grab_motion,
_drag_grab_button,
};
/* local variables */
static Ecore_Idler *_module_idler = NULL;
/* external variables */
EAPI E_Wayland_Compositor *_e_wl_comp;
/* external functions */
EAPI Eina_Bool
e_comp_wl_init(void)
{
int fd = 0;
/* try to allocate space for a new compositor */
if (!(_e_wl_comp = E_NEW(E_Wayland_Compositor, 1)))
return EINA_FALSE;
/* try to create a wayland display */
if (!(_e_wl_comp->wl.display = wl_display_create()))
{
ERR("Could not create a Wayland Display: %m");
goto err;
}
/* init compositor signals */
wl_signal_init(&_e_wl_comp->signals.destroy);
wl_signal_init(&_e_wl_comp->signals.activate);
wl_signal_init(&_e_wl_comp->signals.kill);
wl_signal_init(&_e_wl_comp->signals.seat);
/* try to add compositor to the displays globals */
if (!wl_global_create(_e_wl_comp->wl.display, &wl_compositor_interface, 3,
_e_wl_comp, _e_comp_wl_cb_bind))
{
ERR("Could not add compositor to globals: %m");
goto err;
}
/* init data device manager */
wl_data_device_manager_init(_e_wl_comp->wl.display);
/* try to init shm mechanism */
if (wl_display_init_shm(_e_wl_comp->wl.display) < 0)
ERR("Could not initialize SHM: %m");
#ifdef HAVE_WAYLAND_EGL
/* try to get the egl display
*
* NB: This is interesting....if we try to eglGetDisplay and pass in the
* wayland display, then EGL fails due to XCB not owning the event queue.
* If we pass it a NULL, it inits just fine */
_e_wl_comp->egl.display = eglGetDisplay(NULL);
if (_e_wl_comp->egl.display == EGL_NO_DISPLAY)
ERR("Could not get EGL display: %m");
else
{
EGLint major, minor;
/* try to initialize egl */
if (!eglInitialize(_e_wl_comp->egl.display, &major, &minor))
{
ERR("Could not initialize EGL: %m");
eglTerminate(_e_wl_comp->egl.display);
}
else
{
EGLint n;
EGLint attribs[] =
{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1,
EGL_ALPHA_SIZE, 1, EGL_RENDERABLE_TYPE,
EGL_OPENGL_ES2_BIT, EGL_NONE
};
/* const char *exts; */
if ((!eglChooseConfig(_e_wl_comp->egl.display, attribs,
&_e_wl_comp->egl.config, 1, &n) || (n == 0)))
{
ERR("Could not choose EGL config: %m");
eglTerminate(_e_wl_comp->egl.display);
}
}
}
#endif
/* try to initialize input */
if (!_e_comp_wl_input_init())
{
ERR("Could not initialize input: %m");
goto err;
}
#ifndef WAYLAND_ONLY
/* setup keymap_change event handler */
_e_wl_comp->kbd_handler =
ecore_event_handler_add(ECORE_X_EVENT_XKB_STATE_NOTIFY,
e_comp_wl_cb_keymap_changed, NULL);
#endif
/* get the displays event loop */
_e_wl_comp->wl.loop = wl_display_get_event_loop(_e_wl_comp->wl.display);
/* get the event loop's file descriptor so we can listen on it */
fd = wl_event_loop_get_fd(_e_wl_comp->wl.loop);
/* add the fd to E's main loop */
_e_wl_comp->fd_handler =
ecore_main_fd_handler_add(fd, ECORE_FD_READ,
_e_comp_wl_cb_read, NULL, NULL, NULL);
/* add an idler for flushing clients */
_e_wl_comp->idler = ecore_idle_enterer_add(_e_comp_wl_cb_idle, NULL);
/* TODO: event handlers ?? */
/* try to add a display socket */
if (wl_display_add_socket(_e_wl_comp->wl.display, NULL) < 0)
{
ERR("Could not add a Wayland Display socket: %m");
goto err;
}
wl_event_loop_dispatch(_e_wl_comp->wl.loop, 0);
#ifndef WAYLAND_ONLY
/* add an idler for deferred shell module loading */
_module_idler = ecore_idler_add(_e_comp_wl_cb_module_idle, NULL);
#endif
/* return success */
return EINA_TRUE;
err:
/* remove kbd handler */
if (_e_wl_comp->kbd_handler)
ecore_event_handler_del(_e_wl_comp->kbd_handler);
#ifndef WAYLAND_ONLY
/* remove the module idler */
if (_module_idler) ecore_idler_del(_module_idler);
#endif
#ifdef HAVE_WAYLAND_EGL
/* unbind wayland display */
if (_e_wl_comp->egl.bound)
_e_wl_comp->egl.unbind_display(_e_wl_comp->egl.display, _e_wl_comp->wl.display);
/* terminate the egl display */
if (_e_wl_comp->egl.display) eglTerminate(_e_wl_comp->egl.display);
eglReleaseThread();
#endif
/* if we have a display, destroy it */
if (_e_wl_comp->wl.display) wl_display_destroy(_e_wl_comp->wl.display);
/* free the compositor */
E_FREE(_e_wl_comp);
/* return failure */
return EINA_FALSE;
}
EINTERN void
e_comp_wl_shutdown(void)
{
E_Module *mod = NULL;
if (_e_wl_comp)
{
/* remove the idler */
if (_e_wl_comp->idler) ecore_idler_del(_e_wl_comp->idler);
/* remove the fd handler */
if (_e_wl_comp->fd_handler)
ecore_main_fd_handler_del(_e_wl_comp->fd_handler);
/* shutdown input */
_e_comp_wl_input_shutdown();
#ifdef HAVE_WAYLAND_EGL
/* unbind wayland display */
if (_e_wl_comp->egl.bound)
_e_wl_comp->egl.unbind_display(_e_wl_comp->egl.display, _e_wl_comp->wl.display);
/* terminate the egl display */
if (_e_wl_comp->egl.display) eglTerminate(_e_wl_comp->egl.display);
eglReleaseThread();
#endif
/* if we have a display, destroy it */
if (_e_wl_comp->wl.display) wl_display_destroy(_e_wl_comp->wl.display);
/* free the compositor */
E_FREE(_e_wl_comp);
}
/* disable the loaded shell module */
/* TODO: we should have a config variable somewhere to store which
* shell we want to unload (tablet, mobile, etc) */
if ((mod = e_module_find("wl_desktop_shell")))
e_module_disable(mod);
}
#ifdef WAYLAND_ONLY
EAPI int
e_comp_wl_input_read(int fd EINA_UNUSED, unsigned int mask EINA_UNUSED, void *data)
{
E_Wayland_Compositor *wl_comp = data;
wl_event_loop_dispatch(wl_comp->wl.input_loop, 0);
return 1;
}
#endif
EAPI void
wl_seat_init(struct wl_seat *seat)
{
memset(seat, 0, sizeof *seat);
wl_signal_init(&seat->destroy_signal);
seat->selection_data_source = NULL;
wl_list_init(&seat->base_resource_list);
wl_signal_init(&seat->selection_signal);
wl_list_init(&seat->drag_resource_list);
wl_signal_init(&seat->drag_icon_signal);
}
EAPI void
wl_seat_release(struct wl_seat *seat)
{
/* if (seat->pointer) */
/* { */
/* if (seat->pointer->focus) */
/* wl_list_remove(&seat->pointer->focus_listener.link); */
/* } */
/* if (seat->keyboard) */
/* { */
/* if (seat->keyboard->focus) */
/* wl_list_remove(&seat->keyboard->focus_listener.link); */
/* } */
/* if (seat->touch) */
/* { */
/* if (seat->touch->focus) */
/* wl_list_remove(&seat->touch->focus_listener.link); */
/* } */
wl_signal_emit(&seat->destroy_signal, seat);
}
EAPI void
wl_seat_set_pointer(struct wl_seat *seat, struct wl_pointer *pointer)
{
if (pointer && (seat->pointer || pointer->seat)) return; /* XXX: error? */
if (!pointer && !seat->pointer) return;
seat->pointer = pointer;
if (pointer) pointer->seat = seat;
_seat_send_updated_caps(seat);
}
EAPI void
wl_seat_set_keyboard(struct wl_seat *seat, struct wl_keyboard *keyboard)
{
if (keyboard && (seat->keyboard || keyboard->seat)) return; /* XXX: error? */
if (!keyboard && !seat->keyboard) return;
seat->keyboard = keyboard;
if (keyboard) keyboard->seat = seat;
_seat_send_updated_caps(seat);
}
EAPI void
wl_seat_set_touch(struct wl_seat *seat, struct wl_touch *touch)
{
if (touch && (seat->touch || touch->seat)) return; /* XXX: error? */
if (!touch && !seat->touch) return;
seat->touch = touch;
if (touch) touch->seat = seat;
_seat_send_updated_caps(seat);
}
EAPI void
wl_pointer_init(struct wl_pointer *pointer)
{
memset(pointer, 0, sizeof *pointer);
wl_list_init(&pointer->resource_list);
wl_list_init(&pointer->focus_resource_list);
pointer->default_grab.interface = &_e_pointer_grab_interface;
pointer->default_grab.pointer = pointer;
pointer->grab = &pointer->default_grab;
wl_signal_init(&pointer->focus_signal);
pointer->x = wl_fixed_from_int(100);
pointer->y = wl_fixed_from_int(100);
}
EAPI void
wl_pointer_set_focus(struct wl_pointer *pointer, struct wl_resource *surface, wl_fixed_t sx, wl_fixed_t sy)
{
struct wl_keyboard *kbd = pointer->seat->keyboard;
struct wl_resource *res;
struct wl_list *lst;
uint32_t serial;
lst = &pointer->focus_resource_list;
if ((!wl_list_empty(lst)) && (pointer->focus != surface))
{
serial = wl_display_next_serial(_e_wl_comp->wl.display);
wl_resource_for_each(res, lst)
wl_pointer_send_leave(res, serial, pointer->focus);
_move_resources(&pointer->resource_list, lst);
}
if ((_find_resource_for_surface(&pointer->resource_list, surface)) &&
(pointer->focus != surface))
{
struct wl_client *client;
client = wl_resource_get_client(surface);
_move_resources_for_client(lst, &pointer->resource_list, client);
wl_resource_for_each(res, lst)
wl_pointer_send_enter(res, serial, surface, sx, sy);
pointer->focus_serial = serial;
}
if ((kbd) && (surface) && (kbd->focus != pointer->focus))
{
struct wl_client *client;
client = wl_resource_get_client(surface);
wl_resource_for_each(res, &kbd->resource_list)
{
if (wl_resource_get_client(res) == client)
wl_keyboard_send_modifiers(res, serial,
kbd->modifiers.mods_depressed,
kbd->modifiers.mods_latched,
kbd->modifiers.mods_locked,
kbd->modifiers.group);
}
}
pointer->focus = surface;
pointer->default_grab.focus = surface;
wl_signal_emit(&pointer->focus_signal, pointer);
}
EAPI void
wl_pointer_start_grab(struct wl_pointer *pointer, struct wl_pointer_grab *grab)
{
const struct wl_pointer_grab_interface *interface;
pointer->grab = grab;
interface = pointer->grab->interface;
grab->pointer = pointer;
if (pointer->current)
interface->focus(pointer->grab, pointer->current,
pointer->current_x, pointer->current_y);
}
EAPI void
wl_pointer_end_grab(struct wl_pointer *pointer)
{
const struct wl_pointer_grab_interface *interface;
pointer->grab = &pointer->default_grab;
interface = pointer->grab->interface;
interface->focus(pointer->grab, pointer->current,
pointer->current_x, pointer->current_y);
}
EAPI void
wl_keyboard_init(struct wl_keyboard *keyboard)
{
memset(keyboard, 0, sizeof *keyboard);
wl_list_init(&keyboard->resource_list);
wl_array_init(&keyboard->keys);
wl_list_init(&keyboard->focus_resource_list);
keyboard->default_grab.interface = &_e_default_keyboard_grab_interface;
keyboard->default_grab.keyboard = keyboard;
keyboard->grab = &keyboard->default_grab;
wl_signal_init(&keyboard->focus_signal);
}
EAPI void
wl_keyboard_set_focus(struct wl_keyboard *keyboard, struct wl_resource *surface)
{
struct wl_resource *res;
struct wl_list *lst;
uint32_t serial;
lst = &keyboard->focus_resource_list;
if ((!wl_list_empty(lst)) && (keyboard->focus != surface))
{
serial = wl_display_next_serial(_e_wl_comp->wl.display);
wl_resource_for_each(res, lst)
wl_keyboard_send_leave(res, serial, keyboard->focus);
_move_resources(&keyboard->resource_list, lst);
}
if ((_find_resource_for_surface(&keyboard->resource_list, surface)) &&
(keyboard->focus != surface))
{
struct wl_client *client;
client = wl_resource_get_client(surface);
serial = wl_display_next_serial(_e_wl_comp->wl.display);
_move_resources_for_client(lst, &keyboard->resource_list, client);
wl_resource_for_each(res, lst)
{
wl_keyboard_send_modifiers(res, serial,
keyboard->modifiers.mods_depressed,
keyboard->modifiers.mods_latched,
keyboard->modifiers.mods_locked,
keyboard->modifiers.group);
wl_keyboard_send_enter(res, serial, surface, &keyboard->keys);
}
keyboard->focus_serial = serial;
}
keyboard->focus = surface;
wl_signal_emit(&keyboard->focus_signal, keyboard);
}
EAPI void
wl_keyboard_start_grab(struct wl_keyboard *device, struct wl_keyboard_grab *grab)
{
device->grab = grab;
grab->keyboard = device;
}
EAPI void
wl_keyboard_end_grab(struct wl_keyboard *keyboard)
{
keyboard->grab = &keyboard->default_grab;
}
EAPI void
wl_touch_init(struct wl_touch *touch)
{
memset(touch, 0, sizeof *touch);
wl_list_init(&touch->resource_list);
wl_list_init(&touch->focus_resource_list);
touch->default_grab.interface = &_e_default_touch_grab_interface;
touch->default_grab.touch = touch;
touch->grab = &touch->default_grab;
wl_signal_init(&touch->focus_signal);
}
EAPI void
wl_touch_start_grab(struct wl_touch *device, struct wl_touch_grab *grab)
{
device->grab = grab;
grab->touch = device;
}
EAPI void
wl_touch_end_grab(struct wl_touch *touch)
{
touch->grab = &touch->default_grab;
}
EAPI void
wl_data_device_set_keyboard_focus(struct wl_seat *seat)
{
struct wl_resource *data_device, *focus, *offer;
struct wl_data_source *source;
if (!seat->keyboard) return;
focus = seat->keyboard->focus;
if (!focus) return;
data_device =
wl_resource_find_for_client(&seat->drag_resource_list,
wl_resource_get_client(focus));
if (!data_device) return;
source = seat->selection_data_source;
if (source)
{
offer = wl_data_source_send_offer(source, data_device);
wl_data_device_send_selection(data_device, offer);
}
}
EAPI int
wl_data_device_manager_init(struct wl_display *display)
{
if (!wl_global_create(display, &wl_data_device_manager_interface, 1,
NULL, _bind_manager))
return -1;
return 0;
}
EAPI struct wl_resource *
wl_data_source_send_offer(struct wl_data_source *source, struct wl_resource *target)
{
struct wl_data_offer *offer;
char **p;
offer = malloc(sizeof *offer);
if (offer == NULL) return NULL;
offer->resource =
wl_resource_create(wl_resource_get_client(target),
&wl_data_offer_interface, 1, 0);
if (!offer->resource)
{
free(offer);
return NULL;
}
wl_resource_set_implementation(offer->resource, &_e_data_offer_interface,
offer, _destroy_data_offer);
offer->source = source;
offer->source_destroy_listener.notify = _destroy_offer_data_source;
wl_signal_add(&source->destroy_signal,
&offer->source_destroy_listener);
wl_data_device_send_data_offer(target, offer->resource);
wl_array_for_each(p, &source->mime_types)
wl_data_offer_send_offer(offer->resource, *p);
return offer->resource;
}
EAPI void
wl_seat_set_selection(struct wl_seat *seat, struct wl_data_source *source, uint32_t serial)
{
struct wl_resource *data_device, *offer;
struct wl_resource *focus = NULL;
if (seat->selection_data_source &&
seat->selection_serial - serial < UINT32_MAX / 2)
return;
if (seat->selection_data_source)
{
seat->selection_data_source->cancel(seat->selection_data_source);
wl_list_remove(&seat->selection_data_source_listener.link);
seat->selection_data_source = NULL;
}
seat->selection_data_source = source;
seat->selection_serial = serial;
if (seat->keyboard)
focus = seat->keyboard->focus;
if (focus)
{
data_device =
wl_resource_find_for_client(&seat->drag_resource_list,
wl_resource_get_client(focus));
if (data_device && source)
{
offer = wl_data_source_send_offer(seat->selection_data_source,
data_device);
wl_data_device_send_selection(data_device, offer);
}
else if (data_device)
{
wl_data_device_send_selection(data_device, NULL);
}
}
wl_signal_emit(&seat->selection_signal, seat);
if (source)
{
seat->selection_data_source_listener.notify =
_destroy_selection_data_source;
wl_signal_add(&source->destroy_signal,
&seat->selection_data_source_listener);
}
}
EAPI unsigned int
e_comp_wl_time_get(void)
{
struct timeval tm;
gettimeofday(&tm, NULL);
return (tm.tv_sec * 1000 + tm.tv_usec / 1000);
}
EAPI void
e_comp_wl_mouse_button(struct wl_resource *resource, uint32_t serial, uint32_t timestamp, uint32_t button, uint32_t state_w)
{
switch (button)
{
case BTN_LEFT:
case BTN_MIDDLE:
case BTN_RIGHT:
wl_pointer_send_button(resource, serial, timestamp,
button, state_w);
break;
case 4:
if (state_w)
wl_pointer_send_axis(resource, timestamp,
WL_POINTER_AXIS_VERTICAL_SCROLL,
-wl_fixed_from_int(1));
break;
case 5:
if (state_w)
wl_pointer_send_axis(resource, timestamp,
WL_POINTER_AXIS_VERTICAL_SCROLL,
wl_fixed_from_int(1));
break;
case 6:
if (state_w)
wl_pointer_send_axis(resource, timestamp,
WL_POINTER_AXIS_HORIZONTAL_SCROLL,
-wl_fixed_from_int(1));
break;
case 7:
if (state_w)
wl_pointer_send_axis(resource, timestamp,
WL_POINTER_AXIS_HORIZONTAL_SCROLL,
wl_fixed_from_int(1));
break;
}
}
EAPI void
e_comp_wl_input_modifiers_update(unsigned int serial)
{
struct wl_keyboard *kbd;
struct wl_keyboard_grab *grab;
unsigned int pressed = 0, latched = 0, locked = 0, group = 0;
Eina_Bool changed = EINA_FALSE;
/* check for valid keyboard */
if (!(kbd = _e_wl_comp->input->wl.seat.keyboard))
return;
/* try to get the current keyboard's grab interface.
* Fallback to the default grab */
if (!(grab = kbd->grab)) grab = &kbd->default_grab;
pressed = xkb_state_serialize_mods(_e_wl_comp->input->xkb.state,
XKB_STATE_DEPRESSED);
latched = xkb_state_serialize_mods(_e_wl_comp->input->xkb.state,
XKB_STATE_LATCHED);
locked = xkb_state_serialize_mods(_e_wl_comp->input->xkb.state,
XKB_STATE_LOCKED);
group = xkb_state_serialize_group(_e_wl_comp->input->xkb.state,
XKB_STATE_EFFECTIVE);
if ((pressed != kbd->modifiers.mods_depressed) ||
(latched != kbd->modifiers.mods_latched) ||
(locked != kbd->modifiers.mods_locked) ||
(group != kbd->modifiers.group))
changed = EINA_TRUE;
kbd->modifiers.mods_depressed = pressed;
kbd->modifiers.mods_latched = latched;
kbd->modifiers.mods_locked = locked;
kbd->modifiers.group = group;
/* TODO: update leds ? */
if (changed)
grab->interface->modifiers(grab, serial,
kbd->modifiers.mods_depressed,
kbd->modifiers.mods_latched,
kbd->modifiers.mods_locked,
kbd->modifiers.group);
}
/* local functions */
static void
_seat_send_updated_caps(struct wl_seat *seat)
{
struct wl_resource *res;
enum wl_seat_capability caps = 0;
if (seat->pointer)
caps |= WL_SEAT_CAPABILITY_POINTER;
if (seat->keyboard)
caps |= WL_SEAT_CAPABILITY_KEYBOARD;
if (seat->touch)
caps |= WL_SEAT_CAPABILITY_TOUCH;
wl_resource_for_each(res, &seat->base_resource_list)
wl_seat_send_capabilities(res, caps);
}
static void
_move_resources(struct wl_list *dest, struct wl_list *src)
{
wl_list_insert_list(dest, src);
wl_list_init(src);
}
static void
_move_resources_for_client(struct wl_list *dest, struct wl_list *src, struct wl_client *client)
{
struct wl_resource *res, *tmp;
wl_resource_for_each_safe(res, tmp, src)
{
if (wl_resource_get_client(res) == client)
{
wl_list_remove(wl_resource_get_link(res));
wl_list_insert(dest, wl_resource_get_link(res));
}
}
}
static struct wl_resource *
_find_resource_for_surface(struct wl_list *list, struct wl_resource *surface)
{
if (!surface) return NULL;
return wl_resource_find_for_client(list, wl_resource_get_client(surface));
}
static void
_default_grab_focus(struct wl_pointer_grab *grab, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y)
{
struct wl_pointer *pointer = grab->pointer;
if (pointer->button_count > 0) return;
wl_pointer_set_focus(pointer, surface, x, y);
}
static void
_default_grab_motion(struct wl_pointer_grab *grab, uint32_t timestamp, wl_fixed_t x, wl_fixed_t y)
{
struct wl_list *lst;
struct wl_resource *res;
lst = &grab->pointer->focus_resource_list;
wl_resource_for_each(res, lst)
wl_pointer_send_motion(res, timestamp, x, y);
}
static void
_default_grab_button(struct wl_pointer_grab *grab, uint32_t timestamp, uint32_t button, uint32_t state_w)
{
struct wl_pointer *pointer = grab->pointer;
struct wl_list *lst;
struct wl_resource *res;
enum wl_pointer_button_state state = state_w;
lst = &pointer->focus_resource_list;
if (!wl_list_empty(lst))
{
uint32_t serial;
serial = wl_display_next_serial(_e_wl_comp->wl.display);
wl_resource_for_each(res, lst)
e_comp_wl_mouse_button(res, serial, timestamp, button, state_w);
}
}
static void
_default_grab_touch_down(struct wl_touch_grab *grab, uint32_t timestamp, int touch_id, wl_fixed_t sx, wl_fixed_t sy)
{
struct wl_resource *res;
struct wl_list *lst;
struct wl_touch *touch = grab->touch;
lst = &touch->focus_resource_list;
if (!wl_list_empty(lst) && (touch->focus))
{
uint32_t serial;
serial = wl_display_next_serial(_e_wl_comp->wl.display);
wl_resource_for_each(res, lst)
wl_touch_send_down(res, serial, timestamp,
touch->focus, touch_id, sx, sy);
}
}
static void
_default_grab_touch_up(struct wl_touch_grab *grab, uint32_t timestamp, int touch_id)
{
struct wl_resource *res;
struct wl_list *lst;
struct wl_touch *touch = grab->touch;
lst = &touch->focus_resource_list;
if (!wl_list_empty(lst) && (touch->focus))
{
uint32_t serial;
serial = wl_display_next_serial(_e_wl_comp->wl.display);
wl_resource_for_each(res, lst)
wl_touch_send_up(res, serial, timestamp, touch_id);
}
}
static void
_default_grab_touch_motion(struct wl_touch_grab *grab, uint32_t timestamp, int touch_id, wl_fixed_t sx, wl_fixed_t sy)
{
struct wl_resource *res;
struct wl_list *lst;
struct wl_touch *touch = grab->touch;
lst = &touch->focus_resource_list;
wl_resource_for_each(res, lst)
wl_touch_send_motion(res, timestamp, touch_id, sx, sy);
}
static void
_data_offer_accept(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t serial, const char *mime_type)
{
struct wl_data_offer *offer;
offer = wl_resource_get_user_data(resource);
if (offer->source)
offer->source->accept(offer->source, serial, mime_type);
}
static void
_data_offer_receive(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *mime_type, int32_t fd)
{
struct wl_data_offer *offer;
offer = wl_resource_get_user_data(resource);
if (offer->source)
offer->source->send(offer->source, mime_type, fd);
else
close(fd);
}
static void
_data_offer_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static void
_destroy_data_offer(struct wl_resource *resource)
{
struct wl_data_offer *offer;
offer = wl_resource_get_user_data(resource);
if (offer->source)
wl_list_remove(&offer->source_destroy_listener.link);
free(offer);
}
static void
_destroy_offer_data_source(struct wl_listener *listener, void *data EINA_UNUSED)
{
struct wl_data_offer *offer;
offer = container_of(listener, struct wl_data_offer,
source_destroy_listener);
offer->source = NULL;
}
static void
_create_data_source(struct wl_client *client, struct wl_resource *resource, uint32_t id)
{
struct wl_data_source *source;
source = malloc(sizeof *source);
if (source == NULL)
{
wl_resource_post_no_memory(resource);
return;
}
wl_signal_init(&source->destroy_signal);
source->accept = _client_source_accept;
source->send = _client_source_send;
source->cancel = _client_source_cancel;
wl_array_init(&source->mime_types);
source->resource =
wl_resource_create(client, &wl_data_source_interface, 1, id);
wl_resource_set_implementation(source->resource,
&_e_data_source_interface, source,
_destroy_data_source);
}
static void
_unbind_data_device(struct wl_resource *resource)
{
wl_list_remove(wl_resource_get_link(resource));
}
static void
_get_data_device(struct wl_client *client, struct wl_resource *manager_resource, uint32_t id, struct wl_resource *seat_resource)
{
struct wl_seat *seat;
struct wl_resource *resource;
seat = wl_resource_get_user_data(seat_resource);
resource =
wl_resource_create(client, &wl_data_device_interface, 1, id);
if (!resource)
{
wl_resource_post_no_memory(manager_resource);
return;
}
wl_list_insert(&seat->drag_resource_list, wl_resource_get_link(resource));
wl_resource_set_implementation(resource, &_e_data_device_interface, seat,
_unbind_data_device);
}
static void
_current_surface_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
{
struct wl_pointer *pointer =
container_of(listener, struct wl_pointer, current_listener);
pointer->current = NULL;
}
static void
_bind_manager(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
{
struct wl_resource *res;
res = wl_resource_create(client, &wl_data_device_manager_interface, 1, id);
if (!res)
{
wl_client_post_no_memory(client);
return;
}
wl_resource_set_implementation(res, &_e_manager_interface, NULL, NULL);
}
static void
_default_grab_key(struct wl_keyboard_grab *grab, uint32_t timestamp, uint32_t key, uint32_t state)
{
struct wl_keyboard *keyboard = grab->keyboard;
struct wl_resource *res;
struct wl_list *lst;
lst = &keyboard->focus_resource_list;
if (!wl_list_empty(lst))
{
uint32_t serial;
serial = wl_display_next_serial(_e_wl_comp->wl.display);
wl_resource_for_each(res, lst)
wl_keyboard_send_key(res, serial, timestamp, key, state);
}
}
static void
_default_grab_modifiers(struct wl_keyboard_grab *grab, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
{
struct wl_keyboard *keyboard = grab->keyboard;
struct wl_pointer *pointer = keyboard->seat->pointer;
struct wl_resource *res;
struct wl_list *lst;
lst = &keyboard->focus_resource_list;
wl_resource_for_each(res, lst)
wl_keyboard_send_modifiers(res, serial, mods_depressed, mods_latched,
mods_locked, group);
if (pointer && pointer->focus && pointer->focus != keyboard->focus)
{
struct wl_client *client;
lst = &keyboard->resource_list;
client = wl_resource_get_client(pointer->focus);
wl_resource_for_each(res, lst)
{
if (wl_resource_get_client(res) == client)
wl_keyboard_send_modifiers(res, serial, mods_depressed,
mods_latched, mods_locked, group);
}
}
}
static void
_data_device_start_drag(struct wl_client *client, struct wl_resource *resource, struct wl_resource *source_resource, struct wl_resource *origin_resource, struct wl_resource *icon_resource, uint32_t serial EINA_UNUSED)
{
struct wl_seat *seat;
seat = wl_resource_get_user_data(resource);
if ((seat->pointer->button_count == 0) ||
(seat->pointer->grab_serial != serial) ||
(seat->pointer->focus != wl_resource_get_user_data(origin_resource)))
return;
seat->drag_grab.interface = &_e_drag_grab_interface;
seat->drag_client = client;
seat->drag_data_source = NULL;
if (source_resource)
{
struct wl_data_source *source;
source = wl_resource_get_user_data(source_resource);
seat->drag_data_source = source;
seat->drag_data_source_listener.notify =
_destroy_data_device_source;
wl_signal_add(&source->destroy_signal,
&seat->drag_data_source_listener);
}
if (icon_resource)
{
E_Wayland_Surface *icon;
icon = wl_resource_get_user_data(icon_resource);
seat->drag_surface = icon->wl.surface;
seat->drag_icon_listener.notify = _destroy_data_device_icon;
wl_signal_add(&icon->wl.destroy_signal,
&seat->drag_icon_listener);
/* wl_signal_emit(&seat->drag_icon_signal, icon_resource); */
}
wl_pointer_set_focus(seat->pointer, NULL,
wl_fixed_from_int(0), wl_fixed_from_int(0));
wl_pointer_start_grab(seat->pointer, &seat->drag_grab);
}
static void
_data_device_set_selection(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *source_resource, uint32_t serial)
{
struct wl_data_source *source;
struct wl_seat *seat;
if (!(seat = wl_resource_get_user_data(resource))) return;
source = wl_resource_get_user_data(source_resource);
wl_seat_set_selection(seat, source, serial);
}
static void
_destroy_data_device_icon(struct wl_listener *listener, void *data EINA_UNUSED)
{
struct wl_seat *seat =
container_of(listener, struct wl_seat, drag_icon_listener);
seat->drag_surface = NULL;
}
static void
_destroy_selection_data_source(struct wl_listener *listener, void *data EINA_UNUSED)
{
struct wl_seat *seat =
container_of(listener, struct wl_seat, selection_data_source_listener);
struct wl_resource *data_device;
struct wl_resource *focus = NULL;
seat->selection_data_source = NULL;
if (seat->keyboard)
focus = seat->keyboard->focus;
if (focus)
{
data_device =
wl_resource_find_for_client(&seat->drag_resource_list,
wl_resource_get_client(focus));
if (data_device)
wl_data_device_send_selection(data_device, NULL);
}
wl_signal_emit(&seat->selection_signal, seat);
}
static void
_destroy_data_device_source(struct wl_listener *listener, void *data EINA_UNUSED)
{
struct wl_seat *seat =
container_of(listener, struct wl_seat, drag_data_source_listener);
_data_device_end_drag_grab(seat);
}
static void
_data_source_offer(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, const char *type)
{
struct wl_data_source *source;
char **p;
source = wl_resource_get_user_data(resource);
p = wl_array_add(&source->mime_types, sizeof *p);
if (p) *p = strdup(type);
if (!p || !*p) wl_resource_post_no_memory(resource);
}
static void
_data_source_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static void
_destroy_data_source(struct wl_resource *resource)
{
struct wl_data_source *source;
char **p;
source = wl_resource_get_user_data(resource);
wl_signal_emit(&source->destroy_signal, source);
wl_array_for_each(p, &source->mime_types)
free(*p);
wl_array_release(&source->mime_types);
source->resource = NULL;
}
static void
_data_device_end_drag_grab(struct wl_seat *seat)
{
if (seat->drag_surface)
{
seat->drag_surface = NULL;
wl_signal_emit(&seat->drag_icon_signal, NULL);
wl_list_remove(&seat->drag_icon_listener.link);
}
_drag_grab_focus(&seat->drag_grab, NULL,
wl_fixed_from_int(0), wl_fixed_from_int(0));
wl_pointer_end_grab(seat->pointer);
seat->drag_data_source = NULL;
seat->drag_client = NULL;
}
static void
_drag_grab_button(struct wl_pointer_grab *grab, uint32_t timestamp EINA_UNUSED, uint32_t button, uint32_t state_w)
{
struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
enum wl_pointer_button_state state = state_w;
if (seat->drag_focus_resource &&
seat->pointer->grab_button == button &&
state == WL_POINTER_BUTTON_STATE_RELEASED)
wl_data_device_send_drop(seat->drag_focus_resource);
if (seat->pointer->button_count == 0 &&
state == WL_POINTER_BUTTON_STATE_RELEASED)
{
if (seat->drag_data_source)
wl_list_remove(&seat->drag_data_source_listener.link);
_data_device_end_drag_grab(seat);
}
}
static void
_drag_grab_motion(struct wl_pointer_grab *grab, uint32_t timestamp, wl_fixed_t x, wl_fixed_t y)
{
struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
if (seat->drag_focus_resource)
wl_data_device_send_motion(seat->drag_focus_resource,
timestamp, x, y);
}
static void
_destroy_drag_focus(struct wl_listener *listener, void *data EINA_UNUSED)
{
struct wl_seat *seat =
container_of(listener, struct wl_seat, drag_focus_listener);
seat->drag_focus_resource = NULL;
}
static void
_drag_grab_focus(struct wl_pointer_grab *grab, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y)
{
struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
struct wl_resource *resource, *offer = NULL;
struct wl_display *display;
uint32_t serial;
E_Wayland_Surface *ews;
if (seat->drag_focus_resource)
{
wl_data_device_send_leave(seat->drag_focus_resource);
wl_list_remove(&seat->drag_focus_listener.link);
seat->drag_focus_resource = NULL;
seat->drag_focus = NULL;
}
if (!surface) return;
if (!seat->drag_data_source &&
wl_resource_get_client(surface) != seat->drag_client)
return;
resource =
wl_resource_find_for_client(&seat->drag_resource_list,
wl_resource_get_client(surface));
if (!resource) return;
display = wl_client_get_display(wl_resource_get_client(resource));
serial = wl_display_next_serial(display);
if (seat->drag_data_source)
offer = wl_data_source_send_offer(seat->drag_data_source,
resource);
wl_data_device_send_enter(resource, serial, surface, x, y, offer);
ews = wl_resource_get_user_data(surface);
seat->drag_focus = surface;
seat->drag_focus_listener.notify = _destroy_drag_focus;
wl_signal_add(&ews->wl.destroy_signal, &seat->drag_focus_listener);
seat->drag_focus_resource = resource;
grab->focus = surface;
}
static void
_client_source_accept(struct wl_data_source *source, uint32_t timestamp EINA_UNUSED, const char *mime_type)
{
wl_data_source_send_target(source->resource, mime_type);
}
static void
_client_source_send(struct wl_data_source *source, const char *mime_type, int32_t fd)
{
wl_data_source_send_send(source->resource, mime_type, fd);
close(fd);
}
static void
_client_source_cancel(struct wl_data_source *source)
{
wl_data_source_send_cancelled(source->resource);
}
static void
_e_comp_wl_cb_bind(struct wl_client *client, void *data, unsigned int version, unsigned int id)
{
E_Wayland_Compositor *comp;
struct wl_resource *res;
if (!(comp = data)) return;
res =
wl_resource_create(client, &wl_compositor_interface, MIN(version, 3), id);
if (res)
wl_resource_set_implementation(res, &_e_compositor_interface, comp, NULL);
}
static Eina_Bool
_e_comp_wl_cb_read(void *data EINA_UNUSED, Ecore_Fd_Handler *hdl EINA_UNUSED)
{
/* flush any events before we sleep */
wl_display_flush_clients(_e_wl_comp->wl.display);
wl_event_loop_dispatch(_e_wl_comp->wl.loop, 0);
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_comp_wl_cb_idle(void *data EINA_UNUSED)
{
if ((_e_wl_comp) && (_e_wl_comp->wl.display))
{
/* flush any clients before we idle */
wl_display_flush_clients(_e_wl_comp->wl.display);
}
return ECORE_CALLBACK_RENEW;
}
static Eina_Bool
_e_comp_wl_cb_module_idle(void *data EINA_UNUSED)
{
E_Module *mod = NULL;
/* if we are still in the process of loading modules, then we will wait */
if (e_module_loading_get()) return ECORE_CALLBACK_RENEW;
/* try to find the shell module, and create it if not found
*
* TODO: we should have a config variable somewhere to store which
* shell we want to load (tablet, mobile, etc) */
if (!(mod = e_module_find("wl_desktop_shell")))
mod = e_module_new("wl_desktop_shell");
/* if we have the module now, load it */
if (mod)
{
e_module_enable(mod);
_module_idler = NULL;
/* flush any pending events
*
* NB: This advertises out any globals so it needs to be deferred
* until after the shell has been loaded */
wl_event_loop_dispatch(_e_wl_comp->wl.loop, 0);
return ECORE_CALLBACK_CANCEL;
}
return ECORE_CALLBACK_RENEW;
}
EAPI Eina_Bool
e_comp_wl_cb_keymap_changed(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
{
struct xkb_keymap *keymap;
/* try to fetch the keymap */
if (!(keymap = _e_comp_wl_input_keymap_get()))
return ECORE_CALLBACK_PASS_ON;
/* destroy keyboard */
if (_e_wl_comp->input->xkb.info)
{
/* if we have a keymap, unreference it */
if (_e_wl_comp->input->xkb.info->keymap)
xkb_map_unref(_e_wl_comp->input->xkb.info->keymap);
/* if we have a keymap mmap'd area, unmap it */
if (_e_wl_comp->input->xkb.info->area)
munmap(_e_wl_comp->input->xkb.info->area,
_e_wl_comp->input->xkb.info->size);
/* if we created an fd for keyboard input, close it */
if (_e_wl_comp->input->xkb.info->fd)
close(_e_wl_comp->input->xkb.info->fd);
/* free the allocated keyboard info structure */
E_FREE(_e_wl_comp->input->xkb.info);
}
/* unreference the xkb state we created */
if (_e_wl_comp->input->xkb.state)
xkb_state_unref(_e_wl_comp->input->xkb.state);
/* unreference the xkb context we created */
if (_e_wl_comp->xkb.context)
xkb_context_unref(_e_wl_comp->xkb.context);
/* create the xkb context */
_e_wl_comp->xkb.context = xkb_context_new(0);
/* try to fetch the keymap */
// if ((keymap = _e_comp_wl_input_keymap_get()))
{
/* try to create new keyboard info */
_e_wl_comp->input->xkb.info =
_e_comp_wl_input_keyboard_info_get(keymap);
/* create new xkb state */
_e_wl_comp->input->xkb.state = xkb_state_new(keymap);
/* unreference the keymap */
xkb_map_unref(keymap);
}
/* check for valid keyboard */
if (!_e_wl_comp->input->wl.keyboard_resource)
return ECORE_CALLBACK_PASS_ON;
/* send the current keymap to the keyboard object */
wl_keyboard_send_keymap(_e_wl_comp->input->wl.keyboard_resource,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
_e_wl_comp->input->xkb.info->fd,
_e_wl_comp->input->xkb.info->size);
return ECORE_CALLBACK_PASS_ON;
}
/* compositor interface functions */
static void
_e_comp_wl_cb_surface_create(struct wl_client *client, struct wl_resource *resource, unsigned int id)
{
E_Wayland_Surface *ews = NULL;
uint64_t wid;
pid_t pid;
/* try to allocate space for a new surface */
if (!(ews = E_NEW(E_Wayland_Surface, 1)))
{
wl_resource_post_no_memory(resource);
return;
}
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
ews->wl.client = client;
wl_client_get_credentials(client, &pid, NULL, NULL);
wid = e_comp_wl_id_get(pid, id);
ews->pixmap = e_pixmap_find(E_PIXMAP_TYPE_WL, wid);
if (!ews->pixmap)
ews->pixmap = e_pixmap_new(E_PIXMAP_TYPE_WL, wid);
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
e_pixmap_parent_window_set(ews->pixmap, ews);
e_pixmap_usable_set(ews->pixmap, 1);
/* initialize the destroy signal */
wl_signal_init(&ews->wl.destroy_signal);
/* initialize the link */
wl_list_init(&ews->wl.link);
/* initialize the lists of frames */
wl_list_init(&ews->wl.frames);
wl_list_init(&ews->pending.frames);
ews->wl.surface = NULL;
/* set destroy function for pending buffers */
ews->pending.buffer_destroy.notify =
_e_comp_wl_surface_cb_pending_buffer_destroy;
/* initialize regions */
pixman_region32_init(&ews->region.opaque);
pixman_region32_init(&ews->region.damage);
pixman_region32_init(&ews->region.clip);
pixman_region32_init_rect(&ews->region.input, INT32_MIN, INT32_MIN,
UINT32_MAX, UINT32_MAX);
/* initialize pending regions */
pixman_region32_init(&ews->pending.opaque);
pixman_region32_init(&ews->pending.damage);
pixman_region32_init_rect(&ews->pending.input, INT32_MIN, INT32_MIN,
UINT32_MAX, UINT32_MAX);
ews->wl.surface =
wl_resource_create(client, &wl_surface_interface,
wl_resource_get_version(resource), id);
wl_resource_set_implementation(ews->wl.surface, &_e_surface_interface,
ews, _e_comp_wl_cb_surface_destroy);
/* add this surface to the list of surfaces */
2013-08-18 19:31:24 -07:00
_e_wl_comp->surfaces = eina_inlist_append(_e_wl_comp->surfaces, EINA_INLIST_GET(ews));
}
static void
_e_comp_wl_cb_surface_destroy(struct wl_resource *resource)
{
E_Wayland_Surface *ews = NULL;
E_Wayland_Surface_Frame_Callback *cb = NULL, *ncb = NULL;
struct wl_pointer *pointer;
Eina_Inlist *l;
E_Wayland_Buffer *buffer;
/* try to get the surface from this resource */
if (!(ews = wl_resource_get_user_data(resource)))
return;
pointer = &_e_wl_comp->input->wl.pointer;
if (pointer->focus == resource)
{
wl_pointer_set_focus(pointer, NULL,
wl_fixed_from_int(0), wl_fixed_from_int(0));
_e_wl_comp->input->pointer.surface = NULL;
}
/* if this surface is mapped, unmap it */
if (ews->mapped)
{
if (ews->unmap) ews->unmap(ews);
}
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
if (ews->buffer_reference.buffer)
ews->buffer_reference.buffer->ews = NULL;
if (ews->pending.buffer)
ews->pending.buffer->ews = NULL;
/* loop any pending surface frame callbacks and destroy them */
wl_list_for_each_safe(cb, ncb, &ews->pending.frames, wl.link)
wl_resource_destroy(cb->wl.resource);
/* clear any pending regions */
pixman_region32_fini(&ews->pending.damage);
pixman_region32_fini(&ews->pending.opaque);
pixman_region32_fini(&ews->pending.input);
/* remove the pending buffer from the list */
if (ews->pending.buffer)
wl_list_remove(&ews->pending.buffer_destroy.link);
/* dereference any existing buffers */
_e_comp_wl_surface_buffer_reference(&ews->buffer_reference, NULL);
/* clear any active regions */
pixman_region32_fini(&ews->region.damage);
pixman_region32_fini(&ews->region.opaque);
pixman_region32_fini(&ews->region.input);
pixman_region32_fini(&ews->region.clip);
/* loop any active surface frame callbacks and destroy them */
wl_list_for_each_safe(cb, ncb, &ews->wl.frames, wl.link)
wl_resource_destroy(cb->wl.resource);
EINA_INLIST_FOREACH_SAFE(ews->buffers, l, buffer)
{
buffer->ews = NULL;
ews->buffers = eina_inlist_remove(ews->buffers, EINA_INLIST_GET(buffer));
}
if (e_comp_get(NULL)->pointer->pixmap == ews->pixmap)
{
e_pointer_image_set(e_comp_get(NULL)->pointer, NULL, 0, 0, 0, 0);
}
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
e_pixmap_parent_window_set(ews->pixmap, NULL);
e_pixmap_free(ews->pixmap);
/* remove this surface from the compositor's list of surfaces */
2013-08-18 19:31:24 -07:00
_e_wl_comp->surfaces = eina_inlist_remove(_e_wl_comp->surfaces, EINA_INLIST_GET(ews));
/* free the allocated surface structure */
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
free(ews);
}
static void
_e_comp_wl_cb_region_create(struct wl_client *client, struct wl_resource *resource, unsigned int id)
{
E_Wayland_Region *ewr = NULL;
/* try to allocate space for a new region */
if (!(ewr = E_NEW_RAW(E_Wayland_Region, 1)))
{
wl_resource_post_no_memory(resource);
return;
}
pixman_region32_init(&ewr->region);
ewr->wl.resource =
wl_resource_create(client, &wl_region_interface,
wl_resource_get_version(resource), id);
wl_resource_set_implementation(ewr->wl.resource, &_e_region_interface, ewr,
_e_comp_wl_cb_region_destroy);
}
static void
_e_comp_wl_cb_region_destroy(struct wl_resource *resource)
{
E_Wayland_Region *ewr = NULL;
/* try to get the region from this resource */
if (!(ewr = wl_resource_get_user_data(resource)))
return;
/* tell pixman we are finished with this region */
pixman_region32_fini(&ewr->region);
/* free the allocated region structure */
E_FREE(ewr);
}
/* input functions */
static Eina_Bool
_e_comp_wl_input_init(void)
{
struct xkb_keymap *keymap;
/* try to allocate space for a new compositor */
if (!(_e_wl_comp->input = E_NEW(E_Wayland_Input, 1)))
return EINA_FALSE;
/* initialize the seat */
wl_seat_init(&_e_wl_comp->input->wl.seat);
/* try to add this input to the diplay's list of globals */
if (!wl_global_create(_e_wl_comp->wl.display, &wl_seat_interface, 2,
_e_wl_comp->input, _e_comp_wl_input_cb_bind))
{
ERR("Could not add Input to Wayland Display Globals: %m");
goto err;
}
_e_wl_comp->input->pointer.surface = NULL;
_e_wl_comp->input->pointer.surface_destroy.notify =
_e_comp_wl_pointer_cb_destroy;
_e_wl_comp->input->pointer.hot.x = 16;
_e_wl_comp->input->pointer.hot.y = 16;
/* initialize wayland pointer */
wl_pointer_init(&_e_wl_comp->input->wl.pointer);
/* tell the seat about this pointer */
wl_seat_set_pointer(&_e_wl_comp->input->wl.seat,
&_e_wl_comp->input->wl.pointer);
/* set flag to indicate we have a pointer */
_e_wl_comp->input->has_pointer = EINA_TRUE;
/* create the xkb context */
_e_wl_comp->xkb.context = xkb_context_new(0);
/* try to fetch the keymap */
if ((keymap = _e_comp_wl_input_keymap_get()))
{
/* try to create new keyboard info */
_e_wl_comp->input->xkb.info =
_e_comp_wl_input_keyboard_info_get(keymap);
/* create new xkb state */
_e_wl_comp->input->xkb.state = xkb_state_new(keymap);
/* unreference the keymap */
xkb_map_unref(keymap);
}
/* initialize the keyboard */
wl_keyboard_init(&_e_wl_comp->input->wl.keyboard);
/* tell the seat about this keyboard */
wl_seat_set_keyboard(&_e_wl_comp->input->wl.seat,
&_e_wl_comp->input->wl.keyboard);
/* set flag to indicate we have a keyboard */
_e_wl_comp->input->has_keyboard = EINA_TRUE;
wl_list_init(&_e_wl_comp->input->wl.link);
/* append this input to the list */
_e_wl_comp->seats = eina_list_append(_e_wl_comp->seats, _e_wl_comp->input);
/* emit a signal saying that input has been initialized */
wl_signal_emit(&_e_wl_comp->signals.seat, _e_wl_comp->input);
/* return success */
return EINA_TRUE;
err:
/* release the wl_seat */
wl_seat_release(&_e_wl_comp->input->wl.seat);
/* free the allocated input structure */
E_FREE(_e_wl_comp->input);
/* return failure */
return EINA_FALSE;
}
static void
_e_comp_wl_input_shutdown(void)
{
/* safety check */
if (!_e_wl_comp->input) return;
/* destroy keyboard */
if (_e_wl_comp->input->xkb.info)
{
/* if we have a keymap, unreference it */
if (_e_wl_comp->input->xkb.info->keymap)
xkb_map_unref(_e_wl_comp->input->xkb.info->keymap);
/* if we have a keymap mmap'd area, unmap it */
if (_e_wl_comp->input->xkb.info->area)
munmap(_e_wl_comp->input->xkb.info->area,
_e_wl_comp->input->xkb.info->size);
/* if we created an fd for keyboard input, close it */
if (_e_wl_comp->input->xkb.info->fd)
close(_e_wl_comp->input->xkb.info->fd);
/* free the allocated keyboard info structure */
E_FREE(_e_wl_comp->input->xkb.info);
}
/* unreference the xkb state we created */
if (_e_wl_comp->input->xkb.state)
xkb_state_unref(_e_wl_comp->input->xkb.state);
/* unreference the xkb context we created */
if (_e_wl_comp->xkb.context)
xkb_context_unref(_e_wl_comp->xkb.context);
/* TODO: destroy pointer surface
*
* NB: Currently, we do not create one */
wl_list_remove(&_e_wl_comp->input->wl.link);
/* release the seat */
wl_seat_release(&_e_wl_comp->input->wl.seat);
/* free the allocated input structure */
E_FREE(_e_wl_comp->input);
}
static void
_e_comp_wl_input_cb_bind(struct wl_client *client, void *data, unsigned int version, unsigned int id)
{
struct wl_seat *seat = NULL;
struct wl_resource *resource = NULL;
enum wl_seat_capability caps = 0;
/* try to cast data to our seat */
if (!(seat = data)) return;
/* add the seat object to the client */
resource =
wl_resource_create(client, &wl_seat_interface, MIN(version, 2), id);
wl_list_insert(&seat->base_resource_list, wl_resource_get_link(resource));
wl_resource_set_implementation(resource, &_e_input_interface, data,
_e_comp_wl_input_cb_unbind);
/* set capabilities based on seat */
if (seat->pointer) caps |= WL_SEAT_CAPABILITY_POINTER;
if (seat->keyboard) caps |= WL_SEAT_CAPABILITY_KEYBOARD;
if (seat->touch) caps |= WL_SEAT_CAPABILITY_TOUCH;
/* inform the resource about the seat capabilities */
wl_seat_send_capabilities(resource, caps);
}
static void
_e_comp_wl_input_cb_unbind(struct wl_resource *resource)
{
/* remove the link */
wl_list_remove(wl_resource_get_link(resource));
}
static struct xkb_keymap *
_e_comp_wl_input_keymap_get(void)
{
E_Config_XKB_Layout *kbd_layout;
struct xkb_keymap *keymap;
struct xkb_rule_names names;
memset(&names, 0, sizeof(names));
if ((kbd_layout = e_xkb_layout_get()))
{
names.model = strdup(kbd_layout->model);
names.layout = strdup(kbd_layout->name);
}
#ifndef WAYLAND_ONLY
/* if we are running under X11, try to get the xkb rule names atom */
if (getenv("DISPLAY"))
{
Ecore_X_Atom rules = 0;
Ecore_X_Window root = 0;
int len = 0;
unsigned char *data;
/* TODO: FIXME: NB:
*
* The below commented out code is for using the "already" configured
* E xkb settings in the wayland clients. The only Major problem with
* that is: That the E_Config_XKB_Layout does not define a
* 'RULES' which we need ....
*
*/
root = ecore_x_window_root_first_get();
rules = ecore_x_atom_get("_XKB_RULES_NAMES");
ecore_x_window_prop_property_get(root, rules, ECORE_X_ATOM_STRING,
1024, &data, &len);
if ((data) && (len > 0))
{
names.rules = (char*)data;
data += strlen((const char *)data) + 1;
if (!names.model)
names.model = strdup((const char *)data);
data += strlen((const char *)data) + 1;
if (!names.layout)
names.layout = strdup((const char *)data);
}
}
#endif
printf("Keymap\n");
printf("\tRules: %s\n", names.rules);
printf("\tModel: %s\n", names.model);
printf("\tLayout: %s\n", names.layout);
keymap = xkb_map_new_from_names(_e_wl_comp->xkb.context, &names, 0);
free((char *)names.rules);
free((char *)names.model);
free((char *)names.layout);
return keymap;
}
static int
_e_comp_wl_input_keymap_fd_get(off_t size)
{
char tmp[PATH_MAX];
const char *path;
int fd = 0;
long flags;
if (!(path = getenv("XDG_RUNTIME_DIR")))
return -1;
strcpy(tmp, path);
strcat(tmp, "/e-wl-keymap-XXXXXX");
if ((fd = mkstemp(tmp)) < 0)
return -1;
/* TODO: really should error check the returns here */
flags = fcntl(fd, F_GETFD);
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
if (ftruncate(fd, size) < 0)
{
close(fd);
return -1;
}
unlink(tmp);
return fd;
}
static E_Wayland_Keyboard_Info *
_e_comp_wl_input_keyboard_info_get(struct xkb_keymap *keymap)
{
E_Wayland_Keyboard_Info *info = NULL;
char *tmp;
/* try to allocate space for the keyboard info structure */
if (!(info = E_NEW(E_Wayland_Keyboard_Info, 1)))
return NULL;
if (!(info->keymap = xkb_map_ref(keymap)))
{
E_FREE(info);
return NULL;
}
/* init modifiers */
info->mod_shift = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_SHIFT);
info->mod_caps = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CAPS);
info->mod_ctrl = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_CTRL);
info->mod_alt = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_ALT);
info->mod_super = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_LOGO);
/* try to get a string of this keymap */
if (!(tmp = xkb_map_get_as_string(keymap)))
{
printf("Could not get keymap as string\n");
E_FREE(info);
return NULL;
}
info->size = strlen(tmp) + 1;
/* try to create an fd we can listen on for input */
info->fd = _e_comp_wl_input_keymap_fd_get(info->size);
if (info->fd < 0)
{
printf("Could not create keymap fd\n");
E_FREE(info);
return NULL;
}
info->area =
mmap(NULL, info->size, PROT_READ | PROT_WRITE, MAP_SHARED, info->fd, 0);
/* TODO: error check mmap */
if ((info->area) && (tmp))
{
strcpy(info->area, tmp);
free(tmp);
}
return info;
}
/* input interface functions */
static void
_e_comp_wl_input_cb_pointer_get(struct wl_client *client, struct wl_resource *resource, unsigned int id)
{
E_Wayland_Input *input = NULL;
struct wl_resource *ptr = NULL;
/* try to cast the resource data to our input structure */
if (!(input = wl_resource_get_user_data(resource)))
return;
/* check that input has a pointer */
if (!input->has_pointer) return;
/* add a pointer object to the client */
ptr = wl_resource_create(client, &wl_pointer_interface,
wl_resource_get_version(resource), id);
wl_list_insert(&input->wl.seat.pointer->resource_list,
wl_resource_get_link(ptr));
wl_resource_set_implementation(ptr, &_e_pointer_interface,
input, _e_comp_wl_input_cb_unbind);
/* if the pointer has a focused surface, set it */
if ((input->wl.seat.pointer->focus) &&
(wl_resource_get_client(input->wl.seat.pointer->focus) == client))
{
/* tell pointer which surface is focused */
wl_list_remove(wl_resource_get_link(ptr));
wl_list_insert(&input->wl.seat.pointer->focus_resource_list,
wl_resource_get_link(ptr));
wl_pointer_send_enter(ptr, input->wl.seat.pointer->focus_serial,
input->wl.seat.pointer->focus,
input->wl.seat.pointer->x,
input->wl.seat.pointer->y);
}
}
static void
_e_comp_wl_input_cb_keyboard_get(struct wl_client *client, struct wl_resource *resource, unsigned int id)
{
E_Wayland_Input *input = NULL;
struct wl_resource *kbd = NULL;
/* try to cast the resource data to our input structure */
if (!(input = wl_resource_get_user_data(resource)))
return;
/* check that input has a keyboard */
if (!input->has_keyboard) return;
/* add a keyboard object to the client */
kbd = wl_resource_create(client, &wl_keyboard_interface,
wl_resource_get_version(resource), id);
wl_list_insert(&input->wl.seat.keyboard->resource_list,
wl_resource_get_link(kbd));
wl_resource_set_implementation(kbd, &_e_keyboard_interface, input,
_e_comp_wl_input_cb_unbind);
/* send the current keymap to the keyboard object */
wl_keyboard_send_keymap(kbd, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
input->xkb.info->fd, input->xkb.info->size);
if (((input->wl.seat.keyboard) && (input->wl.seat.keyboard->focus) &&
(wl_resource_get_client(input->wl.seat.keyboard->focus) == client)) ||
((input->wl.seat.pointer) && (input->wl.seat.pointer->focus) &&
(wl_resource_get_client(input->wl.seat.pointer->focus) == client)))
{
wl_keyboard_send_modifiers(kbd, input->wl.seat.keyboard->focus_serial,
input->wl.seat.keyboard->modifiers.mods_depressed,
input->wl.seat.keyboard->modifiers.mods_latched,
input->wl.seat.keyboard->modifiers.mods_locked,
input->wl.seat.keyboard->modifiers.group);
}
/* test if keyboard has a focused client */
if ((input->wl.seat.keyboard->focus) &&
(wl_resource_get_client(input->wl.seat.keyboard->focus) == client))
{
wl_list_remove(wl_resource_get_link(kbd));
wl_list_insert(&input->wl.seat.keyboard->focus_resource_list,
wl_resource_get_link(kbd));
wl_keyboard_send_enter(kbd, input->wl.seat.keyboard->focus_serial,
input->wl.seat.keyboard->focus,
&input->wl.seat.keyboard->keys);
if (input->wl.seat.keyboard->focus_resource_list.prev ==
wl_resource_get_link(kbd))
{
/* update the keyboard focus in the data device */
wl_data_device_set_keyboard_focus(&input->wl.seat);
}
}
input->wl.keyboard_resource = kbd;
}
static void
_e_comp_wl_input_cb_touch_get(struct wl_client *client, struct wl_resource *resource, unsigned int id)
{
E_Wayland_Input *input = NULL;
struct wl_resource *tch = NULL;
/* try to cast the resource data to our input structure */
if (!(input = wl_resource_get_user_data(resource)))
return;
/* check that input has a touch */
if (!input->has_touch) return;
/* add a touch object to the client */
tch = wl_resource_create(client, &wl_touch_interface,
wl_resource_get_version(resource), id);
if ((input->wl.seat.touch->focus) &&
(wl_resource_get_client(input->wl.seat.touch->focus) == client))
{
wl_list_insert(&input->wl.seat.touch->resource_list,
wl_resource_get_link(tch));
}
else
wl_list_insert(&input->wl.seat.touch->focus_resource_list,
wl_resource_get_link(tch));
wl_resource_set_implementation(tch, &_e_touch_interface, input,
_e_comp_wl_input_cb_unbind);
}
/* pointer functions */
static void
_e_comp_wl_pointer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
{
E_Wayland_Input *input = NULL;
/* try to get the input from this listener */
if (!(input = container_of(listener, E_Wayland_Input, pointer.surface_destroy)))
return;
input->pointer.surface = NULL;
}
static void
_e_comp_wl_pointer_configure(E_Wayland_Surface *ews, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
{
E_Wayland_Input *input = NULL;
E_Wayland_Surface *focus = NULL;
/* safety check */
if (!ews) return;
/* see if this surface has 'input' */
if (!(input = ews->input)) return;
input->pointer.hot.x -= x;
input->pointer.hot.y -= y;
/* configure the surface geometry */
ews->geometry.x = x;
ews->geometry.h = h;
ews->geometry.w = w;
ews->geometry.h = h;
ews->geometry.changed = EINA_TRUE;
/* tell pixman we are finished with this region */
pixman_region32_fini(&ews->pending.input);
/* reinitalize the pending input region */
pixman_region32_init(&ews->pending.input);
/* do we have a focused surface ? */
if (!input->wl.seat.pointer->focus) return;
focus = wl_resource_get_user_data(input->wl.seat.pointer->focus);
if (!focus) return;
/* NB: Ideally, I wanted to use the e_pointer methods here so that
* the cursor would match the E theme, however Wayland currently
* provides NO Method to get the cursor name :( so we are stuck
* using the pixels from their cursor surface */
/* is it mapped ? */
if ((!focus->mapped) || (!focus->ec)) return;
e_pixmap_dirty(ews->pixmap);
e_pointer_image_set(focus->ec->comp->pointer, ews->pixmap, w, h, input->pointer.hot.x, input->pointer.hot.y);
}
static void
_e_comp_wl_pointer_unmap(E_Wayland_Surface *ews)
{
E_Wayland_Input *input = NULL;
/* safety check */
if (!ews) return;
if (!(input = ews->input)) return;
wl_list_remove(&input->pointer.surface_destroy.link);
if (input->pointer.surface)
input->pointer.surface->configure = NULL;
input->pointer.surface = NULL;
}
/* pointer interface functions */
static void
_e_comp_wl_pointer_cb_cursor_set(struct wl_client *client, struct wl_resource *resource, unsigned int serial, struct wl_resource *surface_resource, int x, int y)
{
E_Wayland_Input *input = NULL;
E_Wayland_Surface *ews = NULL;
/* try to cast the resource data to our input structure */
if (!(input = wl_resource_get_user_data(resource)))
return;
/* if we were passed in a surface, try to cast it to our structure */
if (surface_resource) ews = wl_resource_get_user_data(surface_resource);
/* if this input has no pointer, get out */
if (!input->has_pointer) return;
/* if the input has no current focus, get out */
if (!input->wl.seat.pointer->focus)
{
/* if we have an existing pointer surface, unmap it */
if (input->pointer.surface)
{
/* call the unmap function */
if (input->pointer.surface->unmap)
input->pointer.surface->unmap(input->pointer.surface);
}
input->pointer.surface = NULL;
return;
}
if (wl_resource_get_client(input->wl.seat.pointer->focus) != client) return;
if ((input->wl.seat.pointer->focus_serial - serial) > (UINT32_MAX / 2))
return;
/* is the passed in surface the same as our pointer surface ? */
if ((ews) && (ews != input->pointer.surface))
{
if (ews->configure)
{
wl_resource_post_error(ews->wl.surface,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"Surface already configured");
return;
}
}
/* if we have an existing pointer surface, unmap it */
if (input->pointer.surface)
{
/* call the unmap function */
if (input->pointer.surface->unmap)
input->pointer.surface->unmap(input->pointer.surface);
}
input->pointer.surface = ews;
/* if we don't have a pointer surface, we are done here */
if (!ews)
{
e_pointer_hide(e_comp_get(NULL)->pointer);
return;
}
/* set the destroy listener */
wl_signal_add(&ews->wl.destroy_signal,
&input->pointer.surface_destroy);
/* set some properties on this surface */
ews->unmap = _e_comp_wl_pointer_unmap;
ews->configure = _e_comp_wl_pointer_configure;
ews->input = input;
/* update input structure with new values */
input->pointer.hot.x = x;
input->pointer.hot.y = y;
if (&ews->buffer_reference)
{
E_Wayland_Buffer *buf;
if ((buf = ews->buffer_reference.buffer))
{
Evas_Coord bw = 0, bh = 0;
bw = buf->w;
bh = buf->h;
/* configure the pointer surface */
_e_comp_wl_pointer_configure(ews, 0, 0, bw, bh);
}
}
}
static void
_e_comp_wl_pointer_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
/* keyboard interface functions */
static void
_e_comp_wl_keyboard_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
/* touch interface functions */
static void
_e_comp_wl_touch_cb_release(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
/* region interface functions */
static void
_e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static void
_e_comp_wl_region_cb_add(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h)
{
E_Wayland_Region *ewr = NULL;
/* try to cast the resource data to our region structure */
if (!(ewr = wl_resource_get_user_data(resource))) return;
/* tell pixman to union this region with any previous one */
pixman_region32_union_rect(&ewr->region, &ewr->region, x, y, w, h);
}
static void
_e_comp_wl_region_cb_subtract(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h)
{
E_Wayland_Region *ewr = NULL;
pixman_region32_t region;
/* try to cast the resource data to our region structure */
if (!(ewr = wl_resource_get_user_data(resource))) return;
/* ask pixman to create a new temporary rect */
pixman_region32_init_rect(&region, x, y, w, h);
/* ask pixman to subtract this temp rect from the existing region */
pixman_region32_subtract(&ewr->region, &ewr->region, &region);
/* tell pixman we are finished with the temporary rect */
pixman_region32_fini(&region);
}
/* surface functions */
static void
_e_comp_wl_surface_cb_pending_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
{
E_Wayland_Surface *ews = NULL;
/* try to get the surface from this listener */
if (!(ews = container_of(listener, E_Wayland_Surface,
pending.buffer_destroy)))
return;
/* set surface pending buffer to null */
ews->pending.buffer = NULL;
}
static void
_e_comp_wl_surface_cb_frame_destroy(struct wl_resource *resource)
{
E_Wayland_Surface_Frame_Callback *cb = NULL;
/* try to cast the resource data to our surface frame callback structure */
if (!(cb = wl_resource_get_user_data(resource))) return;
wl_list_remove(&cb->wl.link);
/* free the allocated callback structure */
E_FREE(cb);
}
static void
_e_comp_wl_surface_buffer_reference(E_Wayland_Buffer_Reference *ref, E_Wayland_Buffer *buffer)
{
if ((ref->buffer) && (buffer != ref->buffer))
{
ref->buffer->busy_count--;
if (ref->buffer->busy_count == 0)
wl_resource_queue_event(ref->buffer->wl.resource, WL_BUFFER_RELEASE);
wl_list_remove(&ref->destroy_listener.link);
}
if ((buffer) && (buffer != ref->buffer))
{
buffer->busy_count++;
wl_signal_add(&buffer->wl.destroy_signal, &ref->destroy_listener);
}
//INF("CURRENT BUFFER SWAP: %p->%p", ref->buffer, buffer);
ref->buffer = buffer;
ref->destroy_listener.notify =
_e_comp_wl_surface_buffer_reference_cb_destroy;
}
static void
_e_comp_wl_surface_buffer_reference_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
{
E_Wayland_Buffer_Reference *ref;
/* try to get the surface from this listener */
ref = container_of(listener, E_Wayland_Buffer_Reference, destroy_listener);
if (!ref) return;
/* set referenced buffer to null */
ref->buffer = NULL;
}
static E_Wayland_Buffer *
_e_comp_wl_surface_buffer_resource(struct wl_resource *resource)
{
E_Wayland_Buffer *buffer;
struct wl_listener *listener;
listener =
wl_resource_get_destroy_listener(resource,
_e_comp_wl_surface_buffer_cb_destroy);
if (listener)
buffer = container_of(listener, E_Wayland_Buffer, wl.destroy_listener);
else
{
buffer = E_NEW_RAW(E_Wayland_Buffer, 1);
memset(buffer, 0, sizeof(*buffer));
buffer->wl.resource = resource;
wl_signal_init(&buffer->wl.destroy_signal);
buffer->wl.destroy_listener.notify =
_e_comp_wl_surface_buffer_cb_destroy;
wl_resource_add_destroy_listener(resource,
&buffer->wl.destroy_listener);
}
return buffer;
}
static void
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
_e_comp_wl_surface_buffer_cb_destroy(struct wl_listener *listener, void *data)
{
E_Wayland_Buffer *buffer;
buffer = container_of(listener, E_Wayland_Buffer, wl.destroy_listener);
wl_signal_emit(&buffer->wl.destroy_signal, buffer);
if (buffer->ews)
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
{
if (buffer->ews->ec && buffer->ews->pixmap && (e_pixmap_resource_get(buffer->ews->pixmap) == data) &&
evas_object_visible_get(buffer->ews->ec->frame))
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
{
//INF("DESTROYED CURRENT BUFFER: %s", e_pixmap_dirty_get(buffer->ews->pixmap) ? "DIRTY" : "CLEAN");
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
e_pixmap_usable_set(buffer->ews->pixmap, 0);
if (!e_pixmap_image_exists(buffer->ews->pixmap))
{
e_pixmap_image_refresh(buffer->ews->pixmap);
}
e_pixmap_image_clear(buffer->ews->pixmap, 0);
e_comp_object_damage(buffer->ews->ec->frame, 0, 0, buffer->ews->ec->client.w, buffer->ews->ec->client.h);
e_comp_object_render(buffer->ews->ec->frame);
e_comp_object_render_update_del(buffer->ews->ec->frame);
}
buffer->ews->buffers = eina_inlist_remove(buffer->ews->buffers, EINA_INLIST_GET(buffer));
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
}
E_FREE(buffer);
}
/* surface interface functionss */
static void
_e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
wl_resource_destroy(resource);
}
static void
_e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *buffer_resource, int x, int y)
{
E_Wayland_Surface *ews = NULL;
E_Wayland_Buffer *buffer = NULL;
/* try to cast the resource data to our surface structure */
if (!(ews = wl_resource_get_user_data(resource))) return;
if (buffer_resource)
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
{
buffer = _e_comp_wl_surface_buffer_resource(buffer_resource);
if (ews->ec && (!ews->buffer_reference.buffer))
{
e_pixmap_usable_set(ews->pixmap, 1);
}
}
/* reference any existing buffers */
_e_comp_wl_surface_buffer_reference(&ews->buffer_reference, buffer);
if (buffer)
{
if (!buffer->ews)
ews->buffers = eina_inlist_append(ews->buffers, EINA_INLIST_GET(buffer));
buffer->ews = ews;
}
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
//INF("ATTACHED NEW BUFFER");
e_pixmap_dirty(ews->pixmap);
//if (ews->ec)
//e_comp_object_damage(ews->ec->frame, 0, 0, ews->ec->client.w, ews->ec->client.h);
/* if we are setting a null buffer, then unmap the surface */
if (!buffer)
{
if (ews->mapped)
{
if (ews->unmap) ews->unmap(ews);
}
}
/* if we already have a pending buffer, remove the listener */
if (ews->pending.buffer)
wl_list_remove(&ews->pending.buffer_destroy.link);
/* set some pending values */
ews->pending.x = x;
ews->pending.y = y;
ews->pending.buffer = buffer;
// if (buffer)
ews->pending.new_buffer = EINA_TRUE;
/* if we were given a buffer, initialize the destroy signal */
if (buffer)
wl_signal_add(&buffer->wl.destroy_signal, &ews->pending.buffer_destroy);
}
static void
_e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h)
{
E_Wayland_Surface *ews = NULL;
/* try to cast the resource data to our surface structure */
if (!(ews = wl_resource_get_user_data(resource))) return;
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
e_pixmap_image_clear(ews->pixmap, 1);
/* tell pixman to add this damage to pending */
pixman_region32_union_rect(&ews->pending.damage, &ews->pending.damage,
x, y, w, h);
}
static void
_e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, unsigned int callback)
{
E_Wayland_Surface *ews = NULL;
E_Wayland_Surface_Frame_Callback *cb = NULL;
/* try to cast the resource data to our surface structure */
if (!(ews = wl_resource_get_user_data(resource))) return;
/* try to allocate space for a new frame callback */
if (!(cb = E_NEW(E_Wayland_Surface_Frame_Callback, 1)))
{
wl_resource_post_no_memory(resource);
return;
}
cb->wl.resource =
wl_resource_create(client, &wl_callback_interface, 1, callback);
wl_resource_set_implementation(cb->wl.resource, NULL, cb,
_e_comp_wl_surface_cb_frame_destroy);
/* add this callback to the surface list of pending frames */
wl_list_insert(ews->pending.frames.prev, &cb->wl.link);
}
static void
_e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
{
E_Wayland_Surface *ews = NULL;
/* try to cast the resource data to our surface structure */
if (!(ews = wl_resource_get_user_data(resource))) return;
if (region_resource)
{
E_Wayland_Region *ewr = NULL;
/* copy this region to the pending opaque region */
if ((ewr = wl_resource_get_user_data(region_resource)))
pixman_region32_copy(&ews->pending.opaque, &ewr->region);
}
else
{
/* tell pixman we are finished with this region */
pixman_region32_fini(&ews->pending.opaque);
/* reinitalize the pending opaque region */
pixman_region32_init(&ews->pending.opaque);
}
}
static void
_e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
{
E_Wayland_Surface *ews = NULL;
/* try to cast the resource data to our surface structure */
if (!(ews = wl_resource_get_user_data(resource))) return;
if (region_resource)
{
E_Wayland_Region *ewr = NULL;
/* copy this region to the pending input region */
if ((ewr = wl_resource_get_user_data(region_resource)))
pixman_region32_copy(&ews->pending.input, &ewr->region);
}
else
{
/* tell pixman we are finished with this region */
pixman_region32_fini(&ews->pending.input);
/* reinitalize the pending input region */
pixman_region32_init_rect(&ews->pending.input, INT32_MIN, INT32_MIN,
UINT32_MAX, UINT32_MAX);
}
}
static void
_e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
{
E_Wayland_Surface *ews = NULL;
Evas_Coord bw = 0, bh = 0;
pixman_region32_t opaque;
pixman_box32_t *rects;
int n = 0;
/* FIXME */
/* try to cast the resource data to our surface structure */
if (!(ews = wl_resource_get_user_data(resource))) return;
/* if we have a pending buffer or a new pending buffer, attach it */
if ((ews->pending.buffer) || (ews->pending.new_buffer))
{
/* reference the pending buffer */
_e_comp_wl_surface_buffer_reference(&ews->buffer_reference,
ews->pending.buffer);
/* if the pending buffer is NULL, unmap the surface */
if (!ews->pending.buffer)
{
if (ews->mapped)
{
if (ews->unmap) ews->unmap(ews);
}
}
}
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
e_pixmap_dirty(ews->pixmap);
e_pixmap_refresh(ews->pixmap);
e_pixmap_size_get(ews->pixmap, &bw, &bh);
/* if we have a new pending buffer, call configure */
if ((ews->configure) && (ews->pending.new_buffer))
// ews->configure(ews, ews->pending.x, ews->pending.y, bw, bh);
ews->configure(ews, ews->geometry.x, ews->geometry.y, bw, bh);
if (ews->pending.buffer)
wl_list_remove(&ews->pending.buffer_destroy.link);
/* set some pending values */
ews->pending.buffer = NULL;
ews->pending.x = 0;
ews->pending.y = 0;
ews->pending.new_buffer = EINA_FALSE;
/* set surface damage */
pixman_region32_union(&ews->region.damage, &ews->region.damage,
&ews->pending.damage);
pixman_region32_intersect_rect(&ews->region.damage, &ews->region.damage,
0, 0, ews->geometry.w, ews->geometry.h);
/* empty any pending damage */
pixman_region32_fini(&ews->pending.damage);
pixman_region32_init(&ews->pending.damage);
/* get the extent of the damage region */
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
if (ews->ec)
{
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
rects = pixman_region32_rectangles(&ews->region.damage, &n);
while (n--)
{
pixman_box32_t *r;
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
r = &rects[n];
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
/* send damages to the image */
e_comp_object_damage(ews->ec->frame, r->x1, r->y1, r->x2, r->y2);
}
}
/* tell pixman we are finished with this region */
/* pixman_region32_fini(&ews->region.damage); */
/* reinitalize the damage region */
/* pixman_region32_init(&ews->region.damage); */
/* calculate new opaque region */
pixman_region32_init_rect(&opaque, 0, 0, ews->geometry.w, ews->geometry.h);
pixman_region32_intersect(&opaque, &opaque, &ews->pending.opaque);
/* if new opaque region is not equal to the current one, then update */
if (!pixman_region32_equal(&opaque, &ews->region.opaque))
{
pixman_region32_copy(&ews->region.opaque, &opaque);
ews->geometry.changed = EINA_TRUE;
}
/* tell pixman we are done with this temporary region */
pixman_region32_fini(&opaque);
/* clear any existing input region */
pixman_region32_fini(&ews->region.input);
/* initialize a new input region */
pixman_region32_init_rect(&ews->region.input, 0, 0,
ews->geometry.w, ews->geometry.h);
/* put pending input region into new input region */
pixman_region32_intersect(&ews->region.input, &ews->region.input,
&ews->pending.input);
/* check for valid input region */
// if (pixman_region32_not_empty(&ews->region.input))
{
/* get the extent of the input region */
rects = pixman_region32_extents(&ews->region.input);
/* update the smart object's input region */
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
if (ews->ec)
e_comp_object_input_area_set(ews->ec->frame, rects->x1, rects->y1,
rects->x2, rects->y2);
}
/* put any pending frame callbacks into active list */
wl_list_insert_list(&ews->wl.frames, &ews->pending.frames);
/* clear list of pending frame callbacks */
wl_list_init(&ews->pending.frames);
compositor rewrite / charlie-foxtrot situation huge fustercluck commit because there wasn't really a way to separate out the changes. better to just rip it all out at once. * compositor and window management completely rewritten. this was the goal for E19, but it pretty much required everything existing to be scrapped since it wasn't optimized, streamlined, or sensible. now instead of having the compositor strapped to the window manager like an outboard motor, it's housed more like an automobile engine. ** various comp structs have been merged into other places (eg. E_Comp_Zone is now just part of E_Zone where applicable), leading to a large deduplication of attributes ** awful E_Comp_Win is totally dead, having been replaced with e_comp_object smart objects which work just like normal canvas objects ** protocol-specific window management and compositor functionality is now kept exclusively in backend files ** e_pixmap api provides generic client finding and rendering api ** screen/xinerama screens are now provided directly by compositor on startup and re-set on change ** e_comp_render_update finally replaced with eina_tiler ** wayland compositor no longer creates X windows ** compositor e_layout removed entirely * e_container is gone. this was made unnecessary in E18, but I kept it to avoid having too much code churn in one release. its sole purpose was to catch some events and handle window stacking, both of which are now just done by the compositor infra * e_manager is just for screensaver and keybind stuff now, possibly remove later? * e_border is gone along with a lot of its api. e_client has replaced it, and e_client has been rewritten completely; some parts may be similar, but the design now relies upon having a functional compositor ** window configuration/focus functions are all removed. all windows are now managed solely with evas_object_X functions on the "frame" member of a client, just as any other canvas object can be managed. *** do NOT set interceptors on a client's comp_object. seriously. * startup order rewritten: compositor now starts much earlier, other things just use attrs and members of the compositor * ecore_x_pointer_xy_get usage replaced with ecore_evas_pointer_xy_get * e_popup is totally gone, existing usage replaced by e_comp_object_util_add where applicable, otherwise just placed normally on the canvas * deskmirror is (more) broken for now * illume is totally fucked * Ecore_X_Window replaced with Ecore_Window in most cases * edge binding XWindows replaced with regular canvas objects * some E_Win functionality has changed such that delete callbacks are now correctly called in ALL cases. various dialogs have been updated to not crash as a result comp files and descriptions: e_comp.c - overall compositor functions, rendering/update loop, shape cutting e_comp_x.c - X window management and compositor functionality e_comp_wl.c - Wayland surface management and compositor functionality e_comp_canvas.c - general compositor canvas functions and utilities e_comp_object.c - E_Client->frame member for managing clients as Evas_Objects, utility functions for adding objects to the compositor rendering systems additional authors: ivan.briano@intel.com feature: new compositor removal: e_border, e_container, e_popup
2014-01-14 17:19:12 -08:00
ews->updates = 1;
_e_wl_comp->surfaces = eina_inlist_promote(_e_wl_comp->surfaces, EINA_INLIST_GET(ews));
/* TODO: schedule repaint ?? */
}
static void
_e_comp_wl_surface_cb_buffer_transform_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, int transform EINA_UNUSED)
{
}
static void
_e_comp_wl_surface_cb_buffer_scale_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, int scale EINA_UNUSED)
{
}