From: Masayuki Sasaki Date: Fri, 7 Feb 2014 04:01:30 +0000 (+0900) Subject: 0.9.14 release -- improve: it corresponded to Wayland/Weston 1.4.0 X-Git-Tag: accepted/tizen/ivi/20140214.223342~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9e5fc1daeddad7e45bc0a9a94ce80d67284daa24;p=profile%2Fivi%2Fico-uxf-weston-plugin.git 0.9.14 release -- improve: it corresponded to Wayland/Weston 1.4.0 Change-Id: I1567c6659cf59da67ad57a1e59b0f4beb354d383 Signed-off-by: Masayuki Sasaki --- diff --git a/configure.ac b/configure.ac index 1a070d2..7f28765 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_PREREQ([2.68]) AC_INIT([ico-uxf-weston-plugin], - [0.9.12], + [0.9.14], [https://BUG-REPORT-ADDRESS]) AC_CONFIG_HEADERS([config.h]) @@ -30,7 +30,9 @@ AC_CHECK_HEADERS([execinfo.h]) AC_CHECK_FUNCS([mkostemp strchrnul]) -PKG_CHECK_MODULES([PLUGIN], [weston >= 1.1.1 pixman-1 xkbcommon]) +PKG_CHECK_MODULES([PLUGIN], [wayland-server >= 1.3.0 weston >= 1.3.0 pixman-1 xkbcommon]) + +PKG_CHECK_MODULES([EGL], [egl]) if test "x$GCC" = "xyes"; then my_common_gcc_flags="-Wall -Wextra -Wno-unused-parameter \ diff --git a/packaging/ico-uxf-weston-plugin.changes b/packaging/ico-uxf-weston-plugin.changes index 775ed7b..ef29faa 100644 --- a/packaging/ico-uxf-weston-plugin.changes +++ b/packaging/ico-uxf-weston-plugin.changes @@ -1,3 +1,10 @@ +* Fri Feb 07 2014 Shibata Makoto accepted/tizen/ivi/20140128.174118@6241868 +- 0.9.14 release +-- improve: it corresponded to Wayland/Weston 1.4.0 +-- bugfix: when change of surface different from deletion of surface overlaps, ico_window_mgr may crash +-- bugfix: when HomeScreen shows the menu and installation/uninstallation of a package are performed, a live thumbnail may blink +-- improve: output the conflict message of a configuration file(weston.ini) with a weston-ivi-config package + * Fri Jan 24 2014 Shibata Makoto accepted/tizen/ivi/release/20140109.181723@96ba865 - 0.9.12 release -- bugfix: ico_input_mgr avoid crashes in case the assigned app were not running diff --git a/packaging/ico-uxf-weston-plugin.spec b/packaging/ico-uxf-weston-plugin.spec index f108e53..d81c088 100644 --- a/packaging/ico-uxf-weston-plugin.spec +++ b/packaging/ico-uxf-weston-plugin.spec @@ -1,13 +1,13 @@ Name: ico-uxf-weston-plugin Summary: Weston Plugins for IVI -Version: 0.9.12 +Version: 0.9.14 Release: 1.1 Group: Graphics & UI Framework/Automotive UI License: MIT URL: "" Source0: %{name}-%{version}.tar.bz2 -BuildRequires: pkgconfig(weston) >= 1.3.0 +BuildRequires: pkgconfig(weston) >= 1.4.0 BuildRequires: pkgconfig(pixman-1) BuildRequires: pkgconfig(xkbcommon) >= 0.0.578 BuildRequires: pkgconfig(eina) @@ -18,8 +18,9 @@ BuildRequires: pkgconfig(ecore-wayland) BuildRequires: pkgconfig(aul) BuildRequires: pkgconfig(ecore) BuildRequires: mesa-devel -Requires: weston >= 1.3.0 +Requires: weston >= 1.4.0 Requires: weekeyboard +Conflicts: weston-ivi-config %description Weston Plugins for IVI diff --git a/protocol/xdg-shell.xml b/protocol/xdg-shell.xml new file mode 100644 index 0000000..4e5cff8 --- /dev/null +++ b/protocol/xdg-shell.xml @@ -0,0 +1,438 @@ + + + + + Copyright © 2008-2013 Kristian Høgsberg + Copyright © 2013 Rafael Antognolli + Copyright © 2013 Jasper St. Pierre + Copyright © 2010-2013 Intel Corporation + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + This interface is implemented by servers that provide + desktop-style user interfaces. + + It allows clients to associate a xdg_surface with + a basic surface. + + + + + Use this enum to check the protocol version, and it will be updated + automatically. + + + + + + + + Use this request in order to enable use of this interface. + + Understand and agree that one is using an unstable interface, + that will likely change in the future, breaking the API. + + + + + + + Create a shell surface for an existing surface. + + Only one shell or popup surface can be associated with a given + surface. + + + + + + + + Create a popup surface for an existing surface. + + Only one shell or popup surface can be associated with a given + surface. + + + + + + + + + + + + + + + + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style user interface. + + It provides requests to treat surfaces like windows, allowing to set + properties like maximized, fullscreen, minimized, and to move and resize + them, and associate metadata like title and app id. + + On the server side the object is automatically destroyed when + the related wl_surface is destroyed. On client side, + xdg_surface.destroy() must be called before destroying + the wl_surface object. + + + + + The xdg_surface interface is removed from the wl_surface object + that was turned into a xdg_surface with + xdg_shell.get_xdg_surface request. The xdg_surface properties, + like maximized and fullscreen, are lost. The wl_surface loses + its role as a xdg_surface. The wl_surface is unmapped. + + + + + + Setting a surface as transient of another means that it is child + of another surface. + + Child surfaces are stacked above their parents, and will be + unmapped if the parent is unmapped too. They should not appear + on task bars and alt+tab. + + + + + + + Set a short title for the surface. + + This string may be used to identify the surface in a task bar, + window list, or other user interface elements provided by the + compositor. + + The string must be encoded in UTF-8. + + + + + + + Set an id for the surface. + + The app id identifies the general class of applications to which + the surface belongs. + + It should be the ID that appears in the new desktop entry + specification, the interface name. + + + + + + + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. + + + + + + + Ping a client to check if it is receiving events and sending + requests. A client is expected to reply with a pong request. + + + + + + + Start a pointer-driven move of the surface. + + This request must be used in response to a button press event. + The server may ignore move requests depending on the state of + the surface (e.g. fullscreen or maximized). + + + + + + + + These values are used to indicate which edge of a surface + is being dragged in a resize operation. The server may + use this information to adapt its behavior, e.g. choose + an appropriate cursor image. + + + + + + + + + + + + + + + Start a pointer-driven resizing of the surface. + + This request must be used in response to a button press event. + The server may ignore resize requests depending on the state of + the surface (e.g. fullscreen or maximized). + + + + + + + + + The configure event asks the client to resize its surface. + + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). + + The edges parameter provides a hint about how the surface + was resized. The client may use this information to decide + how to adjust its content to the new size (e.g. a scrolling + area might adjust its content position to leave the viewable + content unmoved). Valid edge values are from resize_edge enum. + + The client is free to dismiss all but the last configure + event it received. + + The width and height arguments specify the size of the window + in surface local coordinates. + + + + + + + + + + Set the default output used by this surface when it is first mapped. + + If this value is NULL (default), it's up to the compositor to choose + which display will be used to map this surface. + + When fullscreen or maximized state are set on this surface, and it + wasn't mapped yet, the output set with this method will be used. + Otherwise, the output where the surface is currently mapped will be + used. + + + + + + + Event sent from the compositor to the client requesting that the client + goes to a fullscreen state. It's the client job to call set_fullscreen + and really trigger the fullscreen state. + + + + + + Event sent from the compositor to the client requesting that the client + leaves the fullscreen state. It's the client job to call + unset_fullscreen and really leave the fullscreen state. + + + + + + Set the surface as fullscreen. + + After this request, the compositor should send a configure event + informing the output size. + + This request informs the compositor that the next attached buffer + committed will be in a fullscreen state. The buffer size should be the + same size as the size informed in the configure event, if the client + doesn't want to leave any empty area. + + In other words: the next attached buffer after set_maximized is the new + maximized buffer. And the surface will be positioned at the maximized + position on commit. + + A simple way to synchronize and wait for the correct configure event is + to use a wl_display.sync request right after the set_fullscreen + request. When the sync callback returns, the last configure event + received just before it will be the correct one, and should contain the + right size for the surface to maximize. + + Setting one state won't unset another state. Use + xdg_surface.unset_fullscreen for unsetting it. + + + + + + Unset the surface fullscreen state. + + Same negotiation as set_fullscreen must be used. + + + + + + Event sent from the compositor to the client requesting that the client + goes to a maximized state. It's the client job to call set_maximized + and really trigger the maximized state. + + + + + + Event sent from the compositor to the client requesting that the client + leaves the maximized state. It's the client job to call unset_maximized + and really leave the maximized state. + + + + + + Set the surface as maximized. + + After this request, the compositor will send a configure event + informing the output size minus panel and other MW decorations. + + This request informs the compositor that the next attached buffer + committed will be in a maximized state. The buffer size should be the + same size as the size informed in the configure event, if the client + doesn't want to leave any empty area. + + In other words: the next attached buffer after set_maximized is the new + maximized buffer. And the surface will be positioned at the maximized + position on commit. + + A simple way to synchronize and wait for the correct configure event is + to use a wl_display.sync request right after the set_maximized request. + When the sync callback returns, the last configure event received just + before it will be the correct one, and should contain the right size + for the surface to maximize. + + Setting one state won't unset another state. Use + xdg_surface.unset_maximized for unsetting it. + + + + + + Unset the surface maximized state. + + Same negotiation as set_maximized must be used. + + + + + + Set the surface minimized state. + + Setting one state won't unset another state. + + + + + + The focused_set event is sent when this surface has been + activated. Window decorations should be updated accordingly. + + + + + + The focused_unset event is sent when this surface has been + deactivated, because another surface has been activated. Window + decorations should be updated accordingly. + + + + + + + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style popups/menus. A popup + surface is a transient surface with an added pointer grab. + + An existing implicit grab will be changed to owner-events mode, + and the popup grab will continue after the implicit grab ends + (i.e. releasing the mouse button does not cause the popup to be + unmapped). + + The popup grab continues until the window is destroyed or a mouse + button is pressed in any other clients window. A click in any of + the clients surfaces is reported as normal, however, clicks in + other clients surfaces will be discarded and trigger the callback. + + The x and y arguments specify the locations of the upper left + corner of the surface relative to the upper left corner of the + parent surface, in surface local coordinates. + + xdg_popup surfaces are always transient for another surface. + + + + + The xdg_surface interface is removed from the wl_surface object + that was turned into a xdg_surface with + xdg_shell.get_xdg_surface request. The xdg_surface properties, + like maximized and fullscreen, are lost. The wl_surface loses + its role as a xdg_surface. The wl_surface is unmapped. + + + + + + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. + + + + + + + Ping a client to check if it is receiving events and sending + requests. A client is expected to reply with a pong request. + + + + + + + The popup_done event is sent out when a popup grab is broken, + that is, when the users clicks a surface that doesn't belong + to the client owning the popup surface. + + + + + + diff --git a/settings/weston.ini b/settings/weston.ini index 83b7f21..673fbc4 100644 --- a/settings/weston.ini +++ b/settings/weston.ini @@ -4,7 +4,7 @@ shell= [shell] num-workspaces=1 -shell-exe= +client= locking=false animation=fade startup-animation=fade diff --git a/src/Makefile.am b/src/Makefile.am index ab5f846..b82a9bf 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,6 +2,7 @@ lib_LTLIBRARIES = libico-uxf-weston-plugin.la pkginclude_HEADERS = \ desktop-shell-client-protocol.h \ + xdg-shell-client-protocol.h \ input-method-client-protocol.h \ workspaces-client-protocol.h \ ico_window_mgr-client-protocol.h \ @@ -13,6 +14,7 @@ libico_uxf_weston_plugin_la_LIBADD = -ldrm_intel -lrt -lm libico_uxf_weston_plugin_la_LDFLAGS = -version-info 0:9:0 libico_uxf_weston_plugin_la_SOURCES = \ desktop-shell-protocol.c \ + xdg-shell-protocol.c \ input-method-protocol.c \ workspaces-protocol.c \ ico_window_mgr-protocol.c \ @@ -56,20 +58,21 @@ ico_ivi_shell_la_LDFLAGS = -module -avoid-version ico_ivi_shell_la_LIBADD = $(PLUGIN_LIBS) ico_ivi_shell_la_CFLAGS = $(GCC_CFLAGS) $(EXT_CFLAGS) $(PLUGIN_CFLAGS) ico_ivi_shell_la_SOURCES = \ + ico_ivi_shell.h \ ico_ivi_shell.c \ + ico_exposay.c \ + ico_input-panel.c \ ico_ivi_shell_private.h \ ico_ivi_common_private.h \ desktop-shell-protocol.c \ - input-method-protocol.c \ - workspaces-protocol.c \ desktop-shell-server-protocol.h \ - input-method-server-protocol.h \ - workspaces-server-protocol.h + xdg-shell-protocol.c \ + xdg-shell-server-protocol.h # Multi Window Manager ico_window_mgr = ico_window_mgr.la ico_window_mgr_la_LDFLAGS = -module -avoid-version -ico_window_mgr_la_LIBADD = -ldrm_intel $(PLUGIN_LIBS) $(AUL_LIBS) +ico_window_mgr_la_LIBADD = -lEGL -lGLESv2 -ldrm_intel $(PLUGIN_LIBS) $(AUL_LIBS) ico_window_mgr_la_CFLAGS = -I/usr/include/libdrm $(GCC_CFLAGS) $(EXT_CFLAGS) $(PLUGIN_CFLAGS) ico_window_mgr_la_SOURCES = \ ico_window_mgr.c \ @@ -108,6 +111,9 @@ BUILT_SOURCES = \ desktop-shell-protocol.c \ desktop-shell-server-protocol.h \ desktop-shell-client-protocol.h \ + xdg-shell-protocol.c \ + xdg-shell-server-protocol.h \ + xdg-shell-client-protocol.h \ input-method-protocol.c \ input-method-server-protocol.h \ input-method-client-protocol.h \ diff --git a/src/ico_exposay.c b/src/ico_exposay.c new file mode 100644 index 0000000..21f306f --- /dev/null +++ b/src/ico_exposay.c @@ -0,0 +1,605 @@ +/* + * Copyright © 2010-2012 Intel Corporation + * Copyright © 2011-2012 Collabora, Ltd. + * Copyright © 2013 Raspberry Pi Foundation + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "ico_ivi_shell.h" + +struct exposay_surface { + struct desktop_shell *shell; + struct weston_surface *surface; + struct weston_view *view; + struct wl_list link; + + int x; + int y; + int width; + int height; + double scale; + + int row; + int column; + + /* The animations only apply a transformation for their own lifetime, + * and don't have an option to indefinitely maintain the + * transformation in a steady state - so, we apply our own once the + * animation has finished. */ + struct weston_transform transform; +}; + +static void exposay_set_state(struct desktop_shell *shell, + enum exposay_target_state state, + struct weston_seat *seat); +static void exposay_check_state(struct desktop_shell *shell); + +static void +exposay_in_flight_inc(struct desktop_shell *shell) +{ + shell->exposay.in_flight++; +} + +static void +exposay_in_flight_dec(struct desktop_shell *shell) +{ + if (--shell->exposay.in_flight > 0) + return; + + exposay_check_state(shell); +} + +static void +exposay_animate_in_done(struct weston_view_animation *animation, void *data) +{ + struct exposay_surface *esurface = data; + + wl_list_insert(&esurface->view->geometry.transformation_list, + &esurface->transform.link); + weston_matrix_init(&esurface->transform.matrix); + weston_matrix_scale(&esurface->transform.matrix, + esurface->scale, esurface->scale, 1.0f); + weston_matrix_translate(&esurface->transform.matrix, + esurface->x - esurface->view->geometry.x, + esurface->y - esurface->view->geometry.y, + 0); + + weston_view_geometry_dirty(esurface->view); + weston_compositor_schedule_repaint(esurface->view->surface->compositor); + + exposay_in_flight_dec(esurface->shell); +} + +static void +exposay_animate_in(struct exposay_surface *esurface) +{ + exposay_in_flight_inc(esurface->shell); + + weston_move_scale_run(esurface->view, + esurface->x - esurface->view->geometry.x, + esurface->y - esurface->view->geometry.y, + 1.0, esurface->scale, 0, + exposay_animate_in_done, esurface); +} + +static void +exposay_animate_out_done(struct weston_view_animation *animation, void *data) +{ + struct exposay_surface *esurface = data; + struct desktop_shell *shell = esurface->shell; + + wl_list_remove(&esurface->link); + free(esurface); + + exposay_in_flight_dec(shell); +} + +static void +exposay_animate_out(struct exposay_surface *esurface) +{ + exposay_in_flight_inc(esurface->shell); + + /* Remove the static transformation set up by + * exposay_transform_in_done(). */ + wl_list_remove(&esurface->transform.link); + weston_view_geometry_dirty(esurface->view); + + weston_move_scale_run(esurface->view, + esurface->x - esurface->view->geometry.x, + esurface->y - esurface->view->geometry.y, + 1.0, esurface->scale, 1, + exposay_animate_out_done, esurface); +} + +static void +exposay_highlight_surface(struct desktop_shell *shell, + struct exposay_surface *esurface) +{ + struct weston_view *view = esurface->view; + + shell->exposay.row_current = esurface->row; + shell->exposay.column_current = esurface->column; + + activate(shell, view->surface, shell->exposay.seat); + shell->exposay.focus_current = view; +} + +static int +exposay_is_animating(struct desktop_shell *shell) +{ + if (shell->exposay.state_cur == EXPOSAY_LAYOUT_INACTIVE || + shell->exposay.state_cur == EXPOSAY_LAYOUT_OVERVIEW) + return 0; + + return (shell->exposay.in_flight > 0); +} + +static void +exposay_pick(struct desktop_shell *shell, int x, int y) +{ + struct exposay_surface *esurface; + + if (exposay_is_animating(shell)) + return; + + wl_list_for_each(esurface, &shell->exposay.surface_list, link) { + if (x < esurface->x || x > esurface->x + esurface->width) + continue; + if (y < esurface->y || y > esurface->y + esurface->height) + continue; + + exposay_highlight_surface(shell, esurface); + return; + } +} + +/* Pretty lame layout for now; just tries to make a square. Should take + * aspect ratio into account really. Also needs to be notified of surface + * addition and removal and adjust layout/animate accordingly. */ +static enum exposay_layout_state +exposay_layout(struct desktop_shell *shell) +{ + struct workspace *workspace = shell->exposay.workspace; + struct weston_compositor *compositor = shell->compositor; + struct weston_output *output = get_default_output(compositor); + struct weston_view *view; + struct exposay_surface *esurface, *highlight = NULL; + int w, h; + int i; + int last_row_removed = 0; + + wl_list_init(&shell->exposay.surface_list); + + shell->exposay.num_surfaces = 0; + wl_list_for_each(view, &workspace->layer.view_list, layer_link) { + if (!get_shell_surface(view->surface)) + continue; + shell->exposay.num_surfaces++; + } + + if (shell->exposay.num_surfaces == 0) { + shell->exposay.grid_size = 0; + shell->exposay.hpadding_outer = 0; + shell->exposay.vpadding_outer = 0; + shell->exposay.padding_inner = 0; + shell->exposay.surface_size = 0; + return EXPOSAY_LAYOUT_OVERVIEW; + } + + /* Lay the grid out as square as possible, losing surfaces from the + * bottom row if required. Start with fixed padding of a 10% margin + * around the outside and 80px internal padding between surfaces, and + * maximise the area made available to surfaces after this, but only + * to a maximum of 1/3rd the total output size. + * + * If we can't make a square grid, add one extra row at the bottom + * which will have a smaller number of columns. + * + * XXX: Surely there has to be a better way to express this maths, + * right?! + */ + shell->exposay.grid_size = floor(sqrtf(shell->exposay.num_surfaces)); + if (pow(shell->exposay.grid_size, 2) != shell->exposay.num_surfaces) + shell->exposay.grid_size++; + last_row_removed = pow(shell->exposay.grid_size, 2) - shell->exposay.num_surfaces; + + shell->exposay.hpadding_outer = (output->width / 10); + shell->exposay.vpadding_outer = (output->height / 10); + shell->exposay.padding_inner = 80; + + w = output->width - (shell->exposay.hpadding_outer * 2); + w -= shell->exposay.padding_inner * (shell->exposay.grid_size - 1); + w /= shell->exposay.grid_size; + + h = output->height - (shell->exposay.vpadding_outer * 2); + h -= shell->exposay.padding_inner * (shell->exposay.grid_size - 1); + h /= shell->exposay.grid_size; + + shell->exposay.surface_size = (w < h) ? w : h; + if (shell->exposay.surface_size > (output->width / 2)) + shell->exposay.surface_size = output->width / 2; + if (shell->exposay.surface_size > (output->height / 2)) + shell->exposay.surface_size = output->height / 2; + + i = 0; + wl_list_for_each(view, &workspace->layer.view_list, layer_link) { + int pad; + + pad = shell->exposay.surface_size + shell->exposay.padding_inner; + + if (!get_shell_surface(view->surface)) + continue; + + esurface = malloc(sizeof(*esurface)); + if (!esurface) { + exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, + shell->exposay.seat); + break; + } + + wl_list_insert(&shell->exposay.surface_list, &esurface->link); + esurface->shell = shell; + esurface->view = view; + + esurface->row = i / shell->exposay.grid_size; + esurface->column = i % shell->exposay.grid_size; + + esurface->x = shell->exposay.hpadding_outer; + esurface->x += pad * esurface->column; + esurface->y = shell->exposay.vpadding_outer; + esurface->y += pad * esurface->row; + + if (esurface->row == shell->exposay.grid_size - 1) + esurface->x += (shell->exposay.surface_size + shell->exposay.padding_inner) * last_row_removed / 2; + + if (view->surface->width > view->surface->height) + esurface->scale = shell->exposay.surface_size / (float) view->surface->width; + else + esurface->scale = shell->exposay.surface_size / (float) view->surface->height; + esurface->width = view->surface->width * esurface->scale; + esurface->height = view->surface->height * esurface->scale; + + if (shell->exposay.focus_current == esurface->view) + highlight = esurface; + + set_alpha_if_fullscreen(get_shell_surface(view->surface)); + + exposay_animate_in(esurface); + + i++; + } + + if (highlight) + exposay_highlight_surface(shell, highlight); + + weston_compositor_schedule_repaint(shell->compositor); + + return EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW; +} + +static void +exposay_focus(struct weston_pointer_grab *grab) +{ +} + +static void +exposay_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) +{ + struct desktop_shell *shell = + container_of(grab, struct desktop_shell, exposay.grab_ptr); + + weston_pointer_move(grab->pointer, x, y); + + exposay_pick(shell, + wl_fixed_to_int(grab->pointer->x), + wl_fixed_to_int(grab->pointer->y)); +} + +static void +exposay_button(struct weston_pointer_grab *grab, uint32_t time, uint32_t button, + uint32_t state_w) +{ + struct desktop_shell *shell = + container_of(grab, struct desktop_shell, exposay.grab_ptr); + struct weston_seat *seat = grab->pointer->seat; + enum wl_pointer_button_state state = state_w; + + if (button != BTN_LEFT) + return; + + /* Store the surface we clicked on, and don't do anything if we end up + * releasing on a different surface. */ + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { + shell->exposay.clicked = shell->exposay.focus_current; + return; + } + + if (shell->exposay.focus_current == shell->exposay.clicked) + exposay_set_state(shell, EXPOSAY_TARGET_SWITCH, seat); + else + shell->exposay.clicked = NULL; +} + +static void +exposay_pointer_grab_cancel(struct weston_pointer_grab *grab) +{ + struct desktop_shell *shell = + container_of(grab, struct desktop_shell, exposay.grab_ptr); + + exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, shell->exposay.seat); +} + +static const struct weston_pointer_grab_interface exposay_ptr_grab = { + exposay_focus, + exposay_motion, + exposay_button, + exposay_pointer_grab_cancel, +}; + +static int +exposay_maybe_move(struct desktop_shell *shell, int row, int column) +{ + struct exposay_surface *esurface; + + wl_list_for_each(esurface, &shell->exposay.surface_list, link) { + if (esurface->row != row || esurface->column != column) + continue; + + exposay_highlight_surface(shell, esurface); + return 1; + } + + return 0; +} + +static void +exposay_key(struct weston_keyboard_grab *grab, uint32_t time, uint32_t key, + uint32_t state_w) +{ + struct weston_seat *seat = grab->keyboard->seat; + struct desktop_shell *shell = + container_of(grab, struct desktop_shell, exposay.grab_kbd); + enum wl_keyboard_key_state state = state_w; + + if (state != WL_KEYBOARD_KEY_STATE_RELEASED) + return; + + switch (key) { + case KEY_ESC: + exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, seat); + break; + case KEY_ENTER: + exposay_set_state(shell, EXPOSAY_TARGET_SWITCH, seat); + break; + case KEY_UP: + exposay_maybe_move(shell, shell->exposay.row_current - 1, + shell->exposay.column_current); + break; + case KEY_DOWN: + /* Special case for trying to move to the bottom row when it + * has fewer items than all the others. */ + if (!exposay_maybe_move(shell, shell->exposay.row_current + 1, + shell->exposay.column_current) && + shell->exposay.row_current < (shell->exposay.grid_size - 1)) { + exposay_maybe_move(shell, shell->exposay.row_current + 1, + (shell->exposay.num_surfaces % + shell->exposay.grid_size) - 1); + } + break; + case KEY_LEFT: + exposay_maybe_move(shell, shell->exposay.row_current, + shell->exposay.column_current - 1); + break; + case KEY_RIGHT: + exposay_maybe_move(shell, shell->exposay.row_current, + shell->exposay.column_current + 1); + break; + case KEY_TAB: + /* Try to move right, then down (and to the leftmost column), + * then if all else fails, to the top left. */ + if (!exposay_maybe_move(shell, shell->exposay.row_current, + shell->exposay.column_current + 1) && + !exposay_maybe_move(shell, shell->exposay.row_current + 1, 0)) + exposay_maybe_move(shell, 0, 0); + break; + default: + break; + } +} + +static void +exposay_modifier(struct weston_keyboard_grab *grab, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ + struct desktop_shell *shell = + container_of(grab, struct desktop_shell, exposay.grab_kbd); + struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat; + + /* We want to know when mod has been pressed and released. + * FIXME: There is a problem here: if mod is pressed, then a key + * is pressed and released, then mod is released, we will treat that + * as if only mod had been pressed and released. */ + if (seat->modifier_state) { + if (seat->modifier_state == shell->binding_modifier) { + shell->exposay.mod_pressed = true; + } else { + shell->exposay.mod_invalid = true; + } + } else { + if (shell->exposay.mod_pressed && !shell->exposay.mod_invalid) + exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, seat); + + shell->exposay.mod_invalid = false; + shell->exposay.mod_pressed = false; + } + + return; +} + +static void +exposay_cancel(struct weston_keyboard_grab *grab) +{ + struct desktop_shell *shell = + container_of(grab, struct desktop_shell, exposay.grab_kbd); + + exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, shell->exposay.seat); +} + +static const struct weston_keyboard_grab_interface exposay_kbd_grab = { + exposay_key, + exposay_modifier, + exposay_cancel, +}; + +/** + * Called when the transition from overview -> inactive has completed. + */ +static enum exposay_layout_state +exposay_set_inactive(struct desktop_shell *shell) +{ + struct weston_seat *seat = shell->exposay.seat; + + weston_keyboard_end_grab(seat->keyboard); + weston_pointer_end_grab(seat->pointer); + if (seat->keyboard->input_method_resource) + seat->keyboard->grab = &seat->keyboard->input_method_grab; + + return EXPOSAY_LAYOUT_INACTIVE; +} + +/** + * Begins the transition from overview to inactive. */ +static enum exposay_layout_state +exposay_transition_inactive(struct desktop_shell *shell, int switch_focus) +{ + struct exposay_surface *esurface; + + /* Call activate() before we start the animations to avoid + * animating back the old state and then immediately transitioning + * to the new. */ + if (switch_focus && shell->exposay.focus_current) + activate(shell, shell->exposay.focus_current->surface, + shell->exposay.seat); + else if (shell->exposay.focus_prev) + activate(shell, shell->exposay.focus_prev->surface, + shell->exposay.seat); + + wl_list_for_each(esurface, &shell->exposay.surface_list, link) + exposay_animate_out(esurface); + weston_compositor_schedule_repaint(shell->compositor); + + return EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE; +} + +static enum exposay_layout_state +exposay_transition_active(struct desktop_shell *shell) +{ + struct weston_seat *seat = shell->exposay.seat; + + shell->exposay.workspace = get_current_workspace(shell); + shell->exposay.focus_prev = get_default_view (seat->keyboard->focus); + shell->exposay.focus_current = get_default_view (seat->keyboard->focus); + shell->exposay.clicked = NULL; + wl_list_init(&shell->exposay.surface_list); + + lower_fullscreen_layer(shell); + shell->exposay.grab_kbd.interface = &exposay_kbd_grab; + weston_keyboard_start_grab(seat->keyboard, + &shell->exposay.grab_kbd); + weston_keyboard_set_focus(seat->keyboard, NULL); + + shell->exposay.grab_ptr.interface = &exposay_ptr_grab; + weston_pointer_start_grab(seat->pointer, + &shell->exposay.grab_ptr); + weston_pointer_set_focus(seat->pointer, NULL, + seat->pointer->x, seat->pointer->y); + + return exposay_layout(shell); +} + +static void +exposay_check_state(struct desktop_shell *shell) +{ + enum exposay_layout_state state_new = shell->exposay.state_cur; + int do_switch = 0; + + /* Don't do anything whilst animations are running, just store up + * target state changes and only act on them when the animations have + * completed. */ + if (exposay_is_animating(shell)) + return; + + switch (shell->exposay.state_target) { + case EXPOSAY_TARGET_OVERVIEW: + switch (shell->exposay.state_cur) { + case EXPOSAY_LAYOUT_OVERVIEW: + goto out; + case EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW: + state_new = EXPOSAY_LAYOUT_OVERVIEW; + break; + default: + state_new = exposay_transition_active(shell); + break; + } + break; + + case EXPOSAY_TARGET_SWITCH: + do_switch = 1; /* fallthrough */ + case EXPOSAY_TARGET_CANCEL: + switch (shell->exposay.state_cur) { + case EXPOSAY_LAYOUT_INACTIVE: + goto out; + case EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE: + state_new = exposay_set_inactive(shell); + break; + default: + state_new = exposay_transition_inactive(shell, do_switch); + break; + } + + break; + } + +out: + shell->exposay.state_cur = state_new; +} + +static void +exposay_set_state(struct desktop_shell *shell, enum exposay_target_state state, + struct weston_seat *seat) +{ + shell->exposay.state_target = state; + shell->exposay.seat = seat; + exposay_check_state(shell); +} + +void +exposay_binding(struct weston_seat *seat, enum weston_keyboard_modifier modifier, + void *data) +{ + struct desktop_shell *shell = data; + + exposay_set_state(shell, EXPOSAY_TARGET_OVERVIEW, seat); +} diff --git a/src/ico_input-panel.c b/src/ico_input-panel.c new file mode 100644 index 0000000..e58bcac --- /dev/null +++ b/src/ico_input-panel.c @@ -0,0 +1,443 @@ +/* + * Copyright © 2010-2012 Intel Corporation + * Copyright © 2011-2012 Collabora, Ltd. + * Copyright © 2013 Raspberry Pi Foundation + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include "ico_ivi_shell.h" +#include "ico_ivi_shell_private.h" +#include "desktop-shell-server-protocol.h" +#include "input-method-server-protocol.h" + +struct input_panel_surface { + struct wl_resource *resource; + struct wl_signal destroy_signal; + + struct desktop_shell *shell; + + struct wl_list link; + struct weston_surface *surface; + struct weston_view *view; + struct wl_listener surface_destroy_listener; + + struct weston_output *output; + uint32_t panel; +}; + +extern int ico_debug_level; + +/* debug log macros */ +#define uifw_debug(fmt,...) \ + { if (ico_debug_level >= 5) {weston_log("DBG>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} } +#define uifw_trace(fmt,...) \ + { if (ico_debug_level >= 4) {weston_log("TRC>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} } +#define uifw_info(fmt,...) \ + { if (ico_debug_level >= 3) {weston_log("INF>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} } +#define uifw_warn(fmt,...) \ + { if (ico_debug_level >= 2) {weston_log("WRN>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} } +#define uifw_error(fmt,...) \ + { if (ico_debug_level >= 1) {weston_log("ERR>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} } + +static void +show_input_panels(struct wl_listener *listener, void *data) +{ + struct desktop_shell *shell = + container_of(listener, struct desktop_shell, + show_input_panel_listener); + struct input_panel_surface *ipsurf, *next; + + shell->text_input.surface = (struct weston_surface*)data; + + uifw_trace("show_input_panels: Enter(surface=%08x[%d])", + (int)data, shell->showing_input_panels); + + if (shell->showing_input_panels) { + uifw_trace("show_input_panels: Leave(already)"); + return; + } + shell->showing_input_panels = true; + + /* if ico_window_mgr hook, call hook routine */ + if (shell_hook_show_layer) { + (*shell_hook_show_layer)(LAYER_TYPE_INPUTPANEL, 1, data); + return; + } + + if (!shell->locked) + wl_list_insert(&shell->panel_layer.link, + &shell->input_panel_layer.link); + wl_list_for_each_safe(ipsurf, next, + &shell->input_panel.surfaces, link) { + if (ipsurf->surface->width == 0) + continue; + uifw_debug("show_input_panels: insert view=%08x surf=%08x", + (int)ipsurf->view, (int)ipsurf->surface); + wl_list_remove(&ipsurf->view->layer_link); + wl_list_init(&ipsurf->view->layer_link); + wl_list_insert(&shell->input_panel_layer.view_list, + &ipsurf->view->layer_link); + weston_view_geometry_dirty(ipsurf->view); + weston_view_update_transform(ipsurf->view); + weston_surface_damage(ipsurf->surface); + weston_slide_run(ipsurf->view, ipsurf->surface->height * 0.9, + 0, NULL, NULL); + } + uifw_trace("show_input_panels: Leave"); +} + +static void +hide_input_panels(struct wl_listener *listener, void *data) +{ + struct desktop_shell *shell = + container_of(listener, struct desktop_shell, + hide_input_panel_listener); + struct weston_view *view, *next; + + uifw_trace("hide_input_panels: Enter(surface=%08x[%d])", + (int)data, shell->showing_input_panels); + + if (!shell->showing_input_panels) { + uifw_trace("hide_input_panels: Leave(not show)"); + return; + } + shell->showing_input_panels = false; + + /* if ico_window_mgr hook, call hook routine */ + if (shell_hook_show_layer) { + (*shell_hook_show_layer)(LAYER_TYPE_INPUTPANEL, 0, NULL); + return; + } + + if (!shell->locked) + wl_list_remove(&shell->input_panel_layer.link); + + wl_list_for_each_safe(view, next, + &shell->input_panel_layer.view_list, layer_link) + weston_view_unmap(view); + uifw_trace("hide_input_panels: Leave"); +} + +static void +update_input_panels(struct wl_listener *listener, void *data) +{ + struct desktop_shell *shell = + container_of(listener, struct desktop_shell, + update_input_panel_listener); + + memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t)); +} + +static void +input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy) +{ + struct input_panel_surface *ip_surface = surface->configure_private; + struct desktop_shell *shell = ip_surface->shell; + struct weston_view *view; + float x, y; + + uifw_trace("input_panel_configure: Enter(surface=%08x x/y=%d/%d w/h=%d/%d)", + (int)surface, sx, sy, surface->width, surface->height); + + if (surface->width == 0) { + uifw_trace("input_panel_configure: Leave(width==0)"); + return; + } + if (ip_surface->panel) { + view = get_default_view(shell->text_input.surface); + if (view == NULL) { + uifw_trace("input_panel_configure: Leave(no view)"); + return; + } + x = view->geometry.x + shell->text_input.cursor_rectangle.x2; + y = view->geometry.y + shell->text_input.cursor_rectangle.y2; + } else { + x = ip_surface->output->x + (ip_surface->output->width - surface->width) / 2; + y = ip_surface->output->y + ip_surface->output->height - surface->height; + if (! shell_hook_map) { + y -= 132.0f; + } + } + + weston_view_set_position(ip_surface->view, x, y); + + if (!weston_surface_is_mapped(surface) && shell->showing_input_panels) { + wl_list_insert(&shell->input_panel_layer.view_list, + &ip_surface->view->layer_link); + weston_view_update_transform(ip_surface->view); + weston_surface_damage(surface); + weston_slide_run(ip_surface->view, ip_surface->view->surface->height * 0.9, 0, NULL, NULL); + } + + if (shell_hook_map) { + int wx, wy; + int ww, wh; + wx = (int)x; + wy = (int)y; + ww = ip_surface->output->width; + wh = ip_surface->output->height; + (*shell_hook_map)(surface, &ww, &wh, &wx, &wy); + } + if (shell_hook_configure) { + (*shell_hook_configure)(surface); + } + uifw_trace("input_panel_configure: Leave"); +} + +static void +destroy_input_panel_surface(struct input_panel_surface *input_panel_surface) +{ + wl_signal_emit(&input_panel_surface->destroy_signal, input_panel_surface); + + wl_list_remove(&input_panel_surface->surface_destroy_listener.link); + wl_list_remove(&input_panel_surface->link); + + uifw_trace("destroy_input_panel_surface: Enter(surface=%08x)", + (int)input_panel_surface->surface); + + input_panel_surface->surface->configure = NULL; + weston_view_destroy(input_panel_surface->view); + + free(input_panel_surface); + uifw_trace("destroy_input_panel_surface: Leave"); +} + +static struct input_panel_surface * +get_input_panel_surface(struct weston_surface *surface) +{ + if (surface->configure == input_panel_configure) { + return surface->configure_private; + } else { + return NULL; + } +} + +static void +input_panel_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct input_panel_surface *ipsurface = container_of(listener, + struct input_panel_surface, + surface_destroy_listener); + + if (ipsurface->resource) { + wl_resource_destroy(ipsurface->resource); + } else { + destroy_input_panel_surface(ipsurface); + } +} + +static struct input_panel_surface * +create_input_panel_surface(struct desktop_shell *shell, + struct weston_surface *surface) +{ + struct input_panel_surface *input_panel_surface; + + input_panel_surface = calloc(1, sizeof *input_panel_surface); + if (!input_panel_surface) + return NULL; + + uifw_trace("create_input_panel_surface: Enter(surface=%08x)", (int)surface); + + surface->configure = input_panel_configure; + surface->configure_private = input_panel_surface; + + input_panel_surface->shell = shell; + + input_panel_surface->surface = surface; + input_panel_surface->view = weston_view_create(surface); + + wl_signal_init(&input_panel_surface->destroy_signal); + input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy; + wl_signal_add(&surface->destroy_signal, + &input_panel_surface->surface_destroy_listener); + + wl_list_init(&input_panel_surface->link); + + uifw_trace("create_input_panel_surface: Leave(ipsurf=%08x)", (int)input_panel_surface); + + return input_panel_surface; +} + +static void +input_panel_surface_set_toplevel(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *output_resource, + uint32_t position) +{ + struct input_panel_surface *input_panel_surface = + wl_resource_get_user_data(resource); + struct desktop_shell *shell = input_panel_surface->shell; + + wl_list_insert(&shell->input_panel.surfaces, + &input_panel_surface->link); + + input_panel_surface->output = wl_resource_get_user_data(output_resource); + input_panel_surface->panel = 0; +} + +static void +input_panel_surface_set_overlay_panel(struct wl_client *client, + struct wl_resource *resource) +{ + struct input_panel_surface *input_panel_surface = + wl_resource_get_user_data(resource); + struct desktop_shell *shell = input_panel_surface->shell; + + wl_list_insert(&shell->input_panel.surfaces, + &input_panel_surface->link); + + input_panel_surface->panel = 1; +} + +static const struct wl_input_panel_surface_interface input_panel_surface_implementation = { + input_panel_surface_set_toplevel, + input_panel_surface_set_overlay_panel +}; + +static void +destroy_input_panel_surface_resource(struct wl_resource *resource) +{ + struct input_panel_surface *ipsurf = + wl_resource_get_user_data(resource); + + destroy_input_panel_surface(ipsurf); +} + +static void +input_panel_get_input_panel_surface(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource) +{ + struct weston_surface *surface = + wl_resource_get_user_data(surface_resource); + struct desktop_shell *shell = wl_resource_get_user_data(resource); + struct input_panel_surface *ipsurf; + + uifw_trace("input_panel_get_input_panel_surface: Enter"); + + if (get_input_panel_surface(surface)) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "wl_input_panel::get_input_panel_surface already requested"); + return; + } + + ipsurf = create_input_panel_surface(shell, surface); + if (!ipsurf) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "surface->configure already set"); + return; + } + + ipsurf->resource = + wl_resource_create(client, + &wl_input_panel_surface_interface, 1, id); + wl_resource_set_implementation(ipsurf->resource, + &input_panel_surface_implementation, + ipsurf, + destroy_input_panel_surface_resource); + + /* if ico_window_mgr hook, call hook routine */ + if (shell_hook_create) { + (*shell_hook_create)(LAYER_TYPE_INPUTPANEL, + surface, client, (struct shell_surface *)ipsurf); + } + uifw_trace("input_panel_get_input_panel_surface: Leave"); +} + +static const struct wl_input_panel_interface input_panel_implementation = { + input_panel_get_input_panel_surface +}; + +static void +unbind_input_panel(struct wl_resource *resource) +{ + struct desktop_shell *shell = wl_resource_get_user_data(resource); + + shell->input_panel.binding = NULL; +} + +static void +bind_input_panel(struct wl_client *client, + void *data, uint32_t version, uint32_t id) +{ + struct desktop_shell *shell = data; + struct wl_resource *resource; + + resource = wl_resource_create(client, + &wl_input_panel_interface, 1, id); + + if (shell->input_panel.binding == NULL) { + wl_resource_set_implementation(resource, + &input_panel_implementation, + shell, unbind_input_panel); + shell->input_panel.binding = resource; + return; + } + + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "interface object already bound"); + wl_resource_destroy(resource); +} + +void +input_panel_destroy(struct desktop_shell *shell) +{ + wl_list_remove(&shell->show_input_panel_listener.link); + wl_list_remove(&shell->hide_input_panel_listener.link); +} + +int +input_panel_setup(struct desktop_shell *shell) +{ + struct weston_compositor *ec = shell->compositor; + + shell->show_input_panel_listener.notify = show_input_panels; + wl_signal_add(&ec->show_input_panel_signal, + &shell->show_input_panel_listener); + shell->hide_input_panel_listener.notify = hide_input_panels; + wl_signal_add(&ec->hide_input_panel_signal, + &shell->hide_input_panel_listener); + shell->update_input_panel_listener.notify = update_input_panels; + wl_signal_add(&ec->update_input_panel_signal, + &shell->update_input_panel_listener); + + wl_list_init(&shell->input_panel.surfaces); + + if (wl_global_create(shell->compositor->wl_display, + &wl_input_panel_interface, 1, + shell, bind_input_panel) == NULL) + return -1; + + return 0; +} + +WL_EXPORT struct weston_view * +ico_input_panel_get_view(void *ipsurf) +{ + return ((struct input_panel_surface *)ipsurf)->view; +} diff --git a/src/ico_input_mgr.c b/src/ico_input_mgr.c index 7e1699e..17b0fab 100644 --- a/src/ico_input_mgr.c +++ b/src/ico_input_mgr.c @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -127,7 +127,7 @@ struct uifw_input_device { int pend_y; /* pending Y coordinate */ uint16_t node; /* display number */ uint16_t pending; /* pending flag */ - struct weston_surface *grab; /* current grab surface */ + struct weston_view *grab; /* current grab surface view */ }; /* Input Region Table */ @@ -494,7 +494,7 @@ ico_mgr_send_input_event(struct wl_client *client, struct wl_resource *resource, wl_fixed_t fix_x; /* wayland X coordinate */ wl_fixed_t fix_y; /* wayland Y coordinate */ wl_fixed_t dx, dy; /* relative coordinate (dummy) */ - struct weston_surface *grabsave; /* real grab surface */ + struct weston_view *grabsave; /* real grab surface view */ int keyboard_active; /* keyborad active surface flag */ #if 0 /* too many log */ @@ -691,10 +691,10 @@ ico_mgr_send_input_event(struct wl_client *client, struct wl_resource *resource, case EVENT_MOTION: if ((type == ICO_INPUT_MGR_DEVICE_TYPE_TOUCH) && (pInputMgr->seat->touch)) { - if (pInputMgr->seat->num_tp > 10) { + if (pInputMgr->seat->touch->num_tp > 10) { uifw_debug("ico_mgr_send_input_event: num=%d reset", - pInputMgr->seat->num_tp); - pInputMgr->seat->num_tp = 0; /* safty gard */ + pInputMgr->seat->touch->num_tp); + pInputMgr->seat->touch->num_tp = 0; /* safty gard */ } grabsave = pInputMgr->seat->touch->focus; uifw_debug("ico_mgr_send_input_event: MOTION(%d/%d) grab %08x org %08x", @@ -719,10 +719,10 @@ ico_mgr_send_input_event(struct wl_client *client, struct wl_resource *resource, uifw_trace("ico_mgr_send_input_event: notify_button(%d,%d)", code, value); if (pInputMgr->seat->pointer) { if (value) { - dev->grab = weston_compositor_pick_surface( + dev->grab = weston_compositor_pick_view( pInputMgr->compositor, fix_x, fix_y, &dx, &dy); weston_pointer_set_focus(pInputMgr->seat->pointer, dev->grab, dx, dy); - ico_window_mgr_active_surface(dev->grab); + ico_window_mgr_active_surface(dev->grab->surface); } else { dev->grab = NULL; @@ -741,16 +741,16 @@ ico_mgr_send_input_event(struct wl_client *client, struct wl_resource *resource, dev->grab = NULL; if (grabsave) { weston_touch_set_focus(pInputMgr->seat, NULL); - if (pInputMgr->seat->num_tp > 0) { + if (pInputMgr->seat->touch->num_tp > 0) { uifw_debug("ico_mgr_send_input_event: num=%d reset for reset focuse", - pInputMgr->seat->num_tp); - pInputMgr->seat->num_tp = 0; + pInputMgr->seat->touch->num_tp); + pInputMgr->seat->touch->num_tp = 0; } } } else if (value == ICO_INPUT_MGR_CONTROL_TOUCH_EVENT_DOWN) { grabsave = pInputMgr->seat->touch->focus; - dev->grab = weston_compositor_pick_surface( + dev->grab = weston_compositor_pick_view( pInputMgr->compositor, fix_x, fix_y, &dx, &dy); uifw_trace("ico_mgr_send_input_event: notify_touch(DOWN=%d/%d) " "grab=%08x org=%08x", fix_x/256, fix_y/256, @@ -758,13 +758,13 @@ ico_mgr_send_input_event(struct wl_client *client, struct wl_resource *resource, if (grabsave != dev->grab) { weston_touch_set_focus(pInputMgr->seat, dev->grab); } - if (pInputMgr->seat->num_tp > 0) { + if (pInputMgr->seat->touch->num_tp > 0) { uifw_debug("ico_mgr_send_input_event: touch_down illegal num, modify"); weston_touch_set_focus(pInputMgr->seat, NULL); - pInputMgr->seat->num_tp = 0; + pInputMgr->seat->touch->num_tp = 0; } notify_touch(pInputMgr->seat, ctime, 0, fix_x, fix_y, WL_TOUCH_DOWN); - ico_window_mgr_active_surface(dev->grab); + ico_window_mgr_active_surface(dev->grab->surface); } else { grabsave = pInputMgr->seat->touch->focus; @@ -773,10 +773,11 @@ ico_mgr_send_input_event(struct wl_client *client, struct wl_resource *resource, if ((grabsave != dev->grab) && (dev->grab != NULL)) { weston_touch_set_focus(pInputMgr->seat, dev->grab); } - if ((pInputMgr->seat->num_tp == 0) || (pInputMgr->seat->num_tp > 10)) { + if ((pInputMgr->seat->touch->num_tp == 0) || + (pInputMgr->seat->touch->num_tp > 10)) { uifw_debug("ico_mgr_send_input_event: num=%d reset", - pInputMgr->seat->num_tp); - pInputMgr->seat->num_tp = 1; + pInputMgr->seat->touch->num_tp); + pInputMgr->seat->touch->num_tp = 1; } notify_touch(pInputMgr->seat, ctime, 0, 0, 0, WL_TOUCH_UP); if (grabsave == dev->grab) grabsave = NULL; diff --git a/src/ico_input_mgr.h b/src/ico_input_mgr.h index 8b4d9bd..095128f 100644 --- a/src/ico_input_mgr.h +++ b/src/ico_input_mgr.h @@ -1,5 +1,5 @@ /* - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided diff --git a/src/ico_ivi_common_private.h b/src/ico_ivi_common_private.h index 5efd161..bf95e02 100644 --- a/src/ico_ivi_common_private.h +++ b/src/ico_ivi_common_private.h @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided diff --git a/src/ico_ivi_shell.c b/src/ico_ivi_shell.c index fbdd901..e794554 100644 --- a/src/ico_ivi_shell.c +++ b/src/ico_ivi_shell.c @@ -1,7 +1,8 @@ /* * Copyright © 2010-2012 Intel Corporation * Copyright © 2011-2012 Collabora, Ltd. - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013 Raspberry Pi Foundation + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -24,7 +25,6 @@ #include #include -#include #include #include #include @@ -33,28 +33,22 @@ #include #include -#include -#include +#include "ico_ivi_shell.h" +#include "ico_ivi_shell_private.h" #include "desktop-shell-server-protocol.h" -#include "input-method-server-protocol.h" #include "workspaces-server-protocol.h" #include -#include "ico_ivi_shell_private.h" +#include "xdg-shell-server-protocol.h" +#ifndef WESTON_SHELL_CLIENT +#define WESTON_SHELL_CLIENT "weston-desktop-shell" +#endif #define DEFAULT_NUM_WORKSPACES 1 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200 -enum animation_type { - ANIMATION_NONE, - - ANIMATION_ZOOM, - ANIMATION_FADE -}; - -enum fade_type { - FADE_IN, - FADE_OUT -}; +#ifndef static_assert +#define static_assert(cond, msg) +#endif struct focus_state { struct weston_seat *seat; @@ -65,115 +59,17 @@ struct focus_state { struct wl_listener surface_destroy_listener; }; -struct workspace { - struct weston_layer layer; - - struct wl_list focus_list; - struct wl_listener seat_destroyed_listener; -}; - -struct input_panel_surface { - struct wl_resource *resource; - struct wl_signal destroy_signal; - - struct desktop_shell *shell; - - struct wl_list link; - struct weston_surface *surface; - struct wl_listener surface_destroy_listener; - - struct weston_output *output; - uint32_t panel; -}; - -struct desktop_shell { - struct weston_compositor *compositor; - - struct wl_listener idle_listener; - struct wl_listener wake_listener; - struct wl_listener destroy_listener; - struct wl_listener show_input_panel_listener; - struct wl_listener hide_input_panel_listener; - struct wl_listener update_input_panel_listener; - - struct weston_layer fullscreen_layer; - struct weston_layer panel_layer; - struct weston_layer background_layer; - struct weston_layer lock_layer; - struct weston_layer input_panel_layer; - - struct wl_listener pointer_focus_listener; - struct weston_surface *grab_surface; - - struct { - struct weston_process process; - struct wl_client *client; - struct wl_resource *desktop_shell; - - unsigned deathcount; - uint32_t deathstamp; - } child; - - bool locked; - bool showing_input_panels; - bool prepare_event_sent; - - struct { - struct weston_surface *surface; - pixman_box32_t cursor_rectangle; - } text_input; - - struct weston_surface *lock_surface; - struct wl_listener lock_surface_listener; - - struct { - struct wl_array array; - unsigned int current; - unsigned int num; - - struct wl_list client_list; - - struct weston_animation animation; - struct wl_list anim_sticky_list; - int anim_dir; - uint32_t anim_timestamp; - double anim_current; - struct workspace *anim_from; - struct workspace *anim_to; - } workspaces; - - struct { - char *path; - int duration; - struct wl_resource *binding; - struct weston_process process; - struct wl_event_source *timer; - } screensaver; - - struct { - struct wl_resource *binding; - struct wl_list surfaces; - } input_panel; - - struct { - struct weston_surface *surface; - struct weston_surface_animation *animation; - enum fade_type type; - struct wl_event_source *startup_timer; - } fade; - - uint32_t binding_modifier; - enum animation_type win_animation_type; - enum animation_type startup_animation_type; +struct shell_output { + struct desktop_shell *shell; + struct weston_output *output; + struct wl_listener destroy_listener; + struct wl_list link; }; -#if 0 /* move to ico_ivi_shell.h */ +#if 0 /* move to ico_ivi_shell_private.h */ enum shell_surface_type { SHELL_SURFACE_NONE, SHELL_SURFACE_TOPLEVEL, - SHELL_SURFACE_TRANSIENT, - SHELL_SURFACE_FULLSCREEN, - SHELL_SURFACE_MAXIMIZED, SHELL_SURFACE_POPUP, SHELL_SURFACE_XWAYLAND }; @@ -184,22 +80,66 @@ struct ping_timer { uint32_t serial; }; +/* + * Surface stacking and ordering. + * + * This is handled using several linked lists of surfaces, organised into + * ‘layers’. The layers are ordered, and each of the surfaces in one layer are + * above all of the surfaces in the layer below. The set of layers is static and + * in the following order (top-most first): + * • Lock layer (only ever displayed on its own) + * • Cursor layer + * • Fullscreen layer + * • Panel layer + * • Input panel layer + * • Workspace layers + * • Background layer + * + * The list of layers may be manipulated to remove whole layers of surfaces from + * display. For example, when locking the screen, all layers except the lock + * layer are removed. + * + * A surface’s layer is modified on configuring the surface, in + * set_surface_type() (which is only called when the surface’s type change is + * _committed_). If a surface’s type changes (e.g. when making a window + * fullscreen) its layer changes too. + * + * In order to allow popup and transient surfaces to be correctly stacked above + * their parent surfaces, each surface tracks both its parent surface, and a + * linked list of its children. When a surface’s layer is updated, so are the + * layers of its children. Note that child surfaces are *not* the same as + * subsurfaces — child/parent surfaces are purely for maintaining stacking + * order. + * + * The children_link list of siblings of a surface (i.e. those surfaces which + * have the same parent) only contains weston_surfaces which have a + * shell_surface. Stacking is not implemented for non-shell_surface + * weston_surfaces. This means that the following implication does *not* hold: + * (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link) + */ + struct shell_surface { struct wl_resource *resource; struct wl_signal destroy_signal; struct weston_surface *surface; + struct weston_view *view; + int32_t last_width, last_height; struct wl_listener surface_destroy_listener; struct weston_surface *parent; + struct wl_list children_list; /* child surfaces of this one */ + struct wl_list children_link; /* sibling surfaces of this one */ struct desktop_shell *shell; - enum shell_surface_type type, next_type; + enum shell_surface_type type; char *title, *class; int32_t saved_x, saved_y; + int32_t saved_width, saved_height; bool saved_position_valid; + bool saved_size_valid; bool saved_rotation_valid; - char layertype; /* surface layer type */ - int unresponsive; + char layertype; /* surface layer type for ico_window_mgr */ + int unresponsive, grabbed; struct { struct weston_transform transform; @@ -222,7 +162,7 @@ struct shell_surface { enum wl_shell_surface_fullscreen_method type; struct weston_transform transform; /* matrix from x, y */ uint32_t framerate; - struct weston_surface *black_surface; + struct weston_view *black_view; } fullscreen; struct ping_timer *ping_timer; @@ -231,9 +171,17 @@ struct shell_surface { struct weston_output *fullscreen_output; struct weston_output *output; + struct weston_output *recommended_output; struct wl_list link; const struct weston_shell_client *client; + + struct { + bool maximized; + bool fullscreen; + bool relative; + } state, next_state; /* surface states */ + bool state_changed; }; struct shell_grab { @@ -256,6 +204,7 @@ struct weston_move_grab { struct weston_touch_move_grab { struct shell_touch_grab base; + int active; wl_fixed_t dx, dy; }; @@ -280,15 +229,12 @@ struct shell_seat { } popup_grab; }; -static void -activate(struct desktop_shell *shell, struct weston_surface *es, - struct weston_seat *seat); - -static struct workspace * -get_current_workspace(struct desktop_shell *shell); - -static struct shell_surface * -get_shell_surface(struct weston_surface *surface); +void +set_alpha_if_fullscreen(struct shell_surface *shsurf) +{ + if (shsurf && shsurf->state.fullscreen) + shsurf->fullscreen.black_view->alpha = 0.25; +} static struct desktop_shell * shell_surface_get_shell(struct shell_surface *shsurf); @@ -299,13 +245,31 @@ surface_rotate(struct shell_surface *surface, struct weston_seat *seat); static void shell_fade_startup(struct desktop_shell *shell); +static struct shell_seat * +get_shell_seat(struct weston_seat *seat); + +static void +shell_surface_update_child_surface_layers(struct shell_surface *shsurf); + +static bool +shell_surface_is_wl_shell_surface(struct shell_surface *shsurf); + +static bool +shell_surface_is_xdg_surface(struct shell_surface *shsurf); + +static bool +shell_surface_is_xdg_popup(struct shell_surface *shsurf); + +static void +shell_surface_set_parent(struct shell_surface *shsurf, + struct weston_surface *parent); + /* shell management table */ static struct desktop_shell *_ico_ivi_shell = NULL; /* shell program path for ico-ivi */ -static char *shell_exe = NULL; #define DEFAULT_DEBUG_LEVEL 4 -static int ico_debug_level = DEFAULT_DEBUG_LEVEL; /* Debug Level */ +int ico_debug_level = DEFAULT_DEBUG_LEVEL; /* Debug Level */ /* default display */ static struct weston_output *default_inputpanel = NULL; @@ -323,42 +287,41 @@ static struct weston_output *default_inputpanel = NULL; { if (ico_debug_level >= 1) {weston_log("ERR>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} } /* hook functions */ -static void (*shell_hook_bind)(struct wl_client *client, void *shell) = NULL; -static void (*shell_hook_unbind)(struct wl_client *client) = NULL; -static void (*shell_hook_create)(int layertype, - struct wl_client *client, struct wl_resource *resource, - struct weston_surface *surface, - struct shell_surface *shsurf) = NULL; -static void (*shell_hook_destroy)(struct weston_surface *surface) = NULL; -static void (*shell_hook_map)(struct weston_surface *surface, int32_t *width, - int32_t *height, int32_t *sx, int32_t *sy) = NULL; -static void (*shell_hook_configure)(struct weston_surface *surface) = NULL; -static void (*shell_hook_select)(struct weston_surface *surface) = NULL; -static char *(*shell_hook_title)(struct weston_surface *surface, const char *title) = NULL; -static void (*shell_hook_move)(struct weston_surface *surface, int *dx, int *dy) = NULL; -static void (*shell_hook_show_layer)(int layertype, int show, void *data) = NULL; -static int (*shell_hook_fullscreen)(int event, struct weston_surface *surface) = NULL; +WL_EXPORT void (*shell_hook_bind)(struct wl_client *client, void *shell) = NULL; +WL_EXPORT void (*shell_hook_unbind)(struct wl_client *client) = NULL; +WL_EXPORT void (*shell_hook_create)(int layertype, struct weston_surface *surface, + struct wl_client *client, + struct shell_surface *shsurf) = NULL; +WL_EXPORT void (*shell_hook_destroy)(struct weston_surface *surface) = NULL; +WL_EXPORT void (*shell_hook_map)(struct weston_surface *surface, int32_t *width, + int32_t *height, int32_t *sx, int32_t *sy) = NULL; +WL_EXPORT void (*shell_hook_configure)(struct weston_surface *surface) = NULL; +WL_EXPORT void (*shell_hook_select)(struct weston_surface *surface) = NULL; +WL_EXPORT char *(*shell_hook_title)(struct weston_surface *surface, + const char *title) = NULL; +WL_EXPORT void (*shell_hook_move)(struct weston_surface *surface, int *dx, int *dy) = NULL; +WL_EXPORT void (*shell_hook_show_layer)(int layertype, int show, void *data) = NULL; +WL_EXPORT int (*shell_hook_fullscreen)(int event, struct weston_surface *surface) = NULL; static bool shell_surface_is_top_fullscreen(struct shell_surface *shsurf) { + struct desktop_shell *shell; + struct weston_view *top_fs_ev; + if (shell_hook_fullscreen) { return (*shell_hook_fullscreen)(SHELL_FULLSCREEN_ISTOP, shsurf->surface); } - struct desktop_shell *shell; - struct weston_surface *top_fs_es; - shell = shell_surface_get_shell(shsurf); - uifw_debug("shell_surface_is_top_fullscreen: "); - if (wl_list_empty(&shell->fullscreen_layer.surface_list)) + if (wl_list_empty(&shell->fullscreen_layer.view_list)) return false; - top_fs_es = container_of(shell->fullscreen_layer.surface_list.next, - struct weston_surface, + top_fs_ev = container_of(shell->fullscreen_layer.view_list.next, + struct weston_view, layer_link); - return (shsurf == get_shell_surface(top_fs_es)); + return (shsurf == get_shell_surface(top_fs_ev->surface)); } static void @@ -372,6 +335,26 @@ destroy_shell_grab_shsurf(struct wl_listener *listener, void *data) grab->shsurf = NULL; } +struct weston_view * +get_default_view(struct weston_surface *surface) +{ + struct shell_surface *shsurf; + struct weston_view *view; + + if (!surface || wl_list_empty(&surface->views)) + return NULL; + + shsurf = get_shell_surface(surface); + if (shsurf) + return shsurf->view; + + wl_list_for_each(view, &surface->views, surface_link) + if (weston_view_is_mapped(view)) + return view; + + return container_of(surface->views.next, struct weston_view, surface_link); +} + static void popup_grab_end(struct weston_pointer *pointer); @@ -397,11 +380,13 @@ shell_grab_start(struct shell_grab *grab, wl_signal_add(&shsurf->destroy_signal, &grab->shsurf_destroy_listener); + shsurf->grabbed = 1; weston_pointer_start_grab(pointer, &grab->grab); if (shell->child.desktop_shell) { desktop_shell_send_grab_cursor(shell->child.desktop_shell, cursor); - weston_pointer_set_focus(pointer, shell->grab_surface, + weston_pointer_set_focus(pointer, + get_default_view(shell->grab_surface), wl_fixed_from_int(0), wl_fixed_from_int(0)); } @@ -410,8 +395,10 @@ shell_grab_start(struct shell_grab *grab, static void shell_grab_end(struct shell_grab *grab) { - if (grab->shsurf) + if (grab->shsurf) { wl_list_remove(&grab->shsurf_destroy_listener.link); + grab->shsurf->grabbed = 0; + } weston_pointer_end_grab(grab->grab.pointer); } @@ -431,23 +418,27 @@ shell_touch_grab_start(struct shell_touch_grab *grab, &grab->shsurf_destroy_listener); grab->touch = touch; + shsurf->grabbed = 1; weston_touch_start_grab(touch, &grab->grab); if (shell->child.desktop_shell) - weston_touch_set_focus(touch->seat, shell->grab_surface); + weston_touch_set_focus(touch->seat, + get_default_view(shell->grab_surface)); } static void shell_touch_grab_end(struct shell_touch_grab *grab) { - if (grab->shsurf) + if (grab->shsurf) { wl_list_remove(&grab->shsurf_destroy_listener.link); + grab->shsurf->grabbed = 0; + } weston_touch_end_grab(grab->touch); } static void -center_on_output(struct weston_surface *surface, +center_on_output(struct weston_view *view, struct weston_output *output); static enum weston_keyboard_modifier @@ -469,10 +460,15 @@ get_modifier(char *modifier) static enum animation_type get_animation_type(char *animation) { + if (!animation) + return ANIMATION_NONE; + if (!strcmp("zoom", animation)) return ANIMATION_ZOOM; else if (!strcmp("fade", animation)) return ANIMATION_FADE; + else if (!strcmp("dim-layer", animation)) + return ANIMATION_DIM_LAYER; else return ANIMATION_NONE; } @@ -494,9 +490,21 @@ shell_configuration(struct desktop_shell *shell) section = weston_config_get_section(shell->compositor->config, "shell", NULL, NULL); weston_config_section_get_string(section, + "client", &s, LIBEXECDIR "/" WESTON_SHELL_CLIENT); + shell->client = s; + weston_config_section_get_string(section, "binding-modifier", &s, "super"); shell->binding_modifier = get_modifier(s); free(s); + + weston_config_section_get_string(section, + "exposay-modifier", &s, "none"); + if (strcmp(s, "none") == 0) + shell->exposay_modifier = 0; + else + shell->exposay_modifier = get_modifier(s); + free(s); + weston_config_section_get_string(section, "animation", &s, "none"); shell->win_animation_type = get_animation_type(s); free(s); @@ -506,14 +514,15 @@ shell_configuration(struct desktop_shell *shell) free(s); if (shell->startup_animation_type == ANIMATION_ZOOM) shell->startup_animation_type = ANIMATION_NONE; - + weston_config_section_get_string(section, "focus-animation", &s, "none"); + shell->focus_animation_type = get_animation_type(s); + free(s); weston_config_section_get_uint(section, "num-workspaces", &shell->workspaces.num, DEFAULT_NUM_WORKSPACES); - /* shell program path for ico-ivi */ - weston_config_section_get_string(section, "shell-exe", &shell_exe, - LIBEXECDIR "/weston-desktop-shell"); - weston_log("ws=%d exe=%s\n", shell->workspaces.num, shell_exe); + + weston_log("workspaces=%d manager client=<%s>\n", shell->workspaces.num, + shell->client ? shell->client : "NULL"); /* get debug level for ivi debug */ section = weston_config_get_section(shell->compositor->config, "ivi-option", NULL, NULL); @@ -524,6 +533,104 @@ shell_configuration(struct desktop_shell *shell) } } +struct weston_output * +get_default_output(struct weston_compositor *compositor) +{ + /* support multi display, default fullscreen output display */ + if (default_inputpanel) { + return default_inputpanel; + } + return container_of(compositor->output_list.next, + struct weston_output, link); +} + + +/* no-op func for checking focus surface */ +static void +focus_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy) +{ +} + +static struct focus_surface * +get_focus_surface(struct weston_surface *surface) +{ + if (surface->configure == focus_surface_configure) + return surface->configure_private; + else + return NULL; +} + +static bool +is_focus_surface (struct weston_surface *es) +{ + return (es->configure == focus_surface_configure); +} + +static bool +is_focus_view (struct weston_view *view) +{ + return is_focus_surface (view->surface); +} + +static struct focus_surface * +create_focus_surface(struct weston_compositor *ec, + struct weston_output *output) +{ + struct focus_surface *fsurf = NULL; + struct weston_surface *surface = NULL; + + fsurf = malloc(sizeof *fsurf); + if (!fsurf) + return NULL; + + fsurf->surface = weston_surface_create(ec); + surface = fsurf->surface; + if (surface == NULL) { + free(fsurf); + return NULL; + } + + surface->configure = focus_surface_configure; + surface->output = output; + surface->configure_private = fsurf; + + fsurf->view = weston_view_create(surface); + if (fsurf->view == NULL) { + weston_surface_destroy(surface); + free(fsurf); + return NULL; + } + fsurf->view->output = output; + + weston_surface_set_size(surface, output->width, output->height); + weston_view_set_position(fsurf->view, output->x, output->y); + weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0); + pixman_region32_fini(&surface->opaque); + pixman_region32_init_rect(&surface->opaque, output->x, output->y, + output->width, output->height); + pixman_region32_fini(&surface->input); + pixman_region32_init(&surface->input); + + wl_list_init(&fsurf->workspace_transform.link); + + return fsurf; +} + +static void +focus_surface_destroy(struct focus_surface *fsurf) +{ + weston_surface_destroy(fsurf->surface); + free(fsurf); +} + +static void +focus_animation_done(struct weston_view_animation *animation, void *data) +{ + struct workspace *ws = data; + + ws->focus_animation = NULL; +} + static void focus_state_destroy(struct focus_state *state) { @@ -550,17 +657,19 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data) struct focus_state, surface_destroy_listener); struct desktop_shell *shell; - struct weston_surface *main_surface; - struct weston_surface *surface, *next; + struct weston_surface *main_surface, *next; + struct weston_view *view; main_surface = weston_surface_get_main_surface(state->keyboard_focus); next = NULL; - wl_list_for_each(surface, &state->ws->layer.surface_list, layer_link) { - if (surface == main_surface) + wl_list_for_each(view, &state->ws->layer.view_list, layer_link) { + if (view->surface == main_surface) + continue; + if (is_focus_view(view)) continue; - next = surface; + next = view->surface; break; } @@ -568,10 +677,21 @@ focus_state_surface_destroy(struct wl_listener *listener, void *data) if (main_surface != state->keyboard_focus) next = main_surface; + shell = state->seat->compositor->shell_interface.shell; if (next) { - shell = state->seat->compositor->shell_interface.shell; + state->keyboard_focus = NULL; activate(shell, next, state->seat); } else { + if (shell->focus_animation_type == ANIMATION_DIM_LAYER) { + if (state->ws->focus_animation) + weston_view_animation_destroy(state->ws->focus_animation); + + state->ws->focus_animation = weston_fade_run( + state->ws->fsurf_front->view, + state->ws->fsurf_front->view->alpha, 0.0, 300, + focus_animation_done, state->ws); + } + wl_list_remove(&state->link); focus_state_destroy(state); } @@ -586,6 +706,7 @@ focus_state_create(struct weston_seat *seat, struct workspace *ws) if (state == NULL) return NULL; + state->keyboard_focus = NULL; state->ws = ws; state->seat = seat; wl_list_insert(&ws->focus_list, &state->link); @@ -616,12 +737,30 @@ ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat) } static void +focus_state_set_focus(struct focus_state *state, + struct weston_surface *surface) +{ + if (state->keyboard_focus) { + wl_list_remove(&state->surface_destroy_listener.link); + wl_list_init(&state->surface_destroy_listener.link); + } + + state->keyboard_focus = surface; + if (surface) + wl_signal_add(&surface->destroy_signal, + &state->surface_destroy_listener); +} + +static void restore_focus_state(struct desktop_shell *shell, struct workspace *ws) { struct focus_state *state, *next; struct weston_surface *surface; wl_list_for_each_safe(state, next, &ws->focus_list, link) { + if (state->seat->keyboard == NULL) + continue; + surface = state->keyboard_focus; weston_keyboard_set_focus(state->seat->keyboard, surface); @@ -633,12 +772,10 @@ replace_focus_state(struct desktop_shell *shell, struct workspace *ws, struct weston_seat *seat) { struct focus_state *state; - struct weston_surface *surface; wl_list_for_each(state, &ws->focus_list, link) { if (state->seat == seat) { - surface = seat->keyboard->focus; - state->keyboard_focus = surface; + focus_state_set_focus(state, seat->keyboard->focus); return; } } @@ -652,7 +789,72 @@ drop_focus_state(struct desktop_shell *shell, struct workspace *ws, wl_list_for_each(state, &ws->focus_list, link) if (state->keyboard_focus == surface) - state->keyboard_focus = NULL; + focus_state_set_focus(state, NULL); +} + +static void +animate_focus_change(struct desktop_shell *shell, struct workspace *ws, + struct weston_view *from, struct weston_view *to) +{ + struct weston_output *output; + bool focus_surface_created = false; + + /* FIXME: Only support dim animation using two layers */ + if (from == to || shell->focus_animation_type != ANIMATION_DIM_LAYER) + return; + + output = get_default_output(shell->compositor); + if (ws->fsurf_front == NULL && (from || to)) { + ws->fsurf_front = create_focus_surface(shell->compositor, output); + if (ws->fsurf_front == NULL) + return; + ws->fsurf_front->view->alpha = 0.0; + + ws->fsurf_back = create_focus_surface(shell->compositor, output); + if (ws->fsurf_back == NULL) { + focus_surface_destroy(ws->fsurf_front); + return; + } + ws->fsurf_back->view->alpha = 0.0; + + focus_surface_created = true; + } else { + wl_list_remove(&ws->fsurf_front->view->layer_link); + wl_list_remove(&ws->fsurf_back->view->layer_link); + } + + if (ws->focus_animation) { + weston_view_animation_destroy(ws->focus_animation); + ws->focus_animation = NULL; + } + + if (to) + wl_list_insert(&to->layer_link, + &ws->fsurf_front->view->layer_link); + else if (from) + wl_list_insert(&ws->layer.view_list, + &ws->fsurf_front->view->layer_link); + + if (focus_surface_created) { + ws->focus_animation = weston_fade_run( + ws->fsurf_front->view, + ws->fsurf_front->view->alpha, 0.6, 300, + focus_animation_done, ws); + } else if (from) { + wl_list_insert(&from->layer_link, + &ws->fsurf_back->view->layer_link); + ws->focus_animation = weston_stable_fade_run( + ws->fsurf_front->view, 0.0, + ws->fsurf_back->view, 0.6, + focus_animation_done, ws); + } else if (to) { + wl_list_insert(&ws->layer.view_list, + &ws->fsurf_back->view->layer_link); + ws->focus_animation = weston_stable_fade_run( + ws->fsurf_front->view, 0.0, + ws->fsurf_back->view, 0.6, + focus_animation_done, ws); + } } static void @@ -663,6 +865,11 @@ workspace_destroy(struct workspace *ws) wl_list_for_each_safe(state, next, &ws->focus_list, link) focus_state_destroy(state); + if (ws->fsurf_front) + focus_surface_destroy(ws->fsurf_front); + if (ws->fsurf_back) + focus_surface_destroy(ws->fsurf_back); + free(ws); } @@ -692,6 +899,9 @@ workspace_create(void) wl_list_init(&ws->focus_list); wl_list_init(&ws->seat_destroyed_listener.link); ws->seat_destroyed_listener.notify = seat_destroyed; + ws->fsurf_front = NULL; + ws->fsurf_back = NULL; + ws->focus_animation = NULL; return ws; } @@ -699,7 +909,7 @@ workspace_create(void) static int workspace_is_empty(struct workspace *ws) { - return wl_list_empty(&ws->layer.surface_list); + return wl_list_empty(&ws->layer.view_list); } static struct workspace * @@ -711,7 +921,7 @@ get_workspace(struct desktop_shell *shell, unsigned int index) return *pws; } -static struct workspace * +struct workspace * get_current_workspace(struct desktop_shell *shell) { return get_workspace(shell, shell->workspaces.current); @@ -735,53 +945,59 @@ get_output_height(struct weston_output *output) } static void -surface_translate(struct weston_surface *surface, double d) +view_translate(struct workspace *ws, struct weston_view *view, double d) { - struct shell_surface *shsurf = get_shell_surface(surface); struct weston_transform *transform; - transform = &shsurf->workspace_transform; + if (is_focus_view(view)) { + struct focus_surface *fsurf = get_focus_surface(view->surface); + transform = &fsurf->workspace_transform; + } else { + struct shell_surface *shsurf = get_shell_surface(view->surface); + transform = &shsurf->workspace_transform; + } + if (wl_list_empty(&transform->link)) - wl_list_insert(surface->geometry.transformation_list.prev, - &shsurf->workspace_transform.link); + wl_list_insert(view->geometry.transformation_list.prev, + &transform->link); - weston_matrix_init(&shsurf->workspace_transform.matrix); - weston_matrix_translate(&shsurf->workspace_transform.matrix, + weston_matrix_init(&transform->matrix); + weston_matrix_translate(&transform->matrix, 0.0, d, 0.0); - weston_surface_geometry_dirty(surface); + weston_view_geometry_dirty(view); } static void workspace_translate_out(struct workspace *ws, double fraction) { - struct weston_surface *surface; + struct weston_view *view; unsigned int height; double d; - wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { - height = get_output_height(surface->output); + wl_list_for_each(view, &ws->layer.view_list, layer_link) { + height = get_output_height(view->surface->output); d = height * fraction; - surface_translate(surface, d); + view_translate(ws, view, d); } } static void workspace_translate_in(struct workspace *ws, double fraction) { - struct weston_surface *surface; + struct weston_view *view; unsigned int height; double d; - wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { - height = get_output_height(surface->output); + wl_list_for_each(view, &ws->layer.view_list, layer_link) { + height = get_output_height(view->surface->output); if (fraction > 0) d = -(height - height * fraction); else d = height + height * fraction; - surface_translate(surface, d); + view_translate(ws, view, d); } } @@ -815,16 +1031,23 @@ reverse_workspace_change_animation(struct desktop_shell *shell, static void workspace_deactivate_transforms(struct workspace *ws) { - struct weston_surface *surface; - struct shell_surface *shsurf; + struct weston_view *view; + struct weston_transform *transform; + + wl_list_for_each(view, &ws->layer.view_list, layer_link) { + if (is_focus_view(view)) { + struct focus_surface *fsurf = get_focus_surface(view->surface); + transform = &fsurf->workspace_transform; + } else { + struct shell_surface *shsurf = get_shell_surface(view->surface); + transform = &shsurf->workspace_transform; + } - wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { - shsurf = get_shell_surface(surface); - if (!wl_list_empty(&shsurf->workspace_transform.link)) { - wl_list_remove(&shsurf->workspace_transform.link); - wl_list_init(&shsurf->workspace_transform.link); + if (!wl_list_empty(&transform->link)) { + wl_list_remove(&transform->link); + wl_list_init(&transform->link); } - weston_surface_geometry_dirty(surface); + weston_view_geometry_dirty(view); } } @@ -945,12 +1168,13 @@ change_workspace(struct desktop_shell *shell, unsigned int index) { struct workspace *from; struct workspace *to; + struct focus_state *state; if (index == shell->workspaces.current) return; /* Don't change workspace when there is any fullscreen surfaces. */ - if (!wl_list_empty(&shell->fullscreen_layer.surface_list)) + if (!wl_list_empty(&shell->fullscreen_layer.view_list)) return; from = get_current_workspace(shell); @@ -971,6 +1195,18 @@ change_workspace(struct desktop_shell *shell, unsigned int index) restore_focus_state(shell, to); + if (shell->focus_animation_type != ANIMATION_NONE) { + wl_list_for_each(state, &from->focus_list, link) + if (state->keyboard_focus) + animate_focus_change(shell, from, + get_default_view(state->keyboard_focus), NULL); + + wl_list_for_each(state, &to->focus_list, link) + if (state->keyboard_focus) + animate_focus_change(shell, to, + NULL, get_default_view(state->keyboard_focus)); + } + if (workspace_is_empty(to) && workspace_is_empty(from)) update_workspace(shell, index, from, to); else @@ -982,7 +1218,7 @@ change_workspace(struct desktop_shell *shell, unsigned int index) static bool workspace_has_only(struct workspace *ws, struct weston_surface *surface) { - struct wl_list *list = &ws->layer.surface_list; + struct wl_list *list = &ws->layer.view_list; struct wl_list *e; if (wl_list_empty(list)) @@ -993,44 +1229,51 @@ workspace_has_only(struct workspace *ws, struct weston_surface *surface) if (e->next != list) return false; - return container_of(e, struct weston_surface, layer_link) == surface; + return container_of(e, struct weston_view, layer_link)->surface == surface; } static void move_surface_to_workspace(struct desktop_shell *shell, - struct weston_surface *surface, - uint32_t workspace) + struct shell_surface *shsurf, + uint32_t workspace) { struct workspace *from; struct workspace *to; struct weston_seat *seat; struct weston_surface *focus; - - assert(weston_surface_get_main_surface(surface) == surface); + struct weston_view *view; if (workspace == shell->workspaces.current) return; + view = get_default_view(shsurf->surface); + if (!view) + return; + + assert(weston_surface_get_main_surface(view->surface) == view->surface); + if (workspace >= shell->workspaces.num) workspace = shell->workspaces.num - 1; from = get_current_workspace(shell); to = get_workspace(shell, workspace); - wl_list_remove(&surface->layer_link); - wl_list_insert(&to->layer.surface_list, &surface->layer_link); + wl_list_remove(&view->layer_link); + wl_list_insert(&to->layer.view_list, &view->layer_link); - drop_focus_state(shell, from, surface); + shell_surface_update_child_surface_layers(shsurf); + + drop_focus_state(shell, from, view->surface); wl_list_for_each(seat, &shell->compositor->seat_list, link) { if (!seat->keyboard) continue; focus = weston_surface_get_main_surface(seat->keyboard->focus); - if (focus == surface) + if (focus == view->surface) weston_keyboard_set_focus(seat->keyboard, NULL); } - weston_surface_damage_below(surface); + weston_view_damage_below(view); } static void @@ -1039,21 +1282,28 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell, unsigned int index) { struct weston_surface *surface; + struct weston_view *view; struct shell_surface *shsurf; struct workspace *from; struct workspace *to; struct focus_state *state; surface = weston_surface_get_main_surface(seat->keyboard->focus); - if (surface == NULL || - index == shell->workspaces.current) + view = get_default_view(surface); + if (view == NULL || + index == shell->workspaces.current || + is_focus_view(view)) return; from = get_current_workspace(shell); to = get_workspace(shell, index); - wl_list_remove(&surface->layer_link); - wl_list_insert(&to->layer.surface_list, &surface->layer_link); + wl_list_remove(&view->layer_link); + wl_list_insert(&to->layer.view_list, &view->layer_link); + + shsurf = get_shell_surface(surface); + if (shsurf != NULL) + shell_surface_update_child_surface_layers(shsurf); replace_focus_state(shell, to, seat); drop_focus_state(shell, from, surface); @@ -1078,8 +1328,8 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell, workspace_has_only(to, surface)) update_workspace(shell, index, from, to); else { - shsurf = get_shell_surface(surface); - if (wl_list_empty(&shsurf->workspace_transform.link)) + if (shsurf != NULL && + wl_list_empty(&shsurf->workspace_transform.link)) wl_list_insert(&shell->workspaces.anim_sticky_list, &shsurf->workspace_transform.link); @@ -1090,7 +1340,7 @@ take_surface_to_workspace_by_seat(struct desktop_shell *shell, state = ensure_focus_state(shell, seat); if (state != NULL) - state->keyboard_focus = surface; + focus_state_set_focus(state, surface); } static void @@ -1103,9 +1353,14 @@ workspace_manager_move_surface(struct wl_client *client, struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct weston_surface *main_surface; + struct shell_surface *shell_surface; main_surface = weston_surface_get_main_surface(surface); - move_surface_to_workspace(shell, main_surface, workspace); + shell_surface = get_shell_surface(main_surface); + if (shell_surface == NULL) + return; + + move_surface_to_workspace(shell, shell_surface, workspace); } static const struct workspace_manager_interface workspace_manager_implementation = { @@ -1157,7 +1412,10 @@ touch_move_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id) (struct weston_touch_move_grab *) container_of( grab, struct shell_touch_grab, grab); - if (grab->touch->seat->num_tp == 0) { + if (touch_id == 0) + move->active = 0; + + if (grab->touch->num_tp == 0) { shell_touch_grab_end(&move->base); free(move); } @@ -1173,13 +1431,17 @@ touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time, int dx = wl_fixed_to_int(grab->touch->grab_x + move->dx); int dy = wl_fixed_to_int(grab->touch->grab_y + move->dy); - if (!shsurf) + if (!shsurf || !move->active) return; es = shsurf->surface; - weston_surface_configure(es, dx, dy, - es->geometry.width, es->geometry.height); + /* ico-ivi-shell hook move */ + if (shell_hook_move) { + (*shell_hook_move)(es, &dx, &dy); + } + + weston_view_set_position(shsurf->view, dx, dy); weston_compositor_schedule_repaint(es->compositor); } @@ -1210,16 +1472,19 @@ surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat) if (!shsurf) return -1; - if (shsurf->type == SHELL_SURFACE_FULLSCREEN) + if (shsurf->state.fullscreen) + return 0; + if (shsurf->grabbed) return 0; move = malloc(sizeof *move); if (!move) return -1; - move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) - + move->active = 1; + move->dx = wl_fixed_from_double(shsurf->view->geometry.x) - seat->touch->grab_x; - move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) - + move->dy = wl_fixed_from_double(shsurf->view->geometry.y) - seat->touch->grab_y; shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf, @@ -1234,28 +1499,24 @@ noop_grab_focus(struct weston_pointer_grab *grab) } static void -move_grab_motion(struct weston_pointer_grab *grab, uint32_t time) +move_grab_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) { struct weston_move_grab *move = (struct weston_move_grab *) grab; struct weston_pointer *pointer = grab->pointer; struct shell_surface *shsurf = move->base.shsurf; - struct weston_surface *es; - int dx = wl_fixed_to_int(pointer->x + move->dx); - int dy = wl_fixed_to_int(pointer->y + move->dy); + int dx, dy; + + weston_pointer_move(pointer, x, y); + dx = wl_fixed_to_int(pointer->x + move->dx); + dy = wl_fixed_to_int(pointer->y + move->dy); if (!shsurf) return; - es = shsurf->surface; - - /* ico-ivi-shell hook move */ - if (shell_hook_move) { - (*shell_hook_move)(shsurf->surface, &dx, &dy); - } - weston_surface_configure(es, dx, dy, - es->geometry.width, es->geometry.height); + weston_view_set_position(shsurf->view, dx, dy); - weston_compositor_schedule_repaint(es->compositor); + weston_compositor_schedule_repaint(shsurf->surface->compositor); } static void @@ -1299,16 +1560,18 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat) if (!shsurf) return -1; - if (shsurf->type == SHELL_SURFACE_FULLSCREEN) + if (shsurf->grabbed) + return 0; + if (shsurf->state.fullscreen || shsurf->state.maximized) return 0; move = malloc(sizeof *move); if (!move) return -1; - move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) - + move->dx = wl_fixed_from_double(shsurf->view->geometry.x) - seat->pointer->grab_x; - move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) - + move->dy = wl_fixed_from_double(shsurf->view->geometry.y) - seat->pointer->grab_y; shell_grab_start(&move->base, &move_grab_interface, shsurf, @@ -1318,29 +1581,38 @@ surface_move(struct shell_surface *shsurf, struct weston_seat *seat) } static void -shell_surface_move(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *seat_resource, uint32_t serial) +common_surface_move(struct wl_resource *resource, + struct wl_resource *seat_resource, uint32_t serial) { struct weston_seat *seat = wl_resource_get_user_data(seat_resource); struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_surface *surface; if (seat->pointer && + seat->pointer->focus && seat->pointer->button_count > 0 && seat->pointer->grab_serial == serial) { - surface = weston_surface_get_main_surface(seat->pointer->focus); + surface = weston_surface_get_main_surface(seat->pointer->focus->surface); if ((surface == shsurf->surface) && (surface_move(shsurf, seat) < 0)) wl_resource_post_no_memory(resource); } else if (seat->touch && + seat->touch->focus && seat->touch->grab_serial == serial) { - surface = weston_surface_get_main_surface(seat->touch->focus); + surface = weston_surface_get_main_surface(seat->touch->focus->surface); if ((surface == shsurf->surface) && (surface_touch_move(shsurf, seat) < 0)) wl_resource_post_no_memory(resource); } } +static void +shell_surface_move(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *seat_resource, uint32_t serial) +{ + common_surface_move(resource, seat_resource, serial); +} + struct weston_resize_grab { struct shell_grab base; uint32_t edges; @@ -1348,7 +1620,8 @@ struct weston_resize_grab { }; static void -resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time) +resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) { struct weston_resize_grab *resize = (struct weston_resize_grab *) grab; struct weston_pointer *pointer = grab->pointer; @@ -1357,14 +1630,16 @@ resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time) wl_fixed_t from_x, from_y; wl_fixed_t to_x, to_y; + weston_pointer_move(pointer, x, y); + if (!shsurf) return; - weston_surface_from_global_fixed(shsurf->surface, - pointer->grab_x, pointer->grab_y, - &from_x, &from_y); - weston_surface_from_global_fixed(shsurf->surface, - pointer->x, pointer->y, &to_x, &to_y); + weston_view_from_global_fixed(shsurf->view, + pointer->grab_x, pointer->grab_y, + &from_x, &from_y); + weston_view_from_global_fixed(shsurf->view, + pointer->x, pointer->y, &to_x, &to_y); width = resize->width; if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) { @@ -1380,8 +1655,6 @@ resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time) height += wl_fixed_to_int(to_y - from_y); } - uifw_debug("resize_grab_motion: send configure %08x %x w/h=%d/%d", - (int)shsurf->surface, resize->edges, width, height); shsurf->client->send_configure(shsurf->surface, resize->edges, width, height); } @@ -1392,8 +1665,11 @@ send_configure(struct weston_surface *surface, { struct shell_surface *shsurf = get_shell_surface(surface); + assert(shsurf); + uifw_trace("send_configure: send %08x %x w/h=%d/%d", (int)shsurf->surface, edges, width, height); + wl_shell_surface_send_configure(shsurf->resource, edges, width, height); } @@ -1444,15 +1720,15 @@ surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x, struct weston_subsurface *subsurface; pixman_region32_init_rect(®ion, 0, 0, - surface->geometry.width, - surface->geometry.height); + surface->width, + surface->height); wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) { pixman_region32_union_rect(®ion, ®ion, subsurface->position.x, subsurface->position.y, - subsurface->surface->geometry.width, - subsurface->surface->geometry.height); + subsurface->surface->width, + subsurface->surface->height); } box = pixman_region32_extents(®ion); @@ -1474,8 +1750,7 @@ surface_resize(struct shell_surface *shsurf, { struct weston_resize_grab *resize; - if (shsurf->type == SHELL_SURFACE_FULLSCREEN || - shsurf->type == SHELL_SURFACE_MAXIMIZED) + if (shsurf->state.fullscreen || shsurf->state.maximized) return 0; if (edges == 0 || edges > 15 || @@ -1497,28 +1772,39 @@ surface_resize(struct shell_surface *shsurf, } static void -shell_surface_resize(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *seat_resource, uint32_t serial, - uint32_t edges) +common_surface_resize(struct wl_resource *resource, + struct wl_resource *seat_resource, uint32_t serial, + uint32_t edges) { struct weston_seat *seat = wl_resource_get_user_data(seat_resource); struct shell_surface *shsurf = wl_resource_get_user_data(resource); struct weston_surface *surface; - if (shsurf->type == SHELL_SURFACE_FULLSCREEN) + if (shsurf->state.fullscreen) return; - surface = weston_surface_get_main_surface(seat->pointer->focus); if (seat->pointer->button_count == 0 || seat->pointer->grab_serial != serial || - surface != shsurf->surface) + seat->pointer->focus == NULL) return; - if (surface_resize(shsurf, seat, edges) < 0) + surface = weston_surface_get_main_surface(seat->pointer->focus->surface); + if (surface != shsurf->surface) + return; + + if (surface_resize(shsurf, seat, edges) < 0) wl_resource_post_no_memory(resource); } static void +shell_surface_resize(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *seat_resource, uint32_t serial, + uint32_t edges) +{ + common_surface_resize(resource, seat_resource, serial, edges); +} + +static void end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer); static void @@ -1526,20 +1812,22 @@ busy_cursor_grab_focus(struct weston_pointer_grab *base) { struct shell_grab *grab = (struct shell_grab *) base; struct weston_pointer *pointer = base->pointer; - struct weston_surface *surface; + struct weston_view *view; wl_fixed_t sx, sy; - surface = weston_compositor_pick_surface(pointer->seat->compositor, - pointer->x, pointer->y, - &sx, &sy); + view = weston_compositor_pick_view(pointer->seat->compositor, + pointer->x, pointer->y, + &sx, &sy); - if (!grab->shsurf || grab->shsurf->surface != surface) + if (!grab->shsurf || grab->shsurf->surface != view->surface) end_busy_cursor(grab->shsurf, pointer); } static void -busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time) +busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) { + weston_pointer_move(grab->pointer, x, y); } static void @@ -1623,7 +1911,8 @@ ping_timeout_handler(void *data) shsurf->unresponsive = 1; wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link) - if (seat->pointer->focus == shsurf->surface) + if (seat->pointer && seat->pointer->focus && + seat->pointer->focus->surface == shsurf->surface) set_busy_cursor(shsurf, seat->pointer); return 1; @@ -1655,7 +1944,12 @@ ping_handler(struct weston_surface *surface, uint32_t serial) wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf); wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout); - wl_shell_surface_send_ping(shsurf->resource, serial); + if (shell_surface_is_wl_shell_surface(shsurf)) + wl_shell_surface_send_ping(shsurf->resource, serial); + else if (shell_surface_is_xdg_surface(shsurf)) + xdg_surface_send_ping(shsurf->resource, serial); + else if (shell_surface_is_xdg_popup(shsurf)) + xdg_popup_send_ping(shsurf->resource, serial); } } @@ -1663,22 +1957,22 @@ static void handle_pointer_focus(struct wl_listener *listener, void *data) { struct weston_pointer *pointer = data; - struct weston_surface *surface = pointer->focus; + struct weston_view *view = pointer->focus; struct weston_compositor *compositor; struct shell_surface *shsurf; uint32_t serial; - if (!surface) + if (!view) return; - compositor = surface->compositor; - shsurf = get_shell_surface(surface); + compositor = view->surface->compositor; + shsurf = get_shell_surface(view->surface); if (shsurf && shsurf->unresponsive) { set_busy_cursor(shsurf, pointer); } else { serial = wl_display_next_serial(compositor->wl_display); - ping_handler(surface, serial); + ping_handler(view->surface, serial); } } @@ -1696,12 +1990,26 @@ create_pointer_focus_listener(struct weston_seat *seat) } static void -shell_surface_pong(struct wl_client *client, struct wl_resource *resource, - uint32_t serial) +xdg_surface_set_transient_for(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *parent_resource) { struct shell_surface *shsurf = wl_resource_get_user_data(resource); - struct weston_seat *seat; + struct weston_surface *parent; + + if (parent_resource) + parent = wl_resource_get_user_data(parent_resource); + else + parent = NULL; + + shell_surface_set_parent(shsurf, parent); +} + +static void +surface_pong(struct shell_surface *shsurf, uint32_t serial) +{ struct weston_compositor *ec = shsurf->surface->compositor; + struct weston_seat *seat; if (shsurf->ping_timer == NULL) /* Just ignore unsolicited pong. */ @@ -1718,6 +2026,16 @@ shell_surface_pong(struct wl_client *client, struct wl_resource *resource, } static void +shell_surface_pong(struct wl_client *client, struct wl_resource *resource, + uint32_t serial) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + surface_pong(shsurf, serial); + +} + +static void set_title(struct shell_surface *shsurf, const char *title) { char *p; @@ -1755,17 +2073,6 @@ shell_surface_set_class(struct wl_client *client, shsurf->class = strdup(class); } -static struct weston_output * -get_default_output(struct weston_compositor *compositor) -{ - /* support multi display, default fullscreen output display */ - if (default_inputpanel) { - return default_inputpanel; - } - return container_of(compositor->output_list.next, - struct weston_output, link); -} - static void restore_output_mode(struct weston_output *output) { @@ -1786,139 +2093,172 @@ restore_all_output_modes(struct weston_compositor *compositor) restore_output_mode(output); } -static void -shell_unset_fullscreen(struct shell_surface *shsurf) +static int +get_output_panel_height(struct desktop_shell *shell, + struct weston_output *output) { - struct workspace *ws; + struct weston_view *view; + int panel_height = 0; - uifw_debug("shell_unset_fullscreen: "); + if (!output) + return 0; - /* undo all fullscreen things here */ - if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER && - shell_surface_is_top_fullscreen(shsurf)) { - restore_output_mode(shsurf->fullscreen_output); - } - shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; - shsurf->fullscreen.framerate = 0; - wl_list_remove(&shsurf->fullscreen.transform.link); - wl_list_init(&shsurf->fullscreen.transform.link); - if (shsurf->fullscreen.black_surface) - weston_surface_destroy(shsurf->fullscreen.black_surface); - shsurf->fullscreen.black_surface = NULL; - shsurf->fullscreen_output = NULL; - weston_surface_set_position(shsurf->surface, - shsurf->saved_x, shsurf->saved_y); - if (shsurf->saved_rotation_valid) { - wl_list_insert(&shsurf->surface->geometry.transformation_list, - &shsurf->rotation.transform.link); - shsurf->saved_rotation_valid = false; + wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) { + if (view->surface->output == output) { + panel_height = view->surface->height; + break; + } } - ws = get_current_workspace(shsurf->shell); - wl_list_remove(&shsurf->surface->layer_link); - wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link); + return panel_height; } -static void -shell_unset_maximized(struct shell_surface *shsurf) +/* The surface will be inserted into the list immediately after the link + * returned by this function (i.e. will be stacked immediately above the + * returned link). */ +static struct wl_list * +shell_surface_calculate_layer_link (struct shell_surface *shsurf) { struct workspace *ws; + struct weston_view *parent; - uifw_debug("shell_unset_maximized: "); + switch (shsurf->type) { + case SHELL_SURFACE_POPUP: + case SHELL_SURFACE_TOPLEVEL: + if (shsurf->state.fullscreen) { + return &shsurf->shell->fullscreen_layer.view_list; + } else if (shsurf->parent) { + /* Move the surface to its parent layer so + * that surfaces which are transient for + * fullscreen surfaces don't get hidden by the + * fullscreen surfaces. */ + + /* TODO: Handle a parent with multiple views */ + parent = get_default_view(shsurf->parent); + if (parent) + return parent->layer_link.prev; + } + break; - /* undo all maximized things here */ - shsurf->output = get_default_output(shsurf->surface->compositor); - weston_surface_set_position(shsurf->surface, - shsurf->saved_x, - shsurf->saved_y); + case SHELL_SURFACE_XWAYLAND: + return &shsurf->shell->fullscreen_layer.view_list; - if (shsurf->saved_rotation_valid) { - wl_list_insert(&shsurf->surface->geometry.transformation_list, - &shsurf->rotation.transform.link); - shsurf->saved_rotation_valid = false; + case SHELL_SURFACE_NONE: + default: + /* Go to the fallback, below. */ + break; } + /* Move the surface to a normal workspace layer so that surfaces + * which were previously fullscreen or transient are no longer + * rendered on top. */ ws = get_current_workspace(shsurf->shell); - wl_list_remove(&shsurf->surface->layer_link); - wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link); + return &ws->layer.view_list; } -static int -reset_shell_surface_type(struct shell_surface *surface) +static void +shell_surface_update_child_surface_layers (struct shell_surface *shsurf) { - switch (surface->type) { - case SHELL_SURFACE_FULLSCREEN: - shell_unset_fullscreen(surface); - break; - case SHELL_SURFACE_MAXIMIZED: - shell_unset_maximized(surface); - break; - case SHELL_SURFACE_NONE: - case SHELL_SURFACE_TOPLEVEL: - case SHELL_SURFACE_TRANSIENT: - case SHELL_SURFACE_POPUP: - case SHELL_SURFACE_XWAYLAND: - break; - } + struct shell_surface *child; - surface->type = SHELL_SURFACE_NONE; - return 0; + /* Move the child layers to the same workspace as shsurf. They will be + * stacked above shsurf. */ + wl_list_for_each_reverse(child, &shsurf->children_list, children_link) { + if (shsurf->view->layer_link.prev != &child->view->layer_link) { + weston_view_geometry_dirty(child->view); + wl_list_remove(&child->view->layer_link); + wl_list_insert(shsurf->view->layer_link.prev, + &child->view->layer_link); + weston_view_geometry_dirty(child->view); + weston_surface_damage(child->surface); + + /* Recurse. We don’t expect this to recurse very far (if + * at all) because that would imply we have transient + * (or popup) children of transient surfaces, which + * would be unusual. */ + shell_surface_update_child_surface_layers(child); + } + } } +/* Update the surface’s layer. Mark both the old and new views as having dirty + * geometry to ensure the changes are redrawn. + * + * If any child surfaces exist and are mapped, ensure they’re in the same layer + * as this surface. */ static void -set_surface_type(struct shell_surface *shsurf) +shell_surface_update_layer(struct shell_surface *shsurf) { - struct weston_surface *surface = shsurf->surface; - struct weston_surface *pes = shsurf->parent; + struct wl_list *new_layer_link; - reset_shell_surface_type(shsurf); + new_layer_link = shell_surface_calculate_layer_link(shsurf); - shsurf->type = shsurf->next_type; - shsurf->next_type = SHELL_SURFACE_NONE; + if (new_layer_link == &shsurf->view->layer_link) + return; - switch (shsurf->type) { - case SHELL_SURFACE_TOPLEVEL: - break; - case SHELL_SURFACE_TRANSIENT: - weston_surface_set_position(surface, - pes->geometry.x + shsurf->transient.x, - pes->geometry.y + shsurf->transient.y); - break; + weston_view_geometry_dirty(shsurf->view); + wl_list_remove(&shsurf->view->layer_link); + wl_list_insert(new_layer_link, &shsurf->view->layer_link); + weston_view_geometry_dirty(shsurf->view); + weston_surface_damage(shsurf->surface); - case SHELL_SURFACE_MAXIMIZED: - case SHELL_SURFACE_FULLSCREEN: - shsurf->saved_x = surface->geometry.x; - shsurf->saved_y = surface->geometry.y; - shsurf->saved_position_valid = true; - - if (!wl_list_empty(&shsurf->rotation.transform.link)) { - wl_list_remove(&shsurf->rotation.transform.link); - wl_list_init(&shsurf->rotation.transform.link); - weston_surface_geometry_dirty(shsurf->surface); - shsurf->saved_rotation_valid = true; - } - if (shsurf->type == SHELL_SURFACE_FULLSCREEN) { - uifw_debug("set_surface_type: set fullscreen"); - if (shell_hook_fullscreen) { - (*shell_hook_fullscreen)(SHELL_FULLSCREEN_SET, surface); - } - } - break; + shell_surface_update_child_surface_layers(shsurf); +} - case SHELL_SURFACE_XWAYLAND: - weston_surface_set_position(surface, shsurf->transient.x, - shsurf->transient.y); - break; +static void +shell_surface_set_parent(struct shell_surface *shsurf, + struct weston_surface *parent) +{ + shsurf->parent = parent; - default: - break; + wl_list_remove(&shsurf->children_link); + wl_list_init(&shsurf->children_link); + + /* Insert into the parent surface’s child list. */ + if (parent != NULL) { + struct shell_surface *parent_shsurf = get_shell_surface(parent); + if (parent_shsurf != NULL) + wl_list_insert(&parent_shsurf->children_list, + &shsurf->children_link); } } static void +shell_surface_set_output(struct shell_surface *shsurf, + struct weston_output *output) +{ + struct weston_surface *es = shsurf->surface; + + /* get the default output, if the client set it as NULL + check whether the ouput is available */ + if (output) + shsurf->output = output; + else if (es->output) + shsurf->output = es->output; + else + shsurf->output = get_default_output(es->compositor); +} + +static void +surface_clear_next_states(struct shell_surface *shsurf) +{ + shsurf->next_state.maximized = false; + shsurf->next_state.fullscreen = false; + + if ((shsurf->next_state.maximized != shsurf->state.maximized) || + (shsurf->next_state.fullscreen != shsurf->state.fullscreen)) + shsurf->state_changed = true; +} + +static void set_toplevel(struct shell_surface *shsurf) { - shsurf->next_type = SHELL_SURFACE_TOPLEVEL; + shell_surface_set_parent(shsurf, NULL); + surface_clear_next_states(shsurf); + shsurf->type = SHELL_SURFACE_TOPLEVEL; + + /* The layer_link is updated in set_surface_type(), + * called from configure. */ } static void @@ -1934,12 +2274,22 @@ static void set_transient(struct shell_surface *shsurf, struct weston_surface *parent, int x, int y, uint32_t flags) { - /* assign to parents output */ - shsurf->parent = parent; + assert(parent != NULL); + + shell_surface_set_parent(shsurf, parent); + + surface_clear_next_states(shsurf); + shsurf->transient.x = x; shsurf->transient.y = y; shsurf->transient.flags = flags; - shsurf->next_type = SHELL_SURFACE_TRANSIENT; + + shsurf->next_state.relative = true; + shsurf->state_changed = true; + shsurf->type = SHELL_SURFACE_TOPLEVEL; + + /* The layer_link is updated in set_surface_type(), + * called from configure. */ } static void @@ -1955,144 +2305,369 @@ shell_surface_set_transient(struct wl_client *client, set_transient(shsurf, parent, x, y, flags); } -static struct desktop_shell * -shell_surface_get_shell(struct shell_surface *shsurf) +static void +set_fullscreen(struct shell_surface *shsurf, + uint32_t method, + uint32_t framerate, + struct weston_output *output) { - return shsurf->shell; -} + shell_surface_set_output(shsurf, output); -static int -get_output_panel_height(struct desktop_shell *shell, - struct weston_output *output) -{ - struct weston_surface *surface; - int panel_height = 0; + shsurf->fullscreen_output = shsurf->output; + shsurf->fullscreen.type = method; + shsurf->fullscreen.framerate = framerate; - if (!output) - return 0; + shsurf->next_state.fullscreen = true; + shsurf->state_changed = true; + shsurf->type = SHELL_SURFACE_TOPLEVEL; - wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) { - if (surface->output == output) { - panel_height = surface->geometry.height; - break; - } + if (shell_hook_fullscreen) { + (*shell_hook_fullscreen)(SHELL_FULLSCREEN_SET, shsurf->surface); + return; } - return panel_height; + shsurf->client->send_configure(shsurf->surface, 0, + shsurf->output->width, + shsurf->output->height); + + /* The layer_link is updated in set_surface_type(), + * called from configure. */ } static void -shell_surface_set_maximized(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output_resource ) -{ - struct shell_surface *shsurf = wl_resource_get_user_data(resource); - struct weston_surface *es = shsurf->surface; - struct desktop_shell *shell = NULL; - uint32_t edges = 0, panel_height = 0; +weston_view_set_initial_position(struct weston_view *view, + struct desktop_shell *shell); - /* get the default output, if the client set it as NULL - check whether the ouput is available */ - if (output_resource) - shsurf->output = wl_resource_get_user_data(output_resource); - else if (es->output) - shsurf->output = es->output; - else { - shsurf->output = get_default_output(es->compositor); +static void +unset_fullscreen(struct shell_surface *shsurf) +{ + /* Unset the fullscreen output, driver configuration and transforms. */ + if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER && + shell_surface_is_top_fullscreen(shsurf)) { + restore_output_mode(shsurf->fullscreen_output); } - shell = shell_surface_get_shell(shsurf); - panel_height = get_output_panel_height(shell, shsurf->output); - edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT; + shsurf->fullscreen_output = NULL; - uifw_debug("shell_surface_set_maximized: send %08x %x w/h=%d/%d", - (int)shsurf->surface, edges, shsurf->output->width, - shsurf->output->height - panel_height); - shsurf->client->send_configure(shsurf->surface, edges, - shsurf->output->width, - shsurf->output->height - panel_height); + shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; + shsurf->fullscreen.framerate = 0; - shsurf->next_type = SHELL_SURFACE_MAXIMIZED; -} + if (shell_hook_fullscreen) { + (*shell_hook_fullscreen)(SHELL_FULLSCREEN_UNSET, shsurf->surface); + } -static void -black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height); + wl_list_remove(&shsurf->fullscreen.transform.link); + wl_list_init(&shsurf->fullscreen.transform.link); -static struct weston_surface * -create_black_surface(struct weston_compositor *ec, - struct weston_surface *fs_surface, - float x, float y, int w, int h) -{ - struct weston_surface *surface = NULL; + if (shsurf->fullscreen.black_view) + weston_surface_destroy(shsurf->fullscreen.black_view->surface); + shsurf->fullscreen.black_view = NULL; - uifw_debug("create_black_surface: fullscreen"); - surface = weston_surface_create(ec); - if (surface == NULL) { - weston_log("no memory\n"); - return NULL; - } + if (shsurf->saved_position_valid) + weston_view_set_position(shsurf->view, + shsurf->saved_x, shsurf->saved_y); + else + weston_view_set_initial_position(shsurf->view, shsurf->shell); - surface->configure = black_surface_configure; - surface->configure_private = fs_surface; - uifw_debug("create_black_surface: configure %08x x/y=%d/%d w/h=%d/%d", - (int)surface, (int)x, (int)y, w, h); - weston_surface_configure(surface, x, y, w, h); - weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); - pixman_region32_fini(&surface->opaque); - pixman_region32_init_rect(&surface->opaque, 0, 0, w, h); - pixman_region32_fini(&surface->input); - pixman_region32_init_rect(&surface->input, 0, 0, w, h); + if (shsurf->saved_rotation_valid) { + wl_list_insert(&shsurf->view->geometry.transformation_list, + &shsurf->rotation.transform.link); + shsurf->saved_rotation_valid = false; + } - return surface; + /* Layer is updated in set_surface_type(). */ } -/* Create black surface and append it to the associated fullscreen surface. - * Handle size dismatch and positioning according to the method. */ static void -shell_configure_fullscreen(struct shell_surface *shsurf) +shell_surface_set_fullscreen(struct wl_client *client, + struct wl_resource *resource, + uint32_t method, + uint32_t framerate, + struct wl_resource *output_resource) { - uifw_debug("shell_configure_fullscreen: "); + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + struct weston_output *output; - if (shell_hook_fullscreen) { - (*shell_hook_fullscreen)(SHELL_FULLSCREEN_CONF, shsurf->surface); - return; - } + if (output_resource) + output = wl_resource_get_user_data(output_resource); + else + output = NULL; - struct weston_output *output = shsurf->fullscreen_output; - struct weston_surface *surface = shsurf->surface; - struct weston_matrix *matrix; - float scale, output_aspect, surface_aspect, x, y; - int32_t surf_x, surf_y, surf_width, surf_height; + shell_surface_set_parent(shsurf, NULL); - if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER) - restore_output_mode(output); + surface_clear_next_states(shsurf); + set_fullscreen(shsurf, method, framerate, output); +} - if (!shsurf->fullscreen.black_surface) - shsurf->fullscreen.black_surface = - create_black_surface(surface->compositor, - surface, - output->x, output->y, - output->width, - output->height); +static void +set_popup(struct shell_surface *shsurf, + struct weston_surface *parent, + struct weston_seat *seat, + uint32_t serial, + int32_t x, + int32_t y) +{ + assert(parent != NULL); - wl_list_remove(&shsurf->fullscreen.black_surface->layer_link); - wl_list_insert(&surface->layer_link, - &shsurf->fullscreen.black_surface->layer_link); - shsurf->fullscreen.black_surface->output = output; + shsurf->popup.shseat = get_shell_seat(seat); + shsurf->popup.serial = serial; + shsurf->popup.x = x; + shsurf->popup.y = y; - surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y, + shsurf->type = SHELL_SURFACE_POPUP; +} + +static void +shell_surface_set_popup(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *seat_resource, + uint32_t serial, + struct wl_resource *parent_resource, + int32_t x, int32_t y, uint32_t flags) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + struct weston_surface *parent = + wl_resource_get_user_data(parent_resource); + + shell_surface_set_parent(shsurf, parent); + + surface_clear_next_states(shsurf); + set_popup(shsurf, + parent, + wl_resource_get_user_data(seat_resource), + serial, x, y); +} + +static void +set_maximized(struct shell_surface *shsurf, + struct weston_output *output) +{ + struct desktop_shell *shell; + uint32_t edges = 0, panel_height = 0; + + shell_surface_set_output(shsurf, output); + + shell = shell_surface_get_shell(shsurf); + panel_height = get_output_panel_height(shell, shsurf->output); + edges = WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_LEFT; + + shsurf->client->send_configure(shsurf->surface, edges, + shsurf->output->width, + shsurf->output->height - panel_height); + + shsurf->next_state.maximized = true; + shsurf->state_changed = true; + shsurf->type = SHELL_SURFACE_TOPLEVEL; +} + +static void +unset_maximized(struct shell_surface *shsurf) +{ + /* undo all maximized things here */ + shsurf->output = get_default_output(shsurf->surface->compositor); + + if (shsurf->saved_position_valid) + weston_view_set_position(shsurf->view, + shsurf->saved_x, shsurf->saved_y); + else + weston_view_set_initial_position(shsurf->view, shsurf->shell); + + if (shsurf->saved_rotation_valid) { + wl_list_insert(&shsurf->view->geometry.transformation_list, + &shsurf->rotation.transform.link); + shsurf->saved_rotation_valid = false; + } + + /* Layer is updated in set_surface_type(). */ +} + +static void +shell_surface_set_maximized(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *output_resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + struct weston_output *output; + + if (output_resource) + output = wl_resource_get_user_data(output_resource); + else + output = NULL; + + shell_surface_set_parent(shsurf, NULL); + + surface_clear_next_states(shsurf); + set_maximized(shsurf, output); +} + +/* This is only ever called from set_surface_type(), so there’s no need to + * update layer_links here, since they’ll be updated when we return. */ +static int +reset_surface_type(struct shell_surface *surface) +{ + if (surface->state.fullscreen) + unset_fullscreen(surface); + if (surface->state.maximized) + unset_maximized(surface); + + return 0; +} + +static void +set_full_output(struct shell_surface *shsurf) +{ + shsurf->saved_x = shsurf->view->geometry.x; + shsurf->saved_y = shsurf->view->geometry.y; + shsurf->saved_width = shsurf->surface->width; + shsurf->saved_height = shsurf->surface->height; + shsurf->saved_size_valid = true; + shsurf->saved_position_valid = true; + + if (!wl_list_empty(&shsurf->rotation.transform.link)) { + wl_list_remove(&shsurf->rotation.transform.link); + wl_list_init(&shsurf->rotation.transform.link); + weston_view_geometry_dirty(shsurf->view); + shsurf->saved_rotation_valid = true; + } +} + +static void +set_surface_type(struct shell_surface *shsurf) +{ + struct weston_surface *pes = shsurf->parent; + struct weston_view *pev = get_default_view(pes); + + reset_surface_type(shsurf); + + shsurf->state = shsurf->next_state; + shsurf->state_changed = false; + + switch (shsurf->type) { + case SHELL_SURFACE_TOPLEVEL: + if (shsurf->state.maximized || shsurf->state.fullscreen) { + set_full_output(shsurf); + } else if (shsurf->state.relative && pev) { + weston_view_set_position(shsurf->view, + pev->geometry.x + shsurf->transient.x, + pev->geometry.y + shsurf->transient.y); + } + break; + + case SHELL_SURFACE_XWAYLAND: + weston_view_set_position(shsurf->view, shsurf->transient.x, + shsurf->transient.y); + break; + + case SHELL_SURFACE_POPUP: + case SHELL_SURFACE_NONE: + default: + break; + } + + /* Update the surface’s layer. */ + shell_surface_update_layer(shsurf); +} + +static struct desktop_shell * +shell_surface_get_shell(struct shell_surface *shsurf) +{ + return shsurf->shell; +} + +static void +black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy); + +static struct weston_view * +create_black_surface(struct weston_compositor *ec, + struct weston_surface *fs_surface, + float x, float y, int w, int h) +{ + struct weston_surface *surface = NULL; + struct weston_view *view; + + surface = weston_surface_create(ec); + if (surface == NULL) { + weston_log("no memory\n"); + return NULL; + } + view = weston_view_create(surface); + if (surface == NULL) { + weston_log("no memory\n"); + weston_surface_destroy(surface); + return NULL; + } + + surface->configure = black_surface_configure; + surface->configure_private = fs_surface; + weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); + pixman_region32_fini(&surface->opaque); + pixman_region32_init_rect(&surface->opaque, 0, 0, w, h); + pixman_region32_fini(&surface->input); + pixman_region32_init_rect(&surface->input, 0, 0, w, h); + + weston_surface_set_size(surface, w, h); + weston_view_set_position(view, x, y); + + return view; +} + +static void +shell_ensure_fullscreen_black_view(struct shell_surface *shsurf) +{ + struct weston_output *output = shsurf->fullscreen_output; + + assert(shsurf->state.fullscreen); + + if (!shsurf->fullscreen.black_view) + shsurf->fullscreen.black_view = + create_black_surface(shsurf->surface->compositor, + shsurf->surface, + output->x, output->y, + output->width, + output->height); + + weston_view_geometry_dirty(shsurf->fullscreen.black_view); + wl_list_remove(&shsurf->fullscreen.black_view->layer_link); + wl_list_insert(&shsurf->view->layer_link, + &shsurf->fullscreen.black_view->layer_link); + weston_view_geometry_dirty(shsurf->fullscreen.black_view); + weston_surface_damage(shsurf->surface); +} + +/* Create black surface and append it to the associated fullscreen surface. + * Handle size dismatch and positioning according to the method. */ +static void +shell_configure_fullscreen(struct shell_surface *shsurf) +{ + struct weston_output *output = shsurf->fullscreen_output; + struct weston_surface *surface = shsurf->surface; + struct weston_matrix *matrix; + float scale, output_aspect, surface_aspect, x, y; + int32_t surf_x, surf_y, surf_width, surf_height; + + if (shell_hook_fullscreen) { + (*shell_hook_fullscreen)(SHELL_FULLSCREEN_CONF, shsurf->surface); + } + + if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER) + restore_output_mode(output); + + shell_ensure_fullscreen_black_view(shsurf); + + surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y, &surf_width, &surf_height); switch (shsurf->fullscreen.type) { case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT: if (surface->buffer_ref.buffer) - center_on_output(surface, shsurf->fullscreen_output); + center_on_output(shsurf->view, shsurf->fullscreen_output); break; case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE: /* 1:1 mapping between surface and output dimensions */ if (output->width == surf_width && output->height == surf_height) { - weston_surface_set_position(surface, output->x - surf_x, - output->y - surf_y); + weston_view_set_position(shsurf->view, + output->x - surf_x, + output->y - surf_y); break; } @@ -2101,8 +2676,9 @@ shell_configure_fullscreen(struct shell_surface *shsurf) output_aspect = (float) output->width / (float) output->height; - surface_aspect = (float) surface->geometry.width / - (float) surface->geometry.height; + /* XXX: Use surf_width and surf_height here? */ + surface_aspect = (float) surface->width / + (float) surface->height; if (output_aspect < surface_aspect) scale = (float) output->width / (float) surf_width; @@ -2112,145 +2688,64 @@ shell_configure_fullscreen(struct shell_surface *shsurf) weston_matrix_scale(matrix, scale, scale, 1); wl_list_remove(&shsurf->fullscreen.transform.link); - wl_list_insert(&surface->geometry.transformation_list, + wl_list_insert(&shsurf->view->geometry.transformation_list, &shsurf->fullscreen.transform.link); x = output->x + (output->width - surf_width * scale) / 2 - surf_x; y = output->y + (output->height - surf_height * scale) / 2 - surf_y; - weston_surface_set_position(surface, x, y); + weston_view_set_position(shsurf->view, x, y); break; case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER: if (shell_surface_is_top_fullscreen(shsurf)) { struct weston_mode mode = {0, - surf_width * surface->buffer_scale, - surf_height * surface->buffer_scale, + surf_width * surface->buffer_viewport.scale, + surf_height * surface->buffer_viewport.scale, shsurf->fullscreen.framerate}; - if (weston_output_switch_mode(output, &mode, surface->buffer_scale, + if (weston_output_switch_mode(output, &mode, surface->buffer_viewport.scale, WESTON_MODE_SWITCH_SET_TEMPORARY) == 0) { - weston_surface_set_position(surface, - output->x - surf_x, - output->y - surf_y); - uifw_debug("shell_configure_fullscreen: configure %08x x/y=%d/%d w/h=%d/%d", - (int)shsurf->fullscreen.black_surface, (int)(output->x - surf_x), - (int)(output->y - surf_y), output->width, output->height); - weston_surface_configure(shsurf->fullscreen.black_surface, - output->x - surf_x, - output->y - surf_y, - output->width, - output->height); + weston_view_set_position(shsurf->view, + output->x - surf_x, + output->y - surf_y); + shsurf->fullscreen.black_view->surface->width = output->width; + shsurf->fullscreen.black_view->surface->height = output->height; + weston_view_set_position(shsurf->fullscreen.black_view, + output->x - surf_x, + output->y - surf_y); break; } else { restore_output_mode(output); - center_on_output(surface, output); + center_on_output(shsurf->view, output); } } break; case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL: - center_on_output(surface, output); + center_on_output(shsurf->view, output); break; default: break; } } -/* make the fullscreen and black surface at the top */ -static void -shell_stack_fullscreen(struct shell_surface *shsurf) -{ - uifw_debug("shell_stack_fullscreen: "); - - if (shell_hook_fullscreen) { - (*shell_hook_fullscreen)(SHELL_FULLSCREEN_STACK, shsurf->surface); - return; - } - - struct weston_output *output = shsurf->fullscreen_output; - struct weston_surface *surface = shsurf->surface; - struct desktop_shell *shell = shell_surface_get_shell(shsurf); - - wl_list_remove(&surface->layer_link); - wl_list_insert(&shell->fullscreen_layer.surface_list, - &surface->layer_link); - weston_surface_damage(surface); - - if (!shsurf->fullscreen.black_surface) - shsurf->fullscreen.black_surface = - create_black_surface(surface->compositor, - surface, - output->x, output->y, - output->width, - output->height); - - wl_list_remove(&shsurf->fullscreen.black_surface->layer_link); - wl_list_insert(&surface->layer_link, - &shsurf->fullscreen.black_surface->layer_link); - weston_surface_damage(shsurf->fullscreen.black_surface); -} - static void shell_map_fullscreen(struct shell_surface *shsurf) { - uifw_debug("shell_map_fullscreen: "); - shell_stack_fullscreen(shsurf); shell_configure_fullscreen(shsurf); } static void -set_fullscreen(struct shell_surface *shsurf, - uint32_t method, - uint32_t framerate, - struct weston_output *output) -{ - struct weston_surface *es = shsurf->surface; - - uifw_debug("set_fullscreen: "); - - if (output) - shsurf->output = output; - else if (es->output) - shsurf->output = es->output; - else { - shsurf->output = get_default_output(es->compositor); - } - shsurf->fullscreen_output = shsurf->output; - shsurf->fullscreen.type = method; - shsurf->fullscreen.framerate = framerate; - shsurf->next_type = SHELL_SURFACE_FULLSCREEN; - - shsurf->client->send_configure(shsurf->surface, 0, - shsurf->output->width, - shsurf->output->height); -} - -static void -shell_surface_set_fullscreen(struct wl_client *client, - struct wl_resource *resource, - uint32_t method, - uint32_t framerate, - struct wl_resource *output_resource) -{ - struct shell_surface *shsurf = wl_resource_get_user_data(resource); - struct weston_output *output; - - uifw_debug("shell_surface_set_fullscreen: "); - - if (output_resource) - output = wl_resource_get_user_data(output_resource); - else - output = NULL; - - set_fullscreen(shsurf, method, framerate, output); -} - -static void set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags) { /* XXX: using the same fields for transient type */ + surface_clear_next_states(shsurf); shsurf->transient.x = x; shsurf->transient.y = y; shsurf->transient.flags = flags; - shsurf->next_type = SHELL_SURFACE_XWAYLAND; + + shell_surface_set_parent(shsurf, NULL); + + shsurf->type = SHELL_SURFACE_XWAYLAND; + shsurf->state_changed = true; } static const struct weston_pointer_grab_interface popup_grab_interface; @@ -2319,18 +2814,19 @@ static void popup_grab_focus(struct weston_pointer_grab *grab) { struct weston_pointer *pointer = grab->pointer; - struct weston_surface *surface; + struct weston_view *view; struct shell_seat *shseat = container_of(grab, struct shell_seat, popup_grab.grab); struct wl_client *client = shseat->popup_grab.client; wl_fixed_t sx, sy; - surface = weston_compositor_pick_surface(pointer->seat->compositor, - pointer->x, pointer->y, - &sx, &sy); + view = weston_compositor_pick_view(pointer->seat->compositor, + pointer->x, pointer->y, + &sx, &sy); - if (surface && wl_resource_get_client(surface->resource) == client) { - weston_pointer_set_focus(pointer, surface, sx, sy); + if (view && view->surface->resource && + wl_resource_get_client(view->surface->resource) == client) { + weston_pointer_set_focus(pointer, view, sx, sy); } else { weston_pointer_set_focus(pointer, NULL, wl_fixed_from_int(0), @@ -2339,16 +2835,19 @@ popup_grab_focus(struct weston_pointer_grab *grab) } static void -popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time) +popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) { struct weston_pointer *pointer = grab->pointer; struct wl_resource *resource; wl_fixed_t sx, sy; + weston_pointer_move(pointer, x, y); + wl_resource_for_each(resource, &pointer->focus_resource_list) { - weston_surface_from_global_fixed(pointer->focus, - pointer->x, pointer->y, - &sx, &sy); + weston_view_from_global_fixed(pointer->focus, + pointer->x, pointer->y, + &sx, &sy); wl_pointer_send_motion(resource, time, sx, sy); } } @@ -2396,6 +2895,16 @@ static const struct weston_pointer_grab_interface popup_grab_interface = { }; static void +shell_surface_send_popup_done(struct shell_surface *shsurf) +{ + if (shell_surface_is_wl_shell_surface(shsurf)) + wl_shell_surface_send_popup_done(shsurf->resource); + else if (shell_surface_is_xdg_popup(shsurf)) + xdg_popup_send_popup_done(shsurf->resource, + shsurf->popup.serial); +} + +static void popup_grab_end(struct weston_pointer *pointer) { struct weston_pointer_grab *grab = pointer->grab; @@ -2411,7 +2920,7 @@ popup_grab_end(struct weston_pointer *pointer) assert(!wl_list_empty(&shseat->popup_grab.surfaces_list)); /* Send the popup_done event to all the popups open */ wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) { - wl_shell_surface_send_popup_done(shsurf->resource); + shell_surface_send_popup_done(shsurf); shsurf->popup.shseat = NULL; if (prev) { wl_list_init(&prev->popup.grab_link); @@ -2461,41 +2970,23 @@ static void shell_map_popup(struct shell_surface *shsurf) { struct shell_seat *shseat = shsurf->popup.shseat; - struct weston_surface *es = shsurf->surface; - struct weston_surface *parent = shsurf->parent; + struct weston_view *parent_view = get_default_view(shsurf->parent); - es->output = parent->output; + shsurf->surface->output = parent_view->output; + shsurf->view->output = parent_view->output; - weston_surface_set_transform_parent(es, parent); - weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y); - weston_surface_update_transform(es); + weston_view_set_transform_parent(shsurf->view, parent_view); + weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y); + weston_view_update_transform(shsurf->view); if (shseat->seat->pointer->grab_serial == shsurf->popup.serial) { add_popup_grab(shsurf, shseat); } else { - wl_shell_surface_send_popup_done(shsurf->resource); + shell_surface_send_popup_done(shsurf); shseat->popup_grab.client = NULL; } } -static void -shell_surface_set_popup(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *seat_resource, - uint32_t serial, - struct wl_resource *parent_resource, - int32_t x, int32_t y, uint32_t flags) -{ - struct shell_surface *shsurf = wl_resource_get_user_data(resource); - - shsurf->type = SHELL_SURFACE_POPUP; - shsurf->parent = wl_resource_get_user_data(parent_resource); - shsurf->popup.shseat = get_shell_seat(wl_resource_get_user_data(seat_resource)); - shsurf->popup.serial = serial; - shsurf->popup.x = x; - shsurf->popup.y = y; -} - static const struct wl_shell_surface_interface shell_surface_implementation = { shell_surface_pong, shell_surface_move, @@ -2512,13 +3003,15 @@ static const struct wl_shell_surface_interface shell_surface_implementation = { static void destroy_shell_surface(struct shell_surface *shsurf) { - wl_signal_emit(&shsurf->destroy_signal, shsurf); + struct shell_surface *child, *next; /* if ico_window_mgr hook, call hook routine */ if (shell_hook_destroy) { (*shell_hook_destroy)(shsurf->surface); } + wl_signal_emit(&shsurf->destroy_signal, shsurf); + if (!wl_list_empty(&shsurf->popup.grab_link)) { remove_popup_grab(shsurf); } @@ -2527,8 +3020,8 @@ destroy_shell_surface(struct shell_surface *shsurf) shell_surface_is_top_fullscreen(shsurf)) restore_output_mode (shsurf->fullscreen_output); - if (shsurf->fullscreen.black_surface) - weston_surface_destroy(shsurf->fullscreen.black_surface); + if (shsurf->fullscreen.black_view) + weston_surface_destroy(shsurf->fullscreen.black_view->surface); /* As destroy_resource() use wl_list_for_each_safe(), * we can always remove the listener. @@ -2538,6 +3031,14 @@ destroy_shell_surface(struct shell_surface *shsurf) ping_timer_destroy(shsurf); free(shsurf->title); + weston_view_destroy(shsurf->view); + + wl_list_remove(&shsurf->children_link); + wl_list_for_each_safe(child, next, &shsurf->children_list, children_link) { + wl_list_remove(&child->children_link); + child->parent = NULL; + } + wl_list_remove(&shsurf->link); free(shsurf); } @@ -2564,9 +3065,11 @@ shell_handle_surface_destroy(struct wl_listener *listener, void *data) } static void -shell_surface_configure(struct weston_surface *, int32_t, int32_t, int32_t, int32_t); +shell_surface_configure(struct weston_surface *, int32_t, int32_t); +static void +shell_surface_output_destroyed(struct weston_surface *); -static struct shell_surface * +struct shell_surface * get_shell_surface(struct weston_surface *surface) { if (surface->configure == shell_surface_configure) @@ -2575,9 +3078,9 @@ get_shell_surface(struct weston_surface *surface) return NULL; } -static struct shell_surface * -create_shell_surface(void *shell, struct weston_surface *surface, - const struct weston_shell_client *client) +static struct shell_surface * +create_common_surface(void *shell, struct weston_surface *surface, + const struct weston_shell_client *client) { struct shell_surface *shsurf; @@ -2592,57 +3095,458 @@ create_shell_surface(void *shell, struct weston_surface *surface, return NULL; } + shsurf->view = weston_view_create(surface); + if (!shsurf->view) { + weston_log("no memory to allocate shell surface\n"); + free(shsurf); + return NULL; + } + surface->configure = shell_surface_configure; surface->configure_private = shsurf; + surface->output_destroyed = shell_surface_output_destroyed; + + shsurf->shell = (struct desktop_shell *) shell; + shsurf->unresponsive = 0; + shsurf->saved_position_valid = false; + shsurf->saved_size_valid = false; + shsurf->saved_rotation_valid = false; + shsurf->surface = surface; + shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; + shsurf->fullscreen.framerate = 0; + shsurf->fullscreen.black_view = NULL; + shsurf->ping_timer = NULL; + + /* set default color and shader because weston original bug(some time crash weston) */ + weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0); + + wl_list_init(&shsurf->fullscreen.transform.link); + + wl_signal_init(&shsurf->destroy_signal); + shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy; + wl_signal_add(&surface->destroy_signal, + &shsurf->surface_destroy_listener); + + /* init link so its safe to always remove it in destroy_shell_surface */ + wl_list_init(&shsurf->link); + wl_list_init(&shsurf->popup.grab_link); + + /* empty when not in use */ + wl_list_init(&shsurf->rotation.transform.link); + weston_matrix_init(&shsurf->rotation.rotation); + + wl_list_init(&shsurf->workspace_transform.link); + + wl_list_init(&shsurf->children_link); + wl_list_init(&shsurf->children_list); + shsurf->parent = NULL; + + shsurf->type = SHELL_SURFACE_NONE; + + shsurf->client = client; + + return shsurf; +} + +static struct shell_surface * +create_shell_surface(void *shell, struct weston_surface *surface, + const struct weston_shell_client *client) +{ + return create_common_surface(shell, surface, client); +} + +static struct weston_view * +get_primary_view(void *shell, struct shell_surface *shsurf) +{ + return shsurf->view; +} + +static void +shell_get_shell_surface(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource) +{ + struct weston_surface *surface = + wl_resource_get_user_data(surface_resource); + struct desktop_shell *shell = wl_resource_get_user_data(resource); + struct shell_surface *shsurf; + + if (get_shell_surface(surface)) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "desktop_shell::get_shell_surface already requested"); + return; + } + + shsurf = create_shell_surface(shell, surface, &shell_client); + if (!shsurf) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "surface->configure already set"); + return; + } + + /* if ico_window_mgr hook, call hook routine */ + shsurf->layertype = LAYER_TYPE_PANEL; + if (shell_hook_create) { + (*shell_hook_create)(LAYER_TYPE_PANEL, surface, client, shsurf); + } + + shsurf->resource = + wl_resource_create(client, + &wl_shell_surface_interface, 1, id); + wl_resource_set_implementation(shsurf->resource, + &shell_surface_implementation, + shsurf, shell_destroy_shell_surface); +} + +static bool +shell_surface_is_wl_shell_surface(struct shell_surface *shsurf) +{ + return wl_resource_instance_of(shsurf->resource, + &wl_shell_surface_interface, + &shell_surface_implementation); +} + +static const struct wl_shell_interface shell_implementation = { + shell_get_shell_surface +}; + +/**************************** + * xdg-shell implementation */ + +static void +xdg_surface_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +xdg_surface_pong(struct wl_client *client, + struct wl_resource *resource, + uint32_t serial) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + surface_pong(shsurf, serial); +} + +static void +xdg_surface_set_app_id(struct wl_client *client, + struct wl_resource *resource, + const char *app_id) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + free(shsurf->class); + shsurf->class = strdup(app_id); +} + +static void +xdg_surface_set_title(struct wl_client *client, + struct wl_resource *resource, const char *title) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + set_title(shsurf, title); +} + +static void +xdg_surface_move(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *seat_resource, uint32_t serial) +{ + common_surface_move(resource, seat_resource, serial); +} + +static void +xdg_surface_resize(struct wl_client *client, struct wl_resource *resource, + struct wl_resource *seat_resource, uint32_t serial, + uint32_t edges) +{ + common_surface_resize(resource, seat_resource, serial, edges); +} + +static void +xdg_surface_set_output(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *output_resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + struct weston_output *output; + + if (output_resource) + output = wl_resource_get_user_data(output_resource); + else + output = NULL; + + shsurf->recommended_output = output; +} + +static void +xdg_surface_set_fullscreen(struct wl_client *client, + struct wl_resource *resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + if (shsurf->type != SHELL_SURFACE_TOPLEVEL) + return; + + if (!shsurf->next_state.fullscreen) + set_fullscreen(shsurf, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + 0, shsurf->recommended_output); +} + +static void +xdg_surface_unset_fullscreen(struct wl_client *client, + struct wl_resource *resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + int32_t width, height; + + if (shsurf->type != SHELL_SURFACE_TOPLEVEL) + return; + + if (!shsurf->next_state.fullscreen) + return; + + shsurf->next_state.fullscreen = false; + shsurf->state_changed = true; + + if (shsurf->saved_size_valid) { + width = shsurf->saved_width; + height = shsurf->saved_height; + shsurf->saved_size_valid = false; + } else { + width = shsurf->surface->width; + height = shsurf->surface->height; + } + + if (shell_hook_fullscreen) { + (*shell_hook_fullscreen)(SHELL_FULLSCREEN_UNSET, shsurf->surface); + } + + shsurf->client->send_configure(shsurf->surface, 0, width, height); +} + +static void +xdg_surface_set_maximized(struct wl_client *client, + struct wl_resource *resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + + if (shsurf->type != SHELL_SURFACE_TOPLEVEL) + return; + + if (!shsurf->next_state.maximized) + set_maximized(shsurf, NULL); +} + +static void +xdg_surface_unset_maximized(struct wl_client *client, + struct wl_resource *resource) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); + int32_t width, height; + + if (shsurf->type != SHELL_SURFACE_TOPLEVEL) + return; + + if (!shsurf->next_state.maximized) + return; + + shsurf->next_state.maximized = false; + shsurf->state_changed = true; + + if (shsurf->saved_size_valid) { + width = shsurf->saved_width; + height = shsurf->saved_height; + shsurf->saved_size_valid = false; + } else { + width = shsurf->surface->width; + height = shsurf->surface->height; + } + + shsurf->client->send_configure(shsurf->surface, 0, width, height); +} + +static const struct xdg_surface_interface xdg_surface_implementation = { + xdg_surface_destroy, + xdg_surface_set_transient_for, + xdg_surface_set_title, + xdg_surface_set_app_id, + xdg_surface_pong, + xdg_surface_move, + xdg_surface_resize, + xdg_surface_set_output, + xdg_surface_set_fullscreen, + xdg_surface_unset_fullscreen, + xdg_surface_set_maximized, + xdg_surface_unset_maximized, + NULL /* set_minimized */ +}; + +static void +xdg_send_configure(struct weston_surface *surface, + uint32_t edges, int32_t width, int32_t height) +{ + struct shell_surface *shsurf = get_shell_surface(surface); + + assert(shsurf); + + xdg_surface_send_configure(shsurf->resource, edges, width, height); +} + +static const struct weston_shell_client xdg_client = { + xdg_send_configure +}; + +static void +xdg_use_unstable_version(struct wl_client *client, + struct wl_resource *resource, + int32_t version) +{ + if (version > 1) { + wl_resource_post_error(resource, + 1, + "xdg-shell:: version not implemented yet."); + return; + } +} + +static struct shell_surface * +create_xdg_surface(void *shell, struct weston_surface *surface, + const struct weston_shell_client *client) +{ + struct shell_surface *shsurf; + + shsurf = create_common_surface(shell, surface, client); + shsurf->type = SHELL_SURFACE_TOPLEVEL; + + return shsurf; +} + +static void +xdg_get_xdg_surface(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource) +{ + struct weston_surface *surface = + wl_resource_get_user_data(surface_resource); + struct desktop_shell *shell = wl_resource_get_user_data(resource); + struct shell_surface *shsurf; + + if (get_shell_surface(surface)) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "desktop_shell::get_shell_surface already requested"); + return; + } + + shsurf = create_xdg_surface(shell, surface, &xdg_client); + if (!shsurf) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "surface->configure already set"); + return; + } + + /* if ico_window_mgr hook, call hook routine */ + shsurf->layertype = LAYER_TYPE_PANEL; + if (shell_hook_create) { + (*shell_hook_create)(LAYER_TYPE_PANEL, surface, client, shsurf); + } + + shsurf->resource = + wl_resource_create(client, + &xdg_surface_interface, 1, id); + wl_resource_set_implementation(shsurf->resource, + &xdg_surface_implementation, + shsurf, shell_destroy_shell_surface); +} - shsurf->shell = (struct desktop_shell *) shell; - shsurf->unresponsive = 0; - shsurf->saved_position_valid = false; - shsurf->saved_rotation_valid = false; - shsurf->surface = surface; - shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; - shsurf->fullscreen.framerate = 0; - shsurf->fullscreen.black_surface = NULL; - shsurf->ping_timer = NULL; +static bool +shell_surface_is_xdg_surface(struct shell_surface *shsurf) +{ + return wl_resource_instance_of(shsurf->resource, + &xdg_surface_interface, + &xdg_surface_implementation); +} - /* set default color and shader because weston original bug(some time crash weston) */ - weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); +/* xdg-popup implementation */ - wl_list_init(&shsurf->fullscreen.transform.link); +static void +xdg_popup_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} - wl_signal_init(&shsurf->destroy_signal); - shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy; - wl_signal_add(&surface->destroy_signal, - &shsurf->surface_destroy_listener); +static void +xdg_popup_pong(struct wl_client *client, + struct wl_resource *resource, + uint32_t serial) +{ + struct shell_surface *shsurf = wl_resource_get_user_data(resource); - /* init link so its safe to always remove it in destroy_shell_surface */ - wl_list_init(&shsurf->link); - wl_list_init(&shsurf->popup.grab_link); + surface_pong(shsurf, serial); +} - /* empty when not in use */ - wl_list_init(&shsurf->rotation.transform.link); - weston_matrix_init(&shsurf->rotation.rotation); +static const struct xdg_popup_interface xdg_popup_implementation = { + xdg_popup_destroy, + xdg_popup_pong +}; - wl_list_init(&shsurf->workspace_transform.link); +static void +xdg_popup_send_configure(struct weston_surface *surface, + uint32_t edges, int32_t width, int32_t height) +{ +} - shsurf->type = SHELL_SURFACE_NONE; - shsurf->next_type = SHELL_SURFACE_NONE; +static const struct weston_shell_client xdg_popup_client = { + xdg_popup_send_configure +}; - shsurf->client = client; +static struct shell_surface * +create_xdg_popup(void *shell, struct weston_surface *surface, + const struct weston_shell_client *client, + struct weston_surface *parent, + struct shell_seat *seat, + uint32_t serial, + int32_t x, int32_t y) +{ + struct shell_surface *shsurf; + + shsurf = create_common_surface(shell, surface, client); + shsurf->type = SHELL_SURFACE_POPUP; + shsurf->popup.shseat = seat; + shsurf->popup.serial = serial; + shsurf->popup.x = x; + shsurf->popup.y = y; + shell_surface_set_parent(shsurf, parent); return shsurf; } static void -shell_get_shell_surface_layertype(int layertype, struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) +xdg_get_xdg_popup(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource, + struct wl_resource *parent_resource, + struct wl_resource *seat_resource, + uint32_t serial, + int32_t x, int32_t y, uint32_t flags) { struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct desktop_shell *shell = wl_resource_get_user_data(resource); struct shell_surface *shsurf; + struct weston_surface *parent; + struct shell_seat *seat; if (get_shell_surface(surface)) { wl_resource_post_error(surface_resource, @@ -2651,41 +3555,91 @@ shell_get_shell_surface_layertype(int layertype, struct wl_client *client, return; } - shsurf = create_shell_surface(shell, surface, &shell_client); + if (!parent_resource) { + wl_resource_post_error(surface_resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "xdg_shell::get_xdg_popup requires a parent shell surface"); + } + + parent = wl_resource_get_user_data(parent_resource); + seat = get_shell_seat(wl_resource_get_user_data(seat_resource));; + + shsurf = create_xdg_popup(shell, surface, &xdg_popup_client, + parent, seat, serial, x, y); if (!shsurf) { wl_resource_post_error(surface_resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "surface->configure already set"); return; } - shsurf->layertype = layertype; - shsurf->resource = - wl_resource_create(client, - &wl_shell_surface_interface, 1, id); - wl_resource_set_implementation(shsurf->resource, - &shell_surface_implementation, - shsurf, shell_destroy_shell_surface); /* if ico_window_mgr hook, call hook routine */ + shsurf->layertype = LAYER_TYPE_PANEL; if (shell_hook_create) { - (*shell_hook_create)(layertype, client, resource, surface, shsurf); + (*shell_hook_create)(LAYER_TYPE_PANEL, surface, client, shsurf); } + + shsurf->resource = + wl_resource_create(client, + &xdg_popup_interface, 1, id); + wl_resource_set_implementation(shsurf->resource, + &xdg_popup_implementation, + shsurf, shell_destroy_shell_surface); } -static void -shell_get_shell_surface(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) +static bool +shell_surface_is_xdg_popup(struct shell_surface *shsurf) { - shell_get_shell_surface_layertype(LAYER_TYPE_PANEL, - client, resource, id, surface_resource); + return wl_resource_instance_of(shsurf->resource, + &xdg_popup_interface, + &xdg_popup_implementation); } -static const struct wl_shell_interface shell_implementation = { - shell_get_shell_surface +static const struct xdg_shell_interface xdg_implementation = { + xdg_use_unstable_version, + xdg_get_xdg_surface, + xdg_get_xdg_popup }; +static int +xdg_shell_unversioned_dispatch(const void *implementation, + void *_target, uint32_t opcode, + const struct wl_message *message, + union wl_argument *args) +{ + struct wl_resource *resource = _target; + struct desktop_shell *shell = wl_resource_get_user_data(resource); + + if (opcode != 0) { + wl_resource_post_error(resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "must call use_unstable_version first"); + return 0; + } + +#define XDG_SERVER_VERSION 1 + + static_assert(XDG_SERVER_VERSION == XDG_SHELL_VERSION_CURRENT, + "shell implementation doesn't match protocol version"); + + if (args[0].i != XDG_SERVER_VERSION) { + wl_resource_post_error(resource, + WL_DISPLAY_ERROR_INVALID_OBJECT, + "incompatible version, server is %d " + "client wants %d", + XDG_SERVER_VERSION, args[0].i); + return 0; + } + + wl_resource_set_implementation(resource, &xdg_implementation, + shell, NULL); + + return 1; +} + +/* end of xdg-shell implementation */ +/***********************************/ + static void shell_fade(struct desktop_shell *shell, enum fade_type type); @@ -2727,7 +3681,6 @@ launch_screensaver(struct desktop_shell *shell) return; } - uifw_trace("launch_screensaver: launch %s", shell->screensaver.path); weston_client_launch(shell->compositor, &shell->screensaver.process, shell->screensaver.path, @@ -2744,41 +3697,39 @@ terminate_screensaver(struct desktop_shell *shell) } static void -configure_static_surface(struct weston_surface *es, struct weston_layer *layer, int32_t width, int32_t height) +configure_static_view(struct weston_view *ev, struct weston_layer *layer) { - struct weston_surface *s, *next; - - if (width == 0) - return; + struct weston_view *v, *next; - wl_list_for_each_safe(s, next, &layer->surface_list, layer_link) { - if (s->output == es->output && s != es) { - weston_surface_unmap(s); - s->configure = NULL; + wl_list_for_each_safe(v, next, &layer->view_list, layer_link) { + if (v->output == ev->output && v != ev) { + weston_view_unmap(v); + v->surface->configure = NULL; } } - uifw_debug("configure_static_surface: configure %08x x/y=%d/%d w/h=%d/%d", - (int)es, (int)es->output->x, (int)es->output->y, width, height); - weston_surface_configure(es, es->output->x, es->output->y, width, height); + weston_view_set_position(ev, ev->output->x, ev->output->y); - if (wl_list_empty(&es->layer_link)) { - wl_list_insert(&layer->surface_list, &es->layer_link); - weston_compositor_schedule_repaint(es->compositor); + if (wl_list_empty(&ev->layer_link)) { + wl_list_insert(&layer->view_list, &ev->layer_link); + weston_compositor_schedule_repaint(ev->surface->compositor); } /* if ico_window_mgr hook, call hook routine */ if (shell_hook_configure) { - (*shell_hook_configure)(es); + (*shell_hook_configure)(ev->surface); } } static void -background_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +background_configure(struct weston_surface *es, int32_t sx, int32_t sy) { struct desktop_shell *shell = es->configure_private; + struct weston_view *view; + + view = container_of(es->views.next, struct weston_view, surface_link); - configure_static_surface(es, &shell->background_layer, width, height); + configure_static_view(view, &shell->background_layer); } static void @@ -2790,6 +3741,7 @@ desktop_shell_set_background(struct wl_client *client, struct desktop_shell *shell = wl_resource_get_user_data(resource); struct weston_surface *surface = wl_resource_get_user_data(surface_resource); + struct weston_view *view, *next; if (surface->configure) { wl_resource_post_error(surface_resource, @@ -2798,11 +3750,14 @@ desktop_shell_set_background(struct wl_client *client, return; } + wl_list_for_each_safe(view, next, &surface->views, surface_link) + weston_view_destroy(view); + view = weston_view_create(surface); + surface->configure = background_configure; surface->configure_private = shell; surface->output = wl_resource_get_user_data(output_resource); - uifw_debug("desktop_shell_set_background: send %08x 0 w/h=%d/%d", - (int)surface, surface->output->width, surface->output->height); + view->output = surface->output; desktop_shell_send_configure(resource, 0, surface_resource, surface->output->width, @@ -2810,11 +3765,14 @@ desktop_shell_set_background(struct wl_client *client, } static void -panel_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +panel_configure(struct weston_surface *es, int32_t sx, int32_t sy) { struct desktop_shell *shell = es->configure_private; + struct weston_view *view; + + view = container_of(es->views.next, struct weston_view, surface_link); - configure_static_surface(es, &shell->panel_layer, width, height); + configure_static_view(view, &shell->panel_layer); } static void @@ -2826,6 +3784,7 @@ desktop_shell_set_panel(struct wl_client *client, struct desktop_shell *shell = wl_resource_get_user_data(resource); struct weston_surface *surface = wl_resource_get_user_data(surface_resource); + struct weston_view *view, *next; if (surface->configure) { wl_resource_post_error(surface_resource, @@ -2834,11 +3793,14 @@ desktop_shell_set_panel(struct wl_client *client, return; } + wl_list_for_each_safe(view, next, &surface->views, surface_link) + weston_view_destroy(view); + view = weston_view_create(surface); + surface->configure = panel_configure; surface->configure_private = shell; surface->output = wl_resource_get_user_data(output_resource); - uifw_debug("desktop_shell_set_panel: send %08x 0 w/h=%d/%d", - (int)surface, surface->output->width, surface->output->height); + view->output = surface->output; desktop_shell_send_configure(resource, 0, surface_resource, surface->output->width, @@ -2846,22 +3808,22 @@ desktop_shell_set_panel(struct wl_client *client, } static void -lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height) +lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy) { struct desktop_shell *shell = surface->configure_private; + struct weston_view *view; + + view = container_of(surface->views.next, struct weston_view, surface_link); - if (width == 0) + if (surface->width == 0) return; - uifw_debug("lock_surface_configure: change %08x w/h=%d/%d", (int)surface, width, height); - surface->geometry.width = width; - surface->geometry.height = height; - center_on_output(surface, get_default_output(shell->compositor)); + center_on_output(view, get_default_output(shell->compositor)); if (!weston_surface_is_mapped(surface)) { - wl_list_insert(&shell->lock_layer.surface_list, - &surface->layer_link); - weston_surface_update_transform(surface); + wl_list_insert(&shell->lock_layer.view_list, + &view->layer_link); + weston_view_update_transform(view); shell_fade(shell, FADE_IN); } } @@ -2896,6 +3858,7 @@ desktop_shell_set_lock_surface(struct wl_client *client, wl_signal_add(&surface->destroy_signal, &shell->lock_surface_listener); + weston_view_create(surface); surface->configure = lock_surface_configure; surface->configure_private = shell; } @@ -2912,8 +3875,7 @@ resume_desktop(struct desktop_shell *shell) &shell->fullscreen_layer.link); wl_list_insert(&shell->fullscreen_layer.link, &shell->panel_layer.link); - if ((! shell_hook_configure) && - (shell->showing_input_panels)) { + if (shell->showing_input_panels) { wl_list_insert(&shell->panel_layer.link, &shell->input_panel_layer.link); wl_list_insert(&shell->input_panel_layer.link, @@ -2949,6 +3911,7 @@ desktop_shell_set_grab_surface(struct wl_client *client, struct desktop_shell *shell = wl_resource_get_user_data(resource); shell->grab_surface = wl_resource_get_user_data(surface_resource); + weston_view_create(shell->grab_surface); } static void @@ -2983,28 +3946,79 @@ get_shell_surface_type(struct weston_surface *surface) static void move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data) { - struct weston_surface *focus = - (struct weston_surface *) seat->pointer->focus; + struct weston_surface *focus; struct weston_surface *surface; struct shell_surface *shsurf; + if (seat->pointer->focus == NULL) + return; + + focus = seat->pointer->focus->surface; + surface = weston_surface_get_main_surface(focus); if (surface == NULL) return; shsurf = get_shell_surface(surface); - if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN || - shsurf->type == SHELL_SURFACE_MAXIMIZED) + if (shsurf == NULL || shsurf->state.fullscreen || + shsurf->state.maximized) return; surface_move(shsurf, (struct weston_seat *) seat); } static void +maximize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data) +{ + struct weston_surface *focus = seat->pointer->focus->surface; + struct weston_surface *surface; + struct shell_surface *shsurf; + + surface = weston_surface_get_main_surface(focus); + if (surface == NULL) + return; + + shsurf = get_shell_surface(surface); + if (shsurf == NULL) + return; + + if (!shell_surface_is_xdg_surface(shsurf)) + return; + + if (shsurf->state.maximized) + xdg_surface_send_request_unset_maximized(shsurf->resource); + else + xdg_surface_send_request_set_maximized(shsurf->resource); +} + +static void +fullscreen_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data) +{ + struct weston_surface *focus = seat->pointer->focus->surface; + struct weston_surface *surface; + struct shell_surface *shsurf; + + surface = weston_surface_get_main_surface(focus); + if (surface == NULL) + return; + + shsurf = get_shell_surface(surface); + if (shsurf == NULL) + return; + + if (!shell_surface_is_xdg_surface(shsurf)) + return; + + if (shsurf->state.fullscreen) + xdg_surface_send_request_unset_fullscreen(shsurf->resource); + else + xdg_surface_send_request_set_fullscreen(shsurf->resource); +} + +static void touch_move_binding(struct weston_seat *seat, uint32_t time, void *data) { - struct weston_surface *focus = - (struct weston_surface *) seat->touch->focus; + struct weston_surface *focus = seat->touch->focus->surface; struct weston_surface *surface; struct shell_surface *shsurf; @@ -3013,8 +4027,8 @@ touch_move_binding(struct weston_seat *seat, uint32_t time, void *data) return; shsurf = get_shell_surface(surface); - if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN || - shsurf->type == SHELL_SURFACE_MAXIMIZED) + if (shsurf == NULL || shsurf->state.fullscreen || + shsurf->state.maximized) return; surface_touch_move(shsurf, (struct weston_seat *) seat); @@ -3023,37 +4037,41 @@ touch_move_binding(struct weston_seat *seat, uint32_t time, void *data) static void resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data) { - struct weston_surface *focus = - (struct weston_surface *) seat->pointer->focus; + struct weston_surface *focus; struct weston_surface *surface; uint32_t edges = 0; int32_t x, y; struct shell_surface *shsurf; + if (seat->pointer->focus == NULL) + return; + + focus = seat->pointer->focus->surface; + surface = weston_surface_get_main_surface(focus); if (surface == NULL) return; shsurf = get_shell_surface(surface); - if (!shsurf || shsurf->type == SHELL_SURFACE_FULLSCREEN || - shsurf->type == SHELL_SURFACE_MAXIMIZED) + if (shsurf == NULL || shsurf->state.fullscreen || + shsurf->state.maximized) return; - weston_surface_from_global(surface, - wl_fixed_to_int(seat->pointer->grab_x), - wl_fixed_to_int(seat->pointer->grab_y), - &x, &y); + weston_view_from_global(shsurf->view, + wl_fixed_to_int(seat->pointer->grab_x), + wl_fixed_to_int(seat->pointer->grab_y), + &x, &y); - if (x < surface->geometry.width / 3) + if (x < shsurf->surface->width / 3) edges |= WL_SHELL_SURFACE_RESIZE_LEFT; - else if (x < 2 * surface->geometry.width / 3) + else if (x < 2 * shsurf->surface->width / 3) edges |= 0; else edges |= WL_SHELL_SURFACE_RESIZE_RIGHT; - if (y < surface->geometry.height / 3) + if (y < shsurf->surface->height / 3) edges |= WL_SHELL_SURFACE_RESIZE_TOP; - else if (y < 2 * surface->geometry.height / 3) + else if (y < 2 * shsurf->surface->height / 3) edges |= 0; else edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM; @@ -3067,8 +4085,7 @@ surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis, { float step = 0.005; struct shell_surface *shsurf; - struct weston_surface *focus = - (struct weston_surface *) seat->pointer->focus; + struct weston_surface *focus = seat->pointer->focus->surface; struct weston_surface *surface; /* XXX: broken for windows containing sub-surfaces */ @@ -3080,14 +4097,14 @@ surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis, if (!shsurf) return; - surface->alpha -= wl_fixed_to_double(value) * step; + shsurf->view->alpha -= wl_fixed_to_double(value) * step; - if (surface->alpha > 1.0) - surface->alpha = 1.0; - if (surface->alpha < step) - surface->alpha = step; + if (shsurf->view->alpha > 1.0) + shsurf->view->alpha = 1.0; + if (shsurf->view->alpha < step) + shsurf->view->alpha = step; - weston_surface_geometry_dirty(surface); + weston_view_geometry_dirty(shsurf->view); weston_surface_damage(surface); } @@ -3123,13 +4140,12 @@ do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis, else if (output->zoom.level > output->zoom.max_level) output->zoom.level = output->zoom.max_level; else if (!output->zoom.active) { - output->zoom.active = 1; - output->disable_planes++; + weston_output_activate_zoom(output); } output->zoom.spring_z.target = output->zoom.level; - weston_output_update_zoom(output, output->zoom.type); + weston_output_update_zoom(output); } } } @@ -3158,29 +4174,29 @@ terminate_binding(struct weston_seat *seat, uint32_t time, uint32_t key, } static void -rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time) +rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time, + wl_fixed_t x, wl_fixed_t y) { struct rotate_grab *rotate = container_of(grab, struct rotate_grab, base.grab); struct weston_pointer *pointer = grab->pointer; struct shell_surface *shsurf = rotate->base.shsurf; - struct weston_surface *surface; float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r; + weston_pointer_move(pointer, x, y); + if (!shsurf) return; - surface = shsurf->surface; - - cx = 0.5f * surface->geometry.width; - cy = 0.5f * surface->geometry.height; + cx = 0.5f * shsurf->surface->width; + cy = 0.5f * shsurf->surface->height; dx = wl_fixed_to_double(pointer->x) - rotate->center.x; dy = wl_fixed_to_double(pointer->y) - rotate->center.y; r = sqrtf(dx * dx + dy * dy); wl_list_remove(&shsurf->rotation.transform.link); - weston_surface_geometry_dirty(shsurf->surface); + weston_view_geometry_dirty(shsurf->view); if (r > 20.0f) { struct weston_matrix *matrix = @@ -3196,7 +4212,7 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time) weston_matrix_translate(matrix, cx, cy, 0.0f); wl_list_insert( - &shsurf->surface->geometry.transformation_list, + &shsurf->view->geometry.transformation_list, &shsurf->rotation.transform.link); } else { wl_list_init(&shsurf->rotation.transform.link); @@ -3206,14 +4222,14 @@ rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time) /* We need to adjust the position of the surface * in case it was resized in a rotated state before */ - cposx = surface->geometry.x + cx; - cposy = surface->geometry.y + cy; + cposx = shsurf->view->geometry.x + cx; + cposy = shsurf->view->geometry.y + cy; dposx = rotate->center.x - cposx; dposy = rotate->center.y - cposy; if (dposx != 0.0f || dposy != 0.0f) { - weston_surface_set_position(surface, - surface->geometry.x + dposx, - surface->geometry.y + dposy); + weston_view_set_position(shsurf->view, + shsurf->view->geometry.x + dposx, + shsurf->view->geometry.y + dposy); } /* Repaint implies weston_surface_update_transform(), which @@ -3270,10 +4286,10 @@ surface_rotate(struct shell_surface *surface, struct weston_seat *seat) if (!rotate) return; - weston_surface_to_global_float(surface->surface, - surface->surface->geometry.width * 0.5f, - surface->surface->geometry.height * 0.5f, - &rotate->center.x, &rotate->center.y); + weston_view_to_global_float(surface->view, + surface->surface->width * 0.5f, + surface->surface->height * 0.5f, + &rotate->center.x, &rotate->center.y); dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x; dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y; @@ -3300,48 +4316,61 @@ static void rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data) { - struct weston_surface *focus = - (struct weston_surface *) seat->pointer->focus; + struct weston_surface *focus; struct weston_surface *base_surface; struct shell_surface *surface; + if (seat->pointer->focus == NULL) + return; + + focus = seat->pointer->focus->surface; + base_surface = weston_surface_get_main_surface(focus); if (base_surface == NULL) return; surface = get_shell_surface(base_surface); - if (!surface || surface->type == SHELL_SURFACE_FULLSCREEN || - surface->type == SHELL_SURFACE_MAXIMIZED) + if (surface == NULL || surface->state.fullscreen || + surface->state.maximized) return; surface_rotate(surface, seat); } -static void +/* Move all fullscreen layers down to the current workspace in a non-reversible + * manner. This should be used when implementing shell-wide overlays, such as + * the alt-tab switcher, which need to de-promote fullscreen layers. */ +void lower_fullscreen_layer(struct desktop_shell *shell) { + struct workspace *ws; + struct weston_view *view, *prev; + if (shell_hook_fullscreen) { (*shell_hook_fullscreen)(SHELL_FULLSCREEN_HIDEALL, NULL); return; } - struct workspace *ws; - struct weston_surface *surface, *prev; - ws = get_current_workspace(shell); - wl_list_for_each_reverse_safe(surface, prev, - &shell->fullscreen_layer.surface_list, - layer_link) - weston_surface_restack(surface, &ws->layer.surface_list); + wl_list_for_each_reverse_safe(view, prev, + &shell->fullscreen_layer.view_list, + layer_link) { + wl_list_remove(&view->layer_link); + wl_list_insert(&ws->layer.view_list, &view->layer_link); + weston_view_damage_below(view); + weston_surface_damage(view->surface); + } } -static void +void activate(struct desktop_shell *shell, struct weston_surface *es, struct weston_seat *seat) { struct weston_surface *main_surface; struct focus_state *state; struct workspace *ws; + struct weston_surface *old_es; + struct shell_surface *shsurf; main_surface = weston_surface_get_main_surface(es); @@ -3351,32 +4380,35 @@ activate(struct desktop_shell *shell, struct weston_surface *es, if (state == NULL) return; - state->keyboard_focus = es; - wl_list_remove(&state->surface_destroy_listener.link); - wl_signal_add(&es->destroy_signal, &state->surface_destroy_listener); + old_es = state->keyboard_focus; + focus_state_set_focus(state, es); + + shsurf = get_shell_surface(main_surface); + assert(shsurf); /* if ico_window_mgr hook, not change surface stack */ if (shell_hook_select) { return; } - switch (get_shell_surface_type(main_surface)) { - case SHELL_SURFACE_FULLSCREEN: - /* should on top of panels */ - shell_stack_fullscreen(get_shell_surface(main_surface)); - shell_configure_fullscreen(get_shell_surface(main_surface)); - break; - default: + if (shsurf->state.fullscreen) + shell_configure_fullscreen(shsurf); + else restore_all_output_modes(shell->compositor); + + if (shell->focus_animation_type != ANIMATION_NONE) { ws = get_current_workspace(shell); - weston_surface_restack(main_surface, &ws->layer.surface_list); - break; + animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es)); } + + /* Update the surface’s layer. This brings it to the top of the stacking + * order as appropriate. */ + shell_surface_update_layer(shsurf); } /* no-op func for checking black surface */ static void -black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy) { } @@ -3422,9 +4454,10 @@ click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t butt { if (seat->pointer->grab != &seat->pointer->default_grab) return; + if (seat->pointer->focus == NULL) + return; - activate_binding(seat, data, - (struct weston_surface *) seat->pointer->focus); + activate_binding(seat, data, seat->pointer->focus->surface); } static void @@ -3432,9 +4465,10 @@ touch_to_activate_binding(struct weston_seat *seat, uint32_t time, void *data) { if (seat->touch->grab != &seat->touch->default_grab) return; + if (seat->touch->focus == NULL) + return; - activate_binding(seat, data, - (struct weston_surface *) seat->touch->focus); + activate_binding(seat, data, seat->touch->focus->surface); } static void @@ -3455,8 +4489,7 @@ lock(struct desktop_shell *shell) wl_list_remove(&shell->panel_layer.link); wl_list_remove(&shell->fullscreen_layer.link); - if ((! shell_hook_configure) && - (shell->showing_input_panels)) + if (shell->showing_input_panels) wl_list_remove(&shell->input_panel_layer.link); wl_list_remove(&ws->layer.link); wl_list_insert(&shell->compositor->cursor_layer.link, @@ -3491,7 +4524,7 @@ unlock(struct desktop_shell *shell) } static void -shell_fade_done(struct weston_surface_animation *animation, void *data) +shell_fade_done(struct weston_view_animation *animation, void *data) { struct desktop_shell *shell = data; @@ -3499,34 +4532,42 @@ shell_fade_done(struct weston_surface_animation *animation, void *data) switch (shell->fade.type) { case FADE_IN: - weston_surface_destroy(shell->fade.surface); - shell->fade.surface = NULL; + weston_surface_destroy(shell->fade.view->surface); + shell->fade.view = NULL; break; case FADE_OUT: lock(shell); break; + default: + break; } } -static struct weston_surface * +static struct weston_view * shell_fade_create_surface(struct desktop_shell *shell) { struct weston_compositor *compositor = shell->compositor; struct weston_surface *surface; + struct weston_view *view; surface = weston_surface_create(compositor); if (!surface) return NULL; - uifw_debug("shell_fade_create_surface: configure %08x x/y=%d/%d w/h=%d/%d", - (int)surface, 0, 0, 8192, 8192); - weston_surface_configure(surface, 0, 0, 8192, 8192); + view = weston_view_create(surface); + if (!view) { + weston_surface_destroy(surface); + return NULL; + } + + weston_surface_set_size(surface, 8192, 8192); + weston_view_set_position(view, 0, 0); weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0); - wl_list_insert(&compositor->fade_layer.surface_list, - &surface->layer_link); + wl_list_insert(&compositor->fade_layer.view_list, + &view->layer_link); pixman_region32_init(&surface->input); - return surface; + return view; } static void @@ -3548,22 +4589,31 @@ shell_fade(struct desktop_shell *shell, enum fade_type type) shell->fade.type = type; - if (shell->fade.surface == NULL) { - shell->fade.surface = shell_fade_create_surface(shell); - if (!shell->fade.surface) + if (shell->fade.view == NULL) { + shell->fade.view = shell_fade_create_surface(shell); + if (!shell->fade.view) return; - shell->fade.surface->alpha = 1.0 - tint; - weston_surface_update_transform(shell->fade.surface); + shell->fade.view->alpha = 1.0 - tint; + weston_view_update_transform(shell->fade.view); } - if (shell->fade.animation) + if (shell->fade.view->output == NULL) { + /* If the black view gets a NULL output, we lost the + * last output and we'll just cancel the fade. This + * happens when you close the last window under the + * X11 or Wayland backends. */ + shell->locked = false; + weston_surface_destroy(shell->fade.view->surface); + shell->fade.view = NULL; + } else if (shell->fade.animation) { weston_fade_update(shell->fade.animation, tint); - else + } else { shell->fade.animation = - weston_fade_run(shell->fade.surface, + weston_fade_run(shell->fade.view, 1.0 - tint, tint, 300.0, shell_fade_done, shell); + } } static void @@ -3574,8 +4624,8 @@ do_shell_fade_startup(void *data) if (shell->startup_animation_type == ANIMATION_FADE) shell_fade(shell, FADE_IN); else if (shell->startup_animation_type == ANIMATION_NONE) { - weston_surface_destroy(shell->fade.surface); - shell->fade.surface = NULL; + weston_surface_destroy(shell->fade.view->surface); + shell->fade.view = NULL; } } @@ -3613,18 +4663,18 @@ shell_fade_init(struct desktop_shell *shell) struct wl_event_loop *loop; - if (shell->fade.surface != NULL) { + if (shell->fade.view != NULL) { weston_log("%s: warning: fade surface already exists\n", __func__); return; } - shell->fade.surface = shell_fade_create_surface(shell); - if (!shell->fade.surface) + shell->fade.view = shell_fade_create_surface(shell); + if (!shell->fade.view) return; - weston_surface_update_transform(shell->fade.surface); - weston_surface_damage(shell->fade.surface); + weston_view_update_transform(shell->fade.view); + weston_surface_damage(shell->fade.view->surface); loop = wl_display_get_event_loop(shell->compositor->wl_display); shell->fade.startup_timer = @@ -3637,6 +4687,11 @@ idle_handler(struct wl_listener *listener, void *data) { struct desktop_shell *shell = container_of(listener, struct desktop_shell, idle_listener); + struct weston_seat *seat; + + wl_list_for_each(seat, &shell->compositor->seat_list, link) + if (seat->pointer) + popup_grab_end(seat->pointer); shell_fade(shell, FADE_OUT); /* lock() is called from shell_fade_done() */ @@ -3652,106 +4707,22 @@ wake_handler(struct wl_listener *listener, void *data) } static void -show_input_panels(struct wl_listener *listener, void *data) -{ - struct desktop_shell *shell = - container_of(listener, struct desktop_shell, - show_input_panel_listener); - struct input_panel_surface *surface, *next; - struct weston_surface *ws; - - shell->text_input.surface = (struct weston_surface*)data; - - if (shell->showing_input_panels) - return; - - uifw_debug("show_input_panels: input.surface=%08x", (int)shell->text_input.surface); - - shell->showing_input_panels = true; - - /* if ico_window_mgr hook, call hook routine */ - if (shell_hook_show_layer) { - (*shell_hook_show_layer)(LAYER_TYPE_INPUTPANEL, 1, data); - return; - } - if (!shell->locked) - wl_list_insert(&shell->panel_layer.link, - &shell->input_panel_layer.link); - - wl_list_for_each_safe(surface, next, - &shell->input_panel.surfaces, link) { - ws = surface->surface; - if (!ws->buffer_ref.buffer) - continue; - if (! shell_hook_configure) { - wl_list_insert(&shell->input_panel_layer.surface_list, - &ws->layer_link); - } - weston_surface_geometry_dirty(ws); - weston_surface_update_transform(ws); - weston_surface_damage(ws); - weston_slide_run(ws, ws->geometry.height, 0, NULL, NULL); - } -} - -static void -hide_input_panels(struct wl_listener *listener, void *data) -{ - struct desktop_shell *shell = - container_of(listener, struct desktop_shell, - hide_input_panel_listener); - struct weston_surface *surface, *next; - - if (!shell->showing_input_panels) - return; - - uifw_debug("hide_input_panels: input.surface=%08x", (int)shell->text_input.surface); - - shell->showing_input_panels = false; - - /* if ico_window_mgr hook, call hook routine */ - if (shell_hook_show_layer) { - (*shell_hook_show_layer)(LAYER_TYPE_INPUTPANEL, 0, NULL); - return; - } - - if (!shell->locked) - wl_list_remove(&shell->input_panel_layer.link); - - wl_list_for_each_safe(surface, next, - &shell->input_panel_layer.surface_list, layer_link) - weston_surface_unmap(surface); -} - -static void -update_input_panels(struct wl_listener *listener, void *data) -{ - struct desktop_shell *shell = - container_of(listener, struct desktop_shell, - update_input_panel_listener); - - memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t)); -} - -static void -center_on_output(struct weston_surface *surface, struct weston_output *output) +center_on_output(struct weston_view *view, struct weston_output *output) { int32_t surf_x, surf_y, width, height; float x, y; - surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y, &width, &height); + surface_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y, &width, &height); x = output->x + (output->width - width) / 2 - surf_x / 2; y = output->y + (output->height - height) / 2 - surf_y / 2; - uifw_debug("center_on_output: %08x x/y=%d/%d w/h=%d/%d", - (int)output, (int)x, (int)y, width, height); - weston_surface_configure(surface, x, y, width, height); + weston_view_set_position(view, x, y); } static void -weston_surface_set_initial_position (struct weston_surface *surface, - struct desktop_shell *shell) +weston_view_set_initial_position(struct weston_view *view, + struct desktop_shell *shell) { struct weston_compositor *compositor = shell->compositor; int ix = 0, iy = 0; @@ -3781,9 +4752,8 @@ weston_surface_set_initial_position (struct weston_surface *surface, } if (!target_output) { - weston_surface_set_position(surface, 10 + random() % 400, - 10 + random() % 400); - uifw_debug("weston_surface_set_initial_position: no tagret"); + weston_view_set_position(view, 10 + random() % 400, + 10 + random() % 400); return; } @@ -3792,140 +4762,119 @@ weston_surface_set_initial_position (struct weston_surface *surface, * output. */ panel_height = get_output_panel_height(shell, target_output); - range_x = target_output->width - surface->geometry.width; + range_x = target_output->width - view->surface->width; range_y = (target_output->height - panel_height) - - surface->geometry.height; + view->surface->height; - if (range_x > 0) { + if (range_x > 0) dx = random() % range_x; - } - else { + else dx = 0; - } - if (range_y > 0) { + + if (range_y > 0) dy = panel_height + random() % range_y; - } - else { + else dy = panel_height; - } + x = target_output->x + dx; y = target_output->y + dy; - weston_surface_set_position (surface, x, y); + weston_view_set_position(view, x, y); } static void -map(struct desktop_shell *shell, struct weston_surface *surface, - int32_t width, int32_t height, int32_t sx, int32_t sy) +map(struct desktop_shell *shell, struct shell_surface *shsurf, + int32_t sx, int32_t sy) { struct weston_compositor *compositor = shell->compositor; - struct shell_surface *shsurf = get_shell_surface(surface); - enum shell_surface_type surface_type = shsurf->type; - struct weston_surface *parent; struct weston_seat *seat; - struct workspace *ws; int panel_height = 0; int32_t surf_x, surf_y; - uifw_trace("map: %08x sx/sy=%d/%d w/h=%d/%d type=%d", - (int)surface, sx, sy, width, height, (int)surface_type); - - surface->geometry.width = width; - surface->geometry.height = height; - weston_surface_geometry_dirty(surface); - /* initial positioning, see also configure() */ - - switch (surface_type) { + switch (shsurf->type) { case SHELL_SURFACE_TOPLEVEL: - uifw_debug("map: surface TOPLEVEL"); - weston_surface_set_initial_position(surface, shell); - break; - case SHELL_SURFACE_FULLSCREEN: - uifw_debug("map: surface FULLSCREEN"); - center_on_output(surface, shsurf->fullscreen_output); - shell_map_fullscreen(shsurf); - break; - case SHELL_SURFACE_MAXIMIZED: - uifw_debug("map: surface MAXIMIZED"); - /* use surface configure to set the geometry */ - panel_height = get_output_panel_height(shell,surface->output); - surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y, - NULL, NULL); - weston_surface_set_position(surface, shsurf->output->x - surf_x, - shsurf->output->y + panel_height - surf_y); + if (shsurf->state.fullscreen) { + center_on_output(shsurf->view, shsurf->fullscreen_output); + shell_map_fullscreen(shsurf); + } else if (shsurf->state.maximized) { + /* use surface configure to set the geometry */ + panel_height = get_output_panel_height(shell, shsurf->output); + surface_subsurfaces_boundingbox(shsurf->surface, + &surf_x, &surf_y, NULL, NULL); + weston_view_set_position(shsurf->view, + shsurf->output->x - surf_x, + shsurf->output->y + + panel_height - surf_y); + } else if (!shsurf->state.relative) { + weston_view_set_initial_position(shsurf->view, shell); + } break; case SHELL_SURFACE_POPUP: - uifw_debug("map: surface POPUP"); shell_map_popup(shsurf); break; case SHELL_SURFACE_NONE: - uifw_debug("map: surface NONE"); if (shsurf->layertype == LAYER_TYPE_INPUTPANEL) { - weston_surface_set_initial_position(surface, shell); + weston_view_set_initial_position(shsurf->view, shell); } else { - weston_surface_set_position(surface, - surface->geometry.x + sx, - surface->geometry.y + sy); + weston_view_set_position(shsurf->view, + shsurf->view->geometry.x + sx, + shsurf->view->geometry.y + sy); } break; + case SHELL_SURFACE_XWAYLAND: default: - uifw_debug("map: surface unknown type(%d)", surface_type); ; } - - /* surface stacking order, see also activate() */ - switch (surface_type) { - case SHELL_SURFACE_POPUP: - case SHELL_SURFACE_TRANSIENT: - parent = shsurf->parent; - wl_list_insert(parent->layer_link.prev, &surface->layer_link); - break; - case SHELL_SURFACE_FULLSCREEN: - case SHELL_SURFACE_NONE: - break; - case SHELL_SURFACE_XWAYLAND: - default: - ws = get_current_workspace(shell); - wl_list_insert(&ws->layer.surface_list, &surface->layer_link); - break; + + /* Surface stacking order, see also activate(). */ + shell_surface_update_layer(shsurf); + + if (shsurf->type != SHELL_SURFACE_NONE) { + weston_view_update_transform(shsurf->view); + if (shsurf->state.maximized) { + shsurf->surface->output = shsurf->output; + shsurf->view->output = shsurf->output; + } } - if (surface_type != SHELL_SURFACE_NONE) { - weston_surface_update_transform(surface); - if (surface_type == SHELL_SURFACE_MAXIMIZED) - surface->output = shsurf->output; + if ((shsurf->type == SHELL_SURFACE_XWAYLAND || shsurf->state.relative) && + shsurf->transient.flags == WL_SHELL_SURFACE_TRANSIENT_INACTIVE) { } - switch (surface_type) { + switch (shsurf->type) { /* XXX: xwayland's using the same fields for transient type */ case SHELL_SURFACE_XWAYLAND: - case SHELL_SURFACE_TRANSIENT: if (shsurf->transient.flags == WL_SHELL_SURFACE_TRANSIENT_INACTIVE) break; case SHELL_SURFACE_TOPLEVEL: - case SHELL_SURFACE_FULLSCREEN: - case SHELL_SURFACE_MAXIMIZED: - if (!shell->locked) { - wl_list_for_each(seat, &compositor->seat_list, link) - activate(shell, surface, seat); - } + if (shsurf->state.relative && + shsurf->transient.flags == WL_SHELL_SURFACE_TRANSIENT_INACTIVE) + break; + if (shell->locked) + break; + wl_list_for_each(seat, &compositor->seat_list, link) + activate(shell, shsurf->surface, seat); break; + case SHELL_SURFACE_POPUP: + case SHELL_SURFACE_NONE: default: break; } - if (surface_type == SHELL_SURFACE_TOPLEVEL) + if (shsurf->type == SHELL_SURFACE_TOPLEVEL && + !shsurf->state.maximized && !shsurf->state.fullscreen) { switch (shell->win_animation_type) { case ANIMATION_FADE: - weston_fade_run(surface, 0.0, 1.0, 300.0, NULL, NULL); + weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL); break; case ANIMATION_ZOOM: - weston_zoom_run(surface, 0.5, 1.0, NULL, NULL); + weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL); break; + case ANIMATION_NONE: default: break; } @@ -3933,55 +4882,48 @@ map(struct desktop_shell *shell, struct weston_surface *surface, /* if ico_window_mgr hook, call hook routine */ if (shell_hook_map) { - sx = surface->geometry.x; - sy = surface->geometry.y; - (*shell_hook_map)(surface, &width, &height, &sx, &sy); + sx = shsurf->view->geometry.x; + sy = shsurf->view->geometry.y; + (*shell_hook_map)(shsurf->surface, + &shsurf->surface->width, &shsurf->surface->height, &sx, &sy); } if (shell_hook_configure) { - (*shell_hook_configure)(surface); /* send event to manager */ + (*shell_hook_configure)(shsurf->surface); /* send event to manager */ } } static void configure(struct desktop_shell *shell, struct weston_surface *surface, - float x, float y, int32_t width, int32_t height) + float x, float y) { - enum shell_surface_type surface_type = SHELL_SURFACE_NONE; struct shell_surface *shsurf; - int32_t surf_x, surf_y; + struct weston_view *view; + int32_t mx, my, surf_x, surf_y; shsurf = get_shell_surface(surface); - if (shsurf) - surface_type = shsurf->type; - uifw_trace("configure: %08x x/y=%d/%d w/h=%d/%d", - (int)surface, (int)x, (int)y, width, height); - weston_surface_configure(surface, x, y, width, height); + assert(shsurf); - switch (surface_type) { - case SHELL_SURFACE_FULLSCREEN: - shell_stack_fullscreen(shsurf); + if (shsurf->state.fullscreen) shell_configure_fullscreen(shsurf); - break; - case SHELL_SURFACE_MAXIMIZED: + else if (shsurf->state.maximized) { /* setting x, y and using configure to change that geometry */ surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y, NULL, NULL); - surface->geometry.x = surface->output->x - surf_x; - surface->geometry.y = surface->output->y + - get_output_panel_height(shell,surface->output) - surf_y; - break; - case SHELL_SURFACE_TOPLEVEL: - break; - default: - break; + mx = shsurf->output->x - surf_x; + my = shsurf->output->y + + get_output_panel_height(shell,shsurf->output) - surf_y; + weston_view_set_position(shsurf->view, mx, my); + } else { + weston_view_set_position(shsurf->view, x, y); } /* XXX: would a fullscreen surface need the same handling? */ if (surface->output) { - weston_surface_update_transform(surface); + wl_list_for_each(view, &surface->views, surface_link) + weston_view_update_transform(view); - if (surface_type == SHELL_SURFACE_MAXIMIZED) + if (shsurf->state.maximized) surface->output = shsurf->output; } @@ -3992,47 +4934,60 @@ configure(struct desktop_shell *shell, struct weston_surface *surface, } static void -shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height) +shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy) { struct shell_surface *shsurf = get_shell_surface(es); - struct desktop_shell *shell = shsurf->shell; - + struct desktop_shell *shell; int type_changed = 0; + assert(shsurf); + + shell = shsurf->shell; + if (!weston_surface_is_mapped(es) && !wl_list_empty(&shsurf->popup.grab_link)) { remove_popup_grab(shsurf); } - if (width == 0) + if (es->width == 0) return; - if (shsurf->next_type != SHELL_SURFACE_NONE && - shsurf->type != shsurf->next_type) { + if (shsurf->state_changed) { set_surface_type(shsurf); type_changed = 1; } if (!weston_surface_is_mapped(es)) { - map(shell, es, width, height, sx, sy); + map(shell, shsurf, sx, sy); } else if (type_changed || sx != 0 || sy != 0 || - es->geometry.width != width || - es->geometry.height != height) { + shsurf->last_width != es->width || + shsurf->last_height != es->height) { + shsurf->last_width = es->width; + shsurf->last_height = es->height; float from_x, from_y; float to_x, to_y; - weston_surface_to_global_float(es, 0, 0, &from_x, &from_y); - weston_surface_to_global_float(es, sx, sy, &to_x, &to_y); - uifw_trace("shell_surface_configure: configure %08x x/y=%d/%d w/h=%d/%d", - (int)es, (int)(es->geometry.x + to_x - from_x), - (int)(es->geometry.y + to_y - from_y), width, height); + weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y); + weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y); configure(shell, es, - es->geometry.x + to_x - from_x, - es->geometry.y + to_y - from_y, - width, height); + shsurf->view->geometry.x + to_x - from_x, + shsurf->view->geometry.y + to_y - from_y); } } +static void +shell_surface_output_destroyed(struct weston_surface *es) +{ + struct shell_surface *shsurf = get_shell_surface(es); + + assert(shsurf); + + shsurf->saved_position_valid = false; + shsurf->next_state.maximized = false; + shsurf->next_state.fullscreen = false; + shsurf->state_changed = true; +} + static void launch_desktop_shell_process(void *data); static void @@ -4054,36 +5009,50 @@ desktop_shell_sigchld(struct weston_process *process, int status) shell->child.deathcount++; if (shell->child.deathcount > 5) { - weston_log("%s died, giving up.\n", shell_exe); + weston_log("%s died, giving up.\n", shell->client); return; } - weston_log("%s died, respawning...\n", shell_exe); + weston_log("%s died, respawning...\n", shell->client); launch_desktop_shell_process(shell); shell_fade_startup(shell); } static void +desktop_shell_client_destroy(struct wl_listener *listener, void *data) +{ + struct desktop_shell *shell; + + shell = container_of(listener, struct desktop_shell, + child.client_destroy_listener); + + shell->child.client = NULL; +} + +static void launch_desktop_shell_process(void *data) { struct desktop_shell *shell = data; - /* shell program path configurable for ico-ivi */ - /* const char *shell_exe = LIBEXECDIR "/weston-desktop-shell"; */ - if ((shell_exe[0] == 0) || (shell_exe[0] == ' ')) { + /* if shell client(ex. desktop-shell) not exsit, not launch */ + if ((shell->client == NULL) || (shell->client[0] == 0) || (shell->client[0] == ' ')) { weston_log("no shell program\n"); } else { - uifw_trace("launch_desktop_shell_process: launch %s", shell_exe); + uifw_trace("launch_desktop_shell_process: launch %s", shell->client); shell->child.client = weston_client_launch(shell->compositor, - &shell->child.process, - shell_exe, - desktop_shell_sigchld); + &shell->child.process, + shell->client, + desktop_shell_sigchld); if (!shell->child.client) - weston_log("not able to start %s\n", shell_exe); + weston_log("not able to start %s\n", shell->client); else - weston_log("shell %s started\n", shell_exe); + weston_log("shell %s started\n", shell->client); + shell->child.client_destroy_listener.notify = + desktop_shell_client_destroy; + wl_client_add_destroy_listener(shell->child.client, + &shell->child.client_destroy_listener); } } @@ -4105,13 +5074,31 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) } static void +bind_xdg_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + struct desktop_shell *shell = data; + struct wl_resource *resource; + + resource = wl_resource_create(client, &xdg_shell_interface, 1, id); + if (resource) + wl_resource_set_dispatcher(resource, + xdg_shell_unversioned_dispatch, + NULL, shell, NULL); + + /* if ico_window_mgr hook, call hook routine */ + if (shell_hook_bind) { + (*shell_hook_bind)(client, data); + } +} + +static void unbind_desktop_shell(struct wl_resource *resource) { struct desktop_shell *shell = wl_resource_get_user_data(resource); /* if ico_window_mgr hook, call hook routine */ if (shell_hook_unbind) { - (*shell_hook_unbind)(resource->client); + (*shell_hook_unbind)(wl_resource_get_client(resource)); } if (shell->locked) @@ -4142,7 +5129,6 @@ bind_desktop_shell(struct wl_client *client, return; } -weston_log("bind_desktop_shell: client=%08x shell=%08x\n", (int)client, (int)shell->child.client); wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "permission to bind desktop_shell denied"); @@ -4150,23 +5136,25 @@ weston_log("bind_desktop_shell: client=%08x shell=%08x\n", (int)client, (int)she } static void -screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height) +screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy) { struct desktop_shell *shell = surface->configure_private; + struct weston_view *view; - if (width == 0) + if (surface->width == 0) return; /* XXX: starting weston-screensaver beforehand does not work */ if (!shell->locked) return; - center_on_output(surface, surface->output); + view = container_of(surface->views.next, struct weston_view, surface_link); + center_on_output(view, surface->output); - if (wl_list_empty(&surface->layer_link)) { - wl_list_insert(shell->lock_layer.surface_list.prev, - &surface->layer_link); - weston_surface_update_transform(surface); + if (wl_list_empty(&view->layer_link)) { + wl_list_insert(shell->lock_layer.view_list.prev, + &view->layer_link); + weston_view_update_transform(view); wl_event_source_timer_update(shell->screensaver.timer, shell->screensaver.duration); shell_fade(shell, FADE_IN); @@ -4183,6 +5171,12 @@ screensaver_set_surface(struct wl_client *client, struct weston_surface *surface = wl_resource_get_user_data(surface_resource); struct weston_output *output = wl_resource_get_user_data(output_resource); + struct weston_view *view, *next; + + /* Make sure we only have one view */ + wl_list_for_each_safe(view, next, &surface->views, surface_link) + weston_view_destroy(view); + weston_view_create(surface); surface->configure = screensaver_configure; surface->configure_private = shell; @@ -4223,282 +5217,6 @@ bind_screensaver(struct wl_client *client, wl_resource_destroy(resource); } -static void -input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height) -{ - struct input_panel_surface *ip_surface = surface->configure_private; - struct desktop_shell *shell = ip_surface->shell; - float x, y; - uint32_t show_surface = 0; - - if (width == 0) { - uifw_debug("input_panel_configure: configure %08x width=0, Skip", (int)surface); - return; - } - if (!weston_surface_is_mapped(surface)) { - if (!shell->showing_input_panels) { - uifw_debug("input_panel_configure: configure %08x not show, Skip", (int)surface); - return; - } - show_surface = 1; - } - - if (ip_surface->panel) { - x = shell->text_input.surface->geometry.x + shell->text_input.cursor_rectangle.x2; - y = shell->text_input.surface->geometry.y + shell->text_input.cursor_rectangle.y2; - } else { - x = ip_surface->output->x + (ip_surface->output->width - width) / 2; - y = ip_surface->output->y + ip_surface->output->height - height; - if (! shell_hook_map) { - y -= 132.0f; - } - } - - uifw_debug("input_panel_configure: configure %08x x/y=%d/%d w/h=%d/%d", - (int)surface, (int)x, (int)y, width, height); - weston_surface_configure(surface, - x, y, - width, height); - - if (show_surface) { - /* if ico_window_mgr hook, call hook routine */ - if (! shell_hook_configure) { - wl_list_insert(&shell->input_panel_layer.surface_list, - &surface->layer_link); - } - weston_surface_update_transform(surface); - weston_surface_damage(surface); - weston_slide_run(surface, surface->geometry.height, 0, NULL, NULL); - } - - /* if ico_window_mgr hook, call hook routine */ - /* set default color and shader because weston original bug(some time crash weston) */ - weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); - if (shell_hook_map) { - int wx, wy; - wx = (int)x; - wy = (int)y; - (*shell_hook_map)(surface, &width, &height, &wx, &wy); - } - if (shell_hook_configure) { - (*shell_hook_configure)(surface); - } -} - -static void -destroy_input_panel_surface(struct input_panel_surface *input_panel_surface) -{ - uifw_debug("destroy_input_panel_surface: "); - if (shell_hook_create) { - return; - } - - wl_signal_emit(&input_panel_surface->destroy_signal, input_panel_surface); - - wl_list_remove(&input_panel_surface->surface_destroy_listener.link); - wl_list_remove(&input_panel_surface->link); - - input_panel_surface->surface->configure = NULL; - - free(input_panel_surface); -} - -static struct input_panel_surface * -get_input_panel_surface(struct weston_surface *surface) -{ - if (surface->configure == input_panel_configure) { - return surface->configure_private; - } else { - return NULL; - } -} - -static void -input_panel_handle_surface_destroy(struct wl_listener *listener, void *data) -{ - uifw_debug("input_panel_handle_surface_destroy: "); - if (shell_hook_create) { - return; - } - - struct input_panel_surface *ipsurface = container_of(listener, - struct input_panel_surface, - surface_destroy_listener); - - if (ipsurface->resource) { - wl_resource_destroy(ipsurface->resource); - } else { - destroy_input_panel_surface(ipsurface); - } -} - -static struct input_panel_surface * -create_input_panel_surface(struct desktop_shell *shell, - struct weston_surface *surface) -{ - uifw_debug("create_input_panel_surface: "); - if (shell_hook_create) { - return NULL; - } - - struct input_panel_surface *input_panel_surface; - - input_panel_surface = calloc(1, sizeof *input_panel_surface); - if (!input_panel_surface) - return NULL; - - surface->configure = input_panel_configure; - surface->configure_private = input_panel_surface; - - input_panel_surface->shell = shell; - - input_panel_surface->surface = surface; - - wl_signal_init(&input_panel_surface->destroy_signal); - input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy; - wl_signal_add(&surface->destroy_signal, - &input_panel_surface->surface_destroy_listener); - - wl_list_init(&input_panel_surface->link); - - return input_panel_surface; -} - -static void -input_panel_surface_set_toplevel(struct wl_client *client, - struct wl_resource *resource, - struct wl_resource *output_resource, - uint32_t position) -{ - uifw_debug("input_panel_surface_set_toplevel: "); - if (shell_hook_create) { - return; - } - - struct input_panel_surface *input_panel_surface = - wl_resource_get_user_data(resource); - struct desktop_shell *shell = input_panel_surface->shell; - - wl_list_insert(&shell->input_panel.surfaces, - &input_panel_surface->link); - - input_panel_surface->output = wl_resource_get_user_data(output_resource); - input_panel_surface->panel = 0; -} - -static void -input_panel_surface_set_overlay_panel(struct wl_client *client, - struct wl_resource *resource) -{ - uifw_debug("input_panel_surface_set_overlay_panel: "); - if (shell_hook_create) { - return; - } - - struct input_panel_surface *input_panel_surface = - wl_resource_get_user_data(resource); - struct desktop_shell *shell = input_panel_surface->shell; - - wl_list_insert(&shell->input_panel.surfaces, - &input_panel_surface->link); - - input_panel_surface->panel = 1; -} - -static const struct wl_input_panel_surface_interface input_panel_surface_implementation = { - input_panel_surface_set_toplevel, - input_panel_surface_set_overlay_panel -}; - -static void -destroy_input_panel_surface_resource(struct wl_resource *resource) -{ - struct input_panel_surface *ipsurf = - wl_resource_get_user_data(resource); - - destroy_input_panel_surface(ipsurf); -} - -static void -input_panel_get_input_panel_surface(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - if (shell_hook_create) { - uifw_debug("input_panel_get_input_panel_surface: weston_surface=%08x", - (int)wl_resource_get_user_data(surface_resource)); - - shell_get_shell_surface_layertype(LAYER_TYPE_INPUTPANEL, - client, resource, id, surface_resource); - } - else { - struct weston_surface *surface = - wl_resource_get_user_data(surface_resource); - struct desktop_shell *shell = wl_resource_get_user_data(resource); - struct input_panel_surface *ipsurf; - - if (get_input_panel_surface(surface)) { - wl_resource_post_error(surface_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "wl_input_panel::get_input_panel_surface already requested"); - return; - } - - ipsurf = create_input_panel_surface(shell, surface); - if (!ipsurf) { - wl_resource_post_error(surface_resource, - WL_DISPLAY_ERROR_INVALID_OBJECT, - "surface->configure already set"); - return; - } - uifw_debug("input_panel_get_input_panel_surface: weston_surface=%08x", (int)surface); - - ipsurf->resource = - wl_resource_create(client, - &wl_input_panel_surface_interface, 1, id); - wl_resource_set_implementation(ipsurf->resource, - &input_panel_surface_implementation, - ipsurf, - destroy_input_panel_surface_resource); - } -} - -static const struct wl_input_panel_interface input_panel_implementation = { - input_panel_get_input_panel_surface -}; - -static void -unbind_input_panel(struct wl_resource *resource) -{ - struct desktop_shell *shell = wl_resource_get_user_data(resource); - - shell->input_panel.binding = NULL; -} - -static void -bind_input_panel(struct wl_client *client, - void *data, uint32_t version, uint32_t id) -{ - struct desktop_shell *shell = data; - struct wl_resource *resource; - - resource = wl_resource_create(client, - &wl_input_panel_interface, 1, id); - - if (shell->input_panel.binding == NULL) { - wl_resource_set_implementation(resource, - &input_panel_implementation, - shell, unbind_input_panel); - shell->input_panel.binding = resource; - return; - } - - wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, - "interface object already bound"); - wl_resource_destroy(resource); -} - struct switcher { struct desktop_shell *shell; struct weston_surface *current; @@ -4509,33 +5227,30 @@ struct switcher { static void switcher_next(struct switcher *switcher) { - struct weston_surface *surface; + struct weston_view *view; struct weston_surface *first = NULL, *prev = NULL, *next = NULL; struct shell_surface *shsurf; struct workspace *ws = get_current_workspace(switcher->shell); - wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { - switch (get_shell_surface_type(surface)) { - case SHELL_SURFACE_TOPLEVEL: - case SHELL_SURFACE_FULLSCREEN: - case SHELL_SURFACE_MAXIMIZED: + wl_list_for_each(view, &ws->layer.view_list, layer_link) { + shsurf = get_shell_surface(view->surface); + if (shsurf && + shsurf->type == SHELL_SURFACE_TOPLEVEL && + shsurf->parent == NULL) { if (first == NULL) - first = surface; + first = view->surface; if (prev == switcher->current) - next = surface; - prev = surface; - surface->alpha = 0.25; - weston_surface_geometry_dirty(surface); - weston_surface_damage(surface); - break; - default: - break; + next = view->surface; + prev = view->surface; + view->alpha = 0.25; + weston_view_geometry_dirty(view); + weston_surface_damage(view->surface); } - if (is_black_surface(surface, NULL)) { - surface->alpha = 0.25; - weston_surface_geometry_dirty(surface); - weston_surface_damage(surface); + if (is_black_surface(view->surface, NULL)) { + view->alpha = 0.25; + weston_view_geometry_dirty(view); + weston_surface_damage(view->surface); } } @@ -4549,11 +5264,12 @@ switcher_next(struct switcher *switcher) wl_signal_add(&next->destroy_signal, &switcher->listener); switcher->current = next; - next->alpha = 1.0; + wl_list_for_each(view, &next->views, surface_link) + view->alpha = 1.0; shsurf = get_shell_surface(switcher->current); - if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN) - shsurf->fullscreen.black_surface->alpha = 1.0; + if (shsurf && shsurf->state.fullscreen) + shsurf->fullscreen.black_view->alpha = 1.0; } static void @@ -4568,13 +5284,16 @@ switcher_handle_surface_destroy(struct wl_listener *listener, void *data) static void switcher_destroy(struct switcher *switcher) { - struct weston_surface *surface; + struct weston_view *view; struct weston_keyboard *keyboard = switcher->grab.keyboard; struct workspace *ws = get_current_workspace(switcher->shell); - wl_list_for_each(surface, &ws->layer.surface_list, layer_link) { - surface->alpha = 1.0; - weston_surface_damage(surface); + wl_list_for_each(view, &ws->layer.view_list, layer_link) { + if (is_focus_view(view)) + continue; + + view->alpha = 1.0; + weston_surface_damage(view->surface); } if (switcher->current) @@ -4911,25 +5630,91 @@ workspace_move_surface_down_binding(struct weston_seat *seat, uint32_t time, } static void +handle_output_destroy(struct wl_listener *listener, void *data) +{ + struct shell_output *output_listener = + container_of(listener, struct shell_output, destroy_listener); + + wl_list_remove(&output_listener->destroy_listener.link); + wl_list_remove(&output_listener->link); + free(output_listener); +} + +static void +create_shell_output(struct desktop_shell *shell, + struct weston_output *output) +{ + struct shell_output *shell_output; + + shell_output = zalloc(sizeof *shell_output); + if (shell_output == NULL) + return; + + shell_output->output = output; + shell_output->shell = shell; + shell_output->destroy_listener.notify = handle_output_destroy; + wl_signal_add(&output->destroy_signal, + &shell_output->destroy_listener); + wl_list_insert(shell->output_list.prev, &shell_output->link); +} + +static void +handle_output_create(struct wl_listener *listener, void *data) +{ + struct desktop_shell *shell = + container_of(listener, struct desktop_shell, output_create_listener); + struct weston_output *output = (struct weston_output *)data; + + create_shell_output(shell, output); +} + +static void +setup_output_destroy_handler(struct weston_compositor *ec, + struct desktop_shell *shell) +{ + struct weston_output *output; + + wl_list_init(&shell->output_list); + wl_list_for_each(output, &ec->output_list, link) + create_shell_output(shell, output); + + shell->output_create_listener.notify = handle_output_create; + wl_signal_add(&ec->output_created_signal, + &shell->output_create_listener); +} + +static void shell_destroy(struct wl_listener *listener, void *data) { struct desktop_shell *shell = container_of(listener, struct desktop_shell, destroy_listener); struct workspace **ws; + struct shell_output *shell_output, *tmp; + /* Force state to unlocked so we don't try to fade */ + shell->locked = false; if (shell->child.client) wl_client_destroy(shell->child.client); wl_list_remove(&shell->idle_listener.link); wl_list_remove(&shell->wake_listener.link); - wl_list_remove(&shell->show_input_panel_listener.link); - wl_list_remove(&shell->hide_input_panel_listener.link); + + input_panel_destroy(shell); + + wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) { + wl_list_remove(&shell_output->destroy_listener.link); + wl_list_remove(&shell_output->link); + free(shell_output); + } + + wl_list_remove(&shell->output_create_listener.link); wl_array_for_each(ws, &shell->workspaces.array) workspace_destroy(*ws); wl_array_release(&shell->workspaces.array); free(shell->screensaver.path); + free(shell->client); free(shell); } @@ -4962,11 +5747,18 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell) zoom_key_binding, NULL); weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod, zoom_key_binding, NULL); + weston_compositor_add_key_binding(ec, KEY_M, mod | MODIFIER_SHIFT, + maximize_binding, NULL); + weston_compositor_add_key_binding(ec, KEY_F, mod | MODIFIER_SHIFT, + fullscreen_binding, NULL); weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding, shell); weston_compositor_add_touch_binding(ec, mod, touch_move_binding, shell); weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod, resize_binding, shell); + weston_compositor_add_button_binding(ec, BTN_LEFT, + mod | MODIFIER_SHIFT, + resize_binding, shell); if (ec->capabilities & WESTON_CAP_ROTATION_ANY) weston_compositor_add_button_binding(ec, BTN_RIGHT, mod, @@ -4995,6 +5787,10 @@ shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell) workspace_move_surface_down_binding, shell); + if (shell->exposay_modifier) + weston_compositor_add_modifier_binding(ec, shell->exposay_modifier, + exposay_binding, shell); + /* Add bindings for mod+F[1-6] for workspace 1 to 6. */ if (shell->workspaces.num > 1) { num_workspace_bindings = shell->workspaces.num; @@ -5036,15 +5832,11 @@ module_init(struct weston_compositor *ec, wl_signal_add(&ec->idle_signal, &shell->idle_listener); shell->wake_listener.notify = wake_handler; wl_signal_add(&ec->wake_signal, &shell->wake_listener); - shell->show_input_panel_listener.notify = show_input_panels; - wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener); - shell->hide_input_panel_listener.notify = hide_input_panels; - wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener); - shell->update_input_panel_listener.notify = update_input_panels; - wl_signal_add(&ec->update_input_panel_signal, &shell->update_input_panel_listener); + ec->ping_handler = ping_handler; ec->shell_interface.shell = shell; ec->shell_interface.create_shell_surface = create_shell_surface; + ec->shell_interface.get_primary_view = get_primary_view; ec->shell_interface.set_toplevel = set_toplevel; ec->shell_interface.set_transient = set_transient; ec->shell_interface.set_fullscreen = set_fullscreen; @@ -5053,8 +5845,6 @@ module_init(struct weston_compositor *ec, ec->shell_interface.resize = surface_resize; ec->shell_interface.set_title = set_title; - wl_list_init(&shell->input_panel.surfaces); - weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link); weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link); weston_layer_init(&shell->background_layer, &shell->panel_layer.link); @@ -5064,8 +5854,14 @@ module_init(struct weston_compositor *ec, wl_array_init(&shell->workspaces.array); wl_list_init(&shell->workspaces.client_list); + if (input_panel_setup(shell) < 0) + return -1; + shell_configuration(shell); + shell->exposay.state_cur = EXPOSAY_LAYOUT_INACTIVE; + shell->exposay.state_target = EXPOSAY_TARGET_CANCEL; + for (i = 0; i < shell->workspaces.num; i++) { pws = wl_array_add(&shell->workspaces.array, sizeof *pws); if (pws == NULL) @@ -5085,6 +5881,10 @@ module_init(struct weston_compositor *ec, shell, bind_shell) == NULL) return -1; + if (wl_global_create(ec->wl_display, &xdg_shell_interface, 1, + shell, bind_xdg_shell) == NULL) + return -1; + if (wl_global_create(ec->wl_display, &desktop_shell_interface, 2, shell, bind_desktop_shell) == NULL) @@ -5094,16 +5894,14 @@ module_init(struct weston_compositor *ec, shell, bind_screensaver) == NULL) return -1; - if (wl_global_create(ec->wl_display, &wl_input_panel_interface, 1, - shell, bind_input_panel) == NULL) - return -1; - if (wl_global_create(ec->wl_display, &workspace_manager_interface, 1, shell, bind_workspace_manager) == NULL) return -1; shell->child.deathstamp = weston_compositor_get_time(); + setup_output_destroy_handler(ec, shell); + loop = wl_display_get_event_loop(ec->wl_display); wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell); @@ -5230,19 +6028,6 @@ ico_ivi_shell_layertype(struct weston_surface *surface) /*--------------------------------------------------------------------------*/ /** - * @brief ivi_shell_set_surface_initial_position: initialize surface position - * - * @param[in] surface weston surface - * @return none - */ -/*--------------------------------------------------------------------------*/ -WL_EXPORT void -ivi_shell_set_surface_initial_position(struct weston_surface *surface) -{ - weston_surface_set_initial_position (surface, _ico_ivi_shell); -} -/*--------------------------------------------------------------------------*/ -/** * @brief ivi_shell_set_default_display: set default display * * @param[in] inputpanel default display of input panel surface @@ -5293,9 +6078,8 @@ ico_ivi_shell_hook_unbind(void (*hook_unbind)(struct wl_client *client)) /*--------------------------------------------------------------------------*/ WL_EXPORT void ico_ivi_shell_hook_create(void (*hook_create)(int layertype, - struct wl_client *client, - struct wl_resource *resource, struct weston_surface *surface, + struct wl_client *client, struct shell_surface *shsurf)) { shell_hook_create = hook_create; diff --git a/src/ico_ivi_shell.h b/src/ico_ivi_shell.h new file mode 100644 index 0000000..fe437b8 --- /dev/null +++ b/src/ico_ivi_shell.h @@ -0,0 +1,222 @@ +/* + * Copyright © 2010-2012 Intel Corporation + * Copyright © 2011-2012 Collabora, Ltd. + * Copyright © 2013 Raspberry Pi Foundation + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +enum animation_type { + ANIMATION_NONE, + + ANIMATION_ZOOM, + ANIMATION_FADE, + ANIMATION_DIM_LAYER, +}; + +enum fade_type { + FADE_IN, + FADE_OUT +}; + +enum exposay_target_state { + EXPOSAY_TARGET_OVERVIEW, /* show all windows */ + EXPOSAY_TARGET_CANCEL, /* return to normal, same focus */ + EXPOSAY_TARGET_SWITCH, /* return to normal, switch focus */ +}; + +enum exposay_layout_state { + EXPOSAY_LAYOUT_INACTIVE = 0, /* normal desktop */ + EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE, /* in transition to normal */ + EXPOSAY_LAYOUT_OVERVIEW, /* show all windows */ + EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW, /* in transition to all windows */ +}; + +struct focus_surface { + struct weston_surface *surface; + struct weston_view *view; + struct weston_transform workspace_transform; +}; + +struct workspace { + struct weston_layer layer; + + struct wl_list focus_list; + struct wl_listener seat_destroyed_listener; + + struct focus_surface *fsurf_front; + struct focus_surface *fsurf_back; + struct weston_view_animation *focus_animation; +}; + +struct desktop_shell { + struct weston_compositor *compositor; + + struct wl_listener idle_listener; + struct wl_listener wake_listener; + struct wl_listener destroy_listener; + struct wl_listener show_input_panel_listener; + struct wl_listener hide_input_panel_listener; + struct wl_listener update_input_panel_listener; + + struct weston_layer fullscreen_layer; + struct weston_layer panel_layer; + struct weston_layer background_layer; + struct weston_layer lock_layer; + struct weston_layer input_panel_layer; + + struct wl_listener pointer_focus_listener; + struct weston_surface *grab_surface; + + struct { + struct weston_process process; + struct wl_client *client; + struct wl_resource *desktop_shell; + struct wl_listener client_destroy_listener; + + unsigned deathcount; + uint32_t deathstamp; + } child; + + bool locked; + bool showing_input_panels; + bool prepare_event_sent; + + struct { + struct weston_surface *surface; + pixman_box32_t cursor_rectangle; + } text_input; + + struct weston_surface *lock_surface; + struct wl_listener lock_surface_listener; + + struct { + struct wl_array array; + unsigned int current; + unsigned int num; + + struct wl_list client_list; + + struct weston_animation animation; + struct wl_list anim_sticky_list; + int anim_dir; + uint32_t anim_timestamp; + double anim_current; + struct workspace *anim_from; + struct workspace *anim_to; + } workspaces; + + struct { + char *path; + int duration; + struct wl_resource *binding; + struct weston_process process; + struct wl_event_source *timer; + } screensaver; + + struct { + struct wl_resource *binding; + struct wl_list surfaces; + } input_panel; + + struct { + struct weston_view *view; + struct weston_view_animation *animation; + enum fade_type type; + struct wl_event_source *startup_timer; + } fade; + + struct exposay { + /* XXX: Make these exposay_surfaces. */ + struct weston_view *focus_prev; + struct weston_view *focus_current; + struct weston_view *clicked; + struct workspace *workspace; + struct weston_seat *seat; + struct wl_list surface_list; + + struct weston_keyboard_grab grab_kbd; + struct weston_pointer_grab grab_ptr; + + enum exposay_target_state state_target; + enum exposay_layout_state state_cur; + int in_flight; /* number of animations still running */ + + int num_surfaces; + int grid_size; + int surface_size; + + int hpadding_outer; + int vpadding_outer; + int padding_inner; + + int row_current; + int column_current; + + bool mod_pressed; + bool mod_invalid; + } exposay; + + uint32_t binding_modifier; + uint32_t exposay_modifier; + enum animation_type win_animation_type; + enum animation_type startup_animation_type; + enum animation_type focus_animation_type; + + struct wl_listener output_create_listener; + struct wl_list output_list; + + char *client; +}; + +void +set_alpha_if_fullscreen(struct shell_surface *shsurf); + +struct weston_output * +get_default_output(struct weston_compositor *compositor); + +struct weston_view * +get_default_view(struct weston_surface *surface); + +struct shell_surface * +get_shell_surface(struct weston_surface *surface); + +struct workspace * +get_current_workspace(struct desktop_shell *shell); + +void +lower_fullscreen_layer(struct desktop_shell *shell); + +void +activate(struct desktop_shell *shell, struct weston_surface *es, + struct weston_seat *seat); + +void +exposay_binding(struct weston_seat *seat, + enum weston_keyboard_modifier modifier, + void *data); +int +input_panel_setup(struct desktop_shell *shell); +void +input_panel_destroy(struct desktop_shell *shell); diff --git a/src/ico_ivi_shell_private.h b/src/ico_ivi_shell_private.h index 03c346a..c2d4729 100644 --- a/src/ico_ivi_shell_private.h +++ b/src/ico_ivi_shell_private.h @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -24,7 +24,7 @@ /** * @brief Public functions in ico_ivi_shell Weston plugin * - * @date Jul-26-2013 + * @date Jan-30-2014 */ #ifndef _ICO_IVI_SHELL_PRIVATE_H_ @@ -38,9 +38,6 @@ struct shell_surface; enum shell_surface_type { SHELL_SURFACE_NONE, SHELL_SURFACE_TOPLEVEL, - SHELL_SURFACE_TRANSIENT, - SHELL_SURFACE_FULLSCREEN, - SHELL_SURFACE_MAXIMIZED, SHELL_SURFACE_POPUP, SHELL_SURFACE_XWAYLAND }; @@ -60,7 +57,7 @@ enum shell_surface_type { enum shell_fullscreen_control { SHELL_FULLSCREEN_ISTOP, SHELL_FULLSCREEN_SET, - SHELL_FULLSCREEN_STACK, + SHELL_FULLSCREEN_UNSET, SHELL_FULLSCREEN_CONF, SHELL_FULLSCREEN_HIDEALL }; @@ -74,15 +71,14 @@ void ico_ivi_shell_send_configure(struct weston_surface *surface, const uint32_t edges, const int width, const int height); void ico_ivi_shell_startup(void *shell); int ico_ivi_shell_layertype(struct weston_surface *surface); -void ivi_shell_set_surface_initial_position(struct weston_surface *surface); void ivi_shell_set_default_display(struct weston_output *inputpanel); /* Prototypr for hook routine */ void ico_ivi_shell_hook_bind(void (*hook_bind)(struct wl_client *client, void *shell)); void ico_ivi_shell_hook_unbind(void (*hook_unbind)(struct wl_client *client)); -void ico_ivi_shell_hook_create(void (*hook_create)(int layertype, struct wl_client *client, - struct wl_resource *resource, struct weston_surface *surface, - struct shell_surface *shsurf)); +void ico_ivi_shell_hook_create(void (*hook_create)(int layertype, + struct weston_surface *surface, + struct wl_client *client, struct shell_surface *shsurf)); void ico_ivi_shell_hook_destroy(void (*hook_destroy)(struct weston_surface *surface)); void ico_ivi_shell_hook_map(void (*hook_map)(struct weston_surface *surface, int32_t *width, int32_t *height, int32_t *sx, int32_t *sy)); @@ -95,5 +91,22 @@ void ico_ivi_shell_hook_move(void (*hook_move)(struct weston_surface *surface, void ico_ivi_shell_hook_show_layer(void (*hook_show)(int layertype, int show, void *data)); void ico_ivi_shell_hook_fullscreen(int (*hook_fullscreen) (int event, struct weston_surface *surface)); +struct weston_view *ico_input_panel_get_view(void *ipsurf); + +/* hook functions */ +extern void (*shell_hook_bind)(struct wl_client *client, void *shell); +extern void (*shell_hook_unbind)(struct wl_client *client); +extern void (*shell_hook_create)(int layertype, struct weston_surface *surface, + struct wl_client *client, + struct shell_surface *shsurf); +extern void (*shell_hook_destroy)(struct weston_surface *surface); +extern void (*shell_hook_map)(struct weston_surface *surface, int32_t *width, + int32_t *height, int32_t *sx, int32_t *sy); +extern void (*shell_hook_configure)(struct weston_surface *surface); +extern void (*shell_hook_select)(struct weston_surface *surface); +extern char *(*shell_hook_title)(struct weston_surface *surface, const char *title); +extern void (*shell_hook_move)(struct weston_surface *surface, int *dx, int *dy); +extern void (*shell_hook_show_layer)(int layertype, int show, void *data); +extern int (*shell_hook_fullscreen)(int event, struct weston_surface *surface); #endif /*_ICO_IVI_SHELL_PRIVATE_H_*/ diff --git a/src/ico_plugin_loader.c b/src/ico_plugin_loader.c index 3ef9346..ce081cd 100644 --- a/src/ico_plugin_loader.c +++ b/src/ico_plugin_loader.c @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided diff --git a/src/ico_plugin_version.h b/src/ico_plugin_version.h index 699a655..32c09f3 100644 --- a/src/ico_plugin_version.h +++ b/src/ico_plugin_version.h @@ -1 +1 @@ -#define ICO_PLUIGN_VERSION "0.9.12 (Jan-22-2014)" +#define ICO_PLUIGN_VERSION "0.9.14 (Feb-07-2014)" diff --git a/src/ico_window_animation.c b/src/ico_window_animation.c index 5e53bf6..5a4658f 100644 --- a/src/ico_window_animation.c +++ b/src/ico_window_animation.c @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -429,6 +429,7 @@ static void animation_end(struct uifw_win_surface *usurf, const int disp) { struct animation_data *animadata; + struct weston_view *ev; usurf->animation.state = ICO_WINDOW_MGR_ANIMATION_STATE_NONE; animadata = (struct animation_data *)usurf->animation.animadata; @@ -436,6 +437,7 @@ animation_end(struct uifw_win_surface *usurf, const int disp) if (animation_count > 0) { animation_count --; } + ev = ico_ivi_get_primary_view(usurf); if (animadata) { if (animadata->end_function) { @@ -446,7 +448,7 @@ animation_end(struct uifw_win_surface *usurf, const int disp) wl_list_remove(&animadata->transform.link); animadata->transform_set = 0; } - weston_surface_geometry_dirty(usurf->surface); + weston_view_geometry_dirty(ev); } if (disp) { usurf->restrain_configure = 0; @@ -460,7 +462,7 @@ animation_end(struct uifw_win_surface *usurf, const int disp) ico_window_mgr_set_visible(usurf, 1); weston_surface_damage(usurf->surface); } - weston_surface_geometry_dirty(usurf->surface); + weston_view_geometry_dirty(ev); ico_window_mgr_restack_layer(usurf); } usurf->animation.visible = ANIMA_NOCONTROL_AT_END; @@ -516,6 +518,7 @@ animation_slide(struct weston_animation *animation, { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; int dwidth, dheight; int par; int x; @@ -531,6 +534,7 @@ animation_slide(struct weston_animation *animation, } return; } + ev = ico_ivi_get_primary_view(usurf); par = usurf->animation.current; uifw_debug("animation_slide: %08x count=%d %d%% anima=%d state=%d", @@ -594,11 +598,11 @@ animation_slide(struct weston_animation *animation, uifw_debug("animation_slide: %08x %d%% %d/%d(target %d/%d)", usurf->surfaceid, par, x, y, usurf->x, usurf->y); - es->geometry.x = usurf->node_tbl->disp_x + x; - es->geometry.y = usurf->node_tbl->disp_y + y; - if ((es->output) && (es->buffer_ref.buffer) && - (es->geometry.width > 0) && (es->geometry.height > 0)) { - weston_surface_geometry_dirty(es); + ev->geometry.x = usurf->node_tbl->disp_x + x; + ev->geometry.y = usurf->node_tbl->disp_y + y; + if ((ev->output) && (es->buffer_ref.buffer) && + (es->width > 0) && (es->height > 0)) { + weston_view_geometry_dirty(ev); weston_surface_damage(es); } if (par >= 100) { @@ -628,6 +632,7 @@ animation_wipe(struct weston_animation *animation, { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; int par; int x; int y; @@ -644,6 +649,7 @@ animation_wipe(struct weston_animation *animation, } return; } + ev = ico_ivi_get_primary_view(usurf); par = usurf->animation.current; uifw_debug("animation_wipe: %08x count=%d %d%% anima=%d state=%d", @@ -707,12 +713,12 @@ animation_wipe(struct weston_animation *animation, } } - es->geometry.x = usurf->node_tbl->disp_x + x; - es->geometry.y = usurf->node_tbl->disp_y + y; - es->geometry.width = width; - es->geometry.height = height; - if ((es->output) && (es->buffer_ref.buffer)) { - weston_surface_geometry_dirty(es); + ev->geometry.x = usurf->node_tbl->disp_x + x; + ev->geometry.y = usurf->node_tbl->disp_y + y; + es->width = width; + es->height = height; + if ((ev->output) && (es->buffer_ref.buffer)) { + weston_view_geometry_dirty(ev); weston_surface_damage(es); } if (par >= 100) { @@ -742,6 +748,7 @@ animation_swing(struct weston_animation *animation, { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; struct animation_data *animadata; int par; int x; @@ -766,13 +773,14 @@ animation_swing(struct weston_animation *animation, animadata = (struct animation_data *)usurf->animation.animadata; es = usurf->surface; + ev = ico_ivi_get_primary_view(usurf); par = usurf->animation.current; if (animation->frame_counter == 1) { if (animadata->transform_set == 0) { animadata->transform_set = 1; weston_matrix_init(&animadata->transform.matrix); wl_list_init(&animadata->transform.link); - wl_list_insert(&es->geometry.transformation_list, + wl_list_insert(&ev->geometry.transformation_list, &animadata->transform.link); } animadata->end_function = animation_swing_end; @@ -834,8 +842,8 @@ animation_swing(struct weston_animation *animation, } } - es->geometry.x = usurf->node_tbl->disp_x + x; - es->geometry.y = usurf->node_tbl->disp_y + y; + ev->geometry.x = usurf->node_tbl->disp_x + x; + ev->geometry.y = usurf->node_tbl->disp_y + y; weston_matrix_init(&animadata->transform.matrix); weston_matrix_translate(&animadata->transform.matrix, -0.5f * usurf->width, -0.5f * usurf->height, 0); @@ -843,8 +851,8 @@ animation_swing(struct weston_animation *animation, weston_matrix_translate(&animadata->transform.matrix, 0.5f * usurf->width, 0.5f * usurf->height, 0); - if ((es->output) && (es->buffer_ref.buffer)) { - weston_surface_geometry_dirty(es); + if ((ev->output) && (es->buffer_ref.buffer)) { + weston_view_geometry_dirty(ev); weston_surface_damage(es); } if (par >= 100) { @@ -871,13 +879,15 @@ animation_swing_end(struct weston_animation *animation) { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; usurf = container_of(animation, struct uifw_win_surface, animation.animation); if (usurf && usurf->surface) { es = usurf->surface; - es->alpha = 1.0; + ev = ico_ivi_get_primary_view(usurf); + ev->alpha = 1.0; - if ((es->output) && (es->buffer_ref.buffer)) { + if ((ev->output) && (es->buffer_ref.buffer)) { weston_surface_damage(es); } } @@ -900,6 +910,7 @@ animation_fade(struct weston_animation *animation, struct uifw_win_surface *usurf; struct animation_data *animadata; struct weston_surface *es; + struct weston_view *ev; int par; usurf = container_of(animation, struct uifw_win_surface, animation.animation); @@ -915,13 +926,14 @@ animation_fade(struct weston_animation *animation, animadata = (struct animation_data *)usurf->animation.animadata; es = usurf->surface; + ev = ico_ivi_get_primary_view(usurf); par = usurf->animation.current; if (animation->frame_counter == 1) { if (animadata->transform_set == 0) { animadata->transform_set = 1; weston_matrix_init(&animadata->transform.matrix); wl_list_init(&animadata->transform.link); - wl_list_insert(&es->geometry.transformation_list, + wl_list_insert(&ev->geometry.transformation_list, &animadata->transform.link); } animadata->end_function = animation_fade_end; @@ -937,20 +949,20 @@ animation_fade(struct weston_animation *animation, if (usurf->animation.state == ICO_WINDOW_MGR_ANIMATION_STATE_SHOW) { /* fade in */ - es->alpha = ((float)par) / 100.0f; + ev->alpha = ((float)par) / 100.0f; } else if (usurf->animation.state == ICO_WINDOW_MGR_ANIMATION_STATE_HIDE) { /* fade out */ - es->alpha = 1.0f - (((float)par) / 100.0f); + ev->alpha = 1.0f - (((float)par) / 100.0f); } else { /* fade move/resize */ if ((par >= 50) || (usurf->animation.ahalf)) { - es->alpha = ((float)(par*2 - 100)) / 100.0f; + ev->alpha = ((float)(par*2 - 100)) / 100.0f; if (usurf->animation.ahalf == 0) { uifw_trace("animation_fade: fade move chaneg to show"); usurf->animation.ahalf = 1; - es->alpha = 0.0; + ev->alpha = 0.0; ico_window_mgr_set_weston_surface(usurf, usurf->x, usurf->y, usurf->width, usurf->height); ico_window_mgr_change_surface(usurf, @@ -959,18 +971,18 @@ animation_fade(struct weston_animation *animation, } } else { - es->alpha = 1.0f - (((float)(par*2)) / 100.0f); + ev->alpha = 1.0f - (((float)(par*2)) / 100.0f); } } - if (es->alpha < 0.0) es->alpha = 0.0; - else if (es->alpha > 1.0) es->alpha = 1.0; + if (ev->alpha < 0.0) ev->alpha = 0.0; + else if (ev->alpha > 1.0) ev->alpha = 1.0; uifw_debug("animation_fade: %08x count=%d %d%% alpha=%1.2f anima=%d state=%d", usurf->surfaceid, animation->frame_counter, par, - es->alpha, usurf->animation.anima, usurf->animation.state); + ev->alpha, usurf->animation.anima, usurf->animation.state); - if ((es->output) && (es->buffer_ref.buffer) && - (es->geometry.width > 0) && (es->geometry.height > 0)) { + if ((ev->output) && (es->buffer_ref.buffer) && + (es->width > 0) && (es->height > 0)) { weston_surface_damage(es); } if (par >= 100) { @@ -997,14 +1009,16 @@ animation_fade_end(struct weston_animation *animation) { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; usurf = container_of(animation, struct uifw_win_surface, animation.animation); if (usurf && usurf->surface) { es = usurf->surface; - es->alpha = 1.0; + ev = ico_ivi_get_primary_view(usurf); + ev->alpha = 1.0; - if ((es->output) && (es->buffer_ref.buffer) && - (es->geometry.width > 0) && (es->geometry.height > 0)) { + if ((ev->output) && (es->buffer_ref.buffer) && + (es->width > 0) && (es->height > 0)) { weston_surface_damage(es); } } @@ -1027,6 +1041,7 @@ animation_zoom(struct weston_animation *animation, struct uifw_win_surface *usurf; struct animation_data *animadata; struct weston_surface *es; + struct weston_view *ev; int par; float scalex, scaley; float fu, fa, fp; @@ -1045,13 +1060,14 @@ animation_zoom(struct weston_animation *animation, animadata = (struct animation_data *)usurf->animation.animadata; es = usurf->surface; + ev = ico_ivi_get_primary_view(usurf); par = usurf->animation.current; if (animation->frame_counter == 1) { if (animadata->transform_set == 0) { animadata->transform_set = 1; weston_matrix_init(&animadata->transform.matrix); wl_list_init(&animadata->transform.link); - wl_list_insert(&es->geometry.transformation_list, + wl_list_insert(&ev->geometry.transformation_list, &animadata->transform.link); } animadata->end_function = animation_zoom_end; @@ -1113,9 +1129,9 @@ animation_zoom(struct weston_animation *animation, (int)(usurf->height * scaley), usurf->height, usurf->animation.anima, usurf->animation.state); - if ((es->output) && (es->buffer_ref.buffer) && - (es->geometry.width > 0) && (es->geometry.height > 0)) { - weston_surface_geometry_dirty(es); + if ((ev->output) && (es->buffer_ref.buffer) && + (es->width > 0) && (es->height > 0)) { + weston_view_geometry_dirty(ev); weston_surface_damage(es); } if (par >= 100) { @@ -1142,14 +1158,16 @@ animation_zoom_end(struct weston_animation *animation) { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; usurf = container_of(animation, struct uifw_win_surface, animation.animation); if (usurf && usurf->surface) { es = usurf->surface; - es->alpha = 1.0; + ev = ico_ivi_get_primary_view(usurf); + ev->alpha = 1.0; - if ((es->output) && (es->buffer_ref.buffer) && - (es->geometry.width > 0) && (es->geometry.height > 0)) { + if ((ev->output) && (es->buffer_ref.buffer) && + (es->width > 0) && (es->height > 0)) { weston_surface_damage(es); } } diff --git a/src/ico_window_mgr.c b/src/ico_window_mgr.c index 11b35c2..11f634f 100644 --- a/src/ico_window_mgr.c +++ b/src/ico_window_mgr.c @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -252,9 +252,9 @@ static pid_t win_mgr_get_ppid(pid_t pid); /* get appid from pid */ static void win_mgr_get_client_appid(struct uifw_client *uclient); /* create new surface */ -static void win_mgr_register_surface( - int layertype, struct wl_client *client, struct wl_resource *resource, - struct weston_surface *surface, struct shell_surface *shsurf); +static void win_mgr_register_surface(int layertype, struct weston_surface *surface, + struct wl_client *client, + struct shell_surface *shsurf); /* surface destroy */ static void win_mgr_destroy_surface(struct weston_surface *surface); /* map new surface */ @@ -358,6 +358,9 @@ static int ico_win_mgr_send_to_mgr(const int event, struct uifw_win_surface *usu static int win_mgr_set_scale(struct uifw_win_surface *usurf); /* convert animation name to Id value */ static int ico_get_animation_name(const char *animation); + /* read surface pixels */ +static int ico_read_surface_pixels(struct weston_surface *es, pixman_format_code_t format, + void *pixels, int x, int y, int width, int height); /* hook for animation */ static int (*win_mgr_hook_animation)(const int op, void *data) = NULL; /* hook for input region */ @@ -536,6 +539,145 @@ ico_ivi_get_mynode(void) /*--------------------------------------------------------------------------*/ /** + * @brief ico_ivi_surface_buffer_width: get surface buffer width + * + * @param[in] es weston surface + * @return buffer width(if surface has no buffer, return 0) + */ +/*--------------------------------------------------------------------------*/ +WL_EXPORT int +ico_ivi_surface_buffer_width(struct weston_surface *es) +{ + int v; + + if (! es->buffer_ref.buffer) { + return 0; + } + if (es->buffer_viewport.viewport_set) { + return es->buffer_viewport.dst_width; + } + switch (es->buffer_viewport.transform) { + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + v = es->buffer_ref.buffer->height; + break; + default: + v = es->buffer_ref.buffer->width; + break; + } + return (v / es->buffer_viewport.scale); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ivi_surface_buffer_height: get surface buffer height + * + * @param[in] es weston surface + * @return buffer height(if surface has no buffer, return 0) + */ +/*--------------------------------------------------------------------------*/ +WL_EXPORT int +ico_ivi_surface_buffer_height(struct weston_surface *es) +{ + int v; + + if (! es->buffer_ref.buffer) { + return 0; + } + if (es->buffer_viewport.viewport_set) { + return es->buffer_viewport.dst_height; + } + switch (es->buffer_viewport.transform) { + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + v = es->buffer_ref.buffer->width; + break; + default: + v = es->buffer_ref.buffer->height; + break; + } + return (v / es->buffer_viewport.scale); +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ivi_surface_buffer_size: get surface buffer size + * + * @param[in] es weston surface + * @param[out] width buffer width + * @param[out] height buffer height + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +WL_EXPORT void +ico_ivi_surface_buffer_size(struct weston_surface *es, int *width, int *height) +{ + if (! es->buffer_ref.buffer) { + *width = 0; + *height = 0; + } + else if (es->buffer_viewport.viewport_set) { + *width = es->buffer_viewport.dst_width; + *height = es->buffer_viewport.dst_height; + } + else { + switch (es->buffer_viewport.transform) { + case WL_OUTPUT_TRANSFORM_90: + case WL_OUTPUT_TRANSFORM_270: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + *width = es->buffer_ref.buffer->height; + *height = es->buffer_ref.buffer->width; + break; + default: + *width = es->buffer_ref.buffer->width; + *height = es->buffer_ref.buffer->height; + break; + } + *width = *width / es->buffer_viewport.scale; + *height = *height / es->buffer_viewport.scale; + } +} + +/*--------------------------------------------------------------------------*/ +/** + * @brief ico_ivi_surface_buffer_size: get surface buffer size + * + * @param[in] es weston surface + * @param[out] width buffer width + * @param[out] height buffer height + * @return nothing + */ +/*--------------------------------------------------------------------------*/ +WL_EXPORT struct weston_view * +ico_ivi_get_primary_view(struct uifw_win_surface *usurf) +{ + struct weston_view *ev; + + if (usurf->layertype == LAYER_TYPE_INPUTPANEL) { + ev = ico_input_panel_get_view((void *)(usurf->shsurf)); + } + else { + ev = (*_ico_win_mgr->compositor->shell_interface.get_primary_view) + (NULL, usurf->shsurf); + } + if (! ev) { + uifw_error("ico_ivi_get_primary_view: usurf=%08x(%x) surface=%08x has no view", + (int)usurf, usurf->surfaceid, (int)usurf->surface); + } + else { + uifw_debug("ico_ivi_get_primary_view: %08x[%d] view=%08x view->surf=%08x", + usurf->surfaceid, usurf->layertype, (int)ev, (int)ev->surface); + } + return ev; +} + +/*--------------------------------------------------------------------------*/ +/** * @brief ico_window_mgr_set_weston_surface: set weston surface * * @param[in] usurf UIFW surface @@ -551,17 +693,17 @@ ico_window_mgr_set_weston_surface(struct uifw_win_surface *usurf, int x, int y, int width, int height) { struct weston_surface *es = usurf->surface; + struct weston_view *ev; int buf_width, buf_height; - if (es == NULL) { + if ((es == NULL) || (usurf->shsurf == NULL)) { uifw_trace("ico_window_mgr_set_weston_surface: usurf(%08x) has no surface", (int)usurf); return; } if (es->buffer_ref.buffer != NULL) { - buf_width = weston_surface_buffer_width(es); - buf_height = weston_surface_buffer_height(es); + ico_ivi_surface_buffer_size(es, &buf_width, &buf_height); if ((width <= 0) || (height <= 0)) { width = buf_width; usurf->width = buf_width; @@ -584,9 +726,11 @@ ico_window_mgr_set_weston_surface(struct uifw_win_surface *usurf, x = ICO_IVI_MAX_COORDINATE+1; y = ICO_IVI_MAX_COORDINATE+1; } - if ((es->geometry.x != x) || (es->geometry.y != y) || - (es->geometry.width != width) || (es->geometry.height != height)) { - weston_surface_damage_below(es); + ev = ico_ivi_get_primary_view(usurf); + if ((ev != NULL) && + (((int)ev->geometry.x != x) || ((int)ev->geometry.y != y) || + (es->width != width) || (es->height != height))) { + weston_view_damage_below(ev); win_mgr_surface_configure(usurf, x, y, width, height); } weston_surface_damage(es); @@ -1212,20 +1356,81 @@ ico_get_animation_name(const char *animation) /*--------------------------------------------------------------------------*/ /** + * @brief ico_read_surface_pixels: read surface pixel image + * this function inport from weston 1.3.1(by Tizen) + * + * @param[in] es weston surface + * @param[in] format pixel format + * @param[out] pixels pixel read buffer + * @param[in] x X coordinate + * @param[in] y Y coordinate + * @param[in] width width + * @param[in] height height + * @return success(=0) or error(-1) + */ +/*--------------------------------------------------------------------------*/ +static int +ico_read_surface_pixels(struct weston_surface *es, pixman_format_code_t format, + void *pixels, int x, int y, int width, int height) +{ + struct weston_buffer *buffer = es->buffer_ref.buffer; + struct uifw_gl_surface_state *gs = es->renderer_state; + GLenum gl_format; + int size; + struct wl_shm_buffer *shm_buffer = NULL; + GLuint fbo; + + switch (format) { + case PIXMAN_a8r8g8b8: + gl_format = GL_BGRA_EXT; + break; + case PIXMAN_a8b8g8r8: + gl_format = GL_RGBA; + break; + default: + return -1; + } + + if (buffer) { + shm_buffer = wl_shm_buffer_get(buffer->resource); + } + if (shm_buffer) { + size = buffer->width * 4 * buffer->height; + memcpy(pixels, wl_shm_buffer_get_data(shm_buffer), size); + } else if (gs != NULL) { + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, + gs->textures[0], 0); + + glReadPixels(x, y, width, height, + gl_format, GL_UNSIGNED_BYTE, pixels); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo); + } + else { + return -1; + } + return 0; +} + +/*--------------------------------------------------------------------------*/ +/** * @brief win_mgr_register_surface: create UIFW surface * * @param[in] layertype surface layer type - * @param[in] client Wayland client - * @param[in] resource client resource * @param[in] surface Weston surface + * @param[in] client Wayland client * @param[in] shsurf shell surface * @return none */ /*--------------------------------------------------------------------------*/ static void -win_mgr_register_surface(int layertype, struct wl_client *client, - struct wl_resource *resource, struct weston_surface *surface, - struct shell_surface *shsurf) +win_mgr_register_surface(int layertype, struct weston_surface *surface, + struct wl_client *client, struct shell_surface *shsurf) { struct uifw_win_surface *usurf; struct uifw_win_surface *phash; @@ -1233,8 +1438,8 @@ win_mgr_register_surface(int layertype, struct wl_client *client, int layer; uint32_t hash; - uifw_trace("win_mgr_register_surface: Enter(surf=%08x,client=%08x,res=%08x,layertype=%x)", - (int)surface, (int)client, (int)resource, layertype); + uifw_trace("win_mgr_register_surface: Enter(surf=%08x,client=%08x,type=%x,shsurf=%08x)", + (int)surface, (int)client, layertype, (int)shsurf); /* check new surface */ if (find_uifw_win_surface_by_ws(surface)) { @@ -1244,7 +1449,7 @@ win_mgr_register_surface(int layertype, struct wl_client *client, } /* set default color and shader */ - weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1); + weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0); /* create UIFW surface management table */ usurf = malloc(sizeof(struct uifw_win_surface)); @@ -1384,7 +1589,7 @@ win_mgr_surface_map(struct weston_surface *surface, int32_t *width, int32_t *hei usurf = find_uifw_win_surface_by_ws(surface); - if (usurf) { + if ((usurf != NULL) && (usurf->mapped == 0)) { uifw_trace("win_mgr_surface_map: surf=%08x w/h=%d/%d vis=%d", usurf->surfaceid, usurf->width, usurf->height, usurf->visible); if ((usurf->width > 0) && (usurf->height > 0)) { @@ -1412,17 +1617,17 @@ win_mgr_surface_map(struct weston_surface *surface, int32_t *width, int32_t *hei /* set position */ usurf->node_tbl = &_ico_node_table[_ico_ivi_inputpanel_display]; - usurf->width = (float)usurf->surface->geometry.width + usurf->width = (float)usurf->surface->width * (float)_ico_ivi_inputdeco_mag / 100.0f; - usurf->height = (float)usurf->surface->geometry.height + usurf->height = (float)usurf->surface->height * (float)_ico_ivi_inputdeco_mag / 100.0f; if ((usurf->width > (usurf->node_tbl->disp_width - 16)) || (usurf->height > (usurf->node_tbl->disp_height - 16))) { usurf->x = (usurf->node_tbl->disp_width - - usurf->surface->geometry.width) / 2; + - usurf->surface->width) / 2; usurf->y = usurf->node_tbl->disp_height - - usurf->surface->geometry.height - 16 + - usurf->surface->height - 16 - _ico_ivi_inputdeco_diff; if (usurf->x < 0) usurf->x = 0; if (usurf->y < 0) usurf->y = 0; @@ -1454,8 +1659,7 @@ win_mgr_surface_map(struct weston_surface *surface, int32_t *width, int32_t *hei usurf->width, usurf->height); } uifw_trace("win_mgr_surface_map: Change size/position x/y=%d/%d w/h=%d/%d", - (int)surface->geometry.x, (int)surface->geometry.y, - surface->geometry.width, surface->geometry.height); + usurf->x, usurf->y, surface->width, surface->height); } else if (usurf->layertype != LAYER_TYPE_INPUTPANEL) { uifw_trace("win_mgr_surface_map: No HomeScreen, chaneg to Visible"); @@ -1481,7 +1685,7 @@ win_mgr_surface_map(struct weston_surface *surface, int32_t *width, int32_t *hei uifw_trace("win_mgr_surface_map: Leave"); } else { - uifw_trace("win_mgr_surface_map: Leave(No UIFW Surface)"); + uifw_trace("win_mgr_surface_map: Leave(No UIFW Surface or mapped)"); } } @@ -1501,7 +1705,7 @@ ico_window_mgr_restack_layer(struct uifw_win_surface *usurf) int32_t buf_width, buf_height; float new_x, new_y; struct weston_layer *wlayer; - struct weston_surface *surface, *surfacetmp; + struct weston_view *view, *viewtmp; int num_visible = 0; int layertype; @@ -1512,11 +1716,13 @@ ico_window_mgr_restack_layer(struct uifw_win_surface *usurf) (int)usurf, (int)wlayer); /* remove all surfaces in panel_layer */ - wl_list_for_each_safe (surface, surfacetmp, &wlayer->surface_list, layer_link) { - wl_list_remove(&surface->layer_link); - wl_list_init(&surface->layer_link); + wl_list_for_each_safe (view, viewtmp, &wlayer->view_list, layer_link) { +uifw_debug("ico_window_mgr_restack_layer: remove view %08x surf=%08x", + (int)view, (int)view->surface); + wl_list_remove(&view->layer_link); + wl_list_init(&view->layer_link); } - wl_list_init(&wlayer->surface_list); + wl_list_init(&wlayer->view_list); wl_list_for_each (el, &_ico_win_mgr->ivi_layer_list, link) { wl_list_for_each (eu, &el->surface_list, ivi_layer) { @@ -1529,8 +1735,6 @@ ico_window_mgr_restack_layer(struct uifw_win_surface *usurf) (layertype != LAYER_TYPE_UNKNOWN)) { continue; } - wl_list_remove(&eu->surface->layer_link); - wl_list_init(&eu->surface->layer_link); if (eu->mapped != 0) { if ((el->visible == FALSE) || (eu->visible == FALSE)) { @@ -1538,18 +1742,17 @@ ico_window_mgr_restack_layer(struct uifw_win_surface *usurf) new_y = (float)(ICO_IVI_MAX_COORDINATE+1); } else if (eu->surface->buffer_ref.buffer) { - buf_width = weston_surface_buffer_width(eu->surface); - buf_height = weston_surface_buffer_height(eu->surface); + ico_ivi_surface_buffer_size(eu->surface, &buf_width, &buf_height); if ((eu->width > buf_width) && (eu->scalex <= 1.0f)) { new_x = (float)(eu->x + - (eu->width - eu->surface->geometry.width)/2); + (eu->width - eu->surface->width)/2); } else { new_x = (float)eu->x; } if ((eu->height > buf_height) && (eu->scaley <= 1.0f)) { new_y = (float) (eu->y + - (eu->height - eu->surface->geometry.height)/2); + (eu->height - eu->surface->height)/2); } else { new_y = (float)eu->y; @@ -1562,23 +1765,33 @@ ico_window_mgr_restack_layer(struct uifw_win_surface *usurf) new_x = (float)(eu->x + eu->node_tbl->disp_x + eu->xadd); new_y = (float)(eu->y + eu->node_tbl->disp_y + eu->yadd); } - wl_list_insert(wlayer->surface_list.prev, &eu->surface->layer_link); - if ((eu->restrain_configure == 0) && - ((new_x != eu->surface->geometry.x) || - (new_y != eu->surface->geometry.y))) { - weston_surface_damage_below(eu->surface); - weston_surface_set_position(eu->surface, (float)new_x, (float)new_y); - weston_surface_damage(eu->surface); + wl_list_for_each (view, &eu->surface->views, surface_link) { +uifw_debug("ico_window_mgr_restack_layer: add %08x view %08x surf=%08x", + eu->surfaceid, (int)view, (int)view->surface); + wl_list_remove(&view->layer_link); + wl_list_init(&view->layer_link); + wl_list_insert(wlayer->view_list.prev, &view->layer_link); + if ((eu->restrain_configure == 0) && + ((new_x != view->geometry.x) || + (new_y != view->geometry.y))) { + weston_view_damage_below(view); + weston_view_set_position(view, (float)new_x, (float)new_y); + weston_surface_damage(eu->surface); + } + uifw_debug("ico_window_mgr_restack_layer:%3d(%d).%08x(%08x:%d) " + "x/y=%d/%d w/h=%d/%d[%x]", + el->layer, el->visible, eu->surfaceid, (int)eu->surface, + eu->visible, (int)view->geometry.x, + (int)view->geometry.y, eu->surface->width, + eu->surface->height, eu->layertype); } - uifw_debug("ico_window_mgr_restack_layer:%3d(%d).%08x(%08x:%d) " - "x/y=%d/%d w/h=%d/%d %x", - el->layer, el->visible, eu->surfaceid, (int)eu->surface, - eu->visible, (int)eu->surface->geometry.x, - (int)eu->surface->geometry.y, eu->surface->geometry.width, - eu->surface->geometry.height, eu->layertype); } } } + wl_list_for_each (view, &wlayer->view_list, layer_link) { +uifw_debug("ico_window_mgr_restack_layer: panel_layer view %08x surf=%08x", + (int)view, (int)view->surface); + } /* damage(redraw) target surfacem if target exist */ if (usurf) { @@ -1608,7 +1821,8 @@ ico_window_mgr_restack_layer(struct uifw_win_surface *usurf) WL_EXPORT void ico_window_mgr_touch_layer(int omit) { - struct uifw_win_surface *eu; + struct uifw_win_surface *eu; + struct weston_view *ev; /* check current touch layer mode */ if ((_ico_win_mgr->touch_layer == NULL) || @@ -1619,15 +1833,16 @@ ico_window_mgr_touch_layer(int omit) wl_list_for_each (eu, &_ico_win_mgr->touch_layer->surface_list, ivi_layer) { if ((eu->surface == NULL) || (eu->mapped == 0)) continue; + ev = ico_ivi_get_primary_view(eu); if (omit != FALSE) { - eu->animation.pos_x = (int)eu->surface->geometry.x; - eu->animation.pos_y = (int)eu->surface->geometry.y; - eu->surface->geometry.x = (float)(ICO_IVI_MAX_COORDINATE+1); - eu->surface->geometry.y = (float)(ICO_IVI_MAX_COORDINATE+1); + eu->animation.pos_x = (int)ev->geometry.x; + eu->animation.pos_y = (int)ev->geometry.y; + ev->geometry.x = (float)(ICO_IVI_MAX_COORDINATE+1); + ev->geometry.y = (float)(ICO_IVI_MAX_COORDINATE+1); } else { - eu->surface->geometry.x = (float)eu->animation.pos_x; - eu->surface->geometry.y = (float)eu->animation.pos_y; + ev->geometry.x = (float)eu->animation.pos_x; + ev->geometry.y = (float)eu->animation.pos_y; } } } @@ -2113,9 +2328,10 @@ uifw_set_positionsize(struct wl_client *client, struct wl_resource *resource, uint32_t surfaceid, uint32_t node, int32_t x, int32_t y, int32_t width, int32_t height, int32_t flags) { - struct uifw_client *uclient; + struct uifw_client *uclient; struct uifw_win_surface *usurf; - struct weston_surface *es; + struct weston_surface *es; + struct weston_view *ev; int op; int retanima; int oldx, oldy; @@ -2190,6 +2406,7 @@ uifw_set_positionsize(struct wl_client *client, struct wl_resource *resource, if ((surfaceid != ICO_WINDOW_MGR_V_MAINSURFACE) && (uclient->manager == 0) && (uclient->privilege == 0)) uclient = NULL; } + ev = ico_ivi_get_primary_view(usurf); if (! uclient) { if ((usurf->width > 0) && (usurf->height > 0)) { win_mgr_surface_change_mgr(es, x, y, width, height); @@ -2200,13 +2417,13 @@ uifw_set_positionsize(struct wl_client *client, struct wl_resource *resource, uifw_trace("uifw_set_positionsize: Initial Position/Size visible=%d", usurf->visible); /* Initiale position is (0,0) */ - weston_surface_set_position(es, (float)(usurf->node_tbl->disp_x), - (float)(usurf->node_tbl->disp_y)); + weston_view_set_position(ev, (float)(usurf->node_tbl->disp_x), + (float)(usurf->node_tbl->disp_y)); } uifw_trace("uifw_set_positionsize: Old geometry x/y=%d/%d,w/h=%d/%d", - (int)es->geometry.x, (int)es->geometry.y, - (int)es->geometry.width, (int)es->geometry.height); + (int)ev->geometry.x, (int)ev->geometry.y, + (int)es->width, (int)es->height); usurf->animation.pos_x = usurf->x; usurf->animation.pos_y = usurf->y; @@ -2220,23 +2437,23 @@ uifw_set_positionsize(struct wl_client *client, struct wl_resource *resource, usurf->height = height; if (_ico_win_mgr->num_manager <= 0) { /* no manager(HomeScreen), set geometory */ - weston_surface_set_position(es, (float)(usurf->node_tbl->disp_x + x), - (float)(usurf->node_tbl->disp_y + y)); + weston_view_set_position(ev, (float)(usurf->node_tbl->disp_x + x), + (float)(usurf->node_tbl->disp_y + y)); } if ((es->output) && (es->buffer_ref.buffer) && - (es->geometry.width > 0) && (es->geometry.height > 0)) { + (es->width > 0) && (es->height > 0)) { uifw_trace("uifw_set_positionsize: Fixed Geometry, Change(Vis=%d)", usurf->visible); if (usurf->visible) { if ((flags & ICO_WINDOW_MGR_FLAGS_ANIMATION) && (win_mgr_hook_animation != NULL)) { /* with animation */ - if ((x != (usurf->surface->geometry.x - usurf->node_tbl->disp_x)) || - (y != (usurf->surface->geometry.y - usurf->node_tbl->disp_y))) { + if ((x != (ev->geometry.x - usurf->node_tbl->disp_x)) || + (y != (ev->geometry.y - usurf->node_tbl->disp_y))) { op = ICO_WINDOW_MGR_ANIMATION_OPMOVE; } - else if ((width != usurf->surface->geometry.width) || - (height != usurf->surface->geometry.height)) { + else if ((width != usurf->surface->width) || + (height != usurf->surface->height)) { op = ICO_WINDOW_MGR_ANIMATION_OPRESIZE; } else { @@ -2298,7 +2515,8 @@ uifw_set_visible(struct wl_client *client, struct wl_resource *resource, uint32_t surfaceid, int32_t visible, int32_t raise, int32_t flags) { struct uifw_win_surface *usurf; - struct uifw_client *uclient; + struct uifw_client *uclient; + struct weston_view *ev; int restack; int retanima; int oldvisible; @@ -2355,7 +2573,9 @@ uifw_set_visible(struct wl_client *client, struct wl_resource *resource, usurf->visible = 1; uifw_trace("uifw_set_visible: Change to Visible"); - ico_ivi_shell_set_toplevel(usurf->shsurf); + if (usurf->layertype != LAYER_TYPE_INPUTPANEL) { + ico_ivi_shell_set_toplevel(usurf->shsurf); + } /* Weston surface configure */ uifw_trace("uifw_set_visible: Visible to Weston WSurf=%08x,%d.%d/%d/%d/%d", @@ -2404,7 +2624,8 @@ uifw_set_visible(struct wl_client *client, struct wl_resource *resource, win_mgr_reset_focus(usurf); /* Weston surface configure */ - weston_surface_damage_below(usurf->surface); + ev = ico_ivi_get_primary_view(usurf); + weston_view_damage_below(ev); ico_window_mgr_set_weston_surface(usurf, usurf->x, usurf->y, usurf->width, usurf->height); @@ -2859,6 +3080,7 @@ uifw_set_layer_visible(struct wl_client *client, struct wl_resource *resource, struct uifw_win_layer *el; struct uifw_win_layer *new_el; struct uifw_win_surface *usurf; + struct weston_view *ev; int layertype = 0; if ((layer == ICO_WINDOW_MGR_LAYERTYPE_BACKGROUND) || @@ -2945,7 +3167,8 @@ uifw_set_layer_visible(struct wl_client *client, struct wl_resource *resource, win_mgr_reset_focus(usurf); } /* Damage(redraw) target surface */ - weston_surface_damage_below(usurf->surface); + ev = ico_ivi_get_primary_view(usurf); + weston_view_damage_below(ev); } } @@ -3045,22 +3268,23 @@ static void win_mgr_check_mapsurface(struct weston_animation *animation, struct weston_output *output, uint32_t msecs) { - struct uifw_surface_map *sm; + struct uifw_surface_map *sm, *sm_tmp; uint32_t curtime; int wait = 99999999; /* check touch down counter */ - if (touch_check_seat) { - if (touch_check_seat->num_tp > 10) { + if ((touch_check_seat) && + (touch_check_seat->touch)) { + if (touch_check_seat->touch->num_tp > 10) { uifw_trace("win_mgr_check_mapsurface: illegal touch counter(num=%d), reset", - (int)touch_check_seat->num_tp); - touch_check_seat->num_tp = 0; + (int)touch_check_seat->touch->num_tp); + touch_check_seat->touch->num_tp = 0; } } /* check all mapped surfaces */ curtime = weston_compositor_get_time(); - wl_list_for_each (sm, &_ico_win_mgr->map_list, map_link) { + wl_list_for_each_safe (sm, sm_tmp, &_ico_win_mgr->map_list, map_link) { uifw_detail("win_mgr_check_mapsurface: sm=%08x surf=%08x", (int)sm, sm->usurf->surfaceid); win_mgr_change_mapsurface(sm, 0, curtime); @@ -3114,6 +3338,7 @@ win_mgr_change_mapsurface(struct uifw_surface_map *sm, int event, uint32_t curti struct uifw_intel_region *dri_region; struct uifw_gl_surface_state *gl_state; struct weston_surface *es; + struct weston_view *ev; struct wl_shm_buffer *shm_buffer; uint32_t eglname; int width; @@ -3370,25 +3595,32 @@ win_mgr_change_mapsurface(struct uifw_surface_map *sm, int event, uint32_t curti sm->eventque = 0; } else { - if (height > sm->height) { - height = sm->height; - } - if ((*(_ico_win_mgr->compositor->renderer->read_surface_pixels)) - (es, PIXMAN_a8r8g8b8, p->image, - 0, 0, sm->width, height) != 0) { - uifw_debug("win_mgr_change_mapsurface: Error read pixel %s.%08x", - sm->usurf->uclient->appid, sm->usurf->surfaceid); + ev = ico_ivi_get_primary_view(sm->usurf); + if ((ev == NULL) || (ev->output == NULL)) { + uifw_debug("win_mgr_change_mapsurface: surface %08x has no view", + sm->usurf->surfaceid); event = ICO_WINDOW_MGR_MAP_SURFACE_EVENT_ERROR; - sm->eventque = 0; } else { - uifw_detail("win_mgr_change_mapsurface: PIX read pixels(%d)", - idx+1); - p->surfaceid = sm->usurf->surfaceid; - p->settime = curtime; - p->width = sm->width; - p->height = height; - sm->eglname = idx + 1; + if (height > sm->height) { + height = sm->height; + } + if (ico_read_surface_pixels(es, PIXMAN_a8r8g8b8, p->image, + 0, 0, sm->width, height) != 0) { + uifw_debug("win_mgr_change_mapsurface: Error read pixel %s.%08x", + sm->usurf->uclient->appid, sm->usurf->surfaceid); + event = ICO_WINDOW_MGR_MAP_SURFACE_EVENT_ERROR; + sm->eventque = 0; + } + else { + uifw_detail("win_mgr_change_mapsurface: PIX read pixels(%d)", + idx+1); + p->surfaceid = sm->usurf->surfaceid; + p->settime = curtime; + p->width = sm->width; + p->height = height; + sm->eglname = idx + 1; + } } } } @@ -3559,6 +3791,13 @@ uifw_map_surface(struct wl_client *client, struct wl_resource *resource, uifw_trace("uifw_map_surface: Leave(surface=%08x dose not exist)", surfaceid); return; } + if (usurf->layertype == LAYER_TYPE_INPUTPANEL) { + /* input panel surface dose not suport, error */ + ico_window_mgr_send_map_surface(resource, ICO_WINDOW_MGR_MAP_SURFACE_EVENT_ERROR, + surfaceid, 1, 0, 0, 0, 0, 0); + uifw_trace("uifw_map_surface: Leave(surface=%08x is input panel)", surfaceid); + return; + } /* check if buffered */ es = usurf->surface; @@ -3576,15 +3815,6 @@ uifw_map_surface(struct wl_client *client, struct wl_resource *resource, if ((_ico_ivi_gpu_type == ICO_GPUTYPE_NOACCELERATION) || (gl_state == NULL) || (gl_state->buffer_type == BUFFER_TYPE_SHM)) { /* No Acceleration or wl_shm_buffer support ReadPixels */ - if ((_ico_win_mgr->compositor->renderer == NULL) || - (_ico_win_mgr->compositor->renderer->read_surface_pixels == NULL) || - (uclient->shmbuf == NULL)) { - ico_window_mgr_send_map_surface(resource, ICO_WINDOW_MGR_MAP_SURFACE_EVENT_ERROR, - surfaceid, 4, 0, 0, 0, 0, 0); - uifw_trace("uifw_map_surface: Leave(surface(%08x) not support ReadPixels)", - surfaceid); - return; - } if ((gl_state != NULL) && (gl_state->buffer_type == BUFFER_TYPE_SHM)) { maptype = -1; format = 0xff; @@ -3818,17 +4048,7 @@ uifw_unmap_surface(struct wl_client *client, struct wl_resource *resource, wl_list_for_each_safe (sm, sm_tmp, &usurf->surf_map, surf_link) { if (((uclient != NULL) && (sm->uclient != uclient))) continue; - /* send unmap event */ - if ((uclient != NULL) && (uclient->mgr != NULL)) { - uifw_trace("uifw_unmap_surface: send UNMAP event(ev=%d surf=%08x name=%08x " - "w/h/s=%d/%d/%d format=%x", - ICO_WINDOW_MGR_MAP_SURFACE_EVENT_UNMAP, surfaceid, - sm->eglname, sm->width, sm->height, sm->stride, sm->format); - ico_window_mgr_send_map_surface(uclient->mgr->resource, - ICO_WINDOW_MGR_MAP_SURFACE_EVENT_UNMAP, - surfaceid, sm->type, sm->eglname, sm->width, - sm->height, sm->stride, sm->format); - } + if ((sm->type != ICO_WINDOW_MGR_MAP_TYPE_EGL) && (sm->uclient->shmbuf != NULL)) { /* reset shared memory buffer */ @@ -3902,6 +4122,7 @@ win_mgr_change_surface(struct weston_surface *surface, const int to, const int m { struct uifw_win_surface *usurf; struct weston_surface *es; + struct weston_view *ev; int x; int y; int repaint = 0; @@ -3921,25 +4142,25 @@ win_mgr_change_surface(struct weston_surface *surface, const int to, const int m } /* set surface size */ + ev = ico_ivi_get_primary_view(usurf); uifw_debug("win_mgr_change_surface: set surface x/y=%d/%d=>%d/%d w/h=%d/%d=>%d/%d", - (int)es->geometry.x, (int)es->geometry.y, usurf->x, usurf->y, - usurf->width, usurf->height, es->geometry.width, es->geometry.height); + (int)ev->geometry.x, (int)ev->geometry.y, usurf->x, usurf->y, + es->width, es->height, usurf->width, usurf->height); if ((usurf->width <= 0) || (usurf->height <= 0)) { - usurf->width = es->geometry.width; - usurf->height = es->geometry.height; + usurf->width = es->width; + usurf->height = es->height; } win_mgr_set_scale(usurf); if (usurf->visible) { - weston_surface_set_position(usurf->surface, - (float)(usurf->node_tbl->disp_x + - usurf->x + usurf->xadd), - (float)(usurf->node_tbl->disp_y + - usurf->y + usurf->yadd)); + weston_view_set_position(ev, (float)(usurf->node_tbl->disp_x + + usurf->x + usurf->xadd), + (float)(usurf->node_tbl->disp_y + + usurf->y + usurf->yadd)); ico_window_mgr_restack_layer(usurf); } else { - weston_surface_set_position(usurf->surface, (float)(ICO_IVI_MAX_COORDINATE+1), - (float)(ICO_IVI_MAX_COORDINATE+1)); + weston_view_set_position(ev, (float)(ICO_IVI_MAX_COORDINATE+1), + (float)(ICO_IVI_MAX_COORDINATE+1)); } /* send wayland event to client */ @@ -3967,9 +4188,9 @@ win_mgr_change_surface(struct weston_surface *surface, const int to, const int m } /* change geometry if request from manager */ if (manager) { - if ((usurf->width != es->geometry.width) || - (usurf->height != es->geometry.height) || - (es->geometry.x != (float)x) || (es->geometry.y != (float)y)) { + if ((usurf->width != es->width) || + (usurf->height != es->height) || + ((int)ev->geometry.x != x) || ((int)ev->geometry.y != y)) { win_mgr_surface_configure(usurf, (float)x, (float)y, usurf->width, usurf->height); repaint ++; } @@ -3984,15 +4205,15 @@ win_mgr_change_surface(struct weston_surface *surface, const int to, const int m } else { ico_win_mgr_send_to_mgr(ICO_WINDOW_MGR_WINDOW_CONFIGURE, - usurf, (int)es->geometry.x, (int)es->geometry.y, - es->geometry.width, es->geometry.height, 1); + usurf, (int)ev->geometry.x, (int)ev->geometry.y, + es->width, es->height, 1); } } /* change geometry if request from client */ if (! manager) { - if ((usurf->width != es->geometry.width) || (usurf->height != es->geometry.height) || - (es->geometry.x != (float)x) || (es->geometry.y != (float)y)) { + if ((usurf->width != es->width) || (usurf->height != es->height) || + ((int)ev->geometry.x != x) || ((int)ev->geometry.y != y)) { win_mgr_surface_configure(usurf, x, y, usurf->width, usurf->height); repaint ++; } @@ -4022,23 +4243,25 @@ win_mgr_surface_configure(struct uifw_win_surface *usurf, int x, int y, int width, int height) { struct weston_surface *es; + struct weston_view *ev; es = usurf->surface; if ((es != NULL) && (es->buffer_ref.buffer)) { if (usurf->client_width == 0) { - usurf->client_width = es->geometry.width; + usurf->client_width = es->width; if (usurf->client_width == 0) - usurf->client_width = weston_surface_buffer_width(es); + usurf->client_width = ico_ivi_surface_buffer_width(es); } if (usurf->client_height == 0) { - usurf->client_height = es->geometry.height; + usurf->client_height = es->height; if (usurf->client_height == 0) - usurf->client_height = weston_surface_buffer_height(es); + usurf->client_height = ico_ivi_surface_buffer_height(es); } /* not set geometry width/height */ win_mgr_set_scale(usurf); - weston_surface_set_position(es, x + usurf->xadd, y + usurf->yadd); + ev = ico_ivi_get_primary_view(usurf); + weston_view_set_position(ev, x + usurf->xadd, y + usurf->yadd); } } @@ -4066,10 +4289,9 @@ win_mgr_shell_configure(struct weston_surface *surface) return; } - usurf->client_width = surface->geometry.width; - usurf->client_height = surface->geometry.height; - buf_width = weston_surface_buffer_width(surface); - buf_height = weston_surface_buffer_height(surface); + usurf->client_width = surface->width; + usurf->client_height = surface->height; + ico_ivi_surface_buffer_size(surface, &buf_width, &buf_height); uifw_trace("win_mgr_shell_configure: %08x client w/h=%d/%d buf=%d/%d", usurf->surfaceid, usurf->client_width, usurf->client_height, buf_width, buf_height); @@ -4528,20 +4750,17 @@ win_mgr_fullscreen(int event, struct weston_surface *surface) usurf->width, usurf->height, 1); } break; - case SHELL_FULLSCREEN_STACK: /* change surface to top of layer */ - uifw_trace("win_mgr_fullscreen: %08x SHELL_FULLSCREEN_STACK", usurf->surfaceid); - if (usurf->mapped == 0) { - uifw_trace("win_mgr_fullscreen: not map, change to map"); - width = usurf->node_tbl->disp_width; - height = usurf->node_tbl->disp_height; - sx = 0; - sy = 0; - win_mgr_surface_map(usurf->surface, &width, &height, &sx, &sy); - } - if ((usurf->surface != NULL) && (usurf->mapped != 0) && - (usurf->surface->buffer_ref.buffer != NULL)) { - /* fullscreen surface raise */ - win_mgr_set_raise(usurf, 1); + case SHELL_FULLSCREEN_UNSET: /* change surface to normal screen */ + uifw_trace("win_mgr_fullscreen: %08x SHELL_FULLSCREEN_UNSET", usurf->surfaceid); + if (usurf->layertype == LAYER_TYPE_FULLSCREEN) { + ico_window_mgr_set_visible(usurf, 2); + usurf->layertype = usurf->old_layertype; + win_mgr_set_layer(usurf, usurf->old_layer->layer); + win_mgr_change_surface(usurf->surface, -1, 1); + /* send event to HomeScreen */ + ico_win_mgr_send_to_mgr(ICO_WINDOW_MGR_WINDOW_CONFIGURE, + usurf, usurf->x, usurf->y, + usurf->width, usurf->height, 0); } break; case SHELL_FULLSCREEN_CONF: /* configure full screen surface */ @@ -4606,7 +4825,7 @@ win_mgr_reset_focus(struct uifw_win_surface *usurf) * * @param[in] usurf UIFW surface * @param[in] visible bit 0: visible(=1)/unvisible(=0) - * bit 1: widht anima(=1)/without anima(=0) + * bit 1: width anima(=1)/without anima(=0) * @return none */ /*--------------------------------------------------------------------------*/ @@ -5053,14 +5272,15 @@ static int win_mgr_set_scale(struct uifw_win_surface *usurf) { struct weston_surface *es; + struct weston_view *ev; float scalex; float scaley; int ret = 0; es = usurf->surface; if ((es != NULL) && (es->buffer_ref.buffer)) { - if (usurf->client_width == 0) usurf->client_width = es->geometry.width; - if (usurf->client_height == 0) usurf->client_height = es->geometry.height; + if (usurf->client_width == 0) usurf->client_width = es->width; + if (usurf->client_height == 0) usurf->client_height = es->height; if ((usurf->client_width > 0) && (usurf->client_height > 0)) { scalex = (float)usurf->width / (float)usurf->client_width; scaley = (float)usurf->height / (float)usurf->client_height; @@ -5094,20 +5314,24 @@ win_mgr_set_scale(struct uifw_win_surface *usurf) } } } - uifw_trace("win_mgr_set_scale: %08x fixed aspect x/yadd=%d/%d", + uifw_debug("win_mgr_set_scale: %08x fixed aspect x/yadd=%d/%d", usurf->surfaceid, usurf->xadd, usurf->yadd); } if ((scalex != usurf->scalex) || (scaley != usurf->scaley)) { usurf->scalex = scalex; usurf->scaley = scaley; + ev = ico_ivi_get_primary_view(usurf); if ((scalex != 1.0f) || (scaley != 1.0f)) { weston_matrix_init(&usurf->transform.matrix); weston_matrix_scale(&usurf->transform.matrix, scalex, scaley, 1.0f); uifw_trace("win_mgr_set_scale: change scale(%d)", usurf->set_transform); +uifw_trace("ev=%08x transformation_list=%08x next=%08x prev=%08x", + (int)ev, (int)&ev->geometry.transformation_list, + (int)ev->geometry.transformation_list.next, (int)ev->geometry.transformation_list.prev); if (usurf->set_transform == 0) { usurf->set_transform = 1; wl_list_init(&usurf->transform.link); - wl_list_insert(&es->geometry.transformation_list, &usurf->transform.link); + wl_list_insert(&ev->geometry.transformation_list, &usurf->transform.link); } } else if (usurf->set_transform != 0) { @@ -5115,9 +5339,9 @@ win_mgr_set_scale(struct uifw_win_surface *usurf) usurf->set_transform = 0; wl_list_remove(&usurf->transform.link); } - weston_surface_geometry_dirty(es); - weston_surface_update_transform(es); - weston_surface_damage_below(es); + weston_view_geometry_dirty(ev); + weston_view_update_transform(ev); + weston_view_damage_below(ev); weston_surface_damage(es); ret = 1; } diff --git a/src/ico_window_mgr.h b/src/ico_window_mgr.h index 9a081ca..96b7e57 100644 --- a/src/ico_window_mgr.h +++ b/src/ico_window_mgr.h @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided diff --git a/src/ico_window_mgr_private.h b/src/ico_window_mgr_private.h index 08bed30..f390bcb 100644 --- a/src/ico_window_mgr_private.h +++ b/src/ico_window_mgr_private.h @@ -1,7 +1,7 @@ /* * Copyright © 2010-2011 Intel Corporation * Copyright © 2008-2011 Kristian Høgsberg - * Copyright © 2013 TOYOTA MOTOR CORPORATION. + * Copyright © 2013-2014 TOYOTA MOTOR CORPORATION. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -72,7 +72,7 @@ struct uifw_win_layer { char visible; /* visibility */ char layertype; /* layer type */ char res[2]; /* (unused) */ - struct wl_list surface_list; /* Surfacae list */ + struct wl_list surface_list; /* Surface list */ struct wl_list link; /* Link pointer for layer list */ }; @@ -238,6 +238,14 @@ void ico_window_mgr_touch_layer(int omit); int ico_window_mgr_is_visible(struct uifw_win_surface *usurf); /* set active surface */ void ico_window_mgr_active_surface(struct weston_surface *surface); + /* get buffer width */ +int ico_ivi_surface_buffer_width(struct weston_surface *es); + /* get buffer height */ +int ico_ivi_surface_buffer_height(struct weston_surface *es); + /* get buffer size */ +void ico_ivi_surface_buffer_size(struct weston_surface *es, int *width, int *height); + /* get surface primary view */ +struct weston_view *ico_ivi_get_primary_view(struct uifw_win_surface *usurf); /* set window animation hook */ void ico_window_mgr_set_hook_animation(int (*hook_animation)(const int op, void *data)); /* set surface attribute change hook */ diff --git a/tests/weston.ini b/tests/weston.ini index d94fa58..4eb81ba 100644 --- a/tests/weston.ini +++ b/tests/weston.ini @@ -5,7 +5,7 @@ modules=error_but_no_problem_for_test.so [shell] num-workspaces=1 -shell-exe= +client= locking=false animation=zoom startup-animation=fade