Compare commits
4 Commits
a89613d37d
...
0f8c35ae6c
| Author | SHA1 | Date | |
|---|---|---|---|
|
0f8c35ae6c
|
|||
|
5353e4c677
|
|||
|
9728fad871
|
|||
|
ab961d6d79
|
@@ -13,10 +13,47 @@
|
|||||||
|
|
||||||
#include "backend/output_utils.h"
|
#include "backend/output_utils.h"
|
||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
|
#include "base/macros.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "internal.h" /* IWYU pragma: keep */
|
#include "internal.h" /* IWYU pragma: keep */
|
||||||
|
|
||||||
|
typedef struct atom_item_t {
|
||||||
|
const char *name;
|
||||||
|
size_t len;
|
||||||
|
xcb_atom_t *atom;
|
||||||
|
} atom_item_t;
|
||||||
|
|
||||||
|
static void atoms_init(backend_t *backend) {
|
||||||
|
xcb_connection_t *conn = backend->conn;
|
||||||
|
atoms_t *atoms = &backend->atoms;
|
||||||
|
|
||||||
|
atom_item_t atom_list[] = {
|
||||||
|
{"COMPOUND_TEXT", sizeof("COMPOUND_TEXT") - 1, &atoms->COMPOUND_TEXT},
|
||||||
|
{"UTF8_STRING", sizeof("UTF8_STRING") - 1, &atoms->UTF8_STRING},
|
||||||
|
|
||||||
|
{"WM_WINDOW_ROLE", sizeof("WM_WINDOW_ROLE") - 1, &atoms->WM_WINDOW_ROLE},
|
||||||
|
{"WM_NAME", sizeof("WM_NAME") - 1, &atoms->WM_NAME},
|
||||||
|
{"_NET_WM_NAME", sizeof("_NET_WM_NAME") - 1, &atoms->_NET_WM_NAME},
|
||||||
|
};
|
||||||
|
|
||||||
|
xcb_intern_atom_cookie_t cookies[countof(atom_list)];
|
||||||
|
for (size_t i = 0; i < countof(atom_list); ++i) {
|
||||||
|
const atom_item_t *atom = &atom_list[i];
|
||||||
|
cookies[i] = xcb_intern_atom_unchecked(conn, false, atom->len, atom->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_intern_atom_reply_t *reply = nullptr;
|
||||||
|
for (size_t i = 0; i < countof(atom_list); ++i) {
|
||||||
|
reply = xcb_intern_atom_reply(conn, cookies[i], nullptr);
|
||||||
|
if (!reply) continue;
|
||||||
|
|
||||||
|
atom_item_t *atom = &atom_list[i];
|
||||||
|
*atom->atom = reply->atom;
|
||||||
|
p_delete(&reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
backend_t *backend_create(const char *display_name) {
|
backend_t *backend_create(const char *display_name) {
|
||||||
int screen_num = 0;
|
int screen_num = 0;
|
||||||
xcb_connection_t *conn = xcb_connect(display_name, &screen_num);
|
xcb_connection_t *conn = xcb_connect(display_name, &screen_num);
|
||||||
@@ -63,6 +100,8 @@ backend_t *backend_create(const char *display_name) {
|
|||||||
backend->have_xfixes = false;
|
backend->have_xfixes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atoms_init(backend);
|
||||||
|
|
||||||
return backend;
|
return backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,32 @@
|
|||||||
|
#include "core/event.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_event.h>
|
#include <xcb/xcb_event.h>
|
||||||
#include <xcb/xproto.h>
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "backend/x11/window.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
#include "core/backend.h"
|
#include "core/backend.h"
|
||||||
|
#include "core/window.h"
|
||||||
#include "internal.h" /* IWYU pragma: keep */
|
#include "internal.h" /* IWYU pragma: keep */
|
||||||
|
|
||||||
static bool handle_map_request(event_t *event,
|
static bool handle_map_request(backend_t *backend, event_t *event,
|
||||||
const xcb_map_request_event_t *xcb_event) {
|
const xcb_map_request_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
p_clear(event, 1);
|
||||||
|
xcb_window_t window = xcb_event->window;
|
||||||
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
event->type = ZDWM_EVENT_WINDOW_MAP_REQUEST;
|
||||||
|
event->data.window_map_request.window = window;
|
||||||
|
window_metadata_t *metadata = &event->data.window_map_request.metadata;
|
||||||
|
metadata->role = window_get_role(backend, window);
|
||||||
|
metadata->title = window_get_title(backend, window);
|
||||||
|
window_get_class(backend, window, &metadata->class_name,
|
||||||
|
&metadata->instance_name);
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool handle_unmap_notify(event_t *event,
|
static bool handle_unmap_notify(backend_t *backend, event_t *event,
|
||||||
const xcb_unmap_notify_event_t *xcb_event) {
|
const xcb_unmap_notify_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
p_clear(event, 1);
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
@@ -23,7 +34,7 @@ static bool handle_unmap_notify(event_t *event,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool handle_destroy_notify(event_t *event,
|
static bool handle_destroy_notify(backend_t *backend, event_t *event,
|
||||||
const xcb_destroy_notify_event_t *xcb_event) {
|
const xcb_destroy_notify_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
p_clear(event, 1);
|
||||||
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
event->type = ZDWM_EVENT_WINDOW_REMOVE;
|
||||||
@@ -32,7 +43,8 @@ static bool handle_destroy_notify(event_t *event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool handle_configure_request(
|
static bool handle_configure_request(
|
||||||
event_t *event, const xcb_configure_request_event_t *xcb_event) {
|
backend_t *backend, event_t *event,
|
||||||
|
const xcb_configure_request_event_t *xcb_event) {
|
||||||
p_clear(event, 1);
|
p_clear(event, 1);
|
||||||
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
event->type = ZDWM_EVENT_CONFIGURE_REQUEST;
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
@@ -52,9 +64,9 @@ bool backend_next_event(backend_t *backend, event_t *event) {
|
|||||||
printf("xcb event type: %u\n", response_type);
|
printf("xcb event type: %u\n", response_type);
|
||||||
|
|
||||||
switch (response_type) {
|
switch (response_type) {
|
||||||
#define EVENT(type, handler) \
|
#define EVENT(type, handler) \
|
||||||
case type: \
|
case type: \
|
||||||
handled = handler(event, (void *)raw_event); \
|
handled = handler(backend, event, (void *)raw_event); \
|
||||||
break
|
break
|
||||||
|
|
||||||
EVENT(XCB_MAP_REQUEST, handle_map_request);
|
EVENT(XCB_MAP_REQUEST, handle_map_request);
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
#include "core/backend.h" /* IWYU pragma: keep */
|
#include "core/backend.h" /* IWYU pragma: keep */
|
||||||
|
|
||||||
|
typedef struct atoms_t {
|
||||||
|
xcb_atom_t COMPOUND_TEXT;
|
||||||
|
xcb_atom_t UTF8_STRING;
|
||||||
|
xcb_atom_t WM_WINDOW_ROLE;
|
||||||
|
xcb_atom_t WM_NAME;
|
||||||
|
xcb_atom_t _NET_WM_NAME;
|
||||||
|
} atoms_t;
|
||||||
|
|
||||||
struct backend_t {
|
struct backend_t {
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
xcb_screen_t *screen;
|
xcb_screen_t *screen;
|
||||||
int screenp;
|
int screenp;
|
||||||
bool have_xfixes;
|
bool have_xfixes;
|
||||||
|
|
||||||
|
atoms_t atoms;
|
||||||
};
|
};
|
||||||
|
|||||||
63
src/backend/x11/window.c
Normal file
63
src/backend/x11/window.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#include <xcb/xcb_icccm.h>
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "base/memory.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static char *window_get_text_property(backend_t *backend, xcb_window_t window,
|
||||||
|
xcb_atom_t property) {
|
||||||
|
xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(
|
||||||
|
backend->conn, false, window, property, XCB_ATOM_ANY, 0, UINT32_MAX);
|
||||||
|
xcb_get_property_reply_t *reply =
|
||||||
|
xcb_get_property_reply(backend->conn, cookie, nullptr);
|
||||||
|
if (!reply) return nullptr;
|
||||||
|
|
||||||
|
int length = xcb_get_property_value_length(reply);
|
||||||
|
char *value = (char *)xcb_get_property_value(reply);
|
||||||
|
|
||||||
|
char *text = nullptr;
|
||||||
|
if (length && reply->format == 8 &&
|
||||||
|
(reply->type == XCB_ATOM_STRING ||
|
||||||
|
reply->type == backend->atoms.UTF8_STRING ||
|
||||||
|
reply->type == backend->atoms.COMPOUND_TEXT)) {
|
||||||
|
text = p_strndup(value, (size_t)length);
|
||||||
|
}
|
||||||
|
|
||||||
|
p_delete(&reply);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *window_get_role(backend_t *backend, xcb_window_t window) {
|
||||||
|
xcb_atom_t property = backend->atoms.WM_WINDOW_ROLE;
|
||||||
|
return window_get_text_property(backend, window, property);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *window_get_title(backend_t *backend, xcb_window_t window) {
|
||||||
|
xcb_atom_t property = backend->atoms._NET_WM_NAME;
|
||||||
|
char *name = window_get_text_property(backend, window, property);
|
||||||
|
if (!name) {
|
||||||
|
property = backend->atoms.WM_NAME;
|
||||||
|
name = window_get_text_property(backend, window, property);
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_get_class(backend_t *backend, xcb_window_t window, char **class_out,
|
||||||
|
char **instance_out) {
|
||||||
|
xcb_icccm_get_wm_class_reply_t prop;
|
||||||
|
xcb_get_property_cookie_t cookie =
|
||||||
|
xcb_icccm_get_wm_class_unchecked(backend->conn, window);
|
||||||
|
if (!xcb_icccm_get_wm_class_reply(backend->conn, cookie, &prop, nullptr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (class_out) *class_out = p_strdup_nullable(prop.class_name);
|
||||||
|
if (instance_out) *instance_out = p_strdup_nullable(prop.instance_name);
|
||||||
|
|
||||||
|
xcb_icccm_get_wm_class_reply_wipe(&prop);
|
||||||
|
}
|
||||||
33
src/backend/x11/window.h
Normal file
33
src/backend/x11/window.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xcb/xproto.h>
|
||||||
|
|
||||||
|
#include "core/backend.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口的 role 属性
|
||||||
|
* @param backend 后端实例指针
|
||||||
|
* @param window 目标窗口
|
||||||
|
* @return 返回窗口的 role 属性字符串,调用者持有其内存并负责调用 free 释放
|
||||||
|
*/
|
||||||
|
char *window_get_role(backend_t *backend, xcb_window_t window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口标题
|
||||||
|
* @details 获取窗口的 _NET_WM_NAME/WM_NAME 属性作为其 title
|
||||||
|
* @param backend 后端实例指针
|
||||||
|
* @param window 目标窗口
|
||||||
|
* @return 返回窗口标题字符串,由调用者持有其内存并负责调用 free 释放
|
||||||
|
*/
|
||||||
|
char *window_get_title(backend_t *backend, xcb_window_t window);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取窗口的 class 和 instance 信息
|
||||||
|
* @param backend 后端实例指针
|
||||||
|
* @param window 目标窗口
|
||||||
|
* @param class_out class 信息返回指针,调用者持有其内存并负责调用 free 释放
|
||||||
|
* @param instance_out instance 信息返回指针,调用者持有其内存并负责调用 free
|
||||||
|
* 释放
|
||||||
|
*/
|
||||||
|
void window_get_class(backend_t *backend, xcb_window_t window, char **class_out,
|
||||||
|
char **instance_out);
|
||||||
@@ -18,12 +18,25 @@
|
|||||||
*(void **)__ptr = nullptr; \
|
*(void **)__ptr = nullptr; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define p_take(dst_p, src_p) \
|
||||||
|
do { \
|
||||||
|
p_delete(dst_p); \
|
||||||
|
*(dst_p) = *(src_p); \
|
||||||
|
*(src_p) = nullptr; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
static inline char *p_strdup(const char *text) {
|
static inline char *p_strdup(const char *text) {
|
||||||
char *r = strdup(text);
|
char *r = strdup(text);
|
||||||
if (!r) abort();
|
if (!r) abort();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char *p_strndup(const char *text, size_t n) {
|
||||||
|
char *r = strndup(text, n);
|
||||||
|
if (!r) abort();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static inline char *p_strdup_nullable(const char *text) {
|
static inline char *p_strdup_nullable(const char *text) {
|
||||||
if (!text) return nullptr;
|
if (!text) return nullptr;
|
||||||
return p_strdup(text);
|
return p_strdup(text);
|
||||||
|
|||||||
@@ -82,8 +82,9 @@ typedef struct window_remove_event_t {
|
|||||||
typedef enum window_metadata_change_flags_t {
|
typedef enum window_metadata_change_flags_t {
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_TITLE = 1u << 0,
|
ZDWM_WINDOW_METADATA_CHANGE_TITLE = 1u << 0,
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_APP_ID = 1u << 1,
|
ZDWM_WINDOW_METADATA_CHANGE_APP_ID = 1u << 1,
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_CLASS = 1u << 2,
|
ZDWM_WINDOW_METADATA_CHANGE_ROLE = 1u << 2,
|
||||||
ZDWM_WINDOW_METADATA_CHANGE_INSTANCE = 1u << 3,
|
ZDWM_WINDOW_METADATA_CHANGE_CLASS = 1u << 3,
|
||||||
|
ZDWM_WINDOW_METADATA_CHANGE_INSTANCE = 1u << 4,
|
||||||
} window_metadata_change_flags_t;
|
} window_metadata_change_flags_t;
|
||||||
|
|
||||||
typedef struct window_metadata_change_event_t {
|
typedef struct window_metadata_change_event_t {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "base/array.h"
|
#include "base/array.h"
|
||||||
#include "base/log.h"
|
#include "base/log.h"
|
||||||
#include "base/memory.h"
|
#include "base/memory.h"
|
||||||
|
#include "core/event.h"
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/wm_desc.h"
|
||||||
@@ -66,6 +67,7 @@ void state_cleanup(state_t *state) {
|
|||||||
window_t *window = &state->windows[i];
|
window_t *window = &state->windows[i];
|
||||||
p_delete(&window->title);
|
p_delete(&window->title);
|
||||||
p_delete(&window->app_id);
|
p_delete(&window->app_id);
|
||||||
|
p_delete(&window->role);
|
||||||
p_delete(&window->class_name);
|
p_delete(&window->class_name);
|
||||||
p_delete(&window->instance_name);
|
p_delete(&window->instance_name);
|
||||||
}
|
}
|
||||||
@@ -286,6 +288,7 @@ const window_t *state_window_add(state_t *state, const window_info_t *info) {
|
|||||||
state_window_set_frame_rect(state, id, info->frame_rect);
|
state_window_set_frame_rect(state, id, info->frame_rect);
|
||||||
state_window_set_title(state, id, info->title);
|
state_window_set_title(state, id, info->title);
|
||||||
state_window_set_app_id(state, id, info->app_id);
|
state_window_set_app_id(state, id, info->app_id);
|
||||||
|
state_window_set_role(state, id, info->role);
|
||||||
state_window_set_class(state, id, info->class_name);
|
state_window_set_class(state, id, info->class_name);
|
||||||
state_window_set_instance(state, id, info->instance_name);
|
state_window_set_instance(state, id, info->instance_name);
|
||||||
state_window_set_skip_taskbar(state, id, info->skip_taskbar);
|
state_window_set_skip_taskbar(state, id, info->skip_taskbar);
|
||||||
@@ -324,6 +327,7 @@ void state_window_remove(state_t *state, window_id_t id) {
|
|||||||
workspace_id_t workspace_id = window->workspace_id;
|
workspace_id_t workspace_id = window->workspace_id;
|
||||||
p_delete(&window->title);
|
p_delete(&window->title);
|
||||||
p_delete(&window->app_id);
|
p_delete(&window->app_id);
|
||||||
|
p_delete(&window->role);
|
||||||
p_delete(&window->class_name);
|
p_delete(&window->class_name);
|
||||||
p_delete(&window->instance_name);
|
p_delete(&window->instance_name);
|
||||||
|
|
||||||
@@ -432,6 +436,31 @@ void state_window_set_frame_rect(state_t *state, window_id_t window_id,
|
|||||||
window->frame_rect = frame_rect;
|
window->frame_rect = frame_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool state_window_take_metadata(state_t *state, window_id_t window_id,
|
||||||
|
window_metadata_t *metadata,
|
||||||
|
uint32_t changed_fields) {
|
||||||
|
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||||
|
if (!window) return false;
|
||||||
|
|
||||||
|
if (changed_fields & ZDWM_WINDOW_METADATA_CHANGE_TITLE) {
|
||||||
|
p_take(&window->title, &metadata->title);
|
||||||
|
}
|
||||||
|
if (changed_fields & ZDWM_WINDOW_METADATA_CHANGE_APP_ID) {
|
||||||
|
p_take(&window->app_id, &metadata->app_id);
|
||||||
|
}
|
||||||
|
if (changed_fields & ZDWM_WINDOW_METADATA_CHANGE_ROLE) {
|
||||||
|
p_take(&window->role, &metadata->role);
|
||||||
|
}
|
||||||
|
if (changed_fields & ZDWM_WINDOW_METADATA_CHANGE_CLASS) {
|
||||||
|
p_take(&window->class_name, &metadata->class_name);
|
||||||
|
}
|
||||||
|
if (changed_fields & ZDWM_WINDOW_METADATA_CHANGE_INSTANCE) {
|
||||||
|
p_take(&window->instance_name, &metadata->instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool state_window_set_title(state_t *state, window_id_t window_id,
|
bool state_window_set_title(state_t *state, window_id_t window_id,
|
||||||
const char *title) {
|
const char *title) {
|
||||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||||
@@ -453,6 +482,18 @@ bool state_window_set_app_id(state_t *state, window_id_t window_id,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool state_window_set_role(state_t *state, window_id_t window_id,
|
||||||
|
const char *role) {
|
||||||
|
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||||
|
if (!window) return false;
|
||||||
|
|
||||||
|
p_delete(&window->role);
|
||||||
|
window->role = p_strdup_nullable(role);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool state_window_set_class(state_t *state, window_id_t window_id,
|
bool state_window_set_class(state_t *state, window_id_t window_id,
|
||||||
const char *class_name) {
|
const char *class_name) {
|
||||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||||
@@ -463,6 +504,7 @@ bool state_window_set_class(state_t *state, window_id_t window_id,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool state_window_set_instance(state_t *state, window_id_t window_id,
|
bool state_window_set_instance(state_t *state, window_id_t window_id,
|
||||||
const char *instance_name) {
|
const char *instance_name) {
|
||||||
window_t *window = (window_t *)state_window_get(state, window_id);
|
window_t *window = (window_t *)state_window_get(state, window_id);
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "core/layer.h"
|
#include "core/layer.h"
|
||||||
#include "core/types.h"
|
#include "core/types.h"
|
||||||
|
#include "core/window.h"
|
||||||
#include "core/wm_desc.h"
|
#include "core/wm_desc.h"
|
||||||
|
|
||||||
/* 核心实体定义 */
|
/* 核心实体定义 */
|
||||||
@@ -24,10 +26,11 @@ typedef struct window_t {
|
|||||||
rect_t frame_rect; /* 当前外框矩形(由 layout 或 float_rect 解析) */
|
rect_t frame_rect; /* 当前外框矩形(由 layout 或 float_rect 解析) */
|
||||||
|
|
||||||
/* 元数据(核心算法不依赖,仅用于规则匹配和信息展示) */
|
/* 元数据(核心算法不依赖,仅用于规则匹配和信息展示) */
|
||||||
const char *title;
|
char *title;
|
||||||
const char *app_id;
|
char *app_id;
|
||||||
const char *class_name;
|
char *role;
|
||||||
const char *instance_name;
|
char *class_name;
|
||||||
|
char *instance_name;
|
||||||
|
|
||||||
bool skip_taskbar;
|
bool skip_taskbar;
|
||||||
} window_t;
|
} window_t;
|
||||||
@@ -166,10 +169,29 @@ void state_window_set_float_rect(state_t *state, window_id_t window_id,
|
|||||||
rect_t float_rect);
|
rect_t float_rect);
|
||||||
void state_window_set_frame_rect(state_t *state, window_id_t window_id,
|
void state_window_set_frame_rect(state_t *state, window_id_t window_id,
|
||||||
rect_t frame_rect);
|
rect_t frame_rect);
|
||||||
|
/**
|
||||||
|
* @brief 按字段掩码转移窗口元数据的所有权
|
||||||
|
* @param state 状态实例指针
|
||||||
|
* @param window_id 目标窗口 id
|
||||||
|
* @param metadata 元数据来源;成功时仅被转移字段会被置空
|
||||||
|
* @param changed_fields 需要转移的字段掩码
|
||||||
|
* @return 成功返回 true;若目标窗口不存在则返回 false
|
||||||
|
* @details
|
||||||
|
* 成功时,仅转移 changed_fields 指定的字段到目标 window,并将 metadata 中对应
|
||||||
|
* 字段置空;未置位字段保持在 metadata 中,所有权仍归调用方。
|
||||||
|
*
|
||||||
|
* 失败时,不接管 metadata 中任何字段的所有权,metadata 保持不变,仍由调用方负
|
||||||
|
* 责后续访问与释放。
|
||||||
|
*/
|
||||||
|
bool state_window_take_metadata(state_t *state, window_id_t window_id,
|
||||||
|
window_metadata_t *metadata,
|
||||||
|
uint32_t changed_fields);
|
||||||
bool state_window_set_title(state_t *state, window_id_t window_id,
|
bool state_window_set_title(state_t *state, window_id_t window_id,
|
||||||
const char *title);
|
const char *title);
|
||||||
bool state_window_set_app_id(state_t *state, window_id_t window_id,
|
bool state_window_set_app_id(state_t *state, window_id_t window_id,
|
||||||
const char *app_id);
|
const char *app_id);
|
||||||
|
bool state_window_set_role(state_t *state, window_id_t window_id,
|
||||||
|
const char *role);
|
||||||
bool state_window_set_class(state_t *state, window_id_t window_id,
|
bool state_window_set_class(state_t *state, window_id_t window_id,
|
||||||
const char *class_name);
|
const char *class_name);
|
||||||
bool state_window_set_instance(state_t *state, window_id_t window_id,
|
bool state_window_set_instance(state_t *state, window_id_t window_id,
|
||||||
|
|||||||
@@ -45,10 +45,11 @@ typedef struct window_props_t {
|
|||||||
} window_props_t;
|
} window_props_t;
|
||||||
|
|
||||||
typedef struct window_metadata_t {
|
typedef struct window_metadata_t {
|
||||||
const char *title;
|
char *title;
|
||||||
const char *app_id;
|
char *app_id;
|
||||||
const char *class_name;
|
char *role;
|
||||||
const char *instance_name;
|
char *class_name;
|
||||||
|
char *instance_name;
|
||||||
} window_metadata_t;
|
} window_metadata_t;
|
||||||
|
|
||||||
typedef struct window_geometry_t {
|
typedef struct window_geometry_t {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ typedef struct window_info_t {
|
|||||||
|
|
||||||
const char *title;
|
const char *title;
|
||||||
const char *app_id;
|
const char *app_id;
|
||||||
|
const char *role;
|
||||||
const char *class_name;
|
const char *class_name;
|
||||||
const char *instance_name;
|
const char *instance_name;
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ add_executable(${RUNTIME_CONFIG_TEST_APP_NAME}
|
|||||||
${SOURCE_DIR}/config/defaults.c
|
${SOURCE_DIR}/config/defaults.c
|
||||||
${SOURCE_DIR}/config/loader.c
|
${SOURCE_DIR}/config/loader.c
|
||||||
${SOURCE_DIR}/config/runtime_config.c
|
${SOURCE_DIR}/config/runtime_config.c
|
||||||
|
${SOURCE_DIR}/core/layer.c
|
||||||
${SOURCE_DIR}/core/layout.c
|
${SOURCE_DIR}/core/layout.c
|
||||||
${SOURCE_DIR}/core/runtime.c
|
${SOURCE_DIR}/core/runtime.c
|
||||||
${SOURCE_DIR}/core/state.c
|
${SOURCE_DIR}/core/state.c
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ add_executable(${TEST_APP_NAME}
|
|||||||
${SOURCE_DIR}/config/runtime_config.c
|
${SOURCE_DIR}/config/runtime_config.c
|
||||||
${SOURCE_DIR}/backend/x11/backend.c
|
${SOURCE_DIR}/backend/x11/backend.c
|
||||||
${SOURCE_DIR}/backend/x11/event.c
|
${SOURCE_DIR}/backend/x11/event.c
|
||||||
|
${SOURCE_DIR}/backend/x11/window.c
|
||||||
|
${SOURCE_DIR}/core/layer.c
|
||||||
${SOURCE_DIR}/core/layout.c
|
${SOURCE_DIR}/core/layout.c
|
||||||
${SOURCE_DIR}/core/runtime.c
|
${SOURCE_DIR}/core/runtime.c
|
||||||
${SOURCE_DIR}/core/state.c
|
${SOURCE_DIR}/core/state.c
|
||||||
|
|||||||
Reference in New Issue
Block a user