void
shell_surface_set_parent(shell_surface_t *shsurf, pepper_surface_t *parent);
+void
+shell_surface_stack_top(shell_surface_t *shsurf, pepper_bool_t subtree);
+
/* */
shell_surface_t *
get_shsurf_from_surface(pepper_surface_t *surface, desktop_shell_t *shell);
}
+void
+shell_surface_stack_top(shell_surface_t *shsurf, pepper_bool_t subtree)
+{
+ pepper_view_t *cursor_view;
+ pepper_pointer_t *pointer;
+ shell_seat_t *shseat;
+
+ pepper_view_stack_top(shsurf->view, subtree);
+
+ pepper_list_for_each(shseat, &shsurf->shell->shseat_list, link)
+ {
+ pointer = pepper_seat_get_pointer(shseat->seat);
+ if (pointer)
+ {
+ cursor_view = pepper_pointer_get_cursor_view(pointer);
+ if (cursor_view)
+ pepper_view_stack_top(cursor_view, PEPPER_FALSE);
+ }
+ }
+}
+
shell_surface_t *
get_shsurf_from_surface(pepper_surface_t *surface, desktop_shell_t *shell)
{
pepper_view_map(shsurf->view);
- pepper_view_stack_top(shsurf->view, PEPPER_TRUE);
+ shell_surface_stack_top(shsurf, PEPPER_TRUE);
shell_surface_add_popup_grab(shsurf);
}
pepper_view_map(shsurf->view);
/* Set top of z-order */
- pepper_view_stack_top(shsurf->view, PEPPER_TRUE /*FIXME:*/);
+ shell_surface_stack_top(shsurf, PEPPER_TRUE /*FIXME:*/);
}
static void
shell_surface_place_fullscreen_surface(shsurf);
pepper_view_map(shsurf->view);
- pepper_view_stack_top(shsurf->view, PEPPER_TRUE /*FIXME*/ );
+ shell_surface_stack_top(shsurf, PEPPER_TRUE /*FIXME*/ );
}
void
}
if (pointer_focus)
- pepper_view_stack_top(pointer_focus, PEPPER_FALSE);
+ {
+ shell_seat_t *shseat = data;
+ desktop_shell_t *shell = shseat->shell;
+ pepper_surface_t *surface = pepper_view_get_surface(pointer_focus);
+ shell_surface_t *shsurf = get_shsurf_from_surface(surface, shell);
+
+ shell_surface_stack_top(shsurf, PEPPER_FALSE);
+ }
}
pepper_pointer_send_button(pointer, pointer_focus, time, button, state);
void *info, void *data)
{
pepper_pointer_t *pointer = info;
- pepper_pointer_set_grab(pointer, &default_pointer_grab, NULL);
+ pepper_pointer_set_grab(pointer, &default_pointer_grab, data);
}
static void
drm->resources = drmModeGetResources(drm->fd);
PEPPER_CHECK(drm->resources, goto error, "drmModeGetResources() failed.\n");
+ ret = drmGetCap(drm->fd, 0x8 /* DRM_CAP_CURSOR_WIDTH */, &cap);
+ drm->cursor_width = (ret == 0) ? cap : 64;
+
+ ret = drmGetCap(drm->fd, 0x9 /* DRM_CAP_CURSOR_HEIGHT */, &cap);
+ drm->cursor_height = (ret == 0) ? cap : 64;
+
drm_init_planes(drm);
drm_init_connectors(drm);
udev_device_unref(udev_device);
#endif
pepper_renderer_t *pixman_renderer;
pepper_renderer_t *gl_renderer;
+
+ pepper_bool_t cursor_broken;
+ int32_t cursor_width;
+ int32_t cursor_height;
};
struct drm_connector
pepper_bool_t page_flip_pending;
int vblank_pending_count;
+ pepper_view_t *cursor_view;
+ pepper_buffer_t *cursor_buffer;
+ struct gbm_bo *cursor_bo[2];
+ int cursor_bo_index;
+ int cursor_x, cursor_y;
+ pepper_bool_t need_set_cursor;
+
pepper_plane_t *cursor_plane;
pepper_plane_t *primary_plane;
pepper_plane_t *fb_plane;
static pepper_plane_t *
assign_cursor_plane(drm_output_t *output, pepper_view_t *view)
{
- /* TODO: */
- return NULL;
+ int32_t w, h;
+ pepper_surface_t *surface;
+ pepper_buffer_t *buffer;
+ struct wl_resource *resource;
+
+ if (output->cursor_view)
+ return NULL;
+
+ if (!output->drm->gbm_device)
+ return NULL;
+
+ if (output->drm->cursor_broken)
+ return NULL;
+
+ pepper_view_get_size(view, &w, &h);
+ if ((output->drm->cursor_width < w) || (output->drm->cursor_height < h))
+ return NULL;
+
+ surface = pepper_view_get_surface(view);
+ buffer = pepper_surface_get_buffer(surface);
+ if (!buffer)
+ return NULL;
+
+ resource = pepper_buffer_get_resource(buffer);
+ if (!resource || !wl_shm_buffer_get(resource))
+ return NULL;
+
+ output->cursor_view = view;
+ if (output->cursor_buffer != buffer)
+ {
+ output->cursor_buffer = buffer;
+ output->need_set_cursor = PEPPER_TRUE;
+ }
+
+ return output->cursor_plane;
}
static pepper_plane_t *
pepper_output_finish_frame(output->base, &ts);
}
+static void
+drm_output_set_cursor(drm_output_t *output)
+{
+ pepper_drm_t *drm = output->drm;
+ pepper_surface_t *surface;
+ pepper_buffer_t *buffer;
+
+ double x, y;
+
+ if (!output->cursor_view)
+ {
+ drmModeSetCursor(drm->fd, output->crtc_id, 0, 0, 0);
+ return;
+ }
+
+ surface = pepper_view_get_surface(output->cursor_view);
+ buffer = pepper_surface_get_buffer(surface);
+
+ if (buffer && output->need_set_cursor)
+ {
+
+ int32_t i, w, h, stride;
+ uint8_t *data;
+ uint32_t buf[drm->cursor_width * drm->cursor_height];
+
+ struct gbm_bo *bo;
+ struct wl_resource *resource;
+ struct wl_shm_buffer *shm_buffer;
+
+ resource = pepper_buffer_get_resource(buffer);
+
+ shm_buffer = wl_shm_buffer_get(resource);
+ stride = wl_shm_buffer_get_stride(shm_buffer);
+ data = wl_shm_buffer_get_data(shm_buffer);
+
+ pepper_view_get_size(output->cursor_view, &w, &h);
+
+ memset(buf, 0, sizeof(buf));
+ wl_shm_buffer_begin_access(shm_buffer);
+ for (i = 0; i < h; i++)
+ memcpy(buf + i * drm->cursor_width, data + i * stride, w * sizeof(uint32_t));
+ wl_shm_buffer_end_access(shm_buffer);
+
+ output->cursor_bo_index ^= 1;
+ bo = output->cursor_bo[output->cursor_bo_index];
+ gbm_bo_write(bo, buf, sizeof(buf));
+
+ if (drmModeSetCursor(drm->fd, output->crtc_id, gbm_bo_get_handle(bo).s32,
+ drm->cursor_width, drm->cursor_height))
+ {
+ PEPPER_TRACE("failed to set cursor\n");
+ drm->cursor_broken = PEPPER_TRUE;
+ }
+
+ output->need_set_cursor = PEPPER_FALSE;
+ }
+
+ pepper_view_get_position(output->cursor_view, &x, &y);
+ if ((output->cursor_x != (int)x) || (output->cursor_y != (int)y))
+ {
+ if (drmModeMoveCursor(drm->fd, output->crtc_id, (int)x, (int)y))
+ {
+ PEPPER_TRACE("failed to move cursor\n");
+ drm->cursor_broken = PEPPER_TRUE;
+ }
+
+ output->cursor_x = (int)x;
+ output->cursor_y = (int)y;
+ }
+
+ output->cursor_view = NULL;
+}
+
static void
drm_output_repaint(void *o, const pepper_list_t *plane_list)
{
output->page_flip_pending = PEPPER_TRUE;
}
+ drm_output_set_cursor(output);
+
pepper_list_for_each(plane, &output->drm->plane_list, link)
{
drmVBlank vbl;
pepper_renderer_flush_surface_damage(output->renderer, surface);
- if (output->render_type == DRM_RENDER_TYPE_PIXMAN ||
- (buffer && !wl_shm_buffer_get(pepper_buffer_get_resource(buffer))))
- {
- *keep_buffer = PEPPER_TRUE;
- }
- else
+ if (output->render_type == DRM_RENDER_TYPE_PIXMAN)
+ goto keep;
+
+ if (buffer)
{
- *keep_buffer = PEPPER_FALSE;
+ int w, h;
+
+ if (!wl_shm_buffer_get(pepper_buffer_get_resource(buffer)))
+ goto keep;
+
+ pepper_buffer_get_size(buffer, &w, &h);
+ if ((w <= output->drm->cursor_width) && (h <= output->drm->cursor_height))
+ goto keep;
}
+
+ *keep_buffer = PEPPER_FALSE;
+ return;
+
+keep:
+ *keep_buffer = PEPPER_TRUE;
}
struct pepper_output_backend drm_output_backend =
if (use_overlay_env && strcmp(use_overlay_env, "1") == 0)
output->use_overlay = PEPPER_TRUE;
+ if (drm->gbm_device)
+ {
+ int i;
+
+ for (i = 0; i < 2; i++)
+ output->cursor_bo[i] = gbm_bo_create(drm->gbm_device,
+ drm->cursor_width, drm->cursor_height,
+ GBM_FORMAT_ARGB8888,
+ GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
+ if (!output->cursor_bo[0] || !output->cursor_bo[1])
+ {
+ PEPPER_TRACE("failed to create cursor bo\n");
+ drm->cursor_broken = PEPPER_TRUE;
+ }
+ }
+
output->primary_plane = pepper_output_add_plane(output->base, NULL);
PEPPER_CHECK(output->primary_plane, goto error, "pepper_output_add_plane() failed.\n");
void
drm_output_destroy(void *o)
{
+ int i;
drm_output_t *output = o;
drm_plane_t *plane;
return;
}
+ for (i = 0; i < 2; i++)
+ {
+ if (output->cursor_bo[i])
+ gbm_bo_destroy(output->cursor_bo[i]);
+ }
+
if (output->render_type == DRM_RENDER_TYPE_PIXMAN)
fini_pixman_renderer(output);
else if (output->render_type == DRM_RENDER_TYPE_GL)
pixman_region32_t damage_region;
pixman_region32_t opaque_region;
pixman_region32_t input_region;
+ pepper_bool_t pickable;
struct wl_list frame_callback_list;
double x_velocity;
double y_velocity;
+
+ pepper_view_t *cursor_view;
+ int32_t hotspot_x;
+ int32_t hotspot_y;
};
pepper_pointer_t *
PEPPER_API void *
pepper_pointer_get_grab_data(pepper_pointer_t *pointer);
+PEPPER_API pepper_view_t *
+pepper_pointer_get_cursor_view(pepper_pointer_t *pointer);
+
+PEPPER_API void
+pepper_pointer_set_hotspot(pepper_pointer_t *pointer, int32_t x, int32_t y);
+
/* Keyboard. */
struct pepper_keyboard_grab
{
#include "pepper-internal.h"
#include <float.h>
+static pepper_view_t *
+get_cursor_view(pepper_pointer_t *pointer)
+{
+ if (pointer->cursor_view)
+ return pointer->cursor_view;
+
+ pointer->cursor_view = pepper_compositor_add_view(pointer->seat->compositor);
+
+ return pointer->cursor_view;
+}
+
static void
pointer_set_cursor(struct wl_client *client, struct wl_resource *resource, uint32_t serial,
struct wl_resource *surface_resource, int32_t x, int32_t y)
{
- /* TODO: */
+ pepper_pointer_t *pointer = (pepper_pointer_t *)wl_resource_get_user_data(resource);
+ pepper_surface_t *surface;
+ pepper_view_t *cursor_view;
+
+ cursor_view = get_cursor_view(pointer);
+ PEPPER_CHECK(cursor_view, return, "failed to get cursor view\n");
+
+ if (!surface_resource)
+ {
+ pepper_view_set_surface(cursor_view, NULL);
+ return;
+ }
+
+ surface = (pepper_surface_t *)wl_resource_get_user_data(surface_resource);
+ if (!surface->role)
+ pepper_surface_set_role(surface, "wl_pointer-cursor");
+ else if (strcmp("wl_pointer-cursor", surface->role))
+ return;
+
+ if (surface != pepper_view_get_surface(cursor_view))
+ {
+ surface->pickable = PEPPER_FALSE;
+ pixman_region32_fini(&surface->input_region);
+ pixman_region32_init(&surface->input_region);
+ pepper_view_set_surface(cursor_view, surface);
+ }
+
+ pointer->hotspot_x = x;
+ pointer->hotspot_y = y;
+ pepper_view_set_position(cursor_view, pointer->x - x, pointer->y - y);
+ pepper_view_map(cursor_view);
}
static void
pointer_clamp(pointer);
+ if (pointer->cursor_view)
+ pepper_view_set_position(pointer->cursor_view,
+ x - pointer->hotspot_x, y - pointer->hotspot_y);
+
if (pointer->grab)
pointer->grab->motion(pointer, pointer->data, time, pointer->x, pointer->y);
{
return pointer->data;
}
+
+PEPPER_API pepper_view_t *
+pepper_pointer_get_cursor_view(pepper_pointer_t *pointer)
+{
+ return pointer->cursor_view;
+}
+
+PEPPER_API void
+pepper_pointer_set_hotspot(pepper_pointer_t *pointer, int32_t x, int32_t y)
+{
+ pointer->hotspot_x = x;
+ pointer->hotspot_y = y;
+}
pixman_region32_init(&surface->damage_region);
pixman_region32_init(&surface->opaque_region);
pixman_region32_init_rect(&surface->input_region, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX);
+ surface->pickable = PEPPER_TRUE;
wl_list_init(&surface->frame_callback_list);
pepper_list_init(&surface->view_list);
/* surface.set_opaque_region(), surface.set_input_region(). */
pixman_region32_copy(&surface->opaque_region, &state->opaque_region);
- pixman_region32_copy(&surface->input_region, &state->input_region);
+
+ if (surface->pickable)
+ pixman_region32_copy(&surface->input_region, &state->input_region);
pepper_list_for_each(view, &surface->view_list, surface_link)
{