=== modified file 'unity-shared/InputMonitor.cpp'
--- unity-shared/InputMonitor.cpp	2017-02-28 17:16:14 +0000
+++ unity-shared/InputMonitor.cpp	2017-12-14 19:22:54 +0000
@@ -135,8 +135,11 @@
     : xi_opcode_(0)
     , event_filter_set_(false)
     , invoking_callbacks_(false)
+    , basemasks_(nullptr)
+    , num_basemasks_(0)
   {
     Display *dpy = gdk_x11_get_default_xdisplay();
+    Window root = DefaultRootWindow(dpy);
     int event_base, error_base;
 
     if (XQueryExtension(dpy, "XInputExtension", &xi_opcode_, &event_base, &error_base))
@@ -149,6 +152,10 @@
         LOG_ERROR(logger) << "Need XInput version "<< maj << "." << min << ", "
                           << "impossible, to setup an InputMonitor";
       }
+      else
+      {
+        basemasks_ = XIGetSelectedEvents(dpy, root, &num_basemasks_);
+      }
     }
     else
     {
@@ -165,6 +172,7 @@
       barrier_callbacks_.clear();
       UpdateEventMonitor();
     }
+    XFree(basemasks_);
   }
 
   bool RegisterClient(Events type, EventCallback const& cb)
@@ -223,14 +231,51 @@
     return events;
   }
 
+  // Prepare a mask based on the Compiz-configured mask
+  void InitializeMask(int deviceid, XIEventMask* ourmask)
+  {
+    int wanted_mask_len = XIMaskLen(XI_LASTEVENT);
+    int mask_len = -1;
+    unsigned char* mask;
+
+    for (int i = 0; i < num_basemasks_; i++)
+    {
+      if (basemasks_[i].deviceid == deviceid)
+      {
+        // Compiz is already listening for some events on this device, use this as a base
+
+        mask_len = basemasks_[i].mask_len;
+        if (mask_len < wanted_mask_len)
+          mask_len = wanted_mask_len;
+
+        mask = (unsigned char*) malloc(mask_len);
+        memcpy(mask, basemasks_[i].mask, basemasks_[i].mask_len);
+        memset(mask + basemasks_[i].mask_len, 0,
+               mask_len - basemasks_[i].mask_len);
+        break;
+      }
+    }
+
+    if (mask_len < 0)
+    {
+      mask_len = wanted_mask_len;
+      mask = (unsigned char*) calloc(mask_len, 1);
+    }
+
+    ourmask->deviceid = deviceid;
+    ourmask->mask_len = mask_len;
+    ourmask->mask = mask;
+  }
+
   void UpdateEventMonitor()
   {
     auto* nux_dpy = nux::GetGraphicsDisplay();
     auto* dpy = nux_dpy ? nux_dpy->GetX11Display() : gdk_x11_get_default_xdisplay();
     Window root = DefaultRootWindow(dpy);
 
-    unsigned char master_dev_bits[XIMaskLen(XI_LASTEVENT)] = { 0 };
-    XIEventMask master_dev = { XIAllMasterDevices, sizeof(master_dev_bits), master_dev_bits };
+    XIEventMask master_dev;
+
+    InitializeMask(XIAllMasterDevices, &master_dev);
 
     if (!barrier_callbacks_.empty())
     {
@@ -238,8 +283,9 @@
       XISetMask(master_dev.mask, XI_BarrierLeave);
     }
 
-    unsigned char all_devs_bits[XIMaskLen(XI_LASTEVENT)] = { 0 };
-    XIEventMask all_devs = { XIAllDevices, sizeof(all_devs_bits), all_devs_bits };
+    XIEventMask all_devs;
+
+    InitializeMask(XIAllDevices, &all_devs);
 
     if (!pointer_callbacks_.empty())
     {
@@ -254,10 +300,19 @@
       XISetMask(all_devs.mask, XI_KeyRelease);
     }
 
-    XIEventMask selected[] = {master_dev, all_devs};
+    // Note: XISelectEvents can take several masks with the same deviceid,
+    // and only the last mask will be effective, here the merged ones
+    XIEventMask selected[num_basemasks_ + 2];
+    memcpy(selected, basemasks_, num_basemasks_ * sizeof(basemasks_[0]));
+    selected[num_basemasks_] = master_dev;
+    selected[num_basemasks_+1] = all_devs;
+
     XISelectEvents(dpy, root, selected, G_N_ELEMENTS(selected));
     XSync(dpy, False);
 
+    free(master_dev.mask);
+    free(all_devs.mask);
+
     LOG_DEBUG(logger) << "Pointer clients: " << pointer_callbacks_.size() << ", "
                       << "Key clients: " << key_callbacks_.size() << ", "
                       << "Barrier clients: " << barrier_callbacks_.size();
@@ -374,6 +429,8 @@
   EventCallbackSet key_callbacks_;
   EventCallbackSet barrier_callbacks_;
   EventCallbackSet removal_queue_;
+  XIEventMask* basemasks_;
+  int num_basemasks_;
 };
 
 Monitor::Monitor()

