Mir

Merge lp:~kdub/mir/common-fd-type into lp:mir/ubuntu

Proposed by Kevin DuBois
Status: Superseded
Proposed branch: lp:~kdub/mir/common-fd-type
Merge into: lp:mir/ubuntu
Diff against target: 10587 lines (+4833/-1684)
165 files modified
3rd_party/CMakeLists.txt (+11/-1)
3rd_party/xcursor/CMakeLists.txt (+11/-0)
3rd_party/xcursor/xcursor.c (+968/-0)
3rd_party/xcursor/xcursor.h (+65/-0)
CMakeLists.txt (+27/-9)
debian/changelog (+25/-9)
debian/control (+4/-0)
debian/rules (+7/-0)
examples/eglcounter.cpp (+1/-1)
examples/egltriangle.c (+1/-1)
examples/minimal_server.cpp (+9/-1)
examples/multiwin.c (+10/-0)
include/client/mir_toolkit/mir_prompt_session.h (+17/-0)
include/platform/mir/graphics/cursor_image.h (+7/-0)
include/platform/mir/options/configuration.h (+1/-0)
include/server/mir/default_server_configuration.h (+19/-4)
include/server/mir/frontend/fd_sets.h (+2/-2)
include/server/mir/frontend/session_authorizer.h (+1/-0)
include/server/mir/input/cursor_images.h (+11/-8)
include/server/mir/server_configuration.h (+1/-0)
include/shared/mir/basic_observers.h (+122/-0)
include/shared/mir/fd.h (+43/-0)
include/shared/mir/graphics/android/fence.h (+2/-1)
include/shared/mir/graphics/android/sync_fence.h (+4/-4)
include/shared/mir/recursive_read_write_mutex.h (+77/-0)
include/test/mir_test_doubles/mock_buffer_registrar.h (+6/-6)
include/test/mir_test_doubles/mock_fence.h (+4/-0)
include/test/mir_test_doubles/mock_hwc_device_wrapper.h (+5/-0)
include/test/mir_test_doubles/null_client_buffer.h (+2/-1)
include/test/mir_test_doubles/stub_renderable.h (+6/-1)
include/test/mir_test_doubles/stub_session_authorizer.h (+13/-9)
include/test/mir_test_framework/in_process_server.h (+3/-0)
include/test/mir_test_framework/server_runner.h (+3/-0)
src/client/android/CMakeLists.txt (+1/-1)
src/client/android/android_client_buffer_factory.cpp (+4/-2)
src/client/android/android_client_buffer_factory.h (+8/-8)
src/client/android/android_client_platform.cpp (+2/-2)
src/client/android/buffer.cpp (+8/-2)
src/client/android/buffer.h (+4/-3)
src/client/android/buffer_registrar.h (+10/-6)
src/client/android/client_surface_interpreter.cpp (+1/-1)
src/client/android/gralloc_registrar.cpp (+6/-4)
src/client/android/gralloc_registrar.h (+6/-6)
src/client/client_buffer.h (+1/-0)
src/client/client_buffer_depository.cpp (+1/-0)
src/client/mesa/client_buffer.cpp (+4/-0)
src/client/mesa/client_buffer.h (+1/-0)
src/client/mir_prompt_session_api.cpp (+12/-0)
src/platform/graphics/android/android_alloc_adaptor.cpp (+1/-1)
src/platform/graphics/android/hwc_common_device.cpp (+21/-26)
src/platform/graphics/android/hwc_common_device.h (+5/-4)
src/platform/graphics/android/hwc_device.cpp (+71/-59)
src/platform/graphics/android/hwc_device.h (+1/-9)
src/platform/graphics/android/hwc_fb_device.cpp (+13/-11)
src/platform/graphics/android/hwc_fb_device.h (+1/-2)
src/platform/graphics/android/hwc_layerlist.cpp (+22/-22)
src/platform/graphics/android/hwc_layerlist.h (+13/-8)
src/platform/graphics/android/hwc_layers.cpp (+33/-45)
src/platform/graphics/android/hwc_layers.h (+16/-14)
src/platform/graphics/android/hwc_wrapper.h (+6/-0)
src/platform/graphics/android/real_hwc_wrapper.cpp (+45/-0)
src/platform/graphics/android/real_hwc_wrapper.h (+5/-0)
src/platform/graphics/android/resource_factory.cpp (+2/-2)
src/platform/graphics/mesa/cursor.cpp (+73/-20)
src/platform/graphics/mesa/cursor.h (+8/-0)
src/platform/graphics/mesa/display_buffer.cpp (+1/-1)
src/platform/options/default_configuration.cpp (+2/-0)
src/server/CMakeLists.txt (+4/-1)
src/server/asio_main_loop.cpp (+13/-2)
src/server/compositor/buffer_queue.cpp (+4/-0)
src/server/compositor/buffer_queue.h (+1/-1)
src/server/compositor/buffer_stream_factory.cpp (+1/-1)
src/server/default_emergency_cleanup.cpp (+46/-0)
src/server/default_emergency_cleanup.h (+53/-0)
src/server/default_server_configuration.cpp (+8/-29)
src/server/display_server.cpp (+12/-0)
src/server/frontend/CMakeLists.txt (+2/-0)
src/server/frontend/default_configuration.cpp (+85/-2)
src/server/frontend/default_ipc_factory.cpp (+11/-3)
src/server/frontend/default_ipc_factory.h (+7/-3)
src/server/frontend/no_prompt_shell.cpp (+56/-0)
src/server/frontend/no_prompt_shell.h (+52/-0)
src/server/frontend/protobuf_message_processor.cpp (+21/-26)
src/server/frontend/session_mediator.cpp (+4/-3)
src/server/frontend/session_mediator.h (+5/-2)
src/server/frontend/shell_wrapper.cpp (+74/-0)
src/server/frontend/shell_wrapper.h (+70/-0)
src/server/frontend/socket_messenger.cpp (+2/-2)
src/server/frontend/socket_messenger.h (+1/-1)
src/server/graphics/CMakeLists.txt (+0/-1)
src/server/graphics/default_configuration.cpp (+14/-29)
src/server/graphics/nested/nested_display.cpp (+0/-4)
src/server/input/CMakeLists.txt (+8/-1)
src/server/input/builtin_cursor_images.cpp (+7/-2)
src/server/input/builtin_cursor_images.h (+7/-9)
src/server/input/default_configuration.cpp (+43/-7)
src/server/input/nested_input_configuration.cpp (+0/-37)
src/server/input/nested_input_configuration.h (+0/-43)
src/server/input/xcursor_loader.cpp (+152/-0)
src/server/input/xcursor_loader.h (+71/-0)
src/server/run_mir.cpp (+5/-2)
src/server/scene/basic_surface.cpp (+23/-58)
src/server/scene/basic_surface.h (+4/-8)
src/server/scene/surface_stack.cpp (+12/-40)
src/server/scene/surface_stack.h (+5/-7)
src/shared/CMakeLists.txt (+2/-1)
src/shared/fd/CMakeLists.txt (+23/-0)
src/shared/fd/fd.cpp (+49/-0)
src/shared/graphics/android/CMakeLists.txt (+2/-0)
src/shared/graphics/android/android_native_buffer.cpp (+1/-1)
src/shared/graphics/android/syncfence.cpp (+7/-17)
src/shared/protobuf/mir_protobuf.proto (+0/-2)
src/shared/thread/CMakeLists.txt (+3/-2)
src/shared/thread/recursive_read_write_mutex.cpp (+87/-0)
tests/acceptance-tests/test_client_authorization.cpp (+1/-0)
tests/acceptance-tests/test_client_cursor_api.cpp (+9/-3)
tests/acceptance-tests/test_client_surface_events.cpp (+17/-4)
tests/acceptance-tests/test_nested_mir.cpp (+184/-140)
tests/acceptance-tests/test_prompt_session_client_api.cpp (+249/-64)
tests/acceptance-tests/test_protobuf.cpp (+1/-1)
tests/acceptance-tests/test_server_shutdown.cpp (+8/-7)
tests/integration-tests/client/test_client_render.cpp (+2/-2)
tests/integration-tests/client/test_screencast.cpp (+0/-12)
tests/integration-tests/input/test_nested_input.cpp (+3/-8)
tests/integration-tests/test_error_reporting.cpp (+2/-12)
tests/integration-tests/test_surfaceloop.cpp (+23/-11)
tests/mir_test_framework/server_runner.cpp (+7/-0)
tests/mir_test_framework/testing_client_options.cpp (+3/-0)
tests/unit-tests/CMakeLists.txt (+5/-0)
tests/unit-tests/client/android/CMakeLists.txt (+1/-1)
tests/unit-tests/client/android/test_android_native_window.cpp (+0/-1)
tests/unit-tests/client/android/test_buffer.cpp (+3/-3)
tests/unit-tests/client/android/test_client_surface_interpreter.cpp (+2/-1)
tests/unit-tests/client/android/test_gralloc_registrar.cpp (+117/-202)
tests/unit-tests/client/mesa/test_native_surface.cpp (+1/-1)
tests/unit-tests/client/test_aging_buffer.cpp (+4/-0)
tests/unit-tests/client/test_client_buffer_depository.cpp (+58/-54)
tests/unit-tests/client/test_client_mir_surface.cpp (+2/-0)
tests/unit-tests/client/test_event_distributor.cpp (+9/-1)
tests/unit-tests/compositor/test_buffer_queue.cpp (+14/-43)
tests/unit-tests/frontend/CMakeLists.txt (+0/-12)
tests/unit-tests/frontend/test_protobuf_reports_errors.cpp (+0/-9)
tests/unit-tests/frontend/test_protobuf_sends_fds.cpp (+0/-137)
tests/unit-tests/frontend/test_session_mediator.cpp (+1/-1)
tests/unit-tests/graphics/android/test_hwc_common_device.cpp (+59/-115)
tests/unit-tests/graphics/android/test_hwc_device.cpp (+195/-90)
tests/unit-tests/graphics/android/test_hwc_fb_device.cpp (+18/-12)
tests/unit-tests/graphics/android/test_hwc_layerlist.cpp (+47/-4)
tests/unit-tests/graphics/android/test_hwc_layers.cpp (+44/-36)
tests/unit-tests/graphics/android/test_hwc_wrapper.cpp (+70/-0)
tests/unit-tests/graphics/android/test_sync_fence.cpp (+17/-16)
tests/unit-tests/graphics/mesa/test_cursor.cpp (+104/-17)
tests/unit-tests/input/CMakeLists.txt (+1/-0)
tests/unit-tests/input/test_cursor_controller.cpp (+1/-0)
tests/unit-tests/input/test_xcursor_loader.cpp (+157/-0)
tests/unit-tests/input/testing-cursor-theme/default/cursors/arrow.in (+1/-0)
tests/unit-tests/input/testing-cursor-theme/default/cursors/blue.in (+1/-0)
tests/unit-tests/input/testing-cursor-theme/default/cursors/generate-theme.sh (+5/-0)
tests/unit-tests/input/testing-cursor-theme/default/cursors/green.in (+1/-0)
tests/unit-tests/input/testing-cursor-theme/default/cursors/red.in (+1/-0)
tests/unit-tests/scene/test_basic_surface.cpp (+84/-0)
tests/unit-tests/scene/test_surface_stack.cpp (+56/-0)
tests/unit-tests/test_asio_main_loop.cpp (+46/-0)
tests/unit-tests/test_default_emergency_cleanup.cpp (+70/-0)
tests/unit-tests/test_recursive_read_write_mutex.cpp (+176/-0)
To merge this branch: bzr merge lp:~kdub/mir/common-fd-type
Reviewer Review Type Date Requested Status
Mir development team Pending
Review via email: mp+226530@code.launchpad.net

Commit message

add a common raii-friendly type for managing file descriptors.

Description of the change

add a common raii-friendly type for managing file descriptors, and have the protobuf sender and the android sync fences convert to using the new fence as a start. This is useful for me in sending a new fd on every send message, as I can just move the fence fd around.

We had a few things floating around for fd's... most of them just ints with close() in the right location. This mp aims to improve this situation a bit.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '3rd_party/CMakeLists.txt'
2--- 3rd_party/CMakeLists.txt 2013-08-28 03:41:48 +0000
3+++ 3rd_party/CMakeLists.txt 2014-07-11 20:27:44 +0000
4@@ -25,8 +25,18 @@
5 MIR_ANDROID_INPUT_COMPILE_FLAGS
6 ${MIR_ANDROID_INPUT_COMPILE_FLAGS}
7 PARENT_SCOPE)
8+
9+add_subdirectory(xcursor)
10+list(
11+ APPEND MIR_XCURSOR_INCLUDE_DIRECTORIES
12+ ${CMAKE_CURRENT_SOURCE_DIR}/xcursor/
13+)
14+
15+set(MIR_XCURSOR_INCLUDE_DIRECTORIES ${MIR_XCURSOR_INCLUDE_DIRECTORIES} PARENT_SCOPE)
16
17 target_link_libraries(
18 3rd_party
19
20- android-input)
21+ android-input
22+ xcursorloader
23+)
24
25=== added directory '3rd_party/xcursor'
26=== added file '3rd_party/xcursor/CMakeLists.txt'
27--- 3rd_party/xcursor/CMakeLists.txt 1970-01-01 00:00:00 +0000
28+++ 3rd_party/xcursor/CMakeLists.txt 2014-07-11 20:27:44 +0000
29@@ -0,0 +1,11 @@
30+set(
31+ XCURSOR_SOURCES
32+
33+ xcursor.c
34+)
35+
36+add_library(
37+ xcursorloader STATIC
38+
39+ ${XCURSOR_SOURCES}
40+)
41
42=== added file '3rd_party/xcursor/xcursor.c'
43--- 3rd_party/xcursor/xcursor.c 1970-01-01 00:00:00 +0000
44+++ 3rd_party/xcursor/xcursor.c 2014-07-11 20:27:44 +0000
45@@ -0,0 +1,968 @@
46+/*
47+ * Copyright © 2002 Keith Packard
48+ *
49+ * Permission to use, copy, modify, distribute, and sell this software and its
50+ * documentation for any purpose is hereby granted without fee, provided that
51+ * the above copyright notice appear in all copies and that both that
52+ * copyright notice and this permission notice appear in supporting
53+ * documentation, and that the name of Keith Packard not be used in
54+ * advertising or publicity pertaining to distribution of the software without
55+ * specific, written prior permission. Keith Packard makes no
56+ * representations about the suitability of this software for any purpose. It
57+ * is provided "as is" without express or implied warranty.
58+ *
59+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
60+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
61+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
62+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
63+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
64+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
65+ * PERFORMANCE OF THIS SOFTWARE.
66+ */
67+
68+#include "xcursor.h"
69+#include <stdio.h>
70+#include <stdlib.h>
71+#include <string.h>
72+#include <dirent.h>
73+
74+/*
75+ * From libXcursor/include/X11/extensions/Xcursor.h
76+ */
77+
78+#define XcursorTrue 1
79+#define XcursorFalse 0
80+
81+/*
82+ * Cursor files start with a header. The header
83+ * contains a magic number, a version number and a
84+ * table of contents which has type and offset information
85+ * for the remaining tables in the file.
86+ *
87+ * File minor versions increment for compatible changes
88+ * File major versions increment for incompatible changes (never, we hope)
89+ *
90+ * Chunks of the same type are always upward compatible. Incompatible
91+ * changes are made with new chunk types; the old data can remain under
92+ * the old type. Upward compatible changes can add header data as the
93+ * header lengths are specified in the file.
94+ *
95+ * File:
96+ * FileHeader
97+ * LISTofChunk
98+ *
99+ * FileHeader:
100+ * CARD32 magic magic number
101+ * CARD32 header bytes in file header
102+ * CARD32 version file version
103+ * CARD32 ntoc number of toc entries
104+ * LISTofFileToc toc table of contents
105+ *
106+ * FileToc:
107+ * CARD32 type entry type
108+ * CARD32 subtype entry subtype (size for images)
109+ * CARD32 position absolute file position
110+ */
111+
112+#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */
113+
114+/*
115+ * Current Xcursor version number. Will be substituted by configure
116+ * from the version in the libXcursor configure.ac file.
117+ */
118+
119+#define XCURSOR_LIB_MAJOR 1
120+#define XCURSOR_LIB_MINOR 1
121+#define XCURSOR_LIB_REVISION 13
122+#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \
123+ (XCURSOR_LIB_MINOR * 100) + \
124+ (XCURSOR_LIB_REVISION))
125+
126+/*
127+ * This version number is stored in cursor files; changes to the
128+ * file format require updating this version number
129+ */
130+#define XCURSOR_FILE_MAJOR 1
131+#define XCURSOR_FILE_MINOR 0
132+#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR))
133+#define XCURSOR_FILE_HEADER_LEN (4 * 4)
134+#define XCURSOR_FILE_TOC_LEN (3 * 4)
135+
136+typedef struct _XcursorFileToc {
137+ XcursorUInt type; /* chunk type */
138+ XcursorUInt subtype; /* subtype (size for images) */
139+ XcursorUInt position; /* absolute position in file */
140+} XcursorFileToc;
141+
142+typedef struct _XcursorFileHeader {
143+ XcursorUInt magic; /* magic number */
144+ XcursorUInt header; /* byte length of header */
145+ XcursorUInt version; /* file version number */
146+ XcursorUInt ntoc; /* number of toc entries */
147+ XcursorFileToc *tocs; /* table of contents */
148+} XcursorFileHeader;
149+
150+/*
151+ * The rest of the file is a list of chunks, each tagged by type
152+ * and version.
153+ *
154+ * Chunk:
155+ * ChunkHeader
156+ * <extra type-specific header fields>
157+ * <type-specific data>
158+ *
159+ * ChunkHeader:
160+ * CARD32 header bytes in chunk header + type header
161+ * CARD32 type chunk type
162+ * CARD32 subtype chunk subtype
163+ * CARD32 version chunk type version
164+ */
165+
166+#define XCURSOR_CHUNK_HEADER_LEN (4 * 4)
167+
168+typedef struct _XcursorChunkHeader {
169+ XcursorUInt header; /* bytes in chunk header */
170+ XcursorUInt type; /* chunk type */
171+ XcursorUInt subtype; /* chunk subtype (size for images) */
172+ XcursorUInt version; /* version of this type */
173+} XcursorChunkHeader;
174+
175+/*
176+ * Here's a list of the known chunk types
177+ */
178+
179+/*
180+ * Comments consist of a 4-byte length field followed by
181+ * UTF-8 encoded text
182+ *
183+ * Comment:
184+ * ChunkHeader header chunk header
185+ * CARD32 length bytes in text
186+ * LISTofCARD8 text UTF-8 encoded text
187+ */
188+
189+#define XCURSOR_COMMENT_TYPE 0xfffe0001
190+#define XCURSOR_COMMENT_VERSION 1
191+#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4))
192+#define XCURSOR_COMMENT_COPYRIGHT 1
193+#define XCURSOR_COMMENT_LICENSE 2
194+#define XCURSOR_COMMENT_OTHER 3
195+#define XCURSOR_COMMENT_MAX_LEN 0x100000
196+
197+typedef struct _XcursorComment {
198+ XcursorUInt version;
199+ XcursorUInt comment_type;
200+ char *comment;
201+} XcursorComment;
202+
203+/*
204+ * Each cursor image occupies a separate image chunk.
205+ * The length of the image header follows the chunk header
206+ * so that future versions can extend the header without
207+ * breaking older applications
208+ *
209+ * Image:
210+ * ChunkHeader header chunk header
211+ * CARD32 width actual width
212+ * CARD32 height actual height
213+ * CARD32 xhot hot spot x
214+ * CARD32 yhot hot spot y
215+ * CARD32 delay animation delay
216+ * LISTofCARD32 pixels ARGB pixels
217+ */
218+
219+#define XCURSOR_IMAGE_TYPE 0xfffd0002
220+#define XCURSOR_IMAGE_VERSION 1
221+#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
222+#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
223+
224+typedef struct _XcursorFile XcursorFile;
225+
226+struct _XcursorFile {
227+ void *closure;
228+ int (*read) (XcursorFile *file, unsigned char *buf, int len);
229+ int (*write) (XcursorFile *file, unsigned char *buf, int len);
230+ int (*seek) (XcursorFile *file, long offset, int whence);
231+};
232+
233+typedef struct _XcursorComments {
234+ int ncomment; /* number of comments */
235+ XcursorComment **comments; /* array of XcursorComment pointers */
236+} XcursorComments;
237+
238+/*
239+ * From libXcursor/src/file.c
240+ */
241+
242+static XcursorImage *
243+XcursorImageCreate (int width, int height)
244+{
245+ XcursorImage *image;
246+
247+ image = malloc (sizeof (XcursorImage) +
248+ width * height * sizeof (XcursorPixel));
249+ if (!image)
250+ return NULL;
251+ image->version = XCURSOR_IMAGE_VERSION;
252+ image->pixels = (XcursorPixel *) (image + 1);
253+ image->size = width > height ? width : height;
254+ image->width = width;
255+ image->height = height;
256+ image->delay = 0;
257+ return image;
258+}
259+
260+static void
261+XcursorImageDestroy (XcursorImage *image)
262+{
263+ free (image);
264+}
265+
266+static XcursorImages *
267+XcursorImagesCreate (int size)
268+{
269+ XcursorImages *images;
270+
271+ images = malloc (sizeof (XcursorImages) +
272+ size * sizeof (XcursorImage *));
273+ if (!images)
274+ return NULL;
275+ images->nimage = 0;
276+ images->images = (XcursorImage **) (images + 1);
277+ images->name = NULL;
278+ return images;
279+}
280+
281+void
282+XcursorImagesDestroy (XcursorImages *images)
283+{
284+ int n;
285+
286+ if (!images)
287+ return;
288+
289+ for (n = 0; n < images->nimage; n++)
290+ XcursorImageDestroy (images->images[n]);
291+ if (images->name)
292+ free (images->name);
293+ free (images);
294+}
295+
296+static void
297+XcursorImagesSetName (XcursorImages *images, const char *name)
298+{
299+ char *new;
300+
301+ if (!images || !name)
302+ return;
303+
304+ new = malloc (strlen (name) + 1);
305+
306+ if (!new)
307+ return;
308+
309+ strcpy (new, name);
310+ if (images->name)
311+ free (images->name);
312+ images->name = new;
313+}
314+
315+static XcursorBool
316+_XcursorReadUInt (XcursorFile *file, XcursorUInt *u)
317+{
318+ unsigned char bytes[4];
319+
320+ if (!file || !u)
321+ return XcursorFalse;
322+
323+ if ((*file->read) (file, bytes, 4) != 4)
324+ return XcursorFalse;
325+ *u = ((bytes[0] << 0) |
326+ (bytes[1] << 8) |
327+ (bytes[2] << 16) |
328+ (bytes[3] << 24));
329+ return XcursorTrue;
330+}
331+
332+static void
333+_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader)
334+{
335+ free (fileHeader);
336+}
337+
338+static XcursorFileHeader *
339+_XcursorFileHeaderCreate (int ntoc)
340+{
341+ XcursorFileHeader *fileHeader;
342+
343+ if (ntoc > 0x10000)
344+ return NULL;
345+ fileHeader = malloc (sizeof (XcursorFileHeader) +
346+ ntoc * sizeof (XcursorFileToc));
347+ if (!fileHeader)
348+ return NULL;
349+ fileHeader->magic = XCURSOR_MAGIC;
350+ fileHeader->header = XCURSOR_FILE_HEADER_LEN;
351+ fileHeader->version = XCURSOR_FILE_VERSION;
352+ fileHeader->ntoc = ntoc;
353+ fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1);
354+ return fileHeader;
355+}
356+
357+static XcursorFileHeader *
358+_XcursorReadFileHeader (XcursorFile *file)
359+{
360+ XcursorFileHeader head, *fileHeader;
361+ XcursorUInt skip;
362+ unsigned int n;
363+
364+ if (!file)
365+ return NULL;
366+
367+ if (!_XcursorReadUInt (file, &head.magic))
368+ return NULL;
369+ if (head.magic != XCURSOR_MAGIC)
370+ return NULL;
371+ if (!_XcursorReadUInt (file, &head.header))
372+ return NULL;
373+ if (!_XcursorReadUInt (file, &head.version))
374+ return NULL;
375+ if (!_XcursorReadUInt (file, &head.ntoc))
376+ return NULL;
377+ skip = head.header - XCURSOR_FILE_HEADER_LEN;
378+ if (skip)
379+ if ((*file->seek) (file, skip, SEEK_CUR) == EOF)
380+ return NULL;
381+ fileHeader = _XcursorFileHeaderCreate (head.ntoc);
382+ if (!fileHeader)
383+ return NULL;
384+ fileHeader->magic = head.magic;
385+ fileHeader->header = head.header;
386+ fileHeader->version = head.version;
387+ fileHeader->ntoc = head.ntoc;
388+ for (n = 0; n < fileHeader->ntoc; n++)
389+ {
390+ if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type))
391+ break;
392+ if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype))
393+ break;
394+ if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position))
395+ break;
396+ }
397+ if (n != fileHeader->ntoc)
398+ {
399+ _XcursorFileHeaderDestroy (fileHeader);
400+ return NULL;
401+ }
402+ return fileHeader;
403+}
404+
405+static XcursorBool
406+_XcursorSeekToToc (XcursorFile *file,
407+ XcursorFileHeader *fileHeader,
408+ int toc)
409+{
410+ if (!file || !fileHeader || \
411+ (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF)
412+ return XcursorFalse;
413+ return XcursorTrue;
414+}
415+
416+static XcursorBool
417+_XcursorFileReadChunkHeader (XcursorFile *file,
418+ XcursorFileHeader *fileHeader,
419+ int toc,
420+ XcursorChunkHeader *chunkHeader)
421+{
422+ if (!file || !fileHeader || !chunkHeader)
423+ return XcursorFalse;
424+ if (!_XcursorSeekToToc (file, fileHeader, toc))
425+ return XcursorFalse;
426+ if (!_XcursorReadUInt (file, &chunkHeader->header))
427+ return XcursorFalse;
428+ if (!_XcursorReadUInt (file, &chunkHeader->type))
429+ return XcursorFalse;
430+ if (!_XcursorReadUInt (file, &chunkHeader->subtype))
431+ return XcursorFalse;
432+ if (!_XcursorReadUInt (file, &chunkHeader->version))
433+ return XcursorFalse;
434+ /* sanity check */
435+ if (chunkHeader->type != fileHeader->tocs[toc].type ||
436+ chunkHeader->subtype != fileHeader->tocs[toc].subtype)
437+ return XcursorFalse;
438+ return XcursorTrue;
439+}
440+
441+#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a))
442+
443+static XcursorDim
444+_XcursorFindBestSize (XcursorFileHeader *fileHeader,
445+ XcursorDim size,
446+ int *nsizesp)
447+{
448+ unsigned int n;
449+ int nsizes = 0;
450+ XcursorDim bestSize = 0;
451+ XcursorDim thisSize;
452+
453+ if (!fileHeader || !nsizesp)
454+ return 0;
455+
456+ for (n = 0; n < fileHeader->ntoc; n++)
457+ {
458+ if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE)
459+ continue;
460+ thisSize = fileHeader->tocs[n].subtype;
461+ if (!bestSize || dist (thisSize, size) < dist (bestSize, size))
462+ {
463+ bestSize = thisSize;
464+ nsizes = 1;
465+ }
466+ else if (thisSize == bestSize)
467+ nsizes++;
468+ }
469+ *nsizesp = nsizes;
470+ return bestSize;
471+}
472+
473+static int
474+_XcursorFindImageToc (XcursorFileHeader *fileHeader,
475+ XcursorDim size,
476+ int count)
477+{
478+ unsigned int toc;
479+ XcursorDim thisSize;
480+
481+ if (!fileHeader)
482+ return 0;
483+
484+ for (toc = 0; toc < fileHeader->ntoc; toc++)
485+ {
486+ if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE)
487+ continue;
488+ thisSize = fileHeader->tocs[toc].subtype;
489+ if (thisSize != size)
490+ continue;
491+ if (!count)
492+ break;
493+ count--;
494+ }
495+ if (toc == fileHeader->ntoc)
496+ return -1;
497+ return toc;
498+}
499+
500+static XcursorImage *
501+_XcursorReadImage (XcursorFile *file,
502+ XcursorFileHeader *fileHeader,
503+ int toc)
504+{
505+ XcursorChunkHeader chunkHeader;
506+ XcursorImage head;
507+ XcursorImage *image;
508+ int n;
509+ XcursorPixel *p;
510+
511+ if (!file || !fileHeader)
512+ return NULL;
513+
514+ if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader))
515+ return NULL;
516+ if (!_XcursorReadUInt (file, &head.width))
517+ return NULL;
518+ if (!_XcursorReadUInt (file, &head.height))
519+ return NULL;
520+ if (!_XcursorReadUInt (file, &head.xhot))
521+ return NULL;
522+ if (!_XcursorReadUInt (file, &head.yhot))
523+ return NULL;
524+ if (!_XcursorReadUInt (file, &head.delay))
525+ return NULL;
526+ /* sanity check data */
527+ if (head.width >= 0x10000 || head.height > 0x10000)
528+ return NULL;
529+ if (head.width == 0 || head.height == 0)
530+ return NULL;
531+ if (head.xhot > head.width || head.yhot > head.height)
532+ return NULL;
533+
534+ /* Create the image and initialize it */
535+ image = XcursorImageCreate (head.width, head.height);
536+ if (image == NULL)
537+ return NULL;
538+ if (chunkHeader.version < image->version)
539+ image->version = chunkHeader.version;
540+ image->size = chunkHeader.subtype;
541+ image->xhot = head.xhot;
542+ image->yhot = head.yhot;
543+ image->delay = head.delay;
544+ n = image->width * image->height;
545+ p = image->pixels;
546+ while (n--)
547+ {
548+ if (!_XcursorReadUInt (file, p))
549+ {
550+ XcursorImageDestroy (image);
551+ return NULL;
552+ }
553+ p++;
554+ }
555+ return image;
556+}
557+
558+static XcursorImages *
559+XcursorXcFileLoadImages (XcursorFile *file, int size)
560+{
561+ XcursorFileHeader *fileHeader;
562+ XcursorDim bestSize;
563+ int nsize;
564+ XcursorImages *images;
565+ int n;
566+ int toc;
567+
568+ if (!file || size < 0)
569+ return NULL;
570+ fileHeader = _XcursorReadFileHeader (file);
571+ if (!fileHeader)
572+ return NULL;
573+ bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize);
574+ if (!bestSize)
575+ {
576+ _XcursorFileHeaderDestroy (fileHeader);
577+ return NULL;
578+ }
579+ images = XcursorImagesCreate (nsize);
580+ if (!images)
581+ {
582+ _XcursorFileHeaderDestroy (fileHeader);
583+ return NULL;
584+ }
585+ for (n = 0; n < nsize; n++)
586+ {
587+ toc = _XcursorFindImageToc (fileHeader, bestSize, n);
588+ if (toc < 0)
589+ break;
590+ images->images[images->nimage] = _XcursorReadImage (file, fileHeader,
591+ toc);
592+ if (!images->images[images->nimage])
593+ break;
594+ images->nimage++;
595+ }
596+ _XcursorFileHeaderDestroy (fileHeader);
597+ if (images->nimage != nsize)
598+ {
599+ XcursorImagesDestroy (images);
600+ images = NULL;
601+ }
602+ return images;
603+}
604+
605+static int
606+_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len)
607+{
608+ FILE *f = file->closure;
609+ return fread (buf, 1, len, f);
610+}
611+
612+static int
613+_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len)
614+{
615+ FILE *f = file->closure;
616+ return fwrite (buf, 1, len, f);
617+}
618+
619+static int
620+_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence)
621+{
622+ FILE *f = file->closure;
623+ return fseek (f, offset, whence);
624+}
625+
626+static void
627+_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file)
628+{
629+ file->closure = stdfile;
630+ file->read = _XcursorStdioFileRead;
631+ file->write = _XcursorStdioFileWrite;
632+ file->seek = _XcursorStdioFileSeek;
633+}
634+
635+static XcursorImages *
636+XcursorFileLoadImages (FILE *file, int size)
637+{
638+ XcursorFile f;
639+
640+ if (!file)
641+ return NULL;
642+
643+ _XcursorStdioFileInitialize (file, &f);
644+ return XcursorXcFileLoadImages (&f, size);
645+}
646+
647+/*
648+ * From libXcursor/src/library.c
649+ */
650+
651+#ifndef ICONDIR
652+#define ICONDIR "/usr/X11R6/lib/X11/icons"
653+#endif
654+
655+#ifndef XCURSORPATH
656+#define XCURSORPATH "~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:"ICONDIR
657+#endif
658+
659+static const char *
660+XcursorLibraryPath (void)
661+{
662+ static const char *path;
663+
664+ if (!path)
665+ {
666+ path = getenv ("XCURSOR_PATH");
667+ if (!path)
668+ path = XCURSORPATH;
669+ }
670+ return path;
671+}
672+
673+static void
674+_XcursorAddPathElt (char *path, const char *elt, int len)
675+{
676+ int pathlen = strlen (path);
677+
678+ /* append / if the path doesn't currently have one */
679+ if (path[0] == '\0' || path[pathlen - 1] != '/')
680+ {
681+ strcat (path, "/");
682+ pathlen++;
683+ }
684+ if (len == -1)
685+ len = strlen (elt);
686+ /* strip leading slashes */
687+ while (len && elt[0] == '/')
688+ {
689+ elt++;
690+ len--;
691+ }
692+ strncpy (path + pathlen, elt, len);
693+ path[pathlen + len] = '\0';
694+}
695+
696+static char *
697+_XcursorBuildThemeDir (const char *dir, const char *theme)
698+{
699+ const char *colon;
700+ const char *tcolon;
701+ char *full;
702+ char *home;
703+ int dirlen;
704+ int homelen;
705+ int themelen;
706+ int len;
707+
708+ if (!dir || !theme)
709+ return NULL;
710+
711+ colon = strchr (dir, ':');
712+ if (!colon)
713+ colon = dir + strlen (dir);
714+
715+ dirlen = colon - dir;
716+
717+ tcolon = strchr (theme, ':');
718+ if (!tcolon)
719+ tcolon = theme + strlen (theme);
720+
721+ themelen = tcolon - theme;
722+
723+ home = NULL;
724+ homelen = 0;
725+ if (*dir == '~')
726+ {
727+ home = getenv ("HOME");
728+ if (!home)
729+ return NULL;
730+ homelen = strlen (home);
731+ dir++;
732+ dirlen--;
733+ }
734+
735+ /*
736+ * add space for any needed directory separators, one per component,
737+ * and one for the trailing null
738+ */
739+ len = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
740+
741+ full = malloc (len);
742+ if (!full)
743+ return NULL;
744+ full[0] = '\0';
745+
746+ if (home)
747+ _XcursorAddPathElt (full, home, -1);
748+ _XcursorAddPathElt (full, dir, dirlen);
749+ _XcursorAddPathElt (full, theme, themelen);
750+ return full;
751+}
752+
753+static char *
754+_XcursorBuildFullname (const char *dir, const char *subdir, const char *file)
755+{
756+ char *full;
757+
758+ if (!dir || !subdir || !file)
759+ return NULL;
760+
761+ full = malloc (strlen (dir) + 1 + strlen (subdir) + 1 + strlen (file) + 1);
762+ if (!full)
763+ return NULL;
764+ full[0] = '\0';
765+ _XcursorAddPathElt (full, dir, -1);
766+ _XcursorAddPathElt (full, subdir, -1);
767+ _XcursorAddPathElt (full, file, -1);
768+ return full;
769+}
770+
771+static const char *
772+_XcursorNextPath (const char *path)
773+{
774+ char *colon = strchr (path, ':');
775+
776+ if (!colon)
777+ return NULL;
778+ return colon + 1;
779+}
780+
781+#define XcursorWhite(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
782+#define XcursorSep(c) ((c) == ';' || (c) == ',')
783+
784+static char *
785+_XcursorThemeInherits (const char *full)
786+{
787+ char line[8192];
788+ char *result = NULL;
789+ FILE *f;
790+
791+ if (!full)
792+ return NULL;
793+
794+ f = fopen (full, "r");
795+ if (f)
796+ {
797+ while (fgets (line, sizeof (line), f))
798+ {
799+ if (!strncmp (line, "Inherits", 8))
800+ {
801+ char *l = line + 8;
802+ char *r;
803+ while (*l == ' ') l++;
804+ if (*l != '=') continue;
805+ l++;
806+ while (*l == ' ') l++;
807+ result = malloc (strlen (l) + 1);
808+ if (result)
809+ {
810+ r = result;
811+ while (*l)
812+ {
813+ while (XcursorSep(*l) || XcursorWhite (*l)) l++;
814+ if (!*l)
815+ break;
816+ if (r != result)
817+ *r++ = ':';
818+ while (*l && !XcursorWhite(*l) &&
819+ !XcursorSep(*l))
820+ *r++ = *l++;
821+ }
822+ *r++ = '\0';
823+ }
824+ break;
825+ }
826+ }
827+ fclose (f);
828+ }
829+ return result;
830+}
831+
832+static FILE *
833+XcursorScanTheme (const char *theme, const char *name)
834+{
835+ FILE *f = NULL;
836+ char *full;
837+ char *dir;
838+ const char *path;
839+ char *inherits = NULL;
840+ const char *i;
841+
842+ if (!theme || !name)
843+ return NULL;
844+
845+ /*
846+ * Scan this theme
847+ */
848+ for (path = XcursorLibraryPath ();
849+ path && f == NULL;
850+ path = _XcursorNextPath (path))
851+ {
852+ dir = _XcursorBuildThemeDir (path, theme);
853+ if (dir)
854+ {
855+ full = _XcursorBuildFullname (dir, "cursors", name);
856+ if (full)
857+ {
858+ f = fopen (full, "r");
859+ free (full);
860+ }
861+ if (!f && !inherits)
862+ {
863+ full = _XcursorBuildFullname (dir, "", "index.theme");
864+ if (full)
865+ {
866+ inherits = _XcursorThemeInherits (full);
867+ free (full);
868+ }
869+ }
870+ free (dir);
871+ }
872+ }
873+ /*
874+ * Recurse to scan inherited themes
875+ */
876+ for (i = inherits; i && f == NULL; i = _XcursorNextPath (i))
877+ f = XcursorScanTheme (i, name);
878+ if (inherits != NULL)
879+ free (inherits);
880+ return f;
881+}
882+
883+XcursorImages *
884+XcursorLibraryLoadImages (const char *file, const char *theme, int size)
885+{
886+ FILE *f = NULL;
887+ XcursorImages *images = NULL;
888+
889+ if (!file)
890+ return NULL;
891+
892+ if (theme)
893+ f = XcursorScanTheme (theme, file);
894+ if (!f)
895+ f = XcursorScanTheme ("default", file);
896+ if (f)
897+ {
898+ images = XcursorFileLoadImages (f, size);
899+ if (images)
900+ XcursorImagesSetName (images, file);
901+ fclose (f);
902+ }
903+ return images;
904+}
905+
906+static void
907+load_all_cursors_from_dir(const char *path, int size,
908+ void (*load_callback)(XcursorImages *, void *),
909+ void *user_data)
910+{
911+ FILE *f;
912+ DIR *dir = opendir(path);
913+ struct dirent *ent;
914+ char *full;
915+ XcursorImages *images;
916+
917+ if (!dir)
918+ return;
919+
920+ for(ent = readdir(dir); ent; ent = readdir(dir)) {
921+#ifdef _DIRENT_HAVE_D_TYPE
922+ if (ent->d_type != DT_UNKNOWN &&
923+ (ent->d_type != DT_REG && ent->d_type != DT_LNK))
924+ continue;
925+#endif
926+
927+ full = _XcursorBuildFullname(path, "", ent->d_name);
928+ if (!full)
929+ continue;
930+
931+ f = fopen(full, "r");
932+ if (!f) {
933+ free(full);
934+ continue;
935+ }
936+
937+ images = XcursorFileLoadImages(f, size);
938+
939+ if (images) {
940+ XcursorImagesSetName(images, ent->d_name);
941+ load_callback(images, user_data);
942+ }
943+
944+ fclose (f);
945+ free(full);
946+ }
947+
948+ closedir(dir);
949+}
950+
951+/** Load all the cursor of a theme
952+ *
953+ * This function loads all the cursor images of a given theme and its
954+ * inherited themes. Each cursor is loaded into an XcursorImages object
955+ * which is passed to the caller's load callback. If a cursor appears
956+ * more than once across all the inherited themes, the load callback
957+ * will be called multiple times, with possibly different XcursorImages
958+ * object which have the same name. The user is expected to destroy the
959+ * XcursorImages objects passed to the callback with
960+ * XcursorImagesDestroy().
961+ *
962+ * \param theme The name of theme that should be loaded
963+ * \param size The desired size of the cursor images
964+ * \param load_callback A callback function that will be called
965+ * for each cursor loaded. The first parameter is the XcursorImages
966+ * object representing the loaded cursor and the second is a pointer
967+ * to data provided by the user.
968+ * \param user_data The data that should be passed to the load callback
969+ */
970+void
971+xcursor_load_theme(const char *theme, int size,
972+ void (*load_callback)(XcursorImages *, void *),
973+ void *user_data)
974+{
975+ char *full, *dir;
976+ char *inherits = NULL;
977+ const char *path, *i;
978+
979+ if (!theme)
980+ theme = "default";
981+
982+ for (path = XcursorLibraryPath();
983+ path;
984+ path = _XcursorNextPath(path)) {
985+ dir = _XcursorBuildThemeDir(path, theme);
986+ if (!dir)
987+ continue;
988+
989+ full = _XcursorBuildFullname(dir, "cursors", "");
990+
991+ if (full) {
992+ load_all_cursors_from_dir(full, size, load_callback,
993+ user_data);
994+ free(full);
995+ }
996+
997+ if (!inherits) {
998+ full = _XcursorBuildFullname(dir, "", "index.theme");
999+ if (full) {
1000+ inherits = _XcursorThemeInherits(full);
1001+ free(full);
1002+ }
1003+ }
1004+
1005+ free(dir);
1006+ }
1007+
1008+ for (i = inherits; i; i = _XcursorNextPath(i))
1009+ xcursor_load_theme(i, size, load_callback, user_data);
1010+
1011+ if (inherits)
1012+ free(inherits);
1013+}
1014
1015=== added file '3rd_party/xcursor/xcursor.h'
1016--- 3rd_party/xcursor/xcursor.h 1970-01-01 00:00:00 +0000
1017+++ 3rd_party/xcursor/xcursor.h 2014-07-11 20:27:44 +0000
1018@@ -0,0 +1,65 @@
1019+/*
1020+ * Copyright © 2002 Keith Packard
1021+ *
1022+ * Permission to use, copy, modify, distribute, and sell this software and its
1023+ * documentation for any purpose is hereby granted without fee, provided that
1024+ * the above copyright notice appear in all copies and that both that
1025+ * copyright notice and this permission notice appear in supporting
1026+ * documentation, and that the name of Keith Packard not be used in
1027+ * advertising or publicity pertaining to distribution of the software without
1028+ * specific, written prior permission. Keith Packard makes no
1029+ * representations about the suitability of this software for any purpose. It
1030+ * is provided "as is" without express or implied warranty.
1031+ *
1032+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1033+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1034+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1035+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1036+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1037+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1038+ * PERFORMANCE OF THIS SOFTWARE.
1039+ */
1040+
1041+#ifndef XCURSOR_H
1042+#define XCURSOR_H
1043+
1044+#include <stdint.h>
1045+
1046+
1047+typedef int XcursorBool;
1048+typedef uint32_t XcursorUInt;
1049+
1050+typedef XcursorUInt XcursorDim;
1051+typedef XcursorUInt XcursorPixel;
1052+
1053+typedef struct _XcursorImage {
1054+ XcursorUInt version; /* version of the image data */
1055+ XcursorDim size; /* nominal size for matching */
1056+ XcursorDim width; /* actual width */
1057+ XcursorDim height; /* actual height */
1058+ XcursorDim xhot; /* hot spot x (must be inside image) */
1059+ XcursorDim yhot; /* hot spot y (must be inside image) */
1060+ XcursorUInt delay; /* animation delay to next frame (ms) */
1061+ XcursorPixel *pixels; /* pointer to pixels */
1062+} XcursorImage;
1063+
1064+/*
1065+ * Other data structures exposed by the library API
1066+ */
1067+typedef struct _XcursorImages {
1068+ int nimage; /* number of images */
1069+ XcursorImage **images; /* array of XcursorImage pointers */
1070+ char *name; /* name used to load images */
1071+} XcursorImages;
1072+
1073+XcursorImages *
1074+XcursorLibraryLoadImages (const char *file, const char *theme, int size);
1075+
1076+void
1077+XcursorImagesDestroy (XcursorImages *images);
1078+
1079+void
1080+xcursor_load_theme(const char *theme, int size,
1081+ void (*load_callback)(XcursorImages *, void *),
1082+ void *user_data);
1083+#endif
1084
1085=== modified file 'CMakeLists.txt'
1086--- CMakeLists.txt 2014-06-25 07:27:23 +0000
1087+++ CMakeLists.txt 2014-07-11 20:27:44 +0000
1088@@ -27,7 +27,7 @@
1089 set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
1090
1091 set(MIR_VERSION_MAJOR 0)
1092-set(MIR_VERSION_MINOR 4) # This should change at least with every MIRSERVER_ABI
1093+set(MIR_VERSION_MINOR 5) # This should change at least with every MIRSERVER_ABI
1094 set(MIR_VERSION_PATCH 0)
1095
1096 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
1097@@ -47,15 +47,21 @@
1098 include (cmake/PrePush.cmake)
1099 include (GNUInstallDirs)
1100
1101+set(build_types "None;Debug;Release;RelWithDebInfo;MinSizeRel;Coverage;AddressSanitizer")
1102+# Change informational string for CMAKE_BUILD_TYPE
1103+set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "${build_types}" FORCE)
1104+# Enable cmake-gui to display a drop down list for CMAKE_BUILD_TYPE
1105+set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${build_types}")
1106+
1107 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread -g -Werror -Wall -pedantic -Wextra -fPIC")
1108 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -g -std=c++0x -Werror -Wall -fno-strict-aliasing -pedantic -Wnon-virtual-dtor -Wextra -fPIC")
1109-set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
1110-set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
1111
1112 if ("${CMAKE_CXX_COMPILER}" MATCHES "clang")
1113 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage -Wno-mismatched-tags")
1114 endif()
1115
1116+string(TOLOWER "${CMAKE_BUILD_TYPE}" cmake_build_type_lower)
1117+
1118 #####################################################################
1119 # Enable code coverage calculation with gcov/gcovr/lcov
1120 # Usage:
1121@@ -64,12 +70,23 @@
1122 # * Find html report in subdir coveragereport
1123 # * Find xml report feasible for jenkins in coverage.xml
1124 #####################################################################
1125-IF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE])
1126- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs" )
1127- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs" )
1128- SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs" )
1129- SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs" )
1130-ENDIF(CMAKE_BUILD_TYPE MATCHES [cC][oO][vV][eE][rR][aA][gG][eE])
1131+if(cmake_build_type_lower MATCHES "coverage")
1132+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
1133+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs")
1134+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
1135+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -ftest-coverage -fprofile-arcs")
1136+endif()
1137+
1138+if(cmake_build_type_lower MATCHES "addresssanitizer")
1139+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
1140+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
1141+ set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fsanitize=address")
1142+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
1143+else()
1144+ # AddressSanitizer builds fail if we disallow undefined symbols
1145+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
1146+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined")
1147+endif()
1148
1149 enable_testing()
1150
1151@@ -141,6 +158,7 @@
1152
1153 set(MIR_ANDROID_INCLUDE_DIRECTORIES) # to be filled by android-input
1154 set(MIR_ANDROID_INPUT_COMPILE_FLAGS) # to be filled by android-input
1155+set(MIR_XCURSOR_INCLUDE_DIRECTORIES)
1156 set(MIR_3RD_PARTY_INCLUDE_DIRECTORIES)
1157 add_subdirectory(3rd_party/)
1158
1159
1160=== modified file 'debian/changelog'
1161--- debian/changelog 2014-07-01 15:54:36 +0000
1162+++ debian/changelog 2014-07-11 20:27:44 +0000
1163@@ -1,3 +1,9 @@
1164+mir (0.5.0-0ubuntu1) UNRELEASED; urgency=medium
1165+
1166+ * Under development
1167+
1168+ -- Daniel van Vugt <daniel.van.vugt@canonical.com> Fri, 04 Jul 2014 12:45:30 +0800
1169+
1170 mir (0.4.0+14.10.20140701.1-0ubuntu1) utopic; urgency=medium
1171
1172 * New upstream release 0.4.0 (https://launchpad.net/mir/+milestone/0.4.0)
1173@@ -5,7 +11,6 @@
1174 . Add surface attribute for visibility.
1175 . Add surface orientation API.
1176 - mirserver ABI bumped to 22. Shells need rebuilding.
1177- . Allow setting the orientation of a server surface.
1178 . Change compositor::Scene to expose compositor::SceneElements instead
1179 of graphics::Renderables.
1180 . Change various input and Surface classes to support the client cursor
1181@@ -16,18 +21,29 @@
1182 mg::Renderables.
1183 . Add visibility tracking to mc::SceneElement interface and
1184 implementations.
1185- . Unregister FD Handler from EventHandlerRegister.
1186- . Sending user input events through Surfaces.
1187 . Move InputChannelFactory into DefaultServerConfiguration.
1188- . Ensure default input region is updated when surface is resized. (LP: #1332632)
1189- - android: support alpha blending overlays together in HWC. Bumps
1190- android-headers version requirement from 4.2.2 to 4.4.2. (LP: #1329879)
1191- - android: designate the buffer usage when attempting to access or
1192- update the fence associated with the native buffer. (LP: #1329868)
1193+ - Unregister FD Handler from EventHandlerRegister.
1194+ - Sending user input events through Surfaces.
1195+ - Allow setting the orientation of a server surface.
1196 - Enable client cursor API.
1197 - Enable support for USB touchscreens.
1198 - Various test improvements.
1199- - Ensure the_cursor() is not null. (LP: #1334010)
1200+ - Bugs fixed:
1201+ . can't display toolbar after dismissing it (LP: #1332632)
1202+ . [regression] demo client connection crashes the server (LP: #1334010)
1203+ . demo server locks up in certain scenarios with --disable-overlays
1204+ false when starting/stopping second clients (LP: #1329868)
1205+ . MultiThreadedCompositor deadlocks (LP: #1335311)
1206+ . Intermittent memory error in
1207+ ClientSurfaceEvents.client_can_query_current_orientation (LP: #1335819)
1208+ . Intermittent hang & fail in mir_acceptance_tests.TestClientCursorAPI.*
1209+ (LP: #1332011)
1210+ . MirClientSurfaceTests tests leak fds and eventually hang when ran
1211+ repeatedly (LP: #1333673)
1212+ . [testfail] Intermittent "Invalid read" in MirSurfaceSwapBuffersTest.
1213+ swap_buffers_does_not_block_when_surface_is_not_composited
1214+ (LP: #1334287)
1215+ . android: support alpha blending during hwc overlay (LP: #1329879)
1216
1217 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 01 Jul 2014 15:54:36 +0000
1218
1219
1220=== modified file 'debian/control'
1221--- debian/control 2014-06-27 06:10:24 +0000
1222+++ debian/control 2014-07-11 20:27:44 +0000
1223@@ -10,6 +10,10 @@
1224 doxygen,
1225 xsltproc,
1226 graphviz,
1227+# We rely on C++11 features, and to prevent from ABI breaks
1228+# in libstdc++ causing us issues, we explicitly select a G++
1229+# version.
1230+ g++-4.9,
1231 libboost-dev,
1232 libboost-chrono-dev,
1233 libboost-date-time-dev,
1234
1235=== modified file 'debian/rules'
1236--- debian/rules 2014-04-15 17:11:14 +0000
1237+++ debian/rules 2014-07-11 20:27:44 +0000
1238@@ -6,6 +6,13 @@
1239
1240 export DPKG_GENSYMBOLS_CHECK_LEVEL = 4
1241
1242+include /usr/share/dpkg/default.mk
1243+
1244+# Explicitly selecting a G{CC,++}-version here to avoid accidental
1245+# ABI breaks introduced by toolchain updates.
1246+export CC=$(DEB_HOST_GNU_TYPE)-gcc-4.9
1247+export CXX=$(DEB_HOST_GNU_TYPE)-g++-4.9
1248+
1249 %:
1250 dh $@ --parallel --fail-missing
1251
1252
1253=== modified file 'examples/eglcounter.cpp'
1254--- examples/eglcounter.cpp 2014-06-05 21:28:43 +0000
1255+++ examples/eglcounter.cpp 2014-07-11 20:27:44 +0000
1256@@ -201,7 +201,7 @@
1257 };
1258
1259 /* Colours from http://design.ubuntu.com/brand/colour-palette */
1260-#define MID_AUBERGINE(x) x*0.368627451f, x*0.152941176f, x*0.31372549f
1261+#define MID_AUBERGINE(x) (x)*0.368627451f, (x)*0.152941176f, (x)*0.31372549f
1262 #define ORANGE 0.866666667f, 0.282352941f, 0.141414141f
1263
1264 int main(int argc, char *argv[])
1265
1266=== modified file 'examples/egltriangle.c'
1267--- examples/egltriangle.c 2014-06-09 17:16:32 +0000
1268+++ examples/egltriangle.c 2014-07-11 20:27:44 +0000
1269@@ -44,7 +44,7 @@
1270 }
1271
1272 /* Colours from http://design.ubuntu.com/brand/colour-palette */
1273-#define MID_AUBERGINE(x) x*0.368627451f, x*0.152941176f, x*0.31372549f
1274+#define MID_AUBERGINE(x) (x)*0.368627451f, (x)*0.152941176f, (x)*0.31372549f
1275 #define ORANGE 0.866666667f, 0.282352941f, 0.141414141f
1276
1277 int main(int argc, char *argv[])
1278
1279=== modified file 'examples/minimal_server.cpp'
1280--- examples/minimal_server.cpp 2014-04-30 07:05:40 +0000
1281+++ examples/minimal_server.cpp 2014-07-11 20:27:44 +0000
1282@@ -17,12 +17,20 @@
1283 */
1284
1285 #include "mir/default_server_configuration.h"
1286+#include "mir/report_exception.h"
1287 #include "mir/run_mir.h"
1288
1289+#include <iostream>
1290+
1291 int main(int argc, char const* argv[])
1292+try
1293 {
1294 mir::DefaultServerConfiguration config(argc, argv);
1295 run_mir(config, [](mir::DisplayServer&){} );
1296 return 0;
1297 }
1298-
1299+catch (...)
1300+{
1301+ mir::report_exception(std::cerr);
1302+ return 1;
1303+}
1304
1305=== modified file 'examples/multiwin.c'
1306--- examples/multiwin.c 2014-03-06 06:05:17 +0000
1307+++ examples/multiwin.c 2014-07-11 20:27:44 +0000
1308@@ -44,6 +44,13 @@
1309 }
1310 }
1311
1312+static void premultiply_alpha(Color *c)
1313+{
1314+ c->r = (unsigned)c->r * c->a / 255U;
1315+ c->g = (unsigned)c->g * c->a / 255U;
1316+ c->b = (unsigned)c->b * c->a / 255U;
1317+}
1318+
1319 static void put_pixels(void *where, int count, MirPixelFormat format,
1320 const Color *color)
1321 {
1322@@ -187,6 +194,7 @@
1323 win[0].fill.g = 0x00;
1324 win[0].fill.b = 0x00;
1325 win[0].fill.a = 0x50;
1326+ premultiply_alpha(&win[0].fill);
1327
1328 parm.name = "green";
1329 parm.width = 300;
1330@@ -196,6 +204,7 @@
1331 win[1].fill.g = 0xff;
1332 win[1].fill.b = 0x00;
1333 win[1].fill.a = 0x50;
1334+ premultiply_alpha(&win[1].fill);
1335
1336 parm.name = "blue";
1337 parm.width = 150;
1338@@ -205,6 +214,7 @@
1339 win[2].fill.g = 0x00;
1340 win[2].fill.b = 0xff;
1341 win[2].fill.a = 0x50;
1342+ premultiply_alpha(&win[2].fill);
1343
1344 signal(SIGINT, shutdown);
1345 signal(SIGTERM, shutdown);
1346
1347=== modified file 'include/client/mir_toolkit/mir_prompt_session.h'
1348--- include/client/mir_toolkit/mir_prompt_session.h 2014-06-13 10:02:22 +0000
1349+++ include/client/mir_toolkit/mir_prompt_session.h 2014-07-11 20:27:44 +0000
1350@@ -79,6 +79,23 @@
1351 */
1352 void mir_prompt_session_release_sync(MirPromptSession *prompt_session);
1353
1354+/**
1355+ * Test for a valid prompt session
1356+ * \param [in] prompt_session The prompt session
1357+ * \return True if prompt_session is valid, false otherwise
1358+ */
1359+MirBool mir_prompt_session_is_valid(MirPromptSession *prompt_session);
1360+
1361+/**
1362+ * Retrieve a text description of the last error. The returned string is owned
1363+ * by the library and remains valid until the prompt session has been released.
1364+ * \param [in] prompt_session The prompt session
1365+ * \return A text description of any error resulting in an
1366+ * invalid connection, or the empty string "" if the
1367+ * connection is valid.
1368+ */
1369+char const *mir_prompt_session_error_message(MirPromptSession *prompt_session);
1370+
1371 #ifdef __cplusplus
1372 }
1373 /**@}*/
1374
1375=== modified file 'include/platform/mir/graphics/cursor_image.h'
1376--- include/platform/mir/graphics/cursor_image.h 2014-04-28 23:15:05 +0000
1377+++ include/platform/mir/graphics/cursor_image.h 2014-07-11 20:27:44 +0000
1378@@ -21,6 +21,7 @@
1379 #define MIR_GRAPHICS_CURSOR_IMAGE_H_
1380
1381 #include "mir/geometry/size.h"
1382+#include "mir/geometry/displacement.h"
1383
1384 namespace mir
1385 {
1386@@ -33,6 +34,12 @@
1387
1388 virtual void const* as_argb_8888() const = 0;
1389 virtual geometry::Size size() const = 0;
1390+
1391+ // We use "hotspot" to mean the offset within a cursor image
1392+ // which should be placed at the onscreen
1393+ // location of the pointer.
1394+ virtual geometry::Displacement hotspot() const = 0;
1395+
1396
1397 protected:
1398 CursorImage() = default;
1399
1400=== modified file 'include/platform/mir/options/configuration.h'
1401--- include/platform/mir/options/configuration.h 2014-03-26 05:48:59 +0000
1402+++ include/platform/mir/options/configuration.h 2014-07-11 20:27:44 +0000
1403@@ -28,6 +28,7 @@
1404 namespace options
1405 {
1406 extern char const* const server_socket_opt;
1407+extern char const* const prompt_socket_opt;
1408 extern char const* const no_server_socket_opt;
1409 extern char const* const enable_input_opt;
1410 extern char const* const session_mediator_report_opt;
1411
1412=== modified file 'include/server/mir/default_server_configuration.h'
1413--- include/server/mir/default_server_configuration.h 2014-06-23 17:40:57 +0000
1414+++ include/server/mir/default_server_configuration.h 2014-07-11 20:27:44 +0000
1415@@ -98,6 +98,7 @@
1416 }
1417 namespace graphics
1418 {
1419+class NativePlatform;
1420 class Platform;
1421 class Display;
1422 class BufferInitializer;
1423@@ -105,7 +106,6 @@
1424 class GraphicBufferAllocator;
1425 class Cursor;
1426 class CursorImage;
1427-class CursorImages;
1428 class GLConfig;
1429 class GLProgramFactory;
1430 namespace nested { class HostConnection; }
1431@@ -124,6 +124,7 @@
1432 class InputSendObserver;
1433 class NestedInputRelay;
1434 class EventHandler;
1435+class CursorImages;
1436 namespace android
1437 {
1438 class InputRegistrar;
1439@@ -157,6 +158,7 @@
1440 * dependencies of DisplayServer on the rest of the Mir
1441 * @{ */
1442 virtual std::shared_ptr<frontend::Connector> the_connector();
1443+ virtual std::shared_ptr<frontend::Connector> the_prompt_connector();
1444 virtual std::shared_ptr<graphics::Display> the_display();
1445 virtual std::shared_ptr<compositor::Compositor> the_compositor();
1446 virtual std::shared_ptr<input::InputManager> the_input_manager();
1447@@ -164,6 +166,7 @@
1448 virtual std::shared_ptr<ServerStatusListener> the_server_status_listener();
1449 virtual std::shared_ptr<DisplayChanger> the_display_changer();
1450 virtual std::shared_ptr<graphics::Platform> the_graphics_platform();
1451+ virtual std::shared_ptr<graphics::NativePlatform> the_graphics_native_platform();
1452 virtual std::shared_ptr<input::InputConfiguration> the_input_configuration();
1453 virtual std::shared_ptr<input::InputDispatcher> the_input_dispatcher();
1454 virtual std::shared_ptr<input::InputSender> the_input_sender();
1455@@ -187,7 +190,7 @@
1456 virtual std::shared_ptr<graphics::DisplayReport> the_display_report();
1457 virtual std::shared_ptr<graphics::Cursor> the_cursor();
1458 virtual std::shared_ptr<graphics::CursorImage> the_default_cursor_image();
1459- virtual std::shared_ptr<graphics::CursorImages> the_cursor_images();
1460+ virtual std::shared_ptr<input::CursorImages> the_cursor_images();
1461
1462 /** @} */
1463
1464@@ -222,6 +225,7 @@
1465 * internal dependencies of frontend
1466 * @{ */
1467 virtual std::shared_ptr<frontend::ConnectionCreator> the_connection_creator();
1468+ virtual std::shared_ptr<frontend::ConnectionCreator> the_prompt_connection_creator();
1469 virtual std::shared_ptr<frontend::ConnectorReport> the_connector_report();
1470 /** @} */
1471 /** @} */
1472@@ -290,6 +294,12 @@
1473 virtual std::shared_ptr<graphics::GLProgramFactory> the_gl_program_factory();
1474 virtual std::shared_ptr<input::InputChannelFactory> the_input_channel_factory();
1475 virtual std::shared_ptr<scene::MediatingDisplayChanger> the_mediating_display_changer();
1476+ virtual std::shared_ptr<frontend::ProtobufIpcFactory> new_ipc_factory(
1477+ std::shared_ptr<frontend::SessionAuthorizer> const& session_authorizer);
1478+
1479+ // TODO Remove after 0.5.0 is branched: the_ipc_factory() is used by
1480+ // TODO clients that use the "PrivateProtobuf" but is it now deprecated
1481+ // TODO and only retained as a migration aid.
1482 virtual std::shared_ptr<frontend::ProtobufIpcFactory> the_ipc_factory(
1483 std::shared_ptr<frontend::Shell> const& shell,
1484 std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator);
1485@@ -318,6 +328,7 @@
1486 CachedPtr<droidinput::InputDispatcherPolicyInterface> android_dispatcher_policy;
1487
1488 CachedPtr<frontend::Connector> connector;
1489+ CachedPtr<frontend::Connector> prompt_connector;
1490
1491 CachedPtr<input::InputConfiguration> input_configuration;
1492
1493@@ -331,20 +342,23 @@
1494 CachedPtr<shell::InputTargeter> input_targeter;
1495 CachedPtr<input::CursorListener> cursor_listener;
1496 CachedPtr<graphics::Platform> graphics_platform;
1497+ CachedPtr<graphics::NativePlatform> graphics_native_platform;
1498 CachedPtr<graphics::BufferInitializer> buffer_initializer;
1499 CachedPtr<graphics::GraphicBufferAllocator> buffer_allocator;
1500 CachedPtr<graphics::Display> display;
1501 CachedPtr<graphics::Cursor> cursor;
1502 CachedPtr<graphics::CursorImage> default_cursor_image;
1503- CachedPtr<graphics::CursorImages> cursor_images;
1504+ CachedPtr<input::CursorImages> cursor_images;
1505
1506 CachedPtr<frontend::ConnectorReport> connector_report;
1507+ // TODO remove after 0.5.0 is branched - c.f. the_ipc_factory()
1508 CachedPtr<frontend::ProtobufIpcFactory> ipc_factory;
1509 CachedPtr<frontend::SessionMediatorReport> session_mediator_report;
1510 CachedPtr<frontend::MessageProcessorReport> message_processor_report;
1511 CachedPtr<frontend::SessionAuthorizer> session_authorizer;
1512 CachedPtr<frontend::EventSink> global_event_sink;
1513 CachedPtr<frontend::ConnectionCreator> connection_creator;
1514+ CachedPtr<frontend::ConnectionCreator> prompt_connection_creator;
1515 CachedPtr<frontend::Screencast> screencast;
1516 CachedPtr<compositor::RendererFactory> renderer_factory;
1517 CachedPtr<compositor::BufferStreamFactory> buffer_stream_factory;
1518@@ -367,7 +381,8 @@
1519 CachedPtr<compositor::CompositorReport> compositor_report;
1520 CachedPtr<logging::Logger> logger;
1521 CachedPtr<graphics::DisplayReport> display_report;
1522- CachedPtr<time::Clock> clock;
1523+ // static to workaround the singleton clock in AsioMainLoop when running multiple servers
1524+ static CachedPtr<time::Clock> clock;
1525 CachedPtr<MainLoop> main_loop;
1526 CachedPtr<ServerStatusListener> server_status_listener;
1527 CachedPtr<graphics::DisplayConfigurationPolicy> display_configuration_policy;
1528
1529=== modified file 'include/server/mir/frontend/fd_sets.h'
1530--- include/server/mir/frontend/fd_sets.h 2014-03-06 06:05:17 +0000
1531+++ include/server/mir/frontend/fd_sets.h 2014-07-11 20:27:44 +0000
1532@@ -20,7 +20,7 @@
1533
1534 #include <vector>
1535 #include <initializer_list>
1536-#include <stdint.h>
1537+#include "mir/fd.h"
1538
1539 namespace mir
1540 {
1541@@ -28,7 +28,7 @@
1542 {
1543 namespace detail
1544 {
1545-typedef std::initializer_list<std::vector<int32_t>> FdSets;
1546+typedef std::initializer_list<std::vector<Fd>> FdSets;
1547 }
1548 }
1549 } // namespace mir
1550
1551=== modified file 'include/server/mir/frontend/session_authorizer.h'
1552--- include/server/mir/frontend/session_authorizer.h 2014-06-02 17:07:02 +0000
1553+++ include/server/mir/frontend/session_authorizer.h 2014-07-11 20:27:44 +0000
1554@@ -36,6 +36,7 @@
1555 virtual bool connection_is_allowed(SessionCredentials const& creds) = 0;
1556 virtual bool configure_display_is_allowed(SessionCredentials const& creds) = 0;
1557 virtual bool screencast_is_allowed(SessionCredentials const& creds) = 0;
1558+ virtual bool prompt_session_is_allowed(SessionCredentials const& creds) = 0;
1559
1560 protected:
1561 SessionAuthorizer() = default;
1562
1563=== renamed file 'include/server/mir/graphics/cursor_images.h' => 'include/server/mir/input/cursor_images.h'
1564--- include/server/mir/graphics/cursor_images.h 2014-05-13 20:07:20 +0000
1565+++ include/server/mir/input/cursor_images.h 2014-07-11 20:27:44 +0000
1566@@ -17,8 +17,8 @@
1567 */
1568
1569
1570-#ifndef MIR_GRAPHICS_CURSOR_LOADER_H_
1571-#define MIR_GRAPHICS_CURSOR_LOADER_H_
1572+#ifndef MIR_INPUT_CURSOR_IMAGES_H_
1573+#define MIR_INPUT_CURSOR_IMAGES_H_
1574
1575 #include "mir/geometry/size.h"
1576
1577@@ -30,10 +30,13 @@
1578 namespace graphics
1579 {
1580 class CursorImage;
1581-
1582-geometry::Size const default_cursor_size{geometry::Width{64}, geometry::Height{64}};
1583-
1584-/// CursorImages is used to lookup cursor images.
1585+}
1586+
1587+namespace input
1588+{
1589+/// CursorImages is used to lookup cursor images from the system theme.
1590+geometry::Size const default_cursor_size{geometry::Width{24}, geometry::Height{24}};
1591+
1592 class CursorImages
1593 {
1594 public:
1595@@ -41,7 +44,7 @@
1596
1597 /// Looks up the image for a named cursor. Cursor names
1598 /// follow the XCursor naming conventions.
1599- virtual std::shared_ptr<CursorImage> image(std::string const& cursor_name,
1600+ virtual std::shared_ptr<graphics::CursorImage> image(std::string const& cursor_name,
1601 geometry::Size const& size) = 0;
1602
1603 protected:
1604@@ -52,4 +55,4 @@
1605 }
1606 }
1607
1608-#endif /* MIR_GRAPHICS_CURSOR_LOADER_H_ */
1609+#endif /* MIR_INPUT_CURSOR_IMAGES_H_ */
1610
1611=== modified file 'include/server/mir/server_configuration.h'
1612--- include/server/mir/server_configuration.h 2014-06-24 12:00:29 +0000
1613+++ include/server/mir/server_configuration.h 2014-07-11 20:27:44 +0000
1614@@ -60,6 +60,7 @@
1615 // TODO most of these interfaces are wider DisplayServer needs...
1616 // TODO ...some or all of them need narrowing
1617 virtual std::shared_ptr<frontend::Connector> the_connector() = 0;
1618+ virtual std::shared_ptr<frontend::Connector> the_prompt_connector() = 0;
1619 virtual std::shared_ptr<graphics::Display> the_display() = 0;
1620 virtual std::shared_ptr<compositor::Compositor> the_compositor() = 0;
1621 virtual std::shared_ptr<input::InputManager> the_input_manager() = 0;
1622
1623=== added file 'include/shared/mir/basic_observers.h'
1624--- include/shared/mir/basic_observers.h 1970-01-01 00:00:00 +0000
1625+++ include/shared/mir/basic_observers.h 2014-07-11 20:27:44 +0000
1626@@ -0,0 +1,122 @@
1627+/*
1628+ * Copyright © 2014 Canonical Ltd.
1629+ *
1630+ * This program is free software: you can redistribute it and/or modify it
1631+ * under the terms of the GNU Lesser General Public License version 3,
1632+ * as published by the Free Software Foundation.
1633+ *
1634+ * This program is distributed in the hope that it will be useful,
1635+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1636+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1637+ * GNU Lesser General Public License for more details.
1638+ *
1639+ * You should have received a copy of the GNU Lesser General Public License
1640+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1641+ *
1642+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
1643+ */
1644+
1645+#ifndef MIR_BASIC_OBSERVERS_H_
1646+#define MIR_BASIC_OBSERVERS_H_
1647+
1648+#include "mir/recursive_read_write_mutex.h"
1649+
1650+#include <atomic>
1651+#include <memory>
1652+
1653+namespace mir
1654+{
1655+template<class Observer>
1656+class BasicObservers
1657+{
1658+protected:
1659+ void add(std::shared_ptr<Observer> const& observer);
1660+ void remove(std::shared_ptr<Observer> const& observer);
1661+ void for_each(std::function<void(std::shared_ptr<Observer> const& observer)> const& f);
1662+
1663+private:
1664+ struct ListItem
1665+ {
1666+ ListItem() {}
1667+ RecursiveReadWriteMutex mutex;
1668+ std::shared_ptr<Observer> observer;
1669+ std::atomic<ListItem*> next{nullptr};
1670+
1671+ ~ListItem() { delete next.load(); }
1672+ } head;
1673+};
1674+
1675+template<class Observer>
1676+void BasicObservers<Observer>::for_each(
1677+ std::function<void(std::shared_ptr<Observer> const& observer)> const& f)
1678+{
1679+ ListItem* current_item = &head;
1680+
1681+ while (current_item)
1682+ {
1683+ RecursiveReadLock lock{current_item->mutex};
1684+
1685+ // We need to take a copy in case we recursively remove during call
1686+ if (auto const copy_of_observer = current_item->observer) f(copy_of_observer);
1687+
1688+ current_item = current_item->next;
1689+ }
1690+}
1691+
1692+template<class Observer>
1693+void BasicObservers<Observer>::add(std::shared_ptr<Observer> const& observer)
1694+{
1695+ ListItem* current_item = &head;
1696+
1697+ do
1698+ {
1699+ // Note: we release the read lock to avoid two threads calling add at
1700+ // the same time mutually blocking the other's upgrade to write lock.
1701+ {
1702+ RecursiveReadLock lock{current_item->mutex};
1703+ if (current_item->observer) continue;
1704+ }
1705+
1706+ RecursiveWriteLock lock{current_item->mutex};
1707+
1708+ if (!current_item->observer)
1709+ {
1710+ current_item->observer = observer;
1711+ return;
1712+ }
1713+ }
1714+ while (current_item->next && (current_item = current_item->next));
1715+
1716+ // No empty Items so append a new one
1717+ auto new_item = new ListItem;
1718+ new_item->observer = observer;
1719+
1720+ for (ListItem* expected{nullptr};
1721+ !current_item->next.compare_exchange_weak(expected, new_item);
1722+ expected = nullptr)
1723+ {
1724+ current_item = expected;
1725+ }
1726+}
1727+
1728+template<class Observer>
1729+void BasicObservers<Observer>::remove(std::shared_ptr<Observer> const& observer)
1730+{
1731+ ListItem* current_item = &head;
1732+
1733+ while (current_item)
1734+ {
1735+ RecursiveWriteLock lock{current_item->mutex};
1736+
1737+ if (current_item->observer == observer)
1738+ {
1739+ current_item->observer.reset();
1740+ return;
1741+ }
1742+
1743+ current_item = current_item->next;
1744+ }
1745+}
1746+}
1747+
1748+#endif /* MIR_BASIC_OBSERVERS_H_ */
1749
1750=== added file 'include/shared/mir/fd.h'
1751--- include/shared/mir/fd.h 1970-01-01 00:00:00 +0000
1752+++ include/shared/mir/fd.h 2014-07-11 20:27:44 +0000
1753@@ -0,0 +1,43 @@
1754+/*
1755+ * Copyright © 2014 Canonical Ltd.
1756+ *
1757+ * This program is free software: you can redistribute it and/or modify it
1758+ * under the terms of the GNU Lesser General Public License version 3,
1759+ * as published by the Free Software Foundation.
1760+ *
1761+ * This program is distributed in the hope that it will be useful,
1762+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1763+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1764+ * GNU Lesser General Public License for more details.
1765+ *
1766+ * You should have received a copy of the GNU Lesser General Public License
1767+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1768+ *
1769+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
1770+ */
1771+#ifndef MIR_FD_H_
1772+#define MIR_FD_H_
1773+
1774+namespace mir
1775+{
1776+class Fd
1777+{
1778+public:
1779+ //transfer ownership of the POD-int to the object. The int no longer needs close()ing,
1780+ //and has the lifetime of the Fd object.
1781+ explicit Fd(int&& fd);
1782+ explicit Fd(Fd&&);
1783+ Fd& operator=(Fd&&);
1784+ ~Fd() noexcept;
1785+
1786+ //bit of a convenient kludge. take care not to close or otherwise destroy the FD.
1787+ operator int() const;
1788+
1789+private:
1790+ Fd(Fd const&) = delete;
1791+ Fd& operator=(Fd const&) = delete;
1792+ int fd;
1793+};
1794+} // namespace mir
1795+
1796+#endif // MIR_FD_H_
1797
1798=== modified file 'include/shared/mir/graphics/android/fence.h'
1799--- include/shared/mir/graphics/android/fence.h 2013-10-15 08:53:10 +0000
1800+++ include/shared/mir/graphics/android/fence.h 2014-07-11 20:27:44 +0000
1801@@ -26,6 +26,7 @@
1802 namespace android
1803 {
1804
1805+//TODO: (kdub) remove this type in favor of mir::Fd
1806 typedef int NativeFence;
1807
1808 class Fence
1809@@ -34,7 +35,7 @@
1810 virtual ~Fence() = default;
1811
1812 virtual void wait() = 0;
1813- virtual void merge_with(NativeFence& merge_fd) = 0;
1814+ virtual void merge_with(NativeFence&& merge_fd) = 0;
1815 virtual NativeFence copy_native_handle() const = 0;
1816
1817 protected:
1818
1819=== modified file 'include/shared/mir/graphics/android/sync_fence.h'
1820--- include/shared/mir/graphics/android/sync_fence.h 2013-10-15 08:53:10 +0000
1821+++ include/shared/mir/graphics/android/sync_fence.h 2014-07-11 20:27:44 +0000
1822@@ -19,6 +19,7 @@
1823 #define MIR_GRAPHICS_ANDROID_SYNC_FENCE_H_
1824
1825 #include "mir/graphics/android/fence.h"
1826+#include "mir/fd.h"
1827 #include <memory>
1828
1829 namespace mir
1830@@ -48,18 +49,17 @@
1831 class SyncFence : public Fence
1832 {
1833 public:
1834- SyncFence(std::shared_ptr<SyncFileOps> const&, int fd);
1835- ~SyncFence() noexcept;
1836+ explicit SyncFence(std::shared_ptr<SyncFileOps> const&, Fd&& fd);
1837
1838 void wait();
1839- void merge_with(NativeFence& merge_fd);
1840+ void merge_with(NativeFence&& merge_fd);
1841 NativeFence copy_native_handle() const;
1842
1843 private:
1844 SyncFence(SyncFence const&) = delete;
1845 SyncFence& operator=(SyncFence const&) = delete;
1846
1847- int fence_fd;
1848+ Fd fence_fd;
1849 std::shared_ptr<SyncFileOps> const ops;
1850
1851 int const infinite_timeout = -1;
1852
1853=== added file 'include/shared/mir/recursive_read_write_mutex.h'
1854--- include/shared/mir/recursive_read_write_mutex.h 1970-01-01 00:00:00 +0000
1855+++ include/shared/mir/recursive_read_write_mutex.h 2014-07-11 20:27:44 +0000
1856@@ -0,0 +1,77 @@
1857+/*
1858+ * Copyright © 2014 Canonical Ltd.
1859+ *
1860+ * This program is free software: you can redistribute it and/or modify it
1861+ * under the terms of the GNU Lesser General Public License version 3,
1862+ * as published by the Free Software Foundation.
1863+ *
1864+ * This program is distributed in the hope that it will be useful,
1865+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1866+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1867+ * GNU Lesser General Public License for more details.
1868+ *
1869+ * You should have received a copy of the GNU Lesser General Public License
1870+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1871+ *
1872+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
1873+ */
1874+
1875+#ifndef MIR_RECURSIVE_READ_WRITE_MUTEX_H_
1876+#define MIR_RECURSIVE_READ_WRITE_MUTEX_H_
1877+
1878+#include <condition_variable>
1879+#include <thread>
1880+#include <vector>
1881+
1882+namespace mir
1883+{
1884+/** a recursive read-write mutex.
1885+ * Note that a write lock can be acquired if no other threads have a read lock.
1886+ */
1887+class RecursiveReadWriteMutex
1888+{
1889+public:
1890+ void read_lock();
1891+
1892+ void read_unlock();
1893+
1894+ void write_lock();
1895+
1896+ void write_unlock();
1897+
1898+private:
1899+ std::mutex mutex;
1900+ std::condition_variable cv;
1901+ struct ThreadLockCount
1902+ {
1903+ ThreadLockCount() : id(), count(0) {}
1904+ ThreadLockCount(std::thread::id id, unsigned int count) : id(id), count(count) {}
1905+ std::thread::id id;
1906+ unsigned int count;
1907+ };
1908+ std::vector<ThreadLockCount> read_locking_threads;
1909+ ThreadLockCount write_locking_thread;
1910+};
1911+
1912+class RecursiveReadLock
1913+{
1914+public:
1915+ explicit RecursiveReadLock(RecursiveReadWriteMutex& mutex) : mutex(mutex) { mutex.read_lock(); }
1916+ ~RecursiveReadLock() { mutex.read_unlock(); }
1917+
1918+private:
1919+ RecursiveReadWriteMutex& mutex;
1920+};
1921+
1922+class RecursiveWriteLock
1923+{
1924+public:
1925+ explicit RecursiveWriteLock(RecursiveReadWriteMutex& mutex) : mutex(mutex) { mutex.write_lock(); }
1926+ ~RecursiveWriteLock() { mutex.write_unlock(); }
1927+
1928+private:
1929+ RecursiveReadWriteMutex& mutex;
1930+};
1931+}
1932+
1933+#endif /* MIR_RECURSIVE_READ_WRITE_MUTEX_H_ */
1934
1935=== renamed file 'include/test/mir_test_doubles/mock_android_registrar.h' => 'include/test/mir_test_doubles/mock_buffer_registrar.h'
1936--- include/test/mir_test_doubles/mock_android_registrar.h 2014-03-06 06:05:17 +0000
1937+++ include/test/mir_test_doubles/mock_buffer_registrar.h 2014-07-11 20:27:44 +0000
1938@@ -17,11 +17,11 @@
1939 * Kevin DuBois <kevin.dubois@canonical.com>
1940 */
1941
1942-#ifndef MIR_TEST_DOUBLES_MOCK_ANDROID_REGISTRAR_H_
1943-#define MIR_TEST_DOUBLES_MOCK_ANDROID_REGISTRAR_H_
1944+#ifndef MIR_TEST_DOUBLES_MOCK_BUFFER_REGISTRAR_H_
1945+#define MIR_TEST_DOUBLES_MOCK_BUFFER_REGISTRAR_H_
1946
1947+#include "src/client/android/buffer_registrar.h"
1948 #include <gmock/gmock.h>
1949-#include "src/client/android/android_registrar.h"
1950
1951 namespace mir
1952 {
1953@@ -33,9 +33,9 @@
1954 {
1955 namespace doubles
1956 {
1957-struct MockAndroidRegistrar : public client::android::AndroidRegistrar
1958+struct MockBufferRegistrar : public client::android::BufferRegistrar
1959 {
1960- ~MockAndroidRegistrar() noexcept {}
1961+ ~MockBufferRegistrar() noexcept {}
1962 MOCK_CONST_METHOD1(register_buffer,
1963 std::shared_ptr<const native_handle_t>(std::shared_ptr<MirBufferPackage> const&));
1964 MOCK_METHOD2(secure_for_cpu, std::shared_ptr<char>(std::shared_ptr<const native_handle_t>, geometry::Rectangle));
1965@@ -44,4 +44,4 @@
1966 }
1967 }
1968
1969-#endif /* MIR_TEST_DOUBLES_MOCK_ANDROID_REGISTRAR_H_ */
1970+#endif /* MIR_TEST_DOUBLES_MOCK_BUFFER_REGISTRAR_H_ */
1971
1972=== modified file 'include/test/mir_test_doubles/mock_fence.h'
1973--- include/test/mir_test_doubles/mock_fence.h 2013-10-10 22:42:31 +0000
1974+++ include/test/mir_test_doubles/mock_fence.h 2014-07-11 20:27:44 +0000
1975@@ -32,6 +32,10 @@
1976
1977 struct MockFence : public graphics::android::Fence
1978 {
1979+ void merge_with(graphics::android::NativeFence&& fence)
1980+ {
1981+ merge_with(fence);
1982+ }
1983 MOCK_METHOD0(wait, void());
1984 MOCK_METHOD1(merge_with, void(graphics::android::NativeFence&));
1985 MOCK_CONST_METHOD0(copy_native_handle, graphics::android::NativeFence());
1986
1987=== modified file 'include/test/mir_test_doubles/mock_hwc_device_wrapper.h'
1988--- include/test/mir_test_doubles/mock_hwc_device_wrapper.h 2014-03-19 21:56:42 +0000
1989+++ include/test/mir_test_doubles/mock_hwc_device_wrapper.h 2014-07-11 20:27:44 +0000
1990@@ -34,6 +34,11 @@
1991 {
1992 MOCK_CONST_METHOD1(prepare, void(hwc_display_contents_1_t&));
1993 MOCK_CONST_METHOD1(set, void(hwc_display_contents_1_t&));
1994+ MOCK_CONST_METHOD1(register_hooks, void(hwc_procs_t*));
1995+ MOCK_CONST_METHOD0(vsync_signal_on, void());
1996+ MOCK_CONST_METHOD0(vsync_signal_off, void());
1997+ MOCK_CONST_METHOD0(display_on, void());
1998+ MOCK_CONST_METHOD0(display_off, void());
1999 };
2000
2001 }
2002
2003=== modified file 'include/test/mir_test_doubles/null_client_buffer.h'
2004--- include/test/mir_test_doubles/null_client_buffer.h 2014-01-21 18:03:46 +0000
2005+++ include/test/mir_test_doubles/null_client_buffer.h 2014-07-11 20:27:44 +0000
2006@@ -39,8 +39,9 @@
2007 geometry::Stride stride() const { return geometry::Stride(); }
2008 MirPixelFormat pixel_format() const { return mir_pixel_format_invalid; }
2009 uint32_t age() const { return 0; }
2010- void increment_age() { }
2011+ void increment_age() {}
2012 void mark_as_submitted() {}
2013+ void update_from(MirBufferPackage const&) {}
2014 std::shared_ptr<graphics::NativeBuffer> native_buffer_handle() const
2015 {
2016 return nullptr;
2017
2018=== modified file 'include/test/mir_test_doubles/stub_renderable.h'
2019--- include/test/mir_test_doubles/stub_renderable.h 2014-07-01 08:40:57 +0000
2020+++ include/test/mir_test_doubles/stub_renderable.h 2014-07-11 20:27:44 +0000
2021@@ -55,6 +55,11 @@
2022 StubRenderable(make_stub_buffer({{},{}}), {{},{}})
2023 {}
2024
2025+ void set_buffer(std::shared_ptr<graphics::Buffer> const& buffer)
2026+ {
2027+ stub_buffer = buffer;
2028+ }
2029+
2030 ID id() const override
2031 {
2032 return this;
2033@@ -103,7 +108,7 @@
2034
2035 glm::mat4 trans;
2036 geometry::Rectangle const rect;
2037- std::shared_ptr<graphics::Buffer> const stub_buffer;
2038+ std::shared_ptr<graphics::Buffer> stub_buffer;
2039 };
2040
2041 struct StubTransformedRenderable : public StubRenderable
2042
2043=== modified file 'include/test/mir_test_doubles/stub_session_authorizer.h'
2044--- include/test/mir_test_doubles/stub_session_authorizer.h 2014-06-02 17:07:02 +0000
2045+++ include/test/mir_test_doubles/stub_session_authorizer.h 2014-07-11 20:27:44 +0000
2046@@ -30,15 +30,19 @@
2047
2048 class StubSessionAuthorizer : public frontend::SessionAuthorizer
2049 {
2050- bool connection_is_allowed(mir::frontend::SessionCredentials const&)
2051- {
2052- return true;
2053- }
2054- bool configure_display_is_allowed(mir::frontend::SessionCredentials const&)
2055- {
2056- return true;
2057- }
2058- bool screencast_is_allowed(mir::frontend::SessionCredentials const&)
2059+ bool connection_is_allowed(mir::frontend::SessionCredentials const&) override
2060+ {
2061+ return true;
2062+ }
2063+ bool configure_display_is_allowed(mir::frontend::SessionCredentials const&) override
2064+ {
2065+ return true;
2066+ }
2067+ bool screencast_is_allowed(mir::frontend::SessionCredentials const&) override
2068+ {
2069+ return true;
2070+ }
2071+ bool prompt_session_is_allowed(mir::frontend::SessionCredentials const&) override
2072 {
2073 return true;
2074 }
2075
2076=== modified file 'include/test/mir_test_framework/in_process_server.h'
2077--- include/test/mir_test_framework/in_process_server.h 2014-06-23 15:57:55 +0000
2078+++ include/test/mir_test_framework/in_process_server.h 2014-07-11 20:27:44 +0000
2079@@ -38,6 +38,9 @@
2080
2081 /// \return a connection string for a new client to connect to the server
2082 using ServerRunner::new_connection;
2083+
2084+ /// \return a connection string for a new client to connect to the prompt server
2085+ using ServerRunner::new_prompt_connection;
2086 };
2087 }
2088
2089
2090=== modified file 'include/test/mir_test_framework/server_runner.h'
2091--- include/test/mir_test_framework/server_runner.h 2014-06-10 12:28:03 +0000
2092+++ include/test/mir_test_framework/server_runner.h 2014-07-11 20:27:44 +0000
2093@@ -47,6 +47,9 @@
2094 /// \return a connection string for a new client to connect to the server
2095 std::string new_connection();
2096
2097+ /// \return a connection string for a new client to connect to the prompt server
2098+ std::string new_prompt_connection();
2099+
2100 private:
2101 mir::DisplayServer* start_mir_server();
2102 virtual mir::DefaultServerConfiguration& server_config() = 0;
2103
2104=== modified file 'src/client/android/CMakeLists.txt'
2105--- src/client/android/CMakeLists.txt 2014-06-26 19:16:29 +0000
2106+++ src/client/android/CMakeLists.txt 2014-07-11 20:27:44 +0000
2107@@ -6,7 +6,7 @@
2108
2109 buffer.cpp
2110 android_client_buffer_factory.cpp
2111- android_registrar.cpp
2112+ gralloc_registrar.cpp
2113 android_client_platform.cpp
2114 client_platform_factory.cpp
2115 client_surface_interpreter.cpp
2116
2117=== modified file 'src/client/android/android_client_buffer_factory.cpp'
2118--- src/client/android/android_client_buffer_factory.cpp 2014-06-26 19:16:29 +0000
2119+++ src/client/android/android_client_buffer_factory.cpp 2014-07-11 20:27:44 +0000
2120@@ -18,14 +18,16 @@
2121 */
2122
2123 #include "android_client_buffer_factory.h"
2124+#include "buffer_registrar.h"
2125 #include "buffer.h"
2126
2127 namespace mcl=mir::client;
2128 namespace mcla=mir::client::android;
2129 namespace geom=mir::geometry;
2130
2131-mcla::AndroidClientBufferFactory::AndroidClientBufferFactory(std::shared_ptr<AndroidRegistrar> const& buffer_registrar)
2132- : registrar(buffer_registrar)
2133+mcla::AndroidClientBufferFactory::AndroidClientBufferFactory(
2134+ std::shared_ptr<BufferRegistrar> const& buffer_registrar) :
2135+ registrar(buffer_registrar)
2136 {
2137 }
2138
2139
2140=== modified file 'src/client/android/android_client_buffer_factory.h'
2141--- src/client/android/android_client_buffer_factory.h 2014-03-06 06:05:17 +0000
2142+++ src/client/android/android_client_buffer_factory.h 2014-07-11 20:27:44 +0000
2143@@ -33,20 +33,20 @@
2144 namespace client
2145 {
2146 class ClientBuffer;
2147-
2148 namespace android
2149 {
2150-class AndroidRegistrar;
2151-
2152+class BufferRegistrar;
2153 class AndroidClientBufferFactory : public ClientBufferFactory
2154 {
2155 public:
2156- explicit AndroidClientBufferFactory(std::shared_ptr<AndroidRegistrar> const&);
2157-
2158- virtual std::shared_ptr<ClientBuffer> create_buffer(std::shared_ptr<MirBufferPackage> const& package,
2159- geometry::Size size, MirPixelFormat pf);
2160+ explicit AndroidClientBufferFactory(
2161+ std::shared_ptr<BufferRegistrar> const& registrar);
2162+ std::shared_ptr<ClientBuffer> create_buffer(
2163+ std::shared_ptr<MirBufferPackage> const& package,
2164+ geometry::Size size,
2165+ MirPixelFormat pf) override;
2166 private:
2167- std::shared_ptr<AndroidRegistrar> registrar;
2168+ std::shared_ptr<BufferRegistrar> const registrar;
2169 };
2170
2171 }
2172
2173=== modified file 'src/client/android/android_client_platform.cpp'
2174--- src/client/android/android_client_platform.cpp 2014-03-06 06:05:17 +0000
2175+++ src/client/android/android_client_platform.cpp 2014-07-11 20:27:44 +0000
2176@@ -18,7 +18,7 @@
2177
2178 #include "mir/graphics/android/mir_native_window.h"
2179 #include "android_client_platform.h"
2180-#include "android_registrar_gralloc.h"
2181+#include "gralloc_registrar.h"
2182 #include "android_client_buffer_factory.h"
2183 #include "client_surface_interpreter.h"
2184 #include "../mir_connection.h"
2185@@ -56,7 +56,7 @@
2186 /* we use an empty deleter because hw_get_module does not give us the ownership of the ptr */
2187 EmptyDeleter empty_del;
2188 auto gralloc_dev = std::shared_ptr<gralloc_module_t>(gr_dev, empty_del);
2189- auto registrar = std::make_shared<mcla::AndroidRegistrarGralloc>(gralloc_dev);
2190+ auto registrar = std::make_shared<mcla::GrallocRegistrar>(gralloc_dev);
2191 return std::make_shared<mcla::AndroidClientBufferFactory>(registrar);
2192 }
2193
2194
2195=== modified file 'src/client/android/buffer.cpp'
2196--- src/client/android/buffer.cpp 2014-06-26 19:16:29 +0000
2197+++ src/client/android/buffer.cpp 2014-07-11 20:27:44 +0000
2198@@ -19,6 +19,7 @@
2199 #include "mir/graphics/android/android_native_buffer.h"
2200 #include "mir/graphics/android/sync_fence.h"
2201 #include "mir_toolkit/mir_client_library.h"
2202+#include "buffer_registrar.h"
2203 #include "buffer.h"
2204 #include <hardware/gralloc.h>
2205
2206@@ -28,7 +29,7 @@
2207 namespace mga=mir::graphics::android;
2208
2209 mcla::Buffer::Buffer(
2210- std::shared_ptr<AndroidRegistrar> const& registrar,
2211+ std::shared_ptr<BufferRegistrar> const& registrar,
2212 std::shared_ptr<const native_handle_t> const& handle,
2213 geom::Size size,
2214 MirPixelFormat pf,
2215@@ -40,7 +41,7 @@
2216 buffer_size(size)
2217 {
2218 auto ops = std::make_shared<mga::RealSyncFileOps>();
2219- auto fence = std::make_shared<mga::SyncFence>(ops, -1);
2220+ auto fence = std::make_shared<mga::SyncFence>(ops, mir::Fd(-1));
2221 auto anwb = std::shared_ptr<mga::RefCountedNativeBuffer>(
2222 new mga::RefCountedNativeBuffer(handle),
2223 [](mga::RefCountedNativeBuffer* buffer)
2224@@ -96,3 +97,8 @@
2225 {
2226 return native_window_buffer;
2227 }
2228+
2229+void mcla::Buffer::update_from(MirBufferPackage const& update_package)
2230+{
2231+ (void) update_package;
2232+}
2233
2234=== modified file 'src/client/android/buffer.h'
2235--- src/client/android/buffer.h 2014-06-26 19:16:29 +0000
2236+++ src/client/android/buffer.h 2014-07-11 20:27:44 +0000
2237@@ -22,7 +22,6 @@
2238
2239 #include "mir/graphics/android/android_native_buffer.h"
2240 #include "../aging_buffer.h"
2241-#include "android_registrar.h"
2242
2243 #include <system/window.h>
2244 #include <memory>
2245@@ -34,11 +33,12 @@
2246 namespace android
2247 {
2248
2249+class BufferRegistrar;
2250 class Buffer : public AgingBuffer
2251 {
2252 public:
2253 Buffer(
2254- std::shared_ptr<AndroidRegistrar> const&,
2255+ std::shared_ptr<BufferRegistrar> const&,
2256 std::shared_ptr<const native_handle_t> const&,
2257 geometry::Size size,
2258 MirPixelFormat pf,
2259@@ -50,13 +50,14 @@
2260 geometry::Stride stride() const;
2261 MirPixelFormat pixel_format() const;
2262 std::shared_ptr<mir::graphics::NativeBuffer> native_buffer_handle() const;
2263+ void update_from(MirBufferPackage const& update_package);
2264
2265 Buffer(const Buffer&) = delete;
2266 Buffer& operator=(const Buffer&) = delete;
2267 private:
2268 void pack_native_window_buffer();
2269
2270- std::shared_ptr<AndroidRegistrar> buffer_registrar;
2271+ std::shared_ptr<BufferRegistrar> buffer_registrar;
2272 std::shared_ptr<graphics::android::AndroidNativeBuffer> native_window_buffer;
2273 std::shared_ptr<const native_handle_t> native_handle;
2274 const MirPixelFormat buffer_pf;
2275
2276=== renamed file 'src/client/android/android_registrar.h' => 'src/client/android/buffer_registrar.h'
2277--- src/client/android/android_registrar.h 2013-06-21 22:14:10 +0000
2278+++ src/client/android/buffer_registrar.h 2014-07-11 20:27:44 +0000
2279@@ -17,14 +17,14 @@
2280 * Kevin DuBois <kevin.dubois@canonical.com>
2281 */
2282
2283-#ifndef MIR_CLIENT_ANDROID_ANDROID_REGISTRAR_H_
2284-#define MIR_CLIENT_ANDROID_ANDROID_REGISTRAR_H_
2285+#ifndef MIR_CLIENT_ANDROID_BUFFER_REGISTRAR_H_
2286+#define MIR_CLIENT_ANDROID_BUFFER_REGISTRAR_H_
2287
2288 #include <mir_toolkit/mir_native_buffer.h>
2289 #include "mir/geometry/rectangle.h"
2290 #include <cutils/native_handle.h>
2291-
2292 #include <memory>
2293+
2294 namespace mir
2295 {
2296 namespace client
2297@@ -33,16 +33,20 @@
2298
2299 namespace android
2300 {
2301-class AndroidRegistrar
2302+class BufferRegistrar
2303 {
2304 public:
2305- virtual ~AndroidRegistrar() = default;
2306+ virtual ~BufferRegistrar() = default;
2307 virtual std::shared_ptr<const native_handle_t> register_buffer(
2308 std::shared_ptr<MirBufferPackage> const& package) const = 0;
2309 virtual std::shared_ptr<char> secure_for_cpu(std::shared_ptr<const native_handle_t> handle, const geometry::Rectangle) = 0;
2310+protected:
2311+ BufferRegistrar() = default;
2312+ BufferRegistrar(BufferRegistrar const&) = delete;
2313+ BufferRegistrar& operator=(BufferRegistrar const&) = delete;
2314 };
2315
2316 }
2317 }
2318 }
2319-#endif /* MIR_CLIENT_ANDROID_REGISTRAR_H_ */
2320+#endif /* MIR_CLIENT_ANDROID_BUFFER_REGISTRAR_H_ */
2321
2322=== modified file 'src/client/android/client_surface_interpreter.cpp'
2323--- src/client/android/client_surface_interpreter.cpp 2014-05-20 03:37:18 +0000
2324+++ src/client/android/client_surface_interpreter.cpp 2014-07-11 20:27:44 +0000
2325@@ -46,7 +46,7 @@
2326 void mcla::ClientSurfaceInterpreter::driver_returns_buffer(ANativeWindowBuffer*, int fence_fd)
2327 {
2328 //TODO: pass fence to server instead of waiting here
2329- mga::SyncFence sync_fence(sync_ops, fence_fd);
2330+ mga::SyncFence sync_fence(sync_ops, mir::Fd(std::move(fence_fd)));
2331 sync_fence.wait();
2332
2333 surface.request_and_wait_for_next_buffer();
2334
2335=== renamed file 'src/client/android/android_registrar.cpp' => 'src/client/android/gralloc_registrar.cpp'
2336--- src/client/android/android_registrar.cpp 2014-03-06 06:05:17 +0000
2337+++ src/client/android/gralloc_registrar.cpp 2014-07-11 20:27:44 +0000
2338@@ -16,7 +16,7 @@
2339 * Authored by: Kevin DuBois<kevin.dubois@canonical.com>
2340 */
2341
2342-#include "android_registrar_gralloc.h"
2343+#include "gralloc_registrar.h"
2344 #include "../client_buffer.h"
2345
2346 #include <boost/throw_exception.hpp>
2347@@ -66,12 +66,12 @@
2348 };
2349 }
2350
2351-mcla::AndroidRegistrarGralloc::AndroidRegistrarGralloc(const std::shared_ptr<const gralloc_module_t>& gr_module)
2352+mcla::GrallocRegistrar::GrallocRegistrar(const std::shared_ptr<const gralloc_module_t>& gr_module)
2353 : gralloc_module(gr_module)
2354 {
2355 }
2356
2357-std::shared_ptr<const native_handle_t> mcla::AndroidRegistrarGralloc::register_buffer(
2358+std::shared_ptr<const native_handle_t> mcla::GrallocRegistrar::register_buffer(
2359 std::shared_ptr<MirBufferPackage> const& package) const
2360 {
2361 int native_handle_header_size = sizeof(native_handle_t);
2362@@ -102,7 +102,9 @@
2363 return std::shared_ptr<const native_handle_t>(handle, del);
2364 }
2365
2366-std::shared_ptr<char> mcla::AndroidRegistrarGralloc::secure_for_cpu(std::shared_ptr<const native_handle_t> handle, const geometry::Rectangle rect)
2367+std::shared_ptr<char> mcla::GrallocRegistrar::secure_for_cpu(
2368+ std::shared_ptr<const native_handle_t> handle,
2369+ const geometry::Rectangle rect)
2370 {
2371 char* vaddr;
2372 int usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
2373
2374=== renamed file 'src/client/android/android_registrar_gralloc.h' => 'src/client/android/gralloc_registrar.h'
2375--- src/client/android/android_registrar_gralloc.h 2014-03-06 06:05:17 +0000
2376+++ src/client/android/gralloc_registrar.h 2014-07-11 20:27:44 +0000
2377@@ -17,11 +17,11 @@
2378 * Kevin DuBois <kevin.dubois@canonical.com>
2379 */
2380
2381-#ifndef MIR_CLIENT_ANDROID_ANDROID_REGISTRAR_GRALLOC_H_
2382-#define MIR_CLIENT_ANDROID_ANDROID_REGISTRAR_GRALLOC_H_
2383+#ifndef MIR_CLIENT_ANDROID_GRALLOC_REGISTRAR_H_
2384+#define MIR_CLIENT_ANDROID_GRALLOC_REGISTRAR_H_
2385
2386 #include "mir_toolkit/common.h"
2387-#include "android_registrar.h"
2388+#include "buffer_registrar.h"
2389 #include <hardware/gralloc.h>
2390
2391 namespace mir
2392@@ -31,10 +31,10 @@
2393 namespace android
2394 {
2395
2396-class AndroidRegistrarGralloc : public AndroidRegistrar
2397+class GrallocRegistrar : public BufferRegistrar
2398 {
2399 public:
2400- AndroidRegistrarGralloc(const std::shared_ptr<const gralloc_module_t>& gralloc_dev);
2401+ GrallocRegistrar(const std::shared_ptr<const gralloc_module_t>& gralloc_dev);
2402
2403 std::shared_ptr<const native_handle_t> register_buffer(
2404 std::shared_ptr<MirBufferPackage> const& package) const;
2405@@ -47,4 +47,4 @@
2406 }
2407 }
2408 }
2409-#endif /* MIR_CLIENT_ANDROID_ANDROID_REGISTRAR_GRALLOC_H_ */
2410+#endif /* MIR_CLIENT_ANDROID_GRALLOC_REGISTRAR_H_ */
2411
2412=== modified file 'src/client/client_buffer.h'
2413--- src/client/client_buffer.h 2014-03-06 06:05:17 +0000
2414+++ src/client/client_buffer.h 2014-07-11 20:27:44 +0000
2415@@ -62,6 +62,7 @@
2416 virtual void increment_age() = 0;
2417 virtual void mark_as_submitted() = 0;
2418 virtual std::shared_ptr<graphics::NativeBuffer> native_buffer_handle() const = 0;
2419+ virtual void update_from(MirBufferPackage const& update_package) = 0;
2420
2421 protected:
2422 ClientBuffer() = default;
2423
2424=== modified file 'src/client/client_buffer_depository.cpp'
2425--- src/client/client_buffer_depository.cpp 2014-03-06 06:05:17 +0000
2426+++ src/client/client_buffer_depository.cpp 2014-07-11 20:27:44 +0000
2427@@ -53,6 +53,7 @@
2428 }
2429 else
2430 {
2431+ existing_buffer_id_pair->second->update_from(*package);
2432 buffers.push_front(*existing_buffer_id_pair);
2433 buffers.erase(existing_buffer_id_pair);
2434 }
2435
2436=== modified file 'src/client/mesa/client_buffer.cpp'
2437--- src/client/mesa/client_buffer.cpp 2014-03-06 06:05:17 +0000
2438+++ src/client/mesa/client_buffer.cpp 2014-07-11 20:27:44 +0000
2439@@ -131,3 +131,7 @@
2440 creation_package->age = age();
2441 return creation_package;
2442 }
2443+
2444+void mclm::ClientBuffer::update_from(MirBufferPackage const&)
2445+{
2446+}
2447
2448=== modified file 'src/client/mesa/client_buffer.h'
2449--- src/client/mesa/client_buffer.h 2014-03-06 06:05:17 +0000
2450+++ src/client/mesa/client_buffer.h 2014-07-11 20:27:44 +0000
2451@@ -50,6 +50,7 @@
2452 geometry::Stride stride() const;
2453 MirPixelFormat pixel_format() const;
2454 std::shared_ptr<MirNativeBuffer> native_buffer_handle() const;
2455+ void update_from(MirBufferPackage const&);
2456
2457 private:
2458 std::shared_ptr<BufferFileOps> const buffer_file_ops;
2459
2460=== modified file 'src/client/mir_prompt_session_api.cpp'
2461--- src/client/mir_prompt_session_api.cpp 2014-06-13 10:02:22 +0000
2462+++ src/client/mir_prompt_session_api.cpp 2014-07-11 20:27:44 +0000
2463@@ -116,3 +116,15 @@
2464 mir_wait_for(prompt_session->stop(&null_callback, nullptr));
2465 delete prompt_session;
2466 }
2467+
2468+MirBool mir_prompt_session_is_valid(MirPromptSession *prompt_session)
2469+{
2470+ auto const err = prompt_session->get_error_message();
2471+
2472+ return MirBool(!*err);
2473+}
2474+
2475+char const *mir_prompt_session_error_message(MirPromptSession *prompt_session)
2476+{
2477+ return prompt_session->get_error_message();
2478+}
2479
2480=== modified file 'src/platform/graphics/android/android_alloc_adaptor.cpp'
2481--- src/platform/graphics/android/android_alloc_adaptor.cpp 2014-06-17 18:24:48 +0000
2482+++ src/platform/graphics/android/android_alloc_adaptor.cpp 2014-07-11 20:27:44 +0000
2483@@ -72,7 +72,7 @@
2484 std::shared_ptr<native_handle_t const> handle(buf_handle, del1);
2485
2486 auto ops = std::make_shared<mga::RealSyncFileOps>();
2487- auto fence = std::make_shared<mga::SyncFence>(ops, -1);
2488+ auto fence = std::make_shared<mga::SyncFence>(ops, mir::Fd(-1));
2489
2490 auto anwb = std::shared_ptr<mga::RefCountedNativeBuffer>(
2491 new mga::RefCountedNativeBuffer(handle),
2492
2493=== modified file 'src/platform/graphics/android/hwc_common_device.cpp'
2494--- src/platform/graphics/android/hwc_common_device.cpp 2014-06-16 21:16:14 +0000
2495+++ src/platform/graphics/android/hwc_common_device.cpp 2014-07-11 20:27:44 +0000
2496@@ -17,6 +17,7 @@
2497 */
2498
2499 #include "hwc_common_device.h"
2500+#include "hwc_wrapper.h"
2501 #include "hwc_vsync_coordinator.h"
2502
2503 #include <boost/throw_exception.hpp>
2504@@ -42,8 +43,8 @@
2505 }
2506 }
2507
2508-mga::HWCCommonDevice::HWCCommonDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
2509- std::shared_ptr<mga::HWCVsyncCoordinator> const& coordinator)
2510+mga::HWCCommonDevice::HWCCommonDevice(std::shared_ptr<HwcWrapper> const& hwc_device,
2511+ std::shared_ptr<HWCVsyncCoordinator> const& coordinator)
2512 : coordinator(coordinator),
2513 hwc_device(hwc_device),
2514 current_mode(mir_power_mode_on)
2515@@ -53,16 +54,23 @@
2516 callbacks.hooks.hotplug = hotplug_hook;
2517 callbacks.self = this;
2518
2519- hwc_device->registerProcs(hwc_device.get(), &callbacks.hooks);
2520+ hwc_device->register_hooks(&callbacks.hooks);
2521
2522 turn_screen_on();
2523 }
2524
2525 mga::HWCCommonDevice::~HWCCommonDevice() noexcept
2526 {
2527- std::unique_lock<std::mutex> lg(blanked_mutex);
2528 if (current_mode == mir_power_mode_on)
2529- turn_screen_off();
2530+ {
2531+ std::unique_lock<std::mutex> lg(blanked_mutex);
2532+ try
2533+ {
2534+ turn_screen_off();
2535+ } catch (...)
2536+ {
2537+ }
2538+ }
2539 }
2540
2541 void mga::HWCCommonDevice::notify_vsync()
2542@@ -73,7 +81,6 @@
2543 void mga::HWCCommonDevice::mode(MirPowerMode mode_request)
2544 {
2545 std::unique_lock<std::mutex> lg(blanked_mutex);
2546- int err = 0;
2547
2548 if ((mode_request == mir_power_mode_suspend) ||
2549 (mode_request == mir_power_mode_standby))
2550@@ -84,22 +91,12 @@
2551 if ((mode_request == mir_power_mode_on) &&
2552 (current_mode == mir_power_mode_off))
2553 {
2554- err = turn_screen_on();
2555+ turn_screen_on();
2556 }
2557 else if ((mode_request == mir_power_mode_off) &&
2558 (current_mode == mir_power_mode_on))
2559 {
2560- err = turn_screen_off();
2561- }
2562-
2563- if (err)
2564- {
2565- std::string blanking_status_msg = "Could not " +
2566- ((mode_request == mir_power_mode_off) ? std::string("blank") : std::string("unblank")) + " display";
2567- BOOST_THROW_EXCEPTION(
2568- boost::enable_error_info(
2569- std::runtime_error(blanking_status_msg)) <<
2570- boost::errinfo_errno(-err));
2571+ turn_screen_off();
2572 }
2573
2574 current_mode = mode_request;
2575@@ -114,18 +111,16 @@
2576 return std::move(lg);
2577 }
2578
2579-int mga::HWCCommonDevice::turn_screen_on() const noexcept(true)
2580+void mga::HWCCommonDevice::turn_screen_on() const
2581 {
2582- if (auto err = hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 0))
2583- return err;
2584- return hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 1);
2585+ hwc_device->display_on();
2586+ hwc_device->vsync_signal_on();
2587 }
2588
2589-int mga::HWCCommonDevice::turn_screen_off() const noexcept(true)
2590+void mga::HWCCommonDevice::turn_screen_off() const
2591 {
2592- if (auto err = hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 0))
2593- return err;
2594- return hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 1);
2595+ hwc_device->vsync_signal_off();
2596+ hwc_device->display_off();
2597 }
2598
2599 bool mga::HWCCommonDevice::apply_orientation(MirOrientation) const
2600
2601=== modified file 'src/platform/graphics/android/hwc_common_device.h'
2602--- src/platform/graphics/android/hwc_common_device.h 2014-03-26 05:48:59 +0000
2603+++ src/platform/graphics/android/hwc_common_device.h 2014-07-11 20:27:44 +0000
2604@@ -33,6 +33,7 @@
2605 namespace android
2606 {
2607
2608+class HwcWrapper;
2609 class HWCVsyncCoordinator;
2610 class HWCCommonDevice;
2611 struct HWCCallbacks
2612@@ -51,19 +52,19 @@
2613 bool apply_orientation(MirOrientation orientation) const;
2614
2615 protected:
2616- HWCCommonDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
2617+ HWCCommonDevice(std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2618 std::shared_ptr<HWCVsyncCoordinator> const& coordinator);
2619
2620 std::shared_ptr<HWCVsyncCoordinator> const coordinator;
2621 std::unique_lock<std::mutex> lock_unblanked();
2622
2623 private:
2624- int turn_screen_on() const noexcept(true);
2625- int turn_screen_off() const noexcept(true);
2626+ void turn_screen_on() const;
2627+ void turn_screen_off() const;
2628
2629 HWCCallbacks callbacks;
2630
2631- std::shared_ptr<hwc_composer_device_1> const hwc_device;
2632+ std::shared_ptr<HwcWrapper> const hwc_device;
2633
2634 std::mutex blanked_mutex;
2635 std::condition_variable blanked_cond;
2636
2637=== modified file 'src/platform/graphics/android/hwc_device.cpp'
2638--- src/platform/graphics/android/hwc_device.cpp 2014-06-21 02:09:15 +0000
2639+++ src/platform/graphics/android/hwc_device.cpp 2014-07-11 20:27:44 +0000
2640@@ -64,57 +64,46 @@
2641 }
2642 }
2643
2644-void mga::HwcDevice::setup_layer_types()
2645-{
2646- auto it = hwc_list.additional_layers_begin();
2647- auto const num_additional_layers = std::distance(it, hwc_list.end());
2648- switch (num_additional_layers)
2649- {
2650- case fbtarget_plus_skip_size:
2651- it->set_layer_type(mga::LayerType::skip);
2652- ++it;
2653- case fbtarget_size:
2654- it->set_layer_type(mga::LayerType::framebuffer_target);
2655- default:
2656- break;
2657- }
2658-}
2659-
2660-void mga::HwcDevice::set_list_framebuffer(mg::Buffer const& buffer)
2661-{
2662- geom::Rectangle const disp_frame{{0,0}, {buffer.size()}};
2663- for(auto it = hwc_list.additional_layers_begin(); it != hwc_list.end(); it++)
2664- {
2665- //TODO: the functions on mga::Layer should be consolidated
2666- it->set_render_parameters(disp_frame, false);
2667- it->set_buffer(buffer);
2668- it->prepare_for_draw();
2669- }
2670-}
2671-
2672-mga::HwcDevice::HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
2673- std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2674+mga::HwcDevice::HwcDevice(std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2675 std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
2676 std::shared_ptr<SyncFileOps> const& sync_ops)
2677- : HWCCommonDevice(hwc_device, coordinator),
2678- hwc_list{{}, 2},
2679+ : HWCCommonDevice(hwc_wrapper, coordinator),
2680+ hwc_list{{}, fbtarget_plus_skip_size},
2681 hwc_wrapper(hwc_wrapper),
2682 sync_ops(sync_ops)
2683 {
2684- setup_layer_types();
2685 }
2686
2687 void mga::HwcDevice::post_gl(SwappingGLContext const& context)
2688 {
2689- hwc_list.update_list_and_check_if_changed({}, fbtarget_plus_skip_size);
2690- setup_layer_types();
2691+ auto lg = lock_unblanked();
2692+ hwc_list.update_list({}, fbtarget_plus_skip_size);
2693+ auto& skip = *hwc_list.additional_layers_begin();
2694+ auto& fbtarget = *(++hwc_list.additional_layers_begin());
2695+
2696+ auto buffer = context.last_rendered_buffer();
2697+ geom::Rectangle const disp_frame{{0,0}, {buffer->size()}};
2698+ skip.layer.setup_layer(mga::LayerType::skip, disp_frame, false, *buffer);
2699+ fbtarget.layer.setup_layer(mga::LayerType::framebuffer_target, disp_frame, false, *buffer);
2700
2701 hwc_wrapper->prepare(*hwc_list.native_list().lock());
2702
2703 context.swap_buffers();
2704
2705- post(context);
2706+ buffer = context.last_rendered_buffer();
2707+ skip.layer.setup_layer(mga::LayerType::skip, disp_frame, false, *buffer);
2708+ fbtarget.layer.setup_layer(mga::LayerType::framebuffer_target, disp_frame, false, *buffer);
2709+
2710+ for(auto& layer : hwc_list)
2711+ layer.layer.set_acquirefence_from(*buffer);
2712+
2713+ hwc_wrapper->set(*hwc_list.native_list().lock());
2714 onscreen_overlay_buffers.clear();
2715+
2716+ for(auto& layer : hwc_list)
2717+ layer.layer.update_from_releasefence(*buffer);
2718+
2719+ mir::Fd retire_fd(hwc_list.retirement_fence());
2720 }
2721
2722 bool mga::HwcDevice::post_overlays(
2723@@ -124,40 +113,63 @@
2724 {
2725 if (renderable_list_is_hwc_incompatible(renderables))
2726 return false;
2727- if (!hwc_list.update_list_and_check_if_changed(renderables, fbtarget_size))
2728+
2729+ hwc_list.update_list(renderables, fbtarget_size);
2730+
2731+ bool needs_commit{false};
2732+ for(auto& layer : hwc_list)
2733+ needs_commit |= layer.needs_commit;
2734+ if (!needs_commit)
2735 return false;
2736- setup_layer_types();
2737+
2738+ auto lg = lock_unblanked();
2739+ auto& fbtarget = *hwc_list.additional_layers_begin();
2740+
2741+ auto buffer = context.last_rendered_buffer();
2742+ geom::Rectangle const disp_frame{{0,0}, {buffer->size()}};
2743+ fbtarget.layer.setup_layer(mga::LayerType::framebuffer_target, disp_frame, false, *buffer);
2744
2745 hwc_wrapper->prepare(*hwc_list.native_list().lock());
2746
2747 mg::RenderableList rejected_renderables;
2748-
2749 std::vector<std::shared_ptr<mg::Buffer>> next_onscreen_overlay_buffers;
2750- auto layers_it = hwc_list.begin();
2751+ auto it = hwc_list.begin();
2752 for(auto const& renderable : renderables)
2753 {
2754- layers_it->prepare_for_draw();
2755- if (layers_it->needs_gl_render())
2756+ if (it->layer.needs_gl_render())
2757+ {
2758 rejected_renderables.push_back(renderable);
2759+ }
2760 else
2761+ {
2762+ if (it->needs_commit)
2763+ it->layer.set_acquirefence_from(*renderable->buffer());
2764 next_onscreen_overlay_buffers.push_back(renderable->buffer());
2765- layers_it++;
2766- }
2767-
2768- list_compositor.render(rejected_renderables, context);
2769- post(context);
2770+ }
2771+ it++;
2772+ }
2773+
2774+ if (!rejected_renderables.empty())
2775+ {
2776+ list_compositor.render(rejected_renderables, context);
2777+
2778+ buffer = context.last_rendered_buffer();
2779+ fbtarget.layer.setup_layer(mga::LayerType::framebuffer_target, disp_frame, false, *buffer);
2780+ fbtarget.layer.set_acquirefence_from(*buffer);
2781+ }
2782+
2783+ hwc_wrapper->set(*hwc_list.native_list().lock());
2784 onscreen_overlay_buffers = std::move(next_onscreen_overlay_buffers);
2785+
2786+ it = hwc_list.begin();
2787+ for(auto const& renderable : renderables)
2788+ {
2789+ it->layer.update_from_releasefence(*renderable->buffer());
2790+ it++;
2791+ }
2792+ if (!rejected_renderables.empty())
2793+ fbtarget.layer.update_from_releasefence(*buffer);
2794+
2795+ mir::Fd retire_fd(hwc_list.retirement_fence());
2796 return true;
2797 }
2798-
2799-void mga::HwcDevice::post(SwappingGLContext const& context)
2800-{
2801- auto lg = lock_unblanked();
2802- set_list_framebuffer(*context.last_rendered_buffer());
2803- hwc_wrapper->set(*hwc_list.native_list().lock());
2804-
2805- for(auto& layer : hwc_list)
2806- layer.update_fence_and_release_buffer();
2807-
2808- mga::SyncFence retire_fence(sync_ops, hwc_list.retirement_fence());
2809-}
2810
2811=== modified file 'src/platform/graphics/android/hwc_device.h'
2812--- src/platform/graphics/android/hwc_device.h 2014-06-16 14:47:14 +0000
2813+++ src/platform/graphics/android/hwc_device.h 2014-07-11 20:27:44 +0000
2814@@ -41,10 +41,7 @@
2815 class HwcDevice : public HWCCommonDevice
2816 {
2817 public:
2818- //TODO: the first two constructor arguments are redundant. eliminate the 1st one when the 2nd
2819- // one can be used by the HWCCommonDevice
2820- HwcDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
2821- std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2822+ HwcDevice(std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2823 std::shared_ptr<HWCVsyncCoordinator> const& coordinator,
2824 std::shared_ptr<SyncFileOps> const& sync_ops);
2825
2826@@ -55,14 +52,9 @@
2827 RenderableListCompositor const& list_compositor);
2828
2829 private:
2830- void post(SwappingGLContext const& context);
2831-
2832 LayerList hwc_list;
2833 std::vector<std::shared_ptr<Buffer>> onscreen_overlay_buffers;
2834
2835- void set_list_framebuffer(Buffer const&);
2836- void setup_layer_types();
2837-
2838 std::shared_ptr<HwcWrapper> const hwc_wrapper;
2839 std::shared_ptr<SyncFileOps> const sync_ops;
2840 };
2841
2842=== modified file 'src/platform/graphics/android/hwc_fb_device.cpp'
2843--- src/platform/graphics/android/hwc_fb_device.cpp 2014-06-17 18:24:48 +0000
2844+++ src/platform/graphics/android/hwc_fb_device.cpp 2014-07-11 20:27:44 +0000
2845@@ -35,20 +35,22 @@
2846 namespace mga = mir::graphics::android;
2847 namespace geom = mir::geometry;
2848
2849-mga::HwcFbDevice::HwcFbDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
2850- std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2851- std::shared_ptr<framebuffer_device_t> const& fb_device,
2852- std::shared_ptr<HWCVsyncCoordinator> const& coordinator)
2853- : HWCCommonDevice(hwc_device, coordinator),
2854- hwc_wrapper(hwc_wrapper),
2855- fb_device(fb_device),
2856- layer_list{{},1}
2857+mga::HwcFbDevice::HwcFbDevice(
2858+ std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2859+ std::shared_ptr<framebuffer_device_t> const& fb_device,
2860+ std::shared_ptr<HWCVsyncCoordinator> const& coordinator) :
2861+ HWCCommonDevice(hwc_wrapper, coordinator),
2862+ hwc_wrapper(hwc_wrapper),
2863+ fb_device(fb_device),
2864+ layer_list{{},1}
2865 {
2866- layer_list.additional_layers_begin()->set_layer_type(mga::LayerType::skip);
2867 }
2868
2869 void mga::HwcFbDevice::post_gl(SwappingGLContext const& context)
2870 {
2871+ auto& buffer = *context.last_rendered_buffer();
2872+ layer_list.begin()->layer.setup_layer(mga::LayerType::skip, {{0,0},buffer.size()}, false, buffer);
2873+
2874 if (auto display_list = layer_list.native_list().lock())
2875 {
2876 hwc_wrapper->prepare(*display_list);
2877@@ -68,8 +70,8 @@
2878
2879 auto lg = lock_unblanked();
2880
2881- auto const& buffer = context.last_rendered_buffer();
2882- auto native_buffer = buffer->native_buffer_handle();
2883+ buffer = *context.last_rendered_buffer();
2884+ auto native_buffer = buffer.native_buffer_handle();
2885 native_buffer->ensure_available_for(mga::BufferAccess::read);
2886 if (fb_device->post(fb_device.get(), native_buffer->handle()) != 0)
2887 {
2888
2889=== modified file 'src/platform/graphics/android/hwc_fb_device.h'
2890--- src/platform/graphics/android/hwc_fb_device.h 2014-06-16 14:47:14 +0000
2891+++ src/platform/graphics/android/hwc_fb_device.h 2014-07-11 20:27:44 +0000
2892@@ -35,8 +35,7 @@
2893 class HwcFbDevice : public HWCCommonDevice
2894 {
2895 public:
2896- HwcFbDevice(std::shared_ptr<hwc_composer_device_1> const& hwc_device,
2897- std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2898+ HwcFbDevice(std::shared_ptr<HwcWrapper> const& hwc_wrapper,
2899 std::shared_ptr<framebuffer_device_t> const& fb_device,
2900 std::shared_ptr<HWCVsyncCoordinator> const& coordinator);
2901
2902
2903=== modified file 'src/platform/graphics/android/hwc_layerlist.cpp'
2904--- src/platform/graphics/android/hwc_layerlist.cpp 2014-06-04 23:06:47 +0000
2905+++ src/platform/graphics/android/hwc_layerlist.cpp 2014-07-11 20:27:44 +0000
2906@@ -51,13 +51,16 @@
2907 }
2908 }
2909
2910-bool mga::LayerList::update_list_and_check_if_changed(
2911- RenderableList const& renderlist,
2912- size_t additional_layers)
2913+mga::HwcLayerEntry::HwcLayerEntry(HWCLayer && layer, bool needs_commit) :
2914+ layer(std::move(layer)),
2915+ needs_commit{needs_commit}
2916+{
2917+}
2918+
2919+void mga::LayerList::update_list(RenderableList const& renderlist, size_t additional_layers)
2920 {
2921 size_t needed_size = renderlist.size() + additional_layers;
2922
2923- bool any_buffer_updated = false;
2924 if ((!hwc_representation) || hwc_representation->numHwLayers != needed_size)
2925 {
2926 hwc_representation = generate_hwc_list(needed_size);
2927@@ -65,21 +68,20 @@
2928
2929 if (layers.size() == needed_size)
2930 {
2931- auto layers_it = layers.begin();
2932+ auto it = layers.begin();
2933 for(auto renderable : renderlist)
2934 {
2935- layers_it->set_render_parameters(
2936- renderable->screen_position(), renderable->alpha_enabled());
2937- layers_it->set_buffer(*renderable->buffer());
2938- any_buffer_updated |= layers_it->needs_hwc_commit();
2939- layers_it->set_layer_type(mga::LayerType::gl_rendered);
2940- layers_it++;
2941+ it->needs_commit = it->layer.setup_layer(
2942+ mga::LayerType::gl_rendered,
2943+ renderable->screen_position(),
2944+ renderable->alpha_enabled(),
2945+ *renderable->buffer());
2946+ it++;
2947 }
2948 }
2949 else
2950 {
2951- any_buffer_updated = true;
2952- std::list<HWCLayer> new_layers;
2953+ std::list<HwcLayerEntry> new_layers;
2954 auto i = 0u;
2955 for(auto const& renderable : renderlist)
2956 {
2957@@ -88,13 +90,13 @@
2958 mga::LayerType::gl_rendered,
2959 renderable->screen_position(),
2960 renderable->alpha_enabled(),
2961- hwc_representation, i++));
2962- new_layers.back().set_buffer(*renderable->buffer());
2963+ *renderable->buffer(),
2964+ hwc_representation, i++), true);
2965 }
2966
2967 for(; i < needed_size; i++)
2968 {
2969- new_layers.emplace_back(mga::HWCLayer(hwc_representation, i));
2970+ new_layers.emplace_back(mga::HWCLayer(hwc_representation, i), false);
2971 }
2972 layers = std::move(new_layers);
2973 }
2974@@ -108,21 +110,19 @@
2975 first_additional_layer = layers.begin();
2976 std::advance(first_additional_layer, renderlist.size());
2977 }
2978-
2979- return any_buffer_updated;
2980 }
2981
2982-std::list<mga::HWCLayer>::iterator mga::LayerList::begin()
2983+std::list<mga::HwcLayerEntry>::iterator mga::LayerList::begin()
2984 {
2985 return layers.begin();
2986 }
2987
2988-std::list<mga::HWCLayer>::iterator mga::LayerList::additional_layers_begin()
2989+std::list<mga::HwcLayerEntry>::iterator mga::LayerList::additional_layers_begin()
2990 {
2991 return first_additional_layer;
2992 }
2993
2994-std::list<mga::HWCLayer>::iterator mga::LayerList::end()
2995+std::list<mga::HwcLayerEntry>::iterator mga::LayerList::end()
2996 {
2997 return layers.end();
2998 }
2999@@ -141,6 +141,6 @@
3000 RenderableList const& renderlist,
3001 size_t additional_layers)
3002 {
3003- update_list_and_check_if_changed(renderlist, additional_layers);
3004+ update_list(renderlist, additional_layers);
3005 }
3006
3007
3008=== modified file 'src/platform/graphics/android/hwc_layerlist.h'
3009--- src/platform/graphics/android/hwc_layerlist.h 2014-03-26 05:48:59 +0000
3010+++ src/platform/graphics/android/hwc_layerlist.h 2014-07-11 20:27:44 +0000
3011@@ -39,6 +39,13 @@
3012 namespace android
3013 {
3014
3015+struct HwcLayerEntry
3016+{
3017+ HwcLayerEntry(HWCLayer && layer, bool needs_commit);
3018+ HWCLayer layer;
3019+ bool needs_commit;
3020+};
3021+
3022 /* this is a partitioned list. renderlist makes up the first renderlist.size() elements
3023 of the list, and there are additional_layers added to the end.
3024 std::distance(begin(), additional_layers_begin()) == renderlist.size()
3025@@ -49,13 +56,11 @@
3026 {
3027 public:
3028 LayerList(RenderableList const& renderlist, size_t additional_layers);
3029- bool update_list_and_check_if_changed(
3030- RenderableList const& renderlist,
3031- size_t additional_layers);
3032+ void update_list(RenderableList const& renderlist, size_t additional_layers);
3033
3034- std::list<HWCLayer>::iterator begin();
3035- std::list<HWCLayer>::iterator additional_layers_begin();
3036- std::list<HWCLayer>::iterator end();
3037+ std::list<HwcLayerEntry>::iterator begin();
3038+ std::list<HwcLayerEntry>::iterator additional_layers_begin();
3039+ std::list<HwcLayerEntry>::iterator end();
3040
3041 std::weak_ptr<hwc_display_contents_1_t> native_list();
3042 NativeFence retirement_fence();
3043@@ -63,9 +68,9 @@
3044 LayerList& operator=(LayerList const&) = delete;
3045 LayerList(LayerList const&) = delete;
3046
3047- std::list<HWCLayer> layers;
3048+ std::list<HwcLayerEntry> layers;
3049 std::shared_ptr<hwc_display_contents_1_t> hwc_representation;
3050- std::list<HWCLayer>::iterator first_additional_layer;
3051+ std::list<HwcLayerEntry>::iterator first_additional_layer;
3052 };
3053
3054 }
3055
3056=== modified file 'src/platform/graphics/android/hwc_layers.cpp'
3057--- src/platform/graphics/android/hwc_layers.cpp 2014-06-21 02:09:15 +0000
3058+++ src/platform/graphics/android/hwc_layers.cpp 2014-07-11 20:27:44 +0000
3059@@ -55,8 +55,7 @@
3060
3061 mga::HWCLayer::HWCLayer(std::shared_ptr<hwc_display_contents_1_t> list, size_t layer_index)
3062 : hwc_layer(&list->hwLayers[layer_index]),
3063- hwc_list(list),
3064- associated_buffer(nullptr) //todo: take this as a constructor param
3065+ hwc_list(list)
3066 {
3067 memset(hwc_layer, 0, sizeof(hwc_layer_1_t));
3068 memset(&visible_rect, 0, sizeof(hwc_rect_t));
3069@@ -74,34 +73,40 @@
3070
3071 mga::HWCLayer::HWCLayer(
3072 LayerType type,
3073- geometry::Rectangle position,
3074+ geometry::Rectangle const& position,
3075 bool alpha_enabled,
3076+ Buffer const& buffer,
3077 std::shared_ptr<hwc_display_contents_1_t> list,
3078 size_t layer_index)
3079 : HWCLayer(list, layer_index)
3080 {
3081- set_layer_type(type);
3082- set_render_parameters(position, alpha_enabled);
3083+ setup_layer(type, position, alpha_enabled, buffer);
3084 }
3085
3086 bool mga::HWCLayer::needs_gl_render() const
3087 {
3088- return ((hwc_layer->compositionType == HWC_FRAMEBUFFER) || (hwc_layer->flags == HWC_SKIP_LAYER));
3089+ return (hwc_layer->compositionType == HWC_FRAMEBUFFER);
3090 }
3091
3092-void mga::HWCLayer::update_fence_and_release_buffer()
3093+void mga::HWCLayer::update_from_releasefence(mg::Buffer const& buffer)
3094 {
3095 if (hwc_layer->compositionType != HWC_FRAMEBUFFER)
3096 {
3097- associated_buffer->update_usage(hwc_layer->releaseFenceFd, mga::BufferAccess::read);
3098+ auto const& native_buffer = buffer.native_buffer_handle();
3099+ native_buffer->update_usage(hwc_layer->releaseFenceFd, mga::BufferAccess::read);
3100 hwc_layer->releaseFenceFd = -1;
3101 hwc_layer->acquireFenceFd = -1;
3102- associated_buffer.reset();
3103 }
3104 }
3105
3106-void mga::HWCLayer::set_layer_type(LayerType type)
3107+bool mga::HWCLayer::setup_layer(
3108+ LayerType type,
3109+ geometry::Rectangle const& position,
3110+ bool alpha_enabled,
3111+ Buffer const& buffer)
3112 {
3113+ bool needs_commit = needs_gl_render();
3114+
3115 hwc_layer->flags = 0;
3116 switch(type)
3117 {
3118@@ -122,10 +127,7 @@
3119 default:
3120 BOOST_THROW_EXCEPTION(std::logic_error("invalid layer type"));
3121 }
3122-}
3123
3124-void mga::HWCLayer::set_render_parameters(geometry::Rectangle position, bool alpha_enabled)
3125-{
3126 if (alpha_enabled)
3127 hwc_layer->blending = HWC_BLENDING_PREMULT;
3128 else
3129@@ -141,45 +143,31 @@
3130 position.bottom_right().x.as_int(),
3131 position.bottom_right().y.as_int()
3132 };
3133-
3134- visible_rect = hwc_layer->displayFrame;
3135-}
3136-
3137-void mga::HWCLayer::set_buffer(Buffer const& buffer)
3138-{
3139- associated_buffer.reset();
3140- associated_buffer = buffer.native_buffer_handle();
3141- updated = (hwc_layer->handle != associated_buffer->handle());
3142-
3143- hwc_layer->handle = associated_buffer->handle();
3144 hwc_layer->sourceCrop =
3145 {
3146 0, 0,
3147- associated_buffer->anwb()->width,
3148- associated_buffer->anwb()->height
3149+ buffer.size().width.as_int(),
3150+ buffer.size().height.as_int()
3151 };
3152+
3153+ visible_rect = hwc_layer->displayFrame;
3154+
3155+ auto const& native_buffer = buffer.native_buffer_handle();
3156+ needs_commit |= (hwc_layer->handle != native_buffer->handle());
3157+ hwc_layer->handle = native_buffer->handle();
3158+
3159+ return needs_commit;
3160 }
3161
3162-void mga::HWCLayer::prepare_for_draw()
3163+void mga::HWCLayer::set_acquirefence_from(mg::Buffer const& buffer)
3164 {
3165+ hwc_layer->releaseFenceFd = -1;
3166+ hwc_layer->acquireFenceFd = -1;
3167 //we shouldn't be copying the FD unless the HWC has marked this as a buffer its interested in.
3168 //we disregard fences that haven't changed, as the hwc will still own the buffer
3169- if (updated && (((hwc_layer->compositionType == HWC_OVERLAY) ||
3170- (hwc_layer->compositionType == HWC_FRAMEBUFFER_TARGET))))
3171- {
3172- hwc_layer->acquireFenceFd = associated_buffer->copy_fence();
3173- }
3174- //the HWC is not interested in this buffer. we can release the buffer.
3175- else if (hwc_layer->compositionType == HWC_FRAMEBUFFER)
3176- {
3177- hwc_layer->acquireFenceFd = -1;
3178- associated_buffer.reset();
3179- }
3180-
3181- hwc_layer->releaseFenceFd = -1;
3182-}
3183-
3184-bool mga::HWCLayer::needs_hwc_commit() const
3185-{
3186- return (updated || needs_gl_render());
3187+ if (!needs_gl_render())
3188+ {
3189+ auto const& native_buffer = buffer.native_buffer_handle();
3190+ hwc_layer->acquireFenceFd = native_buffer->copy_fence();
3191+ }
3192 }
3193
3194=== modified file 'src/platform/graphics/android/hwc_layers.h'
3195--- src/platform/graphics/android/hwc_layers.h 2014-06-16 21:16:14 +0000
3196+++ src/platform/graphics/android/hwc_layers.h 2014-07-11 20:27:44 +0000
3197@@ -50,11 +50,15 @@
3198 class HWCLayer
3199 {
3200 public:
3201- HWCLayer(std::shared_ptr<hwc_display_contents_1_t> list, size_t layer_index);
3202- HWCLayer(LayerType,
3203- geometry::Rectangle screen_position,
3204- bool alpha_enabled,
3205- std::shared_ptr<hwc_display_contents_1_t> list, size_t layer_index);
3206+ HWCLayer(
3207+ std::shared_ptr<hwc_display_contents_1_t> list,
3208+ size_t layer_index);
3209+ HWCLayer(
3210+ LayerType,
3211+ geometry::Rectangle const& screen_position,
3212+ bool alpha_enabled,
3213+ Buffer const& buffer,
3214+ std::shared_ptr<hwc_display_contents_1_t> list, size_t layer_index);
3215
3216 HWCLayer& operator=(HWCLayer && layer);
3217 HWCLayer(HWCLayer && layer);
3218@@ -62,20 +66,18 @@
3219 HWCLayer& operator=(HWCLayer const& layer) = delete;
3220 HWCLayer(HWCLayer const& layer) = delete;
3221
3222- void set_layer_type(LayerType type);
3223- void set_render_parameters(geometry::Rectangle screen_position, bool alpha_enabled);
3224- void set_buffer(Buffer const& buffer);
3225-
3226- void update_fence_and_release_buffer();
3227+ bool setup_layer(
3228+ LayerType type,
3229+ geometry::Rectangle const& position,
3230+ bool alpha_enabled,
3231+ Buffer const& buffer);
3232 bool needs_gl_render() const;
3233- bool needs_hwc_commit() const;
3234- void prepare_for_draw();
3235+ void set_acquirefence_from(Buffer const& buffer);
3236+ void update_from_releasefence(Buffer const& buffer);
3237 private:
3238 hwc_layer_1_t* hwc_layer;
3239 std::shared_ptr<hwc_display_contents_1_t> hwc_list;
3240 hwc_rect_t visible_rect;
3241- std::shared_ptr<NativeBuffer> associated_buffer;
3242- bool updated{false};
3243 };
3244 }
3245 }
3246
3247=== modified file 'src/platform/graphics/android/hwc_wrapper.h'
3248--- src/platform/graphics/android/hwc_wrapper.h 2014-03-19 21:56:42 +0000
3249+++ src/platform/graphics/android/hwc_wrapper.h 2014-07-11 20:27:44 +0000
3250@@ -27,6 +27,7 @@
3251 {
3252 namespace android
3253 {
3254+struct HWCCallbacks;
3255 class HwcWrapper
3256 {
3257 public:
3258@@ -34,6 +35,11 @@
3259
3260 virtual void prepare(hwc_display_contents_1_t&) const = 0;
3261 virtual void set(hwc_display_contents_1_t&) const = 0;
3262+ virtual void register_hooks(hwc_procs_t* callbacks) const = 0;
3263+ virtual void vsync_signal_on() const = 0;
3264+ virtual void vsync_signal_off() const = 0;
3265+ virtual void display_on() const = 0;
3266+ virtual void display_off() const = 0;
3267
3268 protected:
3269 HwcWrapper() = default;
3270
3271=== modified file 'src/platform/graphics/android/real_hwc_wrapper.cpp'
3272--- src/platform/graphics/android/real_hwc_wrapper.cpp 2014-03-26 05:48:59 +0000
3273+++ src/platform/graphics/android/real_hwc_wrapper.cpp 2014-07-11 20:27:44 +0000
3274@@ -60,3 +60,48 @@
3275 BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
3276 }
3277 }
3278+
3279+void mga::RealHwcWrapper::register_hooks(hwc_procs_t* callbacks) const
3280+{
3281+ hwc_device->registerProcs(hwc_device.get(), callbacks);
3282+}
3283+
3284+void mga::RealHwcWrapper::vsync_signal_on() const
3285+{
3286+ if (auto rc = hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 1))
3287+ {
3288+ std::stringstream ss;
3289+ ss << "error turning vsync signal on. rc = " << std::hex << rc;
3290+ BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
3291+ }
3292+}
3293+
3294+void mga::RealHwcWrapper::vsync_signal_off() const
3295+{
3296+ if (auto rc = hwc_device->eventControl(hwc_device.get(), 0, HWC_EVENT_VSYNC, 0))
3297+ {
3298+ std::stringstream ss;
3299+ ss << "error turning vsync signal off. rc = " << std::hex << rc;
3300+ BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
3301+ }
3302+}
3303+
3304+void mga::RealHwcWrapper::display_on() const
3305+{
3306+ if (auto rc = hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 0))
3307+ {
3308+ std::stringstream ss;
3309+ ss << "error turning display on. rc = " << std::hex << rc;
3310+ BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
3311+ }
3312+}
3313+
3314+void mga::RealHwcWrapper::display_off() const
3315+{
3316+ if (auto rc = hwc_device->blank(hwc_device.get(), HWC_DISPLAY_PRIMARY, 1))
3317+ {
3318+ std::stringstream ss;
3319+ ss << "error turning display off. rc = " << std::hex << rc;
3320+ BOOST_THROW_EXCEPTION(std::runtime_error(ss.str()));
3321+ }
3322+}
3323
3324=== modified file 'src/platform/graphics/android/real_hwc_wrapper.h'
3325--- src/platform/graphics/android/real_hwc_wrapper.h 2014-03-26 05:48:59 +0000
3326+++ src/platform/graphics/android/real_hwc_wrapper.h 2014-07-11 20:27:44 +0000
3327@@ -39,6 +39,11 @@
3328
3329 void prepare(hwc_display_contents_1_t&) const override;
3330 void set(hwc_display_contents_1_t&) const override;
3331+ void register_hooks(hwc_procs_t* callbacks) const override;
3332+ void vsync_signal_on() const override;
3333+ void vsync_signal_off() const override;
3334+ void display_on() const override;
3335+ void display_off() const override;
3336 private:
3337 static size_t const num_displays{3}; //primary, external, virtual
3338 std::shared_ptr<hwc_composer_device_1> const hwc_device;
3339
3340=== modified file 'src/platform/graphics/android/resource_factory.cpp'
3341--- src/platform/graphics/android/resource_factory.cpp 2014-06-02 19:36:02 +0000
3342+++ src/platform/graphics/android/resource_factory.cpp 2014-07-11 20:27:44 +0000
3343@@ -100,7 +100,7 @@
3344 auto syncer = std::make_shared<mga::HWCVsync>();
3345 auto file_ops = std::make_shared<mga::RealSyncFileOps>();
3346 auto wrapper = std::make_shared<mga::RealHwcWrapper>(hwc_native_device, logger);
3347- return std::make_shared<mga::HwcDevice>(hwc_native_device, wrapper, syncer, file_ops);
3348+ return std::make_shared<mga::HwcDevice>(wrapper, syncer, file_ops);
3349 }
3350
3351 std::shared_ptr<mga::DisplayDevice> mga::ResourceFactory::create_hwc_fb_device(
3352@@ -109,5 +109,5 @@
3353 {
3354 auto syncer = std::make_shared<mga::HWCVsync>();
3355 auto wrapper = std::make_shared<mga::RealHwcWrapper>(hwc_native_device, logger);
3356- return std::make_shared<mga::HwcFbDevice>(hwc_native_device, wrapper, fb_native_device, syncer);
3357+ return std::make_shared<mga::HwcFbDevice>(wrapper, fb_native_device, syncer);
3358 }
3359
3360=== modified file 'src/platform/graphics/mesa/cursor.cpp'
3361--- src/platform/graphics/mesa/cursor.cpp 2014-06-17 22:07:15 +0000
3362+++ src/platform/graphics/mesa/cursor.cpp 2014-07-11 20:27:44 +0000
3363@@ -35,8 +35,8 @@
3364
3365 namespace
3366 {
3367-int const width = 64;
3368-int const height = 64;
3369+int const buffer_width = 64;
3370+int const buffer_height = 64;
3371
3372 // Transforms a relative position within the display bounds described by \a rect which is rotated with \a orientation
3373 geom::Displacement transform(geom::Rectangle const& rect, geom::Displacement const& vector, MirOrientation orientation)
3374@@ -59,8 +59,8 @@
3375 mgm::Cursor::GBMBOWrapper::GBMBOWrapper(gbm_device* gbm) :
3376 buffer(gbm_bo_create(
3377 gbm,
3378- width,
3379- height,
3380+ buffer_width,
3381+ buffer_height,
3382 GBM_FORMAT_ARGB8888,
3383 GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
3384 {
3385@@ -82,8 +82,6 @@
3386 current_configuration(current_configuration)
3387 {
3388 show(*initial_image);
3389-
3390- resume();
3391 }
3392
3393 mgm::Cursor::~Cursor() noexcept
3394@@ -91,19 +89,9 @@
3395 hide();
3396 }
3397
3398-void mgm::Cursor::show(CursorImage const& cursor_image)
3399+void mgm::Cursor::write_buffer_data_locked(std::lock_guard<std::mutex> const&, void const* data, size_t count)
3400 {
3401- std::lock_guard<std::mutex> lg(guard);
3402- visible = true;
3403-
3404- auto const& size = cursor_image.size();
3405-
3406- if (size != geometry::Size{width, height})
3407- BOOST_THROW_EXCEPTION(std::logic_error("No support for cursors that aren't 64x64"));
3408-
3409- auto const count = size.width.as_uint32_t() * size.height.as_uint32_t() * sizeof(uint32_t);
3410-
3411- if (auto result = gbm_bo_write(buffer, cursor_image.as_argb_8888(), count))
3412+ if (auto result = gbm_bo_write(buffer, data, count))
3413 {
3414 BOOST_THROW_EXCEPTION(
3415 ::boost::enable_error_info(std::runtime_error("failed to initialize gbm buffer"))
3416@@ -111,6 +99,58 @@
3417 }
3418 }
3419
3420+void mgm::Cursor::pad_and_write_image_data_locked(std::lock_guard<std::mutex> const& lg, CursorImage const& image)
3421+{
3422+ uint32_t const* image_argb = static_cast<uint32_t const*>(image.as_argb_8888());
3423+ auto image_width = image.size().width.as_uint32_t();
3424+ auto image_height = image.size().height.as_uint32_t();
3425+
3426+ if (image_width > buffer_width || image_height > buffer_height)
3427+ {
3428+ BOOST_THROW_EXCEPTION(std::logic_error("Image is too big for GBM cursor buffer"));
3429+ }
3430+
3431+ uint32_t pixels[buffer_width*buffer_height] {};
3432+ // 'pixels' is initialized to transparent so we just need to copy the initial image
3433+ // in to the top left corner.
3434+ for (unsigned int i = 0; i < image_height; i++)
3435+ {
3436+ for (unsigned int j = 0; j < image_width; j++)
3437+ {
3438+ pixels[buffer_width*i+j] = image_argb[image_width*i + j];
3439+ }
3440+ }
3441+
3442+ auto const count = buffer_width * buffer_height * sizeof(uint32_t);
3443+ write_buffer_data_locked(lg, pixels, count);
3444+}
3445+
3446+void mgm::Cursor::show(CursorImage const& cursor_image)
3447+{
3448+ std::lock_guard<std::mutex> lg(guard);
3449+
3450+ auto const& size = cursor_image.size();
3451+
3452+ if (size != geometry::Size{buffer_width, buffer_height})
3453+ {
3454+ pad_and_write_image_data_locked(lg, cursor_image);
3455+ }
3456+ else
3457+ {
3458+ auto const count = size.width.as_uint32_t() * size.height.as_uint32_t() * sizeof(uint32_t);
3459+ write_buffer_data_locked(lg, cursor_image.as_argb_8888(), count);
3460+ }
3461+ hotspot = cursor_image.hotspot();
3462+
3463+ // The hotspot may have changed so we need to call drmModeSetCursor again if the cursor was already visible.
3464+ if (visible)
3465+ place_cursor_at_locked(lg, current_position, ForceState);
3466+
3467+ // Writing the data could throw an exception so lets
3468+ // hold off on setting visible until after we have succeeded.
3469+ visible = true;
3470+}
3471+
3472 void mgm::Cursor::move_to(geometry::Point position)
3473 {
3474 place_cursor_at(position, UpdateState);
3475@@ -162,6 +202,14 @@
3476 ForceCursorState force_state)
3477 {
3478 std::lock_guard<std::mutex> lg(guard);
3479+ place_cursor_at_locked(lg, position, force_state);
3480+}
3481+
3482+void mgm::Cursor::place_cursor_at_locked(
3483+ std::lock_guard<std::mutex> const&,
3484+ geometry::Point position,
3485+ ForceCursorState force_state)
3486+{
3487
3488 current_position = position;
3489
3490@@ -173,10 +221,15 @@
3491 if (output_rect.contains(position))
3492 {
3493 auto dp = transform(output_rect, position - output_rect.top_left, orientation);
3494- output.move_cursor({dp.dx.as_int(), dp.dy.as_int()});
3495+
3496+ // It's a little strange that we implement hotspot this way as there is
3497+ // drmModeSetCursor2 with hotspot support. However it appears to not actually
3498+ // work on radeon and intel. There also seems to be precedent in weston for
3499+ // implementing hotspot in this fashion.
3500+ output.move_cursor(geom::Point{dp.dx.as_int(), dp.dy.as_int()} - hotspot);
3501 if (force_state || !output.has_cursor()) // TODO - or if orientation had changed - then set buffer..
3502 {
3503- output.set_cursor(buffer);// TODO - select rotated buffer image
3504+ output.set_cursor(buffer);
3505 }
3506 }
3507 else
3508
3509=== modified file 'src/platform/graphics/mesa/cursor.h'
3510--- src/platform/graphics/mesa/cursor.h 2014-06-17 22:07:15 +0000
3511+++ src/platform/graphics/mesa/cursor.h 2014-07-11 20:27:44 +0000
3512@@ -21,6 +21,9 @@
3513 #define MIR_GRAPHICS_MESA_CURSOR_H_
3514
3515 #include "mir/graphics/cursor.h"
3516+#include "mir/geometry/point.h"
3517+#include "mir/geometry/displacement.h"
3518+
3519 #include "mir_toolkit/common.h"
3520
3521 #include <gbm.h>
3522@@ -82,11 +85,16 @@
3523 enum ForceCursorState { UpdateState, ForceState };
3524 void for_each_used_output(std::function<void(KMSOutput&, geometry::Rectangle const&, MirOrientation orientation)> const& f);
3525 void place_cursor_at(geometry::Point position, ForceCursorState force_state);
3526+ void place_cursor_at_locked(std::lock_guard<std::mutex> const&, geometry::Point position, ForceCursorState force_state);
3527+ void write_buffer_data_locked(std::lock_guard<std::mutex> const&, void const* data, size_t count);
3528+ void pad_and_write_image_data_locked(std::lock_guard<std::mutex> const&, CursorImage const& image);
3529
3530 std::mutex guard;
3531
3532 KMSOutputContainer& output_container;
3533 geometry::Point current_position;
3534+ geometry::Displacement hotspot;
3535+
3536 bool visible;
3537
3538 struct GBMBOWrapper
3539
3540=== modified file 'src/platform/graphics/mesa/display_buffer.cpp'
3541--- src/platform/graphics/mesa/display_buffer.cpp 2014-06-10 14:40:23 +0000
3542+++ src/platform/graphics/mesa/display_buffer.cpp 2014-07-11 20:27:44 +0000
3543@@ -303,7 +303,7 @@
3544 * the next frame, but not for bypass frames. Deferring the flip of
3545 * bypass frames would increase the time we held
3546 * last_flipped_bypass_buf unacceptably, resulting in client stuttering
3547- * unless we allocate quad-buffers (which I'm trying to avoid).
3548+ * unless we allocate more buffers (which I'm trying to avoid).
3549 * Also, bypass does not need the deferred page flip because it has
3550 * no compositing/rendering step for which to save time for.
3551 */
3552
3553=== modified file 'src/platform/options/default_configuration.cpp'
3554--- src/platform/options/default_configuration.cpp 2014-04-15 14:47:19 +0000
3555+++ src/platform/options/default_configuration.cpp 2014-07-11 20:27:44 +0000
3556@@ -26,6 +26,7 @@
3557 namespace mo = mir::options;
3558
3559 char const* const mo::server_socket_opt = "file,f";
3560+char const* const mo::prompt_socket_opt = "prompt-file,p";
3561 char const* const mo::no_server_socket_opt = "no-file";
3562 char const* const mo::enable_input_opt = "enable-input,i";
3563 char const* const mo::session_mediator_report_opt = "session-mediator-report";
3564@@ -77,6 +78,7 @@
3565 (server_socket_opt, po::value<std::string>()->default_value(::mir::default_server_socket),
3566 "Socket filename [string:default=$XDG_RUNTIME_DIR/mir_socket or /tmp/mir_socket]")
3567 (no_server_socket_opt, "Do not provide a socket filename for client connections")
3568+ (prompt_socket_opt, "Provide a \"..._trusted\" filename for prompt helper connections")
3569 (platform_graphics_lib, po::value<std::string>()->default_value(default_platform_graphics_lib),
3570 "Library to use for platform graphics support")
3571 (enable_input_opt, po::value<bool>()->default_value(enable_input_default),
3572
3573=== modified file 'src/server/CMakeLists.txt'
3574--- src/server/CMakeLists.txt 2014-06-25 07:27:23 +0000
3575+++ src/server/CMakeLists.txt 2014-07-11 20:27:44 +0000
3576@@ -30,6 +30,7 @@
3577 display_server.cpp
3578 default_server_configuration.cpp
3579 asio_main_loop.cpp
3580+ default_emergency_cleanup.cpp
3581 )
3582
3583 set(MIRSERVER_LINKAGE SHARED)
3584@@ -47,9 +48,10 @@
3585 mirsharedinput
3586 mirsharedgeometry
3587 mirsharedlogging
3588+ mirsharedfd
3589 mirsharedenv
3590 mirsharedsharedlibrary
3591- mirsharedthreadname
3592+ mirsharedthread
3593 mirshell
3594 mirscene
3595 mirtime
3596@@ -65,6 +67,7 @@
3597 mirplatform
3598 mirclient
3599 3rd_party
3600+ xcursorloader
3601 ${EGL_LDFLAGS} ${EGL_LIBRARIES}
3602 ${GLESv2_LDFLAGS} ${GLESv2_LIBRARIES}
3603 ${UDEV_LDFLAGS} ${UDEV_LIBRARIES}
3604
3605=== modified file 'src/server/asio_main_loop.cpp'
3606--- src/server/asio_main_loop.cpp 2014-06-27 07:07:35 +0000
3607+++ src/server/asio_main_loop.cpp 2014-07-11 20:27:44 +0000
3608@@ -352,7 +352,9 @@
3609 {
3610 }
3611
3612- std::recursive_mutex m;
3613+ std::mutex m;
3614+ int callbacks_running = 0;
3615+ std::condition_variable callback_done;
3616 std::function<void(void)> const callback;
3617 State state;
3618 };
3619@@ -381,7 +383,12 @@
3620 if (data->state == mir::time::Alarm::pending)
3621 {
3622 data->state = mir::time::Alarm::triggered;
3623+ ++data->callbacks_running;
3624+ lock.unlock();
3625 data->callback();
3626+ lock.lock();
3627+ --data->callbacks_running;
3628+ data->callback_done.notify_all();
3629 }
3630 }
3631 }
3632@@ -420,7 +427,11 @@
3633
3634 bool AlarmImpl::cancel()
3635 {
3636- std::lock_guard<decltype(data->m)> lock(data->m);
3637+ std::unique_lock<decltype(data->m)> lock(data->m);
3638+
3639+ while (data->callbacks_running > 0)
3640+ data->callback_done.wait(lock);
3641+
3642 if (data->state == triggered)
3643 return false;
3644
3645
3646=== modified file 'src/server/compositor/buffer_queue.cpp'
3647--- src/server/compositor/buffer_queue.cpp 2014-06-12 15:35:08 +0000
3648+++ src/server/compositor/buffer_queue.cpp 2014-07-11 20:27:44 +0000
3649@@ -245,6 +245,10 @@
3650 current_buffer_users.push_back(user_id);
3651 current_compositor_buffer = pop(ready_to_composite_queue);
3652 }
3653+ else if (current_buffer_users.empty())
3654+ { // current_buffer_users and ready_to_composite_queue both empty
3655+ current_buffer_users.push_back(user_id);
3656+ }
3657
3658 buffers_sent_to_compositor.push_back(current_compositor_buffer);
3659
3660
3661=== modified file 'src/server/compositor/buffer_queue.h'
3662--- src/server/compositor/buffer_queue.h 2014-06-12 15:35:08 +0000
3663+++ src/server/compositor/buffer_queue.h 2014-07-11 20:27:44 +0000
3664@@ -61,11 +61,11 @@
3665 int buffers_ready_for_compositor() const override;
3666 int buffers_free_for_client() const override;
3667 bool framedropping_allowed() const;
3668+ bool is_a_current_buffer_user(void const* user_id) const;
3669
3670 private:
3671 void give_buffer_to_client(graphics::Buffer* buffer,
3672 std::unique_lock<std::mutex> lock);
3673- bool is_a_current_buffer_user(void const* user_id) const;
3674 void release(graphics::Buffer* buffer,
3675 std::unique_lock<std::mutex> lock);
3676 void drop_frame(std::unique_lock<std::mutex> lock);
3677
3678=== modified file 'src/server/compositor/buffer_stream_factory.cpp'
3679--- src/server/compositor/buffer_stream_factory.cpp 2014-06-09 17:16:32 +0000
3680+++ src/server/compositor/buffer_stream_factory.cpp 2014-07-11 20:27:44 +0000
3681@@ -47,7 +47,7 @@
3682 std::shared_ptr<mc::BufferStream> mc::BufferStreamFactory::create_buffer_stream(
3683 mg::BufferProperties const& buffer_properties)
3684 {
3685- // Note: Framedropping and bypass both require a minimum 3 buffers
3686+ // Note: Framedropping requires a minimum 3 buffers
3687 auto switching_bundle = std::make_shared<mc::BufferQueue>(3, gralloc, buffer_properties, *policy_factory);
3688 return std::make_shared<mc::BufferStreamSurfaces>(switching_bundle);
3689 }
3690
3691=== added file 'src/server/default_emergency_cleanup.cpp'
3692--- src/server/default_emergency_cleanup.cpp 1970-01-01 00:00:00 +0000
3693+++ src/server/default_emergency_cleanup.cpp 2014-07-11 20:27:44 +0000
3694@@ -0,0 +1,46 @@
3695+/*
3696+ * Copyright © 2014 Canonical Ltd.
3697+ *
3698+ * This program is free software: you can redistribute it and/or modify it
3699+ * under the terms of the GNU General Public License version 3,
3700+ * as published by the Free Software Foundation.
3701+ *
3702+ * This program is distributed in the hope that it will be useful,
3703+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3704+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3705+ * GNU General Public License for more details.
3706+ *
3707+ * You should have received a copy of the GNU General Public License
3708+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3709+ *
3710+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
3711+ */
3712+
3713+#include "default_emergency_cleanup.h"
3714+
3715+void mir::DefaultEmergencyCleanup::add(EmergencyCleanupHandler const& handler)
3716+{
3717+ std::lock_guard<std::mutex> lock{handlers_mutex};
3718+
3719+ last_item()->next.reset(new ListItem{handler, nullptr});
3720+ ++num_handlers;
3721+}
3722+
3723+void mir::DefaultEmergencyCleanup::operator()() const
3724+{
3725+ int handlers_left = num_handlers;
3726+ ListItem const* item = &head;
3727+ while (handlers_left-- > 0)
3728+ {
3729+ item = item->next.get();
3730+ item->handler();
3731+ }
3732+}
3733+
3734+mir::DefaultEmergencyCleanup::ListItem* mir::DefaultEmergencyCleanup::last_item()
3735+{
3736+ ListItem* item = &head;
3737+ while (item->next)
3738+ item = item->next.get();
3739+ return item;
3740+}
3741
3742=== added file 'src/server/default_emergency_cleanup.h'
3743--- src/server/default_emergency_cleanup.h 1970-01-01 00:00:00 +0000
3744+++ src/server/default_emergency_cleanup.h 2014-07-11 20:27:44 +0000
3745@@ -0,0 +1,53 @@
3746+/*
3747+ * Copyright © 2014 Canonical Ltd.
3748+ *
3749+ * This program is free software: you can redistribute it and/or modify it
3750+ * under the terms of the GNU General Public License version 3,
3751+ * as published by the Free Software Foundation.
3752+ *
3753+ * This program is distributed in the hope that it will be useful,
3754+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3755+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3756+ * GNU General Public License for more details.
3757+ *
3758+ * You should have received a copy of the GNU General Public License
3759+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3760+ *
3761+ * Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
3762+ */
3763+
3764+#ifndef MIR_DEFAULT_EMERGENCY_CLEANUP_H_
3765+#define MIR_DEFAULT_EMERGENCY_CLEANUP_H_
3766+
3767+#include <mir/emergency_cleanup.h>
3768+
3769+#include <memory>
3770+#include <atomic>
3771+#include <mutex>
3772+
3773+namespace mir
3774+{
3775+
3776+class DefaultEmergencyCleanup : public EmergencyCleanup
3777+{
3778+public:
3779+ void add(EmergencyCleanupHandler const& handler) override;
3780+ void operator()() const override;
3781+
3782+private:
3783+ struct ListItem
3784+ {
3785+ EmergencyCleanupHandler handler;
3786+ std::unique_ptr<ListItem> next;
3787+ };
3788+
3789+ ListItem* last_item();
3790+
3791+ ListItem head;
3792+ std::atomic<int> num_handlers{0};
3793+ std::mutex handlers_mutex;
3794+};
3795+
3796+}
3797+
3798+#endif
3799
3800=== modified file 'src/server/default_server_configuration.cpp'
3801--- src/server/default_server_configuration.cpp 2014-06-17 22:07:15 +0000
3802+++ src/server/default_server_configuration.cpp 2014-07-11 20:27:44 +0000
3803@@ -38,10 +38,7 @@
3804 #include "mir/geometry/rectangles.h"
3805 #include "mir/default_configuration.h"
3806 #include "mir/scene/null_prompt_session_listener.h"
3807-
3808-#include <map>
3809-#include <vector>
3810-#include <mutex>
3811+#include "default_emergency_cleanup.h"
3812
3813 namespace mc = mir::compositor;
3814 namespace geom = mir::geometry;
3815@@ -139,6 +136,11 @@
3816 {
3817 return true;
3818 }
3819+
3820+ bool prompt_session_is_allowed(mf::SessionCredentials const& /* creds */) override
3821+ {
3822+ return true;
3823+ }
3824 };
3825 return session_authorizer(
3826 [&]()
3827@@ -147,6 +149,8 @@
3828 });
3829 }
3830
3831+mir::CachedPtr<mir::time::Clock> mir::DefaultServerConfiguration::clock;
3832+
3833 std::shared_ptr<mir::time::Clock> mir::DefaultServerConfiguration::the_clock()
3834 {
3835 return clock(
3836@@ -181,31 +185,6 @@
3837
3838 std::shared_ptr<mir::EmergencyCleanup> mir::DefaultServerConfiguration::the_emergency_cleanup()
3839 {
3840- struct DefaultEmergencyCleanup : public EmergencyCleanup
3841- {
3842- void add(EmergencyCleanupHandler const& handler) override
3843- {
3844- std::lock_guard<std::mutex> lock{handlers_mutex};
3845- handlers.push_back(handler);
3846- }
3847-
3848- void operator()() const override
3849- {
3850- decltype(handlers) handlers_copy;
3851-
3852- {
3853- std::unique_lock<std::mutex> lock{handlers_mutex};
3854- handlers_copy = handlers;
3855- }
3856-
3857- for (auto const& handler : handlers_copy)
3858- handler();
3859- }
3860-
3861- mutable std::mutex handlers_mutex;
3862- std::vector<EmergencyCleanupHandler> handlers;
3863- };
3864-
3865 return emergency_cleanup(
3866 []()
3867 {
3868
3869=== modified file 'src/server/display_server.cpp'
3870--- src/server/display_server.cpp 2014-06-03 11:04:15 +0000
3871+++ src/server/display_server.cpp 2014-07-11 20:27:44 +0000
3872@@ -77,6 +77,7 @@
3873 input_configuration{config.the_input_configuration()},
3874 compositor{config.the_compositor()},
3875 connector{config.the_connector()},
3876+ prompt_connector{config.the_prompt_connector()},
3877 input_manager{config.the_input_manager()},
3878 main_loop{config.the_main_loop()},
3879 server_status_listener{config.the_server_status_listener()},
3880@@ -112,6 +113,10 @@
3881 [this] { compositor->stop(); },
3882 [this] { compositor->start(); }};
3883
3884+ TryButRevertIfUnwinding prompt{
3885+ [this] { prompt_connector->stop(); },
3886+ [this] { prompt_connector->start(); }};
3887+
3888 TryButRevertIfUnwinding comm{
3889 [this] { connector->stop(); },
3890 [this] { connector->start(); }};
3891@@ -140,6 +145,10 @@
3892 [this] { connector->start(); },
3893 [this] { connector->stop(); }};
3894
3895+ TryButRevertIfUnwinding prompt{
3896+ [this] { prompt_connector->start(); },
3897+ [this] { prompt_connector->stop(); }};
3898+
3899 TryButRevertIfUnwinding display_config_processing{
3900 [this] { display_changer->resume_display_config_processing(); },
3901 [this] { display_changer->pause_display_config_processing(); }};
3902@@ -180,6 +189,7 @@
3903 std::shared_ptr<input::InputConfiguration> const input_configuration;
3904 std::shared_ptr<mc::Compositor> const compositor;
3905 std::shared_ptr<mf::Connector> const connector;
3906+ std::shared_ptr<mf::Connector> const prompt_connector;
3907 std::shared_ptr<mi::InputManager> const input_manager;
3908 std::shared_ptr<mir::MainLoop> const main_loop;
3909 std::shared_ptr<mir::ServerStatusListener> const server_status_listener;
3910@@ -203,6 +213,7 @@
3911 void mir::DisplayServer::run()
3912 {
3913 p->connector->start();
3914+ p->prompt_connector->start();
3915 p->compositor->start();
3916 p->input_manager->start();
3917 p->input_dispatcher->start();
3918@@ -214,6 +225,7 @@
3919 p->input_dispatcher->stop();
3920 p->input_manager->stop();
3921 p->compositor->stop();
3922+ p->prompt_connector->stop();
3923 p->connector->stop();
3924 }
3925
3926
3927=== modified file 'src/server/frontend/CMakeLists.txt'
3928--- src/server/frontend/CMakeLists.txt 2014-06-02 17:07:02 +0000
3929+++ src/server/frontend/CMakeLists.txt 2014-07-11 20:27:44 +0000
3930@@ -3,7 +3,9 @@
3931
3932 client_buffer_tracker.cpp
3933 connection_context.cpp
3934+ no_prompt_shell.cpp
3935 session_mediator.cpp
3936+ shell_wrapper.cpp
3937 protobuf_message_processor.cpp
3938 protobuf_responder.cpp
3939 protobuf_buffer_packer.cpp
3940
3941=== modified file 'src/server/frontend/default_configuration.cpp'
3942--- src/server/frontend/default_configuration.cpp 2014-06-17 22:07:15 +0000
3943+++ src/server/frontend/default_configuration.cpp 2014-07-11 20:27:44 +0000
3944@@ -23,6 +23,7 @@
3945 #include "published_socket_connector.h"
3946
3947 #include "mir/frontend/protobuf_connection_creator.h"
3948+#include "mir/frontend/session_authorizer.h"
3949 #include "mir/options/configuration.h"
3950 #include "mir/options/option.h"
3951
3952@@ -34,9 +35,10 @@
3953 {
3954 return connection_creator([this]
3955 {
3956+ auto const session_authorizer = the_session_authorizer();
3957 return std::make_shared<mf::ProtobufConnectionCreator>(
3958- the_ipc_factory(the_frontend_shell(), the_buffer_allocator()),
3959- the_session_authorizer(),
3960+ new_ipc_factory(session_authorizer),
3961+ session_authorizer,
3962 the_message_processor_report());
3963 });
3964 }
3965@@ -68,6 +70,72 @@
3966 });
3967 }
3968
3969+std::shared_ptr<mf::ConnectionCreator>
3970+mir::DefaultServerConfiguration::the_prompt_connection_creator()
3971+{
3972+ struct PromptSessionAuthorizer : public mf::SessionAuthorizer
3973+ {
3974+ bool connection_is_allowed(mf::SessionCredentials const& /* creds */) override
3975+ {
3976+ return true;
3977+ }
3978+
3979+ bool configure_display_is_allowed(mf::SessionCredentials const& /* creds */) override
3980+ {
3981+ return true;
3982+ }
3983+
3984+ bool screencast_is_allowed(mf::SessionCredentials const& /* creds */) override
3985+ {
3986+ return true;
3987+ }
3988+
3989+ bool prompt_session_is_allowed(mf::SessionCredentials const& /* creds */) override
3990+ {
3991+ return true;
3992+ }
3993+ };
3994+
3995+ return prompt_connection_creator([this]
3996+ {
3997+ auto const session_authorizer = std::make_shared<PromptSessionAuthorizer>();
3998+ return std::make_shared<mf::ProtobufConnectionCreator>(
3999+ new_ipc_factory(session_authorizer),
4000+ session_authorizer,
4001+ the_message_processor_report());
4002+ });
4003+}
4004+
4005+std::shared_ptr<mf::Connector>
4006+mir::DefaultServerConfiguration::the_prompt_connector()
4007+{
4008+ return prompt_connector(
4009+ [&,this]() -> std::shared_ptr<mf::Connector>
4010+ {
4011+ auto const threads = the_options()->get<int>(options::frontend_threads_opt);
4012+
4013+ if (the_options()->is_set(options::prompt_socket_opt))
4014+ {
4015+ return std::make_shared<mf::PublishedSocketConnector>(
4016+ the_socket_file() + "_trusted",
4017+ the_prompt_connection_creator(),
4018+ threads,
4019+ *the_emergency_cleanup(),
4020+ the_connector_report());
4021+ }
4022+ else
4023+ {
4024+ return std::make_shared<mf::BasicConnector>(
4025+ the_prompt_connection_creator(),
4026+ threads,
4027+ the_connector_report());
4028+ }
4029+ });
4030+}
4031+
4032+// TODO Remove after 0.5.0 is branched: the_ipc_factory() is used by
4033+// TODO clients that use the "PrivateProtobuf" but is it now deprecated
4034+// TODO and only retained as a migration aid.
4035 std::shared_ptr<mir::frontend::ProtobufIpcFactory>
4036 mir::DefaultServerConfiguration::the_ipc_factory(
4037 std::shared_ptr<mf::Shell> const& shell,
4038@@ -87,3 +155,18 @@
4039 the_cursor_images());
4040 });
4041 }
4042+
4043+std::shared_ptr<mir::frontend::ProtobufIpcFactory>
4044+mir::DefaultServerConfiguration::new_ipc_factory(
4045+ std::shared_ptr<mf::SessionAuthorizer> const& session_authorizer)
4046+{
4047+ return std::make_shared<mf::DefaultIpcFactory>(
4048+ the_frontend_shell(),
4049+ the_session_mediator_report(),
4050+ the_graphics_platform(),
4051+ the_frontend_display_changer(),
4052+ the_buffer_allocator(),
4053+ the_screencast(),
4054+ session_authorizer,
4055+ the_cursor_images());
4056+}
4057
4058=== modified file 'src/server/frontend/default_ipc_factory.cpp'
4059--- src/server/frontend/default_ipc_factory.cpp 2014-05-14 21:53:39 +0000
4060+++ src/server/frontend/default_ipc_factory.cpp 2014-07-11 20:27:44 +0000
4061@@ -18,6 +18,7 @@
4062
4063 #include "default_ipc_factory.h"
4064
4065+#include "no_prompt_shell.h"
4066 #include "session_mediator.h"
4067 #include "unauthorized_display_changer.h"
4068 #include "unauthorized_screencast.h"
4069@@ -27,6 +28,7 @@
4070
4071 namespace mf = mir::frontend;
4072 namespace mg = mir::graphics;
4073+namespace mi = mir::input;
4074
4075 mf::DefaultIpcFactory::DefaultIpcFactory(
4076 std::shared_ptr<Shell> const& shell,
4077@@ -36,8 +38,9 @@
4078 std::shared_ptr<mg::GraphicBufferAllocator> const& buffer_allocator,
4079 std::shared_ptr<Screencast> const& screencast,
4080 std::shared_ptr<SessionAuthorizer> const& session_authorizer,
4081- std::shared_ptr<mg::CursorImages> const& cursor_images) :
4082+ std::shared_ptr<mi::CursorImages> const& cursor_images) :
4083 shell(shell),
4084+ no_prompt_shell(std::make_shared<NoPromptShell>(shell)),
4085 sm_report(sm_report),
4086 cache(std::make_shared<ResourceCache>()),
4087 graphics_platform(graphics_platform),
4088@@ -75,8 +78,13 @@
4089 effective_screencast = std::make_shared<UnauthorizedScreencast>();
4090 }
4091
4092+ auto const allow_prompt_session =
4093+ session_authorizer->prompt_session_is_allowed(creds);
4094+
4095+ auto const effective_shell = allow_prompt_session ? shell : no_prompt_shell;
4096+
4097 return make_mediator(
4098- shell,
4099+ effective_shell,
4100 graphics_platform,
4101 changer,
4102 buffer_allocator,
4103@@ -100,7 +108,7 @@
4104 std::shared_ptr<EventSink> const& sink,
4105 std::shared_ptr<Screencast> const& effective_screencast,
4106 ConnectionContext const& connection_context,
4107- std::shared_ptr<mg::CursorImages> const& cursor_images)
4108+ std::shared_ptr<mi::CursorImages> const& cursor_images)
4109 {
4110 return std::make_shared<SessionMediator>(
4111 shell,
4112
4113=== modified file 'src/server/frontend/default_ipc_factory.h'
4114--- src/server/frontend/default_ipc_factory.h 2014-05-14 21:53:39 +0000
4115+++ src/server/frontend/default_ipc_factory.h 2014-07-11 20:27:44 +0000
4116@@ -27,6 +27,9 @@
4117 {
4118 class Platform;
4119 class GraphicBufferAllocator;
4120+}
4121+namespace input
4122+{
4123 class CursorImages;
4124 }
4125
4126@@ -49,7 +52,7 @@
4127 std::shared_ptr<graphics::GraphicBufferAllocator> const& buffer_allocator,
4128 std::shared_ptr<Screencast> const& screencast,
4129 std::shared_ptr<SessionAuthorizer> const& session_authorizer,
4130- std::shared_ptr<graphics::CursorImages> const& cursor_images);
4131+ std::shared_ptr<input::CursorImages> const& cursor_images);
4132
4133 std::shared_ptr<detail::DisplayServer> make_ipc_server(
4134 SessionCredentials const& creds,
4135@@ -67,10 +70,11 @@
4136 std::shared_ptr<EventSink> const& sink,
4137 std::shared_ptr<Screencast> const& effective_screencast,
4138 ConnectionContext const& connection_context,
4139- std::shared_ptr<graphics::CursorImages> const& cursor_images);
4140+ std::shared_ptr<input::CursorImages> const& cursor_images);
4141
4142 private:
4143 std::shared_ptr<Shell> const shell;
4144+ std::shared_ptr<Shell> const no_prompt_shell;
4145 std::shared_ptr<SessionMediatorReport> const sm_report;
4146 std::shared_ptr<ResourceCache> const cache;
4147 std::shared_ptr<graphics::Platform> const graphics_platform;
4148@@ -78,7 +82,7 @@
4149 std::shared_ptr<graphics::GraphicBufferAllocator> const buffer_allocator;
4150 std::shared_ptr<Screencast> const screencast;
4151 std::shared_ptr<SessionAuthorizer> const session_authorizer;
4152- std::shared_ptr<graphics::CursorImages> const cursor_images;
4153+ std::shared_ptr<input::CursorImages> const cursor_images;
4154 };
4155 }
4156 }
4157
4158=== added file 'src/server/frontend/no_prompt_shell.cpp'
4159--- src/server/frontend/no_prompt_shell.cpp 1970-01-01 00:00:00 +0000
4160+++ src/server/frontend/no_prompt_shell.cpp 2014-07-11 20:27:44 +0000
4161@@ -0,0 +1,56 @@
4162+/*
4163+ * Copyright © 2014 Canonical Ltd.
4164+ *
4165+ * This program is free software: you can redistribute it and/or modify it
4166+ * under the terms of the GNU General Public License version 3,
4167+ * as published by the Free Software Foundation.
4168+ *
4169+ * This program is distributed in the hope that it will be useful,
4170+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4171+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4172+ * GNU General Public License for more details.
4173+ *
4174+ * You should have received a copy of the GNU General Public License
4175+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4176+ *
4177+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
4178+ */
4179+
4180+#include "no_prompt_shell.h"
4181+
4182+#include <boost/throw_exception.hpp>
4183+#include <stdexcept>
4184+
4185+namespace mf = mir::frontend;
4186+
4187+namespace
4188+{
4189+char const* const prompt_sessions_disabled = "Prompt sessions disabled";
4190+}
4191+
4192+std::shared_ptr<mf::PromptSession> mf::NoPromptShell::start_prompt_session_for(
4193+ std::shared_ptr<Session> const& /*session*/,
4194+ scene::PromptSessionCreationParameters const& /*params*/)
4195+{
4196+ BOOST_THROW_EXCEPTION(std::runtime_error(prompt_sessions_disabled));
4197+}
4198+
4199+void mf::NoPromptShell::add_prompt_provider_process_for(
4200+ std::shared_ptr<PromptSession> const& /*prompt_session*/,
4201+ pid_t /*process_id*/)
4202+{
4203+ BOOST_THROW_EXCEPTION(std::runtime_error(prompt_sessions_disabled));
4204+}
4205+
4206+void mf::NoPromptShell::add_prompt_provider_for(
4207+ std::shared_ptr<PromptSession> const& /*prompt_session*/,
4208+ std::shared_ptr<Session> const& /*session*/)
4209+{
4210+ BOOST_THROW_EXCEPTION(std::runtime_error(prompt_sessions_disabled));
4211+}
4212+
4213+void mf::NoPromptShell::stop_prompt_session(
4214+ std::shared_ptr<PromptSession> const& /*prompt_session*/)
4215+{
4216+ BOOST_THROW_EXCEPTION(std::runtime_error(prompt_sessions_disabled));
4217+}
4218
4219=== added file 'src/server/frontend/no_prompt_shell.h'
4220--- src/server/frontend/no_prompt_shell.h 1970-01-01 00:00:00 +0000
4221+++ src/server/frontend/no_prompt_shell.h 2014-07-11 20:27:44 +0000
4222@@ -0,0 +1,52 @@
4223+/*
4224+ * Copyright © 2014 Canonical Ltd.
4225+ *
4226+ * This program is free software: you can redistribute it and/or modify it
4227+ * under the terms of the GNU General Public License version 3,
4228+ * as published by the Free Software Foundation.
4229+ *
4230+ * This program is distributed in the hope that it will be useful,
4231+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4232+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4233+ * GNU General Public License for more details.
4234+ *
4235+ * You should have received a copy of the GNU General Public License
4236+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4237+ *
4238+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
4239+ */
4240+
4241+#ifndef MIR_FRONTEND_NO_PROMPT_SHELL_H_
4242+#define MIR_FRONTEND_NO_PROMPT_SHELL_H_
4243+
4244+#include "shell_wrapper.h"
4245+
4246+namespace mir
4247+{
4248+namespace frontend
4249+{
4250+class NoPromptShell : public ShellWrapper
4251+{
4252+public:
4253+
4254+ using ShellWrapper::ShellWrapper;
4255+
4256+ std::shared_ptr<PromptSession> start_prompt_session_for(
4257+ std::shared_ptr<Session> const& session,
4258+ scene::PromptSessionCreationParameters const& params) override;
4259+
4260+ void add_prompt_provider_process_for(
4261+ std::shared_ptr<PromptSession> const& prompt_session,
4262+ pid_t process_id) override;
4263+
4264+ void add_prompt_provider_for(
4265+ std::shared_ptr<PromptSession> const& prompt_session,
4266+ std::shared_ptr<Session> const& session) override;
4267+
4268+ void stop_prompt_session(
4269+ std::shared_ptr<PromptSession> const& prompt_session) override;
4270+};
4271+}
4272+}
4273+
4274+#endif /* MIR_FRONTEND_NO_PROMPT_SHELL_H_ */
4275
4276=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
4277--- src/server/frontend/protobuf_message_processor.cpp 2014-06-11 16:11:32 +0000
4278+++ src/server/frontend/protobuf_message_processor.cpp 2014-07-11 20:27:44 +0000
4279@@ -29,9 +29,14 @@
4280 namespace
4281 {
4282 template<class Response>
4283-std::vector<int32_t> extract_fds_from(Response* response)
4284+std::vector<mir::Fd> extract_fds_from(Response* response)
4285 {
4286- std::vector<int32_t> fd(response->fd().data(), response->fd().data() + response->fd().size());
4287+ std::vector<mir::Fd> fd;
4288+ for(auto i = 0u; i < response->fd().size(); ++i)
4289+ {
4290+ int fence = response->fd().data()[i];
4291+ fd.emplace_back(mir::Fd(std::move(fence)));
4292+ }
4293 response->clear_fd();
4294 response->set_fds_on_side_channel(fd.size());
4295 return fd;
4296@@ -151,10 +156,6 @@
4297 {
4298 invoke(this, display_server.get(), &DisplayServer::release_surface, invocation);
4299 }
4300- else if ("test_file_descriptors" == invocation.method_name())
4301- {
4302- invoke(this, display_server.get(), &DisplayServer::test_file_descriptors, invocation);
4303- }
4304 else if ("drm_auth_magic" == invocation.method_name())
4305 {
4306 invoke(this, display_server.get(), &DisplayServer::drm_auth_magic, invocation);
4307@@ -228,8 +229,7 @@
4308
4309 void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::Buffer* response)
4310 {
4311- const auto& fd = extract_fds_from(response);
4312- sender->send_response(id, response, {fd});
4313+ sender->send_response(id, response, {extract_fds_from(response)});
4314 }
4315
4316 void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, std::shared_ptr<protobuf::Buffer> response)
4317@@ -239,35 +239,30 @@
4318
4319 void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::Connection* response)
4320 {
4321- const auto& fd = response->has_platform() ?
4322- extract_fds_from(response->mutable_platform()) :
4323- std::vector<int32_t>();
4324-
4325- sender->send_response(id, response, {fd});
4326+ if (response->has_platform())
4327+ sender->send_response(id, response, {extract_fds_from(response->mutable_platform())});
4328+ else
4329+ sender->send_response(id, response, {});
4330 }
4331
4332 void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::Surface* response)
4333 {
4334- auto const& surface_fd = extract_fds_from(response);
4335- const auto& buffer_fd = response->has_buffer() ?
4336- extract_fds_from(response->mutable_buffer()) :
4337- std::vector<int32_t>();
4338-
4339- sender->send_response(id, response, {surface_fd, buffer_fd});
4340+ if (response->has_buffer())
4341+ sender->send_response(id, response, {extract_fds_from(response), extract_fds_from(response->mutable_buffer())});
4342+ else
4343+ sender->send_response(id, response, {extract_fds_from(response)});
4344 }
4345
4346 void mfd::ProtobufMessageProcessor::send_response(
4347 ::google::protobuf::uint32 id, mir::protobuf::Screencast* response)
4348 {
4349- auto const& buffer_fd = response->has_buffer() ?
4350- extract_fds_from(response->mutable_buffer()) :
4351- std::vector<int32_t>();
4352-
4353- sender->send_response(id, response, {buffer_fd});
4354+ if (response->has_buffer())
4355+ sender->send_response(id, response, {extract_fds_from(response->mutable_buffer())});
4356+ else
4357+ sender->send_response(id, response, {});
4358 }
4359
4360 void mfd::ProtobufMessageProcessor::send_response(::google::protobuf::uint32 id, mir::protobuf::SocketFD* response)
4361 {
4362- const auto& fd = extract_fds_from(response);
4363- sender->send_response(id, response, {fd});
4364+ sender->send_response(id, response, {extract_fds_from(response)});
4365 }
4366
4367=== modified file 'src/server/frontend/session_mediator.cpp'
4368--- src/server/frontend/session_mediator.cpp 2014-06-23 02:57:39 +0000
4369+++ src/server/frontend/session_mediator.cpp 2014-07-11 20:27:44 +0000
4370@@ -29,7 +29,7 @@
4371 #include "mir_toolkit/common.h"
4372 #include "mir/graphics/buffer_id.h"
4373 #include "mir/graphics/buffer.h"
4374-#include "mir/graphics/cursor_images.h"
4375+#include "mir/input/cursor_images.h"
4376 #include "mir/compositor/buffer_stream.h"
4377 #include "mir/geometry/dimensions.h"
4378 #include "mir/frontend/display_changer.h"
4379@@ -58,6 +58,7 @@
4380 namespace mf = mir::frontend;
4381 namespace mfd=mir::frontend::detail;
4382 namespace mg = mir::graphics;
4383+namespace mi = mir::input;
4384 namespace geom = mir::geometry;
4385
4386 mf::SessionMediator::SessionMediator(
4387@@ -70,7 +71,7 @@
4388 std::shared_ptr<ResourceCache> const& resource_cache,
4389 std::shared_ptr<Screencast> const& screencast,
4390 ConnectionContext const& connection_context,
4391- std::shared_ptr<mg::CursorImages> const& cursor_images) :
4392+ std::shared_ptr<mi::CursorImages> const& cursor_images) :
4393 client_pid_(0),
4394 shell(shell),
4395 graphics_platform(graphics_platform),
4396@@ -464,7 +465,7 @@
4397
4398 if (cursor_request->has_name())
4399 {
4400- auto const& image = cursor_images->image(cursor_request->name(), mg::default_cursor_size);
4401+ auto const& image = cursor_images->image(cursor_request->name(), mi::default_cursor_size);
4402 surface->set_cursor_image(image);
4403 }
4404 else
4405
4406=== modified file 'src/server/frontend/session_mediator.h'
4407--- src/server/frontend/session_mediator.h 2014-06-23 02:57:39 +0000
4408+++ src/server/frontend/session_mediator.h 2014-07-11 20:27:44 +0000
4409@@ -39,6 +39,9 @@
4410 class Platform;
4411 class Display;
4412 class GraphicBufferAllocator;
4413+}
4414+namespace input
4415+{
4416 class CursorImages;
4417 }
4418
4419@@ -72,7 +75,7 @@
4420 std::shared_ptr<ResourceCache> const& resource_cache,
4421 std::shared_ptr<Screencast> const& screencast,
4422 ConnectionContext const& connection_context,
4423- std::shared_ptr<graphics::CursorImages> const& cursor_images);
4424+ std::shared_ptr<input::CursorImages> const& cursor_images);
4425
4426 ~SessionMediator() noexcept;
4427
4428@@ -186,7 +189,7 @@
4429 std::shared_ptr<ResourceCache> const resource_cache;
4430 std::shared_ptr<Screencast> const screencast;
4431 ConnectionContext const connection_context;
4432- std::shared_ptr<graphics::CursorImages> const cursor_images;
4433+ std::shared_ptr<input::CursorImages> const cursor_images;
4434
4435 std::unordered_map<SurfaceId,graphics::Buffer*> client_buffer_resource;
4436 std::unordered_map<SurfaceId, std::shared_ptr<ClientBufferTracker>> client_buffer_tracker;
4437
4438=== added file 'src/server/frontend/shell_wrapper.cpp'
4439--- src/server/frontend/shell_wrapper.cpp 1970-01-01 00:00:00 +0000
4440+++ src/server/frontend/shell_wrapper.cpp 2014-07-11 20:27:44 +0000
4441@@ -0,0 +1,74 @@
4442+/*
4443+ * Copyright © 2014 Canonical Ltd.
4444+ *
4445+ * This program is free software: you can redistribute it and/or modify it
4446+ * under the terms of the GNU General Public License version 3,
4447+ * as published by the Free Software Foundation.
4448+ *
4449+ * This program is distributed in the hope that it will be useful,
4450+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4451+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4452+ * GNU General Public License for more details.
4453+ *
4454+ * You should have received a copy of the GNU General Public License
4455+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4456+ *
4457+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
4458+ */
4459+
4460+#include "shell_wrapper.h"
4461+
4462+namespace mf = mir::frontend;
4463+
4464+std::shared_ptr<mf::Session> mf::ShellWrapper::open_session(
4465+ pid_t client_pid,
4466+ std::string const& name,
4467+ std::shared_ptr<EventSink> const& sink)
4468+{
4469+ return wrapped->open_session(client_pid, name,sink);
4470+}
4471+
4472+void mf::ShellWrapper::close_session(std::shared_ptr<Session> const& session)
4473+{
4474+ wrapped->close_session(session);
4475+}
4476+
4477+mf::SurfaceId mf::ShellWrapper::create_surface_for(
4478+ std::shared_ptr<Session> const& session,
4479+ scene::SurfaceCreationParameters const& params)
4480+{
4481+ return wrapped->create_surface_for(session, params);
4482+}
4483+
4484+void mf::ShellWrapper::handle_surface_created(
4485+ std::shared_ptr<Session> const& session)
4486+{
4487+ wrapped->handle_surface_created(session);
4488+}
4489+
4490+std::shared_ptr<mf::PromptSession> mf::ShellWrapper::start_prompt_session_for(
4491+ std::shared_ptr<Session> const& session,
4492+ scene::PromptSessionCreationParameters const& params)
4493+{
4494+ return wrapped->start_prompt_session_for(session, params);
4495+}
4496+
4497+void mf::ShellWrapper::add_prompt_provider_process_for(
4498+ std::shared_ptr<PromptSession> const& prompt_session,
4499+ pid_t process_id)
4500+{
4501+ wrapped->add_prompt_provider_process_for(prompt_session, process_id);
4502+}
4503+
4504+void mf::ShellWrapper::add_prompt_provider_for(
4505+ std::shared_ptr<PromptSession> const& prompt_session,
4506+ std::shared_ptr<Session> const& session)
4507+{
4508+ wrapped->add_prompt_provider_for(prompt_session, session);
4509+}
4510+
4511+void mf::ShellWrapper::stop_prompt_session(
4512+ std::shared_ptr<PromptSession> const& prompt_session)
4513+{
4514+ wrapped->stop_prompt_session(prompt_session);
4515+}
4516
4517=== added file 'src/server/frontend/shell_wrapper.h'
4518--- src/server/frontend/shell_wrapper.h 1970-01-01 00:00:00 +0000
4519+++ src/server/frontend/shell_wrapper.h 2014-07-11 20:27:44 +0000
4520@@ -0,0 +1,70 @@
4521+/*
4522+ * Copyright © 2014 Canonical Ltd.
4523+ *
4524+ * This program is free software: you can redistribute it and/or modify it
4525+ * under the terms of the GNU General Public License version 3,
4526+ * as published by the Free Software Foundation.
4527+ *
4528+ * This program is distributed in the hope that it will be useful,
4529+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4530+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4531+ * GNU General Public License for more details.
4532+ *
4533+ * You should have received a copy of the GNU General Public License
4534+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4535+ *
4536+ * Authored By: Alan Griffiths <alan@octopull.co.uk>
4537+ */
4538+
4539+#ifndef MIR_FRONTEND_SHELL_WRAPPER_H_
4540+#define MIR_FRONTEND_SHELL_WRAPPER_H_
4541+
4542+#include "mir/frontend/shell.h"
4543+
4544+namespace mir
4545+{
4546+namespace frontend
4547+{
4548+class ShellWrapper : public Shell
4549+{
4550+public:
4551+ explicit ShellWrapper(std::shared_ptr<Shell> const& wrapped) :
4552+ wrapped(wrapped) {}
4553+
4554+ virtual ~ShellWrapper() = default;
4555+
4556+ std::shared_ptr<Session> open_session(
4557+ pid_t client_pid,
4558+ std::string const& name,
4559+ std::shared_ptr<EventSink> const& sink) override;
4560+
4561+ void close_session(std::shared_ptr<Session> const& session) override;
4562+
4563+ SurfaceId create_surface_for(
4564+ std::shared_ptr<Session> const& session,
4565+ scene::SurfaceCreationParameters const& params) override;
4566+
4567+ void handle_surface_created(std::shared_ptr<Session> const& session) override;
4568+
4569+ std::shared_ptr<PromptSession> start_prompt_session_for(
4570+ std::shared_ptr<Session> const& session,
4571+ scene::PromptSessionCreationParameters const& params) override;
4572+
4573+ void add_prompt_provider_process_for(
4574+ std::shared_ptr<PromptSession> const& prompt_session,
4575+ pid_t process_id) override;
4576+
4577+ void add_prompt_provider_for(
4578+ std::shared_ptr<PromptSession> const& prompt_session,
4579+ std::shared_ptr<Session> const& session) override;
4580+
4581+ void stop_prompt_session(
4582+ std::shared_ptr<PromptSession> const& prompt_session) override;
4583+
4584+protected:
4585+ std::shared_ptr<Shell> const wrapped;
4586+};
4587+}
4588+}
4589+
4590+#endif /* MIR_FRONTEND_SHELL_WRAPPER_H_ */
4591
4592=== modified file 'src/server/frontend/socket_messenger.cpp'
4593--- src/server/frontend/socket_messenger.cpp 2014-06-12 15:35:08 +0000
4594+++ src/server/frontend/socket_messenger.cpp 2014-07-11 20:27:44 +0000
4595@@ -83,7 +83,7 @@
4596 send_fds_locked(lg, fds);
4597 }
4598
4599-void mfd::SocketMessenger::send_fds_locked(std::unique_lock<std::mutex> const&, std::vector<int32_t> const& fds)
4600+void mfd::SocketMessenger::send_fds_locked(std::unique_lock<std::mutex> const&, std::vector<mir::Fd> const& fds)
4601 {
4602 if (fds.size() > 0)
4603 {
4604@@ -119,7 +119,7 @@
4605
4606 int* const data = reinterpret_cast<int*>(CMSG_DATA(message));
4607 int i = 0;
4608- for (auto fd : fds)
4609+ for (auto& fd : fds)
4610 data[i++] = fd;
4611
4612 auto const sent = sendmsg(socket->native_handle(), &header, 0);
4613
4614=== modified file 'src/server/frontend/socket_messenger.h'
4615--- src/server/frontend/socket_messenger.h 2014-06-03 11:04:15 +0000
4616+++ src/server/frontend/socket_messenger.h 2014-07-11 20:27:44 +0000
4617@@ -51,7 +51,7 @@
4618 std::mutex message_lock;
4619 SessionCredentials session_creds{0, 0, 0};
4620
4621- void send_fds_locked(std::unique_lock<std::mutex> const& lock, std::vector<int32_t> const& fds);
4622+ void send_fds_locked(std::unique_lock<std::mutex> const& lock, std::vector<Fd> const& fds);
4623 };
4624 }
4625 }
4626
4627=== modified file 'src/server/graphics/CMakeLists.txt'
4628--- src/server/graphics/CMakeLists.txt 2014-06-03 11:04:15 +0000
4629+++ src/server/graphics/CMakeLists.txt 2014-07-11 20:27:44 +0000
4630@@ -8,7 +8,6 @@
4631 gl_extensions_base.cpp
4632 program_factory.cpp
4633 surfaceless_egl_context.cpp
4634- builtin_cursor_images.cpp
4635 )
4636
4637 add_subdirectory(nested/)
4638
4639=== modified file 'src/server/graphics/default_configuration.cpp'
4640--- src/server/graphics/default_configuration.cpp 2014-06-24 21:44:55 +0000
4641+++ src/server/graphics/default_configuration.cpp 2014-07-11 20:27:44 +0000
4642@@ -39,8 +39,6 @@
4643
4644 #include <boost/throw_exception.hpp>
4645
4646-#include "builtin_cursor_images.h"
4647-
4648 #include <map>
4649
4650 namespace mg = mir::graphics;
4651@@ -70,22 +68,31 @@
4652 return graphics_platform(
4653 [this]()->std::shared_ptr<mg::Platform>
4654 {
4655- auto graphics_lib = mir::load_library(the_options()->get<std::string>(options::platform_graphics_lib));
4656-
4657 if (!the_options()->is_set(options::host_socket_opt))
4658 {
4659 // fallback to standalone if host socket is unset
4660+ auto graphics_lib = mir::load_library(the_options()->get<std::string>(options::platform_graphics_lib));
4661 auto create_platform = graphics_lib->load_function<mg::CreatePlatform>("create_platform");
4662 return create_platform(the_options(), the_emergency_cleanup(), the_display_report());
4663 }
4664
4665- auto create_native_platform = graphics_lib->load_function<mg::CreateNativePlatform>("create_native_platform");
4666-
4667 return std::make_shared<mir::graphics::nested::NestedPlatform>(
4668 the_host_connection(),
4669 the_input_dispatcher(),
4670 the_display_report(),
4671- create_native_platform(the_display_report()));
4672+ the_graphics_native_platform());
4673+ });
4674+}
4675+
4676+std::shared_ptr<mg::NativePlatform> mir::DefaultServerConfiguration::the_graphics_native_platform()
4677+{
4678+ return graphics_native_platform(
4679+ [this]()
4680+ {
4681+ auto graphics_lib = mir::load_library(the_options()->get<std::string>(options::platform_graphics_lib));
4682+ auto create_native_platform = graphics_lib->load_function<mg::CreateNativePlatform>("create_native_platform");
4683+
4684+ return create_native_platform(the_display_report());
4685 });
4686 }
4687
4688@@ -145,28 +152,6 @@
4689 });
4690 }
4691
4692-std::shared_ptr<mg::CursorImage>
4693-mir::DefaultServerConfiguration::the_default_cursor_image()
4694-{
4695- static geometry::Size const default_cursor_size = {geometry::Width{64},
4696- geometry::Height{64}};
4697- return default_cursor_image(
4698- [this]()
4699- {
4700- return the_cursor_images()->image(mir_default_cursor_name, default_cursor_size);
4701- });
4702-}
4703-
4704-std::shared_ptr<mg::CursorImages>
4705-mir::DefaultServerConfiguration::the_cursor_images()
4706-{
4707- return cursor_images(
4708- [this]()
4709- {
4710- return std::make_shared<mg::BuiltinCursorImages>();
4711- });
4712-}
4713-
4714 auto mir::DefaultServerConfiguration::the_host_connection()
4715 -> std::shared_ptr<graphics::nested::HostConnection>
4716 {
4717
4718=== modified file 'src/server/graphics/nested/nested_display.cpp'
4719--- src/server/graphics/nested/nested_display.cpp 2014-06-02 17:07:02 +0000
4720+++ src/server/graphics/nested/nested_display.cpp 2014-07-11 20:27:44 +0000
4721@@ -215,10 +215,6 @@
4722 });
4723 });
4724
4725- if (result.empty())
4726- BOOST_THROW_EXCEPTION(std::runtime_error("Nested Mir needs at least one output for display"));
4727-
4728-
4729 {
4730 std::unique_lock<std::mutex> lock(outputs_mutex);
4731 outputs.swap(result);
4732
4733=== modified file 'src/server/input/CMakeLists.txt'
4734--- src/server/input/CMakeLists.txt 2014-06-24 15:28:09 +0000
4735+++ src/server/input/CMakeLists.txt 2014-07-11 20:27:44 +0000
4736@@ -1,5 +1,7 @@
4737 include_directories(${MIR_3RD_PARTY_INCLUDE_DIRECTORIES})
4738 include_directories(${MIR_ANDROID_INCLUDE_DIRECTORIES})
4739+include_directories(${MIR_XCURSOR_INCLUDE_DIRECTORIES})
4740+
4741 set(
4742 INPUT_SOURCES
4743
4744@@ -8,11 +10,12 @@
4745 null_input_channel_factory.cpp
4746 null_input_configuration.cpp
4747 null_input_dispatcher.cpp
4748- nested_input_configuration.cpp
4749 display_input_region.cpp
4750 vt_filter.cpp
4751 cursor_controller.cpp
4752 default_configuration.cpp
4753+ xcursor_loader.cpp
4754+ builtin_cursor_images.cpp
4755 )
4756
4757 add_subdirectory(android)
4758@@ -23,3 +26,7 @@
4759 ${INPUT_SOURCES}
4760 )
4761 uses_android_input(mirinput)
4762+target_link_libraries(
4763+ mirinput
4764+ xcursorloader
4765+)
4766
4767=== renamed file 'src/server/graphics/black_arrow.c' => 'src/server/input/black_arrow.c'
4768=== renamed file 'src/server/graphics/black_arrow.xcf' => 'src/server/input/black_arrow.xcf'
4769=== renamed file 'src/server/graphics/builtin_cursor_images.cpp' => 'src/server/input/builtin_cursor_images.cpp'
4770--- src/server/graphics/builtin_cursor_images.cpp 2014-04-23 23:07:05 +0000
4771+++ src/server/input/builtin_cursor_images.cpp 2014-07-11 20:27:44 +0000
4772@@ -21,6 +21,7 @@
4773
4774 #include "mir/graphics/cursor_image.h"
4775
4776+namespace mi = mir::input;
4777 namespace mg = mir::graphics;
4778 namespace geom = mir::geometry;
4779
4780@@ -36,15 +37,19 @@
4781 {
4782 return { black_arrow.width, black_arrow.height };
4783 }
4784+ geom::Displacement hotspot() const
4785+ {
4786+ return {0, 0};
4787+ }
4788 };
4789 }
4790
4791-mg::BuiltinCursorImages::BuiltinCursorImages()
4792+mi::BuiltinCursorImages::BuiltinCursorImages()
4793 : builtin_image(std::make_shared<BlackArrowCursorImage>())
4794 {
4795 }
4796
4797-std::shared_ptr<mg::CursorImage> mg::BuiltinCursorImages::image(std::string const& /* cursor_name */,
4798+std::shared_ptr<mg::CursorImage> mi::BuiltinCursorImages::image(std::string const& /* cursor_name */,
4799 geom::Size const& /* size */)
4800 {
4801 // Builtin repository only has one cursor at a single size.
4802
4803=== renamed file 'src/server/graphics/builtin_cursor_images.h' => 'src/server/input/builtin_cursor_images.h'
4804--- src/server/graphics/builtin_cursor_images.h 2014-04-23 23:07:05 +0000
4805+++ src/server/input/builtin_cursor_images.h 2014-07-11 20:27:44 +0000
4806@@ -17,24 +17,22 @@
4807 */
4808
4809
4810-#ifndef MIR_GRAPHICS_BUILTIN_CURSOR_LOADER_H_
4811-#define MIR_GRAPHICS_BUILTIN_CURSOR_LOADER_H_
4812+#ifndef MIR_INPUT_BUILTIN_CURSOR_IMAGES_H_
4813+#define MIR_INPUT_BUILTIN_CURSOR_IMAGES_H_
4814
4815-#include "mir/graphics/cursor_images.h"
4816+#include "mir/input/cursor_images.h"
4817
4818 namespace mir
4819 {
4820-namespace graphics
4821+namespace input
4822 {
4823-class CursorImage;
4824-
4825 class BuiltinCursorImages : public CursorImages
4826 {
4827 public:
4828 BuiltinCursorImages();
4829 virtual ~BuiltinCursorImages() = default;
4830
4831- std::shared_ptr<CursorImage> image(std::string const& cursor_name,
4832+ std::shared_ptr<graphics::CursorImage> image(std::string const& cursor_name,
4833 geometry::Size const& size);
4834
4835 protected:
4836@@ -42,10 +40,10 @@
4837 BuiltinCursorImages& operator=(BuiltinCursorImages const&) = delete;
4838
4839 private:
4840- std::shared_ptr<CursorImage> const builtin_image;
4841+ std::shared_ptr<graphics::CursorImage> const builtin_image;
4842 };
4843 }
4844 }
4845
4846
4847-#endif /* MIR_GRAPHICS_BUILTIN_CURSOR_LOADER_H_ */
4848+#endif /* MIR_INPUT_BUILTIN_CURSOR_IMAGES_H_ */
4849
4850=== modified file 'src/server/input/default_configuration.cpp'
4851--- src/server/input/default_configuration.cpp 2014-06-26 16:10:36 +0000
4852+++ src/server/input/default_configuration.cpp 2014-07-11 20:27:44 +0000
4853@@ -28,11 +28,12 @@
4854 #include "android/input_channel_factory.h"
4855 #include "display_input_region.h"
4856 #include "event_filter_chain.h"
4857-#include "nested_input_configuration.h"
4858 #include "null_input_configuration.h"
4859 #include "cursor_controller.h"
4860 #include "null_input_dispatcher.h"
4861 #include "null_input_targeter.h"
4862+#include "xcursor_loader.h"
4863+#include "builtin_cursor_images.h"
4864 #include "null_input_send_observer.h"
4865 #include "null_input_channel_factory.h"
4866
4867@@ -50,6 +51,7 @@
4868 namespace mia = mi::android;
4869 namespace mr = mir::report;
4870 namespace ms = mir::scene;
4871+namespace mg = mir::graphics;
4872 namespace msh = mir::shell;
4873
4874 std::shared_ptr<mi::InputRegion> mir::DefaultServerConfiguration::the_input_region()
4875@@ -79,11 +81,11 @@
4876 [this]() -> std::shared_ptr<mi::InputConfiguration>
4877 {
4878 auto const options = the_options();
4879- if (!options->get<bool>(options::enable_input_opt))
4880- {
4881- return std::make_shared<mi::NullInputConfiguration>();
4882- }
4883- else if (!options->is_set(options::host_socket_opt))
4884+ bool input_reading_required =
4885+ options->get<bool>(options::enable_input_opt) &&
4886+ !options->is_set(options::host_socket_opt);
4887+
4888+ if (input_reading_required)
4889 {
4890 // fallback to standalone if host socket is unset
4891 return std::make_shared<mia::DefaultInputConfiguration>(
4892@@ -95,7 +97,7 @@
4893 }
4894 else
4895 {
4896- return std::make_shared<mi::NestedInputConfiguration>();
4897+ return std::make_shared<mi::NullInputConfiguration>();
4898 }
4899 });
4900 }
4901@@ -235,3 +237,37 @@
4902 });
4903
4904 }
4905+
4906+std::shared_ptr<mg::CursorImage>
4907+mir::DefaultServerConfiguration::the_default_cursor_image()
4908+{
4909+ return default_cursor_image(
4910+ [this]()
4911+ {
4912+ return the_cursor_images()->image(mir_default_cursor_name, mi::default_cursor_size);
4913+ });
4914+}
4915+
4916+namespace
4917+{
4918+bool has_default_cursor(mi::CursorImages& images)
4919+{
4920+ if (images.image(mir_default_cursor_name, mi::default_cursor_size))
4921+ return true;
4922+ return false;
4923+}
4924+}
4925+
4926+std::shared_ptr<mi::CursorImages>
4927+mir::DefaultServerConfiguration::the_cursor_images()
4928+{
4929+ return cursor_images(
4930+ [this]() -> std::shared_ptr<mi::CursorImages>
4931+ {
4932+ auto xcursor_loader = std::make_shared<mi::XCursorLoader>();
4933+ if (has_default_cursor(*xcursor_loader))
4934+ return xcursor_loader;
4935+ else
4936+ return std::make_shared<mi::BuiltinCursorImages>();
4937+ });
4938+}
4939
4940=== removed file 'src/server/input/nested_input_configuration.cpp'
4941--- src/server/input/nested_input_configuration.cpp 2014-06-24 15:28:09 +0000
4942+++ src/server/input/nested_input_configuration.cpp 1970-01-01 00:00:00 +0000
4943@@ -1,37 +0,0 @@
4944-/*
4945- * Copyright © 2013-2014 Canonical Ltd.
4946- *
4947- * This program is free software: you can redistribute it and/or modify it
4948- * under the terms of the GNU General Public License version 3,
4949- * as published by the Free Software Foundation.
4950- *
4951- * This program is distributed in the hope that it will be useful,
4952- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4953- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4954- * GNU General Public License for more details.
4955- *
4956- * You should have received a copy of the GNU General Public License
4957- * along with this program. If not, see <http://www.gnu.org/licenses/>.
4958- *
4959- * Authored by: Alan Griffiths <alan@octopull.co.uk>
4960- * Andreas Pokorny <andreas.pokorny@canonical.com>
4961- */
4962-
4963-#include "nested_input_configuration.h"
4964-#include "null_input_manager.h"
4965-
4966-#include "android/input_channel_factory.h"
4967-
4968-#include <memory>
4969-
4970-namespace mi = mir::input;
4971-namespace mia = mir::input::android;
4972-
4973-std::shared_ptr<mi::InputManager> mi::NestedInputConfiguration::the_input_manager()
4974-{
4975- return input_manager(
4976- [this]()
4977- {
4978- return std::make_shared<NullInputManager>();
4979- });
4980-}
4981
4982=== removed file 'src/server/input/nested_input_configuration.h'
4983--- src/server/input/nested_input_configuration.h 2014-06-24 15:28:09 +0000
4984+++ src/server/input/nested_input_configuration.h 1970-01-01 00:00:00 +0000
4985@@ -1,43 +0,0 @@
4986-/*
4987- * Copyright © 2013 Canonical Ltd.
4988- *
4989- * This program is free software: you can redistribute it and/or modify it
4990- * under the terms of the GNU General Public License version 3,
4991- * as published by the Free Software Foundation.
4992- *
4993- * This program is distributed in the hope that it will be useful,
4994- * but WITHOUT ANY WARRANTY; without even the implied warranty of
4995- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4996- * GNU General Public License for more details.
4997- *
4998- * You should have received a copy of the GNU General Public License
4999- * along with this program. If not, see <http://www.gnu.org/licenses/>.
5000- *
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches