[PATCH RFC] Add a FOCUS_FORCE flag to the device's focus class

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 16 20:27:05 PST 2012


Some devices should not use a traditional pointer-focusing model but instead
should be controlled by the client at all times. One example are tablets
that are bound through the GDK map to window option. Once focused, the
tablet events should always go to the focus window.

Currently, devices only send pointer events to the window at the sprite
location. This behaviour was introduced in a88386ee277d136caaae
and breaks how XI 1.x devices used to be handled.

A device that uses forced focus will always either deliver to the focus
window, or to the sprite window if the focus is PointerRoot. If the device
is a floating slave device, the VCP determines the sprite window.
Forced focus devices are listed as IsXExtensionDevice, this best emulates
the original behaviour for XI 1.x clients that need it.

A device can be enabled as such a device through the ForceFocus option in
the config file or snippet. This is a permanent option and cannot be changed
at runtime.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Now, there's an argument that for this particular use-case the client could
just grab the device. However that doesn't quite solve the same problem
since it's harder to share the device between the devices, especially when
the device is focus PointerRoot.  And it is definitely a behaviour change
from the olden days.

For XI2, we could add another focus mode to XISetFocus, but that wouldn't
help with legacy apps that don't support XI2.

 Xi/exevents.c                  |   15 ++++++++++++---
 Xi/listdev.c                   |    2 ++
 dix/devices.c                  |    1 +
 hw/xfree86/common/xf86Xinput.c |   13 +++++++++++++
 hw/xfree86/common/xf86Xinput.h |    1 +
 hw/xfree86/man/xorg.conf.man   |    9 +++++++++
 include/input.h                |    2 ++
 include/inputstr.h             |    1 +
 8 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 6b2db4b..d0ad32b 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1685,9 +1685,18 @@ ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
 
     if (grab)
         DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
-    else if (device->focus && !IsPointerEvent(ev))
-        DeliverFocusedEvent(device, (InternalEvent*)event,
-                            GetSpriteWindow(device));
+    else if (device->focus && (!IsPointerEvent(ev) || !!(device->focus->flags & FOCUS_FORCE)))
+    {
+        Window sprite_win;
+
+        /* Forced focus devices follow the VCP */
+        if (device->focus->flags & FOCUS_FORCE && !IsMaster(device) && IsFloating(device))
+            sprite_win = GetSpriteWindow(inputInfo.pointer);
+        else
+            sprite_win = GetSpriteWindow(device);
+
+        DeliverFocusedEvent(device, (InternalEvent*)event, sprite_win);
+    }
     else
         DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
                             NullGrab, NullWindow, device);
diff --git a/Xi/listdev.c b/Xi/listdev.c
index 1b3081d..764ebc0 100644
--- a/Xi/listdev.c
+++ b/Xi/listdev.c
@@ -176,6 +176,8 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes,
 	dev->use = IsXKeyboard;
     else if (IsMaster(d) && IsPointerDevice(d))
 	dev->use = IsXPointer;
+    else if (d->focus && !!(d->focus->flags & FOCUS_FORCE))
+        dev->use = IsXExtensionDevice;
     else if (d->valuator && d->button)
         dev->use = IsXExtensionPointer;
     else if (d->key && d->kbdfeed)
diff --git a/dix/devices.c b/dix/devices.c
index 7478ad6..86c6e1d 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1417,6 +1417,7 @@ InitFocusClassDeviceStruct(DeviceIntPtr dev)
     focc->traceSize = 0;
     focc->traceGood = 0;
     focc->sourceid = dev->id;
+    focc->flags = 0;
     dev->focus = focc;
     return TRUE;
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index fd40f28..592954b 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -317,6 +317,13 @@ xf86ProcessCommonOptions(InputInfoPtr pInfo,
         pInfo->flags |= XI86_ALWAYS_CORE;
         xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name);
     }
+
+    if (xf86SetBoolOption(list, "ForceFocus", 0))
+    {
+        xf86Msg(X_CONFIG, "%s: needs explicit focusing\n", pInfo->name);
+        pInfo->flags |= XI86_FORCE_FOCUS;
+    }
+
 }
 
 /***********************************************************************
@@ -782,8 +789,14 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
  */
 static int
 xf86InputDevicePostInit(DeviceIntPtr dev) {
+    InputInfoPtr pInfo = dev->public.devicePrivate;
+
     ApplyAccelerationSettings(dev);
     ApplyTransformationMatrix(dev);
+
+    if (dev->focus && (pInfo->flags & XI86_FORCE_FOCUS))
+        dev->focus->flags |= FOCUS_FORCE;
+
     return Success;
 }
 
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index ad092dd..dfdc0a8 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -60,6 +60,7 @@
 
 /* Input device flags */
 #define XI86_ALWAYS_CORE	0x04 /* device always controls the pointer */
+#define XI86_FORCE_FOCUS	0x08 /* device has a forced focus policy */
 /* the device sends Xinput and core pointer events */
 #define XI86_SEND_CORE_EVENTS	XI86_ALWAYS_CORE
 
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
index c1b3c4f..e320c49 100644
--- a/hw/xfree86/man/xorg.conf.man
+++ b/hw/xfree86/man/xorg.conf.man
@@ -933,6 +933,15 @@ is equivalent to
 This option controls the startup behavior only, a device
 may be reattached or set floating at runtime.
 .TP 7
+.BIE "Option \*qForcedFocus\* \*q" boolean \*q
+When enabled, the device always sends events to the focus
+window. Otherwise, only keyboard events are delivered to the focus window
+whereas pointer events go to the sprite window. If the device's focus is
+PointerRoot, the current sprite window is the focus window. If the device is
+a floating slave device and the device's focus is PointerRoot, the sprite
+window of the first master pointer is the focus window. This option emulates
+traditional X Input Extension version 1.x device behaviour. Default off.
+.TP 7
 .BI "Option \*qTransformationMatrix\*q \*q" a " " b " " c " " d " " e " " f " " g " " h " " i \*q
 Specifies the 3x3 transformation matrix for absolute input devices. The
 input device will be bound to the area given in the matrix.  In most
diff --git a/include/input.h b/include/input.h
index fb45617..e3712c2 100644
--- a/include/input.h
+++ b/include/input.h
@@ -243,6 +243,8 @@ typedef struct _InputAttributes {
 #define ATTR_TOUCHPAD (1<<4)
 #define ATTR_TOUCHSCREEN (1<<5)
 
+#define FOCUS_FORCE     (1 << 0) /* all device events follow focus */
+
 /* Key/Button has been run through all input processing and events sent to clients. */
 #define KEY_PROCESSED 1
 #define BUTTON_PROCESSED 1
diff --git a/include/inputstr.h b/include/inputstr.h
index c3297db..7b5f6b7 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -372,6 +372,7 @@ typedef struct _FocusClassRec {
     WindowPtr	*trace;
     int		traceSize;
     int		traceGood;
+    int		flags;  /* FOCUS_FOCE */
 } FocusClassRec, *FocusClassPtr;
 
 typedef struct _ProximityClassRec {
-- 
1.7.7.5



More information about the xorg-devel mailing list