Set focus to current active window

This commit is contained in:
Simon Fels 2016-11-26 13:04:50 +01:00
commit 84b3fa430b
15 changed files with 189 additions and 41 deletions

View file

@ -82,6 +82,7 @@ void AndroidApiStub::install(const std::string &path) {
}
void AndroidApiStub::application_installed(Request<protobuf::rpc::Void> *request) {
(void) request;
install_wait_handle_.result_received();
}
@ -110,6 +111,7 @@ void AndroidApiStub::launch(const std::string &package, const std::string &activ
}
void AndroidApiStub::application_launched(Request<protobuf::rpc::Void> *request) {
(void) request;
launch_wait_handle_.result_received();
}
@ -143,7 +145,37 @@ void AndroidApiStub::set_dns_servers(const std::string &domain, const std::vecto
}
void AndroidApiStub::dns_servers_set(Request<protobuf::rpc::Void> *request) {
(void) request;
set_dns_servers_wait_handle_.result_received();
}
void AndroidApiStub::set_focused_task(const std::int32_t &id) {
ensure_rpc_channel();
auto c = std::make_shared<Request<protobuf::rpc::Void>>();
protobuf::bridge::SetFocusedTask message;
message.set_id(id);
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
set_focused_task_handle_.expect_result();
}
channel_->call_method("set_focused_task",
&message,
c->response.get(),
google::protobuf::NewCallback(this, &AndroidApiStub::focused_task_set, c.get()));
set_focused_task_handle_.wait_for_all();
if (c->response->has_error())
throw std::runtime_error(c->response->error());
}
void AndroidApiStub::focused_task_set(Request<protobuf::rpc::Void> *request) {
(void) request;
set_focused_task_handle_.result_received();
}
} // namespace bridge
} // namespace anbox

View file

@ -46,6 +46,7 @@ public:
void launch(const std::string &package, const std::string &activity) override;
void set_dns_servers(const std::string &domain, const std::vector<std::string> &servers);
void set_focused_task(const std::int32_t &id);
private:
void ensure_rpc_channel();
@ -60,12 +61,14 @@ private:
void application_installed(Request<protobuf::rpc::Void> *request);
void application_launched(Request<protobuf::rpc::Void> *request);
void dns_servers_set(Request<protobuf::rpc::Void> *request);
void focused_task_set(Request<protobuf::rpc::Void> *request);
mutable std::mutex mutex_;
std::shared_ptr<rpc::Channel> channel_;
common::WaitHandle install_wait_handle_;
common::WaitHandle launch_wait_handle_;
common::WaitHandle set_dns_servers_wait_handle_;
common::WaitHandle set_focused_task_handle_;
};
} // namespace bridge
} // namespace anbox

View file

@ -89,7 +89,9 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
auto input_manager = std::make_shared<input::Manager>(rt);
auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager);
auto android_api_stub = std::make_shared<bridge::AndroidApiStub>();
auto policy = std::make_shared<ubuntu::PlatformPolicy>(input_manager, android_api_stub);
// FIXME this needs to be removed and solved differently behind the scenes
registerDisplayManager(policy);
@ -116,7 +118,6 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
renderer->socket_path(),
icon_));
auto android_api_stub = std::make_shared<bridge::AndroidApiStub>();
auto bridge_connector = std::make_shared<network::PublishedSocketConnector>(
utils::string_format("%s/anbox_bridge", config::socket_path()),

View file

@ -32,6 +32,9 @@ message SetDnsServers {
repeated Server servers = 2;
}
message SetFocusedTask {
required int32 id = 1;
}
message BootFinishedEvent {
}

View file

@ -20,6 +20,7 @@
#include "anbox/ubuntu/keycode_converter.h"
#include "anbox/input/manager.h"
#include "anbox/input/device.h"
#include "anbox/bridge/android_api_stub.h"
#include "anbox/logger.h"
#include <boost/throw_exception.hpp>
@ -199,6 +200,15 @@ void PlatformPolicy::window_deleted(const Window::Id &id) {
windows_.erase(w);
}
void PlatformPolicy::window_wants_focus(const Window::Id &id) {
auto w = windows_.find(id);
if (w == windows_.end())
return;
if (auto window = w->second.lock())
android_api_->set_focused_task(window->task());
}
DisplayManager::DisplayInfo PlatformPolicy::display_info() const {
return display_info_;
}

View file

@ -33,18 +33,23 @@ namespace input {
class Device;
class Manager;
} // namespace input
namespace bridge {
class AndroidApiStub;
} // namespace bridge
namespace ubuntu {
class PlatformPolicy : public std::enable_shared_from_this<PlatformPolicy>,
public wm::PlatformPolicy,
public Window::Observer,
public DisplayManager {
public:
PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager);
PlatformPolicy(const std::shared_ptr<input::Manager> &input_manager,
const std::shared_ptr<bridge::AndroidApiStub> &android_api);
~PlatformPolicy();
std::shared_ptr<wm::Window> create_window(const anbox::wm::Task::Id &task, const anbox::graphics::Rect &frame) override;
void window_deleted(const Window::Id &id) override;
void window_wants_focus(const Window::Id &id) override;
DisplayInfo display_info() const override;
@ -55,6 +60,7 @@ private:
static Window::Id next_window_id();
std::shared_ptr<input::Manager> input_manager_;
std::shared_ptr<bridge::AndroidApiStub> android_api_;
// We don't own the windows anymore after the got created by us so we
// need to be careful once we try to use them again.
std::map<Window::Id, std::weak_ptr<Window>> windows_;

View file

@ -62,7 +62,6 @@ Window::Window(const Id &id,
SDL_GetWindowWMInfo(window_, &info);
switch (info.subsystem) {
case SDL_SYSWM_X11:
DEBUG("Running on X11");
native_display_ = static_cast<EGLNativeDisplayType>(info.info.x11.display);
native_window_ = static_cast<EGLNativeWindowType>(info.info.x11.window);
break;
@ -75,41 +74,6 @@ Window::Window(const Id &id,
int actual_x = 0, actual_y = 0;
SDL_GetWindowSize(window_, &actual_width, &actual_height);
SDL_GetWindowPosition(window_, &actual_x, &actual_y);
DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height);
}
Window::Window(int x, int y, int width, int height) :
wm::Window(0, graphics::Rect{x,y,x + width,y + height}),
native_display_(0),
native_window_(0) {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
window_ = SDL_CreateWindow("anbox", x, y, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
if (!window_) {
const auto message = utils::string_format("Failed to create window: %s", SDL_GetError());
BOOST_THROW_EXCEPTION(std::runtime_error(message));
}
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(window_, &info);
switch (info.subsystem) {
case SDL_SYSWM_X11:
DEBUG("Running on X11");
native_display_ = static_cast<EGLNativeDisplayType>(info.info.x11.display);
native_window_ = static_cast<EGLNativeWindowType>(info.info.x11.window);
break;
default:
ERROR("Unknown subsystem (%d)", info.subsystem);
BOOST_THROW_EXCEPTION(std::runtime_error("SDL subsystem not suported"));
}
int actual_width = 0, actual_height = 0;
int actual_x = 0, actual_y = 0;
SDL_GetWindowSize(window_, &actual_width, &actual_height);
SDL_GetWindowPosition(window_, &actual_x, &actual_y);
DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height);
}
Window::~Window() {
@ -129,8 +93,10 @@ void Window::update_position(int x, int y) {
}
void Window::process_event(const SDL_Event &event) {
switch (event.window.type) {
switch (event.window.event) {
case SDL_WINDOWEVENT_FOCUS_GAINED:
if (observer_)
observer_->window_wants_focus(id_);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
break;

View file

@ -39,10 +39,10 @@ public:
public:
virtual ~Observer();
virtual void window_deleted(const Id &id) = 0;
virtual void window_wants_focus(const Id &id) = 0;
};
Window(const Id &id, const wm::Task::Id &task, const std::shared_ptr<Observer> &observer, const graphics::Rect &frame);
Window(int x, int y, int width, int height);
~Window();
void process_event(const SDL_Event &event);