| /* |
| * If not stated otherwise in this file or this component's Licenses.txt file the |
| * following copyright and licenses apply: |
| * |
| * Copyright 2016 RDK Management |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <memory.h> |
| #include <sys/time.h> |
| |
| #include "weston-simpleshell.h" |
| #include "aml-weston/aml-simpleshell.h" |
| #include <libweston/zalloc.h> |
| #include <shared/helpers.h> |
| |
| #include "wayland-server.h" |
| #include "simpleshell-server-protocol.h" |
| |
| #define WST_UNUSED( n ) ((void)n) |
| |
| #define MIN(x,y) (((x) < (y)) ? (x) : (y)) |
| |
| #define DEFAULT_NAME "noname" |
| #define BROADCAST_DELAY (2000) |
| |
| static void destroy_shell(struct wl_resource *resource); |
| static void wstSimpleShellBroadcastCreation( struct wl_simple_shell *shell, uint32_t surfaceId ); |
| |
| struct shell_info |
| { |
| struct wl_client *client; |
| struct wl_resource *resource; |
| struct wl_list link; |
| }; |
| |
| struct pending_broadcast_info |
| { |
| uint32_t surfaceId; |
| long long creationTime; |
| struct wl_list link; |
| }; |
| |
| struct simple_shell_surface_id { |
| uint32_t surfaceId; |
| struct wl_list link; |
| }; |
| |
| struct wl_simple_shell |
| { |
| struct wl_display *display; |
| struct wl_global *wl_simple_shell_global; |
| struct wayland_simple_shell_callbacks *callbacks; |
| void *userData; |
| struct wl_event_source *delayTimer; |
| struct wl_list shells; |
| struct wl_list surfaces; |
| struct wl_list pendingCreateBroadcast; |
| struct wl_listener create_surface_listener; |
| }; |
| |
| struct simple_shell_destroy_info { |
| struct wl_simple_shell *shell; |
| struct wl_listener destroy_surface_listener; |
| }; |
| |
| static long long getCurrentTimeMillis() |
| { |
| struct timeval tv; |
| long long utcCurrentTimeMillis; |
| |
| gettimeofday(&tv,0); |
| utcCurrentTimeMillis= tv.tv_sec*1000LL+(tv.tv_usec/1000LL); |
| |
| return utcCurrentTimeMillis; |
| } |
| |
| static void wstISimpleShellSetName(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, const char *name); |
| static void wstISimpleShellSetVisible(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, uint32_t visible); |
| static void wstISimpleShellSetGeometry(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, int32_t x, int32_t y, int32_t width, int32_t height); |
| static void wstISimpleShellSetOpacity(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, wl_fixed_t opacity); |
| static void wstISimpleShellSetZOrder(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, wl_fixed_t zorder); |
| static void wstISimpleShellGetStatus(struct wl_client *client, struct wl_resource *resource, uint32_t surface); |
| static void wstISimpleShellGetSurfaces(struct wl_client *client, struct wl_resource *resource); |
| static void wstISimpleShellSetFocus(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId); |
| static void wstISimpleShellSetScale(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, wl_fixed_t scaleX, wl_fixed_t scaleY); |
| static void wstISimpleShellSetKeyIntercept(struct wl_client * client, struct wl_resource * resource, |
| uint32_t surfaceId, uint32_t keyCode, uint32_t modifiers); |
| static void wstISimpleShellSetMultiKeyIntercept(struct wl_client * client, struct wl_resource * resource, |
| uint32_t surfaceId, struct wl_array * keyCode, struct wl_array * modifiers); |
| static void wstISimpleShellRemoveMultiKeyIntercept(struct wl_client * client, struct wl_resource * resource, |
| uint32_t surfaceId, struct wl_array * keyCode, struct wl_array * modifiers); |
| static void wstISimpleShellApplyAppsZorder(struct wl_client * client, struct wl_resource * resource, |
| struct wl_array * appList); |
| static void wstISimpleShellSendMultiKey(struct wl_client * client, struct wl_resource * resource, |
| uint32_t surfaceId, struct wl_array * keyCode, struct wl_array * modifiers); |
| |
| |
| const static struct wl_simple_shell_interface simple_shell_interface = { |
| wstISimpleShellSetName, |
| wstISimpleShellSetVisible, |
| wstISimpleShellSetGeometry, |
| wstISimpleShellSetOpacity, |
| wstISimpleShellSetZOrder, |
| wstISimpleShellGetStatus, |
| wstISimpleShellGetSurfaces, |
| wstISimpleShellSetFocus, |
| wstISimpleShellSetScale, |
| wstISimpleShellSetKeyIntercept, |
| wstISimpleShellSetMultiKeyIntercept, |
| wstISimpleShellRemoveMultiKeyIntercept, |
| wstISimpleShellApplyAppsZorder, |
| wstISimpleShellSendMultiKey |
| }; |
| |
| static void wstSimpleShellBroadcastSurfaceUpdate(struct wl_client *client, |
| struct wl_simple_shell *shell, uint32_t surfaceId ) |
| { |
| const char *name= 0; |
| |
| bool visible; |
| int x, y, width, height; |
| float opacity, zorder; |
| wl_fixed_t fixedOpacity, fixedZOrder; |
| struct shell_info *info, *tmp; |
| |
| if (!client || !shell || !shell->callbacks) |
| return; |
| |
| if (shell->callbacks->get_name) |
| shell->callbacks->get_name( shell->userData, surfaceId, &name ); |
| if ( !name ) |
| name= (const char *)DEFAULT_NAME; |
| |
| if (shell->callbacks->get_status) { |
| shell->callbacks->get_status( shell->userData, surfaceId, |
| &visible, |
| &x, &y, &width, &height, |
| &opacity, &zorder ); |
| |
| fixedOpacity= wl_fixed_from_double( (double)opacity ); |
| fixedZOrder= wl_fixed_from_double( (double)zorder ); |
| |
| // Broadcast the surface update announcement to all other clients. |
| wl_list_for_each_safe(info, tmp, &shell->shells, link) { |
| if (info->client != client) { |
| wl_simple_shell_send_surface_status(info->resource, surfaceId, |
| name, (visible ? 1 : 0), |
| x, y, width, height, fixedOpacity, fixedZOrder); |
| } |
| } |
| } |
| } |
| |
| static void wstISimpleShellSetName(struct wl_client *client, |
| struct wl_resource *resource, |
| uint32_t surfaceId, const char *name) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| struct pending_broadcast_info *info, *tmp; |
| |
| if ( shell ) { |
| if (shell->callbacks && shell->callbacks->set_name) |
| shell->callbacks->set_name( shell->userData, surfaceId, name ); |
| |
| wl_list_for_each_safe(info, tmp, &shell->pendingCreateBroadcast, link) { |
| if (info->surfaceId == surfaceId) { |
| wl_list_remove(&info->link); |
| free(info); |
| wstSimpleShellBroadcastCreation( shell, surfaceId ); |
| break; |
| } |
| } |
| |
| wstSimpleShellBroadcastSurfaceUpdate(client, shell, surfaceId ); |
| } |
| } |
| |
| static void wstISimpleShellSetVisible(struct wl_client *client, |
| struct wl_resource *resource, |
| uint32_t surfaceId, uint32_t visible) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| |
| if ( shell ) { |
| if (shell->callbacks && shell->callbacks->set_visible) |
| shell->callbacks->set_visible( shell->userData, surfaceId, (visible != 0) ); |
| |
| wstSimpleShellBroadcastSurfaceUpdate(client, shell, surfaceId ); |
| } |
| } |
| |
| static void wstISimpleShellSetGeometry(struct wl_client *client, |
| struct wl_resource *resource, |
| uint32_t surfaceId, |
| int32_t x, int32_t y, int32_t width, int32_t height) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| |
| if ( shell ) { |
| if (shell->callbacks && shell->callbacks->set_geometry) |
| shell->callbacks->set_geometry( shell->userData, surfaceId, |
| x, y, width, height ); |
| |
| wstSimpleShellBroadcastSurfaceUpdate(client, shell, surfaceId ); |
| } |
| } |
| |
| static void wstISimpleShellSetOpacity(struct wl_client *client, |
| struct wl_resource *resource, |
| uint32_t surfaceId, |
| wl_fixed_t opacity) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| if ( shell ) { |
| float opacityLevel= wl_fixed_to_double( opacity ); |
| |
| if ( opacityLevel < 0.0 ) opacityLevel= 0.0; |
| if ( opacityLevel > 1.0 ) opacityLevel= 1.0; |
| |
| if (shell->callbacks && shell->callbacks->set_opacity) |
| shell->callbacks->set_opacity( shell->userData, surfaceId, opacityLevel ); |
| |
| wstSimpleShellBroadcastSurfaceUpdate(client, shell, surfaceId ); |
| } |
| } |
| |
| static void wstISimpleShellSetZOrder(struct wl_client *client, |
| struct wl_resource *resource, |
| uint32_t surfaceId, |
| wl_fixed_t zorder) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| if ( shell ) { |
| float zOrderLevel= wl_fixed_to_double( zorder ); |
| |
| if ( zOrderLevel < 0.0 ) zOrderLevel= 0.0; |
| if ( zOrderLevel > 1.0 ) zOrderLevel= 1.0; |
| |
| if (shell->callbacks && shell->callbacks->set_zorder) |
| shell->callbacks->set_zorder( shell->userData, surfaceId, zOrderLevel ); |
| |
| wstSimpleShellBroadcastSurfaceUpdate(client, shell, surfaceId ); |
| } |
| } |
| |
| static void wstISimpleShellGetStatus(struct wl_client *client, struct wl_resource *resource, uint32_t surfaceId ) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| if ( shell ) { |
| const char *name= 0; |
| bool visible; |
| int x, y, width = 0, height = 0; |
| float opacity, zorder; |
| wl_fixed_t fixedOpacity, fixedZOrder; |
| |
| if (shell->callbacks && shell->callbacks->get_name) |
| shell->callbacks->get_name( shell->userData, surfaceId, &name ); |
| if ( !name ) |
| name= (const char *)DEFAULT_NAME; |
| |
| if (shell->callbacks && shell->callbacks->get_status) { |
| shell->callbacks->get_status( shell->userData, surfaceId, |
| &visible, |
| &x, &y, &width, &height, |
| &opacity, &zorder ); |
| |
| if (width == 0 && height == 0) |
| return; |
| |
| fixedOpacity= wl_fixed_from_double( (double)opacity ); |
| fixedZOrder= wl_fixed_from_double( (double)zorder ); |
| |
| wl_simple_shell_send_surface_status( resource, surfaceId, |
| name, (visible ? 1 : 0), |
| x, y, width, height, fixedOpacity, fixedZOrder ); |
| } |
| } |
| } |
| |
| static void wstISimpleShellGetSurfaces(struct wl_client *client, struct wl_resource *resource) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| struct simple_shell_surface_id *surface_id, *tmp; |
| |
| if ( shell ) { |
| wl_list_for_each_safe(surface_id, tmp, &shell->surfaces, link) |
| wstISimpleShellGetStatus(client, resource, surface_id->surfaceId ); |
| |
| wl_simple_shell_send_get_surfaces_done( resource ); |
| } |
| } |
| |
| static void wstISimpleShellSetFocus(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| if (shell && shell->callbacks && shell->callbacks->set_focus) |
| shell->callbacks->set_focus(shell->userData, surfaceId); |
| } |
| |
| static void wstISimpleShellSetScale(struct wl_client *client, struct wl_resource *resource, |
| uint32_t surfaceId, wl_fixed_t scaleX, wl_fixed_t scaleY) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| float fScaleX= wl_fixed_to_double(scaleX); |
| float fScaleY= wl_fixed_to_double(scaleY); |
| |
| weston_log("weston-simpleshell: wstSimpleShellSetScale: surfaceId %u scaleX %f scaleY %f\n", |
| surfaceId, fScaleX, fScaleY); |
| if (shell && shell->callbacks && shell->callbacks->set_scale) |
| shell->callbacks->set_scale(shell->userData, surfaceId, fScaleX, fScaleY); |
| } |
| |
| static void wstISimpleShellSetKeyIntercept(struct wl_client * client, struct wl_resource * resource, |
| uint32_t surfaceId, uint32_t keyCode, uint32_t modifiers) { |
| weston_log("intercept key keycode:%d, surfaceId %d, modifiers %d\n", keyCode, surfaceId, modifiers); |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| if (shell && shell->callbacks) |
| shell->callbacks->set_key_intercept(shell->userData, surfaceId, keyCode, modifiers); |
| } |
| |
| static void |
| wstISimpleShellSetMultiKeyIntercept(struct wl_client * client, |
| struct wl_resource * resource, |
| uint32_t surfaceId, |
| struct wl_array * keyCode, |
| struct wl_array * modifiers) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| size_t size; |
| uint32_t *key_code, *modifier; |
| |
| if (!keyCode || !modifiers || keyCode->size != modifiers->size) |
| return; |
| |
| size = keyCode->size / sizeof(uint32_t); |
| key_code = (uint32_t *)keyCode->data; |
| modifier = (uint32_t *)modifiers->data; |
| if (shell && shell->callbacks && shell->callbacks->set_key_intercept) { |
| while (size--) { |
| shell->callbacks->set_key_intercept(shell->userData, surfaceId, *key_code, *modifier); |
| key_code++; |
| modifier++; |
| } |
| } |
| } |
| |
| static void |
| wstISimpleShellRemoveMultiKeyIntercept(struct wl_client * client, |
| struct wl_resource * resource, |
| uint32_t surfaceId, |
| struct wl_array * keyCode, |
| struct wl_array * modifiers) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| size_t size; |
| uint32_t *key_code, *modifier; |
| |
| if (!keyCode || !modifiers || keyCode->size != modifiers->size) |
| return; |
| |
| size = keyCode->size / sizeof(uint32_t); |
| key_code = (uint32_t *)keyCode->data; |
| modifier = (uint32_t *)modifiers->data; |
| if (shell && shell->callbacks && shell->callbacks->remove_key_intercept) { |
| while (size--) { |
| shell->callbacks->remove_key_intercept(shell->userData, surfaceId, *key_code, *modifier); |
| key_code++; |
| modifier++; |
| } |
| } |
| } |
| |
| static void |
| wstISimpleShellApplyAppsZorder(struct wl_client * client, |
| struct wl_resource * resource, |
| struct wl_array * appList) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| uint32_t *id; |
| size_t size; |
| int zorder = WESTON_ZORDER_DEFAULT; |
| |
| if (!appList || !appList->size) |
| return; |
| |
| id = (uint32_t *)appList->data; |
| size = appList->size / sizeof(uint32_t); |
| if (shell && shell->callbacks && shell->callbacks->set_zorder) { |
| while (size--) { |
| shell->callbacks->set_zorder(shell->userData, *id, (float)zorder / WESTON_ZORDER_MAX); |
| wstSimpleShellBroadcastSurfaceUpdate(client, shell, *id ); |
| zorder += WESTON_ZORDER_INTERVAL; |
| id++; |
| } |
| } |
| } |
| |
| static void |
| wstISimpleShellSendMultiKey(struct wl_client * client, |
| struct wl_resource * resource, |
| uint32_t surfaceId, |
| struct wl_array * keyCode, |
| struct wl_array * modifiers) |
| { |
| struct wl_simple_shell *shell = |
| (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| size_t size; |
| uint32_t *key_code, *modifier; |
| |
| if (!keyCode || !modifiers || keyCode->size != modifiers->size) |
| return; |
| |
| size = keyCode->size / sizeof(uint32_t); |
| key_code = (uint32_t *)keyCode->data; |
| modifier = (uint32_t *)modifiers->data; |
| |
| if (shell && shell->callbacks && shell->callbacks->send_key) { |
| while (size--) { |
| shell->callbacks->send_key(shell->userData, surfaceId, *key_code, *modifier); |
| key_code++; |
| modifier++; |
| } |
| } |
| } |
| |
| static void destroy_shell(struct wl_resource *resource) |
| { |
| struct wl_simple_shell *shell= (struct wl_simple_shell*)wl_resource_get_user_data(resource); |
| struct shell_info *info, *tmp; |
| |
| if ( shell ) { |
| wl_list_for_each_safe(info, tmp, &shell->shells, link) { |
| if (info->resource == resource) { |
| wl_list_remove(&info->link); |
| free(info); |
| break; |
| } |
| } |
| } |
| } |
| |
| static void wstSimpleShellBind(struct wl_client *client, void *data, uint32_t version, uint32_t id) |
| { |
| struct wl_simple_shell *shell = (struct wl_simple_shell*)data; |
| struct wl_resource *resource; |
| struct shell_info *info; |
| |
| if ( shell ) { |
| info = zalloc(sizeof *info); |
| if (info == NULL) |
| return; |
| |
| resource= wl_resource_create(client, &wl_simple_shell_interface, MIN(version, 1), id); |
| if (!resource) { |
| wl_client_post_no_memory(client); |
| free(info); |
| return; |
| } |
| |
| wl_resource_set_implementation(resource, &simple_shell_interface, shell, destroy_shell); |
| |
| info->client= client; |
| info->resource= resource; |
| wl_list_insert(&shell->shells, &info->link); |
| } |
| } |
| |
| static void wstSimpleShellBroadcastCreation( struct wl_simple_shell *shell, uint32_t surfaceId ) |
| { |
| const char *name= 0; |
| struct shell_info *info, *tmp; |
| |
| if (!shell || !shell->callbacks) |
| return; |
| |
| // Get any name the creator may have assigned the surface |
| if (shell->callbacks->get_name) |
| shell->callbacks->get_name( shell->userData, surfaceId, &name ); |
| if ( !name ) |
| name= (const char *)DEFAULT_NAME; |
| |
| weston_log("broadcast for surfaceId %x name %s\n", surfaceId, name); |
| |
| // Broadcast the surface creation announcement |
| wl_list_for_each_safe(info, tmp, &shell->shells, link) { |
| wl_simple_shell_send_surface_created( info->resource, surfaceId, name ); |
| } |
| } |
| |
| static int wstSimpleShellTimeOut( void *data ) |
| { |
| bool more = true; |
| long long now; |
| long long delay; |
| struct pending_broadcast_info *pendingInfo; |
| struct wl_simple_shell *shell = (struct wl_simple_shell*)data; |
| |
| while ( more ) { |
| if (!wl_list_empty(&shell->pendingCreateBroadcast)) { |
| pendingInfo = wl_container_of( shell->pendingCreateBroadcast.next, pendingInfo, link); |
| wl_list_remove( shell->pendingCreateBroadcast.next ); |
| |
| wstSimpleShellBroadcastCreation( shell, pendingInfo->surfaceId ); |
| free(pendingInfo); |
| |
| if (!wl_list_empty(&shell->pendingCreateBroadcast)) { |
| pendingInfo = wl_container_of( shell->pendingCreateBroadcast.next, pendingInfo, link); |
| now = getCurrentTimeMillis(); |
| delay = now - pendingInfo->creationTime; |
| |
| if ( delay >= BROADCAST_DELAY ) { |
| continue; |
| } else { |
| delay = BROADCAST_DELAY - delay; |
| wl_event_source_timer_update( shell->delayTimer, delay ); |
| more = false; |
| } |
| } |
| } else { |
| break; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static void |
| WstSimpleShellDestroySurface(struct wl_listener *listener, void *data) |
| { |
| struct weston_surface *surface = (struct weston_surface *)data; |
| struct simple_shell_destroy_info *info = |
| container_of(listener, |
| struct simple_shell_destroy_info, destroy_surface_listener); |
| |
| if (!surface || !info) |
| return; |
| |
| WstSimpleShellNotifySurfaceDestroyed(info->shell, NULL, surface->surface_id); |
| wl_list_remove(&info->destroy_surface_listener.link); |
| free(info); |
| } |
| |
| static void |
| WstSimpleShellCreateSurface(struct wl_listener *listener, void *data) |
| { |
| struct weston_surface *surface = (struct weston_surface *)data; |
| struct simple_shell_destroy_info *info; |
| struct wl_simple_shell *shell = |
| container_of(listener, |
| struct wl_simple_shell, create_surface_listener); |
| struct wl_client *client = wl_resource_get_client(surface->resource); |
| |
| if (!shell) |
| return; |
| |
| info = zalloc(sizeof *info); |
| if (info == NULL) |
| return; |
| |
| info->shell = shell; |
| info->destroy_surface_listener.notify = WstSimpleShellDestroySurface; |
| wl_signal_add(&surface->destroy_signal, |
| &info->destroy_surface_listener); |
| |
| surface->zorder = WESTON_ZORDER_DEFAULT; |
| WstSimpleShellNotifySurfaceCreated(shell, |
| client, surface->resource, surface->surface_id); |
| } |
| |
| WL_EXPORT struct wl_simple_shell* WstSimpleShellInit( struct wl_display *display, |
| struct wayland_simple_shell_callbacks *callbacks, |
| void *userData ) |
| { |
| struct wl_simple_shell *shell= 0; |
| struct wl_event_loop *loop= 0; |
| struct weston_compositor *compositor = (struct weston_compositor *)userData; |
| |
| weston_log("weston-simpleshell: WstSimpleShellInit: enter: display %p\n", display ); |
| shell= (struct wl_simple_shell*)calloc( 1, sizeof(struct wl_simple_shell) ); |
| if ( !shell ) |
| goto exit; |
| |
| shell->display= display; |
| shell->callbacks= callbacks; |
| shell->userData= userData; |
| |
| wl_list_init(&shell->shells); |
| wl_list_init(&shell->surfaces); |
| wl_list_init(&shell->pendingCreateBroadcast); |
| loop= wl_display_get_event_loop(shell->display); |
| if ( !loop ) { |
| free( shell ); |
| shell= 0; |
| goto exit; |
| } |
| |
| shell->delayTimer= wl_event_loop_add_timer( loop, wstSimpleShellTimeOut, shell ); |
| if ( !shell->delayTimer ) { |
| free( shell ); |
| shell= 0; |
| goto exit; |
| } |
| |
| shell->wl_simple_shell_global= wl_global_create(display, &wl_simple_shell_interface, 1, shell, wstSimpleShellBind ); |
| shell->create_surface_listener.notify = WstSimpleShellCreateSurface; |
| wl_signal_add(&compositor->create_surface_signal, |
| &shell->create_surface_listener); |
| |
| exit: |
| weston_log("weston-simpleshell: WstSimpleShellInit: exit: display %p shell %p\n", display, shell); |
| |
| return shell; |
| } |
| |
| static void clear_pending_create_broadcast(struct wl_simple_shell *shell) |
| { |
| struct pending_broadcast_info *info, *tmp; |
| |
| wl_list_for_each_safe(info, tmp, &shell->pendingCreateBroadcast, link) { |
| wl_list_remove(&info->link); |
| free(info); |
| } |
| } |
| |
| static void clear_surface_id(struct wl_simple_shell *shell) |
| { |
| struct simple_shell_surface_id *info, *tmp; |
| |
| wl_list_for_each_safe(info, tmp, &shell->surfaces, link) { |
| wl_list_remove(&info->link); |
| free(info); |
| } |
| } |
| |
| static void clear_shell_info(struct wl_simple_shell *shell) |
| { |
| struct shell_info *info, *tmp; |
| |
| wl_list_for_each_safe(info, tmp, &shell->shells, link) { |
| wl_list_remove(&info->link); |
| free(info); |
| } |
| } |
| |
| void WstSimpleShellUninit( struct wl_simple_shell *shell ) |
| { |
| if ( shell ) { |
| if ( shell->delayTimer ) { |
| wl_event_source_remove( shell->delayTimer ); |
| shell->delayTimer= 0; |
| } |
| wl_global_destroy( shell->wl_simple_shell_global ); |
| clear_pending_create_broadcast(shell); |
| clear_surface_id(shell); |
| clear_shell_info(shell); |
| |
| free( shell ); |
| } |
| } |
| |
| void WstSimpleShellNotifySurfaceCreated( struct wl_simple_shell *shell, |
| struct wl_client *client, |
| struct wl_resource *surface_resource, |
| uint32_t surfaceId ) |
| { |
| bool creatorNotified= false; |
| struct simple_shell_surface_id *surface_id; |
| struct shell_info *info, *tmp; |
| |
| if (!shell) |
| return; |
| |
| surface_id = zalloc(sizeof *surface_id); |
| if (surface_id == NULL) |
| return; |
| |
| // Add surface to list |
| surface_id->surfaceId = surfaceId; |
| wl_list_insert(&shell->surfaces, &surface_id->link); |
| |
| weston_log("WstSimpleShellNotifySurfaceCreated: %d\n", surfaceId); |
| |
| // Provide surface creator with surfaceId |
| wl_list_for_each_safe(info, tmp, &shell->shells, link) { |
| if (info->client == client) { |
| long long now; |
| struct pending_broadcast_info *pendingInfo; |
| |
| wl_simple_shell_send_surface_id( info->resource, surface_resource, surfaceId ); |
| |
| pendingInfo = zalloc(sizeof *pendingInfo); |
| if (pendingInfo == NULL) { |
| wl_list_remove(&surface_id->link); |
| free(surface_id); |
| return; |
| } |
| |
| creatorNotified= true; |
| |
| // Perform the surface creation broadcast after an asynchronous |
| // delay to give the surface creator time to assign a name |
| now = getCurrentTimeMillis(); |
| pendingInfo->creationTime = now; |
| pendingInfo->surfaceId = surfaceId; |
| wl_list_insert(&shell->pendingCreateBroadcast, &pendingInfo->link); |
| if (wl_list_length(&shell->pendingCreateBroadcast) == 1) |
| wl_event_source_timer_update( shell->delayTimer, BROADCAST_DELAY ); |
| break; |
| } |
| } |
| |
| if ( !creatorNotified ) |
| wstSimpleShellBroadcastCreation( shell, surfaceId ); |
| } |
| |
| void WstSimpleShellNotifySurfaceDestroyed( struct wl_simple_shell *shell, struct wl_client *client, uint32_t surfaceId ) |
| { |
| const char *name; |
| struct shell_info *info, *shelltmp; |
| struct simple_shell_surface_id *surface_id, *surfacetmp; |
| |
| WST_UNUSED(client); |
| |
| if (!shell || !shell->callbacks) |
| return; |
| |
| // Get any name the creator may have assigned the surface |
| if (shell->callbacks->get_name) |
| shell->callbacks->get_name( shell->userData, surfaceId, &name ); |
| if ( !name ) |
| name= (const char *)DEFAULT_NAME; |
| |
| // Broadcast the surface destruction announcement |
| wl_list_for_each_safe(info, shelltmp, &shell->shells, link) |
| wl_simple_shell_send_surface_destroyed(info->resource, surfaceId, name); |
| |
| // Remove surface from list |
| wl_list_for_each_safe(surface_id, surfacetmp, &shell->surfaces, link) { |
| if (surface_id->surfaceId == surfaceId) { |
| wl_list_remove(&surface_id->link); |
| free(surface_id); |
| break; |
| } |
| } |
| |
| //Remove surface intercept key |
| if (shell->callbacks->remove_key_intercept) |
| shell->callbacks->remove_key_intercept(shell->userData, surfaceId, 0, 0); |
| } |