From 4a1684308bd6a17c5b112d30e672c40fd348fef3 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Fri, 7 Apr 2023 15:59:49 +0300 Subject: grpc-proxy: Added set_app_output request This is identical to the remote role, but I feel this conveys more information than remote role, as remote denotes that the output is displayed on another device, which it isn't always the case (the system has multiple outputs all connected directly). This introduces two new additions to the agl-shell protocol, a request to use a different output to display/show the application and an event to inform the shell client to use as a map between the application id and its output. The event is necessary to let the shell client know which output to activate the application on. This requests implements a wrapper for gRPC that maps 1-to-1 to the agl-shell request. There's no gRPC subscription similar to the event though. Bug-AGL: SPEC-4673 Signed-off-by: Marius Vlad Change-Id: I070e9fdbafd5616f3a98415193bf846aeaee9a4a --- grpc-proxy/agl_shell.proto | 9 +++++++++ grpc-proxy/grpc-async-cb.cpp | 12 ++++++++++++ grpc-proxy/grpc-async-cb.h | 4 ++++ grpc-proxy/main-grpc.cpp | 31 +++++++++++++++++++++++-------- grpc-proxy/shell.cpp | 26 ++++++++++++++++++++++++++ grpc-proxy/shell.h | 1 + protocol/agl-shell.xml | 33 ++++++++++++++++++++++++++++++++- src/shell.c | 39 ++++++++++++++++++++++++++++++++++++++- 8 files changed, 145 insertions(+), 10 deletions(-) diff --git a/grpc-proxy/agl_shell.proto b/grpc-proxy/agl_shell.proto index 200d43e..aac35f4 100644 --- a/grpc-proxy/agl_shell.proto +++ b/grpc-proxy/agl_shell.proto @@ -12,6 +12,7 @@ service AglShellManagerService { rpc AppStatusState(AppStateRequest) returns (stream AppStateResponse) {} rpc GetOutputs(OutputRequest) returns (ListOutputResponse) {} rpc SetAppNormal(NormalRequest) returns (NormalResponse) {} + rpc SetAppOnOutput(AppOnOutputRequest) returns (AppOnOutputResponse) {} } message ActivateRequest { @@ -78,3 +79,11 @@ message FullscreenRequest { message FullscreenResponse { }; + +message AppOnOutputRequest { + string app_id = 1; + string output = 2; +}; + +message AppOnOutputResponse { +}; diff --git a/grpc-proxy/grpc-async-cb.cpp b/grpc-proxy/grpc-async-cb.cpp index 08bd1f6..1bb367a 100644 --- a/grpc-proxy/grpc-async-cb.cpp +++ b/grpc-proxy/grpc-async-cb.cpp @@ -146,6 +146,18 @@ GrpcServiceImpl::SetAppFullscreen(grpc::CallbackServerContext *context, return reactor; } +grpc::ServerUnaryReactor * +GrpcServiceImpl::SetAppOnOutput(grpc::CallbackServerContext *context, + const ::agl_shell_ipc::AppOnOutputRequest* request, + ::agl_shell_ipc::AppOnOutputResponse* /* response */) +{ + m_aglShell->SetAppOnOutput(request->app_id(), request->output()); + + grpc::ServerUnaryReactor* reactor = context->DefaultReactor(); + reactor->Finish(grpc::Status::OK); + return reactor; +} + grpc::ServerUnaryReactor * GrpcServiceImpl::SetAppSplit(grpc::CallbackServerContext *context, const ::agl_shell_ipc::SplitRequest* request, diff --git a/grpc-proxy/grpc-async-cb.h b/grpc-proxy/grpc-async-cb.h index 5542d80..4987cf7 100644 --- a/grpc-proxy/grpc-async-cb.h +++ b/grpc-proxy/grpc-async-cb.h @@ -92,6 +92,10 @@ public: const ::agl_shell_ipc::FullscreenRequest* request, ::agl_shell_ipc::FullscreenResponse* /*response*/) override; + grpc::ServerUnaryReactor *SetAppOnOutput(grpc::CallbackServerContext *context, + const ::agl_shell_ipc::AppOnOutputRequest* request, + ::agl_shell_ipc::AppOnOutputResponse* /*response*/) override; + grpc::ServerWriteReactor< ::agl_shell_ipc::AppStateResponse>* AppStatusState( ::grpc::CallbackServerContext* /*context*/, const ::agl_shell_ipc::AppStateRequest* /*request*/) override; diff --git a/grpc-proxy/main-grpc.cpp b/grpc-proxy/main-grpc.cpp index dfe899a..1e297c5 100644 --- a/grpc-proxy/main-grpc.cpp +++ b/grpc-proxy/main-grpc.cpp @@ -120,16 +120,31 @@ agl_shell_app_state(void *data, struct agl_shell *agl_shell, } } +static void +agl_shell_app_on_output(void *data, struct agl_shell *agl_shell, + const char *app_id, const char *output_name) +{ + (void) agl_shell; + (void) output_name; + (void) data; + (void) app_id; + + LOG("got app_on_output event app_id %s on output\n", app_id, output_name); +} + + static const struct agl_shell_listener shell_listener = { - agl_shell_bound_ok, - agl_shell_bound_fail, - agl_shell_app_state, + agl_shell_bound_ok, + agl_shell_bound_fail, + agl_shell_app_state, + agl_shell_app_on_output, }; static const struct agl_shell_listener shell_listener_init = { - agl_shell_bound_ok_init, - agl_shell_bound_fail_init, - nullptr, + agl_shell_bound_ok_init, + agl_shell_bound_fail_init, + nullptr, + nullptr, }; static void @@ -260,7 +275,7 @@ global_add(void *data, struct wl_registry *reg, uint32_t id, sh->shell = static_cast(wl_registry_bind(reg, id, &agl_shell_interface, - std::min(static_cast(7), version))); + std::min(static_cast(8), version))); agl_shell_add_listener(sh->shell, &shell_listener, data); sh->version = version; } else if (strcmp(interface, "wl_output") == 0) { @@ -284,7 +299,7 @@ global_add_init(void *data, struct wl_registry *reg, uint32_t id, sh->shell = static_cast(wl_registry_bind(reg, id, &agl_shell_interface, - std::min(static_cast(7), version))); + std::min(static_cast(8), version))); agl_shell_add_listener(sh->shell, &shell_listener_init, data); sh->version = version; } diff --git a/grpc-proxy/shell.cpp b/grpc-proxy/shell.cpp index ef5c22f..34f6d37 100644 --- a/grpc-proxy/shell.cpp +++ b/grpc-proxy/shell.cpp @@ -31,6 +31,7 @@ #include #include "main-grpc.h" +#include "log.h" #include "shell.h" void @@ -94,6 +95,31 @@ Shell::SetAppFullscreen(const std::string &app_id) wl_display_flush(m_shell_data->wl_display); } +void +Shell::SetAppOnOutput(const std::string &app_id, const std::string &output) +{ + struct window_output *woutput, *w_output; + struct agl_shell *shell = this->m_shell.get(); + + woutput = nullptr; + w_output = nullptr; + + wl_list_for_each(woutput, &m_shell_data->output_list, link) { + if (woutput->name && !strcmp(woutput->name, output.c_str())) { + w_output = woutput; + break; + } + } + + if (!w_output) { + LOG("Could not found output '%s' to set the application\n"); + return; + } + + agl_shell_set_app_output(shell, app_id.c_str(), w_output->output); + wl_display_flush(m_shell_data->wl_display); +} + void Shell::SetAppSplit(const std::string &app_id, uint32_t orientation) { diff --git a/grpc-proxy/shell.h b/grpc-proxy/shell.h index a99111a..b047eef 100644 --- a/grpc-proxy/shell.h +++ b/grpc-proxy/shell.h @@ -45,4 +45,5 @@ public: int32_t x_pos, int32_t y_pos); void SetAppNormal(const std::string &app_id); void SetAppFullscreen(const std::string &app_id); + void SetAppOnOutput(const std::string &app_id, const std::string &output); }; diff --git a/protocol/agl-shell.xml b/protocol/agl-shell.xml index 8057387..e010a80 100644 --- a/protocol/agl-shell.xml +++ b/protocol/agl-shell.xml @@ -22,7 +22,7 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - + Starting with version 2 of the protocol, the client is required to wait for the 'bound_ok' or 'bound_fail' events in order to proceed further. @@ -273,6 +273,37 @@ + + + + This would allow the compositor to place an application on a particular + output, if that output is indeed available. This can happen before + application is started which would make the application start on that + particular output. If the application is already started it would + move the application to that output. + + There's no persistence of this request, once the application terminated + you'll need to issue this request again for that particular app_id. + + See xdg_toplevel.set_app_id from the xdg-shell protocol for a + description of app_id. + + + + + + + + Clients can use this event to be notified when an application + wants to be displayed on a certain output. This event is sent in + response to the set_app_output request. + + See xdg_toplevel.set_app_id from the xdg-shell protocol for a + description of app_id. + + + + diff --git a/src/shell.c b/src/shell.c index db9638f..c3459e7 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1168,6 +1168,22 @@ shell_send_app_state(struct ivi_compositor *ivi, const char *app_id, } } +void +shell_send_app_on_output(struct ivi_compositor *ivi, const char *app_id, + const char *output_name) +{ + if (app_id && wl_resource_get_version(ivi->shell_client.resource) >= + AGL_SHELL_APP_ON_OUTPUT_SINCE_VERSION) { + + agl_shell_send_app_on_output(ivi->shell_client.resource, + app_id, output_name); + + if (ivi->shell_client.resource_ext) + agl_shell_send_app_on_output(ivi->shell_client.resource_ext, + app_id, output_name); + } +} + static void shell_ready(struct wl_client *client, struct wl_resource *shell_res) { @@ -1685,6 +1701,26 @@ shell_set_activate_region(struct wl_client *client, struct wl_resource *res, ioutput->area_activation = area; } +static void +shell_set_app_output(struct wl_client *client, struct wl_resource *res, + const char *app_id, struct wl_resource *output) +{ + struct ivi_compositor *ivi = wl_resource_get_user_data(res); + struct weston_head *head = weston_head_from_resource(output); + struct weston_output *woutput = weston_head_get_output(head); + struct ivi_output *ioutput = to_ivi_output(woutput); + struct ivi_surface *surf = ivi_find_app(ivi, app_id); + + if (!app_id || !ioutput) + return; + + if (!surf || (surf && surf->role != IVI_SURFACE_ROLE_REMOTE)) { + ivi_set_pending_desktop_surface_remote(ioutput, app_id); + shell_send_app_on_output(ivi, app_id, woutput->name); + return; + } +} + static void shell_ext_destroy(struct wl_client *client, struct wl_resource *res) { @@ -1712,6 +1748,7 @@ static const struct agl_shell_interface agl_shell_implementation = { .set_app_float = shell_set_app_float, .set_app_normal = shell_set_app_normal, .set_app_fullscreen = shell_set_app_fullscreen, + .set_app_output = shell_set_app_output, }; static const struct agl_shell_ext_interface agl_shell_ext_implementation = { @@ -2011,7 +2048,7 @@ int ivi_shell_create_global(struct ivi_compositor *ivi) { ivi->agl_shell = wl_global_create(ivi->compositor->wl_display, - &agl_shell_interface, 7, + &agl_shell_interface, 8, ivi, bind_agl_shell); if (!ivi->agl_shell) { weston_log("Failed to create wayland global.\n"); -- cgit 1.2.3-korg