diff --git a/xbanan/Base.cpp b/xbanan/Base.cpp index 7c277a4..d7b4885 100644 --- a/xbanan/Base.cpp +++ b/xbanan/Base.cpp @@ -2297,12 +2297,48 @@ BAN::ErrorOr handle_packet(Client& client_info, BAN::ConstByteSpan packet) } case X_GrabServer: { - dwarnln("GrabServer"); + g_server_grabber_fd = client_info.fd; + + for (const auto& [_, thingy] : g_epoll_thingies) + { + if (thingy.type != EpollThingy::Type::Client) + continue; + + auto& other_client = thingy.value.get(); + if (client_info.fd == other_client.fd) + continue; + + uint32_t events = 0; + if (other_client.has_epollout) + events |= EPOLLOUT; + + epoll_event event { .events = events, .data = { .fd = other_client.fd } }; + epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event); + } + break; } case X_UngrabServer: { - dwarnln("UngrabServer"); + g_server_grabber_fd = -1; + + for (const auto& [_, thingy] : g_epoll_thingies) + { + if (thingy.type != EpollThingy::Type::Client) + continue; + + auto& other_client = thingy.value.get(); + if (client_info.fd == other_client.fd) + continue; + + uint32_t events = EPOLLIN; + if (other_client.has_epollout) + events |= EPOLLOUT; + + epoll_event event { .events = events, .data = { .fd = other_client.fd } }; + epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event); + } + break; } case X_QueryPointer: diff --git a/xbanan/Definitions.h b/xbanan/Definitions.h index dd4e6e7..0debc1a 100644 --- a/xbanan/Definitions.h +++ b/xbanan/Definitions.h @@ -194,3 +194,5 @@ extern ATOM g_atom_value; extern int g_epoll_fd; extern BAN::HashMap g_epoll_thingies; + +extern int g_server_grabber_fd; diff --git a/xbanan/main.cpp b/xbanan/main.cpp index ca16d3c..bf9d7d0 100644 --- a/xbanan/main.cpp +++ b/xbanan/main.cpp @@ -106,6 +106,8 @@ ATOM g_atom_value = XA_LAST_PREDEFINED + 1; int g_epoll_fd; BAN::HashMap g_epoll_thingies; +int g_server_grabber_fd = -1; + int main() { for (int sig = 1; sig < NSIG; sig++) @@ -292,6 +294,26 @@ int main() epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr); close(client_fd); g_epoll_thingies.remove(client_fd); + + if (client_fd == g_server_grabber_fd) + { + g_server_grabber_fd = -1; + + for (const auto& [_, thingy] : g_epoll_thingies) + { + if (thingy.type != EpollThingy::Type::Client) + continue; + + auto& other_client = thingy.value.get(); + + uint32_t events = EPOLLIN; + if (other_client.has_epollout) + events |= EPOLLOUT; + + epoll_event event { .events = events, .data = { .fd = other_client.fd } }; + epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event); + } + } }; MUST(g_objects.insert(g_root.windowId, @@ -335,7 +357,11 @@ int main() } })); - epoll_event event = { .events = EPOLLIN, .data = { .fd = client_sock } }; + uint32_t events = 0; + if (g_server_grabber_fd == -1) + events |= EPOLLIN; + + epoll_event event = { .events = events, .data = { .fd = client_sock } }; if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, client_sock, &event) == -1) { perror("xbanan: epoll_ctl"); @@ -398,7 +424,11 @@ int main() if (client_info.output_buffer.empty()) { - epoll_event event { .events = EPOLLIN, .data = { .fd = client_info.fd } }; + uint32_t events = 0; + if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd) + events |= EPOLLIN; + + epoll_event event { .events = events, .data = { .fd = client_info.fd } }; if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1) { perror("xbanan: epoll_ctl"); @@ -416,6 +446,9 @@ int main() if (!(events[i].events & EPOLLIN)) continue; + if (g_server_grabber_fd != -1 && g_server_grabber_fd != client_info.fd) + continue; + switch (client_info.state) { case Client::State::ConnectionSetup: @@ -533,7 +566,11 @@ int main() if (client_info.output_buffer.empty() || client_info.has_epollout) continue; - epoll_event event { .events = EPOLLIN | EPOLLOUT, .data = { .fd = client_info.fd } }; + uint32_t events = EPOLLOUT; + if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd) + events |= EPOLLIN; + + epoll_event event { .events = events, .data = { .fd = client_info.fd } }; if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1) { perror("xbanan: epoll_ctl");