Mir

Merge lp:~robertcarr/mir/focus-tell-dont-ask into lp:mir

Proposed by Robert Carr
Status: Rejected
Rejected by: Robert Carr
Proposed branch: lp:~robertcarr/mir/focus-tell-dont-ask
Merge into: lp:mir
Diff against target: 919 lines (+385/-113)
26 files modified
debian/changelog (+8/-2)
include/server/mir/default_server_configuration.h (+3/-0)
include/server/mir/frontend/connector_report.h (+0/-1)
include/server/mir/frontend/messenger_report.h (+49/-0)
include/server/mir/frontend/protobuf_ipc_factory.h (+3/-1)
include/server/mir/logging/messenger_report.h (+49/-0)
include/server/mir/shell/application_session.h (+6/-0)
include/server/mir/shell/default_focus_mechanism.h (+2/-2)
include/server/mir/shell/session.h (+5/-0)
include/test/mir_test_doubles/mock_shell_session.h (+3/-0)
include/test/mir_test_doubles/stub_ipc_factory.h (+6/-1)
include/test/mir_test_doubles/stub_shell_session.h (+8/-0)
src/server/default_server_configuration.cpp (+31/-3)
src/server/frontend/CMakeLists.txt (+1/-0)
src/server/frontend/null_messenger_report.cpp (+25/-0)
src/server/frontend/protobuf_session_creator.cpp (+2/-2)
src/server/frontend/socket_messenger.cpp (+11/-2)
src/server/frontend/socket_messenger.h (+6/-1)
src/server/logging/CMakeLists.txt (+1/-0)
src/server/logging/messenger_report.cpp (+46/-0)
src/server/shell/application_session.cpp (+39/-3)
src/server/shell/default_focus_mechanism.cpp (+10/-18)
tests/acceptance-tests/test_client_focus_notification.cpp (+3/-1)
tests/unit-tests/frontend/CMakeLists.txt (+1/-0)
tests/unit-tests/frontend/test_socket_messenger.cpp (+37/-0)
tests/unit-tests/shell/test_default_focus_mechanism.cpp (+30/-76)
To merge this branch: bzr merge lp:~robertcarr/mir/focus-tell-dont-ask
Reviewer Review Type Date Requested Status
Robert Carr (community) Disapprove
Alan Griffiths Needs Fixing
Daniel van Vugt Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Alexandros Frantzis Pending
kevin gunn Pending
Review via email: mp+188397@code.launchpad.net

This proposal supersedes a proposal from 2013-09-26.

Description of the change

Broken pipe isnt present in trunk anymore so resubmitting without prereq.

===

Fixed error in ApplicationSession::relinquish_focus :)

Targeting to development-branch

===

Solve some of the races around focus by applying 'tell-dont-ask' in relation to internal Session state and the Focus Mechanism. Now the focus mechanism doesn't have to hold an (unsafe) shared_ptr to the last focused surface. It's ok for the Session to hold this weak_ptr, as it only attempts to lock it when holding surfaces_mutex.

This branch requires: https://code.launchpad.net/~vanvugt/mir/fix-1226139/+merge/186809

As it will cause unfocus messages to be sent in the "connection dropped without disconnect case"(i.e. many of the protobuf tool tests which fail to call disconnect) very likely to lead to a broken pipe error.

== Old Description ==

Fix the races around focus. Essentially these stem from that holding std::shared_ptr<msh::Surface> doesn't guarantee that calling methods on that surface will be safe (the underlying surface could be destroyed via Surface::destroy and then your method call will throw).

So this branch changes ApplicationSession to not destroy the surface explicitly and instead rely on ~msh::Surface, which means that you really can hold a safe pointer. I think this as a reasonable choice, as the shell might want to do similar things, i.e. continue to animate a surface after a session has closed it.

==

New approach relies on ApplicationSession to hold the last focused ptr...WIP

To post a comment you must log in.
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

I was able to run the stress test with continuous cursor input for the full ten minute run. There is also good reason to believe this fixes: https://bugs.launchpad.net/mir/+bug/1220845

The exception in ~SessionMediator can be triggered if session_manager->close_session throws (due to this focus race), causing SessionMediator::disconnect to fail to reset it's session member-variable pointer. This exception is caught in frontend. However now in ~SessionMediator the pointer has not been reset so it closes the session again throwing an Invalid Session exception. causing the session to be closed again in ~

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

The unsafely held surface pointer in this case is the previously focused app.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

There is an inconsistency with this approach: when a session is closed its surface resources are destroyed immediately, but when a surface is explicitly destroyed the resources are not destroyed until there are no more users.

Would it (make sense|be possible) for msh::Surface to own (hold a strong pointer to) ms::Surface and rely on ~msh::Surface() in both the cases above, thus removing the msh::Surface -> ms::Surface weak_ptr dance?

review: Needs Information
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> There is an inconsistency with this approach: when a session is closed its
> surface resources are destroyed immediately, but when a surface is explicitly
> destroyed the resources are not destroyed until there are no more users.
>
> Would it (make sense|be possible) for msh::Surface to own (hold a strong
> pointer to) ms::Surface and rely on ~msh::Surface() in both the cases above,
> thus removing the msh::Surface -> ms::Surface weak_ptr dance?

I've not yet looked at the MP, but I can contribute the origin of the "weak_ptr dance".

Once a surface has been "destroyed" it is no longer in the scenegraph (ok, SurfaceStack) and therefore not composited. If the ms::Surface continued to exist it could reach a state where it has client buffers meaning threads that require them will wait forever.

It may well be that subsequent changes (particularly the introduction of force_requests_to_complete()) permits a better solution than the "weak_ptr dance".

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

I don't think this is the right evolution of the code, but I don't think it makes things worse.

The right solution would be more complex and should probably come as part of fixing the data model.

review: Abstain
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

I think it makes sense to not destroy the surfaces explicitly from the session (as in the last committ). It may be possible to fix the weak_ptr dance (it almost surely is possible). It's not really clear what direction this code should go in right now though (except probably not further down this one), so I am trying to just fix the crashes non invasively

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Bug 1216727 is still happening :(

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::logic_error> >'
  what(): Requesting handle for an unregistered channel

Should we just unlink it from the branch?

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

P.S. Before declaring bug 1216727 fixed, please find a machine on which you can reproduce it (using trunk). To be sure the changes are actually having an effect.

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Can someone review this again?

Revision history for this message
Daniel van Vugt (vanvugt) : Posted in a previous version of this proposal
review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Weirdly, merging this branch now causes an almost immediate hang:

Running tests...
Test project /home/dan/bzr/mir/tmp.focus/build
        Start 1: LGPL-required
  1/145 Test #1: LGPL-required ............................................... Passed 0.01 sec
        Start 2: GPL-required
  2/145 Test #2: GPL-required ................................................ Passed 0.01 sec
        Start 3: acceptance-tests.BespokeDisplayServerTestFixture.*

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Another bug with this branch is that on Alt+Tab in demo_server_shell, the client rendering freezes. Permanently.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:1084
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robertcarr/mir/focus-tell-dont-ask/+merge/187037/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-ci/1558/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/2090
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/1975
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-saucy-amd64-ci/796/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/mir-saucy-armhf-ci/58
        deb: http://jenkins.qa.ubuntu.com/job/mir-saucy-armhf-ci/58/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-ci/1558/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
kevin gunn (kgunn72) wrote : Posted in a previous version of this proposal

wouldn't this require a server api bump? i think so...

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

On both g++ and clang 64bit builds I see:

[ FAILED ] 2 tests, listed below:
[ FAILED ] BespokeDisplayServerTestFixture.a_surface_is_notified_of_receiving_focus
[ FAILED ] BespokeDisplayServerTestFixture.two_surfaces_are_notified_of_gaining_and_losing_focus

(and so does jenkins on amd64)

review: Needs Fixing
Revision history for this message
Robert Ancell (robert-ancell) wrote : Posted in a previous version of this proposal

This merge should be moved to lp:~mir-team/mir/development-branch

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:1085
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~robertcarr/mir/focus-tell-dont-ask/+merge/187648/+edit-commit-message

http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-ci/31/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-android-saucy-i386-build/2142/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-clang-saucy-amd64-build/2027/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/mir-team-mir-development-branch-saucy-amd64-ci/31/console

Click here to trigger a rebuild:
http://s-jenkins:8080/job/mir-team-mir-development-branch-ci/31/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

I think the idea is a step in the right direction, given the problem :) (makes more sense than the shared_ptr in the focus controller)

receive_focus/relinquish focus seems a funny name for what's going on, given that there's no exchange of resources.
There's some gaps with who really has the-focus though still, like with,
148 + if (surfaces.size() == 0)
149 + {
150 + targeter->focus_cleared();
151 + return;
152 + }
when this happens, the focus controller is unaware that it could reassign the focus... perhaps the session should accept or reject the focus, and let the focus mechanism know. I Maybe we're twisting around the funny way ms::Surface is.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

It looked weird before, it looks weird after

review: Abstain
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

The prereq branch needs fixing or even rejecting. And therefore its dependents will need updating too.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

The changes to debian/changelog are old and/or wrong. Even if there's a robot cleaning it up on lp:mir, the changelog entries are still not related to this proposal.

review: Needs Fixing
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I think the MessengerReport changes are probably spurious.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Not required if we can land hold-surface-alive

review: Disapprove

Unmerged revisions

1088. By Robert Carr

Fix error in relinquish focus

1087. By Robert Carr

Merge socket-messenger-reporitng

1086. By Robert Carr

Merge development-branch

1085. By Robert Carr

Typo

1084. By Robert Carr

application_session: Introduce default_surface_locked to dedupe some code

1083. By Robert Carr

Merge fix-1226139

1082. By Robert Carr

More cleanup

1081. By Robert Carr

Merge trunk

1080. By Robert Carr

Cleanup

1079. By Robert Carr

Mutex for surface

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/changelog'
--- debian/changelog 2013-09-26 02:41:07 +0000
+++ debian/changelog 2013-09-30 17:13:36 +0000
@@ -1,4 +1,4 @@
1mir (0.0.12-0ubuntu1) UNRELEASED; urgency=low1mir (0.0.12+13.10.20130926.1-0ubuntu1) saucy; urgency=low
22
3 [ kg ]3 [ kg ]
4 * bump version for ABI break (LP: #1229212)4 * bump version for ABI break (LP: #1229212)
@@ -6,7 +6,13 @@
6 [ Robert Ancell ]6 [ Robert Ancell ]
7 * Bump version to 0.0.127 * Bump version to 0.0.12
88
9 -- Robert Ancell <robert.ancell@canonical.com> Thu, 26 Sep 2013 09:34:23 +12009 [ Alexandros Frantzis ]
10 * tests: Fix compiler warning about maybe-uninitialized struct member
11
12 [ Ubuntu daily release ]
13 * Automatic snapshot from revision 1084
14
15 -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 26 Sep 2013 08:39:29 +0000
1016
11mir (0.0.11+13.10.20130924.1-0ubuntu1) saucy; urgency=low17mir (0.0.11+13.10.20130924.1-0ubuntu1) saucy; urgency=low
1218
1319
=== modified file 'include/server/mir/default_server_configuration.h'
--- include/server/mir/default_server_configuration.h 2013-09-24 11:43:27 +0000
+++ include/server/mir/default_server_configuration.h 2013-09-30 17:13:36 +0000
@@ -46,6 +46,7 @@
46class SessionCreator;46class SessionCreator;
47class SessionMediatorReport;47class SessionMediatorReport;
48class MessageProcessorReport;48class MessageProcessorReport;
49class MessengerReport;
49class SessionAuthorizer;50class SessionAuthorizer;
50class EventSink;51class EventSink;
51class DisplayChanger;52class DisplayChanger;
@@ -165,6 +166,7 @@
165 * @{ */166 * @{ */
166 virtual std::shared_ptr<frontend::SessionMediatorReport> the_session_mediator_report();167 virtual std::shared_ptr<frontend::SessionMediatorReport> the_session_mediator_report();
167 virtual std::shared_ptr<frontend::MessageProcessorReport> the_message_processor_report();168 virtual std::shared_ptr<frontend::MessageProcessorReport> the_message_processor_report();
169 virtual std::shared_ptr<frontend::MessengerReport> the_messenger_report();
168 virtual std::shared_ptr<frontend::SessionAuthorizer> the_session_authorizer();170 virtual std::shared_ptr<frontend::SessionAuthorizer> the_session_authorizer();
169 virtual std::shared_ptr<frontend::Shell> the_frontend_shell();171 virtual std::shared_ptr<frontend::Shell> the_frontend_shell();
170 virtual std::shared_ptr<frontend::EventSink> the_global_event_sink();172 virtual std::shared_ptr<frontend::EventSink> the_global_event_sink();
@@ -270,6 +272,7 @@
270 CachedPtr<frontend::ProtobufIpcFactory> ipc_factory;272 CachedPtr<frontend::ProtobufIpcFactory> ipc_factory;
271 CachedPtr<frontend::SessionMediatorReport> session_mediator_report;273 CachedPtr<frontend::SessionMediatorReport> session_mediator_report;
272 CachedPtr<frontend::MessageProcessorReport> message_processor_report;274 CachedPtr<frontend::MessageProcessorReport> message_processor_report;
275 CachedPtr<frontend::MessengerReport> messenger_report;
273 CachedPtr<frontend::SessionAuthorizer> session_authorizer;276 CachedPtr<frontend::SessionAuthorizer> session_authorizer;
274 CachedPtr<frontend::EventSink> global_event_sink;277 CachedPtr<frontend::EventSink> global_event_sink;
275 CachedPtr<frontend::SessionCreator> session_creator;278 CachedPtr<frontend::SessionCreator> session_creator;
276279
=== modified file 'include/server/mir/frontend/connector_report.h'
--- include/server/mir/frontend/connector_report.h 2013-09-24 16:20:17 +0000
+++ include/server/mir/frontend/connector_report.h 2013-09-30 17:13:36 +0000
@@ -42,7 +42,6 @@
42class NullConnectorReport : public ConnectorReport42class NullConnectorReport : public ConnectorReport
43{43{
44public:44public:
45
46 void error(std::exception const& error);45 void error(std::exception const& error);
47};46};
48}47}
4948
=== added file 'include/server/mir/frontend/messenger_report.h'
--- include/server/mir/frontend/messenger_report.h 1970-01-01 00:00:00 +0000
+++ include/server/mir/frontend/messenger_report.h 2013-09-30 17:13:36 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#ifndef MIR_FRONTEND_MESSENGER_REPORT_H_
20#define MIR_FRONTEND_MESSENGER_REPORT_H_
21
22#include <string>
23
24namespace mir
25{
26namespace frontend
27{
28
29class MessengerReport
30{
31public:
32 virtual void error(std::string const& error_message) = 0;
33
34protected:
35 virtual ~MessengerReport() = default;
36 MessengerReport() = default;
37 MessengerReport(const MessengerReport&) = delete;
38 MessengerReport& operator=(const MessengerReport&) = delete;
39};
40
41class NullMessengerReport : public MessengerReport
42{
43public:
44 void error(std::string const& error_message);
45};
46}
47}
48
49#endif // MIR_FRONTEND_MESSENGER_REPORT_H_
050
=== modified file 'include/server/mir/frontend/protobuf_ipc_factory.h'
--- include/server/mir/frontend/protobuf_ipc_factory.h 2013-08-28 03:41:48 +0000
+++ include/server/mir/frontend/protobuf_ipc_factory.h 2013-09-30 17:13:36 +0000
@@ -32,6 +32,7 @@
32class EventSink;32class EventSink;
33class ResourceCache;33class ResourceCache;
34class MessageProcessorReport;34class MessageProcessorReport;
35class MessengerReport;
3536
36class ProtobufIpcFactory37class ProtobufIpcFactory
37{38{
@@ -39,7 +40,8 @@
39 virtual std::shared_ptr<protobuf::DisplayServer> make_ipc_server(40 virtual std::shared_ptr<protobuf::DisplayServer> make_ipc_server(
40 std::shared_ptr<EventSink> const& sink, bool authorized_to_resize_display) = 0;41 std::shared_ptr<EventSink> const& sink, bool authorized_to_resize_display) = 0;
41 virtual std::shared_ptr<ResourceCache> resource_cache() = 0;42 virtual std::shared_ptr<ResourceCache> resource_cache() = 0;
42 virtual std::shared_ptr<MessageProcessorReport> report() = 0;43 virtual std::shared_ptr<MessageProcessorReport> message_processor_report() = 0;
44 virtual std::shared_ptr<MessengerReport> messenger_report() = 0;
4345
44protected:46protected:
45 ProtobufIpcFactory() {}47 ProtobufIpcFactory() {}
4648
=== added file 'include/server/mir/logging/messenger_report.h'
--- include/server/mir/logging/messenger_report.h 1970-01-01 00:00:00 +0000
+++ include/server/mir/logging/messenger_report.h 2013-09-30 17:13:36 +0000
@@ -0,0 +1,49 @@
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#ifndef MIR_LOGGING_MESSENGER_REPORT_H_
20#define MIR_LOGGING_MESSENGER_REPORT_H_
21
22#include "mir/frontend/messenger_report.h"
23
24#include <memory>
25
26namespace mir
27{
28namespace logging
29{
30class Logger;
31
32class MessengerReport : public frontend::MessengerReport
33{
34public:
35 MessengerReport(std::shared_ptr<Logger> const& logger);
36 virtual ~MessengerReport() noexcept(true) = default;
37
38 void error(std::string const& error_message);
39
40private:
41 char const* component();
42 std::shared_ptr<Logger> const logger;
43};
44
45}
46}
47
48
49#endif /* MIR_LOGGING_MESSENGER_REPORT_H_ */
050
=== modified file 'include/server/mir/shell/application_session.h'
--- include/server/mir/shell/application_session.h 2013-08-28 03:41:48 +0000
+++ include/server/mir/shell/application_session.h 2013-09-30 17:13:36 +0000
@@ -67,6 +67,9 @@
6767
68 void set_lifecycle_state(MirLifecycleState state);68 void set_lifecycle_state(MirLifecycleState state);
6969
70 void receive_focus(std::shared_ptr<InputTargeter> const& targeter, std::shared_ptr<SurfaceController> const& controller);
71 void relinquish_focus();
72
70protected:73protected:
71 ApplicationSession(ApplicationSession const&) = delete;74 ApplicationSession(ApplicationSession const&) = delete;
72 ApplicationSession& operator=(ApplicationSession const&) = delete;75 ApplicationSession& operator=(ApplicationSession const&) = delete;
@@ -79,6 +82,7 @@
79 std::shared_ptr<frontend::EventSink> const event_sink;82 std::shared_ptr<frontend::EventSink> const event_sink;
8083
81 frontend::SurfaceId next_id();84 frontend::SurfaceId next_id();
85 std::shared_ptr<Surface> default_surface_locked(std::unique_lock<std::mutex> const& lock) const;
8286
83 std::atomic<int> next_surface_id;87 std::atomic<int> next_surface_id;
8488
@@ -86,6 +90,8 @@
86 Surfaces::const_iterator checked_find(frontend::SurfaceId id) const;90 Surfaces::const_iterator checked_find(frontend::SurfaceId id) const;
87 std::mutex mutable surfaces_mutex;91 std::mutex mutable surfaces_mutex;
88 Surfaces surfaces;92 Surfaces surfaces;
93
94 std::weak_ptr<Surface> last_focused_surface;
89};95};
9096
91}97}
9298
=== modified file 'include/server/mir/shell/default_focus_mechanism.h'
--- include/server/mir/shell/default_focus_mechanism.h 2013-08-28 03:41:48 +0000
+++ include/server/mir/shell/default_focus_mechanism.h 2013-09-30 17:13:36 +0000
@@ -50,8 +50,8 @@
50 std::shared_ptr<InputTargeter> const input_targeter;50 std::shared_ptr<InputTargeter> const input_targeter;
51 std::shared_ptr<SurfaceController> const surface_controller;51 std::shared_ptr<SurfaceController> const surface_controller;
5252
53 std::mutex surface_focus_lock;53 std::mutex focus_lock;
54 std::weak_ptr<Surface> currently_focused_surface;54 std::weak_ptr<Session> currently_focused_session;
55};55};
5656
57}57}
5858
=== modified file 'include/server/mir/shell/session.h'
--- include/server/mir/shell/session.h 2013-08-28 03:41:48 +0000
+++ include/server/mir/shell/session.h 2013-09-30 17:13:36 +0000
@@ -28,6 +28,8 @@
28namespace shell28namespace shell
29{29{
30class Surface;30class Surface;
31class InputTargeter;
32class SurfaceController;
3133
32class Session : public frontend::Session34class Session : public frontend::Session
33{35{
@@ -37,6 +39,9 @@
3739
38 virtual void take_snapshot(SnapshotCallback const& snapshot_taken) = 0;40 virtual void take_snapshot(SnapshotCallback const& snapshot_taken) = 0;
39 virtual std::shared_ptr<Surface> default_surface() const = 0;41 virtual std::shared_ptr<Surface> default_surface() const = 0;
42
43 virtual void receive_focus(std::shared_ptr<InputTargeter> const& targeter, std::shared_ptr<SurfaceController> const& controller) = 0;
44 virtual void relinquish_focus() = 0;
40};45};
4146
42}47}
4348
=== modified file 'include/test/mir_test_doubles/mock_shell_session.h'
--- include/test/mir_test_doubles/mock_shell_session.h 2013-08-28 03:41:48 +0000
+++ include/test/mir_test_doubles/mock_shell_session.h 2013-09-30 17:13:36 +0000
@@ -49,6 +49,9 @@
49 49
50 MOCK_METHOD1(send_display_config, void(graphics::DisplayConfiguration const&));50 MOCK_METHOD1(send_display_config, void(graphics::DisplayConfiguration const&));
51 MOCK_METHOD3(configure_surface, int(frontend::SurfaceId, MirSurfaceAttrib, int));51 MOCK_METHOD3(configure_surface, int(frontend::SurfaceId, MirSurfaceAttrib, int));
52
53 MOCK_METHOD2(receive_focus, void(std::shared_ptr<shell::InputTargeter> const&, std::shared_ptr<shell::SurfaceController> const&));
54 MOCK_METHOD0(relinquish_focus, void());
52};55};
5356
54}57}
5558
=== modified file 'include/test/mir_test_doubles/stub_ipc_factory.h'
--- include/test/mir_test_doubles/stub_ipc_factory.h 2013-08-28 03:41:48 +0000
+++ include/test/mir_test_doubles/stub_ipc_factory.h 2013-09-30 17:13:36 +0000
@@ -24,6 +24,7 @@
24#include "mir/frontend/protobuf_ipc_factory.h"24#include "mir/frontend/protobuf_ipc_factory.h"
25#include "mir/frontend/resource_cache.h"25#include "mir/frontend/resource_cache.h"
26#include "mir/frontend/null_message_processor_report.h"26#include "mir/frontend/null_message_processor_report.h"
27#include "mir/frontend/messenger_report.h"
2728
28namespace mir29namespace mir
29{30{
@@ -53,10 +54,14 @@
53 return cache;54 return cache;
54 }55 }
5556
56 virtual std::shared_ptr<frontend::MessageProcessorReport> report()57 virtual std::shared_ptr<frontend::MessageProcessorReport> message_processor_report()
57 {58 {
58 return std::make_shared<frontend::NullMessageProcessorReport>();59 return std::make_shared<frontend::NullMessageProcessorReport>();
59 }60 }
61 virtual std::shared_ptr<frontend::MessengerReport> messenger_report()
62 {
63 return std::make_shared<frontend::NullMessengerReport>();
64 }
6065
61 std::shared_ptr<protobuf::DisplayServer> server;66 std::shared_ptr<protobuf::DisplayServer> server;
62 std::shared_ptr<frontend::ResourceCache> const cache;67 std::shared_ptr<frontend::ResourceCache> const cache;
6368
=== modified file 'include/test/mir_test_doubles/stub_shell_session.h'
--- include/test/mir_test_doubles/stub_shell_session.h 2013-08-13 22:20:37 +0000
+++ include/test/mir_test_doubles/stub_shell_session.h 2013-09-30 17:13:36 +0000
@@ -71,6 +71,14 @@
71 {71 {
72 return std::shared_ptr<shell::Surface>();72 return std::shared_ptr<shell::Surface>();
73 }73 }
74
75 void receive_focus(std::shared_ptr<shell::InputTargeter> const&,
76 std::shared_ptr<shell::SurfaceController> const&)
77 {
78 }
79 void relinquish_focus()
80 {
81 }
74};82};
7583
76}84}
7785
=== modified file 'src/server/default_server_configuration.cpp'
--- src/server/default_server_configuration.cpp 2013-09-24 17:25:47 +0000
+++ src/server/default_server_configuration.cpp 2013-09-30 17:13:36 +0000
@@ -30,6 +30,7 @@
30#include "mir/frontend/protobuf_ipc_factory.h"30#include "mir/frontend/protobuf_ipc_factory.h"
31#include "mir/frontend/session_mediator_report.h"31#include "mir/frontend/session_mediator_report.h"
32#include "mir/frontend/null_message_processor_report.h"32#include "mir/frontend/null_message_processor_report.h"
33#include "mir/frontend/messenger_report.h"
33#include "mir/frontend/session_mediator.h"34#include "mir/frontend/session_mediator.h"
34#include "mir/frontend/session_authorizer.h"35#include "mir/frontend/session_authorizer.h"
35#include "mir/frontend/global_event_sender.h"36#include "mir/frontend/global_event_sender.h"
@@ -75,6 +76,7 @@
75#include "mir/logging/session_mediator_report.h"76#include "mir/logging/session_mediator_report.h"
76#include "mir/logging/message_processor_report.h"77#include "mir/logging/message_processor_report.h"
77#include "mir/logging/display_report.h"78#include "mir/logging/display_report.h"
79#include "mir/logging/messenger_report.h"
78#include "mir/lttng/message_processor_report.h"80#include "mir/lttng/message_processor_report.h"
79#include "mir/lttng/input_report.h"81#include "mir/lttng/input_report.h"
80#include "mir/shell/surface_source.h"82#include "mir/shell/surface_source.h"
@@ -113,13 +115,15 @@
113 explicit DefaultIpcFactory(115 explicit DefaultIpcFactory(
114 std::shared_ptr<mf::Shell> const& shell,116 std::shared_ptr<mf::Shell> const& shell,
115 std::shared_ptr<mf::SessionMediatorReport> const& sm_report,117 std::shared_ptr<mf::SessionMediatorReport> const& sm_report,
116 std::shared_ptr<mf::MessageProcessorReport> const& mr_report,118 std::shared_ptr<mf::MessageProcessorReport> const& mp_report,
119 std::shared_ptr<mf::MessengerReport> const& messenger_report,
117 std::shared_ptr<mg::Platform> const& graphics_platform,120 std::shared_ptr<mg::Platform> const& graphics_platform,
118 std::shared_ptr<mf::DisplayChanger> const& display_changer,121 std::shared_ptr<mf::DisplayChanger> const& display_changer,
119 std::shared_ptr<mg::GraphicBufferAllocator> const& buffer_allocator) :122 std::shared_ptr<mg::GraphicBufferAllocator> const& buffer_allocator) :
120 shell(shell),123 shell(shell),
121 sm_report(sm_report),124 sm_report(sm_report),
122 mp_report(mr_report),125 mp_report(mp_report),
126 msger_report(messenger_report),
123 cache(std::make_shared<mf::ResourceCache>()),127 cache(std::make_shared<mf::ResourceCache>()),
124 graphics_platform(graphics_platform),128 graphics_platform(graphics_platform),
125 display_changer(display_changer),129 display_changer(display_changer),
@@ -131,6 +135,7 @@
131 std::shared_ptr<mf::Shell> shell;135 std::shared_ptr<mf::Shell> shell;
132 std::shared_ptr<mf::SessionMediatorReport> const sm_report;136 std::shared_ptr<mf::SessionMediatorReport> const sm_report;
133 std::shared_ptr<mf::MessageProcessorReport> const mp_report;137 std::shared_ptr<mf::MessageProcessorReport> const mp_report;
138 std::shared_ptr<mf::MessengerReport> const msger_report;
134 std::shared_ptr<mf::ResourceCache> const cache;139 std::shared_ptr<mf::ResourceCache> const cache;
135 std::shared_ptr<mg::Platform> const graphics_platform;140 std::shared_ptr<mg::Platform> const graphics_platform;
136 std::shared_ptr<mf::DisplayChanger> const display_changer;141 std::shared_ptr<mf::DisplayChanger> const display_changer;
@@ -164,16 +169,21 @@
164 return cache;169 return cache;
165 }170 }
166171
167 virtual std::shared_ptr<mf::MessageProcessorReport> report()172 virtual std::shared_ptr<mf::MessageProcessorReport> message_processor_report()
168 {173 {
169 return mp_report;174 return mp_report;
170 }175 }
176 virtual std::shared_ptr<mf::MessengerReport> messenger_report()
177 {
178 return msger_report;
179 }
171};180};
172181
173char const* const server_socket_opt = "file";182char const* const server_socket_opt = "file";
174char const* const no_server_socket_opt = "no-file";183char const* const no_server_socket_opt = "no-file";
175char const* const session_mediator_report_opt = "session-mediator-report";184char const* const session_mediator_report_opt = "session-mediator-report";
176char const* const msg_processor_report_opt = "msg-processor-report";185char const* const msg_processor_report_opt = "msg-processor-report";
186char const* const messenger_report_opt = "messenger-report";
177char const* const display_report_opt = "display-report";187char const* const display_report_opt = "display-report";
178char const* const legacy_input_report_opt = "legacy-input-report";188char const* const legacy_input_report_opt = "legacy-input-report";
179char const* const input_report_opt = "input-report";189char const* const input_report_opt = "input-report";
@@ -824,6 +834,7 @@
824 shell,834 shell,
825 the_session_mediator_report(),835 the_session_mediator_report(),
826 the_message_processor_report(),836 the_message_processor_report(),
837 the_messenger_report(),
827 the_graphics_platform(),838 the_graphics_platform(),
828 the_frontend_display_changer(), allocator);839 the_frontend_display_changer(), allocator);
829 });840 });
@@ -890,6 +901,23 @@
890 });901 });
891}902}
892903
904std::shared_ptr<mf::MessengerReport>
905mir::DefaultServerConfiguration::the_messenger_report()
906{
907 return messenger_report(
908 [this]() -> std::shared_ptr<mf::MessengerReport>
909 {
910 auto report_opt = the_options()->get(messenger_report_opt, off_opt_value);
911 if (report_opt == log_opt_value)
912 {
913 return std::make_shared<ml::MessengerReport>(the_logger());
914 }
915 else
916 {
917 return std::make_shared<mf::NullMessengerReport>();
918 }
919 });
920}
893921
894std::shared_ptr<ml::Logger> mir::DefaultServerConfiguration::the_logger()922std::shared_ptr<ml::Logger> mir::DefaultServerConfiguration::the_logger()
895{923{
896924
=== modified file 'src/server/frontend/CMakeLists.txt'
--- src/server/frontend/CMakeLists.txt 2013-09-24 13:27:33 +0000
+++ src/server/frontend/CMakeLists.txt 2013-09-30 17:13:36 +0000
@@ -5,6 +5,7 @@
5 session_mediator.cpp5 session_mediator.cpp
6 null_session_mediator_report.cpp6 null_session_mediator_report.cpp
7 null_message_processor_report.cpp7 null_message_processor_report.cpp
8 null_messenger_report.cpp
8 protobuf_message_processor.cpp9 protobuf_message_processor.cpp
9 protobuf_buffer_packer.cpp10 protobuf_buffer_packer.cpp
10 null_message_processor.cpp11 null_message_processor.cpp
1112
=== added file 'src/server/frontend/null_messenger_report.cpp'
--- src/server/frontend/null_messenger_report.cpp 1970-01-01 00:00:00 +0000
+++ src/server/frontend/null_messenger_report.cpp 2013-09-30 17:13:36 +0000
@@ -0,0 +1,25 @@
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Robert Carr <robert.carr@canonical.com>
17 */
18
19#include "mir/frontend/messenger_report.h"
20
21namespace mf = mir::frontend;
22
23void mf::NullMessengerReport::error(std::string const&)
24{
25}
026
=== modified file 'src/server/frontend/protobuf_session_creator.cpp'
--- src/server/frontend/protobuf_session_creator.cpp 2013-09-24 13:27:33 +0000
+++ src/server/frontend/protobuf_session_creator.cpp 2013-09-30 17:13:36 +0000
@@ -53,7 +53,7 @@
5353
54void mf::ProtobufSessionCreator::create_session_for(std::shared_ptr<ba::local::stream_protocol::socket> const& socket)54void mf::ProtobufSessionCreator::create_session_for(std::shared_ptr<ba::local::stream_protocol::socket> const& socket)
55{55{
56 auto const messenger = std::make_shared<detail::SocketMessenger>(socket);56 auto const messenger = std::make_shared<detail::SocketMessenger>(socket, ipc_factory->messenger_report());
57 auto const client_pid = messenger->client_pid();57 auto const client_pid = messenger->client_pid();
5858
59 if (session_authorizer->connection_is_allowed(client_pid))59 if (session_authorizer->connection_is_allowed(client_pid))
@@ -64,7 +64,7 @@
64 messenger,64 messenger,
65 ipc_factory->make_ipc_server(event_sink, authorized_to_resize_display),65 ipc_factory->make_ipc_server(event_sink, authorized_to_resize_display),
66 ipc_factory->resource_cache(),66 ipc_factory->resource_cache(),
67 ipc_factory->report());67 ipc_factory->message_processor_report());
6868
69 const auto& session = std::make_shared<mfd::SocketSession>(messenger, next_id(), connected_sessions, msg_processor);69 const auto& session = std::make_shared<mfd::SocketSession>(messenger, next_id(), connected_sessions, msg_processor);
70 connected_sessions->add(session);70 connected_sessions->add(session);
7171
=== modified file 'src/server/frontend/socket_messenger.cpp'
--- src/server/frontend/socket_messenger.cpp 2013-09-25 14:18:18 +0000
+++ src/server/frontend/socket_messenger.cpp 2013-09-30 17:13:36 +0000
@@ -18,13 +18,16 @@
1818
19#include "socket_messenger.h"19#include "socket_messenger.h"
20#include "mir/frontend/client_constants.h"20#include "mir/frontend/client_constants.h"
21#include "mir/frontend/messenger_report.h"
2122
22namespace mfd = mir::frontend::detail;23namespace mfd = mir::frontend::detail;
23namespace bs = boost::system;24namespace bs = boost::system;
24namespace ba = boost::asio;25namespace ba = boost::asio;
2526
26mfd::SocketMessenger::SocketMessenger(std::shared_ptr<ba::local::stream_protocol::socket> const& socket)27mfd::SocketMessenger::SocketMessenger(std::shared_ptr<ba::local::stream_protocol::socket> const& socket,
27 : socket(socket)28 std::shared_ptr<MessengerReport> const& report)
29 : socket(socket),
30 report(report)
28{31{
29 whole_message.reserve(serialization_buffer_size);32 whole_message.reserve(serialization_buffer_size);
30}33}
@@ -59,8 +62,14 @@
59 // function has completed (if it would be executed asynchronously.62 // function has completed (if it would be executed asynchronously.
60 // NOTE: we rely on this synchronous behavior as per the comment in63 // NOTE: we rely on this synchronous behavior as per the comment in
61 // mf::SessionMediator::create_surface64 // mf::SessionMediator::create_surface
65
62 boost::system::error_code err;66 boost::system::error_code err;
63 ba::write(*socket, ba::buffer(whole_message), err);67 ba::write(*socket, ba::buffer(whole_message), err);
68 if (!err)
69 {
70 report->error(err.message());
71 }
72
64}73}
6574
66void mfd::SocketMessenger::send_fds(std::vector<int32_t> const& fds)75void mfd::SocketMessenger::send_fds(std::vector<int32_t> const& fds)
6776
=== modified file 'src/server/frontend/socket_messenger.h'
--- src/server/frontend/socket_messenger.h 2013-08-28 03:41:48 +0000
+++ src/server/frontend/socket_messenger.h 2013-09-30 17:13:36 +0000
@@ -26,13 +26,16 @@
26{26{
27namespace frontend27namespace frontend
28{28{
29class MessengerReport;
30
29namespace detail31namespace detail
30{32{
31class SocketMessenger : public MessageSender,33class SocketMessenger : public MessageSender,
32 public MessageReceiver34 public MessageReceiver
33{35{
34public:36public:
35 SocketMessenger(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket);37 SocketMessenger(std::shared_ptr<boost::asio::local::stream_protocol::socket> const& socket,
38 std::shared_ptr<frontend::MessengerReport> const& report);
3639
37 void send(std::string const& body);40 void send(std::string const& body);
38 void send_fds(std::vector<int32_t> const& fds);41 void send_fds(std::vector<int32_t> const& fds);
@@ -42,6 +45,8 @@
4245
43private:46private:
44 std::shared_ptr<boost::asio::local::stream_protocol::socket> socket;47 std::shared_ptr<boost::asio::local::stream_protocol::socket> socket;
48 std::shared_ptr<MessengerReport> const report;
49
45 std::vector<char> whole_message;50 std::vector<char> whole_message;
46};51};
47}52}
4853
=== modified file 'src/server/logging/CMakeLists.txt'
--- src/server/logging/CMakeLists.txt 2013-08-28 03:41:48 +0000
+++ src/server/logging/CMakeLists.txt 2013-09-30 17:13:36 +0000
@@ -6,6 +6,7 @@
6 message_processor_report.cpp6 message_processor_report.cpp
7 display_report.cpp7 display_report.cpp
8 input_report.cpp8 input_report.cpp
9 messenger_report.cpp
9)10)
1011
11add_library(12add_library(
1213
=== added file 'src/server/logging/messenger_report.cpp'
--- src/server/logging/messenger_report.cpp 1970-01-01 00:00:00 +0000
+++ src/server/logging/messenger_report.cpp 2013-09-30 17:13:36 +0000
@@ -0,0 +1,46 @@
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Alan Griffiths <alan@octopull.co.uk>
17 */
18
19#include "mir/logging/messenger_report.h"
20#include "mir/logging/logger.h"
21
22#include "std/MirLog.h"
23#include <std/Log.h>
24
25
26#include <sstream>
27#include <cstring>
28#include <mutex>
29
30namespace ml = mir::logging;
31
32ml::MessengerReport::MessengerReport(const std::shared_ptr<Logger>& logger)
33 : logger(logger)
34{
35}
36
37const char* ml::MessengerReport::component()
38{
39 static const char* s = "messenger";
40 return s;
41}
42
43void ml::MessengerReport::error(std::string const& error_message)
44{
45 logger->log<Logger::informational>(error_message, component());
46}
047
=== modified file 'src/server/shell/application_session.cpp'
--- src/server/shell/application_session.cpp 2013-08-28 03:41:48 +0000
+++ src/server/shell/application_session.cpp 2013-09-30 17:13:36 +0000
@@ -21,6 +21,7 @@
21#include "mir/shell/surface_factory.h"21#include "mir/shell/surface_factory.h"
22#include "mir/shell/snapshot_strategy.h"22#include "mir/shell/snapshot_strategy.h"
23#include "mir/shell/session_listener.h"23#include "mir/shell/session_listener.h"
24#include "mir/shell/input_targeter.h"
24#include "mir/frontend/event_sink.h"25#include "mir/frontend/event_sink.h"
2526
26#include <boost/throw_exception.hpp>27#include <boost/throw_exception.hpp>
@@ -99,16 +100,21 @@
99 snapshot_strategy->take_snapshot_of(default_surface(), snapshot_taken);100 snapshot_strategy->take_snapshot_of(default_surface(), snapshot_taken);
100}101}
101102
102std::shared_ptr<msh::Surface> msh::ApplicationSession::default_surface() const103std::shared_ptr<msh::Surface> msh::ApplicationSession::default_surface_locked(std::unique_lock<std::mutex> const& /* lock */) const
103{104{
104 std::unique_lock<std::mutex> lock(surfaces_mutex);
105
106 if (surfaces.size())105 if (surfaces.size())
107 return surfaces.begin()->second;106 return surfaces.begin()->second;
108 else107 else
109 return std::shared_ptr<msh::Surface>();108 return std::shared_ptr<msh::Surface>();
110}109}
111110
111std::shared_ptr<msh::Surface> msh::ApplicationSession::default_surface() const
112{
113 std::unique_lock<std::mutex> lock(surfaces_mutex);
114
115 return default_surface_locked(lock);
116}
117
112void msh::ApplicationSession::destroy_surface(mf::SurfaceId id)118void msh::ApplicationSession::destroy_surface(mf::SurfaceId id)
113{119{
114 std::unique_lock<std::mutex> lock(surfaces_mutex);120 std::unique_lock<std::mutex> lock(surfaces_mutex);
@@ -171,3 +177,33 @@
171{177{
172 event_sink->handle_lifecycle_event(state);178 event_sink->handle_lifecycle_event(state);
173}179}
180
181void msh::ApplicationSession::receive_focus(std::shared_ptr<msh::InputTargeter> const& targeter,
182 std::shared_ptr<SurfaceController> const& controller)
183{
184 std::unique_lock<std::mutex> lock(surfaces_mutex);
185 if (surfaces.size() == 0)
186 {
187 targeter->focus_cleared();
188 return;
189 }
190 // Use default_surface_locked idiom instead
191 auto focus_surface = surfaces.begin()->second;
192
193 focus_surface->raise(controller);
194 focus_surface->take_input_focus(targeter);
195 focus_surface->configure(mir_surface_attrib_focus, mir_surface_focused);
196
197 last_focused_surface = focus_surface;
198}
199
200void msh::ApplicationSession::relinquish_focus()
201{
202 std::unique_lock<std::mutex> lock(surfaces_mutex);
203 auto surf = last_focused_surface.lock();
204 if (surf)
205 {
206 surf->configure(mir_surface_attrib_focus, mir_surface_unfocused);
207 }
208 last_focused_surface.reset();
209}
174210
=== modified file 'src/server/shell/default_focus_mechanism.cpp'
--- src/server/shell/default_focus_mechanism.cpp 2013-08-28 03:41:48 +0000
+++ src/server/shell/default_focus_mechanism.cpp 2013-09-30 17:13:36 +0000
@@ -35,28 +35,20 @@
3535
36void msh::DefaultFocusMechanism::set_focus_to(std::shared_ptr<Session> const& focus_session)36void msh::DefaultFocusMechanism::set_focus_to(std::shared_ptr<Session> const& focus_session)
37{37{
38 std::lock_guard<std::mutex> lg(focus_lock);
39
40 auto last_session = currently_focused_session.lock();
41 if (last_session)
42 {
43 last_session->relinquish_focus();
44 }
45
38 // TODO: This path should be encapsulated in a seperate clear_focus message46 // TODO: This path should be encapsulated in a seperate clear_focus message
39 if (!focus_session)47 if (!focus_session)
40 {48 {
41 input_targeter->focus_cleared();49 input_targeter->focus_cleared();
42 return;50 return;
43 }51 }
44 52 focus_session->receive_focus(input_targeter, surface_controller);
45 auto surface = focus_session->default_surface();53 currently_focused_session = focus_session;
46 if (surface)
47 {
48 std::lock_guard<std::mutex> lg(surface_focus_lock);
49 auto current_focus = currently_focused_surface.lock();
50 if (current_focus)
51 current_focus->configure(mir_surface_attrib_focus, mir_surface_unfocused);
52 surface->configure(mir_surface_attrib_focus, mir_surface_focused);
53 currently_focused_surface = surface;
54
55 surface->raise(surface_controller);
56 surface->take_input_focus(input_targeter);
57 }
58 else
59 {
60 input_targeter->focus_cleared();
61 }
62}54}
6355
=== modified file 'tests/acceptance-tests/test_client_focus_notification.cpp'
--- tests/acceptance-tests/test_client_focus_notification.cpp 2013-09-25 18:39:57 +0000
+++ tests/acceptance-tests/test_client_focus_notification.cpp 2013-09-30 17:13:36 +0000
@@ -152,7 +152,9 @@
152 void expect_events(mt::WaitCondition* all_events_received) override152 void expect_events(mt::WaitCondition* all_events_received) override
153 {153 {
154 EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_focused)))).Times(1)154 EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_focused)))).Times(1)
155 .WillOnce(mt::WakeUp(all_events_received));155 .WillOnce(mt::WakeUp(all_events_received)); // Now we close the surface generating an unfocused event
156 // libmirclient guarantees we will see this before mir_surface_release finishes, so we don't need further
157 // synchronization
156 EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_unfocused)))).Times(1);158 EXPECT_CALL(*observer, see(Pointee(mt::SurfaceEvent(mir_surface_attrib_focus, mir_surface_unfocused)))).Times(1);
157 }159 }
158 } client_config;160 } client_config;
159161
=== modified file 'tests/unit-tests/frontend/CMakeLists.txt'
--- tests/unit-tests/frontend/CMakeLists.txt 2013-09-24 14:13:15 +0000
+++ tests/unit-tests/frontend/CMakeLists.txt 2013-09-30 17:13:36 +0000
@@ -8,6 +8,7 @@
8 ${CMAKE_CURRENT_SOURCE_DIR}/test_resource_cache.cpp8 ${CMAKE_CURRENT_SOURCE_DIR}/test_resource_cache.cpp
9 ${CMAKE_CURRENT_SOURCE_DIR}/test_session_mediator.cpp9 ${CMAKE_CURRENT_SOURCE_DIR}/test_session_mediator.cpp
10 ${CMAKE_CURRENT_SOURCE_DIR}/test_socket_session.cpp10 ${CMAKE_CURRENT_SOURCE_DIR}/test_socket_session.cpp
11 ${CMAKE_CURRENT_SOURCE_DIR}/test_socket_messenger.cpp
11 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_sender.cpp12 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_sender.cpp
12 ${CMAKE_CURRENT_SOURCE_DIR}/test_global_event_sender.cpp13 ${CMAKE_CURRENT_SOURCE_DIR}/test_global_event_sender.cpp
13)14)
1415
=== added file 'tests/unit-tests/frontend/test_socket_messenger.cpp'
--- tests/unit-tests/frontend/test_socket_messenger.cpp 1970-01-01 00:00:00 +0000
+++ tests/unit-tests/frontend/test_socket_messenger.cpp 2013-09-30 17:13:36 +0000
@@ -0,0 +1,37 @@
1/*
2 * Copyright © 2013 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Daniel van Vugt <daniel.van.vugt@canonical.com>
17 */
18
19#include "mir/frontend/messenger_report.h"
20#include "src/server/frontend/socket_messenger.h"
21
22#include <gmock/gmock.h>
23#include <gtest/gtest.h>
24
25namespace mf = mir::frontend;
26
27using namespace mf::detail;
28using namespace boost::asio;
29
30TEST(SocketMessengerTest, write_failures_never_throw)
31{
32 io_service svc;
33 auto sock = std::make_shared<local::stream_protocol::socket>(svc);
34 SocketMessenger mess(sock, std::make_shared<mf::NullMessengerReport>());
35
36 EXPECT_NO_THROW( mess.send("foo") );
37}
038
=== modified file 'tests/unit-tests/shell/test_default_focus_mechanism.cpp'
--- tests/unit-tests/shell/test_default_focus_mechanism.cpp 2013-08-28 03:41:48 +0000
+++ tests/unit-tests/shell/test_default_focus_mechanism.cpp 2013-09-30 17:13:36 +0000
@@ -47,80 +47,34 @@
47namespace mt = mir::test;47namespace mt = mir::test;
48namespace mtd = mir::test::doubles;48namespace mtd = mir::test::doubles;
4949
50TEST(DefaultFocusMechanism, raises_default_surface)50TEST(DefaultFocusMechanism, hands_focus_to_session)
51{51{
52 using namespace ::testing;52 using namespace ::testing;
53 53
54 NiceMock<mtd::MockShellSession> app1;54 mtd::MockShellSession app1;
55 mtd::MockSurface mock_surface(&app1, std::make_shared<mtd::StubSurfaceBuilder>());55 EXPECT_CALL(app1, receive_focus(_, _)).Times(1);
56 {56
57 InSequence seq;57 msh::DefaultFocusMechanism focus_mechanism(std::make_shared<mtd::StubInputTargeter>(), std::make_shared<mtd::StubSurfaceController>());
58 EXPECT_CALL(app1, default_surface()).Times(1)58
59 .WillOnce(Return(mt::fake_shared(mock_surface)));59 focus_mechanism.set_focus_to(mt::fake_shared(app1));
60 }60}
6161
62 auto controller = std::make_shared<mtd::StubSurfaceController>();62TEST(DefaultFocusMechanism, relinquishes_focus_from_last_session)
63 EXPECT_CALL(mock_surface, raise(Eq(controller))).Times(1);63{
64 mtd::StubInputTargeter targeter;64 using namespace ::testing;
65 msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(targeter), controller);65
66 66 auto app1 = std::make_shared<mtd::MockShellSession>();
67 focus_mechanism.set_focus_to(mt::fake_shared(app1));67 auto app2 = std::make_shared<mtd::MockShellSession>();
68}68
6969 {
70TEST(DefaultFocusMechanism, mechanism_notifies_default_surface_of_focus_changes)70 InSequence seq;
71{71 EXPECT_CALL(*app1, receive_focus(_, _)).Times(1);
72 using namespace ::testing;72 EXPECT_CALL(*app1, relinquish_focus()).Times(1);
7373 EXPECT_CALL(*app2, receive_focus(_, _)).Times(1);
74 NiceMock<mtd::MockShellSession> app1, app2;74 }
75 mtd::MockSurface mock_surface1(&app1, std::make_shared<mtd::StubSurfaceBuilder>());75
76 mtd::MockSurface mock_surface2(&app2, std::make_shared<mtd::StubSurfaceBuilder>());76 msh::DefaultFocusMechanism focus_mechanism(std::make_shared<mtd::StubInputTargeter>(), std::make_shared<mtd::StubSurfaceController>());
77 77
78 ON_CALL(app1, default_surface()).WillByDefault(Return(mt::fake_shared(mock_surface1)));78 focus_mechanism.set_focus_to(app1);
79 ON_CALL(app2, default_surface()).WillByDefault(Return(mt::fake_shared(mock_surface2)));79 focus_mechanism.set_focus_to(app2);
80
81
82 {
83 InSequence seq;
84 EXPECT_CALL(mock_surface1, configure(mir_surface_attrib_focus, mir_surface_focused)).Times(1);
85 EXPECT_CALL(mock_surface1, configure(mir_surface_attrib_focus, mir_surface_unfocused)).Times(1);
86 EXPECT_CALL(mock_surface2, configure(mir_surface_attrib_focus, mir_surface_focused)).Times(1);
87 }
88
89 msh::DefaultFocusMechanism focus_mechanism(std::make_shared<mtd::StubInputTargeter>(),
90 std::make_shared<mtd::StubSurfaceController>());
91
92 focus_mechanism.set_focus_to(mt::fake_shared(app1));
93 focus_mechanism.set_focus_to(mt::fake_shared(app2));
94}
95
96TEST(DefaultFocusMechanism, sets_input_focus)
97{
98 using namespace ::testing;
99
100 NiceMock<mtd::MockShellSession> app1;
101 mtd::MockSurface mock_surface(&app1, std::make_shared<mtd::StubSurfaceBuilder>());
102 {
103 InSequence seq;
104 EXPECT_CALL(app1, default_surface()).Times(1)
105 .WillOnce(Return(mt::fake_shared(mock_surface)));
106 EXPECT_CALL(app1, default_surface()).Times(1)
107 .WillOnce(Return(std::shared_ptr<msh::Surface>()));
108 }
109
110 mtd::MockInputTargeter targeter;
111
112 msh::DefaultFocusMechanism focus_mechanism(mt::fake_shared(targeter), std::make_shared<mtd::StubSurfaceController>());
113
114 {
115 InSequence seq;
116 EXPECT_CALL(mock_surface, take_input_focus(_)).Times(1);
117 // When we have no default surface.
118 EXPECT_CALL(targeter, focus_cleared()).Times(1);
119 // When we have no session.
120 EXPECT_CALL(targeter, focus_cleared()).Times(1);
121 }
122
123 focus_mechanism.set_focus_to(mt::fake_shared(app1));
124 focus_mechanism.set_focus_to(mt::fake_shared(app1));
125 focus_mechanism.set_focus_to(std::shared_ptr<msh::Session>());
126}80}

Subscribers

People subscribed via source and target branches