title: How to create an EGL window in Wayland and set its position on screen?
body: <p>I have a working program that creates an EGL window in Wayland. I can control the window size, but not its position on the screen. Right now, if I set the size to match the size of the screen, it will run fullscreen but if I set anything less than that, it will just appear in a different random position every time.</p>
  <p>I've read that the top surface can't be moved and that if I want to control the surface's position, I have to use a subsurface. However, I wasn't able to find any useful examples. Especially, I wasn't able to find any examples for EGL, which has some caviats.</p>
  <p>Anyway, here's the important bit from my program:</p>
  <pre><code>static struct waylandContext {
      struct wl_display* display;
      struct wl_registry* registry;
      struct wl_compositor* compositor;
      struct wl_shell* shell;
      struct wl_surface* surface;
      struct wl_shell_surface* shell_surface;
      struct wl_egl_window* egl_window;
  } wlContext;
  
  static void registry_add_object(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
  {
      if (!strcmp(interface, &quot;wl_compositor&quot;)) {
          wlContext.compositor = wl_registry_bind(registry, name, &amp;wl_compositor_interface, 1);
      } else if (!strcmp(interface, &quot;wl_shell&quot;)) {
          wlContext.shell = wl_registry_bind(registry, name, &amp;wl_shell_interface, 1);
      }
  }
  
  static void registry_remove_object(void* data, struct wl_registry* registry, uint32_t name)
  {
  }
  
  static struct wl_registry_listener registry_listener = {
      &amp;registry_add_object,
      &amp;registry_remove_object
  };
  
  static void shell_surface_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
  {
      wl_shell_surface_pong(shell_surface, serial);
  }
  
  static void shell_surface_configure(void* data, struct wl_shell_surface* shell_surface, uint32_t edges, int32_t width, int32_t height)
  {
      struct window* window = data;
      wl_egl_window_resize(wlContext.egl_window, width, height, 0, 0);
  }
  
  static void shell_surface_popup_done(void* data, struct wl_shell_surface* shell_surface)
  {
  }
  
  static struct wl_shell_surface_listener shell_surface_listener = {
      &amp;shell_surface_ping,
      &amp;shell_surface_configure,
      &amp;shell_surface_popup_done
  };
  
  static bool initWayland(int width, int height)
  {
      wlContext.display = wl_display_connect(NULL);
      if (!wlContext.display) {
          fprintf(stderr, &quot;failed to connect to display\n&quot;);
          return false;
      }
  
      wlContext.registry = wl_display_get_registry(wlContext.display);
      wl_registry_add_listener(wlContext.registry, &amp;registry_listener, NULL);
      wl_display_dispatch(wlContext.display);
      wl_display_roundtrip(wlContext.display);
  
      wlContext.surface = wl_compositor_create_surface(wlContext.compositor);
      wlContext.shell_surface = wl_shell_get_shell_surface(wlContext.shell, wlContext.surface);
      wl_shell_surface_add_listener(wlContext.shell_surface, &amp;shell_surface_listener, NULL);
      wl_shell_surface_set_toplevel(wlContext.shell_surface);
      wlContext.egl_window = wl_egl_window_create(wlContext.surface, width, height);
  
      return true;
  }
  </code></pre>
  <p>I tried changing the code to this:</p>
  <pre><code>static struct waylandContext {
      struct wl_display* display;
      struct wl_registry* registry;
      struct wl_compositor* compositor;
      struct wl_subcompositor* subcompositor;
      struct wl_shell* shell;
      struct wl_surface* parent_surface;
      struct wl_surface* child_surface;
      struct wl_subsurface* subsurface;
      struct wl_shell_surface* shell_surface;
      struct wl_egl_window* egl_window;
      struct wl_egl_window* egl_window2;
  } wlContext;
  
  static void registry_add_object(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
  {
      if (!strcmp(interface, &quot;wl_compositor&quot;)) {
          wlContext.compositor = wl_registry_bind(registry, name, &amp;wl_compositor_interface, 1);
      } else if (!strcmp(interface, &quot;wl_subcompositor&quot;)) {
          wlContext.subcompositor = wl_registry_bind(registry, name, &amp;wl_subcompositor_interface, 1);
      } else if (!strcmp(interface, &quot;wl_shell&quot;)) {
          wlContext.shell = wl_registry_bind(registry, name, &amp;wl_shell_interface, 1);
      }
  }
  
  static void registry_remove_object(void* data, struct wl_registry* registry, uint32_t name)
  {
  }
  
  static struct wl_registry_listener registry_listener = {
      &amp;registry_add_object,
      &amp;registry_remove_object
  };
  
  static void shell_surface_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
  {
      wl_shell_surface_pong(shell_surface, serial);
  }
  
  static void shell_surface_configure(void* data, struct wl_shell_surface* shell_surface, uint32_t edges, int32_t width, int32_t height)
  {
      struct window* window = data;
      wl_egl_window_resize(wlContext.egl_window, width, height, 0, 0);
  }
  
  static void shell_surface_popup_done(void* data, struct wl_shell_surface* shell_surface)
  {
  }
  
  static struct wl_shell_surface_listener shell_surface_listener = {
      &amp;shell_surface_ping,
      &amp;shell_surface_configure,
      &amp;shell_surface_popup_done
  };
  
  static bool initWayland(int width, int height)
  {
      wlContext.display = wl_display_connect(NULL);
      if (!wlContext.display) {
          fprintf(stderr, &quot;failed to connect to display\n&quot;);
          return false;
      }
  
      wlContext.registry = wl_display_get_registry(wlContext.display);
      wl_registry_add_listener(wlContext.registry, &amp;registry_listener, NULL);
      wl_display_dispatch(wlContext.display);
      wl_display_roundtrip(wlContext.display);
  
      wlContext.parent_surface = wl_compositor_create_surface(wlContext.compositor);
      wlContext.shell_surface = wl_shell_get_shell_surface(wlContext.shell, wlContext.parent_surface);
      wl_shell_surface_add_listener(wlContext.shell_surface, &amp;shell_surface_listener, NULL);
      wl_shell_surface_set_toplevel(wlContext.shell_surface);
  
      wlContext.child_surface = wl_compositor_create_surface(wlContext.compositor);
      wlContext.subsurface = wl_subcompositor_get_subsurface(wlContext.subcompositor, wlContext.child_surface, wlContext.parent_surface);
  
      wlContext.egl_window = wl_egl_window_create(wlContext.child_surface, width, height);
  
      return true;
  }
  </code></pre>
  <p>Where I get subcompositor, create a child surface and create the EGL window from that child surface. However, this doesn't work and I'm not sure why.</p>
  <p>Maybe I should add, how I work with EGL, but it's just standard stuff. After I create the EGL window, I have the regular sequence of calls like <code>eglInitialize</code>, <code>eglCreateContext</code>, etc. Then I create an OpenGL context, draw something and call <code>eglSwapBuffers</code>. When I do it with the subsurface, <code>eglSwapBuffers</code> runs once but nothing shows and then when I call <code>eglSwapBuffers</code> the second time, it freezes forever.</p>