[PATCH 04/16] xdg-shell: Implement part of the interface.

Kristian Høgsberg hoegsberg at gmail.com
Tue Dec 3 15:46:15 PST 2013


On Tue, Dec 3, 2013 at 9:45 AM, Rafael Antognolli <antognolli at gmail.com> wrote:
> On Fri, Nov 29, 2013 at 9:29 PM, Kristian Høgsberg <hoegsberg at gmail.com> wrote:
>> On Wed, Nov 27, 2013 at 03:50:20PM -0200, Rafael Antognolli wrote:
>>> Basic requests are implemented, enough to get a surface displayed.
>>> ---
>>>  src/.gitignore  |   2 +
>>>  src/Makefile.am |   6 +-
>>>  src/shell.c     | 228 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
>>>  3 files changed, 223 insertions(+), 13 deletions(-)
>>>
>>> diff --git a/src/.gitignore b/src/.gitignore
>>> index 723967d..8e59be6 100644
>>> --- a/src/.gitignore
>>> +++ b/src/.gitignore
>>> @@ -19,3 +19,5 @@ workspaces-protocol.c
>>>  workspaces-server-protocol.h
>>>  input-method-protocol.c
>>>  input-method-server-protocol.h
>>> +xdg-shell-protocol.c
>>> +xdg-shell-server-protocol.h
>>> diff --git a/src/Makefile.am b/src/Makefile.am
>>> index 551dff9..f6f277d 100644
>>> --- a/src/Makefile.am
>>> +++ b/src/Makefile.am
>>> @@ -294,7 +294,9 @@ desktop_shell_la_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS)
>>>  desktop_shell_la_SOURCES =                   \
>>>       shell.c                                 \
>>>       desktop-shell-protocol.c                \
>>> -     desktop-shell-server-protocol.h
>>> +     desktop-shell-server-protocol.h         \
>>> +     xdg-shell-protocol.c                    \
>>> +     xdg-shell-server-protocol.h
>>>  endif
>>>
>>>  if ENABLE_TABLET_SHELL
>>> @@ -355,6 +357,8 @@ BUILT_SOURCES =                                   \
>>>       input-method-server-protocol.h          \
>>>       workspaces-server-protocol.h            \
>>>       workspaces-protocol.c                   \
>>> +     xdg-shell-protocol.c                    \
>>> +     xdg-shell-server-protocol.h             \
>>>       git-version.h
>>>
>>>  CLEANFILES = $(BUILT_SOURCES)
>>> diff --git a/src/shell.c b/src/shell.c
>>> index 507d46f..f775899 100644
>>> --- a/src/shell.c
>>> +++ b/src/shell.c
>>> @@ -40,6 +40,7 @@
>>>  #include "input-method-server-protocol.h"
>>>  #include "workspaces-server-protocol.h"
>>>  #include "../shared/config-parser.h"
>>> +#include "xdg-shell-server-protocol.h"
>>>
>>>  #define DEFAULT_NUM_WORKSPACES 1
>>>  #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
>>> @@ -1564,8 +1565,8 @@ 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);
>>> @@ -1587,6 +1588,13 @@ shell_surface_move(struct wl_client *client, struct wl_resource *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;
>>> @@ -1741,9 +1749,9 @@ 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);
>>> @@ -1763,6 +1771,14 @@ shell_surface_resize(struct wl_client *client, struct wl_resource *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
>>> @@ -1943,12 +1959,10 @@ create_pointer_focus_listener(struct weston_seat *seat)
>>>  }
>>>
>>>  static void
>>> -shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
>>> -                                                     uint32_t serial)
>>> +surface_pong(struct shell_surface *shsurf, uint32_t serial)
>>>  {
>>> -     struct shell_surface *shsurf = wl_resource_get_user_data(resource);
>>> -     struct weston_seat *seat;
>>>       struct weston_compositor *ec = shsurf->surface->compositor;
>>> +     struct weston_seat *seat;
>>>
>>>       if (shsurf->ping_timer == NULL)
>>>               /* Just ignore unsolicited pong. */
>>> @@ -1965,6 +1979,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)
>>>  {
>>>       free(shsurf->title);
>>> @@ -2802,9 +2826,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;
>>>
>>> @@ -2863,6 +2887,19 @@ create_shell_surface(void *shell, struct weston_surface *surface,
>>>       return shsurf;
>>>  }
>>>
>>> +static struct shell_surface *
>>> +create_shell_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_NONE;
>>> +     shsurf->next_type = SHELL_SURFACE_NONE;
>>> +
>>> +     return shsurf;
>>> +}
>>> +
>>>  static struct weston_view *
>>>  get_primary_view(void *shell, struct shell_surface *shsurf)
>>>  {
>>> @@ -2907,6 +2944,157 @@ 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 const struct xdg_surface_interface xdg_surface_implementation = {
>>> +     xdg_surface_destroy,
>>> +     NULL, // set_transient_for
>>> +     xdg_surface_set_title,
>>> +     xdg_surface_set_app_id,
>>> +     xdg_surface_pong,
>>> +     xdg_surface_move,
>>> +     xdg_surface_resize,
>>> +     NULL, // set_output
>>> +     NULL, // set_fullscreen
>>> +     NULL, // unset_fullscreen
>>> +     NULL, // set_maximized
>>> +     NULL, // unset_maximized
>>> +     NULL // set_minimized
>>
>> We try to avoid // style comments even for a one-line thing like this.
>> But I think you should just squash patches 4-7 into one big patch.
>> The point of small commits is mainly bisectability - fix one issues or
>> add one feature at a time.  In this case the entire xdg_shell
>> interface is one feature.  If you're landing a big chunk of work,
>> there's really no point in committing it one or three functions at a
>> time.
>
> Done.
>
>>> +};
>>> +
>>> +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);
>>> +
>>> +     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_NONE;
>>> +     shsurf->next_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;
>>> +     }
>>> +
>>> +     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);
>>> +}
>>> +
>>> +static const struct xdg_shell_interface xdg_implementation = {
>>> +     xdg_use_unstable_version,
>>> +     xdg_get_xdg_surface,
>>> +     NULL // get_xdg_popup
>>> +};
>>> +
>>> +
>>>  static void
>>>  shell_fade(struct desktop_shell *shell, enum fade_type type);
>>>
>>> @@ -4507,6 +4695,18 @@ 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_implementation(resource, &xdg_implementation,
>>> +                                            shell, NULL);
>>
>> I'd like to make sure we can't call any requests in the object until
>> use_unstable_version() has been called with a matching version.  We can do something like
>>
>> 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 set_unstable_version first");
>>                 return 0;
>>         }
>>
>> #define XDG_SERVER_VERSION 1
>>
>>         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);
>> }
>>
>> and then use
>>
>>    wl_resource_set_dispatcher(resource, xdg_shell_unversioned_dispatch,
>>                               NULL, shell, NULL);
>>
>> in bind_xdg_shell().
>
> I don't fully understand this sorcery yet (didn't spend too much
> trying), but it apparently works, thanks!
>
> I didn't add it before because I wasn't sure about how to add it.

This is using Jason Ekstrands per-resource dispatcher stuff.  A
dispatcher is a callback that receives all the incoming requests for a
wl_resource.  As you can see it gets the resource, the opcode, the
message signature and the args as a union wl_argument array.  This
lets us catch all requests and reject anything that isn't opcode = 0
(use_unstable_version) with the right version number (first integer
arg in the arg array).  Once we get that request, we set the
implementation as we normally would, which replaces the generic
dispatcher and makes the protocol code dispatch incoming requests to
our handlers.

>>> +}
>>> +
>>> +static void
>>>  unbind_desktop_shell(struct wl_resource *resource)
>>>  {
>>>       struct desktop_shell *shell = wl_resource_get_user_data(resource);
>>> @@ -6045,6 +6245,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)
>>> --
>>> 1.8.3.1
>>>
>>> _______________________________________________
>>> wayland-devel mailing list
>>> wayland-devel at lists.freedesktop.org
>>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>> _______________________________________________
>> wayland-devel mailing list
>> wayland-devel at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
>
>
> --
> Rafael Antognolli


More information about the wayland-devel mailing list