Skip to content

Commit a6bd908

Browse files
zhovnerTingPing
authored andcommitted
drm: Add separate cursor and pointer options
Pointer event delivery in the DRM platform was gated on cursor.enabled, which only becomes true after init_cursor() successfully allocates a hardware cursor plane. Drivers that lack a DRM_PLANE_TYPE_CURSOR plane (e.g. drm_simple_kms_helper panels) silently dropped every libinput pointer event, making COG_PLATFORM_DRM_CURSOR effectively the master switch for pointer input rather than just the on-screen cursor sprite as its name implies. Split into two independent options, each settable via env var, configuration file [drm] section, or -O command-line parameter: cursor draw a hardware cursor plane sprite (COG_PLATFORM_DRM_CURSOR) pointer forward libinput pointer events to WPE (COG_PLATFORM_DRM_POINTER) Both default to off; cursor=on implies pointer=on so the legacy single-flag behaviour of COG_PLATFORM_DRM_CURSOR=1 is preserved.
1 parent 5c32017 commit a6bd908

2 files changed

Lines changed: 129 additions & 22 deletions

File tree

docs/platform-drm.md

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ The DRM platform plug-in additionally requires the following libraries:
1919
If a section named `drm` is found in the configuration file (see
2020
[property@Cog.Shell:config-file]), the following options will be honored:
2121

22-
| Option | Type | Default |
23-
|:-----------------------------|:--------|:---------|
24-
| `device-scale-factor` | float | `1.0` |
25-
| `disable-atomic-modesetting` | boolean | *detect* |
26-
| `renderer` | string | `"modeset"` |
22+
| Option | Type | Default |
23+
|:-----------------------------|:--------|:------------|
24+
| `device-scale-factor` | float | `1.0` |
25+
| `disable-atomic-modesetting` | boolean | *detect* |
26+
| `renderer` | string | `"modeset"` |
27+
| `cursor` | boolean | `false` |
28+
| `pointer` | boolean | `false` |
2729

2830
The `device-scale-factor` option indicates a scaling factor to be applied to
2931
the rendered content. This is particularly useful for displays with a high
@@ -44,23 +46,34 @@ the output. Using the value `"gles"` will “paint” frames onto a quad using
4446
OpenGL ES. The main reason to use the latter is that it supports [output
4547
rotation](#output-rotation).
4648

49+
The `cursor` and `pointer` options control whether the hardware cursor
50+
sprite is drawn and whether `libinput` pointer events are forwarded to
51+
the page, respectively. See [Pointer Input](#pointer-input) for details.
52+
4753

4854
## Parameters
4955

5056
The following parameters can be passed to the platform plug-in during
5157
initialization (e.g. using `cog --platform-params=…`):
5258

53-
| Parameter | Type | Default |
54-
|:-----------|:-------|:----------|
55-
| `renderer` | string | `modeset` |
56-
| `rotation` | number | `0` |
59+
| Parameter | Type | Default |
60+
|:-----------|:--------|:----------|
61+
| `renderer` | string | `modeset` |
62+
| `rotation` | number | `0` |
63+
| `cursor` | boolean | `false` |
64+
| `pointer` | boolean | `false` |
5765

5866
The `renderer` parameter is the same as the [configuration file
5967
option](#configuration-file-options) of the same name.
6068

6169
The `rotation` parameter indicates the initial [output
6270
rotation](#output-rotation) applied.
6371

72+
The `cursor` and `pointer` parameters are the same as the
73+
[configuration file options](#configuration-file-options) of the same
74+
name. See [Pointer Input](#pointer-input) for details. Boolean values
75+
accept `true`, `on`, `1`, `false`, `off`, or `0`.
76+
6477

6578
## Environment Variables
6679

@@ -70,8 +83,9 @@ DRM plug-in operates:
7083
| Variable | Type | Default |
7184
|:---------|:-----|--------:|
7285
| `COG_PLATFORM_DRM_VIDEO_MODE` | string | *(unset*) |
73-
| `COG_PLATFORM_DRM_MODE_MAX` | string | *(unset)* |
74-
| `COG_PLATFORM_DRM_CURSOR` | string | *(unset)* |
86+
| `COG_PLATFORM_DRM_MODE_MAX` | string | *(unset)* |
87+
| `COG_PLATFORM_DRM_CURSOR` | string | *(unset)* |
88+
| `COG_PLATFORM_DRM_POINTER` | string | *(unset)* |
7589

7690
By default the preferred mode for the first found connected output is used
7791
(if available), otherwise the mode with highest resolution.
@@ -83,8 +97,45 @@ mode strings in the format `WxR` (`W`idth and `H`eight in pixels).
8397
a refresh rate in the format `WxH@R`.
8498
for example `1920x1080@60` for a typical Full-HD mode.
8599

86-
Setting `COG_PLATFORM_DRM_CURSOR` to a non-empty string enables showing
87-
the mouse cursor pointer.
100+
Setting `COG_PLATFORM_DRM_CURSOR` or `COG_PLATFORM_DRM_POINTER` to any
101+
non-empty value enables the corresponding option from
102+
[Pointer Input](#pointer-input).
103+
104+
105+
## Pointer Input
106+
107+
Two independent options control how the DRM platform handles
108+
mouse / touchpad input. Both default to off, in which case the plug-in
109+
still delivers keyboard and touchscreen events to the loaded page but
110+
ignores pointer-class devices entirely.
111+
112+
The `pointer` option forwards `libinput` pointer motion, button, and
113+
scroll events to WPE. The page then sees them as DOM `pointermove`,
114+
`pointerdown`, `pointerup`, and `wheel` events. This is independent of
115+
whether anything is drawn on screen; the page is responsible for any
116+
visual cursor (e.g. one drawn on a `<canvas>`).
117+
118+
The `cursor` option allocates a hardware cursor plane and draws a
119+
16×16 sprite on top of the rendered output, moved on every pointer-motion
120+
event. This requires the underlying DRM driver to expose a
121+
`DRM_PLANE_TYPE_CURSOR` plane; many minimal drivers (e.g. SPI/MIPI panels
122+
using `drm_simple_kms_helper`) do not, in which case this option has no
123+
visible effect even when enabled.
124+
125+
For backwards compatibility, enabling `cursor` implies `pointer`. The
126+
four combinations:
127+
128+
| `cursor` | `pointer` | Pointer events to WPE | Hardware cursor sprite |
129+
|:--------:|:---------:|:---------------------:|:----------------------:|
130+
| off | off | no | no |
131+
| off | on | yes | no |
132+
| on | off | yes (implied) | yes (if plane exists) |
133+
| on | on | yes | yes (if plane exists) |
134+
135+
Configuration precedence is: command-line parameter overrides
136+
configuration file, which overrides environment variable. The legacy
137+
behaviour of `COG_PLATFORM_DRM_CURSOR=1` (enabling both pointer dispatch
138+
and the sprite) is preserved by the `cursor``pointer` implication.
88139

89140

90141
## Output Rotation

platform/drm/cog-platform-drm.c

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct _CogDrmPlatform {
6868
CogDrmRenderer *renderer;
6969
CogGLRendererRotation rotation;
7070
GList *rotatable_input_devices;
71+
bool draw_cursor;
72+
bool dispatch_pointer;
7173
bool use_gles;
7274
};
7375

@@ -192,6 +194,8 @@ static struct {
192194
uint32_t input_width;
193195
uint32_t input_height;
194196

197+
bool dispatch_pointer;
198+
195199
struct keyboard_event repeating_key;
196200

197201
struct wpe_input_touch_event_raw touch_points[10];
@@ -203,6 +207,7 @@ static struct {
203207
.rotation = COG_GL_RENDERER_ROTATION_0,
204208
.input_width = 0,
205209
.input_height = 0,
210+
.dispatch_pointer = false,
206211
.repeating_key = {0, 0},
207212
.last_touch_type = wpe_input_touch_event_type_null,
208213
.last_touch_id = 0,
@@ -226,13 +231,30 @@ static struct {
226231
struct wpe_view_backend *backend;
227232
} wpe_view_data;
228233

234+
static bool
235+
parse_bool(const char *value, bool *out)
236+
{
237+
if (g_strcmp0(value, "true") == 0 || g_strcmp0(value, "on") == 0 || g_strcmp0(value, "1") == 0) {
238+
*out = true;
239+
return true;
240+
}
241+
if (g_strcmp0(value, "false") == 0 || g_strcmp0(value, "off") == 0 || g_strcmp0(value, "0") == 0) {
242+
*out = false;
243+
return true;
244+
}
245+
return false;
246+
}
247+
229248
static void
230249
init_config(CogDrmPlatform *self, CogShell *shell, const char *params_string)
231250
{
232251
drm_data.device_scale = cog_shell_get_device_scale_factor (shell);
233252
g_debug ("init_config: overriding device_scale value, using %.2f from shell",
234253
drm_data.device_scale);
235254

255+
self->draw_cursor = g_getenv("COG_PLATFORM_DRM_CURSOR") != NULL;
256+
self->dispatch_pointer = g_getenv("COG_PLATFORM_DRM_POINTER") != NULL;
257+
236258
GKeyFile *key_file = cog_shell_get_config_file (shell);
237259

238260
if (key_file) {
@@ -266,6 +288,20 @@ init_config(CogDrmPlatform *self, CogShell *shell, const char *params_string)
266288
else if (value)
267289
g_warning("Invalid renderer '%s', using default.", value);
268290
}
291+
292+
{
293+
g_autoptr(GError) lookup_error = NULL;
294+
gboolean value = g_key_file_get_boolean(key_file, "drm", "cursor", &lookup_error);
295+
if (!lookup_error)
296+
self->draw_cursor = value;
297+
}
298+
299+
{
300+
g_autoptr(GError) lookup_error = NULL;
301+
gboolean value = g_key_file_get_boolean(key_file, "drm", "pointer", &lookup_error);
302+
if (!lookup_error)
303+
self->dispatch_pointer = value;
304+
}
269305
}
270306

271307
if (params_string) {
@@ -295,11 +331,20 @@ init_config(CogDrmPlatform *self, CogShell *shell, const char *params_string)
295331
g_warning("Invalid value '%s' for parameter '%s'.", v, k);
296332
else
297333
self->rotation = val;
334+
} else if (g_strcmp0(k, "cursor") == 0) {
335+
if (!parse_bool(v, &self->draw_cursor))
336+
g_warning("Invalid value '%s' for parameter '%s'.", v, k);
337+
} else if (g_strcmp0(k, "pointer") == 0) {
338+
if (!parse_bool(v, &self->dispatch_pointer))
339+
g_warning("Invalid value '%s' for parameter '%s'.", v, k);
298340
} else {
299341
g_warning("Invalid parameter '%s'.", k);
300342
}
301343
}
302344
}
345+
346+
if (self->draw_cursor)
347+
self->dispatch_pointer = true;
303348
}
304349

305350
static void
@@ -636,11 +681,6 @@ init_cursor (void)
636681
return FALSE;
637682
}
638683

639-
cursor.x = (cursor.device->screens[0]->width - cursor.cursor->width) / 2;
640-
cursor.y = (cursor.device->screens[0]->height - cursor.cursor->height) / 2;
641-
cursor.screen_width = cursor.device->screens[0]->width;
642-
cursor.screen_height = cursor.device->screens[0]->height;
643-
644684
if (kms_plane_set(cursor.plane, cursor.cursor, cursor.x, cursor.y)) {
645685
g_clear_pointer(&cursor.device, kms_device_free);
646686
g_clear_pointer(&cursor.cursor, kms_framebuffer_free);
@@ -893,7 +933,7 @@ input_handle_touch_event (enum libinput_event_type touch_type, struct libinput_e
893933
static void
894934
input_handle_pointer_motion_event(struct libinput_event_pointer *pointer_event, bool absolute)
895935
{
896-
if (!cursor.enabled)
936+
if (!input_data.dispatch_pointer)
897937
return;
898938

899939
if (absolute) {
@@ -927,13 +967,14 @@ input_handle_pointer_motion_event(struct libinput_event_pointer *pointer_event,
927967
};
928968

929969
wpe_view_backend_dispatch_pointer_event(wpe_view_data.backend, &event);
930-
kms_plane_set(cursor.plane, cursor.cursor, cursor.x, cursor.y);
970+
if (cursor.enabled)
971+
kms_plane_set(cursor.plane, cursor.cursor, cursor.x, cursor.y);
931972
}
932973

933974
static void
934975
input_handle_pointer_button_event (struct libinput_event_pointer *pointer_event)
935976
{
936-
if (!cursor.enabled)
977+
if (!input_data.dispatch_pointer)
937978
return;
938979

939980
struct wpe_input_pointer_event event = {
@@ -953,6 +994,9 @@ input_handle_pointer_button_event (struct libinput_event_pointer *pointer_event)
953994
static void
954995
input_handle_pointer_discrete_scroll_event(struct libinput_event_pointer *pointer_event)
955996
{
997+
if (!input_data.dispatch_pointer)
998+
return;
999+
9561000
struct wpe_input_axis_2d_event event = {
9571001
.base.type = wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion,
9581002
.base.time = libinput_event_pointer_get_time(pointer_event),
@@ -975,6 +1019,9 @@ input_handle_pointer_discrete_scroll_event(struct libinput_event_pointer *pointe
9751019
static void
9761020
input_handle_pointer_smooth_scroll_event(struct libinput_event_pointer *pointer_event)
9771021
{
1022+
if (!input_data.dispatch_pointer)
1023+
return;
1024+
9781025
struct wpe_input_axis_2d_event event = {
9791026
.base.type = wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth,
9801027
.base.time = libinput_event_pointer_get_time(pointer_event),
@@ -997,6 +1044,9 @@ input_handle_pointer_smooth_scroll_event(struct libinput_event_pointer *pointer_
9971044
static void
9981045
input_handle_pointer_axis_event(struct libinput_event_pointer *pointer_event)
9991046
{
1047+
if (!input_data.dispatch_pointer)
1048+
return;
1049+
10001050
struct wpe_input_axis_2d_event event = {
10011051
.base.type = wpe_input_axis_event_type_mask_2d,
10021052
.base.time = libinput_event_pointer_get_time(pointer_event),
@@ -1291,6 +1341,7 @@ init_input(CogDrmPlatform *platform)
12911341
return FALSE;
12921342

12931343
input_data.rotation = platform->rotation;
1344+
input_data.dispatch_pointer = platform->dispatch_pointer;
12941345

12951346
int ret = libinput_udev_assign_seat (input_data.libinput, "seat0");
12961347
if (ret)
@@ -1303,6 +1354,11 @@ init_input(CogDrmPlatform *platform)
13031354
touch_point->type = wpe_input_touch_event_type_null;
13041355
}
13051356

1357+
cursor.screen_width = input_data.input_width;
1358+
cursor.screen_height = input_data.input_height;
1359+
cursor.x = cursor.screen_width / 2;
1360+
cursor.y = cursor.screen_height / 2;
1361+
13061362
return TRUE;
13071363
}
13081364

@@ -1457,7 +1513,7 @@ cog_drm_platform_setup(CogPlatform *platform, CogShell *shell, const char *param
14571513
return FALSE;
14581514
}
14591515

1460-
if (g_getenv ("COG_PLATFORM_DRM_CURSOR")) {
1516+
if (self->draw_cursor) {
14611517
if (!init_cursor ()) {
14621518
g_warning ("Failed to initialize cursor");
14631519
}

0 commit comments

Comments
 (0)