xwayland: move to hyprland impl (#6086)
This commit is contained in:
parent
a71207434c
commit
addd3e7f1a
36 changed files with 2956 additions and 707 deletions
291
src/xwayland/XSurface.cpp
Normal file
291
src/xwayland/XSurface.cpp
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
#include "XSurface.hpp"
|
||||
#include "XWayland.hpp"
|
||||
#include "../protocols/XWaylandShell.hpp"
|
||||
|
||||
#ifndef NO_XWAYLAND
|
||||
|
||||
#include "../Compositor.hpp"
|
||||
#include <ranges>
|
||||
|
||||
CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) {
|
||||
xcb_res_query_client_ids_cookie_t client_id_cookie = {0};
|
||||
if (g_pXWayland->pWM->xres) {
|
||||
xcb_res_client_id_spec_t spec = {.client = xID, .mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID};
|
||||
client_id_cookie = xcb_res_query_client_ids(g_pXWayland->pWM->connection, 1, &spec);
|
||||
}
|
||||
|
||||
uint32_t values[1];
|
||||
values[0] = XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
||||
xcb_change_window_attributes(g_pXWayland->pWM->connection, xID, XCB_CW_EVENT_MASK, values);
|
||||
|
||||
if (g_pXWayland->pWM->xres) {
|
||||
xcb_res_query_client_ids_reply_t* reply = xcb_res_query_client_ids_reply(g_pXWayland->pWM->connection, client_id_cookie, nullptr);
|
||||
if (!reply)
|
||||
return;
|
||||
|
||||
uint32_t* ppid = nullptr;
|
||||
xcb_res_client_id_value_iterator_t iter = xcb_res_query_client_ids_ids_iterator(reply);
|
||||
while (iter.rem > 0) {
|
||||
if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID && xcb_res_client_id_value_value_length(iter.data) > 0) {
|
||||
ppid = xcb_res_client_id_value_value(iter.data);
|
||||
break;
|
||||
}
|
||||
xcb_res_client_id_value_next(&iter);
|
||||
}
|
||||
if (ppid == NULL) {
|
||||
free(reply);
|
||||
return;
|
||||
}
|
||||
pid = *ppid;
|
||||
free(reply);
|
||||
}
|
||||
|
||||
events.resourceChange.registerStaticListener([this](void* data, std::any d) { ensureListeners(); }, nullptr);
|
||||
}
|
||||
|
||||
void CXWaylandSurface::ensureListeners() {
|
||||
bool connected = hyprListener_surfaceDestroy.isConnected();
|
||||
|
||||
if (connected && !surface) {
|
||||
hyprListener_surfaceDestroy.removeCallback();
|
||||
hyprListener_surfaceCommit.removeCallback();
|
||||
} else if (!connected && surface) {
|
||||
hyprListener_surfaceDestroy.initCallback(
|
||||
&surface->events.destroy,
|
||||
[this](void* owner, void* data) {
|
||||
if (mapped)
|
||||
unmap();
|
||||
|
||||
surface = nullptr;
|
||||
hyprListener_surfaceDestroy.removeCallback();
|
||||
hyprListener_surfaceCommit.removeCallback();
|
||||
events.resourceChange.emit();
|
||||
},
|
||||
nullptr, "CXWaylandSurface");
|
||||
hyprListener_surfaceCommit.initCallback(
|
||||
&surface->events.commit,
|
||||
[this](void* owner, void* data) {
|
||||
if (surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0 && !mapped) {
|
||||
map();
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->pending.buffer_width <= 0 && surface->pending.buffer_height <= 0 && mapped) {
|
||||
unmap();
|
||||
return;
|
||||
}
|
||||
|
||||
events.commit.emit();
|
||||
},
|
||||
nullptr, "CXWaylandSurface");
|
||||
}
|
||||
|
||||
if (resource) {
|
||||
listeners.destroyResource = resource->events.destroy.registerListener([this](std::any d) {
|
||||
unmap();
|
||||
surface = nullptr;
|
||||
events.resourceChange.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CXWaylandSurface::map() {
|
||||
if (mapped)
|
||||
return;
|
||||
|
||||
ASSERT(surface);
|
||||
|
||||
g_pXWayland->pWM->mappedSurfaces.emplace_back(self);
|
||||
g_pXWayland->pWM->mappedSurfacesStacking.emplace_back(self);
|
||||
|
||||
mapped = true;
|
||||
wlr_surface_map(surface);
|
||||
|
||||
Debug::log(LOG, "XWayland surface {:x} mapping", (uintptr_t)this);
|
||||
|
||||
events.map.emit();
|
||||
|
||||
g_pXWayland->pWM->updateClientList();
|
||||
}
|
||||
|
||||
void CXWaylandSurface::unmap() {
|
||||
if (!mapped)
|
||||
return;
|
||||
|
||||
ASSERT(surface);
|
||||
|
||||
std::erase(g_pXWayland->pWM->mappedSurfaces, self);
|
||||
std::erase(g_pXWayland->pWM->mappedSurfacesStacking, self);
|
||||
|
||||
mapped = false;
|
||||
wlr_surface_unmap(surface);
|
||||
|
||||
Debug::log(LOG, "XWayland surface {:x} unmapping", (uintptr_t)this);
|
||||
|
||||
events.unmap.emit();
|
||||
|
||||
g_pXWayland->pWM->updateClientList();
|
||||
}
|
||||
|
||||
void CXWaylandSurface::considerMap() {
|
||||
if (mapped)
|
||||
return;
|
||||
|
||||
if (!surface) {
|
||||
Debug::log(LOG, "XWayland surface: considerMap, nope, no surface");
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->pending.buffer_width > 0 && surface->pending.buffer_height > 0) {
|
||||
Debug::log(LOG, "XWayland surface: considerMap, sure, we have a buffer");
|
||||
map();
|
||||
return;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "XWayland surface: considerMap, nope, we don't have a buffer");
|
||||
}
|
||||
|
||||
bool CXWaylandSurface::wantsFocus() {
|
||||
if (atoms.empty())
|
||||
return true;
|
||||
|
||||
const std::array<uint32_t, 10> search = {
|
||||
HYPRATOMS["_NET_WM_WINDOW_TYPE_COMBO"], HYPRATOMS["_NET_WM_WINDOW_TYPE_DND"], HYPRATOMS["_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"],
|
||||
HYPRATOMS["_NET_WM_WINDOW_TYPE_MENU"], HYPRATOMS["_NET_WM_WINDOW_TYPE_NOTIFICATION"], HYPRATOMS["_NET_WM_WINDOW_TYPE_POPUP_MENU"],
|
||||
HYPRATOMS["_NET_WM_WINDOW_TYPE_SPLASH"], HYPRATOMS["_NET_WM_WINDOW_TYPE_DESKTOP"], HYPRATOMS["_NET_WM_WINDOW_TYPE_TOOLTIP"],
|
||||
HYPRATOMS["_NET_WM_WINDOW_TYPE_UTILITY"],
|
||||
};
|
||||
|
||||
for (auto& searched : search) {
|
||||
for (auto& a : atoms) {
|
||||
if (a == searched)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::configure(const CBox& box) {
|
||||
Vector2D oldSize = geometry.size();
|
||||
|
||||
geometry = box;
|
||||
|
||||
uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_BORDER_WIDTH;
|
||||
uint32_t values[] = {box.x, box.y, box.width, box.height, 0};
|
||||
xcb_configure_window(g_pXWayland->pWM->connection, xID, mask, values);
|
||||
|
||||
g_pXWayland->pWM->updateClientList();
|
||||
|
||||
xcb_flush(g_pXWayland->pWM->connection);
|
||||
}
|
||||
|
||||
void CXWaylandSurface::activate(bool activate) {
|
||||
if (overrideRedirect && !activate)
|
||||
return;
|
||||
g_pXWayland->pWM->activateSurface(self.lock());
|
||||
}
|
||||
|
||||
void CXWaylandSurface::setFullscreen(bool fs) {
|
||||
fullscreen = fs;
|
||||
g_pXWayland->pWM->sendState(self.lock());
|
||||
}
|
||||
|
||||
void CXWaylandSurface::setMinimized(bool mz) {
|
||||
minimized = mz;
|
||||
g_pXWayland->pWM->sendState(self.lock());
|
||||
}
|
||||
|
||||
void CXWaylandSurface::restackToTop() {
|
||||
uint32_t values[1] = {XCB_STACK_MODE_ABOVE};
|
||||
|
||||
xcb_configure_window(g_pXWayland->pWM->connection, xID, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||
|
||||
for (auto it = g_pXWayland->pWM->mappedSurfacesStacking.begin(); it != g_pXWayland->pWM->mappedSurfacesStacking.end(); ++it) {
|
||||
if (*it == self) {
|
||||
std::rotate(it, it + 1, g_pXWayland->pWM->mappedSurfacesStacking.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_pXWayland->pWM->updateClientList();
|
||||
|
||||
xcb_flush(g_pXWayland->pWM->connection);
|
||||
}
|
||||
|
||||
void CXWaylandSurface::close() {
|
||||
xcb_client_message_data_t msg = {0};
|
||||
msg.data32[0] = HYPRATOMS["WM_DELETE_WINDOW"];
|
||||
msg.data32[1] = XCB_CURRENT_TIME;
|
||||
g_pXWayland->pWM->sendWMMessage(self.lock(), &msg, XCB_EVENT_MASK_NO_EVENT);
|
||||
}
|
||||
|
||||
void CXWaylandSurface::setWithdrawn(bool withdrawn_) {
|
||||
withdrawn = withdrawn_;
|
||||
std::vector<uint32_t> props = {XCB_ICCCM_WM_STATE_NORMAL, XCB_WINDOW_NONE};
|
||||
|
||||
if (withdrawn)
|
||||
props[0] = XCB_ICCCM_WM_STATE_WITHDRAWN;
|
||||
else if (minimized)
|
||||
props[0] = XCB_ICCCM_WM_STATE_ICONIC;
|
||||
else
|
||||
props[0] = XCB_ICCCM_WM_STATE_NORMAL;
|
||||
|
||||
xcb_change_property(g_pXWayland->pWM->connection, XCB_PROP_MODE_REPLACE, xID, HYPRATOMS["WM_STATE"], HYPRATOMS["WM_STATE"], 32, props.size(), props.data());
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CXWaylandSurface::CXWaylandSurface(uint32_t xID_, CBox geometry_, bool OR) : xID(xID_), geometry(geometry_), overrideRedirect(OR) {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::ensureListeners() {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::map() {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::unmap() {
|
||||
;
|
||||
}
|
||||
|
||||
bool CXWaylandSurface::wantsFocus() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::configure(const CBox& box) {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::activate(bool activate) {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::setFullscreen(bool fs) {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::setMinimized(bool mz) {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::restackToTop() {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::close() {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::considerMap() {
|
||||
;
|
||||
}
|
||||
|
||||
void CXWaylandSurface::setWithdrawn(bool withdrawn) {
|
||||
;
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue