From d75a7a8480885526de6de54dd42920b3955a512e Mon Sep 17 00:00:00 2001 From: jparkkil Date: Sat, 2 Mar 2019 19:05:24 +0200 Subject: [PATCH] Transition animations #1 --- src/backend.cpp | 32 ++++++++++++++++++++------------ src/backend.h | 6 +++--- src/compositor.cpp | 17 +++++++++++++++-- src/compositor.h | 4 +++- src/container.h | 2 ++ src/main.cpp | 17 +++++++++++++++-- 6 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/backend.cpp b/src/backend.cpp index 72fc1e6..2a7f62c 100644 --- a/src/backend.cpp +++ b/src/backend.cpp @@ -156,11 +156,14 @@ X11Client::X11Client(WManager::Container *pcontainer, const CreateInfo *pcreateI xcb_change_window_attributes(pbackend->pcon,window,XCB_CW_EVENT_MASK,values); //if(!(pcontainer->flags & WManager::Container::FLAG_FLOATING)) - if(pcreateInfo->mode == CreateInfo::CREATE_CONTAINED && !(pcontainer->flags & WManager::Container::FLAG_FLOATING))// || - //(pcreateInfo->mode == CreateInfo::CREATE_AUTOMATIC && !pcreateInfo->prect)) - //(pcreateInfo->mode == CreateInfo::CREATE_AUTOMATIC && !pcreateInfo->prect)) + if(pcreateInfo->mode == CreateInfo::CREATE_CONTAINED && !(pcontainer->flags & WManager::Container::FLAG_FLOATING)){ UpdateTranslation(); - else rect = *pcreateInfo->prect; + oldRect = rect; + }else{ + rect = *pcreateInfo->prect; + oldRect = rect; + translationTime = std::numeric_limits::lowest(); //make sure we don't render when nothing is moving + } if(pcreateInfo->mode != CreateInfo::CREATE_AUTOMATIC) xcb_map_window(pbackend->pcon,window); @@ -179,6 +182,8 @@ void X11Client::UpdateTranslation(){ glm::vec4 coord = glm::vec4(pcontainer->p,pcontainer->e)*screen; if(!(pcontainer->flags & WManager::Container::FLAG_FULLSCREEN)) coord += glm::vec4(pcontainer->borderWidth*aspect,-2.0f*pcontainer->borderWidth*aspect)*screen; + oldRect = rect; + clock_gettime(CLOCK_MONOTONIC,&translationTime); rect = (WManager::Rectangle){coord.x,coord.y,coord.z,coord.w}; uint values[4] = {rect.x,rect.y,rect.w,rect.h}; @@ -193,6 +198,8 @@ void X11Client::UpdateTranslation(){ } void X11Client::UpdateTranslation(const WManager::Rectangle *prect){ + oldRect = rect; //should be animated at all in this case? + clock_gettime(CLOCK_MONOTONIC,&translationTime); if(prect->w != rect.w || prect->h != rect.h){ rect = *prect; AdjustSurface1(); @@ -538,7 +545,7 @@ void Default::Start(){ xcb_configure_window(pcon,ewmh_window,XCB_CONFIG_WINDOW_STACK_MODE,values); } -sint Default::HandleEvent(){ +sint Default::HandleEvent(bool forcePoll){ struct timespec currentTime; clock_gettime(CLOCK_MONOTONIC,¤tTime); @@ -591,8 +598,8 @@ sint Default::HandleEvent(){ sint result = 0; - //for(xcb_generic_event_t *pevent = xcb_poll_for_event(pcon); pevent; pevent = xcb_poll_for_event(pcon)){ - for(xcb_generic_event_t *pevent = xcb_wait_for_event(pcon); pevent; pevent = xcb_poll_for_event(pcon)){ + for(xcb_generic_event_t *pevent = forcePoll?xcb_poll_for_event(pcon):xcb_wait_for_event(pcon); + pevent; pevent = xcb_poll_for_event(pcon)){ //Event found, move to polling mode for some time. clock_gettime(CLOCK_MONOTONIC,&pollTimer); //polling = true; @@ -1265,6 +1272,7 @@ X11Client * Default::FindClient(xcb_window_t window, MODE mode) const{ DebugClient::DebugClient(WManager::Container *pcontainer, const DebugClient::CreateInfo *pcreateInfo) : Client(pcontainer), pbackend(pcreateInfo->pbackend){ UpdateTranslation(); + oldRect = rect; } DebugClient::~DebugClient(){ @@ -1282,6 +1290,8 @@ void DebugClient::UpdateTranslation(){ glm::vec4 screen(se.x,se.y,se.x,se.y); glm::vec2 aspect = glm::vec2(1.0,screen.x/screen.y); glm::vec4 coord = glm::vec4(pcontainer->p+pcontainer->borderWidth*aspect,pcontainer->e-2.0f*pcontainer->borderWidth*aspect)*screen; + oldRect = rect; + clock_gettime(CLOCK_MONOTONIC,&translationTime); rect = (WManager::Rectangle){coord.x,coord.y,coord.z,coord.w}; AdjustSurface1(); @@ -1372,10 +1382,9 @@ void Debug::Start(){ xcb_key_symbols_free(psymbols); } -sint Debug::HandleEvent(){ - //xcb_generic_event_t *pevent = xcb_poll_for_event(pcon); - //for(xcb_generic_event_t *pevent = xcb_poll_for_event(pcon); pevent; pevent = xcb_poll_for_event(pcon)){ - for(xcb_generic_event_t *pevent = xcb_wait_for_event(pcon); pevent; pevent = xcb_poll_for_event(pcon)){ +sint Debug::HandleEvent(bool forcePoll){ + for(xcb_generic_event_t *pevent = forcePoll?xcb_poll_for_event(pcon):xcb_wait_for_event(pcon); + pevent; pevent = xcb_poll_for_event(pcon)){ //switch(pevent->response_type & ~0x80){ switch(pevent->response_type & 0x7f){ /*case XCB_EXPOSE:{ @@ -1385,7 +1394,6 @@ sint Debug::HandleEvent(){ case XCB_CLIENT_MESSAGE:{ DebugPrintf(stdout,"message\n"); //xcb_client_message_event_t *pev = (xcb_client_message_event_t*)pevent; - //if(pev->data.data32[0] == wmD } break; case XCB_KEY_PRESS:{ diff --git a/src/backend.h b/src/backend.h index 0ee8c8f..8656c02 100644 --- a/src/backend.h +++ b/src/backend.h @@ -73,7 +73,7 @@ class BackendInterface{ virtual void Start() = 0; //virtual sint GetEventFileDescriptor() = 0; //virtual void SetupEnvironment() = 0; - virtual sint HandleEvent() = 0; + virtual sint HandleEvent(bool) = 0; virtual void MoveContainer(WManager::Container *, WManager::Container *) = 0; virtual const WManager::Container * GetRoot() const = 0; virtual const std::vector> * GetStackAppendix() const = 0; @@ -217,7 +217,7 @@ class Default : public X11Backend{ virtual ~Default(); void Start(); //void SetupEnvironment(); - sint HandleEvent(); + sint HandleEvent(bool); X11Client * FindClient(xcb_window_t, MODE) const; protected: enum PROPERTY_ID{ @@ -270,7 +270,7 @@ class Debug : public X11Backend{ virtual ~Debug(); void Start(); //void SetupEnvironment(); - sint HandleEvent(); + sint HandleEvent(bool); X11Client * FindClient(xcb_window_t, MODE) const; protected: virtual DebugClient * SetupClient(const DebugClient::CreateInfo *) = 0; diff --git a/src/compositor.cpp b/src/compositor.cpp index b415d2b..d8c46a4 100644 --- a/src/compositor.cpp +++ b/src/compositor.cpp @@ -173,7 +173,7 @@ void ClientFrame::UpdateDescSets(){ vkUpdateDescriptorSets(pcomp->logicalDev,writeDescSets.size(),writeDescSets.data(),0,0); } -CompositorInterface::CompositorInterface(uint _physicalDevIndex) : physicalDevIndex(_physicalDevIndex), currentFrame(0), frameTag(0), pbackground(0){ +CompositorInterface::CompositorInterface(uint _physicalDevIndex) : physicalDevIndex(_physicalDevIndex), currentFrame(0), frameTag(0), pbackground(0), playingAnimation(false){ // } @@ -766,6 +766,7 @@ void CompositorInterface::GenerateCommandBuffers(const WManager::Container *proo renderPassBeginInfo.pClearValues = &clearValue; vkCmdBeginRenderPass(pcommandBuffers[currentFrame],&renderPassBeginInfo,VK_SUBPASS_CONTENTS_INLINE); + playingAnimation = false; clock_gettime(CLOCK_MONOTONIC,&frameTime); if(pbackground){ @@ -787,9 +788,21 @@ void CompositorInterface::GenerateCommandBuffers(const WManager::Container *proo || renderObject.pclient->rect.x > imageExtent.width || renderObject.pclient->rect.y > imageExtent.height) continue; + float t = timespec_diff(frameTime,renderObject.pclient->translationTime); + float s = std::clamp(t/0.3f,0.0f,1.0f); + s = 1.0f/(1.0f+expf(-10.0f*s+5.0f)); + + glm::vec2 oldRect1 = glm::vec2(renderObject.pclient->oldRect.x,renderObject.pclient->oldRect.y); + glm::vec2 position = oldRect1+s*(glm::vec2(renderObject.pclient->rect.x,renderObject.pclient->rect.y)-oldRect1); + if(s < 0.99f) + playingAnimation = true; + else position = glm::vec2(renderObject.pclient->rect.x,renderObject.pclient->rect.y); + VkRect2D frame; - frame.offset = {renderObject.pclient->rect.x,renderObject.pclient->rect.y}; + frame.offset = {(sint)position.x,(sint)position.y}; frame.extent = {renderObject.pclient->rect.w,renderObject.pclient->rect.h}; + //frame.offset = {renderObject.pclient->rect.x,renderObject.pclient->rect.y}; + //frame.extent = {renderObject.pclient->rect.w,renderObject.pclient->rect.h}; /*VkRect2D scissor = frame; for(uint j = i+1; j < renderQueue.size(); ++j){ diff --git a/src/compositor.h b/src/compositor.h index 3414f38..c4439e8 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -118,7 +118,7 @@ friend class ClientFrame; VkSampler pointSampler; struct timespec frameTime; - uint64 frameTag; + uint64 frameTag; //frame counter, to prevent releasing resources still in use struct RenderObject{ WManager::Client *pclient; @@ -151,6 +151,8 @@ friend class ClientFrame; }; std::vector descSetCache; + bool playingAnimation; + static VKAPI_ATTR VkBool32 VKAPI_CALL ValidationLayerDebugCallback(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char *, const char *, void *); }; diff --git a/src/container.h b/src/container.h index 092fd90..3570aae 100644 --- a/src/container.h +++ b/src/container.h @@ -20,6 +20,8 @@ class Client{ virtual void UpdateTranslation(){}// = 0; virtual void Kill(){}// = 0; Rectangle rect; //pixel coordinates of the client + Rectangle oldRect; //to animate the transitions + struct timespec translationTime; class Container *pcontainer; }; diff --git a/src/main.cpp b/src/main.cpp index 562629f..2136650 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -291,6 +291,7 @@ class RunCompositor{ RunCompositor(WManager::Container *_proot, std::vector> *_pstackAppendix) : proot(_proot), pstackAppendix(_pstackAppendix){} virtual ~RunCompositor(){} virtual void Present() = 0; + virtual bool IsAnimating() const = 0; virtual void WaitIdle() = 0; protected: WManager::Container *proot; @@ -646,6 +647,10 @@ class DefaultCompositor : public Compositor::X11Compositor, public RunCompositor Compositor::X11Compositor::Present(); } + bool IsAnimating() const{ + return playingAnimation; + } + void WaitIdle(){ Compositor::X11Compositor::WaitIdle(); } @@ -681,6 +686,10 @@ class DebugCompositor : public Compositor::X11DebugCompositor, public RunComposi Compositor::X11DebugCompositor::Present(); } + bool IsAnimating() const{ + return playingAnimation; + } + void WaitIdle(){ Compositor::X11DebugCompositor::WaitIdle(); } @@ -700,6 +709,10 @@ class NullCompositor : public Compositor::NullCompositor, public RunCompositor{ // } + bool IsAnimating() const{ + return false; + } + void WaitIdle(){ // } @@ -769,11 +782,11 @@ int main(sint argc, const char **pargv){ for(;;){ //TODO: can we wait for vsync before handling the event? Might help with the stuttering - sint result = pbackend11->HandleEvent(); + sint result = pbackend11->HandleEvent(pcomp->IsAnimating()); if(result == -1) break; else - if(result == 0) + if(result == 0 && !pcomp->IsAnimating()) //&& !pcomp->Animated() continue; try{