void wlc_view_ack_surface_attach(struct wlc_view *view, struct wlc_surface *surface) { assert(view && surface); if (view->x11.id) { surface->pending.opaque.extents = (pixman_box32_t){ 0, 0, surface->size.w, surface->size.h }; view->surface_pending.visible = (struct wlc_geometry){ wlc_origin_zero, surface->size }; } const bool resizing = (view->pending.state & WLC_BIT_RESIZING || view->commit.state & WLC_BIT_RESIZING); if (!resizing && !wlc_geometry_equals(&view->surface_pending.visible, &view->surface_commit.visible)) { struct wlc_geometry g = (struct wlc_geometry){ view->pending.geometry.origin, view->surface_pending.visible.size }; wlc_view_request_geometry(view, &g); } view->surface_commit = view->surface_pending; wlc_dlog(WLC_DBG_COMMIT, "=> surface view %" PRIuWLC, convert_to_wlc_handle(view)); } static bool should_be_transformed_by_parent(struct wlc_view *view) { return !(view->type & WLC_BIT_OVERRIDE_REDIRECT) && !(view->type & WLC_BIT_UNMANAGED); } void wlc_view_get_bounds(struct wlc_view *view, struct wlc_geometry *out_bounds, struct wlc_geometry *out_visible) { assert(view && out_bounds && out_bounds != out_visible); memcpy(out_bounds, &view->commit.geometry, sizeof(struct wlc_geometry)); struct wlc_surface *surface; if (!(surface = convert_from_wlc_resource(view->surface, "surface"))) return; if (should_be_transformed_by_parent(view)) { for (struct wlc_view *parent = convert_from_wlc_handle(view->parent, "view"); parent; parent = convert_from_wlc_handle(parent->parent, "view")) { out_bounds->origin.x += parent->commit.geometry.origin.x; out_bounds->origin.y += parent->commit.geometry.origin.y; } } if (view->xdg_surface && view->surface_commit.visible.size.w > 0 && view->surface_commit.visible.size.h > 0) { // xdg-surface client that draws drop shadows or other stuff. out_bounds->origin.x -= view->surface_commit.visible.origin.x; out_bounds->origin.y -= view->surface_commit.visible.origin.y; out_bounds->size.w += surface->size.w - view->surface_commit.visible.size.w; out_bounds->size.h += surface->size.h - view->surface_commit.visible.size.h; } // Make sure bounds is never 0x0 w/h wlc_size_max(&out_bounds->size, &(struct wlc_size){ 1, 1 }, &out_bounds->size);
bool wlc_view_request_geometry(struct wlc_view *view, const struct wlc_geometry *r) { assert(view && r); wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") requested geometry %ux%u+%d,%d", convert_to_wlc_handle(view), r->size.w, r->size.h, r->origin.x, r->origin.y); if (view->state.created && wlc_interface()->view.request.geometry) { WLC_INTERFACE_EMIT(view.request.geometry, convert_to_wlc_handle(view), r); } else { memcpy(&view->pending.geometry, r, sizeof(view->pending.geometry)); } configure_view(view, view->pending.edges, &view->pending.geometry); wlc_dlog(WLC_DBG_REQUEST, "(%" PRIuWLC ") applied geometry %ux%u+%d,%d", convert_to_wlc_handle(view), view->pending.geometry.size.w, view->pending.geometry.size.h, view->pending.geometry.origin.x, view->pending.geometry.origin.y); return wlc_geometry_equals(r, &view->pending.geometry); }
static void surface_paint_internal(struct ctx *context, struct wlc_surface *surface, const struct wlc_geometry *geometry, struct paint *settings) { assert(context && surface && geometry && settings); const struct wlc_geometry *g = geometry; if (!wlc_size_equals(&surface->size, &geometry->size)) { if (wlc_geometry_equals(&settings->visible, geometry)) { settings->filter = true; } else { // black borders are requested struct paint settings2 = *settings; settings2.program = (settings2.program == PROGRAM_RGBA || settings2.program == PROGRAM_RGB ? settings2.program : PROGRAM_RGB); texture_paint(context, &context->textures[TEXTURE_BLACK], 1, geometry, &settings2); g = &settings->visible; } } texture_paint(context, surface->textures, 3, g, settings); }
void wlc_view_ack_surface_attach(struct wlc_view *view, struct wlc_surface *surface) { assert(view && surface); if (is_x11_view(view)) { surface->pending.opaque.extents = (pixman_box32_t){ 0, 0, surface->size.w, surface->size.h }; view->surface_pending.visible = (struct wlc_geometry){ wlc_point_zero, surface->size }; } const bool resizing = (view->pending.state & WLC_BIT_RESIZING || view->commit.state & WLC_BIT_RESIZING); if (!resizing && !wlc_geometry_equals(&view->surface_pending.visible, &view->surface_commit.visible)) { struct wlc_geometry g = (struct wlc_geometry){ view->pending.geometry.origin, view->surface_pending.visible.size }; wlc_view_request_geometry(view, &g); } view->surface_commit = view->surface_pending; } void wlc_view_get_bounds(struct wlc_view *view, struct wlc_geometry *out_bounds, struct wlc_geometry *out_visible) { assert(view && out_bounds && out_bounds != out_visible); memcpy(out_bounds, &view->commit.geometry, sizeof(struct wlc_geometry)); struct wlc_surface *surface; if (!(surface = convert_from_wlc_resource(view->surface, "surface"))) return; if (view->xdg_surface && !wlc_size_equals(&view->surface_commit.visible.size, &wlc_size_zero)) { // xdg-surface client that draws drop shadows or other stuff. struct wlc_geometry v = view->surface_commit.visible; v.origin.x = chck_clamp32(v.origin.x, 0, surface->size.w); v.origin.y = chck_clamp32(v.origin.y, 0, surface->size.h); v.size.w = chck_clampu32(surface->size.w - v.size.w, 0, surface->size.w); v.size.h = chck_clampu32(surface->size.h - v.size.h, 0, surface->size.h); assert(surface->size.w > 0 && surface->size.h > 0); const float wa = (float)out_bounds->size.w / surface->size.w, ha = (float)out_bounds->size.h / surface->size.h; out_bounds->origin.x -= v.origin.x * wa; out_bounds->origin.y -= v.origin.y * ha; out_bounds->size.w += v.size.w * wa; out_bounds->size.h += v.size.h * ha; } // Make sure bounds is never 0x0 w/h wlc_size_max(&out_bounds->size, &(struct wlc_size){ 1, 1 }, &out_bounds->size); if (!out_visible) return; // Actual visible area of the view // The idea is to draw black borders to the bounds area, while centering the visible area. if ((is_x11_view(view) || view->shell_surface) && !wlc_size_equals(&surface->size, &out_bounds->size)) { out_visible->size = surface->size; // Scale visible area retaining aspect assert(surface->size.w > 0 && surface->size.h > 0); const float ba = (float)out_bounds->size.w / (float)out_bounds->size.h; const float sa = (float)surface->size.w / (float)surface->size.h; if (ba < sa) { out_visible->size.w *= (float)out_bounds->size.w / surface->size.w; out_visible->size.h *= (float)out_bounds->size.w / surface->size.w; } else { out_visible->size.w *= (float)out_bounds->size.h / surface->size.h; out_visible->size.h *= (float)out_bounds->size.h / surface->size.h; } // Center visible area out_visible->origin.x = out_bounds->origin.x + out_bounds->size.w * 0.5 - out_visible->size.w * 0.5; out_visible->origin.y = out_bounds->origin.y + out_bounds->size.h * 0.5 - out_visible->size.h * 0.5; // Make sure visible is never 0x0 w/h out_visible->size.w = chck_maxu32(out_visible->size.w, 1); out_visible->size.h = chck_maxu32(out_visible->size.h, 1); } else { // For non wl_shell or x11 surfaces, just memcpy memcpy(out_visible, out_bounds, sizeof(struct wlc_geometry)); } }