Skip to content

Commit

Permalink
Handle stacking and focus for #1
Browse files Browse the repository at this point in the history
  • Loading branch information
jaelpark committed Jan 30, 2021
1 parent 550d4e0 commit a931c93
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 62 deletions.
133 changes: 77 additions & 56 deletions src/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,15 @@ void Default::Start(){
for(uint i = 0; i < ATOM_COUNT; ++i)
atoms[i] = GetAtom(patomStrs[i]);

//setup EWMH hints
ewmh_window = xcb_generate_id(pcon);

values[0] = 1;
xcb_create_window(pcon,XCB_COPY_FROM_PARENT,ewmh_window,pscr->root,
-1,-1,1,1,0,XCB_WINDOW_CLASS_INPUT_ONLY,XCB_COPY_FROM_PARENT,XCB_CW_OVERRIDE_REDIRECT,values);

if(standaloneComp){
DebugPrintf(stdout,"Launching in standalone compositor mode.\n");
//send an internal map notification to let the compositor know about the existing windows
xcb_query_tree_cookie_t queryTreeCookie = xcb_query_tree(pcon,pscr->root);
xcb_query_tree_reply_t *pqueryTreeReply = xcb_query_tree_reply(pcon,queryTreeCookie,0);
Expand All @@ -711,15 +719,8 @@ void Default::Start(){
xcb_flush(pcon);

}else{

const char wmName[] = "chamfer";

//setup EWMH hints
ewmh_window = xcb_generate_id(pcon);

values[0] = 1;
xcb_create_window(pcon,XCB_COPY_FROM_PARENT,ewmh_window,pscr->root,
-1,-1,1,1,0,XCB_WINDOW_CLASS_INPUT_ONLY,XCB_COPY_FROM_PARENT,XCB_CW_OVERRIDE_REDIRECT,values);
xcb_change_property(pcon,XCB_PROP_MODE_REPLACE,ewmh_window,ewmh._NET_SUPPORTING_WM_CHECK,XCB_ATOM_WINDOW,32,1,&ewmh_window);
xcb_change_property(pcon,XCB_PROP_MODE_REPLACE,ewmh_window,ewmh._NET_WM_NAME,XCB_ATOM_STRING,8,strlen(wmName),wmName);

Expand Down Expand Up @@ -780,7 +781,6 @@ void Default::Start(){
xcb_configure_window(pcon,ewmh_window,XCB_CONFIG_WINDOW_STACK_MODE,values);

xcb_map_window(pcon,ewmh_window);

}

void Default::Stop(){
Expand Down Expand Up @@ -869,12 +869,12 @@ sint Default::HandleEvent(bool forcePoll){
WManager::Rectangle rect = {pev->x,pev->y,pev->width,pev->height};

auto mrect = std::find_if(configCache.begin(),configCache.end(),[&](auto &p)->bool{
return pev->window == p.first;
return pev->window == std::get<0>(p);//p.first;
});
if(mrect == configCache.end()){
configCache.push_back(std::pair<xcb_window_t, WManager::Rectangle>(pev->window,rect));
configCache.push_back(ConfigCacheElement(pev->window,rect,0));
mrect = configCache.end()-1;
}else (*mrect).second = rect;
}else std::get<1>(*mrect) = rect;

DebugPrintf(stdout,"create %x | %d,%d %ux%u\n",pev->window,pev->x,pev->y,pev->width,pev->height);
}
Expand All @@ -889,7 +889,7 @@ sint Default::HandleEvent(bool forcePoll){
break;

auto mrect = std::find_if(configCache.begin(),configCache.end(),[&](auto &p)->bool{
return pev->window == p.first;
return pev->window == std::get<0>(p);
});

//TODO: allow x,y configuration if dock or desktop feature
Expand Down Expand Up @@ -941,27 +941,27 @@ sint Default::HandleEvent(bool forcePoll){

if(mrect == configCache.end()){
//an entry should always be present, since CREATE_NOTIFY creates one
configCache.push_back(std::pair<xcb_window_t, WManager::Rectangle>(pev->window,rect));
configCache.push_back(ConfigCacheElement(pev->window,rect,0));
mrect = configCache.end()-1;
}else{
if(pev->value_mask & XCB_CONFIG_WINDOW_X)
(*mrect).second.x = rect.x;
std::get<1>(*mrect).x = rect.x;
if(pev->value_mask & XCB_CONFIG_WINDOW_Y)
(*mrect).second.y = rect.y;
std::get<1>(*mrect).y = rect.y;
if(pev->value_mask & XCB_CONFIG_WINDOW_WIDTH)
(*mrect).second.w = rect.w;
std::get<1>(*mrect).w = rect.w;
if(pev->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
(*mrect).second.h = rect.h;
std::get<1>(*mrect).h = rect.h;
}

struct{
uint16_t m;
uint32_t v;
} maskm[] = {
{XCB_CONFIG_WINDOW_X,(*mrect).second.x},
{XCB_CONFIG_WINDOW_Y,(*mrect).second.y},
{XCB_CONFIG_WINDOW_WIDTH,(*mrect).second.w},
{XCB_CONFIG_WINDOW_HEIGHT,(*mrect).second.h},
{XCB_CONFIG_WINDOW_X,std::get<1>(*mrect).x},
{XCB_CONFIG_WINDOW_Y,std::get<1>(*mrect).y},
{XCB_CONFIG_WINDOW_WIDTH,std::get<1>(*mrect).w},
{XCB_CONFIG_WINDOW_HEIGHT,std::get<1>(*mrect).h},
{XCB_CONFIG_WINDOW_BORDER_WIDTH,pev->border_width},
{XCB_CONFIG_WINDOW_SIBLING,pev->sibling},
//{XCB_CONFIG_WINDOW_STACK_MODE,pev->stack_mode} //floating clients may request configuration, including stack mode, which ruins the stacking order we've already set
Expand All @@ -978,9 +978,9 @@ sint Default::HandleEvent(bool forcePoll){

//TODO: do this and the cache in CONFIGURE_NOTIFY?
if(pclient1)
pclient1->UpdateTranslation(&(*mrect).second);
pclient1->UpdateTranslation(&std::get<1>(*mrect));

DebugPrintf(stdout,"configure request: %x | %d, %d, %u, %u (mask: %x) -> %d, %d, %u, %u\n",pev->window,pev->x,pev->y,pev->width,pev->height,pev->value_mask,(*mrect).second.x,(*mrect).second.y,(*mrect).second.w,(*mrect).second.h);
DebugPrintf(stdout,"configure request: %x | %d, %d, %u, %u (mask: %x) -> %d, %d, %u, %u\n",pev->window,pev->x,pev->y,pev->width,pev->height,pev->value_mask,std::get<1>(*mrect).x,std::get<1>(*mrect).y,std::get<1>(*mrect).w,std::get<1>(*mrect).h);
}
break;
case XCB_MAP_REQUEST:{
Expand Down Expand Up @@ -1048,12 +1048,12 @@ sint Default::HandleEvent(bool forcePoll){
}

auto mrect = std::find_if(configCache.begin(),configCache.end(),[&](auto &p)->bool{
return pev->window == p.first;
return pev->window == std::get<0>(p);
});
if(mrect == configCache.end()){
//an entry should always be present, since CREATE_NOTIFY creates one
WManager::Rectangle rect;
configCache.push_back(std::pair<xcb_window_t, WManager::Rectangle>(pev->window,rect));
configCache.push_back(ConfigCacheElement(pev->window,rect,0));
mrect = configCache.end()-1;
}
//printf("Found cached location: %d, %d, %u, %u.\n",(*mrect).second.x,(*mrect).second.y,(*mrect).second.w,(*mrect).second.h);
Expand All @@ -1068,25 +1068,25 @@ sint Default::HandleEvent(bool forcePoll){
(sizeHints.min_width == sizeHints.max_width ||
sizeHints.min_height == sizeHints.max_height)){
//
(*mrect).second.w = sizeHints.min_width;
(*mrect).second.h = sizeHints.min_height;
std::get<1>(*mrect).w = sizeHints.min_width;
std::get<1>(*mrect).h = sizeHints.min_height;
hintFlags |= X11Client::CreateInfo::HINT_FLOATING;
}else
if(sizeHints.flags & XCB_ICCCM_SIZE_HINT_US_SIZE || sizeHints.flags & XCB_ICCCM_SIZE_HINT_P_SIZE){
(*mrect).second.w = sizeHints.width;
(*mrect).second.h = sizeHints.height;
std::get<1>(*mrect).w = sizeHints.width;
std::get<1>(*mrect).h = sizeHints.height;
}

(*mrect).second.x = (pscr->width_in_pixels-(*mrect).second.w)/2;
(*mrect).second.y = (pscr->height_in_pixels-(*mrect).second.h)/2;
std::get<1>(*mrect).x = (pscr->width_in_pixels-std::get<1>(*mrect).w)/2;
std::get<1>(*mrect).y = (pscr->height_in_pixels-std::get<1>(*mrect).h)/2;
if((sizeHints.flags & XCB_ICCCM_SIZE_HINT_US_POSITION || sizeHints.flags & XCB_ICCCM_SIZE_HINT_P_POSITION) && allowPositionConfig && (sizeHints.x != 0 && sizeHints.y != 0)){
(*mrect).second.x = sizeHints.x;
(*mrect).second.y = sizeHints.y;
std::get<1>(*mrect).x = sizeHints.x;
std::get<1>(*mrect).y = sizeHints.y;
}
uint values[4] = {(*mrect).second.x,(*mrect).second.y,(*mrect).second.w,(*mrect).second.h};
uint values[4] = {std::get<1>(*mrect).x,std::get<1>(*mrect).y,std::get<1>(*mrect).w,std::get<1>(*mrect).h};
xcb_configure_window(pcon,pev->window,XCB_CONFIG_WINDOW_X|XCB_CONFIG_WINDOW_Y|XCB_CONFIG_WINDOW_WIDTH|XCB_CONFIG_WINDOW_HEIGHT,values);
}
printf("Size hints: %d, %d, %u, %u.\n",(*mrect).second.x,(*mrect).second.y,(*mrect).second.w,(*mrect).second.h);
printf("Size hints: %d, %d, %u, %u.\n",std::get<1>(*mrect).x,std::get<1>(*mrect).y,std::get<1>(*mrect).w,std::get<1>(*mrect).h);

if(propertyReplyWindowType){
//https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html
Expand Down Expand Up @@ -1167,7 +1167,7 @@ sint Default::HandleEvent(bool forcePoll){

X11Client::CreateInfo createInfo;
createInfo.window = pev->window;
createInfo.prect = &(*mrect).second;
createInfo.prect = &std::get<1>(*mrect);
createInfo.pstackClient =
!(hintFlags & X11Client::CreateInfo::HINT_DESKTOP)?
((pbaseClient && !(hintFlags & X11Client::CreateInfo::HINT_ABOVE))?
Expand Down Expand Up @@ -1221,19 +1221,38 @@ sint Default::HandleEvent(bool forcePoll){
WManager::Rectangle rect = {pev->x,pev->y,pev->width,pev->height};

auto mrect = std::find_if(configCache.begin(),configCache.end(),[&](auto &p)->bool{
return pev->window == p.first;
return pev->window == std::get<0>(p);
});
if(mrect == configCache.end()){
configCache.push_back(std::pair<xcb_window_t, WManager::Rectangle>(pev->window,rect));
configCache.push_back(ConfigCacheElement(pev->window,rect,pev->above_sibling));
mrect = configCache.end()-1;
}else (*mrect).second = rect;
}else{
std::get<1>(*mrect) = rect;
std::get<2>(*mrect) = pev->above_sibling;
}

X11Client *pclient1 = FindClient(pev->window,MODE_AUTOMATIC);

if(pclient1)
pclient1->UpdateTranslation(&(*mrect).second);
if(pclient1){
pclient1->UpdateTranslation(&std::get<1>(*mrect));

if(standaloneComp){
auto m1 = std::find_if(clientStack.begin(),clientStack.end(),[&](auto &p)->bool{
return static_cast<X11Client *>(p)->window == pev->window;
});
if(pev->above_sibling != XCB_NONE){
auto ma = std::find_if(clientStack.begin(),clientStack.end(),[&](auto &p)->bool{
return static_cast<X11Client *>(p)->window == pev->above_sibling;
});
if(ma != clientStack.end())
if(std::distance(m1,ma) > 0)
std::rotate(m1,m1+1,ma+1);
else std::rotate(ma+1,m1,m1+1);
}else std::rotate(clientStack.begin(),m1,m1+1);

//TODO: handle stacking for standalone compositing
result = 1;
}
}

DebugPrintf(stdout,"configure to %d,%d %ux%u, %x\n",pev->x,pev->y,pev->width,pev->height,pev->window);
}
Expand Down Expand Up @@ -1272,7 +1291,7 @@ sint Default::HandleEvent(bool forcePoll){
}

auto mrect = std::find_if(configCache.begin(),configCache.end(),[&](auto &p)->bool{
return pev->window == p.first;
return pev->window == std::get<0>(p);
});
if(mrect == configCache.end()){
//it might be the case that no configure notification was received
Expand All @@ -1283,11 +1302,11 @@ sint Default::HandleEvent(bool forcePoll){
WManager::Rectangle rect = {pgeometryReply->x,pgeometryReply->y,pgeometryReply->width,pgeometryReply->height};
free(pgeometryReply);

configCache.push_back(std::pair<xcb_window_t, WManager::Rectangle>(pev->window,rect));
configCache.push_back(ConfigCacheElement(pev->window,rect,0));
mrect = configCache.end()-1;

}
WManager::Rectangle *prect = &(*mrect).second;
WManager::Rectangle *prect = &std::get<1>(*mrect);

static WManager::Client dummyClient(0);

Expand Down Expand Up @@ -1337,9 +1356,18 @@ sint Default::HandleEvent(bool forcePoll){
break;
clients.push_back(std::pair<X11Client *, MODE>(pclient,MODE_AUTOMATIC));

const WManager::Container *proot = pclient->pcontainer->GetRoot();
if(!standaloneComp)
if(!standaloneComp){
const WManager::Container *proot = pclient->pcontainer->GetRoot();
StackClients(proot);
}else{
//clientStack won't get cleared in standalone compositor mode
if(std::get<2>(*mrect) != 0){ //!= XCB_NONE
auto m = std::find_if(clientStack.begin(),clientStack.end(),[&](auto &p)->bool{
return static_cast<X11Client *>(p)->window == std::get<2>(*mrect);
});
clientStack.insert(m+1,pclient);
}else clientStack.push_front(pclient);
}

for(uint i = 0; i < 2; ++i){
if(propertyReply1[i])
Expand Down Expand Up @@ -1642,18 +1670,11 @@ sint Default::HandleEvent(bool forcePoll){
xcb_focus_in_event_t *pev = (xcb_focus_in_event_t*)pevent;
printf("XCB_FOCUS_IN: *** focus %x\n",pev->event);

/*X11Client *pclient11 = FindClient(pev->event,MODE_UNDEFINED);
X11Client *pclient11 = FindClient(pev->event,MODE_UNDEFINED);
if(!pclient11 || pclient11->flags & X11Client::FLAG_UNMAPPING)
break;

for(auto &m : clientStack){
//std::get<1>(m) = false;
for(WManager::Container *pcontainer = pclient11->pcontainer; pcontainer; pcontainer = pcontainer->GetParent()){
//
}
}*/
//TODO: standaloneComp: set focus. All clients share the same container
//-traverse through parents and mark the focus in clientStack
pfocusInClient = pclient11;
}
break;
case XCB_ENTER_NOTIFY:{
Expand Down
4 changes: 3 additions & 1 deletion src/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ friend class Compositor::TexturePixmap;

public:
std::deque<WManager::Client *> clientStack;
WManager::Client *pfocusInClient; //from XCB_FOCUS_IN events (uncontained clients)
protected:
std::deque<std::pair<const WManager::Client *, WManager::Client *>> appendixQueue; //no need to store, rather keep it here to avoid repeated construction

Expand Down Expand Up @@ -250,8 +251,9 @@ class Default : public X11Backend{
private:
xcb_keycode_t exitKeycode;
//xcb_keycode_t testKeycode;
typedef std::tuple<xcb_window_t, WManager::Rectangle, xcb_window_t> ConfigCacheElement;
std::vector<std::pair<X11Client *, MODE>> clients;
std::vector<std::pair<xcb_window_t, WManager::Rectangle>> configCache;
std::vector<ConfigCacheElement> configCache;
std::vector<X11Client *> unmappingQueue;
std::vector<xcb_window_t> netClientList; //used only to update the property - not maintained
X11Client *pdragClient;
Expand Down
6 changes: 4 additions & 2 deletions src/compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -890,9 +890,11 @@ bool CompositorInterface::PollFrameFence(bool suspend){
return true;
}

void CompositorInterface::GenerateCommandBuffers(const std::deque<WManager::Client *> *pclientStack, const WManager::Container *pfocus){
void CompositorInterface::GenerateCommandBuffers(const std::deque<WManager::Client *> *pclientStack, const WManager::Container *pfocus, const WManager::Client *pfocusClient){
//Create a render list elements arranged from back to front
auto checkFocus = [&](const WManager::Client *pclient)->bool{
if(pclient->pcontainer == pclient->pcontainer->GetRoot())
return false;
for(WManager::Container *pcontainer = pclient->pcontainer; pcontainer; pcontainer = pcontainer->GetParent())
if(pfocus == pcontainer)
return true;
Expand All @@ -910,7 +912,7 @@ void CompositorInterface::GenerateCommandBuffers(const std::deque<WManager::Clie
renderObject.pclientFrame->oldShaderFlags = renderObject.pclientFrame->shaderFlags;
renderObject.pclientFrame->shaderFlags =
//(std::get<1>(m)?ClientFrame::SHADER_FLAG_FOCUS:0)
(checkFocus(renderObject.pclient)?ClientFrame::SHADER_FLAG_FOCUS:0)
((checkFocus(renderObject.pclient) || m == pfocusClient)?ClientFrame::SHADER_FLAG_FOCUS:0)
|(renderObject.pclient->pcontainer->flags & WManager::Container::FLAG_FLOATING?ClientFrame::SHADER_FLAG_FLOATING:0)
|(renderObject.pclient->pcontainer->pParent && renderObject.pclient->pcontainer->pParent->flags & WManager::Container::FLAG_STACKED?ClientFrame::SHADER_FLAG_STACKED:0)
|renderObject.pclientFrame->shaderUserFlags;
Expand Down
2 changes: 1 addition & 1 deletion src/compositor.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ friend class X11DebugClientFrame;
void CreateRenderQueueAppendix(const WManager::Client *, const WManager::Container *);
void CreateRenderQueue(const WManager::Container *, const WManager::Container *);
bool PollFrameFence(bool);
void GenerateCommandBuffers(const std::deque<WManager::Client *> *, const WManager::Container *);
void GenerateCommandBuffers(const std::deque<WManager::Client *> *, const WManager::Container *, const WManager::Client *);
void Present();
virtual bool CheckPresentQueueCompatibility(VkPhysicalDevice, uint) const = 0;
virtual void CreateSurfaceKHR(VkSurfaceKHR *) const = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ class DefaultCompositor : public Compositor::X11Compositor, public RunCompositor
if(!PollFrameFence(proot->noComp))
return;

GenerateCommandBuffers(&pbackend->clientStack,WManager::Container::ptreeFocus);
GenerateCommandBuffers(&pbackend->clientStack,WManager::Container::ptreeFocus,pbackend->pfocusInClient);
Compositor::X11Compositor::Present();
}

Expand Down Expand Up @@ -880,7 +880,7 @@ class DebugCompositor : public Compositor::X11DebugCompositor, public RunComposi
if(!PollFrameFence(false))
return;

GenerateCommandBuffers(&pbackend->clientStack,WManager::Container::ptreeFocus);
GenerateCommandBuffers(&pbackend->clientStack,WManager::Container::ptreeFocus,pbackend->pfocusInClient);
Compositor::X11DebugCompositor::Present();
}

Expand Down

0 comments on commit a931c93

Please sign in to comment.