mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-04 13:29:51 -05:00
Make multi-pointer work.
This also add command line parsing as a way to specify the input device files to use.
This commit is contained in:
parent
d6531261de
commit
c492b482d0
3 changed files with 80 additions and 47 deletions
|
|
@ -40,6 +40,8 @@
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <eagle.h>
|
#include <eagle.h>
|
||||||
|
|
@ -55,6 +57,7 @@ struct egl_input_device {
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
struct egl_compositor *ec;
|
struct egl_compositor *ec;
|
||||||
struct egl_surface *pointer_surface;
|
struct egl_surface *pointer_surface;
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
int grab;
|
int grab;
|
||||||
struct egl_surface *grab_surface;
|
struct egl_surface *grab_surface;
|
||||||
|
|
@ -73,8 +76,7 @@ struct egl_compositor {
|
||||||
struct egl_surface *overlay;
|
struct egl_surface *overlay;
|
||||||
double overlay_y, overlay_target, overlay_previous;
|
double overlay_y, overlay_target, overlay_previous;
|
||||||
|
|
||||||
struct egl_input_device *input_device;
|
struct wl_list input_device_list;
|
||||||
|
|
||||||
struct wl_list surface_list;
|
struct wl_list surface_list;
|
||||||
|
|
||||||
/* Repaint state. */
|
/* Repaint state. */
|
||||||
|
|
@ -571,6 +573,7 @@ repaint(void *data)
|
||||||
{
|
{
|
||||||
struct egl_compositor *ec = data;
|
struct egl_compositor *ec = data;
|
||||||
struct egl_surface *es;
|
struct egl_surface *es;
|
||||||
|
struct egl_input_device *eid;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
uint32_t msecs;
|
uint32_t msecs;
|
||||||
|
|
||||||
|
|
@ -592,7 +595,14 @@ repaint(void *data)
|
||||||
|
|
||||||
draw_surface(ec->overlay);
|
draw_surface(ec->overlay);
|
||||||
|
|
||||||
draw_surface(ec->input_device->pointer_surface);
|
eid = container_of(ec->input_device_list.next,
|
||||||
|
struct egl_input_device, link);
|
||||||
|
while (&eid->link != &ec->input_device_list) {
|
||||||
|
draw_surface(eid->pointer_surface);
|
||||||
|
|
||||||
|
eid = container_of(eid->link.next,
|
||||||
|
struct egl_input_device, link);
|
||||||
|
}
|
||||||
|
|
||||||
eglSwapBuffers(ec->display, ec->surface);
|
eglSwapBuffers(ec->display, ec->surface);
|
||||||
ec->repaint_needed = 0;
|
ec->repaint_needed = 0;
|
||||||
|
|
@ -747,6 +757,9 @@ pick_surface(struct egl_input_device *device)
|
||||||
struct egl_compositor *ec = device->ec;
|
struct egl_compositor *ec = device->ec;
|
||||||
struct egl_surface *es;
|
struct egl_surface *es;
|
||||||
|
|
||||||
|
if (device->grab > 0)
|
||||||
|
return device->grab_surface;
|
||||||
|
|
||||||
es = container_of(ec->surface_list.prev,
|
es = container_of(ec->surface_list.prev,
|
||||||
struct egl_surface, link);
|
struct egl_surface, link);
|
||||||
while (&es->link != &ec->surface_list) {
|
while (&es->link != &ec->surface_list) {
|
||||||
|
|
@ -770,9 +783,6 @@ notify_motion(struct egl_input_device *device, int x, int y)
|
||||||
const int hotspot_x = 16, hotspot_y = 16;
|
const int hotspot_x = 16, hotspot_y = 16;
|
||||||
int32_t sx, sy;
|
int32_t sx, sy;
|
||||||
|
|
||||||
if (device->grab > 0)
|
|
||||||
es = device->grab_surface;
|
|
||||||
else
|
|
||||||
es = pick_surface(device);
|
es = pick_surface(device);
|
||||||
|
|
||||||
if (es) {
|
if (es) {
|
||||||
|
|
@ -795,6 +805,7 @@ notify_button(struct egl_input_device *device,
|
||||||
int32_t button, int32_t state)
|
int32_t button, int32_t state)
|
||||||
{
|
{
|
||||||
struct egl_surface *es;
|
struct egl_surface *es;
|
||||||
|
int32_t sx, sy;
|
||||||
|
|
||||||
es = pick_surface(device);
|
es = pick_surface(device);
|
||||||
if (es) {
|
if (es) {
|
||||||
|
|
@ -808,9 +819,13 @@ notify_button(struct egl_input_device *device,
|
||||||
device->grab--;
|
device->grab--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sx = (device->x - es->map.x) * es->width / es->map.width;
|
||||||
|
sy = (device->y - es->map.y) * es->height / es->map.height;
|
||||||
|
|
||||||
/* FIXME: Swallow click on raise? */
|
/* FIXME: Swallow click on raise? */
|
||||||
wl_surface_post_event(es->wl_surface, &device->base,
|
wl_surface_post_event(es->wl_surface, &device->base,
|
||||||
WL_INPUT_BUTTON, button, state);
|
WL_INPUT_BUTTON, button, state,
|
||||||
|
device->x, device->y, sx, sy);
|
||||||
|
|
||||||
schedule_repaint(device->ec);
|
schedule_repaint(device->ec);
|
||||||
}
|
}
|
||||||
|
|
@ -851,11 +866,6 @@ static const struct wl_compositor_interface interface = {
|
||||||
notify_commit,
|
notify_commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char pointer_device_file[] =
|
|
||||||
"/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-mouse";
|
|
||||||
static const char keyboard_device_file[] =
|
|
||||||
"/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-kbd";
|
|
||||||
|
|
||||||
struct evdev_input_device *
|
struct evdev_input_device *
|
||||||
evdev_input_device_create(struct egl_input_device *device,
|
evdev_input_device_create(struct egl_input_device *device,
|
||||||
struct wl_display *display, const char *path);
|
struct wl_display *display, const char *path);
|
||||||
|
|
@ -864,34 +874,42 @@ void
|
||||||
egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y);
|
egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_input_devices(struct egl_compositor *ec)
|
create_input_device(struct egl_compositor *ec, const char *glob)
|
||||||
{
|
{
|
||||||
struct egl_input_device *device;
|
struct egl_input_device *device;
|
||||||
const char *path;
|
struct dirent *de;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
const char *by_path_dir = "/dev/input/by-path";
|
||||||
|
DIR *dir;
|
||||||
|
|
||||||
device = malloc(sizeof *device);
|
device = malloc(sizeof *device);
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
memset(device, 0, sizeof *device);
|
||||||
device->base.interface = wl_input_device_get_interface();
|
device->base.interface = wl_input_device_get_interface();
|
||||||
wl_display_add_object(ec->wl_display, &device->base);
|
wl_display_add_object(ec->wl_display, &device->base);
|
||||||
ec->input_device = device;
|
|
||||||
device->x = 100;
|
device->x = 100;
|
||||||
device->y = 100;
|
device->y = 100;
|
||||||
device->pointer_surface = pointer_create(device->x, device->y, 64, 64);
|
device->pointer_surface = pointer_create(device->x, device->y, 64, 64);
|
||||||
device->ec = ec;
|
device->ec = ec;
|
||||||
|
|
||||||
path = getenv("WAYLAND_POINTER");
|
dir = opendir(by_path_dir);
|
||||||
if (path == NULL)
|
if (dir == NULL) {
|
||||||
path = pointer_device_file;
|
fprintf(stderr, "couldn't read dir %s\n", by_path_dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (de = readdir(dir), de != NULL) {
|
||||||
|
if (fnmatch(glob, de->d_name, 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
snprintf(path, sizeof path, "%s/%s", by_path_dir, de->d_name);
|
||||||
evdev_input_device_create(device, ec->wl_display, path);
|
evdev_input_device_create(device, ec->wl_display, path);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
|
||||||
path = getenv("WAYLAND_KEYBOARD");
|
wl_list_insert(ec->input_device_list.prev, &device->link);
|
||||||
if (path == NULL)
|
|
||||||
path = keyboard_device_file;
|
|
||||||
|
|
||||||
evdev_input_device_create(device, ec->wl_display, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -1047,10 +1065,18 @@ pick_config(struct egl_compositor *ec)
|
||||||
|
|
||||||
static const char gem_device[] = "/dev/dri/card0";
|
static const char gem_device[] = "/dev/dri/card0";
|
||||||
|
|
||||||
static const char *background_image = "background.jpg";
|
static const char *macbook_air_default_input_device[] = {
|
||||||
|
"pci-0000:00:1d.0-usb-0:2:1*event*"
|
||||||
|
};
|
||||||
|
|
||||||
static GOptionEntry option_entries[] = {
|
static const char *option_background = "background.jpg";
|
||||||
{ "background", 'b', 0, G_OPTION_ARG_STRING, &background_image, "Background image" },
|
static const char **option_input_devices = macbook_air_default_input_device;
|
||||||
|
|
||||||
|
static const GOptionEntry option_entries[] = {
|
||||||
|
{ "background", 'b', 0, G_OPTION_ARG_STRING,
|
||||||
|
&option_background, "Background image" },
|
||||||
|
{ "input-device", 'i', 0, G_OPTION_ARG_STRING_ARRAY,
|
||||||
|
&option_input_devices, "Input device glob" },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1061,7 +1087,7 @@ egl_compositor_create(struct wl_display *display)
|
||||||
struct egl_compositor *ec;
|
struct egl_compositor *ec;
|
||||||
struct screenshooter *shooter;
|
struct screenshooter *shooter;
|
||||||
uint32_t fb_name;
|
uint32_t fb_name;
|
||||||
int stride;
|
int i, stride;
|
||||||
struct wl_event_loop *loop;
|
struct wl_event_loop *loop;
|
||||||
const static EGLint attribs[] =
|
const static EGLint attribs[] =
|
||||||
{ EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE };
|
{ EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE };
|
||||||
|
|
@ -1113,10 +1139,12 @@ egl_compositor_create(struct wl_display *display)
|
||||||
glOrtho(0, ec->width, ec->height, 0, 0, 1000.0);
|
glOrtho(0, ec->width, ec->height, 0, 0, 1000.0);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
create_input_devices(ec);
|
wl_list_init(&ec->input_device_list);
|
||||||
|
for (i = 0; option_input_devices[i]; i++)
|
||||||
|
create_input_device(ec, option_input_devices[i]);
|
||||||
|
|
||||||
wl_list_init(&ec->surface_list);
|
wl_list_init(&ec->surface_list);
|
||||||
ec->background = background_create(background_image,
|
ec->background = background_create(option_background,
|
||||||
ec->width, ec->height);
|
ec->width, ec->height);
|
||||||
ec->overlay = overlay_create(0, ec->height, ec->width, 200);
|
ec->overlay = overlay_create(0, ec->height, ec->width, 200);
|
||||||
ec->overlay_y = ec->height;
|
ec->overlay_y = ec->height;
|
||||||
|
|
|
||||||
|
|
@ -646,7 +646,7 @@ static const struct wl_method input_device_methods[] = {
|
||||||
|
|
||||||
static const struct wl_event input_device_events[] = {
|
static const struct wl_event input_device_events[] = {
|
||||||
{ "motion", "iiii" },
|
{ "motion", "iiii" },
|
||||||
{ "button", "uu" },
|
{ "button", "uuiiii" },
|
||||||
{ "key", "uu" },
|
{ "key", "uu" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
37
window.c
37
window.c
|
|
@ -46,8 +46,9 @@ struct window {
|
||||||
int x, y, width, height;
|
int x, y, width, height;
|
||||||
int minimum_width, minimum_height;
|
int minimum_width, minimum_height;
|
||||||
int margin;
|
int margin;
|
||||||
int drag_x, drag_y, last_x, last_y;
|
int drag_x, drag_y;
|
||||||
int state;
|
int state;
|
||||||
|
uint32_t grab_device;
|
||||||
uint32_t name;
|
uint32_t name;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
|
@ -232,10 +233,10 @@ event_handler(struct wl_display *display,
|
||||||
} else if (opcode == 0) {
|
} else if (opcode == 0) {
|
||||||
int x = p[0], y = p[1];
|
int x = p[0], y = p[1];
|
||||||
|
|
||||||
window->last_x = x;
|
|
||||||
window->last_y = y;
|
|
||||||
switch (window->state) {
|
switch (window->state) {
|
||||||
case WINDOW_MOVING:
|
case WINDOW_MOVING:
|
||||||
|
if (window->grab_device != object)
|
||||||
|
break;
|
||||||
window->x = window->drag_x + x;
|
window->x = window->drag_x + x;
|
||||||
window->y = window->drag_y + y;
|
window->y = window->drag_y + y;
|
||||||
wl_surface_map(window->surface,
|
wl_surface_map(window->surface,
|
||||||
|
|
@ -246,6 +247,8 @@ event_handler(struct wl_display *display,
|
||||||
wl_display_commit(window->display, 1);
|
wl_display_commit(window->display, 1);
|
||||||
break;
|
break;
|
||||||
case WINDOW_RESIZING_LOWER_RIGHT:
|
case WINDOW_RESIZING_LOWER_RIGHT:
|
||||||
|
if (window->grab_device != object)
|
||||||
|
break;
|
||||||
window->width = window->drag_x + x;
|
window->width = window->drag_x + x;
|
||||||
window->height = window->drag_y + y;
|
window->height = window->drag_y + y;
|
||||||
|
|
||||||
|
|
@ -258,16 +261,15 @@ event_handler(struct wl_display *display,
|
||||||
}
|
}
|
||||||
} else if (opcode == 1) {
|
} else if (opcode == 1) {
|
||||||
int button = p[0], state = p[1];
|
int button = p[0], state = p[1];
|
||||||
|
int32_t x = p[2], y = p[3];
|
||||||
|
|
||||||
if (window->x + window->width - grip_size <= window->last_x &&
|
if (window->x + window->width - grip_size <= x &&
|
||||||
window->last_x < window->x + window->width &&
|
x < window->x + window->width &&
|
||||||
window->y + window->height - grip_size <= window->last_y &&
|
window->y + window->height - grip_size <= y &&
|
||||||
window->last_y < window->y + window->height) {
|
y < window->y + window->height) {
|
||||||
location = LOCATION_LOWER_RIGHT;
|
location = LOCATION_LOWER_RIGHT;
|
||||||
} else if (window->x <= window->last_x &&
|
} else if (window->x <= x && x < window->x + window->width &&
|
||||||
window->last_x < window->x + window->width &&
|
window->y <= y && y < window->y + window->height) {
|
||||||
window->y <= window->last_y &&
|
|
||||||
window->last_y < window->y + window->height) {
|
|
||||||
location = LOCATION_INTERIOR;
|
location = LOCATION_INTERIOR;
|
||||||
} else {
|
} else {
|
||||||
location = LOCATION_OUTSIDE;
|
location = LOCATION_OUTSIDE;
|
||||||
|
|
@ -276,20 +278,23 @@ event_handler(struct wl_display *display,
|
||||||
if (button == BTN_LEFT && state == 1) {
|
if (button == BTN_LEFT && state == 1) {
|
||||||
switch (location) {
|
switch (location) {
|
||||||
case LOCATION_INTERIOR:
|
case LOCATION_INTERIOR:
|
||||||
window->drag_x = window->x - window->last_x;
|
window->drag_x = window->x - x;
|
||||||
window->drag_y = window->y - window->last_y;
|
window->drag_y = window->y - y;
|
||||||
window->state = WINDOW_MOVING;
|
window->state = WINDOW_MOVING;
|
||||||
|
window->grab_device = object;
|
||||||
break;
|
break;
|
||||||
case LOCATION_LOWER_RIGHT:
|
case LOCATION_LOWER_RIGHT:
|
||||||
window->drag_x = window->width - window->last_x;
|
window->drag_x = window->width - x;
|
||||||
window->drag_y = window->height - window->last_y;
|
window->drag_y = window->height - y;
|
||||||
window->state = WINDOW_RESIZING_LOWER_RIGHT;
|
window->state = WINDOW_RESIZING_LOWER_RIGHT;
|
||||||
|
window->grab_device = object;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
window->state = WINDOW_STABLE;
|
window->state = WINDOW_STABLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (button == BTN_LEFT && state == 0) {
|
} else if (button == BTN_LEFT &&
|
||||||
|
state == 0 && object == window->grab_device) {
|
||||||
window->state = WINDOW_STABLE;
|
window->state = WINDOW_STABLE;
|
||||||
}
|
}
|
||||||
} else if (opcode == 2) {
|
} else if (opcode == 2) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue