[PATCH] xwayland: Clear pending cursor frame callbacks on pointer enter
The last cursor frame we commited before the pointer left one of our surfaces might not have been shown. In that case we'll have a cursor surface frame callback pending which we need to clear so that we can continue submitting new cursor frames. Signed-off-by: Rui Matos Reviewed-by: Daniel Stone --- v2: as suggested by Jonas, moved the hunk further up to stay close to another related hack we already have and also removed the xwl_seat_set_cursor() call since CheckMotion() will do that too. I think Daniel's r-b still stands anyway. hw/xwayland/xwayland-input.c | 9 + 1 file changed, 9 insertions(+) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 61ca70b..d6cbf32 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -251,6 +251,15 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, mipointer = MIPOINTER(master); mipointer->pSpriteCursor = (CursorPtr) 1; +/* The last cursor frame we commited before the pointer left one + * of our surfaces might not have been shown. In that case we'll + * have a cursor surface frame callback pending which we need to + * clear so that we can continue submitting new cursor frames. */ +if (xwl_seat->cursor_frame_cb) { +wl_callback_destroy(xwl_seat->cursor_frame_cb); +xwl_seat->cursor_frame_cb = NULL; +} + CheckMotion(NULL, master); /* Ideally, X clients shouldn't see these button releases. When -- 2.5.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] xwayland: Clear pending cursor frame callbacks on pointer enter
The last cursor frame we commited before the pointer left one of our surfaces might not have been shown. In that case we'll have a cursor surface frame callback pending which we need to clear so that we can continue submitting new cursor frames. Signed-off-by: Rui Matos --- On Wed, Feb 3, 2016 at 9:30 AM, Pekka Paalanen wrote: > Xwayland commits a wl_buffer to a cursor wl_surface with a frame > callback, and the frame callback may never be emitted by the > compositor, right? > > Is Xwayland waiting for any previous frame callback to be signalled > before it commits a buffer or re-sets the cursor role on the > wl_surface? Even if the commit and re-set is caused by wl_pointer.enter? > > Would it be a better fix to destroy any pending frame callback and > commit and re-set the role unconditionally on wl_pointer.enter? Yes, this seems like the proper fix indeed. Thanks, Rui hw/xwayland/xwayland-input.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 61ca70b..f9e3255 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -267,6 +267,16 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer, for (i = 0; i < dev->button->numButtons; i++) if (BitIsOn(dev->button->down, i)) QueuePointerEvents(dev, ButtonRelease, i, 0, &mask); + +/* The last cursor frame we commited before the pointer left one + * of our surfaces might not have been shown. In that case we'll + * have a cursor surface frame callback pending which we need to + * clear so that we can continue submitting new cursor frames. */ +if (xwl_seat->cursor_frame_cb) { +wl_callback_destroy(xwl_seat->cursor_frame_cb); +xwl_seat->cursor_frame_cb = NULL; +xwl_seat_set_cursor(xwl_seat); +} } static void -- 2.5.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] xwayland: Throttle our cursor surface updates with a frame callback
In some extreme cases with animated cursors at a high frame rate we could end up filling the wl_display outgoing buffer and end up with wl_display_flush() failing. In any case, using the frame callback to throttle ourselves is the right thing to do. Signed-off-by: Rui Matos --- On Tue, May 26, 2015 at 10:58 PM, Keith Packard wrote: > Looks like there have been some other updates in this area? Can I get > one of you to build a patch on master? Sorry, my master branch was a couple of weeks old. Rebased. hw/xwayland/xwayland-cursor.c | 26 ++ hw/xwayland/xwayland-input.c | 2 ++ hw/xwayland/xwayland.h| 4 +++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index 5a9d1fe..c137e1e 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -82,6 +82,23 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) return xwl_shm_destroy_pixmap(pixmap); } +static void +frame_callback(void *data, + struct wl_callback *callback, + uint32_t time) +{ +struct xwl_seat *xwl_seat = data; +xwl_seat->cursor_frame_cb = NULL; +if (xwl_seat->cursor_needs_update) { +xwl_seat->cursor_needs_update = FALSE; +xwl_seat_set_cursor(xwl_seat); +} +} + +static const struct wl_callback_listener frame_listener = { +frame_callback +}; + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat) { @@ -98,6 +115,11 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) return; } +if (xwl_seat->cursor_frame_cb) { +xwl_seat->cursor_needs_update = TRUE; +return; +} + cursor = xwl_seat->x_cursor; pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); stride = cursor->bits->width * 4; @@ -117,6 +139,10 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) wl_surface_damage(xwl_seat->cursor, 0, 0, xwl_seat->x_cursor->bits->width, xwl_seat->x_cursor->bits->height); + +xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor); +wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat); + wl_surface_commit(xwl_seat->cursor); } diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 51a3379..af11c5b 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -559,6 +559,8 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) RemoveDevice(xwl_seat->keyboard, FALSE); wl_seat_destroy(xwl_seat->seat); wl_surface_destroy(xwl_seat->cursor); +if (xwl_seat->cursor_frame_cb) +wl_callback_destroy(xwl_seat->cursor_frame_cb); wl_array_release(&xwl_seat->keys); free(xwl_seat); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index cfb343d..28b0c99 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -115,12 +115,14 @@ struct xwl_seat { struct wl_pointer *wl_pointer; struct wl_keyboard *wl_keyboard; struct wl_array keys; -struct wl_surface *cursor; struct xwl_window *focus_window; uint32_t id; uint32_t pointer_enter_serial; struct xorg_list link; CursorPtr x_cursor; +struct wl_surface *cursor; +struct wl_callback *cursor_frame_cb; +Bool cursor_needs_update; size_t keymap_size; char *keymap; -- 2.4.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] xwayland: Throttle our cursor surface updates with a frame callback
In some extreme cases with animated cursors at a high frame rate we could end up filling the wl_display outgoing buffer and end up with wl_display_flush() failing. In any case, using the frame callback to throttle ourselves is the right thing to do. Signed-off-by: Rui Matos --- v2: ensure that we don't lose cursor updates requested while a frame callback is pending hw/xwayland/xwayland-cursor.c | 26 ++ hw/xwayland/xwayland-input.c | 2 ++ hw/xwayland/xwayland.h| 4 +++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index 5a9d1fe..c137e1e 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -82,6 +82,23 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) return xwl_shm_destroy_pixmap(pixmap); } +static void +frame_callback(void *data, + struct wl_callback *callback, + uint32_t time) +{ +struct xwl_seat *xwl_seat = data; +xwl_seat->cursor_frame_cb = NULL; +if (xwl_seat->cursor_needs_update) { +xwl_seat->cursor_needs_update = FALSE; +xwl_seat_set_cursor(xwl_seat); +} +} + +static const struct wl_callback_listener frame_listener = { +frame_callback +}; + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat) { @@ -98,6 +115,11 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) return; } +if (xwl_seat->cursor_frame_cb) { +xwl_seat->cursor_needs_update = TRUE; +return; +} + cursor = xwl_seat->x_cursor; pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); stride = cursor->bits->width * 4; @@ -117,6 +139,10 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) wl_surface_damage(xwl_seat->cursor, 0, 0, xwl_seat->x_cursor->bits->width, xwl_seat->x_cursor->bits->height); + +xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor); +wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat); + wl_surface_commit(xwl_seat->cursor); } diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 5230d8c..a3142f4 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -586,6 +586,8 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) RemoveDevice(xwl_seat->keyboard, FALSE); wl_seat_destroy(xwl_seat->seat); wl_surface_destroy(xwl_seat->cursor); +if (xwl_seat->cursor_frame_cb) +wl_callback_destroy(xwl_seat->cursor_frame_cb); wl_array_release(&xwl_seat->keys); free(xwl_seat); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index bfffa71..a31c040 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -115,12 +115,14 @@ struct xwl_seat { struct wl_pointer *wl_pointer; struct wl_keyboard *wl_keyboard; struct wl_array keys; -struct wl_surface *cursor; struct xwl_window *focus_window; uint32_t id; uint32_t pointer_enter_serial; struct xorg_list link; CursorPtr x_cursor; +struct wl_surface *cursor; +struct wl_callback *cursor_frame_cb; +Bool cursor_needs_update; wl_fixed_t horizontal_scroll; wl_fixed_t vertical_scroll; -- 2.4.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH xwayland] xwayland: Throttle our cursor surface updates with a frame callback
In some extreme cases with animated cursors at a high frame rate we could end up filling the wl_display outgoing buffer and end up with wl_display_flush() failing. In any case, using the frame callback to throttle ourselves is the right thing to do. Signed-off-by: Rui Matos --- hw/xwayland/xwayland-cursor.c | 20 hw/xwayland/xwayland-input.c | 2 ++ hw/xwayland/xwayland.h| 1 + 3 files changed, 23 insertions(+) diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c index 5a9d1fe..3ba5ad6 100644 --- a/hw/xwayland/xwayland-cursor.c +++ b/hw/xwayland/xwayland-cursor.c @@ -82,6 +82,19 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) return xwl_shm_destroy_pixmap(pixmap); } +static void +frame_callback(void *data, + struct wl_callback *callback, + uint32_t time) +{ +struct xwl_seat *xwl_seat = data; +xwl_seat->cursor_frame_cb = NULL; +} + +static const struct wl_callback_listener frame_listener = { +frame_callback +}; + void xwl_seat_set_cursor(struct xwl_seat *xwl_seat) { @@ -98,6 +111,9 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) return; } +if (xwl_seat->cursor_frame_cb) +return; + cursor = xwl_seat->x_cursor; pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key); stride = cursor->bits->width * 4; @@ -117,6 +133,10 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) wl_surface_damage(xwl_seat->cursor, 0, 0, xwl_seat->x_cursor->bits->width, xwl_seat->x_cursor->bits->height); + +xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor); +wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat); + wl_surface_commit(xwl_seat->cursor); } diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 5230d8c..a3142f4 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -586,6 +586,8 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat) RemoveDevice(xwl_seat->keyboard, FALSE); wl_seat_destroy(xwl_seat->seat); wl_surface_destroy(xwl_seat->cursor); +if (xwl_seat->cursor_frame_cb) +wl_callback_destroy(xwl_seat->cursor_frame_cb); wl_array_release(&xwl_seat->keys); free(xwl_seat); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index bfffa71..92d6d6e 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -116,6 +116,7 @@ struct xwl_seat { struct wl_keyboard *wl_keyboard; struct wl_array keys; struct wl_surface *cursor; +struct wl_callback *cursor_frame_cb; struct xwl_window *focus_window; uint32_t id; uint32_t pointer_enter_serial; -- 2.4.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] touchpad: Make sure we don't underflow tap_finger_count
If a touch begins before tap gets enabled we underflow tap_finger_count when the touch ends. This happens in practice when enabling tapping on a GUI with a touchpad click. Signed-off-by: Rui Matos --- This patch seems enough to fix the issue in my testing but I'm not familiar with the state machine so it might not be the best solution. src/evdev-mt-touchpad-tap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 0f25e26..0feff70 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -659,7 +659,8 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time); } else if (t->state == TOUCH_END) { - tp->tap.tap_finger_count--; + if (tp->tap.tap_finger_count > 0) + tp->tap.tap_finger_count--; tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time); t->tap.state = TAP_TOUCH_STATE_IDLE; } else if (tp->tap.state != TAP_STATE_IDLE && -- 2.3.6 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] doc/publican/Makefile.am: Add a missing order-only prerequisite
Otherwise a parallel make invocation could fail due to the directory not existing. Signed-off-by: Rui Matos --- doc/publican/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/publican/Makefile.am b/doc/publican/Makefile.am index 278da12..50a6188 100644 --- a/doc/publican/Makefile.am +++ b/doc/publican/Makefile.am @@ -85,7 +85,7 @@ $(builddir)/en-US/ProtocolSpec.xml: $(top_srcdir)/protocol/wayland.xml $(srcdir) $(AM_V_GEN)$(XSLTPROC) $(srcdir)/protocol-to-docbook.xsl \ $(top_srcdir)/protocol/wayland.xml > $@ -$(builddir)/en-US/ProtocolInterfaces.xml: $(top_srcdir)/protocol/wayland.xml $(srcdir)/protocol-interfaces-to-docbook.xsl +$(builddir)/en-US/ProtocolInterfaces.xml: $(top_srcdir)/protocol/wayland.xml $(srcdir)/protocol-interfaces-to-docbook.xsl | $(builddir)/en-US $(AM_V_GEN)$(XSLTPROC) $(srcdir)/protocol-interfaces-to-docbook.xsl \ $(top_srcdir)/protocol/wayland.xml > $@ -- 2.1.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] protocol: Document how clients are supposed to get the xkb keycode
This encodes what everyone is doing and avoids other implementers having to guess. --- Jasper suggested that it would be nice if the compositor sent keycodes that clients could use directly as an index in the keymap. I suppose we can't do that at this point so we should at least document it clearly in the protocol so that implementers don't have to guess. protocol/wayland.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol/wayland.xml b/protocol/wayland.xml index 3aa89af..db1b349 100644 --- a/protocol/wayland.xml +++ b/protocol/wayland.xml @@ -1503,7 +1503,8 @@ - + -- 1.9.0 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] xwayland: Destroy wl_buffers only after they are released
Destroying a wl_buffer that is still attached to a wl_surface is undefined behavior according to the wayland protocol. We should delay the destruction until we get the release event. To achieve this we need to track ownership of wl_buffers, both our own and the compositor's which occurs from either the first commit request or the first commit request after a release event until the next release event. --- On 12 February 2014 08:54, Pekka Paalanen wrote: > I assume the code never added a wl_buffer listener before, because if > it did, this patch would be a no-op. "wl_buffer_add_listener" is a > misnomer, there can only ever be one listener, and trying to "add" > another will not actually do anything. Thanks for the headsup. But, indeed, there was nothing adding a wl_buffer listener before. > Also, you rely on wl_buffer.release not having arrived before you add > the listener. With weston's gl-renderer, the release comes very soon > after each wl_surface.commit for wl_shm buffers. Maybe it works, maybe > it doesn't, but it seems very fragile. Did you check you don't leak > wl_buffers now? Right, I was leaking in some cases. So, I came up with the solution below which, if I'm reading the logs correctly, doesn't leak and works correctly. This solution abuses the user_data field to essentially keep two toggle references, our own and the compositor's, and only destroys the wl_buffer when both are dropped. Thanks, Rui --- hw/xfree86/xwayland/xwayland-cursor.c | 4 ++- hw/xfree86/xwayland/xwayland-private.h | 4 +++ hw/xfree86/xwayland/xwayland-window.c | 8 +++--- hw/xfree86/xwayland/xwayland.c | 50 ++ 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-cursor.c b/hw/xfree86/xwayland/xwayland-cursor.c index 2b3cb5e..232b038 100644 --- a/hw/xfree86/xwayland/xwayland-cursor.c +++ b/hw/xfree86/xwayland/xwayland-cursor.c @@ -125,6 +125,7 @@ xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) cursor->bits->width, cursor->bits->height, cursor->bits->width * 4, WL_SHM_FORMAT_ARGB); +_buffer_init(buffer); wl_shm_pool_destroy(pool); dixSetPrivate(&cursor->devPrivates, @@ -143,7 +144,7 @@ xwl_unrealize_cursor(DeviceIntPtr device, xwl_screen = xwl_screen_get(screen); buffer = dixGetPrivate(&cursor->devPrivates, &xwl_screen->cursor_private_key); -wl_buffer_destroy(buffer); +_buffer_disown(buffer); return TRUE; } @@ -176,6 +177,7 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat) xwl_seat->x_cursor->bits->width, xwl_seat->x_cursor->bits->height); wl_surface_commit(xwl_seat->cursor); +_buffer_commited(buffer); } static void diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h index bdecf8a..41e7e13 100644 --- a/hw/xfree86/xwayland/xwayland-private.h +++ b/hw/xfree86/xwayland/xwayland-private.h @@ -137,4 +137,8 @@ void xwl_output_remove(struct xwl_output *output); extern const struct xserver_listener xwl_server_listener; +void _buffer_commited(struct wl_buffer *buffer); +void _buffer_disown(struct wl_buffer *buffer); +void _buffer_init(struct wl_buffer *buffer); + #endif /* _XWAYLAND_PRIVATE_H_ */ diff --git a/hw/xfree86/xwayland/xwayland-window.c b/hw/xfree86/xwayland/xwayland-window.c index a2a8206..d18c7f6 100644 --- a/hw/xfree86/xwayland/xwayland-window.c +++ b/hw/xfree86/xwayland/xwayland-window.c @@ -62,10 +62,8 @@ xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap) struct xwl_screen *xwl_screen = xwl_window->xwl_screen; struct wl_callback *callback; -/* We can safely destroy the buffer because we only use one buffer - * per surface in xwayland model */ if (xwl_window->buffer) -wl_buffer_destroy(xwl_window->buffer); +_buffer_disown(xwl_window->buffer); xwl_screen->driver->create_window_buffer(xwl_window, pixmap); @@ -74,6 +72,8 @@ xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap) return; } +_buffer_init(xwl_window->buffer); + wl_surface_attach(xwl_window->surface, xwl_window->buffer, 0, 0); wl_surface_damage(xwl_window->surface, 0, 0, pixmap->drawable.width, @@ -185,7 +185,7 @@ xwl_unrealize_window(WindowPtr window) return ret; if (xwl_window->buffer) - wl_buffer_destroy(xwl_window->buffer); +_buffer_disown(xwl_window->buffer); wl_surface_destroy(xwl_window->surface); xorg_list_del(&xwl_window->link); if (RegionNotEmpty(DamageRegion(xwl_window->damage))) diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c index c70a52d..c373fcc 100644 --- a/hw/xfree86/xwayland/xwayland.c +++ b/hw/xfree86/xwayland/xwayland.c @@ -72,6 +72,55 @@
[PATCH] xwayland: Destroy wl_buffers only after they are released
Destroying a wl_buffer that is still attached to a wl_surface is undefined behavior according to the wayland protocol. We should delay the destruction until we get the release event. --- So, I'm not sure why there was this comment saying that it was safe to do this, perhaps it was in an old protocol version? In any case, this has been making xwayland crash under mutter ever since this mutter commit https://git.gnome.org/browse/mutter/commit/?h=wayland&id=3e98ffaf9958366b584b360ac12bbc03cd070c07 . hw/xfree86/xwayland/xwayland-window.c | 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-window.c b/hw/xfree86/xwayland/xwayland-window.c index a2a8206..a005cc6 100644 --- a/hw/xfree86/xwayland/xwayland-window.c +++ b/hw/xfree86/xwayland/xwayland-window.c @@ -43,6 +43,16 @@ static DevPrivateKeyRec xwl_window_private_key; static void +free_buffer(void *data, struct wl_buffer *buffer) +{ +wl_buffer_destroy(buffer); +} + +static const struct wl_buffer_listener buffer_listener = { +free_buffer, +}; + +static void free_pixmap(void *data, struct wl_callback *callback, uint32_t time) { PixmapPtr pixmap = data; @@ -62,10 +72,8 @@ xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap) struct xwl_screen *xwl_screen = xwl_window->xwl_screen; struct wl_callback *callback; -/* We can safely destroy the buffer because we only use one buffer - * per surface in xwayland model */ if (xwl_window->buffer) -wl_buffer_destroy(xwl_window->buffer); +wl_buffer_add_listener(xwl_window->buffer, &buffer_listener, NULL); xwl_screen->driver->create_window_buffer(xwl_window, pixmap); @@ -185,7 +193,7 @@ xwl_unrealize_window(WindowPtr window) return ret; if (xwl_window->buffer) - wl_buffer_destroy(xwl_window->buffer); +wl_buffer_add_listener(xwl_window->buffer, &buffer_listener, NULL); wl_surface_destroy(xwl_window->surface); xorg_list_del(&xwl_window->link); if (RegionNotEmpty(DamageRegion(xwl_window->damage))) -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] input: Don't leak the initial keymap
weston_xkb_info_create() takes ownership of the xkb_keymap instance so we should drop our reference or we would leak it later if the keymap was changed. --- src/input.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/input.c b/src/input.c index 2fed718..da89b47 100644 --- a/src/input.c +++ b/src/input.c @@ -1706,6 +1706,7 @@ weston_compositor_build_global_keymap(struct weston_compositor *ec) } ec->xkb_info = weston_xkb_info_create(keymap); + xkb_keymap_unref(keymap); if (ec->xkb_info == NULL) return -1; -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH] xwayland: Handle the wl_keyboard modifiers event
This allows us to keep track of latched and locked modifiers as well as the XKB group while the keyboard focus is on another wayland client. Note that we don't need to track depressed modifiers since wayland guarantees that we'll get them as key press events whenever we get the keyboard focus. --- hw/xfree86/xwayland/xwayland-input.c | 40 +- hw/xfree86/xwayland/xwayland-private.h | 2 +- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-input.c b/hw/xfree86/xwayland/xwayland-input.c index ebf1af1..2f14b20 100644 --- a/hw/xfree86/xwayland/xwayland-input.c +++ b/hw/xfree86/xwayland/xwayland-input.c @@ -504,6 +504,7 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, uint32_t *k; xwl_seat->xwl_screen->serial = serial; +xwl_seat->keyboard_focus = surface; wl_array_copy(&xwl_seat->keys, keys); wl_array_for_each(k, &xwl_seat->keys) @@ -521,6 +522,8 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, wl_array_for_each(k, &xwl_seat->keys) xf86PostKeyboardEvent(xwl_seat->keyboard, *k + 8, 0); + +xwl_seat->keyboard_focus = NULL; } static void @@ -529,7 +532,42 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { -/* FIXME: Need more server XKB API here. */ +struct xwl_seat *xwl_seat = data; +DeviceIntPtr dev; +XkbStateRec old_state, *new_state; +xkbStateNotify sn; +CARD16 changed; + +/* We don't need any of this while we have keyboard focus since + the regular key event processing already takes care of setting + our internal state correctly. */ +if (xwl_seat->keyboard_focus) +return; + +for (dev = inputInfo.devices; dev; dev = dev->next) { +if (dev != xwl_seat->keyboard && dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD)) +continue; + +old_state = dev->key->xkbInfo->state; +new_state = &dev->key->xkbInfo->state; + +new_state->locked_group = group & XkbAllGroupsMask; +new_state->locked_mods = mods_locked & XkbAllModifiersMask; +XkbLatchModifiers(dev, XkbAllModifiersMask, mods_latched & XkbAllModifiersMask); + +XkbComputeDerivedState(dev->key->xkbInfo); + +changed = XkbStateChangedFlags(&old_state, new_state); +if (!changed) +continue; + +sn.keycode = 0; +sn.eventType = 0; +sn.requestMajor = XkbReqCode; +sn.requestMinor = X_kbLatchLockState; /* close enough */ +sn.changed = changed; +XkbSendStateNotify(dev, &sn); +} } static const struct wl_keyboard_listener keyboard_listener = { diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h index aa9fc03..bdecf8a 100644 --- a/hw/xfree86/xwayland/xwayland-private.h +++ b/hw/xfree86/xwayland/xwayland-private.h @@ -112,7 +112,7 @@ struct xwl_seat { size_t keymap_size; char *keymap; - +struct wl_surface *keyboard_focus; }; -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH v2 1/3] xkb: Repurpose XkbCopyDeviceKeymap to apply a given keymap to a device
This will also make it useful for cases when we have a new keymap to apply to a device but don't have a source device. --- On 21 October 2013 19:04, Daniel Stone wrote: > CopyKeyClass is only called when device->key is set. True, amended. > But for the rest: > Reviewed-by: Daniel Stone Thanks for the reviews. Rui Xi/exevents.c| 2 +- include/xkbsrv.h | 4 ++-- xkb/xkb.c| 2 +- xkb/xkbUtils.c | 14 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index f510a9e..5b6d370 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -230,7 +230,7 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) mk->sourceid = device->id; -if (!XkbCopyDeviceKeymap(master, device)) +if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc)) FatalError("Couldn't pivot keymap from device to core!\n"); } diff --git a/include/xkbsrv.h b/include/xkbsrv.h index bef98ef..83ee1d0 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -812,8 +812,8 @@ extern _X_EXPORT void XkbSendNewKeyboardNotify(DeviceIntPtr /* kbd */ , extern Bool XkbCopyKeymap(XkbDescPtr /* dst */ , XkbDescPtr /* src */ ); -extern _X_EXPORT Bool XkbCopyDeviceKeymap(DeviceIntPtr /* dst */ , - DeviceIntPtr /* src */ ); +extern _X_EXPORT Bool XkbDeviceApplyKeymap(DeviceIntPtr /* dst */ , + XkbDescPtr /* src */ ); extern void XkbFilterEvents(ClientPtr /* pClient */ , int /* nEvents */ , diff --git a/xkb/xkb.c b/xkb/xkb.c index c78aceb..7a631b8 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5991,7 +5991,7 @@ ProcXkbGetKbdByName(ClientPtr client) continue; if (tmpd != dev) -XkbCopyDeviceKeymap(tmpd, dev); +XkbDeviceApplyKeymap(tmpd, xkb); if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { old_sli = tmpd->kbdfeed->xkb_sli; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 6c6af60..1f8a839 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -1999,28 +1999,28 @@ XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src) } Bool -XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) +XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc) { xkbNewKeyboardNotify nkn; Bool ret; -if (!dst->key || !src->key) +if (!dst->key || !desc) return FALSE; memset(&nkn, 0, sizeof(xkbNewKeyboardNotify)); nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code; nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code; nkn.deviceID = dst->id; -nkn.oldDeviceID = dst->id; /* maybe src->id? */ -nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code; -nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code; +nkn.oldDeviceID = dst->id; +nkn.minKeyCode = desc->min_key_code; +nkn.maxKeyCode = desc->max_key_code; nkn.requestMajor = XkbReqCode; nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */ nkn.changed = XkbNKN_KeycodesMask; -if (src->key->xkbInfo->desc->geom) +if (desc->geom) nkn.changed |= XkbNKN_GeometryMask; -ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc); +ret = XkbCopyKeymap(dst->key->xkbInfo->desc, desc); if (ret) XkbSendNewKeyboardNotify(dst, &nkn); -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 3/3] xwayland: Handle keymap changes
--- hw/xfree86/xwayland/xwayland-input.c | 39 +--- include/input.h | 2 +- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/hw/xfree86/xwayland/xwayland-input.c b/hw/xfree86/xwayland/xwayland-input.c index d031b34..ebf1af1 100644 --- a/hw/xfree86/xwayland/xwayland-input.c +++ b/hw/xfree86/xwayland/xwayland-input.c @@ -143,7 +143,10 @@ xwl_keyboard_proc(DeviceIntPtr device, int what) switch (what) { case DEVICE_INIT: device->public.on = FALSE; - len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size); +if (xwl_seat->keymap) +len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size); +else +len = 0; if (!InitKeyboardDeviceStructFromString(device, xwl_seat->keymap, len, NULL, xwl_keyboard_control)) @@ -453,12 +456,42 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) { struct xwl_seat *xwl_seat = data; +DeviceIntPtr master; +XkbDescPtr xkb; +XkbChangesRec changes = { 0 }; + +if (xwl_seat->keymap) +munmap(xwl_seat->keymap, xwl_seat->keymap_size); xwl_seat->keymap_size = size; xwl_seat->keymap = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); -if (xwl_seat->keymap == MAP_FAILED) - ; /* wah wah */ +if (xwl_seat->keymap == MAP_FAILED) { +xwl_seat->keymap_size = 0; +xwl_seat->keymap = NULL; +goto out; +} + +if (!xwl_seat->keyboard) +goto out; + +xkb = XkbCompileKeymapFromString(xwl_seat->keyboard, xwl_seat->keymap, + strnlen(xwl_seat->keymap, xwl_seat->keymap_size)); +if (!xkb) +goto out; + +XkbUpdateDescActions(xkb, xkb->min_key_code, XkbNumKeys(xkb), &changes); +/* Keep the current controls */ +XkbCopyControls(xkb, xwl_seat->keyboard->key->xkbInfo->desc); + +XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb); + +master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD); +if (master && master->lastSlave == xwl_seat->keyboard) +XkbDeviceApplyKeymap(master, xkb); + +XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE); + out: close(fd); } diff --git a/include/input.h b/include/input.h index 9f09e65..ecbcb0a 100644 --- a/include/input.h +++ b/include/input.h @@ -508,7 +508,7 @@ extern int AttachDevice(ClientPtr client, DeviceIntPtr slave, DeviceIntPtr master); extern _X_EXPORT DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd); -extern DeviceIntPtr GetMaster(DeviceIntPtr dev, int type); +extern _X_EXPORT DeviceIntPtr GetMaster(DeviceIntPtr dev, int type); extern _X_EXPORT int AllocDevicePair(ClientPtr client, const char *name, -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 2/3] xkb: Factor out a function to copy a keymap's controls unto another
--- include/xkbsrv.h | 3 +++ xkb/xkb.c| 14 +- xkb/xkbUtils.c | 23 +++ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/xkbsrv.h b/include/xkbsrv.h index 83ee1d0..6a2e96e 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -829,6 +829,9 @@ extern void XkbFakeDeviceButton(DeviceIntPtr /* dev */ , int /* press */ , int /* button */ ); +extern _X_EXPORT void XkbCopyControls(XkbDescPtr /* dst */ , + XkbDescPtr /* src */ ); + #include "xkbfile.h" #include "xkbrules.h" diff --git a/xkb/xkb.c b/xkb/xkb.c index 7a631b8..6a68e81 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5950,25 +5950,13 @@ ProcXkbGetKbdByName(ClientPtr client) if (rep.loaded) { XkbDescPtr old_xkb; xkbNewKeyboardNotify nkn; -int i, nG, nTG; old_xkb = xkb; xkb = new; dev->key->xkbInfo->desc = xkb; new = old_xkb; /* so it'll get freed automatically */ -*xkb->ctrls = *old_xkb->ctrls; -for (nG = nTG = 0, i = xkb->min_key_code; i <= xkb->max_key_code; i++) { -nG = XkbKeyNumGroups(xkb, i); -if (nG >= XkbNumKbdGroups) { -nTG = XkbNumKbdGroups; -break; -} -if (nG > nTG) { -nTG = nG; -} -} -xkb->ctrls->num_groups = nTG; +XkbCopyControls(xkb, old_xkb); nkn.deviceID = nkn.oldDeviceID = dev->id; nkn.minKeyCode = new->min_key_code; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 1f8a839..6cf6e79 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -2090,3 +2090,26 @@ XkbMergeLockedPtrBtns(DeviceIntPtr master) xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons; } } + +void +XkbCopyControls(XkbDescPtr dst, XkbDescPtr src) +{ +int i, nG, nTG; + +if (!dst || !src) +return; + +*dst->ctrls = *src->ctrls; + +for (nG = nTG = 0, i = dst->min_key_code; i <= dst->max_key_code; i++) { +nG = XkbKeyNumGroups(dst, i); +if (nG >= XkbNumKbdGroups) { +nTG = XkbNumKbdGroups; +break; +} +if (nG > nTG) { +nTG = nG; +} +} +dst->ctrls->num_groups = nTG; +} -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 1/3] xkb: Repurpose XkbCopyDeviceKeymap to apply a given keymap to a device
This will also make it useful for cases when we have a new keymap to apply to a device but don't have a source device. --- Xi/exevents.c| 2 +- include/xkbsrv.h | 4 ++-- xkb/xkb.c| 2 +- xkb/xkbUtils.c | 14 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index f510a9e..8aec526 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -230,7 +230,7 @@ CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) mk->sourceid = device->id; -if (!XkbCopyDeviceKeymap(master, device)) +if (device->key && !XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc)) FatalError("Couldn't pivot keymap from device to core!\n"); } diff --git a/include/xkbsrv.h b/include/xkbsrv.h index bef98ef..83ee1d0 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -812,8 +812,8 @@ extern _X_EXPORT void XkbSendNewKeyboardNotify(DeviceIntPtr /* kbd */ , extern Bool XkbCopyKeymap(XkbDescPtr /* dst */ , XkbDescPtr /* src */ ); -extern _X_EXPORT Bool XkbCopyDeviceKeymap(DeviceIntPtr /* dst */ , - DeviceIntPtr /* src */ ); +extern _X_EXPORT Bool XkbDeviceApplyKeymap(DeviceIntPtr /* dst */ , + XkbDescPtr /* src */ ); extern void XkbFilterEvents(ClientPtr /* pClient */ , int /* nEvents */ , diff --git a/xkb/xkb.c b/xkb/xkb.c index c78aceb..7a631b8 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5991,7 +5991,7 @@ ProcXkbGetKbdByName(ClientPtr client) continue; if (tmpd != dev) -XkbCopyDeviceKeymap(tmpd, dev); +XkbDeviceApplyKeymap(tmpd, xkb); if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) { old_sli = tmpd->kbdfeed->xkb_sli; diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 6c6af60..1f8a839 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -1999,28 +1999,28 @@ XkbCopyKeymap(XkbDescPtr dst, XkbDescPtr src) } Bool -XkbCopyDeviceKeymap(DeviceIntPtr dst, DeviceIntPtr src) +XkbDeviceApplyKeymap(DeviceIntPtr dst, XkbDescPtr desc) { xkbNewKeyboardNotify nkn; Bool ret; -if (!dst->key || !src->key) +if (!dst->key || !desc) return FALSE; memset(&nkn, 0, sizeof(xkbNewKeyboardNotify)); nkn.oldMinKeyCode = dst->key->xkbInfo->desc->min_key_code; nkn.oldMaxKeyCode = dst->key->xkbInfo->desc->max_key_code; nkn.deviceID = dst->id; -nkn.oldDeviceID = dst->id; /* maybe src->id? */ -nkn.minKeyCode = src->key->xkbInfo->desc->min_key_code; -nkn.maxKeyCode = src->key->xkbInfo->desc->max_key_code; +nkn.oldDeviceID = dst->id; +nkn.minKeyCode = desc->min_key_code; +nkn.maxKeyCode = desc->max_key_code; nkn.requestMajor = XkbReqCode; nkn.requestMinor = X_kbSetMap; /* Near enough's good enough. */ nkn.changed = XkbNKN_KeycodesMask; -if (src->key->xkbInfo->desc->geom) +if (desc->geom) nkn.changed |= XkbNKN_GeometryMask; -ret = XkbCopyKeymap(dst->key->xkbInfo->desc, src->key->xkbInfo->desc); +ret = XkbCopyKeymap(dst->key->xkbInfo->desc, desc); if (ret) XkbSendNewKeyboardNotify(dst, &nkn); -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH xwayland] Handle wayland keymap events
These patches add support for changing the X keymap on wayland keymap events. I wonder what we should do for X client requests to change the keymap though. We could: a) somehow try to change the wayland keymap accordingly, possibly through some private compositor protocol; b) ignore such requests, which seems legal according to both the core X protocol and XKB; c) keep the current status quo, i.e. if an X client changes the keymap we have a different keymap for X clients and wayland clients until the next time the wayland keymap is updated. Rui ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH v2 4/4] clients/window: Dispose of previous keymap and state on keymap change
--- clients/window.c | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/clients/window.c b/clients/window.c index 5b20da5..1f32c73 100644 --- a/clients/window.c +++ b/clients/window.c @@ -3037,6 +3037,8 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) { struct input *input = data; + struct xkb_keymap *keymap; + struct xkb_state *state; char *map_str; if (!data) { @@ -3055,26 +3057,30 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } - input->xkb.keymap = xkb_map_new_from_string(input->display->xkb_context, - map_str, - XKB_KEYMAP_FORMAT_TEXT_V1, - 0); + keymap = xkb_map_new_from_string(input->display->xkb_context, +map_str, +XKB_KEYMAP_FORMAT_TEXT_V1, +0); munmap(map_str, size); close(fd); - if (!input->xkb.keymap) { + if (!keymap) { fprintf(stderr, "failed to compile keymap\n"); return; } - input->xkb.state = xkb_state_new(input->xkb.keymap); - if (!input->xkb.state) { + state = xkb_state_new(keymap); + if (!state) { fprintf(stderr, "failed to create XKB state\n"); - xkb_map_unref(input->xkb.keymap); - input->xkb.keymap = NULL; + xkb_map_unref(keymap); return; } + xkb_keymap_unref(input->xkb.keymap); + xkb_state_unref(input->xkb.state); + input->xkb.keymap = keymap; + input->xkb.state = state; + input->xkb.control_mask = 1 << xkb_map_mod_get_index(input->xkb.keymap, "Control"); input->xkb.alt_mask = -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH v2 3/4] compositor-wayland: Handle keymap changes
--- src/compositor-wayland.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 77b2a2c..0fd7267 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -515,7 +515,11 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, return; } - weston_seat_init_keyboard(&input->base, keymap); + if (input->base.keyboard) + weston_seat_update_keymap(&input->base, keymap); + else + weston_seat_init_keyboard(&input->base, keymap); + xkb_map_unref(keymap); } -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH v2 2/4] compositor-x11: Update keymap when XKB keymap changes
--- v2: - improved error handling a bit; src/compositor-x11.c | 38 -- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 704e751..6530bde 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -201,6 +201,7 @@ x11_compositor_setup_xkb(struct x11_compositor *c) xcb_xkb_per_client_flags_reply_t *pcf_reply; xcb_xkb_get_state_cookie_t state; xcb_xkb_get_state_reply_t *state_reply; + uint32_t values[1] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; c->has_xkb = 0; c->xkb_event_base = 0; @@ -280,10 +281,27 @@ x11_compositor_setup_xkb(struct x11_compositor *c) free(state_reply); + xcb_change_window_attributes(c->conn, c->screen->root, +XCB_CW_EVENT_MASK, values); + c->has_xkb = 1; #endif } +static void +update_xkb_keymap(struct x11_compositor *c) +{ + struct xkb_keymap *keymap; + + keymap = x11_compositor_get_keymap(c); + if (!keymap) { + weston_log("failed to get XKB keymap\n"); + return; + } + weston_seat_update_keymap(&c->core_seat, keymap); + xkb_keymap_unref(keymap); +} + static int x11_input_create(struct x11_compositor *c, int no_input) { @@ -1284,12 +1302,20 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) } #ifdef HAVE_XCB_XKB - if (c->has_xkb && - response_type == c->xkb_event_base) { - xcb_xkb_state_notify_event_t *state = - (xcb_xkb_state_notify_event_t *) event; - if (state->xkbType == XCB_XKB_STATE_NOTIFY) - update_xkb_state(c, state); + if (c->has_xkb) { + if (response_type == c->xkb_event_base) { + xcb_xkb_state_notify_event_t *state = + (xcb_xkb_state_notify_event_t *) event; + if (state->xkbType == XCB_XKB_STATE_NOTIFY) + update_xkb_state(c, state); + } else if (response_type == XCB_PROPERTY_NOTIFY) { + xcb_property_notify_event_t *prop_notify = + (xcb_property_notify_event_t *) event; + if (prop_notify->window == c->screen->root && + prop_notify->atom == c->atom.xkb_names && + prop_notify->state == XCB_PROPERTY_NEW_VALUE) + update_xkb_keymap(c); + } } #endif -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH v2 1/4] input: Add core API to update the keymap
How and when to update the keymap is left to each backend. The new keymap only becomes effective when no keys are pressed and we keep latched and locked modifiers from the previous state. --- v2: - defer updating the keymap until no keys are pressed; - keep latched and locked modifiers state; - send the new keymap also to the focus_resource_list clients - not sure how I missed this in testing before; - send the new modifiers state to all keyboard clients if any bit is set since a new keymap means that they have to reset their state so we need to tell them if we are keeping some src/compositor.h | 3 ++ src/input.c | 109 +++ 2 files changed, 112 insertions(+) diff --git a/src/compositor.h b/src/compositor.h index a19d966..a4fedc3 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -486,6 +486,7 @@ struct weston_seat { struct xkb_state *state; enum weston_led leds; } xkb_state; + struct xkb_keymap *pending_keymap; struct input_method *input_method; char *seat_name; @@ -1115,6 +1116,8 @@ void weston_seat_init_touch(struct weston_seat *seat); void weston_seat_repick(struct weston_seat *seat); +void +weston_seat_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap); void weston_seat_release(struct weston_seat *seat); diff --git a/src/input.c b/src/input.c index 1313b52..539aba3 100644 --- a/src/input.c +++ b/src/input.c @@ -889,6 +889,86 @@ update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key, notify_modifiers(seat, serial); } + +static void +send_keymap(struct wl_resource *resource, struct weston_xkb_info *xkb_info) +{ + wl_keyboard_send_keymap(resource, + WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + xkb_info->keymap_fd, + xkb_info->keymap_size); +} + +static void +send_modifiers(struct wl_resource *resource, uint32_t serial, struct weston_keyboard *keyboard) +{ + wl_keyboard_send_modifiers(resource, serial, + keyboard->modifiers.mods_depressed, + keyboard->modifiers.mods_latched, + keyboard->modifiers.mods_locked, + keyboard->modifiers.group); +} + +static struct weston_xkb_info * +weston_xkb_info_create(struct xkb_keymap *keymap); +static void +weston_xkb_info_destroy(struct weston_xkb_info *xkb_info); + +static void +update_keymap(struct weston_seat *seat) +{ + struct wl_resource *resource; + struct weston_xkb_info *xkb_info; + struct xkb_state *state; + xkb_mod_mask_t latched_mods; + xkb_mod_mask_t locked_mods; + + xkb_info = weston_xkb_info_create(seat->pending_keymap); + + xkb_keymap_unref(seat->pending_keymap); + seat->pending_keymap = NULL; + + if (!xkb_info) { + weston_log("failed to create XKB info\n"); + return; + } + + state = xkb_state_new(xkb_info->keymap); + if (!state) { + weston_log("failed to initialise XKB state\n"); + weston_xkb_info_destroy(xkb_info); + return; + } + + latched_mods = xkb_state_serialize_mods(seat->xkb_state.state, XKB_STATE_MODS_LATCHED); + locked_mods = xkb_state_serialize_mods(seat->xkb_state.state, XKB_STATE_MODS_LOCKED); + xkb_state_update_mask(state, + 0, /* depressed */ + latched_mods, + locked_mods, + 0, 0, 0); + + weston_xkb_info_destroy(seat->xkb_info); + seat->xkb_info = xkb_info; + + xkb_state_unref(seat->xkb_state.state); + seat->xkb_state.state = state; + + wl_resource_for_each(resource, &seat->keyboard->resource_list) + send_keymap(resource, xkb_info); + wl_resource_for_each(resource, &seat->keyboard->focus_resource_list) + send_keymap(resource, xkb_info); + + notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display)); + + if (!latched_mods && !locked_mods) + return; + + wl_resource_for_each(resource, &seat->keyboard->resource_list) + send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), seat->keyboard); + wl_resource_for_each(resource, &seat->keyboard->focus_resource_list) + send_modifiers(resource, wl_display_get_serial(seat->compositor->wl_display), seat->keyboard); +} #else WL_EXPORT void notify_modifiers(struct weston_seat *seat, uint32_t serial) @@ -900,6 +980,11 @@ update_modifier_state(struct weston_seat *seat, uint32_t serial, uint32_t key, enum wl_keyboard_key_state state) { } + +static void +update_keymap(struct weston_seat *seat) +{ +} #endif WL_
[PATCH 4/4] clients/window: Dispose of previous keymap and state on keymap change
--- clients/window.c | 24 +++- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/clients/window.c b/clients/window.c index 5b20da5..1f32c73 100644 --- a/clients/window.c +++ b/clients/window.c @@ -3037,6 +3037,8 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) { struct input *input = data; + struct xkb_keymap *keymap; + struct xkb_state *state; char *map_str; if (!data) { @@ -3055,26 +3057,30 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } - input->xkb.keymap = xkb_map_new_from_string(input->display->xkb_context, - map_str, - XKB_KEYMAP_FORMAT_TEXT_V1, - 0); + keymap = xkb_map_new_from_string(input->display->xkb_context, +map_str, +XKB_KEYMAP_FORMAT_TEXT_V1, +0); munmap(map_str, size); close(fd); - if (!input->xkb.keymap) { + if (!keymap) { fprintf(stderr, "failed to compile keymap\n"); return; } - input->xkb.state = xkb_state_new(input->xkb.keymap); - if (!input->xkb.state) { + state = xkb_state_new(keymap); + if (!state) { fprintf(stderr, "failed to create XKB state\n"); - xkb_map_unref(input->xkb.keymap); - input->xkb.keymap = NULL; + xkb_map_unref(keymap); return; } + xkb_keymap_unref(input->xkb.keymap); + xkb_state_unref(input->xkb.state); + input->xkb.keymap = keymap; + input->xkb.state = state; + input->xkb.control_mask = 1 << xkb_map_mod_get_index(input->xkb.keymap, "Control"); input->xkb.alt_mask = -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 3/4] compositor-wayland: Handle keymap changes
--- src/compositor-wayland.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 77b2a2c..95545bc 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -515,7 +515,11 @@ input_handle_keymap(void *data, struct wl_keyboard *keyboard, uint32_t format, return; } - weston_seat_init_keyboard(&input->base, keymap); + if (input->base.keyboard) + weston_seat_update_keyboard(&input->base, keymap); + else + weston_seat_init_keyboard(&input->base, keymap); + xkb_map_unref(keymap); } -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 2/4] compositor-x11: Update keymap when XKB keymap changes
--- src/compositor-x11.c | 35 +-- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 704e751..bdff323 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -201,6 +201,7 @@ x11_compositor_setup_xkb(struct x11_compositor *c) xcb_xkb_per_client_flags_reply_t *pcf_reply; xcb_xkb_get_state_cookie_t state; xcb_xkb_get_state_reply_t *state_reply; + uint32_t values[1] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; c->has_xkb = 0; c->xkb_event_base = 0; @@ -280,10 +281,24 @@ x11_compositor_setup_xkb(struct x11_compositor *c) free(state_reply); + xcb_change_window_attributes(c->conn, c->screen->root, +XCB_CW_EVENT_MASK, values); + c->has_xkb = 1; #endif } +static void +update_xkb_keymap(struct x11_compositor *c) +{ + struct xkb_keymap *keymap; + + keymap = x11_compositor_get_keymap(c); + weston_seat_update_keyboard (&c->core_seat, keymap); + if (keymap) + xkb_map_unref(keymap); +} + static int x11_input_create(struct x11_compositor *c, int no_input) { @@ -1284,12 +1299,20 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) } #ifdef HAVE_XCB_XKB - if (c->has_xkb && - response_type == c->xkb_event_base) { - xcb_xkb_state_notify_event_t *state = - (xcb_xkb_state_notify_event_t *) event; - if (state->xkbType == XCB_XKB_STATE_NOTIFY) - update_xkb_state(c, state); + if (c->has_xkb) { + if (response_type == c->xkb_event_base) { + xcb_xkb_state_notify_event_t *state = + (xcb_xkb_state_notify_event_t *) event; + if (state->xkbType == XCB_XKB_STATE_NOTIFY) + update_xkb_state(c, state); + } else if (response_type == XCB_PROPERTY_NOTIFY) { + xcb_property_notify_event_t *prop_notify = + (xcb_property_notify_event_t *) event; + if (prop_notify->window == c->screen->root && + prop_notify->atom == c->atom.xkb_names && + prop_notify->state == XCB_PROPERTY_NEW_VALUE) + update_xkb_keymap(c); + } } #endif -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH 1/4] input: Add core API to update the keymap
How and when to update the keymap is left to each backend. --- src/compositor.h | 2 ++ src/input.c | 38 ++ 2 files changed, 40 insertions(+) diff --git a/src/compositor.h b/src/compositor.h index a19d966..041758a 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -1115,6 +1115,8 @@ void weston_seat_init_touch(struct weston_seat *seat); void weston_seat_repick(struct weston_seat *seat); +void +weston_seat_update_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap); void weston_seat_release(struct weston_seat *seat); diff --git a/src/input.c b/src/input.c index 1313b52..e769554 100644 --- a/src/input.c +++ b/src/input.c @@ -1623,6 +1623,44 @@ weston_compositor_xkb_destroy(struct weston_compositor *ec) } #endif +WL_EXPORT void +weston_seat_update_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) +{ + struct wl_resource *resource; + + if (!seat->keyboard) + return; + +#ifdef ENABLE_XKBCOMMON + if (seat->compositor->use_xkbcommon) { + if (seat->xkb_info != NULL) + weston_xkb_info_destroy(seat->xkb_info); + seat->xkb_info = weston_xkb_info_create(keymap); + if (seat->xkb_info == NULL) { + weston_log("failed to create XKB info\n"); + return; + } + + if (seat->xkb_state.state != NULL) + xkb_state_unref(seat->xkb_state.state); + seat->xkb_state.state = xkb_state_new(seat->xkb_info->keymap); + if (seat->xkb_state.state == NULL) { + weston_log("failed to initialise XKB state\n"); + return; + } + + wl_resource_for_each(resource, &seat->keyboard->resource_list) { + wl_keyboard_send_keymap(resource, + WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + seat->xkb_info->keymap_fd, + seat->xkb_info->keymap_size); + } + + notify_modifiers(seat, wl_display_next_serial(seat->compositor->wl_display)); + } +#endif +} + WL_EXPORT int weston_seat_init_keyboard(struct weston_seat *seat, struct xkb_keymap *keymap) { -- 1.8.3.1 ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH weston] Add a way to update the keymap
We'll need something like this in mutter-wayland to allow people to add/change their keyboard layouts with gnome-control-center so I figured I'd start by implementing the basics in weston first. There's an implementation for a couple of backends and a fix for the client side which would leak on keymap events. Comments welcome, especially about the state handling - right now I'm just reseting the XKB state but I'm not sure this is the correct thing to do. Rui ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel