diff options
author | Marius Vlad <marius.vlad@collabora.com> | 2023-03-01 16:57:38 +0200 |
---|---|---|
committer | Marius Vlad <marius.vlad@collabora.com> | 2023-03-03 12:23:36 +0200 |
commit | 4e4624dee9850b4a4e590dd0f0f2b3173bded085 (patch) | |
tree | 4f5250eaa1c9756afcf52f3cef2ab17438e8f37f | |
parent | 9eb8ca6ac7473107ebe391c2f78543e92e461240 (diff) |
grpc-proxy: Add set_app_fullscreen functionality
This implements set_app_fullscreen which clients can set-up before being
mapped.
The worthwhile change here was the fact that transitioning between
fullscreen, normal, and float would cause invalid tracking of the active
window when switching between these states. This would make floating
operation display the incorrect active window, so in order to reconcile
that, we only update the previous surface if it is different that the
current active one. Otherwise this fairly similar to set_app_float.
Bug-AGL: SPEC-4673
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
Change-Id: Ie912c86ff7ac38d034cf4d97b2adbc5ef47ce9d3
-rw-r--r-- | grpc-proxy/agl_shell.proto | 8 | ||||
-rw-r--r-- | grpc-proxy/grpc-async-cb.cpp | 12 | ||||
-rw-r--r-- | grpc-proxy/grpc-async-cb.h | 4 | ||||
-rw-r--r-- | grpc-proxy/main-grpc.cpp | 4 | ||||
-rw-r--r-- | grpc-proxy/shell.cpp | 9 | ||||
-rw-r--r-- | grpc-proxy/shell.h | 1 | ||||
-rw-r--r-- | protocol/agl-shell.xml | 23 | ||||
-rw-r--r-- | src/layout.c | 28 | ||||
-rw-r--r-- | src/shell.c | 76 |
9 files changed, 157 insertions, 8 deletions
diff --git a/grpc-proxy/agl_shell.proto b/grpc-proxy/agl_shell.proto index f8a57d2..200d43e 100644 --- a/grpc-proxy/agl_shell.proto +++ b/grpc-proxy/agl_shell.proto @@ -8,6 +8,7 @@ service AglShellManagerService { rpc DeactivateApp(DeactivateRequest) returns (DeactivateResponse) {} rpc SetAppSplit(SplitRequest) returns (SplitResponse) {} rpc SetAppFloat(FloatRequest) returns (FloatResponse) {} + rpc SetAppFullscreen(FullscreenRequest) returns (FullscreenResponse) {} rpc AppStatusState(AppStateRequest) returns (stream AppStateResponse) {} rpc GetOutputs(OutputRequest) returns (ListOutputResponse) {} rpc SetAppNormal(NormalRequest) returns (NormalResponse) {} @@ -70,3 +71,10 @@ message NormalRequest { message NormalResponse { }; + +message FullscreenRequest { + string app_id = 1; +}; + +message FullscreenResponse { +}; diff --git a/grpc-proxy/grpc-async-cb.cpp b/grpc-proxy/grpc-async-cb.cpp index f7c114a..08bd1f6 100644 --- a/grpc-proxy/grpc-async-cb.cpp +++ b/grpc-proxy/grpc-async-cb.cpp @@ -135,6 +135,18 @@ GrpcServiceImpl::SetAppNormal(grpc::CallbackServerContext *context, } grpc::ServerUnaryReactor * +GrpcServiceImpl::SetAppFullscreen(grpc::CallbackServerContext *context, + const ::agl_shell_ipc::FullscreenRequest* request, + ::agl_shell_ipc::FullscreenResponse* /* response */) +{ + m_aglShell->SetAppFullscreen(request->app_id()); + + 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, ::agl_shell_ipc::SplitResponse* /*response*/) diff --git a/grpc-proxy/grpc-async-cb.h b/grpc-proxy/grpc-async-cb.h index 214ce12..5542d80 100644 --- a/grpc-proxy/grpc-async-cb.h +++ b/grpc-proxy/grpc-async-cb.h @@ -88,6 +88,10 @@ public: const ::agl_shell_ipc::NormalRequest* request, ::agl_shell_ipc::NormalResponse* /*response*/) override; + grpc::ServerUnaryReactor *SetAppFullscreen(grpc::CallbackServerContext *context, + const ::agl_shell_ipc::FullscreenRequest* request, + ::agl_shell_ipc::FullscreenResponse* /*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 ea609f0..dfe899a 100644 --- a/grpc-proxy/main-grpc.cpp +++ b/grpc-proxy/main-grpc.cpp @@ -260,7 +260,7 @@ global_add(void *data, struct wl_registry *reg, uint32_t id, sh->shell = static_cast<struct agl_shell *>(wl_registry_bind(reg, id, &agl_shell_interface, - std::min(static_cast<uint32_t>(6), version))); + std::min(static_cast<uint32_t>(7), version))); agl_shell_add_listener(sh->shell, &shell_listener, data); sh->version = version; } else if (strcmp(interface, "wl_output") == 0) { @@ -284,7 +284,7 @@ global_add_init(void *data, struct wl_registry *reg, uint32_t id, sh->shell = static_cast<struct agl_shell *>(wl_registry_bind(reg, id, &agl_shell_interface, - std::min(static_cast<uint32_t>(6), version))); + std::min(static_cast<uint32_t>(7), 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 eb2e08b..ef5c22f 100644 --- a/grpc-proxy/shell.cpp +++ b/grpc-proxy/shell.cpp @@ -86,6 +86,15 @@ Shell::SetAppNormal(const std::string &app_id) } void +Shell::SetAppFullscreen(const std::string &app_id) +{ + struct agl_shell *shell = this->m_shell.get(); + + agl_shell_set_app_fullscreen(shell, app_id.c_str()); + wl_display_flush(m_shell_data->wl_display); +} + +void Shell::SetAppSplit(const std::string &app_id, uint32_t orientation) { (void) app_id; diff --git a/grpc-proxy/shell.h b/grpc-proxy/shell.h index 143599a..a99111a 100644 --- a/grpc-proxy/shell.h +++ b/grpc-proxy/shell.h @@ -44,4 +44,5 @@ public: void SetAppFloat(const std::string &app_id, int32_t x_pos, int32_t y_pos); void SetAppNormal(const std::string &app_id); + void SetAppFullscreen(const std::string &app_id); }; diff --git a/protocol/agl-shell.xml b/protocol/agl-shell.xml index d01771f..8057387 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. </copyright> - <interface name="agl_shell" version="6"> + <interface name="agl_shell" version="7"> <description summary="user interface for Automotive Grade Linux platform"> 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. @@ -252,6 +252,27 @@ </description> <arg name="app_id" type="string"/> </request> + + <request name="set_app_fullscreen" since="7"> + <description summary=""> + Makes the application identified by app_id as fullscreen. If the + application's window is already mapped, in a maximized, normal state, + it would transition to the fullscreen state. + + For applications that want to modify their own state, this request + must be done before the initial surface commit in order to take effect. + + If the application is already in fullscreen state, this request wouldn't + do anything. + + There's no persistence of this request, once the application terminated + you'll 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. + </description> + <arg name="app_id" type="string"/> + </request> </interface> <interface name="agl_shell_ext" version="1"> diff --git a/src/layout.c b/src/layout.c index df9184d..9981ebb 100644 --- a/src/layout.c +++ b/src/layout.c @@ -218,6 +218,7 @@ ivi_layout_activate_complete(struct ivi_output *output, struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi); struct ivi_shell_seat *ivi_seat = get_ivi_shell_seat(wseat); const char *app_id = weston_desktop_surface_get_app_id(surf->dsurface); + bool update_previous = true; if (weston_view_is_mapped(view)) { weston_layer_entry_remove(&view->layer_link); @@ -288,7 +289,22 @@ ivi_layout_activate_complete(struct ivi_output *output, weston_layer_entry_remove(&output->active->view->layer_link); } } - output->previous_active = output->active; + + if (output->previous_active && output->active) { + const char *c_app_id = + weston_desktop_surface_get_app_id(output->active->dsurface); + + /* if the currently activated app_id is the same as the one + * we're trying to complete activation with means we're + * operating on the same app_id so do update previous_active as + * it will overwrite it with the same value */ + if (!strcmp(c_app_id, app_id)) { + update_previous = false; + } + } + + if (update_previous) + output->previous_active = output->active; output->active = surf; surf->current_completed_output = output; @@ -596,7 +612,8 @@ ivi_layout_fullscreen_committed(struct ivi_surface *surface) assert(surface->role == IVI_SURFACE_ROLE_FULLSCREEN); - if (weston_view_is_mapped(view)) + + if (surface->state == FULLSCREEN && weston_view_is_mapped(view)) return; /* if we still get here but we haven't resized so far, send configure @@ -632,7 +649,7 @@ ivi_layout_fullscreen_committed(struct ivi_surface *surface) } /* this implies we resized correctly */ - if (!weston_view_is_mapped(view)) { + if (!weston_view_is_mapped(view) || surface->state != FULLSCREEN) { weston_layer_entry_remove(&view->layer_link); weston_view_set_output(view, woutput); @@ -800,6 +817,11 @@ ivi_surf_in_hidden_layer(struct ivi_compositor *ivi, struct ivi_surface *surface return true; } + wl_list_for_each(ev, &ivi->fullscreen.view_list.link, layer_link.link) { + if (ev == surface->view) + return true; + } + return false; } diff --git a/src/shell.c b/src/shell.c index a3eb31f..ddb8981 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1467,13 +1467,28 @@ shell_set_app_float(struct wl_client *client, struct wl_resource *shell_res, struct weston_view *ev = surf->view; struct weston_desktop_surface *dsurf = surf->dsurface; struct ivi_bounding_box bb = {}; + const char *prev_activate_app_id = NULL; /* XXX: if this is useful we could bring it as active then make * it float, but avoid doing it for the moment */ if (surf != ivi_output->active) return; - ivi_layout_deactivate(ivi, app_id); + if (ivi_output->previous_active) + prev_activate_app_id = + weston_desktop_surface_get_app_id(ivi_output->previous_active->dsurface); + + /* only deactivate if previous_active is different, otherwise + * this will blow up, because we're trying to activate the same + * app_id as the this one! */ + if (prev_activate_app_id && strcmp(app_id, prev_activate_app_id)) { + ivi_layout_deactivate(ivi, app_id); + } else if (prev_activate_app_id) { + weston_layer_entry_remove(&ev->layer_link); + weston_view_geometry_dirty(ev); + weston_surface_damage(ev->surface); + } + surf->hidden_layer_output = ivi_output; /* set attributes */ @@ -1506,6 +1521,59 @@ shell_set_app_float(struct wl_client *client, struct wl_resource *shell_res, } static void +shell_set_app_fullscreen(struct wl_client *client, + struct wl_resource *shell_res, const char *app_id) +{ + struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res); + struct weston_output *output = get_focused_output(ivi->compositor); + struct ivi_output *ivi_output; + struct ivi_surface *surf = ivi_find_app(ivi, app_id); + + if (!output) + output = get_default_output(ivi->compositor); + + ivi_output = to_ivi_output(output); + + if (surf && surf->role == IVI_SURFACE_ROLE_DESKTOP) { + struct weston_view *ev = surf->view; + struct weston_desktop_surface *dsurf = surf->dsurface; + + if (surf != ivi_output->active) + return; + + weston_layer_entry_remove(&surf->view->layer_link); + weston_view_geometry_dirty(surf->view); + weston_surface_damage(surf->view->surface); + + surf->hidden_layer_output = ivi_output; + + /* set attributes */ + surf->fullscreen.output = ivi_output; + + /* change the role */ + surf->role = IVI_SURFACE_ROLE_NONE; + + wl_list_remove(&surf->link); + wl_list_init(&surf->link); + + ivi_set_desktop_surface_fullscreen(surf); + + weston_desktop_surface_set_maximized(dsurf, false); + weston_desktop_surface_set_fullscreen(dsurf, true); + weston_desktop_surface_set_size(dsurf, + ivi_output->output->width, + ivi_output->output->height); + + /* add to hidden layer */ + weston_layer_entry_insert(&ivi->hidden.view_list, &ev->layer_link); + weston_compositor_schedule_repaint(ivi->compositor); + } else if (!surf || (surf && surf->role != IVI_SURFACE_ROLE_FULLSCREEN)) { + ivi_set_pending_desktop_surface_fullscreen(ivi_output, app_id); + } +} + + +static void shell_set_app_normal(struct wl_client *client, struct wl_resource *shell_res, const char *app_id) { @@ -1546,6 +1614,9 @@ shell_set_app_normal(struct wl_client *client, struct wl_resource *shell_res, else area = ivi_output->area; + if (weston_desktop_surface_get_fullscreen(dsurf)) + weston_desktop_surface_set_fullscreen(dsurf, false); + weston_desktop_surface_set_maximized(dsurf, true); weston_desktop_surface_set_size(dsurf, area.width, area.height); @@ -1640,6 +1711,7 @@ static const struct agl_shell_interface agl_shell_implementation = { .deactivate_app = shell_new_deactivate_app, .set_app_float = shell_set_app_float, .set_app_normal = shell_set_app_normal, + .set_app_fullscreen = shell_set_app_fullscreen, }; static const struct agl_shell_ext_interface agl_shell_ext_implementation = { @@ -1939,7 +2011,7 @@ int ivi_shell_create_global(struct ivi_compositor *ivi) { ivi->agl_shell = wl_global_create(ivi->compositor->wl_display, - &agl_shell_interface, 6, + &agl_shell_interface, 7, ivi, bind_agl_shell); if (!ivi->agl_shell) { weston_log("Failed to create wayland global.\n"); |