feat(tray): 拦截托盘图标的 unmap/destroy 事件并移除图标
This commit is contained in:
@@ -205,6 +205,8 @@ static bool handle_unmap_notify(
|
|||||||
event_t *event,
|
event_t *event,
|
||||||
const xcb_unmap_notify_event_t *xcb_event
|
const xcb_unmap_notify_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
|
if (tray_handle_unmap_notify(backend, xcb_event)) return false;
|
||||||
|
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
event->as.window_remove.window = xcb_event->window;
|
event->as.window_remove.window = xcb_event->window;
|
||||||
if (XCB_EVENT_SENT(xcb_event)) {
|
if (XCB_EVENT_SENT(xcb_event)) {
|
||||||
@@ -221,6 +223,8 @@ static bool handle_destroy_notify(
|
|||||||
event_t *event,
|
event_t *event,
|
||||||
const xcb_destroy_notify_event_t *xcb_event
|
const xcb_destroy_notify_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
|
if (tray_handle_destroy_notify(backend, xcb_event)) return false;
|
||||||
|
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
event->as.window_remove.window = xcb_event->window;
|
event->as.window_remove.window = xcb_event->window;
|
||||||
event->as.window_remove.reason = ZDWM_WINDOW_REMOVE_DESTROY;
|
event->as.window_remove.reason = ZDWM_WINDOW_REMOVE_DESTROY;
|
||||||
|
|||||||
@@ -62,6 +62,14 @@ static tray_host_t *get_tray_host(void *handle) {
|
|||||||
return tray;
|
return tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t tray_find_icon(tray_host_t *tray, xcb_window_t window) {
|
||||||
|
for (size_t i = 0; i < tray->icon_count; ++i) {
|
||||||
|
if (tray->icons[i].window == window) return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
static tray_icon_t *tray_get_icon(tray_host_t *tray, xcb_window_t window) {
|
static tray_icon_t *tray_get_icon(tray_host_t *tray, xcb_window_t window) {
|
||||||
for (size_t i = 0; i < tray->icon_count; ++i) {
|
for (size_t i = 0; i < tray->icon_count; ++i) {
|
||||||
auto icon = &tray->icons[i];
|
auto icon = &tray->icons[i];
|
||||||
@@ -92,6 +100,21 @@ static void tray_release_icon_window(backend_t *backend, tray_icon_t *icon) {
|
|||||||
xcb_reparent_window(conn, window, root, 0, 0);
|
xcb_reparent_window(conn, window, root, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tray_remove_icon_by_index(
|
||||||
|
backend_t *backend,
|
||||||
|
size_t index,
|
||||||
|
bool release_window
|
||||||
|
) {
|
||||||
|
auto tray = backend->tray;
|
||||||
|
if (index >= tray->icon_count) return;
|
||||||
|
|
||||||
|
auto icon = &tray->icons[index];
|
||||||
|
if (release_window) tray_release_icon_window(backend, icon);
|
||||||
|
|
||||||
|
array_erase(tray->icons, tray->icon_count, index);
|
||||||
|
tray_dispatch_callback(tray);
|
||||||
|
}
|
||||||
|
|
||||||
static zdwm_size_t tray_get_icon_size(tray_host_t *tray, size_t index) {
|
static zdwm_size_t tray_get_icon_size(tray_host_t *tray, size_t index) {
|
||||||
auto target_size = MAX(tray->icon_size, (int32_t)1);
|
auto target_size = MAX(tray->icon_size, (int32_t)1);
|
||||||
auto natural_width = tray->icons[index].natural_width;
|
auto natural_width = tray->icons[index].natural_width;
|
||||||
@@ -548,3 +571,36 @@ bool tray_handle_property_notify(
|
|||||||
if (ev->window == tray->container) return true;
|
if (ev->window == tray->container) return true;
|
||||||
return tray_get_icon(tray, ev->window) != nullptr;
|
return tray_get_icon(tray, ev->window) != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tray_handle_unmap_notify(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_unmap_notify_event_t *ev
|
||||||
|
) {
|
||||||
|
auto tray = get_tray_host(backend);
|
||||||
|
if (!tray || !tray->initialized) return false;
|
||||||
|
|
||||||
|
auto index = tray_find_icon(tray, ev->window);
|
||||||
|
if (index == SIZE_MAX) return ev->window == tray->container;
|
||||||
|
|
||||||
|
tray_remove_icon_by_index(backend, index, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tray_handle_destroy_notify(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_destroy_notify_event_t *ev
|
||||||
|
) {
|
||||||
|
auto tray = get_tray_host(backend);
|
||||||
|
if (!tray || !tray->initialized) return false;
|
||||||
|
|
||||||
|
if (ev->window == tray->container) {
|
||||||
|
tray_cleanup(backend);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto index = tray_find_icon(tray, ev->window);
|
||||||
|
if (index == SIZE_MAX) return false;
|
||||||
|
|
||||||
|
tray_remove_icon_by_index(backend, index, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -34,3 +34,11 @@ bool tray_handle_property_notify(
|
|||||||
backend_t *backend,
|
backend_t *backend,
|
||||||
const xcb_property_notify_event_t *ev
|
const xcb_property_notify_event_t *ev
|
||||||
);
|
);
|
||||||
|
bool tray_handle_unmap_notify(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_unmap_notify_event_t *ev
|
||||||
|
);
|
||||||
|
bool tray_handle_destroy_notify(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_destroy_notify_event_t *ev
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user