discomfitor pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=da74e690f0139aa85272314f1d688a717c52668c

commit da74e690f0139aa85272314f1d688a717c52668c
Author: Mike Blumenkrantz <zm...@osg.samsung.com>
Date:   Tue Apr 5 15:05:10 2016 -0400

    redo xdg shell to enforce double buffering of client-side configure serials
    
    xdg shell configure states (maximize, fullscreen) return a client ack when 
the
    client has applied the state. the ack, followed by the next surface commit,
    indicates that the surface is ready to be transitioned into the configured 
state
---
 src/bin/e_comp_wl.c                       |  26 +++++
 src/bin/e_comp_wl.h                       |   8 ++
 src/modules/wl_desktop_shell/e_mod_main.c | 169 +++++++++++++++++++++++-------
 3 files changed, 168 insertions(+), 35 deletions(-)

diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index 5370d2f..0617a3a 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -1058,6 +1058,7 @@ _e_comp_wl_surface_state_commit(E_Client *ec, 
E_Comp_Wl_Surface_State *state)
    Eina_Rectangle *dmg;
    Eina_Bool placed = EINA_TRUE;
    int x = 0, y = 0, w, h;
+   Eina_Rectangle saved;
 
    first = !e_pixmap_usable_get(ec->pixmap);
 #ifndef HAVE_WAYLAND_ONLY
@@ -1073,6 +1074,11 @@ _e_comp_wl_surface_state_commit(E_Client *ec, 
E_Comp_Wl_Surface_State *state)
         e_client_unignore(ec);
      }
 
+   /* store to override in case of buffered fullscreen */
+   memcpy(&saved, &ec->client, sizeof(Eina_Rectangle));
+   saved.x -= ec->zone->x;
+   saved.y -= ec->zone->y;
+
    if (state->new_attach)
      _e_comp_wl_surface_state_attach(ec, state);
 
@@ -1195,6 +1201,26 @@ _e_comp_wl_surface_state_commit(E_Client *ec, 
E_Comp_Wl_Surface_State *state)
    state->sy = 0;
    state->new_attach = EINA_FALSE;
 
+
+   if (ec->comp_data->shell.surface)
+     {
+        if (ec->comp_data->shell.set.fullscreen)
+          {
+             e_client_fullscreen(ec, E_FULLSCREEN_RESIZE);
+             memcpy(&ec->saved, &saved, sizeof(Eina_Rectangle));
+          }
+        if (ec->comp_data->shell.set.unfullscreen)
+           e_client_unfullscreen(ec);
+        if (ec->comp_data->shell.set.maximize)
+          e_client_maximize(ec,
+               (e_config->maximize_policy & E_MAXIMIZE_TYPE) | 
E_MAXIMIZE_BOTH);
+        if (ec->comp_data->shell.set.unmaximize)
+          e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
+        if (ec->comp_data->shell.set.minimize)
+          e_client_iconify(ec);
+        memset(&ec->comp_data->shell.set, 0, sizeof(ec->comp_data->shell.set));
+     }
+
    /* insert state frame callbacks into comp_data->frames
     * NB: This clears state->frames list */
    ec->comp_data->frames = eina_list_merge(ec->comp_data->frames,
diff --git a/src/bin/e_comp_wl.h b/src/bin/e_comp_wl.h
index 84fbd48..98044e9 100644
--- a/src/bin/e_comp_wl.h
+++ b/src/bin/e_comp_wl.h
@@ -286,6 +286,14 @@ struct _E_Comp_Wl_Client_Data
         void (*unmap)(struct wl_resource *resource);
         Eina_Rectangle window;
         E_Shell_Data *data;
+        struct
+        {
+           Eina_Bool fullscreen : 1;
+           Eina_Bool unfullscreen : 1;
+           Eina_Bool maximize : 1;
+           Eina_Bool unmaximize : 1;
+           Eina_Bool minimize : 1;
+        } set;
      } shell;
    struct
    {
diff --git a/src/modules/wl_desktop_shell/e_mod_main.c 
b/src/modules/wl_desktop_shell/e_mod_main.c
index d30ccca..57ca1bc 100644
--- a/src/modules/wl_desktop_shell/e_mod_main.c
+++ b/src/modules/wl_desktop_shell/e_mod_main.c
@@ -5,11 +5,26 @@
 
 #define XDG_SERVER_VERSION 5
 
+typedef enum
+{
+   STATE_MAXIMIZED = (1 << 0),
+   STATE_UNMAXIMIZED = (1 << 1),
+   STATE_FULLSCREEN = (1 << 2),
+   STATE_UNFULLSCREEN = (1 << 3),
+} State;
+
+typedef struct Pending_State
+{
+   State state;
+   uint32_t serial;
+} Pending_State;
+
 struct E_Shell_Data
 {
    uint32_t edges;
    int32_t width;
    int32_t height;
+   Eina_List *pending;
    Eina_Bool fullscreen : 1;
    Eina_Bool maximized : 1;
    Eina_Bool activated : 1;
@@ -115,6 +130,9 @@ _e_shell_surface_destroy(struct wl_resource *resource)
 
         if (ec->comp_data)
           {
+             E_Shell_Data *shd = ec->comp_data->shell.data;
+
+             E_FREE_LIST(shd->pending, free);
              E_FREE(ec->comp_data->shell.data);
              if (ec->comp_data->mapped)
                {
@@ -603,17 +621,14 @@ _e_xdg_surface_state_add(struct wl_resource *resource, 
struct wl_array *states,
 }
 
 static void
-_e_xdg_shell_surface_configure_send(struct wl_resource *resource, uint32_t 
edges, int32_t width, int32_t height)
+_xdg_shell_surface_send_configure(struct wl_resource *resource, Eina_Bool 
fullscreen, Eina_Bool maximized, uint32_t edges, Eina_Bool focused, int32_t 
width, int32_t height)
 {
-   E_Client *ec;
-   E_Shell_Data *shd;
    struct wl_array states;
    uint32_t serial;
+   E_Client *ec;
+   E_Shell_Data *shd;
+   State pending = 0;
 
-   /* DBG("XDG_SHELL: Surface Configure Send: %d \t%d %d\tEdges: %d", */
-   /*     wl_resource_get_id(resource), width, height, edges); */
-
-   /* get the client for this resource */
    if (!(ec = wl_resource_get_user_data(resource)))
      {
         wl_resource_post_error(resource,
@@ -621,37 +636,74 @@ _e_xdg_shell_surface_configure_send(struct wl_resource 
*resource, uint32_t edges
                                "No Client For Shell Surface");
         return;
      }
+   if (ec->netwm.type == E_WINDOW_TYPE_POPUP_MENU) return;
 
    shd = ec->comp_data->shell.data;
    if ((shd->edges == edges) && (shd->width == width) && (shd->height == 
height) &&
-       (shd->fullscreen == ec->fullscreen) &&
-       ((!ec->fullscreen) || (shd->maximized == ec->maximized)) &&
-       (shd->activated == ec->focused)) return;
+       (shd->fullscreen == fullscreen) &&
+       ((!fullscreen) || (shd->maximized == maximized)) &&
+       (shd->activated == focused)) return;
    shd->edges = edges;
    shd->width = width;
    shd->height = height;
-   shd->fullscreen = ec->fullscreen;
-   shd->maximized = ec->maximized;
-   shd->activated = ec->focused;
-
+   if (shd->fullscreen != fullscreen)
+     {
+        if (fullscreen)
+          pending |= STATE_FULLSCREEN;
+        else
+          pending |= STATE_UNFULLSCREEN;
+     }
+   shd->fullscreen = fullscreen;
+   if (shd->maximized != maximized)
+     {
+        if (maximized)
+          pending |= STATE_MAXIMIZED;
+        else
+          pending |= STATE_UNMAXIMIZED;
+     }
+   shd->maximized = maximized;
+   shd->activated = focused;
    wl_array_init(&states);
 
-   if (ec->fullscreen)
+   if (fullscreen)
      _e_xdg_surface_state_add(resource, &states, XDG_SURFACE_STATE_FULLSCREEN);
-   else if (ec->maximized)
+   else if (maximized)
      _e_xdg_surface_state_add(resource, &states, XDG_SURFACE_STATE_MAXIMIZED);
-   if (edges != 0)
+   if (edges)
      _e_xdg_surface_state_add(resource, &states, XDG_SURFACE_STATE_RESIZING);
-   if (ec->focused)
+   if (focused)
      _e_xdg_surface_state_add(resource, &states, XDG_SURFACE_STATE_ACTIVATED);
 
-   if (ec->netwm.type != E_WINDOW_TYPE_POPUP_MENU)
+   serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   xdg_surface_send_configure(resource, width, height, &states, serial);
+   {
+      Pending_State *ps;
+
+      ps = E_NEW(Pending_State, 1);
+      ps->state = pending;
+      ps->serial = serial;
+      shd->pending = eina_list_append(shd->pending, ps);
+   }
+
+   wl_array_release(&states);
+}
+
+static void
+_e_xdg_shell_surface_configure_send(struct wl_resource *resource, uint32_t 
edges, int32_t width, int32_t height)
+{
+   E_Client *ec;
+
+   /* get the client for this resource */
+   if (!(ec = wl_resource_get_user_data(resource)))
      {
-        serial = wl_display_next_serial(e_comp_wl->wl.disp);
-        xdg_surface_send_configure(resource, width, height, &states, serial);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No Client For Shell Surface");
+        return;
      }
+   if (ec->netwm.type == E_WINDOW_TYPE_POPUP_MENU) return;
 
-   wl_array_release(&states);
+   _xdg_shell_surface_send_configure(resource, ec->fullscreen, ec->maximized, 
edges, ec->focused, width, height);
 }
 
 static void
@@ -832,9 +884,45 @@ _e_xdg_shell_surface_cb_resize(struct wl_client *client 
EINA_UNUSED, struct wl_r
 }
 
 static void
-_e_xdg_shell_surface_cb_ack_configure(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource EINA_UNUSED, uint32_t serial EINA_UNUSED)
+_e_xdg_shell_surface_cb_ack_configure(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource, uint32_t serial)
 {
-   /* No-Op */
+   E_Client *ec;
+   Pending_State *ps;
+   E_Shell_Data *shd;
+
+   ec = wl_resource_get_user_data(resource);
+   if (!ec)
+     {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                "No Client For Shell Surface");
+        return;
+     }
+   shd = ec->comp_data->shell.data;
+   EINA_LIST_FREE(shd->pending, ps)
+     {
+        if (ps->serial > serial) break;
+        if (ps->state & STATE_FULLSCREEN)
+          {
+             ec->comp_data->shell.set.fullscreen = 1;
+             ec->comp_data->shell.set.unfullscreen = 0;
+          }
+        if (ps->state & STATE_UNFULLSCREEN)
+          {
+             ec->comp_data->shell.set.unfullscreen = 1;
+             ec->comp_data->shell.set.fullscreen = 0;
+          }
+        if (ps->state & STATE_MAXIMIZED)
+          {
+             ec->comp_data->shell.set.maximize = 1;
+             ec->comp_data->shell.set.unmaximize = 0;
+          }
+        if (ps->state & STATE_UNMAXIMIZED)
+          {
+             ec->comp_data->shell.set.unmaximize = 1;
+             ec->comp_data->shell.set.maximize = 0;
+          }
+        free(ps);
+     }
 }
 
 static void
@@ -857,6 +945,7 @@ static void
 _e_xdg_shell_surface_cb_maximized_set(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource)
 {
    E_Client *ec;
+   int w, h;
 
    /* get the client for this resource */
    if (!(ec = wl_resource_get_user_data(resource)))
@@ -867,11 +956,21 @@ _e_xdg_shell_surface_cb_maximized_set(struct wl_client 
*client EINA_UNUSED, stru
         return;
      }
 
-   if (!ec->lock_user_maximize)
+   if (ec->lock_user_maximize) return;
+   if (e_config->window_maximize_animate)
+     w = ec->w, h = ec->h;
+   else
      {
-        e_client_maximize(ec, ((e_config->maximize_policy & E_MAXIMIZE_TYPE) |
-                               E_MAXIMIZE_BOTH));
+        switch (e_config->maximize_policy & E_MAXIMIZE_TYPE)
+          {
+           case E_MAXIMIZE_FULLSCREEN:
+             w = ec->zone->w, h = ec->zone->h;
+             break;
+           default:
+             e_zone_useful_geometry_get(ec->zone, NULL, NULL, &w, &h);
+          }
      }
+   _xdg_shell_surface_send_configure(resource, ec->fullscreen, 1, 0, 
ec->focused, w, h);
 }
 
 static void
@@ -888,8 +987,8 @@ _e_xdg_shell_surface_cb_maximized_unset(struct wl_client 
*client EINA_UNUSED, st
         return;
      }
 
-   e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
-   _e_xdg_shell_surface_configure_send(resource, 0, ec->w, ec->h);
+   if (ec->lock_user_maximize) return;
+   _xdg_shell_surface_send_configure(resource, ec->fullscreen, 0, 0, 
ec->focused, ec->saved.w, ec->saved.h);
 }
 
 static void
@@ -906,8 +1005,8 @@ _e_xdg_shell_surface_cb_fullscreen_set(struct wl_client 
*client EINA_UNUSED, str
         return;
      }
 
-   if (!ec->lock_user_fullscreen)
-     e_client_fullscreen(ec, e_config->fullscreen_policy);
+   if (ec->lock_user_fullscreen) return;
+   _xdg_shell_surface_send_configure(resource, 1, ec->maximized, 0, 
ec->focused, ec->zone->w, ec->zone->h);
 }
 
 static void
@@ -924,8 +1023,8 @@ _e_xdg_shell_surface_cb_fullscreen_unset(struct wl_client 
*client EINA_UNUSED, s
         return;
      }
 
-   if (!ec->lock_user_fullscreen)
-     e_client_unfullscreen(ec);
+   if (ec->lock_user_fullscreen) return;
+   _xdg_shell_surface_send_configure(resource, 0, ec->maximized, 0, 
ec->focused, ec->saved.w, ec->saved.h);
 }
 
 static void
@@ -942,8 +1041,8 @@ _e_xdg_shell_surface_cb_minimized_set(struct wl_client 
*client EINA_UNUSED, stru
         return;
      }
 
-   if (!ec->lock_client_iconify)
-     e_client_iconify(ec);
+   if (!ec->lock_user_iconify)
+     ec->comp_data->shell.set.minimize = 1;
 }
 
 static const struct xdg_surface_interface _e_xdg_surface_interface =

-- 


Reply via email to