Compare commits
7 Commits
d47ca9cf1a
...
89f11d1e24
| Author | SHA1 | Date | |
|---|---|---|---|
|
89f11d1e24
|
|||
|
ceb40b434d
|
|||
|
272139f34f
|
|||
|
583b1fa382
|
|||
|
612c2367ca
|
|||
|
88e589cc9e
|
|||
|
c609d15d77
|
@@ -848,7 +848,15 @@ backend_bar_window_t backend_create_bar_window(
|
|||||||
fatal("cannot create cairo context: %s", cairo_status_to_string(statue));
|
fatal("cannot create cairo context: %s", cairo_status_to_string(statue));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (enable_tray) tray_init(backend, window_id, width, height);
|
if (enable_tray) {
|
||||||
|
tray_host_window_t host_window = {
|
||||||
|
.window = window_id,
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
.bg_pixel = bg_pixel,
|
||||||
|
};
|
||||||
|
tray_init(backend, host_window);
|
||||||
|
}
|
||||||
|
|
||||||
return (backend_bar_window_t){
|
return (backend_bar_window_t){
|
||||||
.window_id = window_id,
|
.window_id = window_id,
|
||||||
|
|||||||
@@ -190,6 +190,8 @@ static bool handle_map_request(
|
|||||||
event_t *event,
|
event_t *event,
|
||||||
const xcb_map_request_event_t *xcb_event
|
const xcb_map_request_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
|
if (tray_handle_map_request(backend, xcb_event)) return false;
|
||||||
|
|
||||||
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
||||||
return populate_window_event(
|
return populate_window_event(
|
||||||
backend,
|
backend,
|
||||||
@@ -203,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)) {
|
||||||
@@ -219,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;
|
||||||
@@ -231,6 +237,8 @@ static bool handle_configure_request(
|
|||||||
event_t *event,
|
event_t *event,
|
||||||
const xcb_configure_request_event_t *xcb_event
|
const xcb_configure_request_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
|
if (tray_handle_configure_request(backend, xcb_event)) return false;
|
||||||
|
|
||||||
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
||||||
auto data = &event->as.configure_request;
|
auto data = &event->as.configure_request;
|
||||||
data->window = xcb_event->window;
|
data->window = xcb_event->window;
|
||||||
@@ -342,6 +350,8 @@ static bool handle_property_notify(
|
|||||||
event_t *event,
|
event_t *event,
|
||||||
const xcb_property_notify_event_t *xcb_event
|
const xcb_property_notify_event_t *xcb_event
|
||||||
) {
|
) {
|
||||||
|
if (tray_handle_property_notify(backend, xcb_event)) return false;
|
||||||
|
|
||||||
auto window_id = xcb_event->window;
|
auto window_id = xcb_event->window;
|
||||||
if (
|
if (
|
||||||
xcb_event->atom == backend->atoms.WM_NAME ||
|
xcb_event->atom == backend->atoms.WM_NAME ||
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ static constexpr auto XEMBED_VERSION = 0;
|
|||||||
|
|
||||||
typedef struct tray_icon_t {
|
typedef struct tray_icon_t {
|
||||||
xcb_window_t window;
|
xcb_window_t window;
|
||||||
uint16_t natural_width;
|
int32_t natural_width;
|
||||||
uint16_t natural_height;
|
int32_t natural_height;
|
||||||
} tray_icon_t;
|
} tray_icon_t;
|
||||||
|
|
||||||
typedef struct tray_host_t {
|
typedef struct tray_host_t {
|
||||||
@@ -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,80 @@ 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) {
|
||||||
|
auto target_size = MAX(tray->icon_size, (int32_t)1);
|
||||||
|
auto natural_width = tray->icons[index].natural_width;
|
||||||
|
auto natural_height = tray->icons[index].natural_height;
|
||||||
|
|
||||||
|
if (natural_width == 0) natural_width = target_size;
|
||||||
|
if (natural_height == 0) natural_height = target_size;
|
||||||
|
|
||||||
|
double width_scale = (double)target_size / (double)natural_width;
|
||||||
|
double height_scale = (double)target_size / (double)natural_height;
|
||||||
|
auto scale = MIN(width_scale, height_scale);
|
||||||
|
zdwm_size_t size = {
|
||||||
|
.width = (int32_t)(natural_width * scale),
|
||||||
|
.height = (int32_t)(natural_height * scale),
|
||||||
|
};
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tray_layout_icons(backend_t *backend, int32_t start_x) {
|
||||||
|
auto tray = get_tray_host(backend);
|
||||||
|
if (!tray || !tray->initialized) return;
|
||||||
|
if (tray->container == XCB_WINDOW_NONE) return;
|
||||||
|
|
||||||
|
auto conn = backend->conn;
|
||||||
|
if (tray->icon_count == 0) {
|
||||||
|
xcb_unmap_window(conn, tray->container);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto height = tray->icon_size;
|
||||||
|
auto width = height * (int32_t)tray->icon_count;
|
||||||
|
xcb_configure_window_value_list_t value_list = {
|
||||||
|
.x = start_x,
|
||||||
|
.y = 0,
|
||||||
|
.width = (uint32_t)width,
|
||||||
|
.height = (uint32_t)height,
|
||||||
|
};
|
||||||
|
uint16_t value_mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y |
|
||||||
|
XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
|
||||||
|
xcb_configure_window_aux(conn, tray->container, value_mask, &value_list);
|
||||||
|
xcb_map_window(conn, tray->container);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < tray->icon_count; ++i) {
|
||||||
|
auto window = tray->icons[i].window;
|
||||||
|
auto icon_size = tray_get_icon_size(tray, i);
|
||||||
|
value_mask |= XCB_CONFIG_WINDOW_BORDER_WIDTH;
|
||||||
|
auto offset_x = height * (int32_t)i;
|
||||||
|
value_list = (xcb_configure_window_value_list_t){
|
||||||
|
.x = offset_x + (icon_size.width - height) / 2,
|
||||||
|
.y = (icon_size.height - height) / 2,
|
||||||
|
.width = icon_size.width,
|
||||||
|
.height = icon_size.height,
|
||||||
|
.border_width = 0,
|
||||||
|
};
|
||||||
|
xcb_configure_window_aux(conn, window, value_mask, &value_list);
|
||||||
|
xcb_map_window(conn, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static window_id_t tray_host_window(void *handle) {
|
static window_id_t tray_host_window(void *handle) {
|
||||||
auto tray = get_tray_host(handle);
|
auto tray = get_tray_host(handle);
|
||||||
if (!tray) return ZDWM_WINDOW_ID_INVALID;
|
if (!tray) return ZDWM_WINDOW_ID_INVALID;
|
||||||
@@ -115,10 +197,7 @@ static void tray_place(void *handle, int32_t x) {
|
|||||||
auto tray = get_tray_host(handle);
|
auto tray = get_tray_host(handle);
|
||||||
if (!tray) return;
|
if (!tray) return;
|
||||||
|
|
||||||
auto conn = ((backend_t *)handle)->conn;
|
tray_layout_icons((backend_t *)handle, x);
|
||||||
uint16_t value_mask = XCB_CONFIG_WINDOW_X;
|
|
||||||
xcb_configure_window_value_list_t value_list = {.x = x};
|
|
||||||
xcb_configure_window_aux(conn, tray->container, value_mask, &value_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -159,12 +238,6 @@ static bool tray_intern_selection_atom(tray_host_t *tray, backend_t *backend) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct tray_host_window_t {
|
|
||||||
xcb_window_t window;
|
|
||||||
int32_t width;
|
|
||||||
int32_t height;
|
|
||||||
} tray_host_window_t;
|
|
||||||
|
|
||||||
static bool tray_create_container_window(
|
static bool tray_create_container_window(
|
||||||
tray_host_t *tray,
|
tray_host_t *tray,
|
||||||
backend_t *backend,
|
backend_t *backend,
|
||||||
@@ -172,15 +245,31 @@ static bool tray_create_container_window(
|
|||||||
) {
|
) {
|
||||||
auto conn = backend->conn;
|
auto conn = backend->conn;
|
||||||
auto window_id = xcb_generate_id(conn);
|
auto window_id = xcb_generate_id(conn);
|
||||||
|
auto depth = backend->screen->root_depth;
|
||||||
|
auto visual_id = backend->screen->root_visual;
|
||||||
|
|
||||||
|
static xcb_colormap_t colormap = XCB_NONE;
|
||||||
|
if (colormap == XCB_NONE) {
|
||||||
|
colormap = xcb_generate_id(conn);
|
||||||
|
auto root = backend->screen->root;
|
||||||
|
uint8_t alloc = XCB_COLORMAP_ALLOC_NONE;
|
||||||
|
xcb_create_colormap(conn, alloc, colormap, root, visual_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t value_mask = XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL |
|
||||||
|
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK |
|
||||||
|
XCB_CW_COLORMAP;
|
||||||
xcb_create_window_value_list_t value_list = {
|
xcb_create_window_value_list_t value_list = {
|
||||||
|
.background_pixel = host_window.bg_pixel,
|
||||||
|
.border_pixel = 0,
|
||||||
.override_redirect = true,
|
.override_redirect = true,
|
||||||
.event_mask =
|
.event_mask =
|
||||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY
|
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_STRUCTURE_NOTIFY,
|
||||||
|
.colormap = colormap,
|
||||||
};
|
};
|
||||||
auto cookie = xcb_create_window_aux_checked(
|
auto cookie = xcb_create_window_aux_checked(
|
||||||
conn,
|
conn,
|
||||||
XCB_COPY_FROM_PARENT,
|
depth,
|
||||||
window_id,
|
window_id,
|
||||||
host_window.window,
|
host_window.window,
|
||||||
(int16_t)host_window.width,
|
(int16_t)host_window.width,
|
||||||
@@ -189,8 +278,8 @@ static bool tray_create_container_window(
|
|||||||
(uint16_t)MAX(1, host_window.height),
|
(uint16_t)MAX(1, host_window.height),
|
||||||
0,
|
0,
|
||||||
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||||
XCB_COPY_FROM_PARENT,
|
visual_id,
|
||||||
XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK,
|
value_mask,
|
||||||
&value_list
|
&value_list
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -265,12 +354,7 @@ static void tray_broadcast_manager(tray_host_t *tray, backend_t *backend) {
|
|||||||
xcb_send_event(conn, false, root, event_mask, (char *)&event);
|
xcb_send_event(conn, false, root, event_mask, (char *)&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tray_init(
|
void tray_init(backend_t *backend, tray_host_window_t host_window) {
|
||||||
backend_t *backend,
|
|
||||||
xcb_window_t host_window,
|
|
||||||
int32_t host_width,
|
|
||||||
int32_t host_height
|
|
||||||
) {
|
|
||||||
auto tray = get_tray_host(backend);
|
auto tray = get_tray_host(backend);
|
||||||
if (!tray) {
|
if (!tray) {
|
||||||
tray = p_new(tray_host_t, 1);
|
tray = p_new(tray_host_t, 1);
|
||||||
@@ -281,12 +365,7 @@ void tray_init(
|
|||||||
|
|
||||||
if (!tray_intern_selection_atom(tray, backend)) return;
|
if (!tray_intern_selection_atom(tray, backend)) return;
|
||||||
|
|
||||||
tray_host_window_t host_window_params = {
|
if (!tray_create_container_window(tray, backend, host_window)) return;
|
||||||
.window = host_window,
|
|
||||||
.width = host_width,
|
|
||||||
.height = host_height
|
|
||||||
};
|
|
||||||
if (!tray_create_container_window(tray, backend, host_window_params)) return;
|
|
||||||
if (!tray_take_selection_owner(tray, backend)) {
|
if (!tray_take_selection_owner(tray, backend)) {
|
||||||
tray_cleanup(backend);
|
tray_cleanup(backend);
|
||||||
return;
|
return;
|
||||||
@@ -294,8 +373,11 @@ void tray_init(
|
|||||||
|
|
||||||
tray->enabled = true;
|
tray->enabled = true;
|
||||||
tray->initialized = true;
|
tray->initialized = true;
|
||||||
|
tray->host_window = host_window.window;
|
||||||
|
tray->icon_size = host_window.height;
|
||||||
|
|
||||||
tray_broadcast_manager(tray, backend);
|
tray_broadcast_manager(tray, backend);
|
||||||
|
tray_layout_icons(backend, host_window.width);
|
||||||
xcb_flush(backend->conn);
|
xcb_flush(backend->conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +465,7 @@ static void tray_add_icon(backend_t *backend, xcb_window_t window) {
|
|||||||
*icon = (tray_icon_t){
|
*icon = (tray_icon_t){
|
||||||
.window = window,
|
.window = window,
|
||||||
.natural_width = geometry.width,
|
.natural_width = geometry.width,
|
||||||
.natural_height = geometry.height
|
.natural_height = geometry.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto conn = backend->conn;
|
auto conn = backend->conn;
|
||||||
@@ -428,3 +510,97 @@ bool tray_handle_client_message(
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tray_handle_configure_request(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_configure_request_event_t *ev
|
||||||
|
) {
|
||||||
|
auto tray = get_tray_host(backend);
|
||||||
|
if (!tray || !tray->initialized) return false;
|
||||||
|
|
||||||
|
if (ev->window == tray->container) {
|
||||||
|
tray_dispatch_callback(tray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto icon = tray_get_icon(tray, ev->window);
|
||||||
|
if (!icon) return false;
|
||||||
|
|
||||||
|
if ((ev->value_mask & XCB_CONFIG_WINDOW_WIDTH) && ev->width > 0) {
|
||||||
|
icon->natural_width = (int32_t)ev->width;
|
||||||
|
}
|
||||||
|
if ((ev->value_mask & XCB_CONFIG_WINDOW_HEIGHT) && ev->height > 0) {
|
||||||
|
icon->natural_height = (int32_t)ev->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
tray_dispatch_callback(tray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tray_handle_map_request(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_map_request_event_t *ev
|
||||||
|
) {
|
||||||
|
auto tray = get_tray_host(backend);
|
||||||
|
if (!tray || !tray->initialized) return false;
|
||||||
|
|
||||||
|
auto conn = backend->conn;
|
||||||
|
if (ev->window == tray->container) {
|
||||||
|
tray_dispatch_callback(tray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto icon = tray_get_icon(tray, ev->window);
|
||||||
|
if (!icon && ev->parent != tray->container) return false;
|
||||||
|
|
||||||
|
xcb_map_window(conn, ev->window);
|
||||||
|
xcb_flush(conn);
|
||||||
|
|
||||||
|
tray_dispatch_callback(tray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tray_handle_property_notify(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_property_notify_event_t *ev
|
||||||
|
) {
|
||||||
|
auto tray = get_tray_host(backend);
|
||||||
|
if (!tray || !tray->initialized) return false;
|
||||||
|
|
||||||
|
if (ev->window == XCB_WINDOW_NONE) return false;
|
||||||
|
if (ev->window == tray->container) return true;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,16 +9,37 @@ extern const tray_api_t tray_api;
|
|||||||
|
|
||||||
typedef struct backend_t backend_t;
|
typedef struct backend_t backend_t;
|
||||||
|
|
||||||
/* TODO: 添加窗口背景色 */
|
typedef struct tray_host_window_t {
|
||||||
void tray_init(
|
xcb_window_t window;
|
||||||
backend_t *backend,
|
int32_t width;
|
||||||
xcb_window_t host_window,
|
int32_t height;
|
||||||
int32_t host_width,
|
uint32_t bg_pixel;
|
||||||
int32_t host_height
|
} tray_host_window_t;
|
||||||
);
|
|
||||||
|
void tray_init(backend_t *backend, tray_host_window_t host_window);
|
||||||
void tray_cleanup(backend_t *backend);
|
void tray_cleanup(backend_t *backend);
|
||||||
|
|
||||||
bool tray_handle_client_message(
|
bool tray_handle_client_message(
|
||||||
backend_t *backend,
|
backend_t *backend,
|
||||||
const xcb_client_message_event_t *ev
|
const xcb_client_message_event_t *ev
|
||||||
);
|
);
|
||||||
|
bool tray_handle_configure_request(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_configure_request_event_t *ev
|
||||||
|
);
|
||||||
|
bool tray_handle_map_request(
|
||||||
|
backend_t *backend,
|
||||||
|
const xcb_map_request_event_t *ev
|
||||||
|
);
|
||||||
|
bool tray_handle_property_notify(
|
||||||
|
backend_t *backend,
|
||||||
|
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