Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support agl-shell v8 #134

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 179 additions & 11 deletions shell/wayland/display.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,16 @@ void Display::registry_handle_global(void* data,
auto oi = std::make_shared<output_info_t>();
std::fill_n(oi.get(), 1, output_info_t{});
oi->global_id = name;
oi->output = static_cast<struct wl_output*>(
wl_registry_bind(registry, name, &wl_output_interface,
std::min(static_cast<uint32_t>(2), version)));
// be compat with v2 as well
if (version >= WL_OUTPUT_NAME_SINCE_VERSION &&
version >= WL_OUTPUT_DESCRIPTION_SINCE_VERSION)
oi->output = static_cast<struct wl_output*>(
wl_registry_bind(registry, name, &wl_output_interface,
std::min(static_cast<uint32_t>(4), version)));
else
oi->output = static_cast<struct wl_output*>(
wl_registry_bind(registry, name, &wl_output_interface,
std::min(static_cast<uint32_t>(2), version)));
wl_output_add_listener(oi->output, &output_listener, oi.get());
SPDLOG_DEBUG("Wayland: Output [{}]", d->m_all_outputs.size());
d->m_all_outputs.push_back(oi);
Expand All @@ -213,7 +220,7 @@ void Display::registry_handle_global(void* data,
if (version >= 2) {
d->m_agl.shell = static_cast<struct agl_shell*>(
wl_registry_bind(registry, name, &agl_shell_interface,
std::min(static_cast<uint32_t>(4), version)));
std::min(static_cast<uint32_t>(8), version)));
agl_shell_add_listener(d->m_agl.shell, &agl_shell_listener, data);
} else {
d->m_agl.shell = static_cast<struct agl_shell*>(
Expand Down Expand Up @@ -299,9 +306,28 @@ void Display::display_handle_done(void* data,
oi->done = true;
}

void Display::display_handle_name(void* data,
struct wl_output* /* wl_output */,
const char* name) {
auto* oi = static_cast<output_info_t*>(data);
oi->name = std::string(name);
}

void Display::display_handle_desc(void* data,
struct wl_output* /* wl_output */,
const char* desc) {
auto* oi = static_cast<output_info_t*>(data);
oi->desc = std::string(desc);
}

const struct wl_output_listener Display::output_listener = {
display_handle_geometry, display_handle_mode, display_handle_done,
display_handle_scale};
display_handle_scale
#if defined(WL_OUTPUT_NAME_SINCE_VERSION) && \
defined(WL_OUTPUT_DESCRIPTION_SINCE_VERSION)
, display_handle_name, display_handle_desc
#endif
};

void Display::shm_format(void* /* data */,
struct wl_shm* /* wl_shm */,
Expand Down Expand Up @@ -954,6 +980,148 @@ void Display::agl_shell_bound_fail(void* data, struct agl_shell* shell) {
d->m_agl.bound_ok = false;
}

void Display::addAppToStack(std::string app_id) {
if (app_id == "homescreen")
return;

bool found_app = false;
for (auto& i : apps_stack) {
if (i == app_id) {
found_app = true;
break;
}
}

if (!found_app) {
apps_stack.push_back(app_id);
} else {
// fixme
}
}

int Display::find_output_by_name(std::string output_name) {
int index = 0;
for (auto& i : m_all_outputs) {
if (i->name == output_name) {
return index;
}
index++;
}

return -1;
}

void Display::activateApp(std::string app_id) {
int default_output_index = 0;

FML_LOG(INFO) << "got app_id " << app_id;

// search for a pending application which might have a different output
auto iter = pending_app_list.begin();
bool found_pending_app = false;
while (iter != pending_app_list.end()) {
auto app_to_search = iter->first;
FML_LOG(INFO) << "searching for " << app_to_search;

if (app_to_search == app_id) {
found_pending_app = true;
break;
}

iter++;
}

if (found_pending_app) {
auto output_name = iter->second;
default_output_index = find_output_by_name(output_name);

FML_LOG(INFO) << "Found app_id " << app_id << " at all";

if (default_output_index < 0) {
// try with remoting-remote-X which is the streaming
std::string new_remote_output = "remoting-" + output_name;

default_output_index = find_output_by_name(new_remote_output);
if (default_output_index < 0) {
FML_LOG(INFO) << "Not activating app_id " << app_id << " at all";
return;
}
}

pending_app_list.erase(iter);
}

FML_LOG(INFO) << "Activating app_id " << app_id << " on output "
<< default_output_index;
agl_shell_activate_app(m_agl.shell, app_id.c_str(),
m_all_outputs[default_output_index]->output);
wl_display_flush(m_display);
}

void Display::deactivateApp(std::string app_id) {
for (auto& i : apps_stack) {
if (i == app_id) {
// remove it from apps_stack
apps_stack.remove(i);
if (!apps_stack.empty())
activateApp(apps_stack.back());
break;
}
}
}

void Display::processAppStatusEvent(const char* app_id,
const std::string event_type) {
if (!m_agl.shell)
return;

if (event_type == "started") {
activateApp(std::string(app_id));
} else if (event_type == "terminated") {
deactivateApp(std::string(app_id));
} else if (event_type == "deactivated") {
// not handled
}
}

void Display::agl_shell_app_on_output(void* data,
struct agl_shell* agl_shell,
const char* app_id,
const char* output_name) {
auto* d = static_cast<Display*>(data);

FML_LOG(INFO) << "Gove event app_on_out app_id " << app_id << " output name "
<< output_name;

// a couple of use-cases, if there is no app_id in the app_list then it
// means this is a request to map the application, from the start to a
// different output that the default one. We'd get an
// AGL_SHELL_APP_STATE_STARTED which will handle activation.
//
// if there's an app_id then it means we might have gotten an event to
// move the application to another output; so we'd need to process it
// by explicitly calling processAppStatusEvent() which would ultimately
// activate the application on other output. We'd have to pick-up the
// last activated window and activate the default output.
//
// finally if the outputs are identical probably that's an user-error -
// but the compositor won't activate it again, so we don't handle that.
std::pair new_pending_app =
std::pair(std::string(app_id), std::string(output_name));
d->pending_app_list.push_back(new_pending_app);

auto iter = d->apps_stack.begin();
while (iter != d->apps_stack.end()) {
if (*iter == std::string(app_id)) {
FML_LOG(INFO) << "Gove event to move " << app_id << " to another output "
<< output_name;
d->processAppStatusEvent(app_id, std::string("started"));
break;
}
iter++;
}
}

void Display::agl_shell_app_state(void* data,
struct agl_shell* /* agl_shell */,
const char* app_id,
Expand All @@ -965,12 +1133,7 @@ void Display::agl_shell_app_state(void* data,
FML_DLOG(INFO) << "Got AGL_SHELL_APP_STATE_STARTED for app_id " << app_id;

if (d->m_agl.shell) {
// we always assume the first output advertised by the wl_output
// interface
unsigned int default_output_index = 0;

agl_shell_activate_app(d->m_agl.shell, app_id,
d->m_all_outputs[default_output_index]->output);
d->processAppStatusEvent(app_id, std::string("started"));
}

break;
Expand All @@ -981,6 +1144,10 @@ void Display::agl_shell_app_state(void* data,
case AGL_SHELL_APP_STATE_ACTIVATED:
FML_DLOG(INFO) << "Got AGL_SHELL_APP_STATE_ACTIVATED for app_id "
<< app_id;
d->addAppToStack(std::string(app_id));
break;
case AGL_SHELL_APP_STATE_DEACTIVATED:
d->processAppStatusEvent(app_id, std::string("deactivated"));
break;
default:
break;
Expand All @@ -991,6 +1158,7 @@ const struct agl_shell_listener Display::agl_shell_listener = {
.bound_ok = agl_shell_bound_ok,
.bound_fail = agl_shell_bound_fail,
.app_state = agl_shell_app_state,
.app_on_output = agl_shell_app_on_output,
};

void Display::ivi_wm_surface_visibility(void* /* data */,
Expand Down
86 changes: 86 additions & 0 deletions shell/wayland/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#pragma once

#include <chrono>
#include <list>
#include <memory>
#include <mutex>
#include <string>
Expand Down Expand Up @@ -271,6 +272,44 @@ class Display {
*/
std::pair<int32_t, int32_t> GetVideoModeSize(uint32_t index);

/**
* @brief deactivate/hide the application pointed by app_id
* @param[in] app_id the app_id
* @relation
* agl_shell
*/
void deactivateApp(std::string app_id);
/**
* @brief activate/show the application pointed by app_id
* @param[in] app_id the app_id
* @relation
* agl_shell
*/
void activateApp(std::string app_id);
/**
* @brief Add app_id to a list of list applications
* @param[in] app_id the app_id
* @relation
* agl_shell
*/
void addAppToStack(std::string app_id);
/**
* @brief Helper to retrieve the output using its output_name
* @param[in] output_name a std::string representing the output
* @retval an integer that can used to get the proper output
* @relation
* agl_sell
*/
int find_output_by_name(std::string output_name);
/**
* @brief helper to process the application status
* @param[in] app_id an array of char
* @param[in] event_type a std::string representing the type of event (started/stopped/terminated)
* @relation
* agl_shell
*/
void processAppStatusEvent(const char* app_id, const std::string event_type);

private:
std::shared_ptr<Engine> m_flutter_engine;

Expand Down Expand Up @@ -300,6 +339,9 @@ class Display {
uint32_t version = 0;
} m_agl;

std::list<std::string> apps_stack;
std::list<std::pair<const std::string, const std::string>> pending_app_list;

struct ivi_shell {
struct ivi_application* application = nullptr;
struct ivi_wm* ivi_wm = nullptr;
Expand Down Expand Up @@ -329,6 +371,8 @@ class Display {
int32_t scale;
MAYBE_UNUSED bool done;
int transform;
std::string name;
std::string desc;
} output_info_t;

struct pointer_event {
Expand Down Expand Up @@ -520,6 +564,32 @@ class Display {
*/
static void display_handle_done(void* data, struct wl_output* wl_output);

/**
* @brief Set the display output name
* @param[in,out] data Data of type output_info_t*
* @param[in] wl_output No use
* @param[in] output_name Display name
* @return void
* @relation
* wayland - since @v4 of wl_output
*/
static void display_handle_name(void* data,
struct wl_output* wl_output,
const char* output_name);

/**
* @brief Set the display description
* @param[in,out] data Data of type output_info_t*
* @param[in] wl_output No use
* @param[in] desc_name Display description name
* @return void
* @relation
* wayland - since @v4 of wl_output
*/
static void display_handle_desc(void* data,
struct wl_output* wl_output,
const char* desc_name);

static const struct wl_shm_listener shm_listener;

/**
Expand Down Expand Up @@ -954,6 +1024,22 @@ class Display {
const char* app_id,
uint32_t state);

/**
* @brief AGL app_app_on_output event
* @param[in,out] data Data of type Display
* @param[in] shell No use
* @param[in] app_id the application id for which this event was sent
* @param[in] state the state: CREATED/TERMINATED/ACTIVATED/DEACTIVATED
* @return void
* @relation
* wayland, agl-shell
* @note Do nothing
*/
static void agl_shell_app_on_output(void* data,
struct agl_shell* agl_shell,
const char* app_id,
const char* output_name);

static const struct agl_shell_listener agl_shell_listener;

/**
Expand Down
Loading