Merge lp:~samuel-thibault/unity/shortcuts into lp:unity

Proposed by Samuel thibault on 2017-12-14
Status: Needs review
Proposed branch: lp:~samuel-thibault/unity/shortcuts
Merge into: lp:unity
Diff against target: 130 lines (+62/-5)
1 file modified
unity-shared/InputMonitor.cpp (+62/-5)
To merge this branch: bzr merge lp:~samuel-thibault/unity/shortcuts
Reviewer Review Type Date Requested Status
Samuel thibault (community) Resubmit on 2017-12-21
Unity Team 2017-12-14 Pending
Review via email: mp+335231@code.launchpad.net
To post a comment you must log in.
Marco Trevisan (Treviño) (3v1n0) wrote :

Thanks for this, looks sane... Check the comments please.

lp:~samuel-thibault/unity/shortcuts updated on 2017-12-14
4267. By Samuel thibault on 2017-12-14

xi2: Rework according to review

Samuel thibault (samuel-thibault) wrote :

I pushed fixes to address the comments.

review: Resubmit
Marco Trevisan (Treviño) (3v1n0) wrote :

Just an update... I've tried this, but there are some problems... For example the Alt+Mouse-down to Move doesn't work and same for right click on Unity window switcher to select windows.

I've been debugging this a bit, and also I've prepared some cleanup for the compiz branch, I'll submit them asap.

Unmerged revisions

4267. By Samuel thibault on 2017-12-14

xi2: Rework according to review

4266. By Samuel thibault on 2017-12-14

xi2: Use compiz-provided masks as a base for ours

This is needed for the fix for https://launchpad.net/bugs/1653072 , which makes
compiz use xi2.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'unity-shared/InputMonitor.cpp'
2--- unity-shared/InputMonitor.cpp 2017-02-28 17:16:14 +0000
3+++ unity-shared/InputMonitor.cpp 2017-12-14 19:22:54 +0000
4@@ -135,8 +135,11 @@
5 : xi_opcode_(0)
6 , event_filter_set_(false)
7 , invoking_callbacks_(false)
8+ , basemasks_(nullptr)
9+ , num_basemasks_(0)
10 {
11 Display *dpy = gdk_x11_get_default_xdisplay();
12+ Window root = DefaultRootWindow(dpy);
13 int event_base, error_base;
14
15 if (XQueryExtension(dpy, "XInputExtension", &xi_opcode_, &event_base, &error_base))
16@@ -149,6 +152,10 @@
17 LOG_ERROR(logger) << "Need XInput version "<< maj << "." << min << ", "
18 << "impossible, to setup an InputMonitor";
19 }
20+ else
21+ {
22+ basemasks_ = XIGetSelectedEvents(dpy, root, &num_basemasks_);
23+ }
24 }
25 else
26 {
27@@ -165,6 +172,7 @@
28 barrier_callbacks_.clear();
29 UpdateEventMonitor();
30 }
31+ XFree(basemasks_);
32 }
33
34 bool RegisterClient(Events type, EventCallback const& cb)
35@@ -223,14 +231,51 @@
36 return events;
37 }
38
39+ // Prepare a mask based on the Compiz-configured mask
40+ void InitializeMask(int deviceid, XIEventMask* ourmask)
41+ {
42+ int wanted_mask_len = XIMaskLen(XI_LASTEVENT);
43+ int mask_len = -1;
44+ unsigned char* mask;
45+
46+ for (int i = 0; i < num_basemasks_; i++)
47+ {
48+ if (basemasks_[i].deviceid == deviceid)
49+ {
50+ // Compiz is already listening for some events on this device, use this as a base
51+
52+ mask_len = basemasks_[i].mask_len;
53+ if (mask_len < wanted_mask_len)
54+ mask_len = wanted_mask_len;
55+
56+ mask = (unsigned char*) malloc(mask_len);
57+ memcpy(mask, basemasks_[i].mask, basemasks_[i].mask_len);
58+ memset(mask + basemasks_[i].mask_len, 0,
59+ mask_len - basemasks_[i].mask_len);
60+ break;
61+ }
62+ }
63+
64+ if (mask_len < 0)
65+ {
66+ mask_len = wanted_mask_len;
67+ mask = (unsigned char*) calloc(mask_len, 1);
68+ }
69+
70+ ourmask->deviceid = deviceid;
71+ ourmask->mask_len = mask_len;
72+ ourmask->mask = mask;
73+ }
74+
75 void UpdateEventMonitor()
76 {
77 auto* nux_dpy = nux::GetGraphicsDisplay();
78 auto* dpy = nux_dpy ? nux_dpy->GetX11Display() : gdk_x11_get_default_xdisplay();
79 Window root = DefaultRootWindow(dpy);
80
81- unsigned char master_dev_bits[XIMaskLen(XI_LASTEVENT)] = { 0 };
82- XIEventMask master_dev = { XIAllMasterDevices, sizeof(master_dev_bits), master_dev_bits };
83+ XIEventMask master_dev;
84+
85+ InitializeMask(XIAllMasterDevices, &master_dev);
86
87 if (!barrier_callbacks_.empty())
88 {
89@@ -238,8 +283,9 @@
90 XISetMask(master_dev.mask, XI_BarrierLeave);
91 }
92
93- unsigned char all_devs_bits[XIMaskLen(XI_LASTEVENT)] = { 0 };
94- XIEventMask all_devs = { XIAllDevices, sizeof(all_devs_bits), all_devs_bits };
95+ XIEventMask all_devs;
96+
97+ InitializeMask(XIAllDevices, &all_devs);
98
99 if (!pointer_callbacks_.empty())
100 {
101@@ -254,10 +300,19 @@
102 XISetMask(all_devs.mask, XI_KeyRelease);
103 }
104
105- XIEventMask selected[] = {master_dev, all_devs};
106+ // Note: XISelectEvents can take several masks with the same deviceid,
107+ // and only the last mask will be effective, here the merged ones
108+ XIEventMask selected[num_basemasks_ + 2];
109+ memcpy(selected, basemasks_, num_basemasks_ * sizeof(basemasks_[0]));
110+ selected[num_basemasks_] = master_dev;
111+ selected[num_basemasks_+1] = all_devs;
112+
113 XISelectEvents(dpy, root, selected, G_N_ELEMENTS(selected));
114 XSync(dpy, False);
115
116+ free(master_dev.mask);
117+ free(all_devs.mask);
118+
119 LOG_DEBUG(logger) << "Pointer clients: " << pointer_callbacks_.size() << ", "
120 << "Key clients: " << key_callbacks_.size() << ", "
121 << "Barrier clients: " << barrier_callbacks_.size();
122@@ -374,6 +429,8 @@
123 EventCallbackSet key_callbacks_;
124 EventCallbackSet barrier_callbacks_;
125 EventCallbackSet removal_queue_;
126+ XIEventMask* basemasks_;
127+ int num_basemasks_;
128 };
129
130 Monitor::Monitor()