Merge lp:~afrantzis/unity-system-compositor/fix-1543495-spinner-orientation into lp:unity-system-compositor

Proposed by Alexandros Frantzis
Status: Merged
Approved by: Alexandros Frantzis
Approved revision: 275
Merged at revision: 276
Proposed branch: lp:~afrantzis/unity-system-compositor/fix-1543495-spinner-orientation
Merge into: lp:unity-system-compositor
Diff against target: 344 lines (+119/-122)
2 files modified
debian/control (+1/-0)
spinner/eglspinner.cpp (+118/-122)
To merge this branch: bzr merge lp:~afrantzis/unity-system-compositor/fix-1543495-spinner-orientation
Reviewer Review Type Date Requested Status
Andreas Pokorny (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+285621@code.launchpad.net

Commit message

Orient the spinner according to the native orientation of the device

Description of the change

Orient the spinner according to the native orientation of the device

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

I dont like the logic around HAVE_PROPS and then taking the device configuration file or android.conf. Sine we will do that on regular desktops too. But that is preexisting.

Additionally what if someone configures a value in android.conf or generic.conf but does not set that value in the per device configuration, again preexisting.

review: Approve
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

I agree that the logic there could be improved, especially for the desktop, but as you note it's all pre-existing so we are not breaking anything that's not already broken. Hopefully the refactoring that was performed will make it much easier to change the code in the future.

> Additionally what if someone configures a value in android.conf or generic.conf
> but does not set that value in the per device configuration, again preexisting.

The per device configurations are just a fallback in case no android.conf is found. Note that android.conf is not part of the regular ubuntu package that provides the conf files, but is provided by the android part of the system image and is therefore device specific (i.e., /etc/ubuntu-touch-session.d/android.conf is really mounted from /system/ubuntu/etc/ubuntu-touch-session.d/android.conf). All recent images provide a suitable android.conf.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2016-01-27 23:25:41 +0000
3+++ debian/control 2016-02-10 15:36:19 +0000
4@@ -13,6 +13,7 @@
5 libdbus-1-dev,
6 libglib2.0-dev,
7 libgles2-mesa-dev,
8+ libglm-dev,
9 libmirclient-dev (>= 0.19.0),
10 libmirserver-dev (>= 0.19.0),
11 libprotobuf-dev,
12
13=== modified file 'spinner/eglspinner.cpp'
14--- spinner/eglspinner.cpp 2015-12-02 16:28:08 +0000
15+++ spinner/eglspinner.cpp 2016-02-10 15:36:19 +0000
16@@ -25,26 +25,26 @@
17 #include <glib.h>
18 #include <string.h>
19 #include <GLES2/gl2.h>
20-#include <sys/stat.h>
21 #if HAVE_PROPS
22 #include <hybris/properties/properties.h>
23 #endif
24 #include <signal.h>
25
26+#include <fstream>
27+#include <algorithm>
28+#include <cctype>
29+#include <map>
30+#include <iostream>
31+
32+#define GLM_FORCE_RADIANS
33+#include <glm/gtc/matrix_transform.hpp>
34+#include <glm/gtc/type_ptr.hpp>
35+
36 #include "wallpaper.h"
37 #include "logo.h"
38 #include "white_dot.h"
39 #include "orange_dot.h"
40
41-// this is needed for get_gu() to obtain the grid-unit value
42-#define MAX_LENGTH 256
43-#define VALUE_KEY "GRID_UNIT_PX"
44-#define VALUE_KEY_LENGTH 12
45-#define PROP_KEY "ro.product.device"
46-#define DEFAULT_FILE "/etc/ubuntu-touch-session.d/android.conf"
47-#define FILE_BASE "/etc/ubuntu-touch-session.d/"
48-#define FILE_EXTENSION ".conf"
49-
50 enum TextureIds {
51 WALLPAPER = 0,
52 LOGO,
53@@ -53,66 +53,77 @@
54 MAX_TEXTURES
55 };
56
57-int get_gu ()
58+class SessionConfig
59 {
60- int gu = 13; // use 13 as a default value
61- FILE* handle = NULL;
62- int i = 0;
63- int j = 0;
64- int len = 0;
65- char line[MAX_LENGTH];
66- char filename[MAX_LENGTH];
67-
68- // get name of file to read from
69- bzero ((void*) filename, MAX_LENGTH);
70- strcpy (filename, FILE_BASE);
71-
72- struct stat buf;
73- if (stat(DEFAULT_FILE, &buf) == 0)
74- {
75- strcpy (filename, DEFAULT_FILE);
76- }
77- else
78- {
79-#ifdef HAVE_PROPS
80- char const* defaultValue = "";
81- char value[PROP_VALUE_MAX];
82- property_get (PROP_KEY, value, defaultValue);
83- strcat (filename, value);
84-#endif
85- strcat (filename, FILE_EXTENSION);
86- }
87-
88- // try to open it
89- handle = fopen ((const char*) filename, "r");
90- if (!handle)
91- return gu;
92-
93- // read one line at a time
94- while (fgets (line, MAX_LENGTH, handle))
95- {
96- // strip line of whitespaces
97- i = 0;
98- j = 0;
99- len = (int) strlen (line);
100- while (i != len)
101- {
102- if (line[i] != ' ' && line[i] != '\t')
103- line[j++] = line[i];
104- i++;
105- }
106- line[j] = 0;
107-
108- // parse the line for GU-value
109- if (!strncmp (line, VALUE_KEY, VALUE_KEY_LENGTH))
110- sscanf (line, VALUE_KEY"=%d", &gu);
111- }
112-
113- // clean up
114- fclose (handle);
115-
116- return gu;
117-}
118+public:
119+ SessionConfig()
120+ {
121+ parse_session_conf_file();
122+ }
123+
124+ int get_int(std::string const& key, int default_value)
125+ {
126+ try
127+ {
128+ if (conf_map.find(key) != conf_map.end())
129+ return std::stoi(conf_map[key]);
130+ }
131+ catch (...)
132+ {
133+ }
134+
135+ return default_value;
136+ }
137+
138+ std::string get_string(std::string const& key, std::string const& default_value)
139+ {
140+ return conf_map.find(key) != conf_map.end() ? conf_map[key] : default_value;
141+ }
142+
143+private:
144+ void parse_session_conf_file()
145+ {
146+ std::ifstream fs{default_file};
147+ if (!fs.is_open())
148+ {
149+ fs.clear();
150+ #ifdef HAVE_PROPS
151+ char const* default_value = "";
152+ char value[PROP_VALUE_MAX];
153+ property_get(device_property_key, value, default_value);
154+ #endif
155+ fs.open(file_base + value + file_extension);
156+ }
157+
158+ std::string line;
159+ while (std::getline(fs, line))
160+ conf_map.insert(parse_key_value_pair(line));
161+ }
162+
163+ std::string trim(std::string const& s)
164+ {
165+ auto const wsfront = std::find_if_not(s.begin(), s.end(), [](int c) { return std::isspace(c); });
166+ auto const wsback = std::find_if_not(s.rbegin(), s.rend(), [](int c) { return std::isspace(c); }).base();
167+ return (wsback <= wsfront ? std::string() : std::string(wsfront, wsback));
168+ }
169+
170+ std::pair<std::string,std::string> parse_key_value_pair(std::string kv)
171+ {
172+ auto const separator = kv.find("=");
173+ auto const key = kv.substr(0, separator);
174+ auto const value = separator != std::string::npos ?
175+ kv.substr(separator + 1, std::string::npos) :
176+ std::string{};
177+
178+ return {trim(key), trim(value)};
179+ }
180+
181+ std::string const default_file{"/etc/ubuntu-touch-session.d/android.conf"};
182+ std::string const file_base{"/etc/ubuntu-touch-session.d/"};
183+ std::string const file_extension{".conf"};
184+ char const* device_property_key = "ro.product.device";
185+ std::map<std::string,std::string> conf_map;
186+};
187
188 static GLuint load_shader(const char *src, GLenum type)
189 {
190@@ -212,49 +223,6 @@
191 int dot_mask;
192 } AnimationValues;
193
194-void ortho(GLfloat* mat,
195- GLfloat left,
196- GLfloat right,
197- GLfloat bottom,
198- GLfloat top,
199- GLfloat near,
200- GLfloat far)
201-{
202- if (right == left ||
203- top == bottom ||
204- far == near ||
205- mat == NULL)
206- {
207- return;
208- }
209-
210- mat[0] = 2.0f / (right - left);
211- mat[1] = 0.0f;
212- mat[2] = 0.0f;
213- mat[3] = 0.0f;
214-
215- mat[4] = 0.0f;
216- mat[5] = 2.0f / (top - bottom);
217- mat[6] = 0.0f;
218- mat[7] = 0.0f;
219-
220- mat[8] = 0.0f;
221- mat[9] = 0.0f;
222- mat[10] = -2.0f / (far - near);
223- mat[11] = 0.0f;
224-
225- mat[12] = -(right + left) / (right - left);
226- mat[13] = -(top + bottom) / (top - bottom);
227- mat[14] = -(far + near) / (far - near);
228- mat[15] = 1.0f;
229-}
230-
231-GLfloat gu2px(GLfloat gu) {
232- static GLfloat pixelsPerGU = get_gu();
233-
234- return gu * pixelsPerGU;
235-}
236-
237 void
238 updateAnimation (GTimer* timer, AnimationValues* anim)
239 {
240@@ -329,6 +297,8 @@
241 GLint offset[MAX_TEXTURES];
242 GLint projMat[MAX_TEXTURES];
243
244+ SessionConfig session_config;
245+
246 auto const surfaces = mir_eglapp_init(argc, argv);
247
248 if (!surfaces.size())
249@@ -400,23 +370,43 @@
250 AnimationValues anim = {0.0, 0.0, 0};
251 GTimer* timer = g_timer_new();
252
253+ auto const pixels_per_gu = session_config.get_int("GRID_UNIT_PX", 13);
254+ auto const gu2px =
255+ [pixels_per_gu] (float gu)
256+ {
257+ return pixels_per_gu * gu;
258+ };
259+ auto const native_orientation = session_config.get_string("NATIVE_ORIENTATION", "");
260+
261+ std::cout << "Spinner using pixels per grid unit: " << pixels_per_gu << std::endl;
262+ std::cout << "Spinner using native orientation: '" << native_orientation << "'" << std::endl;
263+
264 while (mir_eglapp_running())
265 {
266 for (auto const& surface : surfaces)
267 surface->paint([&](unsigned int width, unsigned int height)
268 {
269+ bool const needs_rotation =
270+ (width < height && native_orientation == "landscape") ||
271+ (width > height && native_orientation == "portrait");
272+
273 GLfloat logoWidth = gu2px (14.5f);
274 GLfloat logoHeight = gu2px (3.0f);
275 GLfloat logoXOffset = gu2px (1.0f);
276 GLfloat dotSize = gu2px (0.5f);
277 GLfloat dotXGap = gu2px (2.5f);
278 GLfloat dotYGap = gu2px (2.0f);
279+
280+ auto render_width = width;
281+ auto render_height = height;
282+ if (needs_rotation)
283+ std::swap(render_width, render_height);
284
285 const GLfloat fullscreen[] = {
286- (GLfloat) width, 0.0f,
287- (GLfloat) width, (GLfloat) height,
288+ (GLfloat) render_width, 0.0f,
289+ (GLfloat) render_width, (GLfloat) render_height,
290 0.0f, 0.0f,
291- 0.0f, (GLfloat) height
292+ 0.0f, (GLfloat) render_height
293 };
294
295 const GLfloat logo[] = {
296@@ -433,8 +423,14 @@
297 0.0f, dotSize
298 };
299
300- GLfloat projMatrix[16];
301- ortho(&projMatrix[0], 0.0f, (GLfloat) width, (GLfloat) height, 0.0f, -1.0f, 1.0f);
302+ auto mvpMatrix = glm::mat4(1.0f);
303+ if (needs_rotation)
304+ mvpMatrix = glm::rotate(mvpMatrix, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f));
305+ mvpMatrix = glm::translate(mvpMatrix, glm::vec3(-1.0, -1.0, 0.0f));
306+ mvpMatrix = glm::scale(mvpMatrix,
307+ glm::vec3(2.0f / render_width, 2.0f / render_height, 1.0f));
308+ auto const projMatrix = glm::ortho(-1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f);
309+ mvpMatrix = projMatrix * mvpMatrix;
310
311 glViewport(0, 0, width, height);
312
313@@ -447,7 +443,7 @@
314 glBindTexture(GL_TEXTURE_2D, texture[WALLPAPER]);
315 glUniform1i(sampler[WALLPAPER], 0);
316 glUniform2f(offset[WALLPAPER], 0.0f, 0.0f);
317- glUniformMatrix4fv(projMat[WALLPAPER], 1, GL_FALSE, projMatrix);
318+ glUniformMatrix4fv(projMat[WALLPAPER], 1, GL_FALSE, glm::value_ptr(mvpMatrix));
319 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
320
321 // draw logo
322@@ -455,18 +451,18 @@
323 glUseProgram(prog[LOGO]);
324 glBindTexture(GL_TEXTURE_2D, texture[LOGO]);
325 glUniform1i(sampler[LOGO], 0);
326- glUniform2f(offset[LOGO], width/2.0f - logoWidth / 2.0f + logoXOffset, height / 2.0f - logoHeight * 0.75f);
327- glUniformMatrix4fv(projMat[LOGO], 1, GL_FALSE, projMatrix);
328+ glUniform2f(offset[LOGO], render_width/2.0f - logoWidth / 2.0f + logoXOffset, render_height / 2.0f - logoHeight * 0.75f);
329+ glUniformMatrix4fv(projMat[LOGO], 1, GL_FALSE, glm::value_ptr(mvpMatrix));
330 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
331
332 // draw white/orange dots
333 glVertexAttribPointer(vpos[WHITE_DOT], 2, GL_FLOAT, GL_FALSE, 0, dot);
334 glUseProgram(prog[WHITE_DOT]);
335 glUniform1i(sampler[WHITE_DOT], 0);
336- glUniformMatrix4fv(projMat[WHITE_DOT], 1, GL_FALSE, projMatrix);
337+ glUniformMatrix4fv(projMat[WHITE_DOT], 1, GL_FALSE, glm::value_ptr(mvpMatrix));
338 for (int i = -2; i < 3; i++) {
339 glBindTexture(GL_TEXTURE_2D, texture[anim.dot_mask >> (i + 2) ? ORANGE_DOT : WHITE_DOT]);
340- glUniform2f(offset[WHITE_DOT], width/2.0f + i * dotXGap, height / 2.0f + logoHeight / 2.0f + dotYGap - logoHeight * 0.25f);
341+ glUniform2f(offset[WHITE_DOT], render_width/2.0f + i * dotXGap, render_height / 2.0f + logoHeight / 2.0f + dotYGap - logoHeight * 0.25f);
342 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
343 }
344 });

Subscribers

People subscribed via source and target branches