xserver: Branch 'master' - 4 commits

Peter Hutterer whot at kemper.freedesktop.org
Mon Nov 23 17:42:36 PST 2015


 Xi/exevents.c                |    4 +
 dix/getevents.c              |   29 ++++---
 dix/inpututils.c             |    4 -
 hw/xwayland/xwayland-input.c |    6 +
 include/eventstr.h           |   10 ++
 include/inpututils.h         |    4 -
 xkb/xkbAccessX.c             |    2 
 xkb/xkbActions.c             |  170 +++++++++++++++++++++++++------------------
 8 files changed, 146 insertions(+), 83 deletions(-)

New commits:
commit fee0827a9a695600765f3d04376fc9babe497401
Author: Daniel Stone <daniels at collabora.com>
Date:   Fri Nov 20 15:37:31 2015 +0000

    XWayland: Use FocusIn events for keyboard enter
    
    wl_keyboard::enter is the equivalent of FocusIn + KeymapNotify: it
    notifies us that the surface/window has now received the focus, and
    provides us a set of keys which are currently down.
    
    We should use these keys to update the current state, but not to send
    any events to clients.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 0515eb9..473f306 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -432,7 +432,7 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
 
     wl_array_copy(&xwl_seat->keys, keys);
     wl_array_for_each(k, &xwl_seat->keys)
-        QueueKeyboardEvents(xwl_seat->keyboard, KeyPress, *k + 8);
+        QueueKeyboardEvents(xwl_seat->keyboard, KeymapNotify, *k + 8);
 }
 
 static void
@@ -444,6 +444,10 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
 
     xwl_seat->xwl_screen->serial = serial;
 
+    /* Unlike keymap_handle_enter above, this time we _do_ want to trigger
+     * full release, as we don't know how long we'll be out of focus for.
+     * Notify clients that the keys have been released, disable autorepeat,
+     * etc. */
     wl_array_for_each(k, &xwl_seat->keys)
         QueueKeyboardEvents(xwl_seat->keyboard, KeyRelease, *k + 8);
 
commit 816015648ffe660ddaa0f7d4d192e555b723c372
Author: Daniel Stone <daniels at collabora.com>
Date:   Fri Nov 20 15:37:30 2015 +0000

    Input: Add focus-in event source
    
    Add a new event source type for keypress events synthesised from focus
    notifications (e.g. KeymapNotify from the parent server, when running
    nested). This is used to keep the keys-down array in sync with the host
    server's, without sending actual keypress events to clients.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e728310..74e49ed 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1760,6 +1760,10 @@ ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
 
     switch (event->type) {
     case ET_KeyPress:
+        /* Don't deliver focus events (e.g. from KeymapNotify when running
+         * nested) to clients. */
+        if (event->source_type == EVENT_SOURCE_FOCUS)
+            return;
         if (!grab && CheckDeviceGrabs(device, event, 0))
             return;
         break;
diff --git a/dix/getevents.c b/dix/getevents.c
index f04b415..4d06818 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1101,6 +1101,11 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
     }
 #endif
 
+    if (type == KeymapNotify) {
+        source_type = EVENT_SOURCE_FOCUS;
+        type = KeyPress;
+    }
+
     /* refuse events from disabled devices */
     if (!pDev->enabled)
         return 0;
diff --git a/include/eventstr.h b/include/eventstr.h
index 4fd846f..7446961 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -83,6 +83,7 @@ enum EventType {
  */
 enum DeviceEventSource {
   EVENT_SOURCE_NORMAL = 0, /**< Default: from a user action (e.g. key press) */
+  EVENT_SOURCE_FOCUS, /**< Keys or buttons previously down on focus-in */
 };
 
 /**
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index ddd09ab..aeb702c 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1206,6 +1206,32 @@ XkbActionGetFilter(DeviceIntPtr dev, DeviceEvent *event, KeyCode key,
     XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
     XkbFilterPtr filter;
 
+    /* For focus events, we only want to run actions which update our state to
+     * (hopefully vaguely kinda) match that of the host server, rather than
+     * actually execute anything. For example, if we enter our VT with
+     * Ctrl+Alt+Backspace held down, we don't want to terminate our server
+     * immediately, but we _do_ want Ctrl+Alt to be latched down, so if
+     * Backspace is released and then pressed again, the server will terminate.
+     *
+     * This is pretty flaky, and we should in fact inherit the complete state
+     * from the host server. There are some state combinations that we cannot
+     * express by running the state machine over every key, e.g. if AltGr+Shift
+     * generates a different state to Shift+AltGr. */
+    if (event->source_type == EVENT_SOURCE_FOCUS) {
+        switch (act->type) {
+        case XkbSA_SetMods:
+        case XkbSA_SetGroup:
+        case XkbSA_LatchMods:
+        case XkbSA_LatchGroup:
+        case XkbSA_LockMods:
+        case XkbSA_LockGroup:
+            break;
+        default:
+            *sendEvent = 1;
+            return;
+        }
+    }
+
     switch (act->type) {
     case XkbSA_SetMods:
     case XkbSA_SetGroup:
commit c3788394e9190130a8eed44c5c93eeb93c2a9893
Author: Daniel Stone <daniels at collabora.com>
Date:   Fri Nov 20 15:37:29 2015 +0000

    Input: Add DeviceEventSource enum
    
    Add a flag to DeviceEvents, giving the source of the event. Currently
    this only supports a 'normal' flag, but will be used later to add a
    'focus-in' flag, noting events synthesised from key/button arrays on
    focus-in notifications.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/getevents.c b/dix/getevents.c
index 7ebddc4..f04b415 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1092,6 +1092,7 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
     CARD32 ms = 0;
     DeviceEvent *event;
     RawDeviceEvent *raw;
+    enum DeviceEventSource source_type = EVENT_SOURCE_NORMAL;
 
 #if XSERVER_DTRACE
     if (XSERVER_INPUT_EVENT_ENABLED()) {
@@ -1126,14 +1127,15 @@ GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
 
     ms = GetTimeInMillis();
 
-    raw = &events->raw_event;
-    events++;
-    num_events++;
-
-    init_raw(pDev, raw, ms, type, key_code);
+    if (source_type == EVENT_SOURCE_NORMAL) {
+        raw = &events->raw_event;
+        init_raw(pDev, raw, ms, type, key_code);
+        events++;
+        num_events++;
+    }
 
     event = &events->device_event;
-    init_device_event(event, pDev, ms);
+    init_device_event(event, pDev, ms, source_type);
     event->detail.key = key_code;
 
     if (type == KeyPress) {
@@ -1468,7 +1470,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
     }
 
     event = &events->device_event;
-    init_device_event(event, pDev, ms);
+    init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
 
     if (type == MotionNotify) {
         event->type = ET_Motion;
@@ -1804,7 +1806,7 @@ GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
         UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
 
     event = &events->device_event;
-    init_device_event(event, pDev, GetTimeInMillis());
+    init_device_event(event, pDev, GetTimeInMillis(), EVENT_SOURCE_NORMAL);
     event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
 
     clipValuators(pDev, &mask);
@@ -1939,7 +1941,7 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
     event = &events->device_event;
     num_events++;
 
-    init_device_event(event, dev, ms);
+    init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
 
     switch (type) {
     case XI_TouchBegin:
@@ -2054,7 +2056,7 @@ GetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti,
 
     BUG_WARN(!dev->enabled);
 
-    init_device_event(event, dev, ms);
+    init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
 
     event->sourceid = ti->sourceid;
     event->type = ET_TouchEnd;
@@ -2098,7 +2100,7 @@ PostSyntheticMotion(DeviceIntPtr pDev,
 #endif
 
     memset(&ev, 0, sizeof(DeviceEvent));
-    init_device_event(&ev, pDev, time);
+    init_device_event(&ev, pDev, time, EVENT_SOURCE_NORMAL);
     ev.root_x = x;
     ev.root_y = y;
     ev.type = ET_Motion;
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 1363988..5b7da3a 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -727,7 +727,8 @@ verify_internal_event(const InternalEvent *ev)
  * device.
  */
 void
-init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
+init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
+                  enum DeviceEventSource source_type)
 {
     memset(event, 0, sizeof(DeviceEvent));
     event->header = ET_Internal;
@@ -735,6 +736,7 @@ init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms)
     event->time = ms;
     event->deviceid = dev->id;
     event->sourceid = dev->id;
+    event->source_type = source_type;
 }
 
 int
diff --git a/include/eventstr.h b/include/eventstr.h
index cce903d..4fd846f 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -25,6 +25,7 @@
 #ifndef EVENTSTR_H
 #define EVENTSTR_H
 
+#include "inputstr.h"
 #include <events.h>
 /**
  * @file events.h
@@ -78,6 +79,13 @@ enum EventType {
 };
 
 /**
+ * How a DeviceEvent was provoked
+ */
+enum DeviceEventSource {
+  EVENT_SOURCE_NORMAL = 0, /**< Default: from a user action (e.g. key press) */
+};
+
+/**
  * Used for ALL input device events internal in the server until
  * copied into the matching protocol event.
  *
@@ -124,6 +132,7 @@ struct _DeviceEvent {
     int key_repeat;   /**< Internally-generated key repeat event */
     uint32_t flags;   /**< Flags to be copied into the generated event */
     uint32_t resource; /**< Touch event resource, only for TOUCH_REPLAYING */
+    enum DeviceEventSource source_type; /**< How this event was provoked */
 };
 
 /**
diff --git a/include/inpututils.h b/include/inpututils.h
index 4e90815..48c95c4 100644
--- a/include/inpututils.h
+++ b/include/inpututils.h
@@ -30,6 +30,7 @@
 #define INPUTUTILS_H
 
 #include "input.h"
+#include "eventstr.h"
 #include <X11/extensions/XI2proto.h>
 
 extern Mask event_filters[MAXDEVICES][MAXEVENTS];
@@ -43,7 +44,8 @@ struct _ValuatorMask {
 };
 
 extern void verify_internal_event(const InternalEvent *ev);
-extern void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms);
+extern void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
+                              enum DeviceEventSource event_source);
 extern int event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd);
 extern void event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd,
                             DeviceEvent *event);
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 7fd6a48..02e820b 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -126,7 +126,7 @@ AccessXKeyboardEvent(DeviceIntPtr keybd, int type, BYTE keyCode, Bool isRepeat)
 {
     DeviceEvent event;
 
-    init_device_event(&event, keybd, GetTimeInMillis());
+    init_device_event(&event, keybd, GetTimeInMillis(), EVENT_SOURCE_NORMAL);
     event.type = type;
     event.detail.key = keyCode;
     event.key_repeat = isRepeat;
commit 2e61901e46d28ce2f436219ad1a495aa0dcd0fba
Author: Daniel Stone <daniels at collabora.com>
Date:   Fri Nov 20 15:37:28 2015 +0000

    XKB: Split filter execution into a separate function
    
    Move the giant state machine which maps from a key action to actually
    running the filters into a separate function, to be used when adding
    KeyFocusIn.
    
    Signed-off-by: Daniel Stone <daniels at collabora.com>
    Tested-by: Giulio Camuffo <giuliocamuffo at gmail.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 1a9878d..ddd09ab 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -1199,6 +1199,80 @@ XkbPushLockedStateToSlaves(DeviceIntPtr master, int evtype, int key)
     }
 }
 
+static void
+XkbActionGetFilter(DeviceIntPtr dev, DeviceEvent *event, KeyCode key,
+                   XkbAction *act, int *sendEvent)
+{
+    XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
+    XkbFilterPtr filter;
+
+    switch (act->type) {
+    case XkbSA_SetMods:
+    case XkbSA_SetGroup:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterSetState(xkbi, filter, key, act);
+        break;
+    case XkbSA_LatchMods:
+    case XkbSA_LatchGroup:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterLatchState(xkbi, filter, key, act);
+        break;
+    case XkbSA_LockMods:
+    case XkbSA_LockGroup:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterLockState(xkbi, filter, key, act);
+        break;
+    case XkbSA_ISOLock:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterISOLock(xkbi, filter, key, act);
+        break;
+    case XkbSA_MovePtr:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterPointerMove(xkbi, filter, key, act);
+        break;
+    case XkbSA_PtrBtn:
+    case XkbSA_LockPtrBtn:
+    case XkbSA_SetPtrDflt:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, act);
+        break;
+    case XkbSA_Terminate:
+        *sendEvent = XkbDDXTerminateServer(dev, key, act);
+        break;
+    case XkbSA_SwitchScreen:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, act);
+        break;
+    case XkbSA_SetControls:
+    case XkbSA_LockControls:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterControls(xkbi, filter, key, act);
+        break;
+    case XkbSA_ActionMessage:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterActionMessage(xkbi, filter, key, act);
+        break;
+    case XkbSA_RedirectKey:
+        filter = _XkbNextFreeFilter(xkbi);
+        /* redirect actions must create a new DeviceEvent.  The
+         * source device id for this event cannot be obtained from
+         * xkbi, so we pass it here explicitly. The field deviceid
+         * equals to xkbi->device->id. */
+        filter->priv = event->sourceid;
+        *sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, act);
+        break;
+    case XkbSA_DeviceBtn:
+    case XkbSA_LockDeviceBtn:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, act);
+        break;
+    case XkbSA_XFree86Private:
+        filter = _XkbNextFreeFilter(xkbi);
+        *sendEvent = _XkbFilterXF86Private(xkbi, filter, key, act);
+        break;
+    }
+}
+
 void
 XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
 {
@@ -1208,7 +1282,6 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
     int sendEvent;
     Bool genStateNotify;
     XkbAction act;
-    XkbFilterPtr filter;
     Bool keyEvent;
     Bool pressEvent;
     ProcessInputProc backupproc;
@@ -1236,74 +1309,9 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
             act = XkbGetButtonAction(kbd, dev, key);
             key |= BTN_ACT_FLAG;
         }
+
         sendEvent = _XkbApplyFilters(xkbi, key, &act);
-        if (sendEvent) {
-            switch (act.type) {
-            case XkbSA_SetMods:
-            case XkbSA_SetGroup:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterSetState(xkbi, filter, key, &act);
-                break;
-            case XkbSA_LatchMods:
-            case XkbSA_LatchGroup:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterLatchState(xkbi, filter, key, &act);
-                break;
-            case XkbSA_LockMods:
-            case XkbSA_LockGroup:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterLockState(xkbi, filter, key, &act);
-                break;
-            case XkbSA_ISOLock:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterISOLock(xkbi, filter, key, &act);
-                break;
-            case XkbSA_MovePtr:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterPointerMove(xkbi, filter, key, &act);
-                break;
-            case XkbSA_PtrBtn:
-            case XkbSA_LockPtrBtn:
-            case XkbSA_SetPtrDflt:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, &act);
-                break;
-            case XkbSA_Terminate:
-                sendEvent = XkbDDXTerminateServer(dev, key, &act);
-                break;
-            case XkbSA_SwitchScreen:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, &act);
-                break;
-            case XkbSA_SetControls:
-            case XkbSA_LockControls:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterControls(xkbi, filter, key, &act);
-                break;
-            case XkbSA_ActionMessage:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterActionMessage(xkbi, filter, key, &act);
-                break;
-            case XkbSA_RedirectKey:
-                filter = _XkbNextFreeFilter(xkbi);
-                /* redirect actions must create a new DeviceEvent.  The
-                 * source device id for this event cannot be obtained from
-                 * xkbi, so we pass it here explicitly. The field deviceid
-                 * equals to xkbi->device->id. */
-                filter->priv = event->sourceid;
-                sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, &act);
-                break;
-            case XkbSA_DeviceBtn:
-            case XkbSA_LockDeviceBtn:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, &act);
-                break;
-            case XkbSA_XFree86Private:
-                filter = _XkbNextFreeFilter(xkbi);
-                sendEvent = _XkbFilterXF86Private(xkbi, filter, key, &act);
-                break;
-            }
-        }
+        XkbActionGetFilter(dev, event, key, &act, &sendEvent);
     }
     else {
         if (!keyEvent)


More information about the xorg-commit mailing list