void MyShellModule::render(Output& outp, ny::DrawContext& dc) { if(!myTexture.glTexture()) { ny::Image myImage; ny::sendLog("loading wallpaper... ", myImage.load("wallpaper.png")); myTexture.create(myImage); } glViewport(0, 0, outp.size().x, outp.size().y); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); dc.clear(ny::Color::red); ny::TextureBrush texBrush; texBrush.extents.position = {0.f, 0.f}; texBrush.extents.size = outp.size(); texBrush.texture = &myTexture; ny::Rectangle bg = texBrush.extents; dc.mask(bg); dc.fill(texBrush); SurfaceRes* cursorSurface = nullptr; ny::sendLog("Shell: Drawing ", outp.mappedSurfaces().size(), " mapped surfaces"); for(auto& surf : outp.mappedSurfaces()) { if(surf->roleType() == surfaceRoleType::cursor) cursorSurface = surf; /* ny::Rectangle surfaceRect(surf->extents()); surfaceRect.position(surfaceRect.position() - outp.extents().position); dc.mask(surfaceRect); ny::TextureBrush surfaceBrush; surfaceBrush.extents = surfaceRect; surfaceBrush.texture = surf->surfaceContext().content(); dc.fill(surfaceBrush); */ surf->sendFrameDone(); } //windows are sorted by z order for(auto& window : windows_) { auto* surf = window->surfaceRes(); if(!surf) continue; if(window == focus_) { ny::Rectangle surfaceRect(surf->extents()); surfaceRect.position(surfaceRect.position() + nytl::Vec2ui{20,20}); surfaceRect.size(surfaceRect.size() - nytl::Vec2ui{40,40}); dc.mask(surfaceRect); dc.fill(ny::Color::green); } ny::Rectangle surfaceRect(surf->extents()); surfaceRect.position(surfaceRect.position() - outp.extents().position); dc.mask(surfaceRect); ny::TextureBrush surfaceBrush; surfaceBrush.extents = surfaceRect; surfaceBrush.texture = surf->surfaceContext().content(); dc.fill(surfaceBrush); } if(cursorSurface) { SurfaceRes* surf = cursorSurface; ny::Rectangle surfaceRect(surf->extents()); surfaceRect.position(surfaceRect.position() - outp.extents().position); dc.mask(surfaceRect); ny::TextureBrush surfaceBrush; surfaceBrush.extents = surfaceRect; surfaceBrush.texture = surf->surfaceContext().content(); dc.fill(surfaceBrush); surf->sendFrameDone(); } else { if(!cursorTexture.glTexture()) { ny::Image cursorImage; ny::sendLog("loading cursor image: ", cursorImage.load("cursor.png")); cursorTexture.create(cursorImage); } ny::TextureBrush cursorBrush; cursorBrush.extents.position = seat_->pointer()->position() - outp.extents().position; cursorBrush.extents.size = nytl::Vec2f(30, 30); cursorBrush.texture = &cursorTexture; dc.mask(ny::Rectangle(cursorBrush.extents.position, nytl::Vec2f(30, 30))); dc.fill(cursorBrush); } }
void Screenshooter::shootSurface(wl_client *client, wl_resource *resource, uint32_t id) { wl_resource *res = wl_resource_create(client, &orbital_surface_screenshot_interface, 1, id); class SurfaceScreenshot : public PointerGrab { public: SurfaceScreenshot(Compositor *c, wl_resource *res) : m_compositor(c) , m_resource(res) , m_surface(nullptr) { static const struct orbital_surface_screenshot_interface implementation = { wrapInterface(shoot), }; wl_resource_set_implementation(m_resource, &implementation, this, nullptr); } void failed() { orbital_surface_screenshot_send_failed(m_resource); wl_resource_destroy(m_resource); delete this; } void shoot(wl_resource *resource) { if (!wl_shm_buffer_get(resource)) { failed(); return; } wl_shm_buffer *shm = wl_shm_buffer_get(resource); int width = wl_shm_buffer_get_width(shm); int height = wl_shm_buffer_get_height(shm); int stride = wl_shm_buffer_get_stride(shm); QSize size = m_surface->contentSize(); if (stride != size.width() * 4 || height != size.height()) { failed(); return; } wl_shm_buffer_begin_access(shm); void *data = wl_shm_buffer_get_data(shm); m_surface->copyContent(data, stride * height, QRect(0, 0, width, height)); wl_shm_buffer_end_access(shm); orbital_surface_screenshot_send_done(m_resource); wl_resource_destroy(m_resource); delete this; } void motion(uint32_t time, Pointer::MotionEvent evt) override { pointer()->move(evt); } void button(uint32_t time, PointerButton button, Pointer::ButtonState state) override { if (pointer()->buttonCount() == 0 && state == Pointer::ButtonState::Released) { View *view = m_compositor->pickView(pointer()->x(), pointer()->y()); if (view) { m_surface = view->surface(); QSize size = m_surface->contentSize(); orbital_surface_screenshot_send_setup(m_resource, size.width(), size.height(), size.width() * 4, 0); } end(); } } Compositor *m_compositor; wl_resource *m_resource; Surface *m_surface; }; auto *grab = new SurfaceScreenshot(m_compositor, res); Seat *seat = m_compositor->seats().front(); seat->pointer()->setFocus(nullptr); grab->start(seat, PointerCursor::Kill); }