32#include "uwac-utils.h" 
   35#include <uwac/config.h> 
   37#include <winpr/cast.h> 
   39#define UWAC_INITIAL_BUFFERS 3ull 
   41static int bppFromShmFormat(
enum wl_shm_format format)
 
   45    case WL_SHM_FORMAT_ARGB8888:
 
   46    case WL_SHM_FORMAT_XRGB8888:
 
   52static void buffer_release(
void* data, 
struct wl_buffer* buffer)
 
   54  UwacBufferReleaseData* releaseData = data;
 
   55  UwacBuffer* uwacBuffer = &releaseData->window->buffers[releaseData->bufferIdx];
 
   56  uwacBuffer->used = 
false;
 
   59static const struct wl_buffer_listener buffer_listener = { buffer_release };
 
   61static void UwacWindowDestroyBuffers(UwacWindow* w)
 
   63  for (
size_t i = 0; i < w->nbuffers; i++)
 
   65    UwacBuffer* buffer = &w->buffers[i];
 
   66#ifdef UWAC_HAVE_PIXMAN_REGION 
   67    pixman_region32_fini(&buffer->damage);
 
   69    region16_uninit(&buffer->damage);
 
   71    UwacBufferReleaseData* releaseData =
 
   72        (UwacBufferReleaseData*)wl_buffer_get_user_data(buffer->wayland_buffer);
 
   73    wl_buffer_destroy(buffer->wayland_buffer);
 
   75    munmap(buffer->data, buffer->size);
 
   83static int UwacWindowShmAllocBuffers(UwacWindow* w, uint64_t nbuffers, uint64_t allocSize,
 
   84                                     uint32_t width, uint32_t height, 
enum wl_shm_format format);
 
   86static void xdg_handle_toplevel_configure(
void* data, 
struct xdg_toplevel* xdg_toplevel,
 
   87                                          int32_t width, int32_t height, 
struct wl_array* states)
 
   89  UwacWindow* window = (UwacWindow*)data;
 
   90  int scale = window->display->actual_scale;
 
   91  int32_t actual_width = width;
 
   92  int32_t actual_height = height;
 
   95  UwacConfigureEvent* 
event = NULL;
 
   98  enum xdg_toplevel_state* state = NULL;
 
  100  wl_array_for_each(state, states)
 
  104      case XDG_TOPLEVEL_STATE_MAXIMIZED:
 
  105        surfaceState |= UWAC_WINDOW_MAXIMIZED;
 
  108      case XDG_TOPLEVEL_STATE_FULLSCREEN:
 
  109        surfaceState |= UWAC_WINDOW_FULLSCREEN;
 
  112      case XDG_TOPLEVEL_STATE_ACTIVATED:
 
  113        surfaceState |= UWAC_WINDOW_ACTIVATED;
 
  116      case XDG_TOPLEVEL_STATE_RESIZING:
 
  117        surfaceState |= UWAC_WINDOW_RESIZING;
 
  124  window->surfaceStates = surfaceState;
 
  125  event = (UwacConfigureEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
 
  129    assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY,
 
  130                            "failed to allocate a configure event\n"));
 
  134  event->window = window;
 
  135  event->states = surfaceState;
 
  137  if ((width > 0 && height > 0) && (width != window->width || height != window->height))
 
  139    event->width = width;
 
  140    event->height = height;
 
  141    UwacWindowDestroyBuffers(window);
 
  142    window->width = width;
 
  143    window->stride = width * bppFromShmFormat(window->format);
 
  144    window->height = height;
 
  146        UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, 1ull * window->stride * height,
 
  147                                  width, height, window->format);
 
  149    if (ret != UWAC_SUCCESS)
 
  152          uwacErrorHandler(window->display, ret, 
"failed to reallocate a wayland buffers\n"));
 
  153      window->drawingBufferIdx = window->pendingBufferIdx = -1;
 
  157    window->drawingBufferIdx = 0;
 
  158    if (window->pendingBufferIdx != -1)
 
  159      window->pendingBufferIdx = window->drawingBufferIdx;
 
  161    if (window->viewport)
 
  163      wp_viewport_set_source(window->viewport, wl_fixed_from_int(0), wl_fixed_from_int(0),
 
  164                             wl_fixed_from_int(actual_width),
 
  165                             wl_fixed_from_int(actual_height));
 
  166      wp_viewport_set_destination(window->viewport, actual_width, actual_height);
 
  171    event->width = window->width;
 
  172    event->height = window->height;
 
  176static void xdg_handle_toplevel_close(
void* data, 
struct xdg_toplevel* xdg_toplevel)
 
  178  UwacCloseEvent* 
event = NULL;
 
  179  UwacWindow* window = (UwacWindow*)data;
 
  180  event = (UwacCloseEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CLOSE);
 
  184    assert(uwacErrorHandler(window->display, UWAC_ERROR_INTERNAL,
 
  185                            "failed to allocate a close event\n"));
 
  189  event->window = window;
 
  192static const struct xdg_toplevel_listener xdg_toplevel_listener = {
 
  193  xdg_handle_toplevel_configure,
 
  194  xdg_handle_toplevel_close,
 
  197static void xdg_handle_surface_configure(
void* data, 
struct xdg_surface* xdg_surface,
 
  200  xdg_surface_ack_configure(xdg_surface, serial);
 
  203static const struct xdg_surface_listener xdg_surface_listener = {
 
  204  .configure = xdg_handle_surface_configure,
 
  209static void ivi_handle_configure(
void* data, 
struct ivi_surface* surface, int32_t width,
 
  212  UwacWindow* window = (UwacWindow*)data;
 
  213  UwacConfigureEvent* 
event = NULL;
 
  215  event = (UwacConfigureEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
 
  219    assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY,
 
  220                            "failed to allocate a configure event\n"));
 
  224  event->window = window;
 
  229    event->width = width;
 
  230    event->height = height;
 
  231    UwacWindowDestroyBuffers(window);
 
  232    window->width = width;
 
  233    window->stride = width * bppFromShmFormat(window->format);
 
  234    window->height = height;
 
  236        UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, 1ull * window->stride * height,
 
  237                                  width, height, window->format);
 
  239    if (ret != UWAC_SUCCESS)
 
  242          uwacErrorHandler(window->display, ret, 
"failed to reallocate a wayland buffers\n"));
 
  243      window->drawingBufferIdx = window->pendingBufferIdx = -1;
 
  247    window->drawingBufferIdx = 0;
 
  248    if (window->pendingBufferIdx != -1)
 
  249      window->pendingBufferIdx = window->drawingBufferIdx;
 
  253    event->width = window->width;
 
  254    event->height = window->height;
 
  258static const struct ivi_surface_listener ivi_surface_listener = {
 
  259  ivi_handle_configure,
 
  263static void shell_ping(
void* data, 
struct wl_shell_surface* surface, uint32_t serial)
 
  265  wl_shell_surface_pong(surface, serial);
 
  268static void shell_configure(
void* data, 
struct wl_shell_surface* surface, uint32_t edges,
 
  269                            int32_t width, int32_t height)
 
  271  UwacWindow* window = (UwacWindow*)data;
 
  272  UwacConfigureEvent* 
event = NULL;
 
  274  event = (UwacConfigureEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
 
  278    assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY,
 
  279                            "failed to allocate a configure event\n"));
 
  283  event->window = window;
 
  288    event->width = width;
 
  289    event->height = height;
 
  290    UwacWindowDestroyBuffers(window);
 
  291    window->width = width;
 
  292    window->stride = width * bppFromShmFormat(window->format);
 
  293    window->height = height;
 
  295        UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, 1ull * window->stride * height,
 
  296                                  width, height, window->format);
 
  298    if (ret != UWAC_SUCCESS)
 
  301          uwacErrorHandler(window->display, ret, 
"failed to reallocate a wayland buffers\n"));
 
  302      window->drawingBufferIdx = window->pendingBufferIdx = -1;
 
  306    window->drawingBufferIdx = 0;
 
  307    if (window->pendingBufferIdx != -1)
 
  308      window->pendingBufferIdx = window->drawingBufferIdx;
 
  312    event->width = window->width;
 
  313    event->height = window->height;
 
  317static void shell_popup_done(
void* data, 
struct wl_shell_surface* surface)
 
  321static const struct wl_shell_surface_listener shell_listener = { shell_ping, shell_configure,
 
  324int UwacWindowShmAllocBuffers(UwacWindow* w, uint64_t nbuffers, uint64_t allocSize, uint32_t width,
 
  325                              uint32_t height, 
enum wl_shm_format format)
 
  327  int ret = UWAC_SUCCESS;
 
  330  struct wl_shm_pool* pool = NULL;
 
  332  if ((width > INT32_MAX) || (height > INT32_MAX))
 
  333    return UWAC_ERROR_NOMEMORY;
 
  335  const int64_t pagesize = sysconf(_SC_PAGESIZE);
 
  337    return UWAC_ERROR_NOMEMORY;
 
  340  const uint64_t test = (1ull * allocSize + (size_t)pagesize - 1ull) & ~((size_t)pagesize - 1);
 
  341  if (test > INT64_MAX)
 
  342    return UWAC_ERROR_NOMEMORY;
 
  346  UwacBuffer* newBuffers =
 
  347      xrealloc(w->buffers, (0ull + w->nbuffers + nbuffers) * 
sizeof(UwacBuffer));
 
  350    return UWAC_ERROR_NOMEMORY;
 
  352  w->buffers = newBuffers;
 
  353  memset(w->buffers + w->nbuffers, 0, 
sizeof(UwacBuffer) * nbuffers);
 
  355  const size_t allocbuffersize = 1ull * allocSize * nbuffers;
 
  356  if (allocbuffersize > INT32_MAX)
 
  357    return UWAC_ERROR_NOMEMORY;
 
  359  fd = uwac_create_anonymous_file(WINPR_ASSERTING_INT_CAST(off_t, allocbuffersize));
 
  363    return UWAC_ERROR_INTERNAL;
 
  366  data = mmap(NULL, allocbuffersize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 
  368  if (data == MAP_FAILED)
 
  370    ret = UWAC_ERROR_NOMEMORY;
 
  374  pool = wl_shm_create_pool(w->display->shm, fd, (int32_t)allocbuffersize);
 
  378    munmap(data, allocbuffersize);
 
  379    ret = UWAC_ERROR_NOMEMORY;
 
  383  for (uint64_t i = 0; i < nbuffers; i++)
 
  385    const size_t idx = (size_t)i;
 
  386    const size_t bufferIdx = w->nbuffers + idx;
 
  387    UwacBuffer* buffer = &w->buffers[bufferIdx];
 
  389#ifdef UWAC_HAVE_PIXMAN_REGION 
  390    pixman_region32_init(&buffer->damage);
 
  392    region16_init(&buffer->damage);
 
  394    const size_t offset = allocSize * idx;
 
  395    if (offset > INT32_MAX)
 
  398    buffer->data = &((
char*)data)[allocSize * idx];
 
  399    buffer->size = allocSize;
 
  400    buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, (int32_t)offset, (int32_t)width,
 
  401                                                       (int32_t)height, w->stride, format);
 
  402    UwacBufferReleaseData* listener_data = xmalloc(
sizeof(UwacBufferReleaseData));
 
  403    listener_data->window = w;
 
  404    listener_data->bufferIdx = bufferIdx;
 
  405    wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, listener_data);
 
  408  wl_shm_pool_destroy(pool);
 
  409  w->nbuffers += nbuffers;
 
  415static UwacBuffer* UwacWindowFindFreeBuffer(UwacWindow* w, ssize_t* index)
 
  423  for (; i < w->nbuffers; i++)
 
  425    if (!w->buffers[i].used)
 
  427      w->buffers[i].used = 
true;
 
  429        *index = WINPR_ASSERTING_INT_CAST(ssize_t, i);
 
  430      return &w->buffers[i];
 
  434  ret = UwacWindowShmAllocBuffers(w, 2, 1ull * w->stride * w->height, w->width, w->height,
 
  437  if (ret != UWAC_SUCCESS)
 
  439    w->display->last_error = ret;
 
  443  w->buffers[i].used = 
true;
 
  445    *index = WINPR_ASSERTING_INT_CAST(ssize_t, i);
 
  446  return &w->buffers[i];
 
  449static UwacReturnCode UwacWindowSetDecorations(UwacWindow* w)
 
  451  if (!w || !w->display)
 
  452    return UWAC_ERROR_INTERNAL;
 
  454  if (w->display->deco_manager)
 
  456    w->deco = zxdg_decoration_manager_v1_get_toplevel_decoration(w->display->deco_manager,
 
  460      uwacErrorHandler(w->display, UWAC_NOT_FOUND,
 
  461                       "Current window manager does not allow decorating with SSD");
 
  464      zxdg_toplevel_decoration_v1_set_mode(w->deco,
 
  465                                           ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
 
  467  else if (w->display->kde_deco_manager)
 
  470        org_kde_kwin_server_decoration_manager_create(w->display->kde_deco_manager, w->surface);
 
  473      uwacErrorHandler(w->display, UWAC_NOT_FOUND,
 
  474                       "Current window manager does not allow decorating with SSD");
 
  477      org_kde_kwin_server_decoration_request_mode(w->kde_deco,
 
  478                                                  ORG_KDE_KWIN_SERVER_DECORATION_MODE_SERVER);
 
  483UwacWindow* UwacCreateWindowShm(UwacDisplay* display, uint32_t width, uint32_t height,
 
  484                                enum wl_shm_format format)
 
  486  UwacWindow* w = NULL;
 
  494  w = xzalloc(
sizeof(*w));
 
  498    display->last_error = UWAC_ERROR_NOMEMORY;
 
  502  w->display = display;
 
  504  w->width = WINPR_ASSERTING_INT_CAST(int32_t, width);
 
  505  w->height = WINPR_ASSERTING_INT_CAST(int32_t, height);
 
  506  w->stride = WINPR_ASSERTING_INT_CAST(int32_t, width* bppFromShmFormat(format));
 
  507  const size_t allocSize = 1ULL * w->stride * height;
 
  508  ret = UwacWindowShmAllocBuffers(w, UWAC_INITIAL_BUFFERS, allocSize, width, height, format);
 
  510  if (ret != UWAC_SUCCESS)
 
  512    display->last_error = ret;
 
  516  w->buffers[0].used = 
true;
 
  517  w->drawingBufferIdx = 0;
 
  518  w->pendingBufferIdx = -1;
 
  519  w->surface = wl_compositor_create_surface(display->compositor);
 
  523    display->last_error = UWAC_ERROR_NOMEMORY;
 
  524    goto out_error_surface;
 
  527  wl_surface_set_user_data(w->surface, w);
 
  530  uint32_t ivi_surface_id = 1;
 
  532  char* env = getenv(
"IVI_SURFACE_ID");
 
  535    unsigned long val = 0;
 
  539    val = strtoul(env, &endp, 10);
 
  541    if (!errno && val != 0 && val != UINT32_MAX)
 
  542      ivi_surface_id = val;
 
  545  if (display->ivi_application)
 
  548        ivi_application_surface_create(display->ivi_application, ivi_surface_id, w->surface);
 
  549    assert(w->ivi_surface);
 
  550    ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w);
 
  554#if BUILD_FULLSCREEN_SHELL 
  555      if (display->fullscreen_shell)
 
  557    zwp_fullscreen_shell_v1_present_surface(display->fullscreen_shell, w->surface,
 
  558                                            ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
 
  563      if (display->xdg_base)
 
  565    w->xdg_surface = xdg_wm_base_get_xdg_surface(display->xdg_base, w->surface);
 
  569      display->last_error = UWAC_ERROR_NOMEMORY;
 
  570      goto out_error_shell;
 
  573    xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
 
  575    w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
 
  576    if (!w->xdg_toplevel)
 
  578      display->last_error = UWAC_ERROR_NOMEMORY;
 
  579      goto out_error_shell;
 
  582    assert(w->xdg_surface);
 
  583    xdg_toplevel_add_listener(w->xdg_toplevel, &xdg_toplevel_listener, w);
 
  584    wl_surface_commit(w->surface);
 
  585    wl_display_roundtrip(w->display->display);
 
  589    w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface);
 
  590    assert(w->shell_surface);
 
  591    wl_shell_surface_add_listener(w->shell_surface, &shell_listener, w);
 
  592    wl_shell_surface_set_toplevel(w->shell_surface);
 
  595  if (display->viewporter)
 
  597    w->viewport = wp_viewporter_get_viewport(display->viewporter, w->surface);
 
  598    if (display->actual_scale != 1)
 
  599      wl_surface_set_buffer_scale(w->surface, display->actual_scale);
 
  602  wl_list_insert(display->windows.prev, &w->link);
 
  603  display->last_error = UWAC_SUCCESS;
 
  604  UwacWindowSetDecorations(w);
 
  607  wl_surface_destroy(w->surface);
 
  609  UwacWindowDestroyBuffers(w);
 
  615UwacReturnCode UwacDestroyWindow(UwacWindow** pwindow)
 
  617  UwacWindow* w = NULL;
 
  620  UwacWindowDestroyBuffers(w);
 
  623    zxdg_toplevel_decoration_v1_destroy(w->deco);
 
  626    org_kde_kwin_server_decoration_destroy(w->kde_deco);
 
  629    xdg_surface_destroy(w->xdg_surface);
 
  634    ivi_surface_destroy(w->ivi_surface);
 
  638  if (w->opaque_region)
 
  639    wl_region_destroy(w->opaque_region);
 
  642    wl_region_destroy(w->input_region);
 
  645    wp_viewport_destroy(w->viewport);
 
  647  wl_surface_destroy(w->surface);
 
  648  wl_list_remove(&w->link);
 
  654UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
 
  659  if (window->opaque_region)
 
  660    wl_region_destroy(window->opaque_region);
 
  662  window->opaque_region = wl_compositor_create_region(window->display->compositor);
 
  664  if (!window->opaque_region)
 
  665    return UWAC_ERROR_NOMEMORY;
 
  667  wl_region_add(window->opaque_region, WINPR_ASSERTING_INT_CAST(int32_t, x),
 
  668                WINPR_ASSERTING_INT_CAST(int32_t, y), WINPR_ASSERTING_INT_CAST(int32_t, width),
 
  669                WINPR_ASSERTING_INT_CAST(int32_t, height));
 
  670  wl_surface_set_opaque_region(window->surface, window->opaque_region);
 
  674UwacReturnCode UwacWindowSetInputRegion(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
 
  679  if (window->input_region)
 
  680    wl_region_destroy(window->input_region);
 
  682  window->input_region = wl_compositor_create_region(window->display->compositor);
 
  684  if (!window->input_region)
 
  685    return UWAC_ERROR_NOMEMORY;
 
  687  wl_region_add(window->input_region, WINPR_ASSERTING_INT_CAST(int32_t, x),
 
  688                WINPR_ASSERTING_INT_CAST(int32_t, y), WINPR_ASSERTING_INT_CAST(int32_t, width),
 
  689                WINPR_ASSERTING_INT_CAST(int32_t, height));
 
  690  wl_surface_set_input_region(window->surface, window->input_region);
 
  694void* UwacWindowGetDrawingBuffer(UwacWindow* window)
 
  696  UwacBuffer* buffer = NULL;
 
  698  if (window->drawingBufferIdx < 0)
 
  701  buffer = &window->buffers[window->drawingBufferIdx];
 
  708static void frame_done_cb(
void* data, 
struct wl_callback* callback, uint32_t time);
 
  710static const struct wl_callback_listener frame_listener = { frame_done_cb };
 
  712#ifdef UWAC_HAVE_PIXMAN_REGION 
  713static void damage_surface(UwacWindow* window, UwacBuffer* buffer, 
int scale)
 
  716  const pixman_box32_t* box = pixman_region32_rectangles(&buffer->damage, &nrects);
 
  718  for (
int i = 0; i < nrects; i++, box++)
 
  720    const int x = ((int)floor(box->x1 / scale)) - 1;
 
  721    const int y = ((int)floor(box->y1 / scale)) - 1;
 
  722    const int w = ((int)ceil((box->x2 - box->x1) / scale)) + 2;
 
  723    const int h = ((int)ceil((box->y2 - box->y1) / scale)) + 2;
 
  724    wl_surface_damage(window->surface, x, y, w, h);
 
  727  pixman_region32_clear(&buffer->damage);
 
  730static void damage_surface(UwacWindow* window, UwacBuffer* buffer, 
int scale)
 
  733  const RECTANGLE_16* boxes = region16_rects(&buffer->damage, &nrects);
 
  735  for (UINT32 i = 0; i < nrects; i++)
 
  738    const double dx = floor(1.0 * box->left / scale);
 
  739    const double dy = floor(1.0 * box->top / scale);
 
  740    const double dw = ceil(1.0 * (box->right - box->left) / scale);
 
  741    const double dh = ceil(1.0 * (box->bottom - box->top) / scale);
 
  742    const int x = ((int)dx) - 1;
 
  743    const int y = ((int)dy) - 1;
 
  744    const int w = ((int)dw) + 2;
 
  745    const int h = ((int)dh) + 2;
 
  746    wl_surface_damage(window->surface, x, y, w, h);
 
  749  region16_clear(&buffer->damage);
 
  753static void UwacSubmitBufferPtr(UwacWindow* window, UwacBuffer* buffer)
 
  755  wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0);
 
  757  int scale = window->display->actual_scale;
 
  758  damage_surface(window, buffer, scale);
 
  760  struct wl_callback* frame_callback = wl_surface_frame(window->surface);
 
  761  wl_callback_add_listener(frame_callback, &frame_listener, window);
 
  762  wl_surface_commit(window->surface);
 
  763  buffer->dirty = 
false;
 
  766static void frame_done_cb(
void* data, 
struct wl_callback* callback, uint32_t time)
 
  768  UwacWindow* window = (UwacWindow*)data;
 
  769  UwacFrameDoneEvent* 
event = NULL;
 
  771  wl_callback_destroy(callback);
 
  772  window->pendingBufferIdx = -1;
 
  773  event = (UwacFrameDoneEvent*)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
 
  776    event->window = window;
 
  779#ifdef UWAC_HAVE_PIXMAN_REGION 
  780UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
 
  783  UwacBuffer* buf = NULL;
 
  785  if (window->drawingBufferIdx < 0)
 
  786    return UWAC_ERROR_INTERNAL;
 
  788  buf = &window->buffers[window->drawingBufferIdx];
 
  789  if (!pixman_region32_union_rect(&buf->damage, &buf->damage, x, y, width, height))
 
  790    return UWAC_ERROR_INTERNAL;
 
  796UwacReturnCode UwacWindowAddDamage(UwacWindow* window, uint32_t x, uint32_t y, uint32_t width,
 
  800  UwacBuffer* buf = NULL;
 
  804  box.right = x + width;
 
  805  box.bottom = y + height;
 
  807  if (window->drawingBufferIdx < 0)
 
  808    return UWAC_ERROR_INTERNAL;
 
  810  buf = &window->buffers[window->drawingBufferIdx];
 
  812    return UWAC_ERROR_INTERNAL;
 
  814  if (!region16_union_rect(&buf->damage, &buf->damage, &box))
 
  815    return UWAC_ERROR_INTERNAL;
 
  822UwacReturnCode UwacWindowGetDrawingBufferGeometry(UwacWindow* window, UwacSize* geometry,
 
  825  if (!window || (window->drawingBufferIdx < 0))
 
  826    return UWAC_ERROR_INTERNAL;
 
  830    geometry->width = window->width;
 
  831    geometry->height = window->height;
 
  835    *stride = window->stride;
 
  840UwacReturnCode UwacWindowSubmitBuffer(UwacWindow* window, 
bool copyContentForNextFrame)
 
  842  UwacBuffer* currentDrawingBuffer = NULL;
 
  843  UwacBuffer* nextDrawingBuffer = NULL;
 
  844  UwacBuffer* pendingBuffer = NULL;
 
  846  if (window->drawingBufferIdx < 0)
 
  847    return UWAC_ERROR_INTERNAL;
 
  849  currentDrawingBuffer = &window->buffers[window->drawingBufferIdx];
 
  851  if ((window->pendingBufferIdx >= 0) || !currentDrawingBuffer->dirty)
 
  854  window->pendingBufferIdx = window->drawingBufferIdx;
 
  855  nextDrawingBuffer = UwacWindowFindFreeBuffer(window, &window->drawingBufferIdx);
 
  856  pendingBuffer = &window->buffers[window->pendingBufferIdx];
 
  858  if ((!nextDrawingBuffer) || (window->drawingBufferIdx < 0))
 
  859    return UWAC_ERROR_NOMEMORY;
 
  861  if (copyContentForNextFrame)
 
  862    memcpy(nextDrawingBuffer->data, pendingBuffer->data,
 
  863           1ull * window->stride * window->height);
 
  865  UwacSubmitBufferPtr(window, pendingBuffer);
 
  869UwacReturnCode UwacWindowGetGeometry(UwacWindow* window, UwacSize* geometry)
 
  873  geometry->width = window->width;
 
  874  geometry->height = window->height;
 
  878UwacReturnCode UwacWindowSetFullscreenState(UwacWindow* window, UwacOutput* output,
 
  881  if (window->xdg_toplevel)
 
  885      xdg_toplevel_set_fullscreen(window->xdg_toplevel, output ? output->output : NULL);
 
  889      xdg_toplevel_unset_fullscreen(window->xdg_toplevel);
 
  892  else if (window->shell_surface)
 
  896      wl_shell_surface_set_fullscreen(window->shell_surface,
 
  897                                      WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0,
 
  898                                      output ? output->output : NULL);
 
  902      wl_shell_surface_set_toplevel(window->shell_surface);
 
  909void UwacWindowSetTitle(UwacWindow* window, 
const char* name)
 
  911  if (window->xdg_toplevel)
 
  912    xdg_toplevel_set_title(window->xdg_toplevel, name);
 
  913  else if (window->shell_surface)
 
  914    wl_shell_surface_set_title(window->shell_surface, name);
 
  917void UwacWindowSetAppId(UwacWindow* window, 
const char* app_id)
 
  919  if (window->xdg_toplevel)
 
  920    xdg_toplevel_set_app_id(window->xdg_toplevel, app_id);