mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-22 15:31:14 +00:00
Merge pull request #34 from nongio/wayland-shm-surface
Wayland shm surface
This commit is contained in:
commit
06be91b267
9 changed files with 313 additions and 262 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
WaylandCairoSurface.h
|
||||
WaylandCairoShmSurface.h
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
|
@ -25,14 +25,15 @@
|
|||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef WaylandCairoSurface_h
|
||||
#define WaylandCairoSurface_h
|
||||
#ifndef WaylandCairoShmSurface_h
|
||||
#define WaylandCairoShmSurface_h
|
||||
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
@interface WaylandCairoSurface : CairoSurface
|
||||
@interface WaylandCairoShmSurface : CairoSurface
|
||||
{
|
||||
}
|
||||
- (void)destroySurface;
|
||||
@end
|
||||
|
||||
#endif
|
|
@ -37,7 +37,8 @@
|
|||
#include <cairo/cairo.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include "cairo/WaylandCairoSurface.h"
|
||||
#include "cairo/CairoSurface.h"
|
||||
|
||||
#include "wayland/xdg-shell-client-protocol.h"
|
||||
#include "wayland/wlr-layer-shell-client-protocol.h"
|
||||
|
||||
|
@ -129,8 +130,6 @@ struct window
|
|||
int is_out;
|
||||
int level;
|
||||
|
||||
unsigned char *data;
|
||||
struct wl_buffer *buffer;
|
||||
struct wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *toplevel;
|
||||
|
@ -138,7 +137,7 @@ struct window
|
|||
struct xdg_positioner *positioner;
|
||||
struct zwlr_layer_surface_v1 *layer_surface;
|
||||
struct output *output;
|
||||
WaylandCairoSurface *wcs;
|
||||
CairoSurface *wcs;
|
||||
};
|
||||
|
||||
@interface WaylandServer : GSDisplayServer
|
||||
|
|
|
@ -73,9 +73,9 @@
|
|||
#elif BUILD_SERVER == SERVER_wayland
|
||||
# include "wayland/WaylandServer.h"
|
||||
# include "cairo/CairoGState.h"
|
||||
# include "cairo/WaylandCairoSurface.h"
|
||||
# include "cairo/WaylandCairoShmSurface.h"
|
||||
# define _CAIRO_GSTATE_CLASSNAME CairoGState
|
||||
# define _CAIRO_SURFACE_CLASSNAME WaylandCairoSurface
|
||||
# define _CAIRO_SURFACE_CLASSNAME WaylandCairoShmSurface
|
||||
#else
|
||||
# error Invalid server for Cairo backend : non implemented
|
||||
#endif /* BUILD_SERVER */
|
||||
|
|
|
@ -50,7 +50,7 @@ ifeq ($(BUILD_SERVER),x11)
|
|||
endif
|
||||
else
|
||||
ifeq ($(BUILD_SERVER),wayland)
|
||||
cairo_OBJC_FILES += WaylandCairoSurface.m
|
||||
cairo_OBJC_FILES += WaylandCairoShmSurface.m
|
||||
else
|
||||
ifeq ($(BUILD_GRAPHICS),cairo)
|
||||
ifeq ($(WITH_GLITZ),yes)
|
||||
|
|
275
Source/cairo/WaylandCairoShmSurface.m
Normal file
275
Source/cairo/WaylandCairoShmSurface.m
Normal file
|
@ -0,0 +1,275 @@
|
|||
/* WaylandCairoSurface
|
||||
|
||||
WaylandCairoShmSurface - A cairo surface backed by a wayland
|
||||
shared memory buffer.
|
||||
After the wayland surface is configured, the buffer needs to be
|
||||
attached to the surface. Subsequent changes to the cairo surface
|
||||
needs to be notified to the wayland server using wl_surface_damage
|
||||
and wl_surface_commit. The buffer is freed after the compositor
|
||||
releases it and the cairo surface is not in use.
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
Author: Sergio L. Pascual <slp@sinrega.org>
|
||||
Rewrite: Riccardo Canalicchio <riccardo.canalicchio(at)gmail.com>
|
||||
Date: November 2021
|
||||
|
||||
This file is part of the GNU Objective C Backend Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "wayland/WaylandServer.h"
|
||||
#include "cairo/WaylandCairoShmSurface.h"
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
struct pool_buffer
|
||||
{
|
||||
int poolfd;
|
||||
struct wl_shm_pool *pool;
|
||||
struct wl_buffer *buffer;
|
||||
cairo_surface_t *surface;
|
||||
uint32_t width, height;
|
||||
void *data;
|
||||
size_t size;
|
||||
bool busy;
|
||||
};
|
||||
|
||||
static const enum wl_shm_format wl_fmt = WL_SHM_FORMAT_ARGB8888;
|
||||
static const cairo_format_t cairo_fmt = CAIRO_FORMAT_ARGB32;
|
||||
|
||||
static void
|
||||
finishBuffer(struct pool_buffer *buf)
|
||||
{
|
||||
// The buffer can be deleted if it has been released by the compositor
|
||||
// and if not used by the cairo surface
|
||||
if(buf == NULL || buf->busy || buf->surface != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (buf->buffer)
|
||||
{
|
||||
wl_buffer_destroy(buf->buffer);
|
||||
}
|
||||
if (buf->data)
|
||||
{
|
||||
munmap(buf->data, buf->size);
|
||||
}
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_handle_release(void *data, struct wl_buffer *wl_buffer)
|
||||
{
|
||||
struct pool_buffer *buffer = data;
|
||||
buffer->busy = false;
|
||||
// If the buffer was not released before dealloc
|
||||
finishBuffer(buffer);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
// Sent by the compositor when it's no longer using a buffer
|
||||
.release = buffer_handle_release,
|
||||
};
|
||||
|
||||
// Creates a file descriptor for the compositor to share pixel buffers
|
||||
static int
|
||||
createPoolFile(off_t size)
|
||||
{
|
||||
static const char template[] = "/gnustep-shared-XXXXXX";
|
||||
const char *path;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
path = getenv("XDG_RUNTIME_DIR");
|
||||
if (!path)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
name = malloc(strlen(path) + sizeof(template));
|
||||
if (!name)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(name, path);
|
||||
strcat(name, template);
|
||||
|
||||
fd = memfd_create(name, MFD_CLOEXEC);
|
||||
|
||||
free(name);
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (ftruncate(fd, size) != 0)
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static struct pool_buffer *
|
||||
createBufferForWindow(struct window * window, struct wl_shm *shm)
|
||||
{
|
||||
uint32_t stride = cairo_format_stride_for_width(cairo_fmt, window->width);
|
||||
size_t size = stride * window->height;
|
||||
|
||||
struct pool_buffer * buf = malloc(sizeof(struct pool_buffer));
|
||||
|
||||
void *data = NULL;
|
||||
if (size > 0)
|
||||
{
|
||||
buf->poolfd = createPoolFile(size);
|
||||
if (buf->poolfd == -1)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data
|
||||
= mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, buf->poolfd, 0);
|
||||
if (data == MAP_FAILED)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf->pool = wl_shm_create_pool(shm, buf->poolfd, size);
|
||||
buf->buffer = wl_shm_pool_create_buffer(buf->pool, 0, window->width, window->height,
|
||||
stride, wl_fmt);
|
||||
wl_buffer_add_listener(buf->buffer, &buffer_listener, buf);
|
||||
}
|
||||
|
||||
buf->data = data;
|
||||
buf->size = size;
|
||||
buf->width = window->width;
|
||||
buf->height = window->height;
|
||||
buf->surface = cairo_image_surface_create_for_data(data, cairo_fmt, window->width, window->height, stride);
|
||||
|
||||
wl_shm_pool_destroy(buf->pool);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
@implementation WaylandCairoShmSurface
|
||||
{
|
||||
struct pool_buffer *pbuffer;
|
||||
}
|
||||
- (id)initWithDevice:(void *)device
|
||||
{
|
||||
struct window *window = (struct window *) device;
|
||||
NSDebugLog(@"WaylandCairoShmSurface: initWithDevice win=%d",
|
||||
window->window_id);
|
||||
|
||||
gsDevice = device;
|
||||
|
||||
pbuffer = createBufferForWindow(window, window->wlconfig->shm);
|
||||
|
||||
if (pbuffer == NULL)
|
||||
{
|
||||
NSDebugLog(@"failed to obtain buffer");
|
||||
return nil;
|
||||
}
|
||||
|
||||
_surface = pbuffer->surface;
|
||||
|
||||
window->buffer_needs_attach = YES;
|
||||
if (_surface == NULL)
|
||||
{
|
||||
NSDebugLog(@"can't create cairo surface");
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (window->configured)
|
||||
{
|
||||
// we can attach a buffer to the surface only if the surface is configured
|
||||
// this is usually done in the configure event handler
|
||||
// in case of resize of an already configured surface
|
||||
// we should reattach the new allocated buffer
|
||||
NSDebugLog(@"wl_surface_attach: win=%d",
|
||||
window->window_id);
|
||||
window->buffer_needs_attach = NO;
|
||||
wl_surface_attach(window->surface, pbuffer->buffer, 0, 0);
|
||||
wl_surface_commit(window->surface);
|
||||
}
|
||||
window->wcs = self;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
struct window *window = (struct window *) gsDevice;
|
||||
NSDebugLog(@"WaylandCairoSurface: dealloc win=%d", window->window_id);
|
||||
cairo_surface_destroy(_surface);
|
||||
_surface = NULL;
|
||||
pbuffer->surface = NULL;
|
||||
// try to free the buffer if already released by the compositor
|
||||
finishBuffer(pbuffer);
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSSize)size
|
||||
{
|
||||
if (_surface == NULL)
|
||||
{
|
||||
return NSZeroSize;
|
||||
}
|
||||
return NSMakeSize(cairo_image_surface_get_width(_surface),
|
||||
cairo_image_surface_get_height(_surface));
|
||||
}
|
||||
|
||||
- (void)handleExposeRect:(NSRect)rect
|
||||
{
|
||||
struct window *window = (struct window *) gsDevice;
|
||||
NSDebugLog(@"[CairoSurface handleExposeRect] %d", window->window_id);
|
||||
|
||||
window->buffer_needs_attach = YES;
|
||||
|
||||
if (window->configured)
|
||||
{
|
||||
window->buffer_needs_attach = NO;
|
||||
wl_surface_attach(window->surface, pbuffer->buffer, 0, 0);
|
||||
NSDebugLog(@"[%d] updating region: %d,%d %fx%f", window->window_id, 0, 0,
|
||||
window->width, window->height);
|
||||
// FIXME we should update only the damaged area defined as x,y,width,
|
||||
// height at the moment it doesnt work
|
||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||
wl_surface_commit(window->surface);
|
||||
wl_display_dispatch_pending(window->wlconfig->display);
|
||||
wl_display_flush(window->wlconfig->display);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)destroySurface
|
||||
{
|
||||
// noop this is an offscreen surface
|
||||
// no need to destroy it when not visible
|
||||
}
|
||||
@end
|
|
@ -1,236 +0,0 @@
|
|||
/* WaylandCairoSurface
|
||||
|
||||
WaylandCairoSurface - Draw with Cairo onto Wayland surfaces
|
||||
|
||||
|
||||
Copyright (C) 2020 Free Software Foundation, Inc.
|
||||
|
||||
Author: Sergio L. Pascual <slp@sinrega.org>
|
||||
Rewrite: Riccardo Canalicchio <riccardo.canalicchio(at)gmail.com>
|
||||
Date: November 2021
|
||||
|
||||
This file is part of the GNU Objective C Backend Library.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; see the file COPYING.LIB.
|
||||
If not, see <http://www.gnu.org/licenses/> or write to the
|
||||
Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "wayland/WaylandServer.h"
|
||||
#include "cairo/WaylandCairoSurface.h"
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define GSWINDEVICE ((struct window *) gsDevice)
|
||||
|
||||
/* Linux specific version */
|
||||
static int
|
||||
os_create_anonymous_file(off_t size)
|
||||
{
|
||||
static const char template[] = "/gnustep-shared-XXXXXX";
|
||||
const char *path;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
path = getenv("XDG_RUNTIME_DIR");
|
||||
if (!path)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
name = malloc(strlen(path) + sizeof(template));
|
||||
if (!name)
|
||||
return -1;
|
||||
|
||||
strcpy(name, path);
|
||||
strcat(name, template);
|
||||
|
||||
fd = memfd_create(name, MFD_CLOEXEC);
|
||||
|
||||
free(name);
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (ftruncate(fd, size) != 0)
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
shm_buffer_stride(struct window *window)
|
||||
{
|
||||
return window->width * 4;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
shm_buffer_size(struct window *window)
|
||||
{
|
||||
return shm_buffer_stride(window) * window->height;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
create_shm_buffer(struct window *window)
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
cairo_surface_t *surface;
|
||||
int fd, size, stride;
|
||||
|
||||
stride = shm_buffer_stride(window);
|
||||
size = shm_buffer_size(window);
|
||||
|
||||
NSDebugLog(@"WaylandCairoSurface: creating shm buffer of %d bytes", size);
|
||||
fd = os_create_anonymous_file(size);
|
||||
if (fd < 0)
|
||||
{
|
||||
NSLog(@"creating a buffer file for surface failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
window->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (window->data == MAP_FAILED)
|
||||
{
|
||||
NSLog(@"error mapping anonymous file");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pool = wl_shm_create_pool(window->wlconfig->shm, fd, size);
|
||||
|
||||
surface
|
||||
= cairo_image_surface_create_for_data(window->data, CAIRO_FORMAT_ARGB32,
|
||||
window->width, window->height,
|
||||
stride);
|
||||
|
||||
window->buffer
|
||||
= wl_shm_pool_create_buffer(pool, 0, window->width, window->height, stride,
|
||||
WL_SHM_FORMAT_ARGB8888);
|
||||
wl_shm_pool_destroy(pool);
|
||||
|
||||
close(fd);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
@implementation WaylandCairoSurface
|
||||
|
||||
- (id)initWithDevice:(void *)device
|
||||
{
|
||||
struct window *window = (struct window *) device;
|
||||
NSDebugLog(@"WaylandCairoSurface: initWithDevice win=%d", window->window_id);
|
||||
|
||||
gsDevice = device;
|
||||
|
||||
_surface = create_shm_buffer(window);
|
||||
window->buffer_needs_attach = YES;
|
||||
if (_surface == NULL)
|
||||
{
|
||||
NSDebugLog(@"can't create cairo surface");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (window->configured)
|
||||
{
|
||||
// we can attach a buffer to the surface only if the surface is configured
|
||||
// this is usually done in the configure event handler
|
||||
// in case of resize of an already configured surface
|
||||
// we should reattach the new allocated buffer
|
||||
NSDebugLog(@"wl_surface_attach: win=%d toplevel_surface",
|
||||
window->window_id);
|
||||
window->buffer_needs_attach = NO;
|
||||
wl_surface_attach(window->surface, window->buffer, 0, 0);
|
||||
wl_surface_commit(window->surface);
|
||||
}
|
||||
window->wcs = self;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
struct window *window = (struct window *) gsDevice;
|
||||
NSDebugLog(@"WaylandCairoSurface: dealloc win=%d", window->window_id);
|
||||
|
||||
// FIXME: This is leaking memory. We need to *correctly* implement
|
||||
// the counterpart to create_shm_buffer.
|
||||
//
|
||||
// For instance, this is the wrong place to destroy the cairo surface:
|
||||
// cairo_surface_destroy(window->surface);
|
||||
// window->surface = NULL;
|
||||
// and likely to unmap the data, and destroy/release the buffer.
|
||||
// "Destroying the wl_buffer after wl_buffer.release does not change
|
||||
// the surface contents. However, if the client destroys the wl_buffer
|
||||
// before receiving the wl_buffer.release event, the surface contents
|
||||
// become undefined immediately."
|
||||
// Hence also skipping:
|
||||
// munmap(window->data, shm_buffer_size(window));
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSSize)size
|
||||
{
|
||||
// NSDebugLog(@"WaylandCairoSurface: size");
|
||||
struct window *window = (struct window *) gsDevice;
|
||||
return NSMakeSize(window->width, window->height);
|
||||
}
|
||||
|
||||
- (void)setSurface:(cairo_surface_t *)surface
|
||||
{
|
||||
// NSDebugLog(@"WaylandCairoSurface: setSurface");
|
||||
_surface = surface;
|
||||
}
|
||||
|
||||
- (void)handleExposeRect:(NSRect)rect
|
||||
{
|
||||
struct window *window = (struct window *) gsDevice;
|
||||
NSDebugLog(@"[CairoSurface handleExposeRect] %d", window->window_id);
|
||||
|
||||
int x = NSMinX(rect);
|
||||
int y = NSMinY(rect);
|
||||
int width = NSWidth(rect);
|
||||
int height = NSHeight(rect);
|
||||
|
||||
window->buffer_needs_attach = YES;
|
||||
|
||||
if (window->configured)
|
||||
{
|
||||
window->buffer_needs_attach = NO;
|
||||
wl_surface_attach(window->surface, window->buffer, 0, 0);
|
||||
NSDebugLog(@"[%d] updating region: %d,%d %dx%d", window->window_id, 0, 0,
|
||||
window->width, window->height);
|
||||
// FIXME we should update only the damaged area define as x,y,width,height
|
||||
// at the moment it doesnt work
|
||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||
wl_surface_commit(window->surface);
|
||||
wl_display_dispatch_pending(window->wlconfig->display);
|
||||
wl_display_flush(window->wlconfig->display);
|
||||
}
|
||||
|
||||
// NSDebugLog(@"[CairoSurface handleExposeRect end]");
|
||||
}
|
||||
|
||||
@end
|
6
Source/wayland/WaylandServer+Layershell.m
Normal file → Executable file
6
Source/wayland/WaylandServer+Layershell.m
Normal file → Executable file
|
@ -40,9 +40,9 @@ layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface,
|
|||
window->configured = YES;
|
||||
if (window->buffer_needs_attach)
|
||||
{
|
||||
NSDebugLog(@"attach: win=%d layer", window->window_id);
|
||||
wl_surface_attach(window->surface, window->buffer, 0, 0);
|
||||
wl_surface_commit(window->surface);
|
||||
[window->instance flushwindowrect:NSMakeRect(window->pos_x, window->pos_y,
|
||||
window->width, window->height
|
||||
):window->window_id];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
9
Source/wayland/WaylandServer+Xdgshell.m
Executable file → Normal file
9
Source/wayland/WaylandServer+Xdgshell.m
Executable file → Normal file
|
@ -56,9 +56,9 @@ xdg_surface_on_configure(void *data, struct xdg_surface *xdg_surface,
|
|||
|
||||
if (window->buffer_needs_attach)
|
||||
{
|
||||
NSDebugLog(@"attach: win=%d toplevel", window->window_id);
|
||||
wl_surface_attach(window->surface, window->buffer, 0, 0);
|
||||
wl_surface_commit(window->surface);
|
||||
[window->instance flushwindowrect:NSMakeRect(window->pos_x, window->pos_y,
|
||||
window->width, window->height
|
||||
):window->window_id];
|
||||
}
|
||||
|
||||
if (wlconfig->pointer.focus
|
||||
|
@ -129,7 +129,8 @@ xdg_popup_configure(void *data, struct xdg_popup *xdg_popup, int32_t x,
|
|||
struct window *window = data;
|
||||
WaylandConfig *wlconfig = window->wlconfig;
|
||||
|
||||
NSDebugLog(@"xdg_popup_configure");
|
||||
NSDebugLog(@"[%d] xdg_popup_configure [%d,%d %dx%d]", window->window_id, x, y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -487,6 +487,8 @@ WaylandServer (WindowOps)
|
|||
if (window->toplevel)
|
||||
{
|
||||
xdg_toplevel_set_title(window->toplevel, cString);
|
||||
wl_surface_commit(window->surface);
|
||||
wl_display_flush(window->wlconfig->display);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,7 +513,11 @@ WaylandServer (WindowOps)
|
|||
struct window *window;
|
||||
|
||||
window = get_window_with_id(wlconfig, winId);
|
||||
|
||||
// FIXME we could resize the current surface instead of creating a new one
|
||||
if (window->wcs)
|
||||
{
|
||||
NSDebugLog(@"[%d] window has already a surface", winId);
|
||||
}
|
||||
GSSetDevice(ctxt, window, 0.0, window->height);
|
||||
DPSinitmatrix(ctxt);
|
||||
DPSinitclip(ctxt);
|
||||
|
@ -970,7 +976,6 @@ WaylandServer (SurfaceRoles)
|
|||
}
|
||||
if (!parentwindow)
|
||||
{
|
||||
//[self createTopLevel: window];
|
||||
return;
|
||||
}
|
||||
NSDebugLog(@"new popup: %d parent id: %d", win, parentwindow->window_id);
|
||||
|
@ -991,7 +996,7 @@ WaylandServer (SurfaceRoles)
|
|||
{
|
||||
NSDebugLog(@"createPopupShell");
|
||||
|
||||
if (parent->xdg_surface == NULL || parent->toplevel == NULL)
|
||||
if (parent->toplevel == NULL && parent->layer_surface == NULL)
|
||||
{
|
||||
NSDebugLog(@"parent surface %d is not toplevel", parent->window_id);
|
||||
return;
|
||||
|
@ -1025,12 +1030,14 @@ WaylandServer (SurfaceRoles)
|
|||
xdg_positioner_set_offset(positioner, (child->pos_x - parent->pos_x),
|
||||
(child->pos_y - parent->pos_y));
|
||||
|
||||
// NSDebugLog(@"xdg_positioner offset: %f,%f",
|
||||
// (child->pos_x - parent->pos_x), (child->pos_y - parent->pos_y));
|
||||
|
||||
child->popup = xdg_surface_get_popup(child->xdg_surface, parent->xdg_surface,
|
||||
positioner);
|
||||
|
||||
if (parent->layer_surface)
|
||||
{
|
||||
zwlr_layer_surface_v1_get_popup(parent->layer_surface, child->popup);
|
||||
}
|
||||
|
||||
xdg_popup_add_listener(child->popup, &xdg_popup_listener, child);
|
||||
xdg_surface_add_listener(child->xdg_surface, &xdg_surface_listener, child);
|
||||
|
||||
|
@ -1040,8 +1047,8 @@ WaylandServer (SurfaceRoles)
|
|||
NSDebugLog(@"child_geometry : %f,%f %fx%f", child->pos_x - parent->pos_x,
|
||||
child->pos_y - parent->pos_y, child->width, child->height);
|
||||
wl_surface_commit(child->surface);
|
||||
wl_display_dispatch_pending(wlconfig->display);
|
||||
wl_display_flush(wlconfig->display);
|
||||
wl_display_roundtrip(wlconfig->display);
|
||||
xdg_positioner_destroy(positioner);
|
||||
}
|
||||
|
||||
- (void)destroySurfaceRole:(struct window *)window
|
||||
|
@ -1072,6 +1079,10 @@ WaylandServer (SurfaceRoles)
|
|||
xdg_surface_destroy(window->xdg_surface);
|
||||
window->xdg_surface = NULL;
|
||||
}
|
||||
if (window->wcs)
|
||||
{
|
||||
[window->wcs destroySurface];
|
||||
}
|
||||
window->configured = NO;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue