Merge lp:~albertomilone/unity-settings-daemon/non-blocking-touch-mapping-wily into lp:unity-settings-daemon

Proposed by Alberto Milone
Status: Merged
Approved by: Iain Lane
Approved revision: 4091
Merged at revision: 4092
Proposed branch: lp:~albertomilone/unity-settings-daemon/non-blocking-touch-mapping-wily
Merge into: lp:unity-settings-daemon
Diff against target: 231 lines (+156/-18)
1 file modified
plugins/xrandr/gsd-xrandr-manager.c (+156/-18)
To merge this branch: bzr merge lp:~albertomilone/unity-settings-daemon/non-blocking-touch-mapping-wily
Reviewer Review Type Date Requested Status
Iain Lane Approve
Canonical Desktop Team Pending
Review via email: mp+266248@code.launchpad.net

Commit message

Make touchscreen mapping non-blocking, and kill it if it takes more than 3 seconds; finally, in case of failure, try again after a few seconds. This helps on resume from S3 (LP: #1471708).

Description of the change

Make touchscreen mapping non-blocking, and kill it if it takes more than 3 seconds; finally, in case of failure, try again after a few seconds. This helps on resume from S3 (LP: #1471708).

To post a comment you must log in.
Revision history for this message
Iain Lane (laney) wrote :

Basic logic mostly fine (not tested), some comments inline. I hope they make sense.

Style for this file is to not include {} when not required - i.e. if there's only one statement in that branch.

review: Needs Fixing
4091. By Alberto Milone

Keep track of processes and retries dinamically

Revision history for this message
Iain Lane (laney) wrote :

I think this is fine, thanks. Just some small comments to fix. Feel free to upload once that is done.

review: Approve
4092. By Alberto Milone

Add whitespaces and remove duplicate message

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/xrandr/gsd-xrandr-manager.c'
2--- plugins/xrandr/gsd-xrandr-manager.c 2014-11-27 10:32:03 +0000
3+++ plugins/xrandr/gsd-xrandr-manager.c 2015-08-25 08:21:49 +0000
4@@ -129,6 +129,13 @@
5 gchar *main_touchscreen_name;
6 };
7
8+typedef struct {
9+ int mapping_pid;
10+ guint mapping_kill_id;
11+ guint mapping_retry_id;
12+ gboolean mapping_killed;
13+} TouchMappingPrivate;
14+
15 static const GsdRRRotation possible_rotations[] = {
16 GSD_RR_ROTATION_0,
17 GSD_RR_ROTATION_90,
18@@ -157,9 +164,14 @@
19
20 static FILE *log_file;
21
22+/* Wait before retrying */
23+static const int RETRY_TIMEOUT = 5;
24+/* Wait before timing out */
25+static const int MAPPING_TIMEOUT = 3;
26+
27 static GsdRROutput * input_info_find_size_match (GsdXrandrManager *manager, GsdRRScreen *rr_screen);
28-static int map_touch_to_output (GsdRRScreen *screen, int device_id, GsdRROutputInfo *output);
29-static void do_touchscreen_mapping (GsdXrandrManager *manager);
30+static int map_touch_to_output (GsdXrandrManager *manager, GsdRROutputInfo *output);
31+static gboolean do_touchscreen_mapping (GsdXrandrManager *manager);
32
33 static void
34 log_open (void)
35@@ -2179,37 +2191,163 @@
36 XFreeDeviceList (device_info);
37 }
38
39+/* Kill a mapping process */
40+static gboolean
41+cb_mapping_child_kill (gpointer data)
42+{
43+ int kill_status;
44+
45+ gchar *message = NULL;
46+ TouchMappingPrivate *mapping_data = (TouchMappingPrivate*) data;
47+
48+ message = g_strdup_printf ("Killing touchscreen mapping process %d after %d second(s) timeout...",
49+ mapping_data->mapping_pid, MAPPING_TIMEOUT);
50+
51+ if (!message) {
52+ g_error ("Failed to allocate memory to log the killing of the mapping process");
53+ goto out;
54+ }
55+
56+ g_warning ("%s", message);
57+
58+ g_free (message);
59+
60+ kill_status = kill (mapping_data->mapping_pid, SIGTERM);
61+
62+ /* Mark as killed */
63+ mapping_data->mapping_killed = TRUE;
64+
65+ g_debug ("Kill status %d...", kill_status);
66+
67+ if (kill_status != 0)
68+ g_error ("Failed to kill mapping process: %s", strerror (errno));
69+
70+out:
71+ return G_SOURCE_REMOVE;
72+}
73+
74+/* Clean up spawned processes when they are done */
75+static void
76+cb_mapping_child_watch (GPid pid,
77+ gint status,
78+ gpointer data)
79+{
80+ TouchMappingPrivate *mapping_data = (TouchMappingPrivate*) data;
81+
82+ g_debug ("Cleaning up spawned mapping");
83+
84+ /* Close pid */
85+ g_spawn_close_pid (pid);
86+
87+ /* No need to kill a process that ended */
88+ if (mapping_data->mapping_kill_id > 0) {
89+ g_debug ("Cancelling killing of process that ended");
90+ g_source_remove (mapping_data->mapping_kill_id);
91+ }
92+
93+ /* No need to retry if it succeeded */
94+ if (!mapping_data->mapping_killed) {
95+ g_debug ("Cancelling retry id %d", mapping_data->mapping_retry_id);
96+ g_source_remove (mapping_data->mapping_retry_id);
97+ }
98+
99+ /* Free mapping data */
100+ g_slice_free (TouchMappingPrivate, mapping_data);
101+ mapping_data = NULL;
102+}
103+
104 static int
105-map_touch_to_output (GsdRRScreen *screen, int device_id,
106- GsdRROutputInfo *output)
107+map_touch_to_output (GsdXrandrManager *manager, GsdRROutputInfo *output)
108 {
109- int status = 0;
110- char command[100];
111+ TouchMappingPrivate *mapping_data = NULL;
112+ gchar *command_str = NULL;
113+ GError **error = NULL;
114+ gboolean success = FALSE;
115+ gchar **command = NULL;
116+
117+ GsdXrandrManagerPrivate *priv = manager->priv;
118 gchar *name = gsd_rr_output_info_get_name (output);
119
120 if (!name) {
121 g_debug ("Failure to map screen with missing name");
122- status = 1;
123 goto out;
124 }
125
126- if (gsd_rr_output_info_is_active(output)) {
127+ if (gsd_rr_output_info_is_active (output)) {
128 g_debug ("Mapping touchscreen %d onto output %s",
129- device_id, name);
130- sprintf (command, "xinput --map-to-output %d %s",
131- device_id, name);
132- status = system (command);
133+ priv->main_touchscreen_id, name);
134+
135+ command_str = g_strdup_printf ("/usr/bin/xinput --map-to-output %d %s",
136+ priv->main_touchscreen_id, name);
137+
138+ if (!command_str)
139+ goto out;
140+
141+ if (!g_shell_parse_argv (command_str, NULL, &command, NULL))
142+ goto out;
143+
144+ /* Each spawned process gets its own mapping data */
145+ mapping_data = g_slice_new (TouchMappingPrivate);
146+ if (!mapping_data) {
147+ g_error ("Touchscreen mapping resource allocation failed");
148+ goto out;
149+ }
150+ /* Initialise mapping data */
151+ mapping_data->mapping_pid = -1;
152+ mapping_data->mapping_kill_id = 0;
153+ mapping_data->mapping_retry_id = 0;
154+ mapping_data->mapping_killed = FALSE;
155+
156+ success = g_spawn_async (NULL,
157+ command,
158+ NULL,
159+ G_SPAWN_DO_NOT_REAP_CHILD,
160+ NULL,
161+ NULL,
162+ &(mapping_data->mapping_pid),
163+ error);
164+ g_strfreev (command);
165+
166+ if (success) {
167+ g_debug ("Touchscreen mapping spawn succeeded");
168+
169+ /* Clean up after child is done */
170+ g_child_watch_add (mapping_data->mapping_pid, (GChildWatchFunc) cb_mapping_child_watch,
171+ mapping_data);
172+ /* Kill the child after n seconds */
173+ mapping_data->mapping_kill_id = g_timeout_add_seconds (MAPPING_TIMEOUT,
174+ (GSourceFunc) cb_mapping_child_kill,
175+ mapping_data);
176+ /* Set potential retry */
177+ g_debug ("Retrying in %d second(s)", RETRY_TIMEOUT+MAPPING_TIMEOUT);
178+ mapping_data->mapping_retry_id = g_timeout_add_seconds (RETRY_TIMEOUT+MAPPING_TIMEOUT,
179+ (GSourceFunc) do_touchscreen_mapping,
180+ manager);
181+ g_debug ("Retry id: %d", mapping_data->mapping_retry_id);
182+ }
183+ else {
184+ g_error ("Touchscreen mapping failed");
185+ if (error != NULL)
186+ g_error ("%s", (*error)->message);
187+ g_clear_error (error);
188+
189+ /* Free mapping data */
190+ g_slice_free(TouchMappingPrivate, mapping_data);
191+ mapping_data = NULL;
192+ }
193 }
194 else {
195 g_debug ("No need to map %d onto output %s. The output is off",
196- device_id, name);
197+ priv->main_touchscreen_id, name);
198 }
199
200 out:
201- return (status == 0);
202+ g_free (command_str);
203+
204+ return success;
205 }
206
207-static void
208+static gboolean
209 do_touchscreen_mapping (GsdXrandrManager *manager)
210 {
211 GsdXrandrManagerPrivate *priv = manager->priv;
212@@ -2231,9 +2369,7 @@
213 if (priv->main_touchscreen_id != -1) {
214 /* Set initial mapping */
215 g_debug ("Setting initial touchscreen mapping");
216- map_touch_to_output (screen,
217- priv->main_touchscreen_id,
218- laptop_output);
219+ map_touch_to_output (manager, laptop_output);
220 }
221 else {
222 g_debug ("No main touchscreen detected");
223@@ -2241,6 +2377,8 @@
224
225 out:
226 g_object_unref (current);
227+
228+ return G_SOURCE_REMOVE;
229 }
230
231 gboolean

Subscribers

People subscribed via source and target branches