wayland backend: delayed toplevel creation

This commit is contained in:
Riccardo Canalicchio 2021-10-18 03:37:02 -04:00
parent 3227b39c58
commit c6ce795898
3 changed files with 117 additions and 74 deletions

View file

@ -107,6 +107,7 @@ struct window {
int window_id; int window_id;
struct wl_list link; struct wl_list link;
BOOL configured; // surface has been configured once BOOL configured; // surface has been configured once
BOOL buffer_needs_attach; // surface has been configured once
float pos_x; float pos_x;
float pos_y; float pos_y;

View file

@ -141,12 +141,20 @@ create_shm_buffer(struct window *window)
gsDevice = device; gsDevice = device;
_surface = create_shm_buffer(window); _surface = create_shm_buffer(window);
window->buffer_needs_attach = YES;
if (_surface == NULL) { if (_surface == NULL) {
NSDebugLog(@"can't create cairo surface"); NSDebugLog(@"can't create cairo surface");
return 0; return 0;
} }
wl_surface_attach(window->surface, window->buffer, 0, 0); if(window->toplevel != NULL && window->configured) {
// if the window has a toplevel then it should appear on screen
// we can attach a buffer only if the xdg surface is configured
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; window->wcs = self;
return self; return self;
@ -176,7 +184,7 @@ create_shm_buffer(struct window *window)
- (NSSize) size - (NSSize) size
{ {
NSDebugLog(@"WaylandCairoSurface: size"); // NSDebugLog(@"WaylandCairoSurface: size");
struct window *window = (struct window*) gsDevice; struct window *window = (struct window*) gsDevice;
return NSMakeSize(window->width, window->height); return NSMakeSize(window->width, window->height);
} }
@ -189,7 +197,7 @@ create_shm_buffer(struct window *window)
- (void) handleExposeRect: (NSRect)rect - (void) handleExposeRect: (NSRect)rect
{ {
NSDebugLog(@"handleExposeRect"); NSDebugLog(@"[CairoSurface handleExposeRect]");
struct window *window = (struct window*) gsDevice; struct window *window = (struct window*) gsDevice;
cairo_surface_t *cairo_surface = _surface; cairo_surface_t *cairo_surface = _surface;
double backupOffsetX = 0; double backupOffsetX = 0;
@ -199,39 +207,28 @@ create_shm_buffer(struct window *window)
int width = NSWidth(rect); int width = NSWidth(rect);
int height = NSHeight(rect); int height = NSHeight(rect);
NSDebugLog(@"updating region: %dx%d %dx%d", x, y, width, height); NSDebugLog(@"...updating region: %dx%d %dx%d", x, y, width, height);
if (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS) if (cairo_surface_status(cairo_surface) != CAIRO_STATUS_SUCCESS)
{ {
NSWarnMLog(@"cairo initial window error status: %s\n", NSWarnMLog(@"...cairo initial window error status: %s\n",
cairo_status_to_string(cairo_surface_status(_surface))); cairo_status_to_string(cairo_surface_status(_surface)));
} }
cairo_surface_get_device_offset(cairo_surface, &backupOffsetX, &backupOffsetY); if (window->configured) {
cairo_surface_set_device_offset(cairo_surface, 0, 0); if(window->buffer_needs_attach) {
window->buffer_needs_attach = NO;
wl_surface_attach(window->surface, window->buffer, 0, 0);
}
wl_surface_damage(window->surface, 0, 0, width, height);
wl_surface_commit(window->surface);
//wl_display_dispatch_pending(window->wlconfig->display);
//wl_display_flush(window->wlconfig->display);
} else {
window->buffer_needs_attach = YES;
}
// FIXME: This seems to be creating a context to paint into cairo_surface, NSDebugLog(@"[CairoSurface handleExposeRect end]");
// and then copies back into the same cairo_surface.
cairo_t *cr = cairo_create(cairo_surface);
cairo_rectangle(cr, x, y, width, height);
cairo_clip(cr);
cairo_set_source_surface(cr, cairo_surface, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_paint(cr);
cairo_destroy(cr);
NSDebugLog(@"trying to commit cairo surface for window %d", window->window_id);
if (window->configured)
wl_surface_commit(window->surface);
NSDebugLog(@"done trying to commit cairo surface for window %d", window->window_id);
wl_display_dispatch_pending(window->wlconfig->display);
wl_display_flush(window->wlconfig->display);
cairo_surface_set_device_offset(_surface, backupOffsetX, backupOffsetY);
NSDebugLog(@"handleExposeRect exit");
} }
@end @end

View file

@ -689,14 +689,12 @@ xdg_surface_on_configure(void *data, struct xdg_surface *xdg_surface,
xdg_surface_ack_configure(xdg_surface, serial); xdg_surface_ack_configure(xdg_surface, serial);
window->configured = YES; window->configured = YES;
// TODO: do we need to check that the surface has been painted to?
if (window->surface) if(window->buffer_needs_attach) {
{ NSDebugLog(@"attach: win=%d toplevel", window->window_id);
// TODO: is this ever going to be null when we get here? wl_surface_attach(window->surface, window->buffer, 0, 0);
wl_surface_commit(window->surface); wl_surface_commit(window->surface);
wl_display_dispatch_pending(window->wlconfig->display); }
wl_display_flush(window->wlconfig->display);
}
if (wlconfig->pointer.focus && if (wlconfig->pointer.focus &&
@ -1081,35 +1079,23 @@ int NSToWayland(struct window *window, int ns_y)
window->pos_x = frame.origin.x; window->pos_x = frame.origin.x;
window->pos_y = NSToWayland(window, frame.origin.y); window->pos_y = NSToWayland(window, frame.origin.y);
window->window_id = wlconfig->last_window_id; window->window_id = wlconfig->last_window_id;
window->surface = wl_compositor_create_surface(wlconfig->compositor); window->xdg_surface = NULL;
if (!window->surface) { window->toplevel = NULL;
NSDebugLog(@"can't create wayland surface"); window->configured = NO;
free(window); window->buffer_needs_attach = NO;
return 0;
}
wl_surface_set_user_data(window->surface, window);
window->xdg_surface =
xdg_wm_base_get_xdg_surface(wlconfig->wm_base, window->surface);
#if 0 #if 0
// TODO: xdg_shell_get_xdg_surface_special() no longer exists, if (style & NSMiniWindowMask) {
// so we need to find another way, see *get_popup for menus NSDebugLog(@"window id=%d will be a NSMiniWindowMask", window->window_id);
if (style & NSMainMenuWindowMask) { } else if (style & NSIconWindowMask) {
NSDebugLog(@"window id=%d will be a panel", window->window_id); NSDebugLog(@"window id=%d will be a NSIconWindowMask", window->window_id);
} else if (style & NSBackgroundWindowMask) { } else if (style & NSBorderlessWindowMask) {
NSDebugLog(@"window id=%d will be a ?", window->window_id); NSDebugLog(@"window id=%d will be a NSBorderlessWindowMask", window->window_id);
} else { } else {
NSDebugLog(@"window id=%d will be ordinary", window->window_id); NSDebugLog(@"window id=%d will be ordinary", window->window_id);
} }
#endif #endif
window->toplevel = xdg_surface_get_toplevel(window->xdg_surface);
xdg_surface_set_user_data(window->xdg_surface, window);
xdg_surface_add_listener(window->xdg_surface,
&xdg_surface_listener, window);
if (window->pos_x < 0) { if (window->pos_x < 0) {
window->pos_x = 0; window->pos_x = 0;
altered = 1; altered = 1;
@ -1125,18 +1111,13 @@ int NSToWayland(struct window *window, int ns_y)
NSDebugLog(@"creating new window with id=%d: pos=%fx%f, size=%fx%f", NSDebugLog(@"creating new window with id=%d: pos=%fx%f, size=%fx%f",
window->window_id, window->pos_x, window->pos_y, window->window_id, window->pos_x, window->pos_y,
window->width, window->height); window->width, window->height);
xdg_surface_set_window_geometry(window->xdg_surface,
window->pos_x,
window->pos_y,
window->width,
window->height);
wl_surface_commit(window->surface);
wl_display_flush(wlconfig->display);
wl_list_insert(wlconfig->window_list.prev, &window->link); wl_list_insert(wlconfig->window_list.prev, &window->link);
wlconfig->last_window_id++; wlconfig->last_window_id++;
wlconfig->window_count++; wlconfig->window_count++;
// creates a buffer for the window
[self _setWindowOwnedByServer: (int)window->window_id]; [self _setWindowOwnedByServer: (int)window->window_id];
if (altered) { if (altered) {
@ -1156,7 +1137,49 @@ int NSToWayland(struct window *window, int ns_y)
return window->window_id; return window->window_id;
} }
- (void) makeWindowTopLevel: (int) win
{
NSDebugLog(@"makeWindowTopLevel");
struct window *window = get_window_with_id(wlconfig, win);
window->surface = wl_compositor_create_surface(wlconfig->compositor);
if (!window->surface) {
NSDebugLog(@"can't create wayland surface");
free(window);
return;
}
wl_surface_set_user_data(window->surface, window);
window->xdg_surface =
xdg_wm_base_get_xdg_surface(wlconfig->wm_base, window->surface);
window->toplevel = xdg_surface_get_toplevel(window->xdg_surface);
xdg_surface_add_listener(window->xdg_surface,
&xdg_surface_listener, window);
xdg_surface_set_window_geometry(window->xdg_surface,
window->pos_x,
window->pos_y,
window->width,
window->height);
NSDebugLog(@"wl_surface_commit: win=%d toplevel", window->window_id);
wl_surface_commit(window->surface);
wl_display_dispatch_pending(window->wlconfig->display);
wl_display_flush(window->wlconfig->display);
return;
#if 0
// TODO: xdg_shell_get_xdg_surface_special() no longer exists,
// so we need to find another way, see *get_popup for menus
if (style & NSMainMenuWindowMask) {
NSDebugLog(@"window id=%d will be a panel", window->window_id);
} else if (style & NSBackgroundWindowMask) {
NSDebugLog(@"window id=%d will be a ?", window->window_id);
} else {
NSDebugLog(@"window id=%d will be ordinary", window->window_id);
}
#endif
}
- (void) termwindow: (int) win - (void) termwindow: (int) win
{ {
NSDebugLog(@"termwindow: win=%d", win); NSDebugLog(@"termwindow: win=%d", win);
@ -1199,7 +1222,8 @@ int NSToWayland(struct window *window, int ns_y)
struct window *window = get_window_with_id(wlconfig, win); struct window *window = get_window_with_id(wlconfig, win);
const char *cString = [window_title UTF8String]; const char *cString = [window_title UTF8String];
xdg_toplevel_set_title(window->toplevel, cString); if(window->toplevel)
xdg_toplevel_set_title(window->toplevel, cString);
} }
- (void) miniwindow: (int) win - (void) miniwindow: (int) win
@ -1210,6 +1234,8 @@ int NSToWayland(struct window *window, int ns_y)
- (void) setWindowdevice: (int) winId forContext: (NSGraphicsContext *)ctxt - (void) setWindowdevice: (int) winId forContext: (NSGraphicsContext *)ctxt
{ {
// creates a new shm buffer
NSDebugLog(@"creating a new shm buffer: %d", winId);
NSDebugLog(@"setWindowdevice: %d", winId); NSDebugLog(@"setWindowdevice: %d", winId);
struct window *window; struct window *window;
@ -1228,21 +1254,28 @@ int NSToWayland(struct window *window, int ns_y)
if (op == NSWindowOut) { if (op == NSWindowOut) {
NSDebugLog(@"orderwindow: NSWindowOut"); NSDebugLog(@"orderwindow: NSWindowOut");
window->is_out = 1; window->is_out = 1;
if(window->xdg_surface) {
xdg_surface_set_window_geometry(window->xdg_surface, xdg_surface_set_window_geometry(window->xdg_surface,
window->pos_x + 32000, window->pos_x + 32000,
window->pos_y + 32000, window->pos_y + 32000,
window->width, window->width,
window->height); window->height);
}
NSRect rect = NSMakeRect(0, 0, NSRect rect = NSMakeRect(0, 0,
window->width, window->height); window->width, window->height);
[window->instance flushwindowrect:rect :window->window_id]; [window->instance flushwindowrect:rect :window->window_id];
if(window->toplevel != NULL) {
xdg_toplevel_set_minimized(window->toplevel);
}
xdg_toplevel_set_minimized(window->toplevel);
wl_display_dispatch_pending(window->wlconfig->display); wl_display_dispatch_pending(window->wlconfig->display);
wl_display_flush(window->wlconfig->display); wl_display_flush(window->wlconfig->display);
} else /*if (window->is_out)*/ { } else /*if (window->is_out)*/ {
NSDebugLog(@"orderwindow: restoring to %fx%f", window->pos_x, window->pos_y); if(window->toplevel == NULL) {
[self makeWindowTopLevel: win];
}
NSDebugLog(@"orderwindow: %d restoring to %fx%f", win, window->pos_x, window->pos_y);
xdg_surface_set_window_geometry(window->xdg_surface, xdg_surface_set_window_geometry(window->xdg_surface,
window->pos_x, window->pos_x,
window->pos_y, window->pos_y,
@ -1325,10 +1358,13 @@ int NSToWayland(struct window *window, int ns_y)
[GSCurrentServer() postEvent: event atStart: NO]; [GSCurrentServer() postEvent: event atStart: NO];
xdg_toplevel_move(window->toplevel, //xdg_toplevel_move(window->toplevel,
config->seat, // config->seat,
config->pointer.serial); // config->pointer.serial);
} else { } else {
if(window->toplevel == NULL) {
[self makeWindowTopLevel: win];
}
NSDebugLog(@"placewindow: oldpos=%fx%f", window->pos_x, window->pos_y); NSDebugLog(@"placewindow: oldpos=%fx%f", window->pos_x, window->pos_y);
NSDebugLog(@"placewindow: oldsize=%fx%f", window->width, window->height); NSDebugLog(@"placewindow: oldsize=%fx%f", window->width, window->height);
NSRect frame; NSRect frame;
@ -1384,8 +1420,10 @@ int NSToWayland(struct window *window, int ns_y)
subtype: GSAppKitWindowResized subtype: GSAppKitWindowResized
data1: rect.size.width data1: rect.size.width
data2: rect.size.height]; data2: rect.size.height];
NSDebugLog(@"notify resize=%fx%f", rect.size.width, rect.size.height);
[(GSWindowWithNumber(window->window_id)) sendEvent: ev]; [(GSWindowWithNumber(window->window_id)) sendEvent: ev];
NSDebugLog(@"placewindow notify resized=%fx%f", rect.size.width, rect.size.height); NSDebugLog(@"notified resize=%fx%f", rect.size.width, rect.size.height);
// we have a new buffer
} else if (move == YES) { } else if (move == YES) {
NSEvent *ev = [NSEvent otherEventWithType: NSAppKitDefined NSEvent *ev = [NSEvent otherEventWithType: NSAppKitDefined
location: NSZeroPoint location: NSZeroPoint
@ -1454,6 +1492,7 @@ int NSToWayland(struct window *window, int ns_y)
struct window *window = get_window_with_id(wlconfig, win); struct window *window = get_window_with_id(wlconfig, win);
[[GSCurrentContext() class] handleExposeRect: rect forDriver: window->wcs]; [[GSCurrentContext() class] handleExposeRect: rect forDriver: window->wcs];
// [(CairoSurface *)driver handleExposeRect: rect];
} }
- (void) styleoffsets: (float*) l : (float*) r : (float*) t : (float*) b - (void) styleoffsets: (float*) l : (float*) r : (float*) t : (float*) b
@ -1612,10 +1651,16 @@ int NSToWayland(struct window *window, int ns_y)
struct window *parent = get_window_with_id(wlconfig, parentWin); struct window *parent = get_window_with_id(wlconfig, parentWin);
struct window *child = get_window_with_id(wlconfig, childWin); struct window *child = get_window_with_id(wlconfig, childWin);
if(!child->toplevel) {
return;
}
if (parent) { if (parent) {
xdg_toplevel_set_parent(child->toplevel, parent->toplevel); if(!parent->toplevel) {
return;
}
xdg_toplevel_set_parent(child->toplevel, parent->toplevel);
} else { } else {
xdg_toplevel_set_parent(child->toplevel, NULL); xdg_toplevel_set_parent(child->toplevel, NULL);
} }
xdg_toplevel_set_minimized(child->toplevel); xdg_toplevel_set_minimized(child->toplevel);
wl_display_dispatch_pending(wlconfig->display); wl_display_dispatch_pending(wlconfig->display);