build: add -ldl linker flag, recursive source discovery, and API test targets to Makefile
This commit is contained in:
@@ -10,6 +10,11 @@
|
||||
#include "dwn.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Forward declarations for libcurl types */
|
||||
struct curl_slist;
|
||||
struct Curl_easy;
|
||||
typedef struct Curl_easy DWN_CURL;
|
||||
|
||||
typedef enum {
|
||||
AI_STATE_IDLE,
|
||||
AI_STATE_PENDING,
|
||||
@@ -24,6 +29,8 @@ typedef struct AIRequest {
|
||||
void (*callback)(struct AIRequest *req);
|
||||
void *user_data;
|
||||
struct AIRequest *next;
|
||||
struct curl_slist *headers; /* Stored for proper cleanup */
|
||||
struct Curl_easy *curl_handle; /* Stored for cancellation */
|
||||
} AIRequest;
|
||||
|
||||
typedef struct {
|
||||
@@ -74,6 +81,8 @@ typedef struct ExaRequest {
|
||||
void (*callback)(struct ExaRequest *req);
|
||||
void *user_data;
|
||||
struct ExaRequest *next;
|
||||
struct curl_slist *headers; /* Stored for proper cleanup */
|
||||
struct Curl_easy *curl_handle; /* Stored for cancellation */
|
||||
} ExaRequest;
|
||||
|
||||
bool exa_is_available(void);
|
||||
|
||||
@@ -55,6 +55,23 @@ typedef enum {
|
||||
EVENT_NOTIFICATION_SHOWN,
|
||||
EVENT_NOTIFICATION_CLOSED,
|
||||
|
||||
EVENT_FADE_SPEED_CHANGED,
|
||||
EVENT_FADE_INTENSITY_CHANGED,
|
||||
|
||||
EVENT_WINDOW_SNAPPED,
|
||||
EVENT_AUDIO_VOLUME_CHANGED,
|
||||
EVENT_AUDIO_MUTE_TOGGLED,
|
||||
EVENT_PANEL_VISIBILITY_CHANGED,
|
||||
EVENT_CONFIG_RELOADED,
|
||||
EVENT_AI_RESPONSE_RECEIVED,
|
||||
EVENT_EXA_SEARCH_COMPLETED,
|
||||
EVENT_NEWS_ARTICLE_CHANGED,
|
||||
EVENT_DEMO_STARTED,
|
||||
EVENT_DEMO_STOPPED,
|
||||
EVENT_DEMO_PHASE_CHANGED,
|
||||
EVENT_TUTORIAL_STARTED,
|
||||
EVENT_TUTORIAL_STOPPED,
|
||||
|
||||
EVENT_COUNT
|
||||
} ApiEventType;
|
||||
|
||||
@@ -104,4 +121,21 @@ void api_emit_show_desktop_toggled(bool shown);
|
||||
void api_emit_notification_shown(unsigned int id, const char *summary, const char *body);
|
||||
void api_emit_notification_closed(unsigned int id);
|
||||
|
||||
void api_emit_fade_speed_changed(float old_speed, float new_speed);
|
||||
void api_emit_fade_intensity_changed(float old_intensity, float new_intensity);
|
||||
|
||||
void api_emit_window_snapped(Window window, int horizontal, int vertical);
|
||||
void api_emit_audio_volume_changed(int old_volume, int new_volume);
|
||||
void api_emit_audio_mute_toggled(bool muted);
|
||||
void api_emit_panel_visibility_changed(const char *panel, bool visible);
|
||||
void api_emit_config_reloaded(void);
|
||||
void api_emit_ai_response_received(const char *prompt, const char *response, bool success);
|
||||
void api_emit_exa_search_completed(const char *query, int result_count, bool success);
|
||||
void api_emit_news_article_changed(int old_index, int new_index, const char *title);
|
||||
void api_emit_demo_started(void);
|
||||
void api_emit_demo_stopped(void);
|
||||
void api_emit_demo_phase_changed(int phase, const char *phase_name);
|
||||
void api_emit_tutorial_started(void);
|
||||
void api_emit_tutorial_stopped(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Backend Abstraction Interface
|
||||
*/
|
||||
|
||||
#ifndef BACKEND_INTERFACE_H
|
||||
#define BACKEND_INTERFACE_H
|
||||
|
||||
#include "core/wm_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Backend Capabilities
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_BACKEND_CAP_WINDOWS = (1 << 0),
|
||||
WM_BACKEND_CAP_COMPOSITING = (1 << 1),
|
||||
WM_BACKEND_CAP_TRANSPARENCY = (1 << 2),
|
||||
WM_BACKEND_CAP_ANIMATIONS = (1 << 3),
|
||||
WM_BACKEND_CAP_MULTI_MONITOR = (1 << 4),
|
||||
WM_BACKEND_CAP_INPUT_EVENTS = (1 << 5),
|
||||
WM_BACKEND_CAP_CLIPBOARD = (1 << 6),
|
||||
WM_BACKEND_CAP_DRAG_DROP = (1 << 7),
|
||||
WM_BACKEND_CAP_TOUCH = (1 << 8),
|
||||
WM_BACKEND_CAP_GESTURES = (1 << 9)
|
||||
} WmBackendCapabilities;
|
||||
|
||||
/*==============================================================================
|
||||
* Backend Information
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *version;
|
||||
const char *description;
|
||||
uint32_t capabilities;
|
||||
bool supports_multiple_instances;
|
||||
bool requires_compositor;
|
||||
} WmBackendInfo;
|
||||
|
||||
/*==============================================================================
|
||||
* Backend Event Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_BACKEND_EVENT_NONE,
|
||||
WM_BACKEND_EVENT_EXPOSE,
|
||||
WM_BACKEND_EVENT_CONFIGURE,
|
||||
WM_BACKEND_EVENT_MAP,
|
||||
WM_BACKEND_EVENT_UNMAP,
|
||||
WM_BACKEND_EVENT_DESTROY,
|
||||
WM_BACKEND_EVENT_FOCUS_IN,
|
||||
WM_BACKEND_EVENT_FOCUS_OUT,
|
||||
WM_BACKEND_EVENT_KEY_PRESS,
|
||||
WM_BACKEND_EVENT_KEY_RELEASE,
|
||||
WM_BACKEND_EVENT_BUTTON_PRESS,
|
||||
WM_BACKEND_EVENT_BUTTON_RELEASE,
|
||||
WM_BACKEND_EVENT_MOTION,
|
||||
WM_BACKEND_EVENT_ENTER,
|
||||
WM_BACKEND_EVENT_LEAVE,
|
||||
WM_BACKEND_EVENT_PROPERTY,
|
||||
WM_BACKEND_EVENT_CLIENT_MESSAGE,
|
||||
WM_BACKEND_EVENT_SELECTION,
|
||||
} WmBackendEventType;
|
||||
|
||||
typedef struct {
|
||||
WmBackendEventType type;
|
||||
WmWindowHandle window;
|
||||
WmTime timestamp;
|
||||
union {
|
||||
struct { int x, y, width, height; } configure;
|
||||
struct { int x, y; } point;
|
||||
struct { unsigned int keycode; unsigned int state; } key;
|
||||
struct { unsigned int button; int x, y; unsigned int state; } button;
|
||||
struct { const char *name; const void *data; size_t size; } property;
|
||||
} data;
|
||||
} WmBackendEvent;
|
||||
|
||||
/*==============================================================================
|
||||
* Backend Interface Definition
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct BackendInterface {
|
||||
/* Identification */
|
||||
const char *name;
|
||||
WmBackendInfo (*get_info)(void);
|
||||
|
||||
/* Lifecycle */
|
||||
bool (*init)(void *config);
|
||||
void (*shutdown)(void);
|
||||
bool (*is_initialized)(void);
|
||||
|
||||
/* Connection */
|
||||
bool (*connect)(void);
|
||||
void (*disconnect)(void);
|
||||
bool (*is_connected)(void);
|
||||
int (*get_file_descriptor)(void);
|
||||
void (*flush)(void);
|
||||
void (*sync)(void);
|
||||
|
||||
/* Screen/Display */
|
||||
void (*get_screen_dimensions)(int *width, int *height);
|
||||
int (*get_screen_count)(void);
|
||||
void (*get_screen_geometry)(int screen, WmRect *geometry);
|
||||
|
||||
/* Monitor Management */
|
||||
int (*get_monitor_count)(void);
|
||||
void (*get_monitor_geometry)(int monitor, WmRect *geometry);
|
||||
bool (*get_monitor_primary)(int monitor);
|
||||
const char* (*get_monitor_name)(int monitor);
|
||||
|
||||
/* Work Area */
|
||||
void (*get_work_area)(int monitor, WmRect *area);
|
||||
void (*set_work_area)(int monitor, const WmRect *area);
|
||||
|
||||
/* Window Management - Lifecycle */
|
||||
WmWindowHandle (*window_create)(const WmRect *geometry, uint32_t flags);
|
||||
void (*window_destroy)(WmWindowHandle window);
|
||||
WmWindowHandle (*window_create_frame)(WmWindowHandle parent, const WmRect *geometry);
|
||||
|
||||
/* Window Management - Geometry */
|
||||
void (*window_get_geometry)(WmWindowHandle window, WmRect *geometry);
|
||||
void (*window_set_geometry)(WmWindowHandle window, const WmRect *geometry);
|
||||
void (*window_move)(WmWindowHandle window, int x, int y);
|
||||
void (*window_resize)(WmWindowHandle window, int width, int height);
|
||||
void (*window_move_resize)(WmWindowHandle window, const WmRect *geometry);
|
||||
|
||||
/* Window Management - Visibility */
|
||||
void (*window_show)(WmWindowHandle window);
|
||||
void (*window_hide)(WmWindowHandle window);
|
||||
bool (*window_is_visible)(WmWindowHandle window);
|
||||
void (*window_map)(WmWindowHandle window);
|
||||
void (*window_unmap)(WmWindowHandle window);
|
||||
bool (*window_is_mapped)(WmWindowHandle window);
|
||||
|
||||
/* Window Management - Stacking */
|
||||
void (*window_raise)(WmWindowHandle window);
|
||||
void (*window_lower)(WmWindowHandle window);
|
||||
void (*window_raise_above)(WmWindowHandle window, WmWindowHandle above);
|
||||
void (*window_lower_below)(WmWindowHandle window, WmWindowHandle below);
|
||||
void (*window_set_stack_position)(WmWindowHandle window, int position);
|
||||
int (*window_get_stack_position)(WmWindowHandle window);
|
||||
|
||||
/* Window Management - Reparenting */
|
||||
void (*window_reparent)(WmWindowHandle window, WmWindowHandle parent, int x, int y);
|
||||
WmWindowHandle (*window_get_parent)(WmWindowHandle window);
|
||||
|
||||
/* Window Management - Focus */
|
||||
void (*window_focus)(WmWindowHandle window);
|
||||
void (*window_unfocus)(WmWindowHandle window);
|
||||
bool (*window_is_focused)(WmWindowHandle window);
|
||||
WmWindowHandle (*window_get_focused)(void);
|
||||
|
||||
/* Window Management - Decoration */
|
||||
void (*window_set_decorated)(WmWindowHandle window, bool decorated);
|
||||
bool (*window_is_decorated)(WmWindowHandle window);
|
||||
void (*window_set_border_width)(WmWindowHandle window, int width);
|
||||
int (*window_get_border_width)(WmWindowHandle window);
|
||||
void (*window_set_border_color)(WmWindowHandle window, WmColor color);
|
||||
|
||||
/* Window Management - Properties */
|
||||
void (*window_set_title)(WmWindowHandle window, const char *title);
|
||||
char* (*window_get_title)(WmWindowHandle window);
|
||||
void (*window_set_class)(WmWindowHandle window, const char *class, const char *instance);
|
||||
void (*window_get_class)(WmWindowHandle window, char **class, char **instance);
|
||||
void (*window_set_icon_name)(WmWindowHandle window, const char *name);
|
||||
|
||||
/* Window Management - Protocols */
|
||||
bool (*window_supports_protocol)(WmWindowHandle window, const char *protocol);
|
||||
void (*window_send_protocol)(WmWindowHandle window, const char *protocol, WmTime timestamp);
|
||||
void (*window_close)(WmWindowHandle window);
|
||||
void (*window_kill)(WmWindowHandle window);
|
||||
|
||||
/* Window Management - State */
|
||||
void (*window_set_fullscreen)(WmWindowHandle window, bool fullscreen);
|
||||
bool (*window_is_fullscreen)(WmWindowHandle window);
|
||||
void (*window_set_maximized)(WmWindowHandle window, bool maximized);
|
||||
bool (*window_is_maximized)(WmWindowHandle window);
|
||||
void (*window_set_minimized)(WmWindowHandle window, bool minimized);
|
||||
bool (*window_is_minimized)(WmWindowHandle window);
|
||||
void (*window_set_modal)(WmWindowHandle window, bool modal);
|
||||
void (*window_set_sticky)(WmWindowHandle window, bool sticky);
|
||||
void (*window_set_shaded)(WmWindowHandle window, bool shaded);
|
||||
void (*window_set_skip_taskbar)(WmWindowHandle window, bool skip);
|
||||
void (*window_set_skip_pager)(WmWindowHandle window, bool skip);
|
||||
void (*window_set_urgent)(WmWindowHandle window, bool urgent);
|
||||
bool (*window_is_urgent)(WmWindowHandle window);
|
||||
|
||||
/* Window Management - Type */
|
||||
void (*window_set_type)(WmWindowHandle window, WmWindowType type);
|
||||
WmWindowType (*window_get_type)(WmWindowHandle window);
|
||||
|
||||
/* Window Management - Selection */
|
||||
void (*window_set_selection_owner)(WmWindowHandle window, const char *selection, WmTime time);
|
||||
WmWindowHandle (*window_get_selection_owner)(const char *selection);
|
||||
void (*window_convert_selection)(WmWindowHandle requestor, const char *selection,
|
||||
const char *target, WmTime time);
|
||||
|
||||
/* Window Management - Client List */
|
||||
WmContainer* (*window_get_stacking_list)(void);
|
||||
WmContainer* (*window_get_client_list)(void);
|
||||
|
||||
/* Input - Events */
|
||||
bool (*poll_event)(WmBackendEvent *event);
|
||||
void (*wait_event)(WmBackendEvent *event);
|
||||
bool (*check_mask_event)(uint32_t mask, WmBackendEvent *event);
|
||||
void (*put_back_event)(const WmBackendEvent *event);
|
||||
|
||||
/* Input - Key Grabbing */
|
||||
void (*grab_key)(int keycode, uint32_t modifiers, WmWindowHandle window,
|
||||
bool owner_events, uint32_t pointer_mode, uint32_t keyboard_mode);
|
||||
void (*ungrab_key)(int keycode, uint32_t modifiers, WmWindowHandle window);
|
||||
void (*grab_keyboard)(WmWindowHandle window, bool owner_events,
|
||||
uint32_t pointer_mode, uint32_t keyboard_mode, WmTime time);
|
||||
void (*ungrab_keyboard)(WmTime time);
|
||||
|
||||
/* Input - Button Grabbing */
|
||||
void (*grab_button)(int button, uint32_t modifiers, WmWindowHandle window,
|
||||
bool owner_events, uint32_t event_mask,
|
||||
uint32_t pointer_mode, uint32_t keyboard_mode,
|
||||
WmWindowHandle confine_to, uint32_t cursor);
|
||||
void (*ungrab_button)(int button, uint32_t modifiers, WmWindowHandle window);
|
||||
void (*grab_pointer)(WmWindowHandle window, bool owner_events, uint32_t event_mask,
|
||||
uint32_t pointer_mode, uint32_t keyboard_mode,
|
||||
WmWindowHandle confine_to, uint32_t cursor, WmTime time);
|
||||
void (*ungrab_pointer)(WmTime time);
|
||||
|
||||
/* Input - Pointer */
|
||||
void (*query_pointer)(WmWindowHandle window, int *root_x, int *root_y,
|
||||
int *win_x, int *win_y, uint32_t *mask);
|
||||
void (*warp_pointer)(WmWindowHandle dest_w, int dest_x, int dest_y);
|
||||
void (*set_cursor)(WmWindowHandle window, uint32_t cursor);
|
||||
|
||||
/* Rendering - Basic */
|
||||
void (*fill_rectangle)(WmWindowHandle window, const WmRect *rect, WmColor color);
|
||||
void (*draw_rectangle)(WmWindowHandle window, const WmRect *rect, WmColor color, int line_width);
|
||||
void (*draw_line)(WmWindowHandle window, int x1, int y1, int x2, int y2,
|
||||
WmColor color, int line_width);
|
||||
void (*clear_window)(WmWindowHandle window);
|
||||
void (*copy_area)(WmWindowHandle src, WmWindowHandle dst,
|
||||
int src_x, int src_y, int width, int height,
|
||||
int dst_x, int dst_y);
|
||||
|
||||
/* Rendering - Text (if supported) */
|
||||
void* (*font_load)(const char *name, int size);
|
||||
void (*font_destroy)(void *font);
|
||||
int (*font_text_width)(void *font, const char *text, int len);
|
||||
void (*draw_text)(WmWindowHandle window, void *font, int x, int y,
|
||||
const char *text, int len, WmColor color);
|
||||
|
||||
/* Rendering - Images (if supported) */
|
||||
void* (*image_load)(const uint8_t *data, size_t size);
|
||||
void (*image_destroy)(void *image);
|
||||
void (*image_get_size)(void *image, int *width, int *height);
|
||||
void (*draw_image)(WmWindowHandle window, void *image, int x, int y,
|
||||
int width, int height);
|
||||
|
||||
/* Rendering - Sync */
|
||||
void (*begin_paint)(WmWindowHandle window);
|
||||
void (*end_paint)(WmWindowHandle window);
|
||||
|
||||
/* Atoms/Properties */
|
||||
uint32_t (*atom_get)(const char *name);
|
||||
const char* (*atom_get_name)(uint32_t atom);
|
||||
void (*property_set)(WmWindowHandle window, uint32_t property, uint32_t type,
|
||||
int format, const void *data, int num_items);
|
||||
int (*property_get)(WmWindowHandle window, uint32_t property, uint32_t type,
|
||||
void **data, int *num_items);
|
||||
void (*property_delete)(WmWindowHandle window, uint32_t property);
|
||||
|
||||
/* Session Management */
|
||||
void (*set_selection_owner)(WmWindowHandle owner, const char *selection);
|
||||
void (*send_client_message)(WmWindowHandle window, const char *message_type,
|
||||
const void *data, int format);
|
||||
|
||||
/* Error Handling */
|
||||
int (*get_last_error)(void);
|
||||
void (*set_error_handler)(int (*handler)(void *display, void *event));
|
||||
void (*set_io_error_handler)(int (*handler)(void *display));
|
||||
|
||||
} BackendInterface;
|
||||
|
||||
/*==============================================================================
|
||||
* Backend Registration
|
||||
*============================================================================*/
|
||||
|
||||
typedef const BackendInterface* (*BackendEntryFunc)(void);
|
||||
|
||||
void wm_backend_register(const char *name, BackendEntryFunc entry);
|
||||
const BackendInterface* wm_backend_get(const char *name);
|
||||
WmContainer* wm_backend_get_available(void);
|
||||
|
||||
/*==============================================================================
|
||||
* Backend Helpers
|
||||
*============================================================================*/
|
||||
|
||||
static inline bool wm_backend_has_capability(const BackendInterface *backend,
|
||||
WmBackendCapabilities cap) {
|
||||
WmBackendInfo info = backend->get_info();
|
||||
return (info.capabilities & cap) != 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BACKEND_INTERFACE_H */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* X11 Backend Header
|
||||
*/
|
||||
|
||||
#ifndef X11_BACKEND_H
|
||||
#define X11_BACKEND_H
|
||||
|
||||
#include "backends/backend_interface.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* X11 Backend Access
|
||||
*============================================================================*/
|
||||
|
||||
const BackendInterface* x11_backend_get_interface(void);
|
||||
Display* x11_backend_get_display(void);
|
||||
Window x11_backend_get_root(void);
|
||||
int x11_backend_get_screen(void);
|
||||
|
||||
static inline bool x11_backend_is_available(void) {
|
||||
const BackendInterface *iface = x11_backend_get_interface();
|
||||
return iface && iface->init(NULL);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* X11_BACKEND_H */
|
||||
@@ -68,6 +68,10 @@ struct Config {
|
||||
int demo_ai_timeout_ms;
|
||||
int demo_window_timeout_ms;
|
||||
|
||||
/* Fade effects */
|
||||
float fade_speed; /* Animation speed multiplier (0.1 - 3.0) */
|
||||
float fade_intensity; /* Glow intensity (0.0 - 1.0) */
|
||||
|
||||
char color_panel_bg[16];
|
||||
char color_panel_fg[16];
|
||||
char color_workspace_active[16];
|
||||
@@ -88,6 +92,7 @@ void config_destroy(Config *cfg);
|
||||
bool config_load(Config *cfg, const char *path);
|
||||
bool config_reload(Config *cfg);
|
||||
void config_set_defaults(Config *cfg);
|
||||
void config_validate(Config *cfg);
|
||||
|
||||
const char *config_get_terminal(void);
|
||||
const char *config_get_launcher(void);
|
||||
@@ -96,6 +101,10 @@ int config_get_title_height(void);
|
||||
int config_get_panel_height(void);
|
||||
int config_get_gap(void);
|
||||
const ColorScheme *config_get_colors(void);
|
||||
float config_get_fade_speed(void);
|
||||
float config_get_fade_intensity(void);
|
||||
void config_set_fade_speed(float speed);
|
||||
void config_set_fade_intensity(float intensity);
|
||||
|
||||
typedef void (*ConfigCallback)(const char *section, const char *key,
|
||||
const char *value, void *user_data);
|
||||
|
||||
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Abstract Client Interface
|
||||
*/
|
||||
|
||||
#ifndef WM_CLIENT_H
|
||||
#define WM_CLIENT_H
|
||||
|
||||
#include "core/wm_types.h"
|
||||
#include "core/wm_string.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
typedef struct Client Client; /* Legacy client structure */
|
||||
|
||||
/*==============================================================================
|
||||
* Abstract Client Type
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct AbstractClient AbstractClient;
|
||||
|
||||
/*==============================================================================
|
||||
* Client State Flags
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_CLIENT_STATE_NORMAL = 0,
|
||||
WM_CLIENT_STATE_FLOATING = (1 << 0),
|
||||
WM_CLIENT_STATE_FULLSCREEN = (1 << 1),
|
||||
WM_CLIENT_STATE_MAXIMIZED = (1 << 2),
|
||||
WM_CLIENT_STATE_MINIMIZED = (1 << 3),
|
||||
WM_CLIENT_STATE_URGENT = (1 << 4),
|
||||
WM_CLIENT_STATE_STICKY = (1 << 5),
|
||||
WM_CLIENT_STATE_HIDDEN = (1 << 6),
|
||||
WM_CLIENT_STATE_FOCUS = (1 << 7),
|
||||
WM_CLIENT_STATE_MAPPED = (1 << 8),
|
||||
WM_CLIENT_STATE_MANAGED = (1 << 9),
|
||||
WM_CLIENT_STATE_DESTROYING = (1 << 10)
|
||||
} WmClientState;
|
||||
|
||||
/*==============================================================================
|
||||
* Client Window Type
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_CLIENT_TYPE_UNKNOWN = 0,
|
||||
WM_CLIENT_TYPE_NORMAL,
|
||||
WM_CLIENT_TYPE_DIALOG,
|
||||
WM_CLIENT_TYPE_DOCK,
|
||||
WM_CLIENT_TYPE_DESKTOP,
|
||||
WM_CLIENT_TYPE_TOOLBAR,
|
||||
WM_CLIENT_TYPE_MENU,
|
||||
WM_CLIENT_TYPE_UTILITY,
|
||||
WM_CLIENT_TYPE_SPLASH,
|
||||
WM_CLIENT_TYPE_NOTIFICATION
|
||||
} WmClientType;
|
||||
|
||||
/*==============================================================================
|
||||
* Client Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Create an abstract client from a native window handle.
|
||||
* This takes ownership of the native window.
|
||||
*/
|
||||
AbstractClient* wm_client_create(WmWindowHandle window, WmClientType type);
|
||||
|
||||
/**
|
||||
* Destroy a client and release all associated resources.
|
||||
*/
|
||||
void wm_client_destroy(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Check if a client is valid (not NULL and not being destroyed).
|
||||
*/
|
||||
bool wm_client_is_valid(const AbstractClient *client);
|
||||
|
||||
/*==============================================================================
|
||||
* Native Access (for compatibility during migration)
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the native window handle.
|
||||
* Note: This should be avoided in backend-agnostic code.
|
||||
*/
|
||||
WmWindowHandle wm_client_get_window(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the native frame window handle (if reparented).
|
||||
*/
|
||||
WmWindowHandle wm_client_get_frame(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the legacy Client structure.
|
||||
* Note: This is for gradual migration only.
|
||||
*/
|
||||
Client* wm_client_get_legacy(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Create an abstract client wrapper around an existing legacy Client.
|
||||
* Note: The abstract client does NOT own the legacy client.
|
||||
*/
|
||||
AbstractClient* wm_client_from_legacy(Client *client);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Identification
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the unique client ID.
|
||||
*/
|
||||
WmClientId wm_client_get_id(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the client window type.
|
||||
*/
|
||||
WmClientType wm_client_get_type(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client window type.
|
||||
*/
|
||||
void wm_client_set_type(AbstractClient *client, WmClientType type);
|
||||
|
||||
/*==============================================================================
|
||||
* Client State
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the current state flags.
|
||||
*/
|
||||
WmClientState wm_client_get_state(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set state flags.
|
||||
*/
|
||||
void wm_client_set_state(AbstractClient *client, WmClientState state);
|
||||
|
||||
/**
|
||||
* Add state flags.
|
||||
*/
|
||||
void wm_client_add_state(AbstractClient *client, WmClientState state);
|
||||
|
||||
/**
|
||||
* Remove state flags.
|
||||
*/
|
||||
void wm_client_remove_state(AbstractClient *client, WmClientState state);
|
||||
|
||||
/**
|
||||
* Toggle state flags.
|
||||
*/
|
||||
void wm_client_toggle_state(AbstractClient *client, WmClientState state);
|
||||
|
||||
/**
|
||||
* Check if a specific state is set.
|
||||
*/
|
||||
bool wm_client_has_state(const AbstractClient *client, WmClientState state);
|
||||
|
||||
/* Convenience state checks */
|
||||
static inline bool wm_client_is_floating(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_FLOATING);
|
||||
}
|
||||
static inline bool wm_client_is_fullscreen(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_FULLSCREEN);
|
||||
}
|
||||
static inline bool wm_client_is_maximized(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_MAXIMIZED);
|
||||
}
|
||||
static inline bool wm_client_is_minimized(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_MINIMIZED);
|
||||
}
|
||||
static inline bool wm_client_is_urgent(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_URGENT);
|
||||
}
|
||||
static inline bool wm_client_is_sticky(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_STICKY);
|
||||
}
|
||||
static inline bool wm_client_is_focused(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_FOCUS);
|
||||
}
|
||||
static inline bool wm_client_is_mapped(const AbstractClient *c) {
|
||||
return c && wm_client_has_state(c, WM_CLIENT_STATE_MAPPED);
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* Client Geometry
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the client geometry (position and size).
|
||||
*/
|
||||
WmRect wm_client_get_geometry(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client geometry.
|
||||
*/
|
||||
void wm_client_set_geometry(AbstractClient *client, const WmRect *geometry);
|
||||
|
||||
/**
|
||||
* Get the client position.
|
||||
*/
|
||||
WmPoint wm_client_get_position(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client position.
|
||||
*/
|
||||
void wm_client_set_position(AbstractClient *client, int x, int y);
|
||||
|
||||
/**
|
||||
* Get the client size.
|
||||
*/
|
||||
WmSize wm_client_get_size(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client size.
|
||||
*/
|
||||
void wm_client_set_size(AbstractClient *client, int width, int height);
|
||||
|
||||
/**
|
||||
* Get the border width.
|
||||
*/
|
||||
int wm_client_get_border_width(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the border width.
|
||||
*/
|
||||
void wm_client_set_border_width(AbstractClient *client, int width);
|
||||
|
||||
/**
|
||||
* Store previous geometry (for restore after maximize/fullscreen).
|
||||
*/
|
||||
void wm_client_save_geometry(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Restore previous geometry.
|
||||
*/
|
||||
void wm_client_restore_geometry(AbstractClient *client);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Workspace
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the client's workspace ID.
|
||||
*/
|
||||
WmWorkspaceId wm_client_get_workspace(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client's workspace ID.
|
||||
*/
|
||||
void wm_client_set_workspace(AbstractClient *client, WmWorkspaceId workspace);
|
||||
|
||||
/**
|
||||
* Check if the client is on a specific workspace.
|
||||
*/
|
||||
bool wm_client_is_on_workspace(const AbstractClient *client, WmWorkspaceId workspace);
|
||||
|
||||
/**
|
||||
* Check if the client is visible on the current workspace.
|
||||
*/
|
||||
bool wm_client_is_visible_on_current(const AbstractClient *client);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Properties
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the client title.
|
||||
* Returns a reference to the internal string (do not free).
|
||||
*/
|
||||
const char* wm_client_get_title(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client title.
|
||||
*/
|
||||
void wm_client_set_title(AbstractClient *client, const char *title);
|
||||
|
||||
/**
|
||||
* Get the client class (application class).
|
||||
*/
|
||||
const char* wm_client_get_class(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client class.
|
||||
*/
|
||||
void wm_client_set_class(AbstractClient *client, const char *class_name);
|
||||
|
||||
/**
|
||||
* Get the client instance name.
|
||||
*/
|
||||
const char* wm_client_get_instance(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client instance name.
|
||||
*/
|
||||
void wm_client_set_instance(AbstractClient *client, const char *instance);
|
||||
|
||||
/**
|
||||
* Get the client's taskbar color.
|
||||
*/
|
||||
WmColor wm_client_get_color(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Set the client's taskbar color.
|
||||
*/
|
||||
void wm_client_set_color(AbstractClient *client, WmColor color);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Actions
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Focus the client.
|
||||
*/
|
||||
void wm_client_focus(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Unfocus the client.
|
||||
*/
|
||||
void wm_client_unfocus(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Raise the client to the top of the stack.
|
||||
*/
|
||||
void wm_client_raise(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Lower the client to the bottom of the stack.
|
||||
*/
|
||||
void wm_client_lower(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Show/map the client window.
|
||||
*/
|
||||
void wm_client_show(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Hide/unmap the client window.
|
||||
*/
|
||||
void wm_client_hide(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Minimize the client.
|
||||
*/
|
||||
void wm_client_minimize(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Restore the client from minimized state.
|
||||
*/
|
||||
void wm_client_restore(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Close the client (politely request close).
|
||||
*/
|
||||
void wm_client_close(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Kill the client (forcefully terminate).
|
||||
*/
|
||||
void wm_client_kill(AbstractClient *client);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Management
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Reparent the client into a frame window.
|
||||
*/
|
||||
void wm_client_reparent(AbstractClient *client, WmWindowHandle frame);
|
||||
|
||||
/**
|
||||
* Unreparent the client from its frame.
|
||||
*/
|
||||
void wm_client_unreparent(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Configure the client (apply size hints, constraints).
|
||||
*/
|
||||
void wm_client_configure(AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Apply size hints to constrain width/height.
|
||||
*/
|
||||
void wm_client_apply_size_hints(AbstractClient *client, int *width, int *height);
|
||||
|
||||
/**
|
||||
* Move and resize a client.
|
||||
*/
|
||||
void wm_client_move_resize(AbstractClient *client, int x, int y, int width, int height);
|
||||
|
||||
/*==============================================================================
|
||||
* Client List Management
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Get the next client in the global list.
|
||||
*/
|
||||
AbstractClient* wm_client_get_next(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the previous client in the global list.
|
||||
*/
|
||||
AbstractClient* wm_client_get_prev(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the first client in the global list.
|
||||
*/
|
||||
AbstractClient* wm_client_get_first(void);
|
||||
|
||||
/**
|
||||
* Get the last client in the global list.
|
||||
*/
|
||||
AbstractClient* wm_client_get_last(void);
|
||||
|
||||
/**
|
||||
* Get the next client in MRU (Most Recently Used) order.
|
||||
*/
|
||||
AbstractClient* wm_client_get_next_mru(const AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the previous client in MRU order.
|
||||
*/
|
||||
AbstractClient* wm_client_get_prev_mru(const AbstractClient *client);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Lookup
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Find a client by its window handle.
|
||||
*/
|
||||
AbstractClient* wm_client_find_by_window(WmWindowHandle window);
|
||||
|
||||
/**
|
||||
* Find a client by its frame handle.
|
||||
*/
|
||||
AbstractClient* wm_client_find_by_frame(WmWindowHandle frame);
|
||||
|
||||
/**
|
||||
* Find a client by its ID.
|
||||
*/
|
||||
AbstractClient* wm_client_find_by_id(WmClientId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Iteration
|
||||
*============================================================================*/
|
||||
|
||||
typedef bool (*WmClientForeachFunc)(AbstractClient *client, void *user_data);
|
||||
|
||||
/**
|
||||
* Iterate over all clients.
|
||||
*/
|
||||
void wm_client_foreach(WmClientForeachFunc func, void *user_data);
|
||||
|
||||
/**
|
||||
* Iterate over clients on a specific workspace.
|
||||
*/
|
||||
void wm_client_foreach_on_workspace(WmWorkspaceId workspace,
|
||||
WmClientForeachFunc func, void *user_data);
|
||||
|
||||
/**
|
||||
* Count total clients.
|
||||
*/
|
||||
int wm_client_count(void);
|
||||
|
||||
/**
|
||||
* Count clients on a specific workspace.
|
||||
*/
|
||||
int wm_client_count_on_workspace(WmWorkspaceId workspace);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Manager
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WmClientManager WmClientManager;
|
||||
|
||||
/**
|
||||
* Get the global client manager.
|
||||
*/
|
||||
WmClientManager* wm_client_manager_get(void);
|
||||
|
||||
/**
|
||||
* Initialize the client manager.
|
||||
*/
|
||||
bool wm_client_manager_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown the client manager.
|
||||
*/
|
||||
void wm_client_manager_shutdown(void);
|
||||
|
||||
/**
|
||||
* Register a client with the manager.
|
||||
*/
|
||||
void wm_client_manager_add(WmClientManager *mgr, AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Unregister a client from the manager.
|
||||
*/
|
||||
void wm_client_manager_remove(WmClientManager *mgr, AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Move a client to the front of the MRU list.
|
||||
*/
|
||||
void wm_client_manager_touch(WmClientManager *mgr, AbstractClient *client);
|
||||
|
||||
/**
|
||||
* Get the focused client.
|
||||
*/
|
||||
AbstractClient* wm_client_manager_get_focused(const WmClientManager *mgr);
|
||||
|
||||
/**
|
||||
* Set the focused client.
|
||||
*/
|
||||
void wm_client_manager_set_focused(WmClientManager *mgr, AbstractClient *client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_CLIENT_H */
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Generic Container Interface
|
||||
*/
|
||||
|
||||
#ifndef WM_CONTAINER_H
|
||||
#define WM_CONTAINER_H
|
||||
|
||||
#include "wm_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Container Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
WmContainer* wm_container_create(WmContainerType type, WmDestroyFunc destroy_fn);
|
||||
void wm_container_destroy(WmContainer *container);
|
||||
void wm_container_clear(WmContainer *container);
|
||||
|
||||
WmContainer* wm_container_clone(const WmContainer *container, WmCloneFunc clone_fn);
|
||||
|
||||
/*==============================================================================
|
||||
* Container Properties
|
||||
*============================================================================*/
|
||||
|
||||
WmContainerType wm_container_get_type(const WmContainer *container);
|
||||
size_t wm_container_size(const WmContainer *container);
|
||||
bool wm_container_is_empty(const WmContainer *container);
|
||||
|
||||
/*==============================================================================
|
||||
* List Operations
|
||||
*============================================================================*/
|
||||
|
||||
/* These work for LIST and QUEUE */
|
||||
void wm_list_append(WmContainer *list, void *data);
|
||||
void wm_list_prepend(WmContainer *list, void *data);
|
||||
void wm_list_insert(WmContainer *list, size_t index, void *data);
|
||||
|
||||
bool wm_list_remove(WmContainer *list, void *data);
|
||||
void* wm_list_remove_at(WmContainer *list, size_t index);
|
||||
|
||||
void* wm_list_get(const WmContainer *list, size_t index);
|
||||
void* wm_list_get_first(const WmContainer *list);
|
||||
void* wm_list_get_last(const WmContainer *list);
|
||||
|
||||
size_t wm_list_index_of(const WmContainer *list, void *data);
|
||||
bool wm_list_contains(const WmContainer *list, void *data);
|
||||
|
||||
void* wm_list_find(const WmContainer *list, WmCompareFunc cmp, const void *key);
|
||||
void* wm_list_find_custom(const WmContainer *list,
|
||||
bool (*predicate)(const void *item, const void *user_data),
|
||||
const void *user_data);
|
||||
|
||||
void wm_list_sort(WmContainer *list, WmCompareFunc cmp);
|
||||
void wm_list_reverse(WmContainer *list);
|
||||
|
||||
/*==============================================================================
|
||||
* Array Operations
|
||||
*============================================================================*/
|
||||
|
||||
void wm_array_append(WmContainer *array, void *data);
|
||||
void wm_array_insert(WmContainer *array, size_t index, void *data);
|
||||
void wm_array_set(WmContainer *array, size_t index, void *data);
|
||||
|
||||
void* wm_array_get(const WmContainer *array, size_t index);
|
||||
void* wm_array_remove_at(WmContainer *array, size_t index);
|
||||
|
||||
void wm_array_resize(WmContainer *array, size_t new_size);
|
||||
void wm_array_reserve(WmContainer *array, size_t capacity);
|
||||
size_t wm_array_capacity(const WmContainer *array);
|
||||
|
||||
void wm_array_compact(WmContainer *array);
|
||||
void wm_array_sort(WmContainer *array, WmCompareFunc cmp);
|
||||
|
||||
/*==============================================================================
|
||||
* HashMap Operations
|
||||
*============================================================================*/
|
||||
|
||||
/* Key types supported */
|
||||
typedef enum {
|
||||
WM_HASH_KEY_STRING,
|
||||
WM_HASH_KEY_INT,
|
||||
WM_HASH_KEY_POINTER
|
||||
} WmHashKeyType;
|
||||
|
||||
WmContainer* wm_hashmap_create(WmHashKeyType key_type, WmDestroyFunc destroy_fn);
|
||||
|
||||
void wm_hashmap_insert(WmContainer *map, const void *key, void *value);
|
||||
void* wm_hashmap_get(const WmContainer *map, const void *key);
|
||||
bool wm_hashmap_contains(const WmContainer *map, const void *key);
|
||||
bool wm_hashmap_remove(WmContainer *map, const void *key);
|
||||
|
||||
void* wm_hashmap_lookup(const WmContainer *map, WmCompareFunc cmp, const void *key);
|
||||
|
||||
WmContainer* wm_hashmap_get_keys(const WmContainer *map);
|
||||
WmContainer* wm_hashmap_get_values(const WmContainer *map);
|
||||
|
||||
void wm_hashmap_rehash(WmContainer *map, size_t new_capacity);
|
||||
float wm_hashmap_load_factor(const WmContainer *map);
|
||||
|
||||
/* Convenience functions for string keys */
|
||||
void wm_hashmap_insert_string(WmContainer *map, const char *key, void *value);
|
||||
void* wm_hashmap_get_string(const WmContainer *map, const char *key);
|
||||
bool wm_hashmap_contains_string(const WmContainer *map, const char *key);
|
||||
bool wm_hashmap_remove_string(WmContainer *map, const char *key);
|
||||
|
||||
/* Convenience functions for int keys */
|
||||
void wm_hashmap_insert_int(WmContainer *map, int key, void *value);
|
||||
void* wm_hashmap_get_int(const WmContainer *map, int key);
|
||||
bool wm_hashmap_contains_int(const WmContainer *map, int key);
|
||||
bool wm_hashmap_remove_int(WmContainer *map, int key);
|
||||
|
||||
/*==============================================================================
|
||||
* Stack Operations
|
||||
*============================================================================*/
|
||||
|
||||
void wm_stack_push(WmContainer *stack, void *data);
|
||||
void* wm_stack_pop(WmContainer *stack);
|
||||
void* wm_stack_peek(const WmContainer *stack);
|
||||
|
||||
/*==============================================================================
|
||||
* Queue Operations
|
||||
*============================================================================*/
|
||||
|
||||
void wm_queue_enqueue(WmContainer *queue, void *data);
|
||||
void* wm_queue_dequeue(WmContainer *queue);
|
||||
void* wm_queue_peek(const WmContainer *queue);
|
||||
void* wm_queue_peek_tail(const WmContainer *queue);
|
||||
|
||||
/*==============================================================================
|
||||
* Tree Operations (if type is TREE)
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WmTreeNode WmTreeNode;
|
||||
|
||||
WmTreeNode* wm_tree_get_root(const WmContainer *tree);
|
||||
WmTreeNode* wm_tree_node_get_left(const WmTreeNode *node);
|
||||
WmTreeNode* wm_tree_node_get_right(const WmTreeNode *node);
|
||||
WmTreeNode* wm_tree_node_get_parent(const WmTreeNode *node);
|
||||
void* wm_tree_node_get_data(const WmTreeNode *node);
|
||||
|
||||
/*==============================================================================
|
||||
* Iteration
|
||||
*============================================================================*/
|
||||
|
||||
WmIterator* wm_container_iterator(const WmContainer *container);
|
||||
WmIterator* wm_container_iterator_reverse(const WmContainer *container);
|
||||
|
||||
void wm_iterator_destroy(WmIterator *it);
|
||||
bool wm_iterator_has_next(const WmIterator *it);
|
||||
void* wm_iterator_next(WmIterator *it);
|
||||
const void* wm_iterator_peek(const WmIterator *it);
|
||||
|
||||
/* HashMap iteration - returns key-value pairs */
|
||||
typedef struct {
|
||||
const void *key;
|
||||
void *value;
|
||||
} WmHashEntry;
|
||||
|
||||
WmIterator* wm_hashmap_iterator(const WmContainer *map);
|
||||
WmHashEntry* wm_hashmap_iterator_next(WmIterator *it);
|
||||
|
||||
/*==============================================================================
|
||||
* Functional Operations
|
||||
*============================================================================*/
|
||||
|
||||
typedef void (*WmForeachFunc)(void *item, void *user_data);
|
||||
typedef void* (*WmMapFunc)(const void *item, void *user_data);
|
||||
typedef bool (*WmFilterFunc)(const void *item, void *user_data);
|
||||
typedef void* (*WmReduceFunc)(void *accumulator, const void *item, void *user_data);
|
||||
|
||||
void wm_container_foreach(const WmContainer *container, WmForeachFunc func, void *user_data);
|
||||
|
||||
WmContainer* wm_container_map(const WmContainer *container, WmContainerType new_type,
|
||||
WmMapFunc func, WmDestroyFunc destroy_fn, void *user_data);
|
||||
|
||||
WmContainer* wm_container_filter(const WmContainer *container,
|
||||
WmFilterFunc predicate, void *user_data);
|
||||
|
||||
void* wm_container_reduce(const WmContainer *container,
|
||||
WmReduceFunc func, void *initial, void *user_data);
|
||||
|
||||
bool wm_container_all_match(const WmContainer *container,
|
||||
WmFilterFunc predicate, void *user_data);
|
||||
|
||||
bool wm_container_any_match(const WmContainer *container,
|
||||
WmFilterFunc predicate, void *user_data);
|
||||
|
||||
/*==============================================================================
|
||||
* Convenience Constructors
|
||||
*============================================================================*/
|
||||
|
||||
static inline WmContainer* wm_list_create(WmDestroyFunc destroy_fn) {
|
||||
return wm_container_create(WM_CONTAINER_LIST, destroy_fn);
|
||||
}
|
||||
|
||||
static inline WmContainer* wm_array_create(WmDestroyFunc destroy_fn) {
|
||||
return wm_container_create(WM_CONTAINER_ARRAY, destroy_fn);
|
||||
}
|
||||
|
||||
static inline WmContainer* wm_hashmap_create_string(WmDestroyFunc destroy_fn) {
|
||||
return wm_hashmap_create(WM_HASH_KEY_STRING, destroy_fn);
|
||||
}
|
||||
|
||||
static inline WmContainer* wm_queue_create(WmDestroyFunc destroy_fn) {
|
||||
return wm_container_create(WM_CONTAINER_QUEUE, destroy_fn);
|
||||
}
|
||||
|
||||
static inline WmContainer* wm_stack_create(WmDestroyFunc destroy_fn) {
|
||||
return wm_container_create(WM_CONTAINER_STACK, destroy_fn);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_CONTAINER_H */
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Event Bus System
|
||||
*/
|
||||
|
||||
#ifndef WM_EVENT_H
|
||||
#define WM_EVENT_H
|
||||
|
||||
#include "wm_types.h"
|
||||
#include "wm_client.h"
|
||||
#include "wm_string.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Event Data Structures
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
WmEventType type;
|
||||
WmTime timestamp;
|
||||
WmId source_id;
|
||||
} WmEventHeader;
|
||||
|
||||
/* Window Events */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
AbstractClient *client;
|
||||
} WmEventWindowBase;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
AbstractClient *client;
|
||||
} WmEventWindowCreated;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
AbstractClient *client;
|
||||
WmString *old_title;
|
||||
WmString *new_title;
|
||||
} WmEventWindowTitleChanged;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
AbstractClient *client;
|
||||
WmRect old_geometry;
|
||||
WmRect new_geometry;
|
||||
} WmEventWindowMoved;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
AbstractClient *client;
|
||||
WmRect old_geometry;
|
||||
WmRect new_geometry;
|
||||
} WmEventWindowResized;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
AbstractClient *client;
|
||||
WmClientFlags old_flags;
|
||||
WmClientFlags new_flags;
|
||||
} WmEventWindowStateChanged;
|
||||
|
||||
/* Workspace Events */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmWorkspaceId workspace;
|
||||
} WmEventWorkspaceBase;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmWorkspaceId old_workspace;
|
||||
WmWorkspaceId new_workspace;
|
||||
} WmEventWorkspaceSwitched;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmWorkspaceId workspace;
|
||||
WmLayoutType old_layout;
|
||||
WmLayoutType new_layout;
|
||||
} WmEventWorkspaceLayoutChanged;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmWorkspaceId workspace;
|
||||
AbstractClient *client;
|
||||
} WmEventClientWorkspaceChanged;
|
||||
|
||||
/* Input Events */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
unsigned int keycode;
|
||||
unsigned int keysym;
|
||||
unsigned int modifiers;
|
||||
const char *key_name;
|
||||
} WmEventKey;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
unsigned int button;
|
||||
int x;
|
||||
int y;
|
||||
unsigned int modifiers;
|
||||
} WmEventButton;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
int x;
|
||||
int y;
|
||||
int delta_x;
|
||||
int delta_y;
|
||||
unsigned int modifiers;
|
||||
} WmEventMotion;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
int delta;
|
||||
int x;
|
||||
int y;
|
||||
} WmEventScroll;
|
||||
|
||||
/* Monitor Events */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
int monitor_index;
|
||||
WmRect geometry;
|
||||
bool primary;
|
||||
} WmEventMonitorAdded;
|
||||
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
int monitor_index;
|
||||
} WmEventMonitorRemoved;
|
||||
|
||||
/* Configuration Events */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmString *config_path;
|
||||
bool success;
|
||||
WmString *error_message;
|
||||
} WmEventConfigReloaded;
|
||||
|
||||
/* Command Events */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmCommandType command;
|
||||
bool success;
|
||||
WmString *error_message;
|
||||
} WmEventCommandExecuted;
|
||||
|
||||
/* Custom Event */
|
||||
typedef struct {
|
||||
WmEventHeader header;
|
||||
WmString *event_name;
|
||||
void *custom_data;
|
||||
WmDestroyFunc destroy_func;
|
||||
} WmEventCustom;
|
||||
|
||||
/*==============================================================================
|
||||
* Event Bus Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
WmEventBus* wm_event_bus_create(void);
|
||||
void wm_event_bus_destroy(WmEventBus *bus);
|
||||
|
||||
WmEventBus* wm_event_bus_get_default(void);
|
||||
void wm_event_bus_set_default(WmEventBus *bus);
|
||||
|
||||
/*==============================================================================
|
||||
* Event Subscription
|
||||
*============================================================================*/
|
||||
|
||||
WmEventSubscription* wm_event_subscribe(WmEventBus *bus,
|
||||
WmEventType type,
|
||||
WmEventHandler handler,
|
||||
void *user_data);
|
||||
|
||||
WmEventSubscription* wm_event_subscribe_pattern(WmEventBus *bus,
|
||||
WmEventType type_min,
|
||||
WmEventType type_max,
|
||||
WmEventHandler handler,
|
||||
void *user_data);
|
||||
|
||||
WmEventSubscription* wm_event_subscribe_all(WmEventBus *bus,
|
||||
WmEventHandler handler,
|
||||
void *user_data);
|
||||
|
||||
void wm_event_unsubscribe(WmEventBus *bus, WmEventSubscription *subscription);
|
||||
void wm_event_unsubscribe_all(WmEventBus *bus, void *user_data);
|
||||
|
||||
/*==============================================================================
|
||||
* Event Emission
|
||||
*============================================================================*/
|
||||
|
||||
void wm_event_emit(WmEventBus *bus, WmEventType type, const void *event_data);
|
||||
void wm_event_emit_async(WmEventBus *bus, WmEventType type, const void *event_data);
|
||||
|
||||
/* Convenience emitters */
|
||||
void wm_event_emit_window_created(WmEventBus *bus, AbstractClient *client);
|
||||
void wm_event_emit_window_destroyed(WmEventBus *bus, AbstractClient *client);
|
||||
void wm_event_emit_window_focused(WmEventBus *bus, AbstractClient *client, AbstractClient *prev_focus);
|
||||
void wm_event_emit_window_moved(WmEventBus *bus, AbstractClient *client, const WmRect *old_geom);
|
||||
void wm_event_emit_window_resized(WmEventBus *bus, AbstractClient *client, const WmRect *old_geom);
|
||||
void wm_event_emit_window_state_changed(WmEventBus *bus, AbstractClient *client,
|
||||
WmClientFlags old_flags, WmClientFlags new_flags);
|
||||
|
||||
void wm_event_emit_workspace_switched(WmEventBus *bus, WmWorkspaceId old_ws, WmWorkspaceId new_ws);
|
||||
void wm_event_emit_workspace_layout_changed(WmEventBus *bus, WmWorkspaceId ws,
|
||||
WmLayoutType old_layout, WmLayoutType new_layout);
|
||||
|
||||
/*==============================================================================
|
||||
* Event Processing
|
||||
*============================================================================*/
|
||||
|
||||
void wm_event_process(WmEventBus *bus);
|
||||
void wm_event_process_all(WmEventBus *bus);
|
||||
bool wm_event_process_one(WmEventBus *bus);
|
||||
|
||||
void wm_event_dispatch_pending(WmEventBus *bus);
|
||||
int wm_event_get_pending_count(const WmEventBus *bus);
|
||||
|
||||
/*==============================================================================
|
||||
* Event Data Helpers
|
||||
*============================================================================*/
|
||||
|
||||
WmEventHeader* wm_event_get_header(void *event_data);
|
||||
WmTime wm_event_get_timestamp(const void *event_data);
|
||||
const char* wm_event_type_to_string(WmEventType type);
|
||||
WmEventType wm_event_type_from_string(const char *str);
|
||||
|
||||
/*==============================================================================
|
||||
* Event Blocking/Filtering
|
||||
*============================================================================*/
|
||||
|
||||
void wm_event_begin_block(WmEventBus *bus, WmEventType type);
|
||||
void wm_event_end_block(WmEventBus *bus, WmEventType type);
|
||||
bool wm_event_is_blocked(const WmEventBus *bus, WmEventType type);
|
||||
|
||||
void wm_event_suppress(WmEventBus *bus, WmEventType type);
|
||||
void wm_event_unsuppress(WmEventBus *bus, WmEventType type);
|
||||
bool wm_event_is_suppressed(const WmEventBus *bus, WmEventType type);
|
||||
|
||||
/*==============================================================================
|
||||
* Custom Events
|
||||
*============================================================================*/
|
||||
|
||||
void wm_event_emit_custom(WmEventBus *bus, const char *event_name, void *data, WmDestroyFunc destroy_fn);
|
||||
WmEventSubscription* wm_event_subscribe_custom(WmEventBus *bus, const char *event_name,
|
||||
WmEventHandler handler, void *user_data);
|
||||
|
||||
/*==============================================================================
|
||||
* Event Statistics
|
||||
*============================================================================*/
|
||||
|
||||
uint64_t wm_event_get_emit_count(const WmEventBus *bus, WmEventType type);
|
||||
uint64_t wm_event_get_total_emit_count(const WmEventBus *bus);
|
||||
void wm_event_reset_statistics(WmEventBus *bus);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_EVENT_H */
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Abstract Hash Map Container
|
||||
*/
|
||||
|
||||
#ifndef WM_HASHMAP_H
|
||||
#define WM_HASHMAP_H
|
||||
|
||||
#include "core/wm_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Opaque Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WmHashMap WmHashMap;
|
||||
|
||||
/*==============================================================================
|
||||
* Function Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef uint32_t (*WmHashFunc)(const void *key);
|
||||
typedef bool (*WmKeyEqualFunc)(const void *a, const void *b);
|
||||
typedef void (*WmHashForeachFunc)(void *key, void *value, void *user_data);
|
||||
|
||||
/*==============================================================================
|
||||
* Hash Functions
|
||||
*============================================================================*/
|
||||
|
||||
static inline uint32_t wm_hash_ptr(const void *ptr) {
|
||||
uintptr_t p = (uintptr_t)ptr;
|
||||
return (uint32_t)(p ^ (p >> 32));
|
||||
}
|
||||
|
||||
static inline uint32_t wm_hash_int(int key) {
|
||||
return (uint32_t)key;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
WmHashMap* wm_hashmap_new(void);
|
||||
WmHashMap* wm_hashmap_new_full(WmHashFunc hash_func, WmKeyEqualFunc key_equal,
|
||||
WmFreeFunc key_free, WmFreeFunc value_free);
|
||||
WmHashMap* wm_hashmap_new_string_key(void);
|
||||
void wm_hashmap_destroy(WmHashMap *map);
|
||||
WmHashMap* wm_hashmap_clone(const WmHashMap *map);
|
||||
|
||||
/*==============================================================================
|
||||
* Capacity
|
||||
*============================================================================*/
|
||||
|
||||
size_t wm_hashmap_size(const WmHashMap *map);
|
||||
bool wm_hashmap_is_empty(const WmHashMap *map);
|
||||
void wm_hashmap_clear(WmHashMap *map);
|
||||
|
||||
/*==============================================================================
|
||||
* Element Access
|
||||
*============================================================================*/
|
||||
|
||||
void* wm_hashmap_get(const WmHashMap *map, const void *key);
|
||||
void* wm_hashmap_get_or_default(const WmHashMap *map, const void *key, void *default_val);
|
||||
bool wm_hashmap_contains(const WmHashMap *map, const void *key);
|
||||
|
||||
/*==============================================================================
|
||||
* Modifiers
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_hashmap_insert(WmHashMap *map, void *key, void *value);
|
||||
bool wm_hashmap_insert_no_replace(WmHashMap *map, void *key, void *value);
|
||||
void* wm_hashmap_set(WmHashMap *map, void *key, void *value);
|
||||
void* wm_hashmap_remove(WmHashMap *map, const void *key);
|
||||
bool wm_hashmap_steal(WmHashMap *map, const void *key);
|
||||
|
||||
/*==============================================================================
|
||||
* Iteration
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
void *map; /* Opaque pointer to hashmap */
|
||||
size_t bucket;
|
||||
void *entry; /* Opaque pointer to current entry */
|
||||
void *next_entry; /* Opaque pointer to next entry */
|
||||
} WmHashMapIter;
|
||||
|
||||
void wm_hashmap_iter_init(WmHashMapIter *iter, WmHashMap *map);
|
||||
bool wm_hashmap_iter_next(WmHashMapIter *iter, void **key, void **value);
|
||||
void wm_hashmap_foreach(const WmHashMap *map, WmHashForeachFunc func, void *user_data);
|
||||
|
||||
/*==============================================================================
|
||||
* String Helpers
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_hashmap_insert_string(WmHashMap *map, const char *key, void *value);
|
||||
void* wm_hashmap_get_string(const WmHashMap *map, const char *key);
|
||||
bool wm_hashmap_contains_string(const WmHashMap *map, const char *key);
|
||||
void* wm_hashmap_remove_string(WmHashMap *map, const char *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_HASHMAP_H */
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Abstract List Container
|
||||
*/
|
||||
|
||||
#ifndef WM_LIST_H
|
||||
#define WM_LIST_H
|
||||
|
||||
#include "core/wm_types.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Opaque Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WmList WmList;
|
||||
|
||||
/*==============================================================================
|
||||
* Function Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef void (*WmFreeFunc)(void *item);
|
||||
typedef int (*WmCompareFunc)(const void *a, const void *b);
|
||||
typedef bool (*WmForeachFunc)(void *item, size_t index, void *user_data);
|
||||
typedef void* (*WmCloneFunc)(const void *item);
|
||||
|
||||
/*==============================================================================
|
||||
* Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
WmList* wm_list_new(void);
|
||||
WmList* wm_list_new_sized(size_t initial_capacity);
|
||||
void wm_list_destroy(WmList *list);
|
||||
void wm_list_destroy_no_free(WmList *list);
|
||||
WmList* wm_list_clone(const WmList *list);
|
||||
void wm_list_set_free_func(WmList *list, WmFreeFunc func);
|
||||
|
||||
/*==============================================================================
|
||||
* Capacity
|
||||
*============================================================================*/
|
||||
|
||||
size_t wm_list_size(const WmList *list);
|
||||
size_t wm_list_capacity(const WmList *list);
|
||||
bool wm_list_is_empty(const WmList *list);
|
||||
void wm_list_reserve(WmList *list, size_t capacity);
|
||||
void wm_list_compact(WmList *list);
|
||||
void wm_list_clear(WmList *list);
|
||||
|
||||
/*==============================================================================
|
||||
* Modifiers
|
||||
*============================================================================*/
|
||||
|
||||
void wm_list_append(WmList *list, void *item);
|
||||
void wm_list_prepend(WmList *list, void *item);
|
||||
void wm_list_insert(WmList *list, size_t index, void *item);
|
||||
void wm_list_insert_sorted(WmList *list, void *item, WmCompareFunc compare);
|
||||
void wm_list_remove(WmList *list, void *item);
|
||||
void wm_list_remove_at(WmList *list, size_t index);
|
||||
void* wm_list_take_at(WmList *list, size_t index);
|
||||
bool wm_list_remove_one(WmList *list, void *item);
|
||||
bool wm_list_remove_all(WmList *list, void *item);
|
||||
void* wm_list_pop_back(WmList *list);
|
||||
void* wm_list_pop_front(WmList *list);
|
||||
|
||||
/*==============================================================================
|
||||
* Accessors
|
||||
*============================================================================*/
|
||||
|
||||
void* wm_list_get(const WmList *list, size_t index);
|
||||
void* wm_list_first(const WmList *list);
|
||||
void* wm_list_last(const WmList *list);
|
||||
void* wm_list_front(const WmList *list);
|
||||
void* wm_list_back(const WmList *list);
|
||||
void wm_list_set(WmList *list, size_t index, void *item);
|
||||
|
||||
/*==============================================================================
|
||||
* Iteration
|
||||
*============================================================================*/
|
||||
|
||||
void wm_list_foreach(const WmList *list, WmForeachFunc func, void *user_data);
|
||||
void wm_list_foreach_reverse(const WmList *list, WmForeachFunc func, void *user_data);
|
||||
|
||||
/*==============================================================================
|
||||
* Search
|
||||
*============================================================================*/
|
||||
|
||||
ssize_t wm_list_index_of(const WmList *list, void *item);
|
||||
bool wm_list_contains(const WmList *list, void *item);
|
||||
void* wm_list_find(const WmList *list, WmCompareFunc compare, const void *key);
|
||||
ssize_t wm_list_find_index(const WmList *list, WmCompareFunc compare, const void *key);
|
||||
|
||||
/*==============================================================================
|
||||
* Sorting
|
||||
*============================================================================*/
|
||||
|
||||
void wm_list_sort(WmList *list, WmCompareFunc compare);
|
||||
|
||||
/*==============================================================================
|
||||
* Data Operations
|
||||
*============================================================================*/
|
||||
|
||||
void** wm_list_data(WmList *list);
|
||||
void* wm_list_steal(WmList *list, size_t index);
|
||||
WmList* wm_list_slice(const WmList *list, size_t start, size_t end);
|
||||
void wm_list_move(WmList *list, size_t from, size_t to);
|
||||
void wm_list_swap(WmList *list, size_t i, size_t j);
|
||||
|
||||
/*==============================================================================
|
||||
* Comparison
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_list_equals(const WmList *list1, const WmList *list2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_LIST_H */
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Abstract String Type
|
||||
*/
|
||||
|
||||
#ifndef WM_STRING_H
|
||||
#define WM_STRING_H
|
||||
|
||||
#include "wm_types.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* String Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
WmString* wm_string_new(const char *str);
|
||||
WmString* wm_string_new_empty(void);
|
||||
WmString* wm_string_new_sized(size_t capacity);
|
||||
WmString* wm_string_new_printf(const char *fmt, ...);
|
||||
WmString* wm_string_new_vprintf(const char *fmt, va_list args);
|
||||
WmString* wm_string_new_n(const char *str, size_t n);
|
||||
|
||||
void wm_string_destroy(WmString *str);
|
||||
WmString* wm_string_clone(const WmString *str);
|
||||
|
||||
/*==============================================================================
|
||||
* String Operations
|
||||
*============================================================================*/
|
||||
|
||||
void wm_string_append(WmString *str, const char *suffix);
|
||||
void wm_string_append_char(WmString *str, char c);
|
||||
void wm_string_append_n(WmString *str, const char *suffix, size_t n);
|
||||
void wm_string_append_printf(WmString *str, const char *fmt, ...);
|
||||
void wm_string_append_vprintf(WmString *str, const char *fmt, va_list args);
|
||||
void wm_string_append_string(WmString *str, const WmString *suffix);
|
||||
|
||||
void wm_string_prepend(WmString *str, const char *prefix);
|
||||
void wm_string_prepend_char(WmString *str, char c);
|
||||
|
||||
void wm_string_insert(WmString *str, size_t pos, const char *insert);
|
||||
void wm_string_insert_char(WmString *str, size_t pos, char c);
|
||||
void wm_string_insert_string(WmString *str, size_t pos, const WmString *insert);
|
||||
|
||||
void wm_string_erase(WmString *str, size_t pos, size_t len);
|
||||
void wm_string_clear(WmString *str);
|
||||
|
||||
/*==============================================================================
|
||||
* String Queries
|
||||
*============================================================================*/
|
||||
|
||||
const char* wm_string_cstr(const WmString *str);
|
||||
char* wm_string_detach(WmString *str);
|
||||
|
||||
size_t wm_string_length(const WmString *str);
|
||||
size_t wm_string_capacity(const WmString *str);
|
||||
size_t wm_string_bytes(const WmString *str);
|
||||
|
||||
bool wm_string_is_empty(const WmString *str);
|
||||
bool wm_string_is_null(const WmString *str);
|
||||
|
||||
char wm_string_char_at(const WmString *str, size_t pos);
|
||||
|
||||
/*==============================================================================
|
||||
* String Comparison
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_string_equals(const WmString *str1, const WmString *str2);
|
||||
bool wm_string_equals_cstr(const WmString *str, const char *cstr);
|
||||
|
||||
int wm_string_compare(const WmString *str1, const WmString *str2);
|
||||
int wm_string_compare_cstr(const WmString *str, const char *cstr);
|
||||
int wm_string_case_compare(const WmString *str1, const WmString *str2);
|
||||
int wm_string_case_compare_cstr(const WmString *str, const char *cstr);
|
||||
|
||||
/*==============================================================================
|
||||
* String Searching
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_string_contains(const WmString *str, const char *needle);
|
||||
bool wm_string_contains_char(const WmString *str, char c);
|
||||
|
||||
size_t wm_string_find(const WmString *str, const char *needle, size_t start);
|
||||
size_t wm_string_find_char(const WmString *str, char c, size_t start);
|
||||
size_t wm_string_find_last(const WmString *str, const char *needle);
|
||||
size_t wm_string_find_last_char(const WmString *str, char c);
|
||||
|
||||
bool wm_string_starts_with(const WmString *str, const char *prefix);
|
||||
bool wm_string_starts_with_char(const WmString *str, char c);
|
||||
bool wm_string_ends_with(const WmString *str, const char *suffix);
|
||||
bool wm_string_ends_with_char(const WmString *str, char c);
|
||||
|
||||
/*==============================================================================
|
||||
* String Modification
|
||||
*============================================================================*/
|
||||
|
||||
void wm_string_trim(WmString *str);
|
||||
void wm_string_trim_left(WmString *str);
|
||||
void wm_string_trim_right(WmString *str);
|
||||
|
||||
void wm_string_replace(WmString *str, const char *search, const char *replace);
|
||||
void wm_string_replace_char(WmString *str, char search, char replace);
|
||||
size_t wm_string_replace_all(WmString *str, const char *search, const char *replace);
|
||||
|
||||
void wm_string_to_lower(WmString *str);
|
||||
void wm_string_to_upper(WmString *str);
|
||||
|
||||
void wm_string_reverse(WmString *str);
|
||||
|
||||
/*==============================================================================
|
||||
* String Substrings
|
||||
*============================================================================*/
|
||||
|
||||
WmString* wm_string_substring(const WmString *str, size_t start, size_t len);
|
||||
WmString* wm_string_left(const WmString *str, size_t n);
|
||||
WmString* wm_string_right(const WmString *str, size_t n);
|
||||
|
||||
/*==============================================================================
|
||||
* String Splitting and Joining
|
||||
*============================================================================*/
|
||||
|
||||
WmContainer* wm_string_split(const WmString *str, const char *delimiter);
|
||||
WmContainer* wm_string_split_chars(const WmString *str, const char *delimiters);
|
||||
WmContainer* wm_string_split_lines(const WmString *str);
|
||||
|
||||
WmString* wm_string_join(const WmContainer *strings, const char *separator);
|
||||
WmString* wm_string_join_cstr(const char **strings, size_t count, const char *separator);
|
||||
|
||||
/*==============================================================================
|
||||
* String Formatting
|
||||
*============================================================================*/
|
||||
|
||||
void wm_string_printf(WmString *str, const char *fmt, ...);
|
||||
void wm_string_vprintf(WmString *str, const char *fmt, va_list args);
|
||||
|
||||
/*==============================================================================
|
||||
* String Validation
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_string_is_valid_utf8(const WmString *str);
|
||||
bool wm_string_is_ascii(const WmString *str);
|
||||
bool wm_string_is_numeric(const WmString *str);
|
||||
bool wm_string_is_integer(const WmString *str);
|
||||
bool wm_string_is_float(const WmString *str);
|
||||
|
||||
/*==============================================================================
|
||||
* String Conversion
|
||||
*============================================================================*/
|
||||
|
||||
int wm_string_to_int(const WmString *str, int default_val);
|
||||
long wm_string_to_long(const WmString *str, long default_val);
|
||||
float wm_string_to_float(const WmString *str, float default_val);
|
||||
double wm_string_to_double(const WmString *str, double default_val);
|
||||
bool wm_string_to_bool(const WmString *str, bool default_val);
|
||||
|
||||
WmString* wm_string_from_int(int val);
|
||||
WmString* wm_string_from_long(long val);
|
||||
WmString* wm_string_from_float(float val, int precision);
|
||||
WmString* wm_string_from_double(double val, int precision);
|
||||
WmString* wm_string_from_bool(bool val);
|
||||
|
||||
/*==============================================================================
|
||||
* String Hash
|
||||
*============================================================================*/
|
||||
|
||||
uint32_t wm_string_hash(const WmString *str);
|
||||
uint32_t wm_string_hash_cstr(const char *str);
|
||||
|
||||
/*==============================================================================
|
||||
* String Escaping
|
||||
*============================================================================*/
|
||||
|
||||
WmString* wm_string_escape_json(const WmString *str);
|
||||
WmString* wm_string_escape_xml(const WmString *str);
|
||||
WmString* wm_string_escape_html(const WmString *str);
|
||||
WmString* wm_string_escape_shell(const WmString *str);
|
||||
WmString* wm_string_escape_regex(const WmString *str);
|
||||
|
||||
WmString* wm_string_unescape_json(const WmString *str);
|
||||
WmString* wm_string_unescape_xml(const WmString *str);
|
||||
WmString* wm_string_unescape_html(const WmString *str);
|
||||
|
||||
/*==============================================================================
|
||||
* Static String Helpers
|
||||
*============================================================================*/
|
||||
|
||||
static inline bool wm_cstr_is_empty(const char *str) {
|
||||
return str == NULL || str[0] == '\0';
|
||||
}
|
||||
|
||||
static inline size_t wm_cstr_length(const char *str) {
|
||||
return str == NULL ? 0 : strlen(str);
|
||||
}
|
||||
|
||||
static inline bool wm_cstr_equals(const char *a, const char *b) {
|
||||
if (a == b) return true;
|
||||
if (a == NULL || b == NULL) return false;
|
||||
return strcmp(a, b) == 0;
|
||||
}
|
||||
|
||||
static inline bool wm_cstr_case_equals(const char *a, const char *b) {
|
||||
if (a == b) return true;
|
||||
if (a == NULL || b == NULL) return false;
|
||||
return strcasecmp(a, b) == 0;
|
||||
}
|
||||
|
||||
static inline void wm_cstr_copy(char *dest, const char *src, size_t size) {
|
||||
if (size == 0) return;
|
||||
strncpy(dest, src, size - 1);
|
||||
dest[size - 1] = '\0';
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_STRING_H */
|
||||
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Core Abstract Types
|
||||
* Extreme Abstraction Architecture
|
||||
*/
|
||||
|
||||
#ifndef WM_TYPES_H
|
||||
#define WM_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Version and API Information
|
||||
*============================================================================*/
|
||||
|
||||
#define WM_CORE_VERSION_MAJOR 2
|
||||
#define WM_CORE_VERSION_MINOR 0
|
||||
#define WM_CORE_VERSION_PATCH 0
|
||||
|
||||
#define WM_PLUGIN_API_VERSION 1
|
||||
|
||||
/*==============================================================================
|
||||
* Opaque Type Declarations
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WmCore WmCore;
|
||||
typedef struct WmBackend WmBackend;
|
||||
typedef struct WmPlugin WmPlugin;
|
||||
typedef struct WmPluginManager WmPluginManager;
|
||||
typedef struct WmEventBus WmEventBus;
|
||||
typedef struct WmEventSubscription WmEventSubscription;
|
||||
typedef struct WmContainer WmContainer;
|
||||
typedef struct WmIterator WmIterator;
|
||||
typedef struct WmString WmString;
|
||||
typedef struct WmRenderer WmRenderer;
|
||||
typedef struct WmSurface WmSurface;
|
||||
typedef struct WmFont WmFont;
|
||||
typedef struct WmImage WmImage;
|
||||
typedef struct WmCommand WmCommand;
|
||||
typedef struct WmCommandBuilder WmCommandBuilder;
|
||||
typedef struct WmConfigSchema WmConfigSchema;
|
||||
typedef struct WmConfigInstance WmConfigInstance;
|
||||
typedef struct WmLayoutEngine WmLayoutEngine;
|
||||
typedef struct WmPanelSystem WmPanelSystem;
|
||||
typedef struct WmAnimation WmAnimation;
|
||||
typedef struct WmTimer WmTimer;
|
||||
typedef struct WmMutex WmMutex;
|
||||
typedef struct WmCondition WmCondition;
|
||||
typedef struct WmThread WmThread;
|
||||
|
||||
/*==============================================================================
|
||||
* Basic Type Definitions
|
||||
*============================================================================*/
|
||||
|
||||
typedef uint32_t WmColor;
|
||||
typedef uint64_t WmTime;
|
||||
typedef uint32_t WmHandle;
|
||||
typedef uint32_t WmId;
|
||||
typedef WmId WmClientId;
|
||||
typedef int WmWorkspaceId;
|
||||
typedef void* WmWindowHandle;
|
||||
typedef void* WmNativeHandle;
|
||||
|
||||
/*==============================================================================
|
||||
* Window Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_WINDOW_TYPE_UNKNOWN = 0,
|
||||
WM_WINDOW_TYPE_NORMAL,
|
||||
WM_WINDOW_TYPE_DIALOG,
|
||||
WM_WINDOW_TYPE_DOCK,
|
||||
WM_WINDOW_TYPE_DESKTOP,
|
||||
WM_WINDOW_TYPE_TOOLBAR,
|
||||
WM_WINDOW_TYPE_MENU,
|
||||
WM_WINDOW_TYPE_UTILITY,
|
||||
WM_WINDOW_TYPE_SPLASH,
|
||||
WM_WINDOW_TYPE_NOTIFICATION,
|
||||
WM_WINDOW_TYPE_COMBO,
|
||||
WM_WINDOW_TYPE_DND,
|
||||
WM_WINDOW_TYPE_POPUP_MENU,
|
||||
WM_WINDOW_TYPE_TOOLTIP
|
||||
} WmWindowType;
|
||||
|
||||
/*==============================================================================
|
||||
* Geometry Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} WmPoint;
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
} WmSize;
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
} WmRect;
|
||||
|
||||
typedef struct {
|
||||
WmPoint location;
|
||||
WmSize size;
|
||||
} WmGeometry;
|
||||
|
||||
typedef struct {
|
||||
int top;
|
||||
int bottom;
|
||||
int left;
|
||||
int right;
|
||||
} WmInsets;
|
||||
|
||||
typedef struct {
|
||||
float x;
|
||||
float y;
|
||||
} WmPointF;
|
||||
|
||||
typedef struct {
|
||||
float width;
|
||||
float height;
|
||||
} WmSizeF;
|
||||
|
||||
typedef struct {
|
||||
WmPointF location;
|
||||
WmSizeF size;
|
||||
} WmGeometryF;
|
||||
|
||||
/*==============================================================================
|
||||
* Rectangle Operations (Inline)
|
||||
*============================================================================*/
|
||||
|
||||
static inline WmRect wm_rect_make(int x, int y, int width, int height) {
|
||||
WmRect r = { x, y, width, height };
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline bool wm_rect_is_empty(const WmRect *r) {
|
||||
return r == NULL || r->width <= 0 || r->height <= 0;
|
||||
}
|
||||
|
||||
static inline bool wm_rect_contains_point(const WmRect *r, int x, int y) {
|
||||
return r != NULL &&
|
||||
x >= r->x && x < r->x + r->width &&
|
||||
y >= r->y && y < r->y + r->height;
|
||||
}
|
||||
|
||||
static inline bool wm_rect_intersects(const WmRect *a, const WmRect *b) {
|
||||
if (a == NULL || b == NULL) return false;
|
||||
return !(a->x + a->width <= b->x ||
|
||||
b->x + b->width <= a->x ||
|
||||
a->y + a->height <= b->y ||
|
||||
b->y + b->height <= a->y);
|
||||
}
|
||||
|
||||
static inline WmRect wm_rect_intersection(const WmRect *a, const WmRect *b) {
|
||||
WmRect r = { 0, 0, 0, 0 };
|
||||
if (a == NULL || b == NULL) return r;
|
||||
|
||||
int x1 = a->x > b->x ? a->x : b->x;
|
||||
int y1 = a->y > b->y ? a->y : b->y;
|
||||
int x2 = (a->x + a->width) < (b->x + b->width) ? (a->x + a->width) : (b->x + b->width);
|
||||
int y2 = (a->y + a->height) < (b->y + b->height) ? (a->y + a->height) : (b->y + b->height);
|
||||
|
||||
if (x2 > x1 && y2 > y1) {
|
||||
r.x = x1;
|
||||
r.y = y1;
|
||||
r.width = x2 - x1;
|
||||
r.height = y2 - y1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline WmRect wm_rect_union(const WmRect *a, const WmRect *b) {
|
||||
WmRect r = { 0, 0, 0, 0 };
|
||||
if (a == NULL && b == NULL) return r;
|
||||
if (a == NULL) return *b;
|
||||
if (b == NULL) return *a;
|
||||
|
||||
int x1 = a->x < b->x ? a->x : b->x;
|
||||
int y1 = a->y < b->y ? a->y : b->y;
|
||||
int x2 = (a->x + a->width) > (b->x + b->width) ? (a->x + a->width) : (b->x + b->width);
|
||||
int y2 = (a->y + a->height) > (b->y + b->height) ? (a->y + a->height) : (b->y + b->height);
|
||||
|
||||
r.x = x1;
|
||||
r.y = y1;
|
||||
r.width = x2 - x1;
|
||||
r.height = y2 - y1;
|
||||
return r;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* Color Operations (Inline)
|
||||
*============================================================================*/
|
||||
|
||||
static inline WmColor wm_color_rgb(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return (0xFF << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
static inline WmColor wm_color_rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
return (a << 24) | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
static inline uint8_t wm_color_get_red(WmColor c) {
|
||||
return (c >> 16) & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint8_t wm_color_get_green(WmColor c) {
|
||||
return (c >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint8_t wm_color_get_blue(WmColor c) {
|
||||
return c & 0xFF;
|
||||
}
|
||||
|
||||
static inline uint8_t wm_color_get_alpha(WmColor c) {
|
||||
return (c >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* Client State Flags
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_CLIENT_FLAG_NONE = 0,
|
||||
WM_CLIENT_FLAG_FLOATING = (1 << 0),
|
||||
WM_CLIENT_FLAG_FULLSCREEN = (1 << 1),
|
||||
WM_CLIENT_FLAG_URGENT = (1 << 2),
|
||||
WM_CLIENT_FLAG_MINIMIZED = (1 << 3),
|
||||
WM_CLIENT_FLAG_STICKY = (1 << 4),
|
||||
WM_CLIENT_FLAG_MAXIMIZED = (1 << 5),
|
||||
WM_CLIENT_FLAG_UNMANAGING = (1 << 6),
|
||||
WM_CLIENT_FLAG_FOCUSED = (1 << 7),
|
||||
WM_CLIENT_FLAG_MAPPED = (1 << 8),
|
||||
WM_CLIENT_FLAG_DECORATED = (1 << 9),
|
||||
WM_CLIENT_FLAG_DIALOG = (1 << 10),
|
||||
WM_CLIENT_FLAG_DOCK = (1 << 11),
|
||||
WM_CLIENT_FLAG_UTILITY = (1 << 12),
|
||||
WM_CLIENT_FLAG_SPLASH = (1 << 13),
|
||||
WM_CLIENT_FLAG_MENU = (1 << 14),
|
||||
WM_CLIENT_FLAG_TOOLBAR = (1 << 15)
|
||||
} WmClientFlags;
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_LAYOUT_TYPE_TILING,
|
||||
WM_LAYOUT_TYPE_FLOATING,
|
||||
WM_LAYOUT_TYPE_MONOCLE,
|
||||
WM_LAYOUT_TYPE_GRID,
|
||||
WM_LAYOUT_TYPE_SPIRAL,
|
||||
WM_LAYOUT_TYPE_DWINDLE,
|
||||
WM_LAYOUT_TYPE_MAX
|
||||
} WmLayoutType;
|
||||
|
||||
/*==============================================================================
|
||||
* Panel Positions
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_PANEL_POSITION_TOP,
|
||||
WM_PANEL_POSITION_BOTTOM,
|
||||
WM_PANEL_POSITION_LEFT,
|
||||
WM_PANEL_POSITION_RIGHT
|
||||
} WmPanelPosition;
|
||||
|
||||
/*==============================================================================
|
||||
* Event Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
/* Window events */
|
||||
WM_EVENT_NONE = 0,
|
||||
WM_EVENT_WINDOW_CREATED,
|
||||
WM_EVENT_WINDOW_DESTROYED,
|
||||
WM_EVENT_WINDOW_MAPPED,
|
||||
WM_EVENT_WINDOW_UNMAPPED,
|
||||
WM_EVENT_WINDOW_CONFIGURED,
|
||||
WM_EVENT_WINDOW_FOCUSED,
|
||||
WM_EVENT_WINDOW_UNFOCUSED,
|
||||
WM_EVENT_WINDOW_RAISED,
|
||||
WM_EVENT_WINDOW_LOWERED,
|
||||
WM_EVENT_WINDOW_MINIMIZED,
|
||||
WM_EVENT_WINDOW_RESTORED,
|
||||
WM_EVENT_WINDOW_MAXIMIZED,
|
||||
WM_EVENT_WINDOW_UNMAXIMIZED,
|
||||
WM_EVENT_WINDOW_FULLSCREENED,
|
||||
WM_EVENT_WINDOW_UNFULLSCREENED,
|
||||
WM_EVENT_WINDOW_FLOATING_CHANGED,
|
||||
WM_EVENT_WINDOW_PROPERTY_CHANGED,
|
||||
WM_EVENT_WINDOW_STATE_CHANGED,
|
||||
WM_EVENT_WINDOW_TITLE_CHANGED,
|
||||
WM_EVENT_WINDOW_CLASS_CHANGED,
|
||||
WM_EVENT_WINDOW_ROLE_CHANGED,
|
||||
WM_EVENT_WINDOW_URGENCY_CHANGED,
|
||||
WM_EVENT_WINDOW_MOVED,
|
||||
WM_EVENT_WINDOW_RESIZED,
|
||||
|
||||
/* Workspace events */
|
||||
WM_EVENT_WORKSPACE_CREATED,
|
||||
WM_EVENT_WORKSPACE_DESTROYED,
|
||||
WM_EVENT_WORKSPACE_SWITCHED,
|
||||
WM_EVENT_WORKSPACE_RENAMED,
|
||||
WM_EVENT_WORKSPACE_LAYOUT_CHANGED,
|
||||
WM_EVENT_WORKSPACE_MASTER_RATIO_CHANGED,
|
||||
WM_EVENT_WORKSPACE_MASTER_COUNT_CHANGED,
|
||||
|
||||
/* Client/workspace relationship */
|
||||
WM_EVENT_CLIENT_ADDED_TO_WORKSPACE,
|
||||
WM_EVENT_CLIENT_REMOVED_FROM_WORKSPACE,
|
||||
|
||||
/* Input events */
|
||||
WM_EVENT_KEY_PRESSED,
|
||||
WM_EVENT_KEY_RELEASED,
|
||||
WM_EVENT_BUTTON_PRESSED,
|
||||
WM_EVENT_BUTTON_RELEASED,
|
||||
WM_EVENT_MOTION,
|
||||
WM_EVENT_ENTER,
|
||||
WM_EVENT_LEAVE,
|
||||
WM_EVENT_SCROLL,
|
||||
|
||||
/* System events */
|
||||
WM_EVENT_MONITOR_ADDED,
|
||||
WM_EVENT_MONITOR_REMOVED,
|
||||
WM_EVENT_MONITOR_CONFIGURED,
|
||||
WM_EVENT_SCREEN_RESIZED,
|
||||
|
||||
/* Configuration events */
|
||||
WM_EVENT_CONFIG_RELOADED,
|
||||
WM_EVENT_CONFIG_CHANGED,
|
||||
|
||||
/* Lifecycle events */
|
||||
WM_EVENT_WM_STARTED,
|
||||
WM_EVENT_WM_SHUTDOWN,
|
||||
WM_EVENT_WM_READY,
|
||||
|
||||
/* Plugin events */
|
||||
WM_EVENT_PLUGIN_LOADED,
|
||||
WM_EVENT_PLUGIN_UNLOADED,
|
||||
WM_EVENT_PLUGIN_ERROR,
|
||||
|
||||
/* Custom events for plugins */
|
||||
WM_EVENT_CUSTOM = 1000
|
||||
} WmEventType;
|
||||
|
||||
/*==============================================================================
|
||||
* Container Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_CONTAINER_LIST,
|
||||
WM_CONTAINER_ARRAY,
|
||||
WM_CONTAINER_HASHMAP,
|
||||
WM_CONTAINER_QUEUE,
|
||||
WM_CONTAINER_STACK,
|
||||
WM_CONTAINER_TREE
|
||||
} WmContainerType;
|
||||
|
||||
/*==============================================================================
|
||||
* Command Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_COMMAND_NONE = 0,
|
||||
|
||||
/* Window commands */
|
||||
WM_COMMAND_WINDOW_FOCUS,
|
||||
WM_COMMAND_WINDOW_MOVE,
|
||||
WM_COMMAND_WINDOW_RESIZE,
|
||||
WM_COMMAND_WINDOW_MOVE_RESIZE,
|
||||
WM_COMMAND_WINDOW_CLOSE,
|
||||
WM_COMMAND_WINDOW_KILL,
|
||||
WM_COMMAND_WINDOW_MINIMIZE,
|
||||
WM_COMMAND_WINDOW_RESTORE,
|
||||
WM_COMMAND_WINDOW_MAXIMIZE,
|
||||
WM_COMMAND_WINDOW_UNMAXIMIZE,
|
||||
WM_COMMAND_WINDOW_FULLSCREEN,
|
||||
WM_COMMAND_WINDOW_UNFULLSCREEN,
|
||||
WM_COMMAND_WINDOW_FLOAT,
|
||||
WM_COMMAND_WINDOW_UNFLOAT,
|
||||
WM_COMMAND_WINDOW_RAISE,
|
||||
WM_COMMAND_WINDOW_LOWER,
|
||||
WM_COMMAND_WINDOW_SET_WORKSPACE,
|
||||
|
||||
/* Workspace commands */
|
||||
WM_COMMAND_WORKSPACE_SWITCH,
|
||||
WM_COMMAND_WORKSPACE_CREATE,
|
||||
WM_COMMAND_WORKSPACE_DESTROY,
|
||||
WM_COMMAND_WORKSPACE_RENAME,
|
||||
WM_COMMAND_WORKSPACE_SET_LAYOUT,
|
||||
WM_COMMAND_WORKSPACE_ADJUST_MASTER_RATIO,
|
||||
WM_COMMAND_WORKSPACE_ADJUST_MASTER_COUNT,
|
||||
WM_COMMAND_WORKSPACE_SWAP,
|
||||
|
||||
/* Client manipulation */
|
||||
WM_COMMAND_CLIENT_SWAP,
|
||||
WM_COMMAND_CLIENT_SWAP_MASTER,
|
||||
WM_COMMAND_CLIENT_CYCLE,
|
||||
WM_COMMAND_CLIENT_CYCLE_REVERSE,
|
||||
|
||||
/* System commands */
|
||||
WM_COMMAND_RELOAD_CONFIG,
|
||||
WM_COMMAND_QUIT,
|
||||
WM_COMMAND_RESTART,
|
||||
|
||||
/* Plugin commands */
|
||||
WM_COMMAND_PLUGIN_LOAD,
|
||||
WM_COMMAND_PLUGIN_UNLOAD,
|
||||
WM_COMMAND_PLUGIN_ENABLE,
|
||||
WM_COMMAND_PLUGIN_DISABLE
|
||||
} WmCommandType;
|
||||
|
||||
/*==============================================================================
|
||||
* Result/Error Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_RESULT_OK = 0,
|
||||
WM_RESULT_ERROR_GENERIC = -1,
|
||||
WM_RESULT_ERROR_INVALID_ARG = -2,
|
||||
WM_RESULT_ERROR_NO_MEMORY = -3,
|
||||
WM_RESULT_ERROR_NOT_FOUND = -4,
|
||||
WM_RESULT_ERROR_EXISTS = -5,
|
||||
WM_RESULT_ERROR_PERMISSION = -6,
|
||||
WM_RESULT_ERROR_NOT_SUPPORTED = -7,
|
||||
WM_RESULT_ERROR_NOT_IMPLEMENTED = -8,
|
||||
WM_RESULT_ERROR_BACKEND = -9,
|
||||
WM_RESULT_ERROR_PLUGIN = -10,
|
||||
WM_RESULT_ERROR_TIMEOUT = -11,
|
||||
WM_RESULT_ERROR_CANCELED = -12
|
||||
} WmResult;
|
||||
|
||||
/*==============================================================================
|
||||
* Callback Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef void (*WmDestroyFunc)(void *data);
|
||||
typedef int (*WmCompareFunc)(const void *a, const void *b);
|
||||
typedef uint32_t (*WmHashFunc)(const void *key);
|
||||
typedef void* (*WmCloneFunc)(const void *data);
|
||||
typedef void (*WmEventHandler)(WmEventType type, const void *event_data, void *user_data);
|
||||
typedef void (*WmTimerCallback)(WmTimer *timer, void *user_data);
|
||||
typedef void* (*WmThreadFunc)(void *arg);
|
||||
|
||||
/*==============================================================================
|
||||
* Memory Management Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef void* (*WmAllocFunc)(size_t size);
|
||||
typedef void* (*WmReallocFunc)(void *ptr, size_t old_size, size_t new_size);
|
||||
typedef void (*WmFreeFunc)(void *ptr);
|
||||
|
||||
typedef struct {
|
||||
WmAllocFunc alloc;
|
||||
WmReallocFunc realloc;
|
||||
WmFreeFunc free;
|
||||
} WmAllocator;
|
||||
|
||||
/*==============================================================================
|
||||
* Logging Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_LOG_LEVEL_DEBUG,
|
||||
WM_LOG_LEVEL_INFO,
|
||||
WM_LOG_LEVEL_WARN,
|
||||
WM_LOG_LEVEL_ERROR,
|
||||
WM_LOG_LEVEL_FATAL
|
||||
} WmLogLevel;
|
||||
|
||||
typedef void (*WmLogHandler)(WmLogLevel level, const char *file, int line,
|
||||
const char *func, const char *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_TYPES_H */
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Abstract Workspace Interface
|
||||
*/
|
||||
|
||||
#ifndef WM_WORKSPACE_H
|
||||
#define WM_WORKSPACE_H
|
||||
|
||||
#include "wm_types.h"
|
||||
#include "wm_client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Workspace Configuration
|
||||
*============================================================================*/
|
||||
|
||||
#define WM_MAX_WORKSPACES 32
|
||||
|
||||
typedef struct {
|
||||
WmLayoutType layout_type;
|
||||
float master_ratio;
|
||||
int master_count;
|
||||
char name[64];
|
||||
bool persistent;
|
||||
WmString *custom_data;
|
||||
} WmWorkspaceConfig;
|
||||
|
||||
/*==============================================================================
|
||||
* Workspace Lifecycle
|
||||
*============================================================================*/
|
||||
|
||||
bool wm_workspace_exists(WmCore *core, WmWorkspaceId id);
|
||||
WmWorkspaceId wm_workspace_create(WmCore *core, const char *name);
|
||||
void wm_workspace_destroy(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
void wm_workspace_init_all(WmCore *core);
|
||||
void wm_workspace_cleanup_all(WmCore *core);
|
||||
|
||||
/*==============================================================================
|
||||
* Workspace Properties
|
||||
*============================================================================*/
|
||||
|
||||
const char* wm_workspace_get_name(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_set_name(WmCore *core, WmWorkspaceId id, const char *name);
|
||||
|
||||
bool wm_workspace_is_empty(WmCore *core, WmWorkspaceId id);
|
||||
size_t wm_workspace_get_client_count(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Current Workspace
|
||||
*============================================================================*/
|
||||
|
||||
WmWorkspaceId wm_workspace_get_current(WmCore *core);
|
||||
void wm_workspace_set_current(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_switch(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
void wm_workspace_switch_next(WmCore *core);
|
||||
void wm_workspace_switch_prev(WmCore *core);
|
||||
|
||||
/*==============================================================================
|
||||
* Client Management
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_add_client(WmCore *core, WmWorkspaceId id, AbstractClient *client);
|
||||
void wm_workspace_remove_client(WmCore *core, WmWorkspaceId id, AbstractClient *client);
|
||||
void wm_workspace_move_client(WmCore *core, AbstractClient *client, WmWorkspaceId to_workspace);
|
||||
|
||||
WmContainer* wm_workspace_get_clients(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
AbstractClient* wm_workspace_get_focused_client(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_set_focused_client(WmCore *core, WmWorkspaceId id, AbstractClient *client);
|
||||
|
||||
AbstractClient* wm_workspace_get_first_client(WmCore *core, WmWorkspaceId id);
|
||||
AbstractClient* wm_workspace_get_last_client(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Management
|
||||
*============================================================================*/
|
||||
|
||||
WmLayoutType wm_workspace_get_layout(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_set_layout(WmCore *core, WmWorkspaceId id, WmLayoutType layout);
|
||||
void wm_workspace_cycle_layout(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_cycle_layout_reverse(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
float wm_workspace_get_master_ratio(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_set_master_ratio(WmCore *core, WmWorkspaceId id, float ratio);
|
||||
void wm_workspace_adjust_master_ratio(WmCore *core, WmWorkspaceId id, float delta);
|
||||
|
||||
int wm_workspace_get_master_count(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_set_master_count(WmCore *core, WmWorkspaceId id, int count);
|
||||
void wm_workspace_adjust_master_count(WmCore *core, WmWorkspaceId id, int delta);
|
||||
|
||||
/*==============================================================================
|
||||
* Workspace Arrangement
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_arrange(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_arrange_all(WmCore *core);
|
||||
void wm_workspace_arrange_current(WmCore *core);
|
||||
|
||||
WmRect wm_workspace_get_arrange_area(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Workspace Visibility
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_show(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_hide(WmCore *core, WmWorkspaceId id);
|
||||
bool wm_workspace_is_visible(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Focus Management
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_focus_next(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_focus_prev(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_focus_master(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* MRU (Most Recently Used) Stack
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_mru_push(WmCore *core, WmWorkspaceId id, AbstractClient *client);
|
||||
void wm_workspace_mru_remove(WmCore *core, WmWorkspaceId id, AbstractClient *client);
|
||||
AbstractClient* wm_workspace_mru_get_next(WmCore *core, WmWorkspaceId id, AbstractClient *current);
|
||||
AbstractClient* wm_workspace_mru_get_prev(WmCore *core, WmWorkspaceId id, AbstractClient *current);
|
||||
|
||||
/*==============================================================================
|
||||
* Alt-Tab Navigation
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_alt_tab_start(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_alt_tab_next(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_alt_tab_prev(WmCore *core, WmWorkspaceId id);
|
||||
void wm_workspace_alt_tab_end(WmCore *core, WmWorkspaceId id);
|
||||
bool wm_workspace_alt_tab_is_active(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Workspace Iteration
|
||||
*============================================================================*/
|
||||
|
||||
WmWorkspaceId wm_workspace_get_first(WmCore *core);
|
||||
WmWorkspaceId wm_workspace_get_last(WmCore *core);
|
||||
WmWorkspaceId wm_workspace_get_next(WmCore *core, WmWorkspaceId id);
|
||||
WmWorkspaceId wm_workspace_get_prev(WmCore *core, WmWorkspaceId id);
|
||||
|
||||
/*==============================================================================
|
||||
* Configuration
|
||||
*============================================================================*/
|
||||
|
||||
void wm_workspace_save_config(WmCore *core, WmWorkspaceId id, const WmWorkspaceConfig *config);
|
||||
bool wm_workspace_load_config(WmCore *core, WmWorkspaceId id, WmWorkspaceConfig *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WM_WORKSPACE_H */
|
||||
+5
-1
@@ -49,6 +49,9 @@ typedef enum {
|
||||
LAYOUT_TILING,
|
||||
LAYOUT_FLOATING,
|
||||
LAYOUT_MONOCLE,
|
||||
LAYOUT_CENTERED_MASTER,
|
||||
LAYOUT_COLUMNS,
|
||||
LAYOUT_FIBONACCI,
|
||||
LAYOUT_COUNT
|
||||
} LayoutType;
|
||||
|
||||
@@ -64,7 +67,8 @@ typedef enum {
|
||||
CLIENT_URGENT = (1 << 2),
|
||||
CLIENT_MINIMIZED = (1 << 3),
|
||||
CLIENT_STICKY = (1 << 4),
|
||||
CLIENT_MAXIMIZED = (1 << 5)
|
||||
CLIENT_MAXIMIZED = (1 << 5),
|
||||
CLIENT_UNMANAGING = (1 << 6) /* Being destroyed, skip processing */
|
||||
} ClientFlags;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -89,6 +89,17 @@ void key_start_demo(void);
|
||||
void key_show_desktop(void);
|
||||
void key_move_to_workspace_prev(void);
|
||||
void key_move_to_workspace_next(void);
|
||||
void key_kill_all_clients(void);
|
||||
void key_move_window_left(void);
|
||||
void key_move_window_right(void);
|
||||
void key_move_window_up(void);
|
||||
void key_move_window_down(void);
|
||||
void key_resize_window_left(void);
|
||||
void key_resize_window_right(void);
|
||||
void key_resize_window_up(void);
|
||||
void key_resize_window_down(void);
|
||||
void key_set_mark(void);
|
||||
void key_goto_mark(void);
|
||||
|
||||
void tutorial_start(void);
|
||||
void tutorial_stop(void);
|
||||
|
||||
@@ -13,6 +13,9 @@ void layout_arrange(int workspace);
|
||||
void layout_arrange_tiling(int workspace);
|
||||
void layout_arrange_floating(int workspace);
|
||||
void layout_arrange_monocle(int workspace);
|
||||
void layout_arrange_centered_master(int workspace);
|
||||
void layout_arrange_columns(int workspace);
|
||||
void layout_arrange_fibonacci(int workspace);
|
||||
|
||||
int layout_get_usable_area(int *x, int *y, int *width, int *height);
|
||||
int layout_count_tiled_clients(int workspace);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Window marks for quick navigation
|
||||
*/
|
||||
|
||||
#ifndef DWN_MARKS_H
|
||||
#define DWN_MARKS_H
|
||||
|
||||
#include "dwn.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAX_MARKS 26
|
||||
|
||||
void marks_init(void);
|
||||
void marks_cleanup(void);
|
||||
|
||||
void marks_set(char mark, Client *client);
|
||||
Client *marks_get(char mark);
|
||||
void marks_clear(char mark);
|
||||
void marks_clear_all(void);
|
||||
void marks_remove_client(Client *client);
|
||||
|
||||
bool marks_is_waiting_for_mark(void);
|
||||
bool marks_is_waiting_for_goto(void);
|
||||
void marks_start_set_mode(void);
|
||||
void marks_start_goto_mode(void);
|
||||
void marks_cancel_mode(void);
|
||||
bool marks_handle_key(char key);
|
||||
|
||||
char marks_get_mark_for_client(Client *client);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Built-in Layout Registration
|
||||
*/
|
||||
|
||||
#ifndef BUILTIN_LAYOUTS_H
|
||||
#define BUILTIN_LAYOUTS_H
|
||||
|
||||
#include "plugins/layout_plugin.h"
|
||||
#include "dwn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize and register all built-in layouts.
|
||||
* Called during DWN startup.
|
||||
*/
|
||||
bool wm_layouts_builtin_init(void);
|
||||
|
||||
/**
|
||||
* Get a layout plugin by legacy LayoutType.
|
||||
*/
|
||||
LayoutPlugin* wm_layout_get_by_type(LayoutManager *mgr, LayoutType type);
|
||||
|
||||
/**
|
||||
* Bridge function to arrange a workspace using the plugin system.
|
||||
*/
|
||||
bool wm_layout_arrange_workspace(LayoutManager *mgr, int workspace, LayoutType type);
|
||||
|
||||
/**
|
||||
* Get symbol for a layout type.
|
||||
*/
|
||||
const char* wm_layout_get_symbol_for_type(LayoutType type);
|
||||
|
||||
/**
|
||||
* Get name for a layout type.
|
||||
*/
|
||||
const char* wm_layout_get_name_for_type(LayoutType type);
|
||||
|
||||
/**
|
||||
* Get LayoutType from name.
|
||||
*/
|
||||
LayoutType wm_layout_type_from_name(const char *name);
|
||||
|
||||
/* External layout interface getters */
|
||||
const LayoutPluginInterface* wm_layout_tiling_get_interface(void);
|
||||
const LayoutPluginInterface* wm_layout_floating_get_interface(void);
|
||||
const LayoutPluginInterface* wm_layout_monocle_get_interface(void);
|
||||
const LayoutPluginInterface* wm_layout_grid_get_interface(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BUILTIN_LAYOUTS_H */
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Layout Plugin Interface
|
||||
*/
|
||||
|
||||
#ifndef LAYOUT_PLUGIN_H
|
||||
#define LAYOUT_PLUGIN_H
|
||||
|
||||
#include "core/wm_types.h"
|
||||
#include "core/wm_client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Plugin API Version
|
||||
*============================================================================*/
|
||||
|
||||
#define WM_LAYOUT_PLUGIN_API_VERSION 1
|
||||
|
||||
/*==============================================================================
|
||||
* Forward Declarations
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct LayoutPlugin LayoutPlugin;
|
||||
typedef struct LayoutContext LayoutContext;
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Geometry
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Layout geometry for a single client.
|
||||
*/
|
||||
typedef struct {
|
||||
int x, y;
|
||||
int width, height;
|
||||
bool floating; /* If true, layout doesn't manage this client */
|
||||
bool fullscreen; /* If true, client should be fullscreen */
|
||||
bool hidden; /* If true, client should be hidden */
|
||||
} WmLayoutGeometry;
|
||||
|
||||
/**
|
||||
* Work area for layout calculations.
|
||||
*/
|
||||
typedef struct {
|
||||
int x, y;
|
||||
int width, height;
|
||||
int padding_top;
|
||||
int padding_bottom;
|
||||
int padding_left;
|
||||
int padding_right;
|
||||
int gap;
|
||||
} WmLayoutWorkArea;
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Configuration
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Layout configuration parameter.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *description;
|
||||
union {
|
||||
int int_value;
|
||||
float float_value;
|
||||
bool bool_value;
|
||||
const char *string_value;
|
||||
} default_value;
|
||||
enum {
|
||||
WM_LAYOUT_PARAM_INT,
|
||||
WM_LAYOUT_PARAM_FLOAT,
|
||||
WM_LAYOUT_PARAM_BOOL,
|
||||
WM_LAYOUT_PARAM_STRING,
|
||||
WM_LAYOUT_PARAM_CHOICE
|
||||
} type;
|
||||
/* For PARAM_CHOICE */
|
||||
const char **choices;
|
||||
int num_choices;
|
||||
} WmLayoutParameter;
|
||||
|
||||
/**
|
||||
* Layout configuration instance.
|
||||
*/
|
||||
typedef struct {
|
||||
WmLayoutParameter *parameters;
|
||||
int num_parameters;
|
||||
void *user_data; /* Plugin can store parsed config here */
|
||||
} WmLayoutConfig;
|
||||
|
||||
/*==============================================================================
|
||||
* Layout State
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Opaque layout state per workspace.
|
||||
* Layout plugins can store workspace-specific state here.
|
||||
*/
|
||||
typedef struct WmLayoutState WmLayoutState;
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Context
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Context passed to layout operations.
|
||||
*/
|
||||
struct LayoutContext {
|
||||
/* Workspace info */
|
||||
WmWorkspaceId workspace;
|
||||
WmLayoutWorkArea work_area;
|
||||
|
||||
/* Client counts */
|
||||
int client_count;
|
||||
int master_count;
|
||||
int stack_count;
|
||||
|
||||
/* Layout parameters */
|
||||
float master_ratio;
|
||||
int master_count_target;
|
||||
int gap;
|
||||
|
||||
/* Configuration */
|
||||
WmLayoutConfig *config;
|
||||
|
||||
/* Layout state (managed by plugin) */
|
||||
WmLayoutState *state;
|
||||
|
||||
/* User data (for plugin use) */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Plugin Interface
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Layout plugin interface vtable.
|
||||
* All layouts must implement these functions.
|
||||
*/
|
||||
typedef struct {
|
||||
/* Version check */
|
||||
int api_version;
|
||||
|
||||
/* Metadata */
|
||||
const char *name;
|
||||
const char *description;
|
||||
const char *author;
|
||||
const char *version;
|
||||
|
||||
/* Configuration */
|
||||
WmLayoutParameter *parameters;
|
||||
int num_parameters;
|
||||
|
||||
/* Lifecycle */
|
||||
bool (*init)(LayoutPlugin *plugin);
|
||||
void (*shutdown)(LayoutPlugin *plugin);
|
||||
|
||||
/* State management */
|
||||
WmLayoutState* (*state_create)(LayoutPlugin *plugin, WmWorkspaceId workspace);
|
||||
void (*state_destroy)(LayoutPlugin *plugin, WmLayoutState *state);
|
||||
void (*state_reset)(LayoutPlugin *plugin, WmLayoutState *state);
|
||||
|
||||
/* Configuration */
|
||||
bool (*config_parse)(LayoutPlugin *plugin, WmLayoutConfig *config,
|
||||
const char *key, const char *value);
|
||||
void (*config_apply)(LayoutPlugin *plugin, WmLayoutConfig *config);
|
||||
|
||||
/* Layout calculation */
|
||||
bool (*arrange)(LayoutPlugin *plugin, LayoutContext *ctx,
|
||||
AbstractClient **clients, int num_clients,
|
||||
WmLayoutGeometry *geometries);
|
||||
|
||||
/* Client operations */
|
||||
void (*client_added)(LayoutPlugin *plugin, LayoutContext *ctx,
|
||||
AbstractClient *client);
|
||||
void (*client_removed)(LayoutPlugin *plugin, LayoutContext *ctx,
|
||||
AbstractClient *client);
|
||||
void (*client_floating_changed)(LayoutPlugin *plugin, LayoutContext *ctx,
|
||||
AbstractClient *client, bool floating);
|
||||
|
||||
/* Layout manipulation */
|
||||
void (*inc_master)(LayoutPlugin *plugin, LayoutContext *ctx, int delta);
|
||||
void (*set_master_ratio)(LayoutPlugin *plugin, LayoutContext *ctx, float ratio);
|
||||
void (*set_master_count)(LayoutPlugin *plugin, LayoutContext *ctx, int count);
|
||||
void (*swap_master)(LayoutPlugin *plugin, LayoutContext *ctx);
|
||||
void (*rotate)(LayoutPlugin *plugin, LayoutContext *ctx, bool clockwise);
|
||||
|
||||
/* Mouse resizing support */
|
||||
void (*resize_master)(LayoutPlugin *plugin, LayoutContext *ctx,
|
||||
int x, int y, int *new_master_count, float *new_ratio);
|
||||
|
||||
} LayoutPluginInterface;
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Plugin Structure
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Layout plugin instance.
|
||||
*/
|
||||
struct LayoutPlugin {
|
||||
/* Interface vtable */
|
||||
const LayoutPluginInterface *interface;
|
||||
|
||||
/* Plugin handle (for dynamic loading) */
|
||||
void *handle;
|
||||
|
||||
/* Plugin path */
|
||||
char *path;
|
||||
|
||||
/* Enabled state */
|
||||
bool enabled;
|
||||
|
||||
/* Global configuration */
|
||||
WmLayoutConfig config;
|
||||
|
||||
/* Per-workspace states */
|
||||
WmLayoutState **workspace_states;
|
||||
int num_workspaces;
|
||||
|
||||
/* Plugin-private data */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Manager
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Layout manager handles all loaded layouts.
|
||||
*/
|
||||
typedef struct LayoutManager LayoutManager;
|
||||
|
||||
/**
|
||||
* Get the global layout manager.
|
||||
*/
|
||||
LayoutManager* wm_layout_manager_get(void);
|
||||
|
||||
/**
|
||||
* Initialize the layout manager.
|
||||
*/
|
||||
bool wm_layout_manager_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown the layout manager.
|
||||
*/
|
||||
void wm_layout_manager_shutdown(void);
|
||||
|
||||
/**
|
||||
* Register a layout plugin.
|
||||
*/
|
||||
bool wm_layout_manager_register(LayoutManager *mgr, LayoutPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Unregister a layout plugin.
|
||||
*/
|
||||
void wm_layout_manager_unregister(LayoutManager *mgr, LayoutPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Load a layout plugin from a file.
|
||||
*/
|
||||
LayoutPlugin* wm_layout_manager_load(LayoutManager *mgr, const char *path);
|
||||
|
||||
/**
|
||||
* Unload a layout plugin.
|
||||
*/
|
||||
void wm_layout_manager_unload(LayoutManager *mgr, LayoutPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Get a loaded layout by name.
|
||||
*/
|
||||
LayoutPlugin* wm_layout_manager_get_layout(LayoutManager *mgr, const char *name);
|
||||
|
||||
/**
|
||||
* Get the default layout.
|
||||
*/
|
||||
LayoutPlugin* wm_layout_manager_get_default(LayoutManager *mgr);
|
||||
|
||||
/**
|
||||
* Set the default layout.
|
||||
*/
|
||||
void wm_layout_manager_set_default(LayoutManager *mgr, LayoutPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Get list of available layouts.
|
||||
*/
|
||||
const char** wm_layout_manager_list(LayoutManager *mgr, int *count);
|
||||
|
||||
/*==============================================================================
|
||||
* Layout Operations
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Apply a layout to a workspace.
|
||||
*/
|
||||
bool wm_layout_arrange(LayoutPlugin *plugin, WmWorkspaceId workspace);
|
||||
|
||||
/**
|
||||
* Apply layout to specific clients.
|
||||
*/
|
||||
bool wm_layout_arrange_clients(LayoutPlugin *plugin, LayoutContext *ctx,
|
||||
AbstractClient **clients, int num_clients);
|
||||
|
||||
/**
|
||||
* Create a layout context for a workspace.
|
||||
*/
|
||||
bool wm_layout_context_init(LayoutContext *ctx, WmWorkspaceId workspace);
|
||||
|
||||
/**
|
||||
* Clean up a layout context.
|
||||
*/
|
||||
void wm_layout_context_cleanup(LayoutContext *ctx);
|
||||
|
||||
/*==============================================================================
|
||||
* Built-in Layouts
|
||||
*============================================================================*/
|
||||
|
||||
/* Tiling layout */
|
||||
extern const LayoutPluginInterface wm_layout_tiling;
|
||||
|
||||
/* Floating layout */
|
||||
extern const LayoutPluginInterface wm_layout_floating;
|
||||
|
||||
/* Monocle (maximized) layout */
|
||||
extern const LayoutPluginInterface wm_layout_monocle;
|
||||
|
||||
/* Grid layout */
|
||||
extern const LayoutPluginInterface wm_layout_grid;
|
||||
|
||||
/* Spiral layout */
|
||||
extern const LayoutPluginInterface wm_layout_spiral;
|
||||
|
||||
/* Dwindle layout */
|
||||
extern const LayoutPluginInterface wm_layout_dwindle;
|
||||
|
||||
/*==============================================================================
|
||||
* Plugin Entry Point
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Layout plugins must export this function.
|
||||
*/
|
||||
typedef const LayoutPluginInterface* (*LayoutPluginEntryFunc)(void);
|
||||
|
||||
#define WM_LAYOUT_PLUGIN_ENTRY "wm_layout_plugin_entry"
|
||||
|
||||
/*==============================================================================
|
||||
* Helper Macros
|
||||
*============================================================================*/
|
||||
|
||||
#define WM_LAYOUT_REGISTER(name, iface) \
|
||||
__attribute__((unused)) static const LayoutPluginInterface* wm_layout_plugin_entry(void) { return &(iface); }
|
||||
|
||||
/* Typedef for built-in layout getters */
|
||||
typedef const LayoutPluginInterface* (*WmLayoutBuiltinFunc)(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LAYOUT_PLUGIN_H */
|
||||
@@ -0,0 +1,435 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* Widget Plugin Interface
|
||||
* Panel components (taskbar, clock, workspaces, etc.)
|
||||
*/
|
||||
|
||||
#ifndef WIDGET_PLUGIN_H
|
||||
#define WIDGET_PLUGIN_H
|
||||
|
||||
#include "core/wm_types.h"
|
||||
#include "core/wm_client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Plugin API Version
|
||||
*============================================================================*/
|
||||
|
||||
#define WM_WIDGET_PLUGIN_API_VERSION 1
|
||||
|
||||
/*==============================================================================
|
||||
* Forward Declarations
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WidgetPlugin WidgetPlugin;
|
||||
typedef struct WidgetContext WidgetContext;
|
||||
typedef struct WidgetInstance WidgetInstance;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Position
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_WIDGET_POSITION_LEFT,
|
||||
WM_WIDGET_POSITION_CENTER,
|
||||
WM_WIDGET_POSITION_RIGHT
|
||||
} WmWidgetPosition;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Size Constraints
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
int min_width;
|
||||
int min_height;
|
||||
int max_width;
|
||||
int max_height;
|
||||
bool expand_horizontal; /* Take available horizontal space */
|
||||
bool expand_vertical; /* Take available vertical space */
|
||||
} WmWidgetConstraints;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Geometry
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
int width, height;
|
||||
} WmWidgetGeometry;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget State
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_WIDGET_STATE_NORMAL = 0,
|
||||
WM_WIDGET_STATE_HOVERED = (1 << 0),
|
||||
WM_WIDGET_STATE_PRESSED = (1 << 1),
|
||||
WM_WIDGET_STATE_ACTIVE = (1 << 2),
|
||||
WM_WIDGET_STATE_DISABLED = (1 << 3),
|
||||
WM_WIDGET_STATE_HIDDEN = (1 << 4),
|
||||
WM_WIDGET_STATE_URGENT = (1 << 5)
|
||||
} WmWidgetState;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Context
|
||||
*============================================================================*/
|
||||
|
||||
struct WidgetContext {
|
||||
/* Position in panel */
|
||||
WmWidgetPosition position;
|
||||
|
||||
/* Geometry */
|
||||
WmWidgetGeometry geometry;
|
||||
WmWidgetConstraints constraints;
|
||||
|
||||
/* Panel info */
|
||||
WmRect panel_geometry;
|
||||
bool is_top_panel;
|
||||
|
||||
/* Rendering context */
|
||||
void *render_context; /* Backend-specific (X11 GC, cairo, etc.) */
|
||||
WmColor bg_color;
|
||||
WmColor fg_color;
|
||||
|
||||
/* Font */
|
||||
void *font; /* Opaque font handle */
|
||||
int font_size;
|
||||
|
||||
/* User data */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Event Types
|
||||
*============================================================================*/
|
||||
|
||||
typedef enum {
|
||||
WM_WIDGET_EVENT_NONE,
|
||||
WM_WIDGET_EVENT_MOUSE_ENTER,
|
||||
WM_WIDGET_EVENT_MOUSE_LEAVE,
|
||||
WM_WIDGET_EVENT_MOUSE_MOVE,
|
||||
WM_WIDGET_EVENT_BUTTON_PRESS,
|
||||
WM_WIDGET_EVENT_BUTTON_RELEASE,
|
||||
WM_WIDGET_EVENT_SCROLL,
|
||||
WM_WIDGET_EVENT_KEY_PRESS,
|
||||
WM_WIDGET_EVENT_FOCUS_IN,
|
||||
WM_WIDGET_EVENT_FOCUS_OUT,
|
||||
WM_WIDGET_EVENT_UPDATE, /* Request to redraw */
|
||||
WM_WIDGET_EVENT_CONFIGURE, /* Size/position changed */
|
||||
WM_WIDGET_EVENT_DATA_CHANGED /* External data changed */
|
||||
} WmWidgetEventType;
|
||||
|
||||
typedef struct {
|
||||
WmWidgetEventType type;
|
||||
WmWidgetGeometry widget_geometry;
|
||||
union {
|
||||
struct { int x, y; } point;
|
||||
struct { int button; int x, y; } button;
|
||||
struct { int delta; bool horizontal; } scroll;
|
||||
struct { unsigned int keycode; unsigned int state; } key;
|
||||
} data;
|
||||
} WmWidgetEvent;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Configuration
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *value;
|
||||
} WmWidgetConfigOption;
|
||||
|
||||
typedef struct {
|
||||
WmWidgetConfigOption *options;
|
||||
int num_options;
|
||||
} WmWidgetConfig;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Information
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
const char *id; /* Unique identifier */
|
||||
const char *name; /* Display name */
|
||||
const char *description; /* Description */
|
||||
const char *author; /* Author */
|
||||
const char *version; /* Version */
|
||||
|
||||
/* Default constraints */
|
||||
WmWidgetConstraints default_constraints;
|
||||
|
||||
/* Default position */
|
||||
WmWidgetPosition default_position;
|
||||
|
||||
/* Configuration schema */
|
||||
const char **config_options; /* List of accepted config option names */
|
||||
int num_config_options;
|
||||
} WmWidgetInfo;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Plugin Interface
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct {
|
||||
/* Version check */
|
||||
int api_version;
|
||||
|
||||
/* Metadata */
|
||||
WmWidgetInfo info;
|
||||
|
||||
/* Lifecycle */
|
||||
bool (*init)(WidgetPlugin *plugin);
|
||||
void (*shutdown)(WidgetPlugin *plugin);
|
||||
|
||||
/* Instance management */
|
||||
WidgetInstance* (*instance_create)(WidgetPlugin *plugin,
|
||||
const WmWidgetConfig *config);
|
||||
void (*instance_destroy)(WidgetPlugin *plugin, WidgetInstance *instance);
|
||||
void (*instance_configure)(WidgetPlugin *plugin, WidgetInstance *instance,
|
||||
const WmWidgetConfig *config);
|
||||
|
||||
/* Rendering */
|
||||
void (*render)(WidgetPlugin *plugin, WidgetInstance *instance,
|
||||
WidgetContext *ctx);
|
||||
|
||||
/* Event handling */
|
||||
bool (*handle_event)(WidgetPlugin *plugin, WidgetInstance *instance,
|
||||
const WmWidgetEvent *event);
|
||||
|
||||
/* Update notification */
|
||||
void (*update)(WidgetPlugin *plugin, WidgetInstance *instance);
|
||||
|
||||
/* Size calculation */
|
||||
void (*get_preferred_size)(WidgetPlugin *plugin, WidgetInstance *instance,
|
||||
int *width, int *height);
|
||||
|
||||
} WidgetPluginInterface;
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Instance
|
||||
*============================================================================*/
|
||||
|
||||
struct WidgetInstance {
|
||||
/* Plugin that created this instance */
|
||||
WidgetPlugin *plugin;
|
||||
|
||||
/* Instance state */
|
||||
WmWidgetState state;
|
||||
WmWidgetGeometry geometry;
|
||||
WmWidgetConstraints constraints;
|
||||
|
||||
/* Configuration */
|
||||
WmWidgetConfig config;
|
||||
|
||||
/* Context */
|
||||
WidgetContext *context;
|
||||
|
||||
/* Plugin-private data */
|
||||
void *user_data;
|
||||
|
||||
/* Linked list for panel */
|
||||
WidgetInstance *next;
|
||||
WidgetInstance *prev;
|
||||
};
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Plugin Structure
|
||||
*============================================================================*/
|
||||
|
||||
struct WidgetPlugin {
|
||||
/* Interface vtable */
|
||||
const WidgetPluginInterface *interface;
|
||||
|
||||
/* Plugin handle (for dynamic loading) */
|
||||
void *handle;
|
||||
|
||||
/* Plugin path */
|
||||
char *path;
|
||||
|
||||
/* Enabled state */
|
||||
bool enabled;
|
||||
|
||||
/* Instances */
|
||||
WidgetInstance *instances;
|
||||
int instance_count;
|
||||
|
||||
/* Plugin-private data */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Manager
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WidgetManager WidgetManager;
|
||||
|
||||
/**
|
||||
* Get the global widget manager.
|
||||
*/
|
||||
WidgetManager* wm_widget_manager_get(void);
|
||||
|
||||
/**
|
||||
* Initialize the widget manager.
|
||||
*/
|
||||
bool wm_widget_manager_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown the widget manager.
|
||||
*/
|
||||
void wm_widget_manager_shutdown(void);
|
||||
|
||||
/**
|
||||
* Register a widget plugin.
|
||||
*/
|
||||
bool wm_widget_manager_register(WidgetManager *mgr, WidgetPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Unregister a widget plugin.
|
||||
*/
|
||||
void wm_widget_manager_unregister(WidgetManager *mgr, WidgetPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Load a widget plugin from a file.
|
||||
*/
|
||||
WidgetPlugin* wm_widget_manager_load(WidgetManager *mgr, const char *path);
|
||||
|
||||
/**
|
||||
* Unload a widget plugin.
|
||||
*/
|
||||
void wm_widget_manager_unload(WidgetManager *mgr, WidgetPlugin *plugin);
|
||||
|
||||
/**
|
||||
* Get a loaded widget by ID.
|
||||
*/
|
||||
WidgetPlugin* wm_widget_manager_get_widget(WidgetManager *mgr, const char *id);
|
||||
|
||||
/**
|
||||
* Get list of available widgets.
|
||||
*/
|
||||
const char** wm_widget_manager_list(WidgetManager *mgr, int *count);
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Instance Operations
|
||||
*============================================================================*/
|
||||
|
||||
/**
|
||||
* Create a widget instance.
|
||||
*/
|
||||
WidgetInstance* wm_widget_create_instance(WidgetPlugin *plugin,
|
||||
const WmWidgetConfig *config);
|
||||
|
||||
/**
|
||||
* Destroy a widget instance.
|
||||
*/
|
||||
void wm_widget_destroy_instance(WidgetInstance *instance);
|
||||
|
||||
/**
|
||||
* Render a widget instance.
|
||||
*/
|
||||
void wm_widget_render(WidgetInstance *instance, WidgetContext *ctx);
|
||||
|
||||
/**
|
||||
* Send an event to a widget instance.
|
||||
*/
|
||||
bool wm_widget_send_event(WidgetInstance *instance, const WmWidgetEvent *event);
|
||||
|
||||
/**
|
||||
* Update a widget instance (request redraw).
|
||||
*/
|
||||
void wm_widget_update(WidgetInstance *instance);
|
||||
|
||||
/**
|
||||
* Get preferred size for a widget instance.
|
||||
*/
|
||||
void wm_widget_get_preferred_size(WidgetInstance *instance,
|
||||
int *width, int *height);
|
||||
|
||||
/*==============================================================================
|
||||
* Widget Panel Integration
|
||||
*============================================================================*/
|
||||
|
||||
typedef struct WidgetPanel WidgetPanel;
|
||||
|
||||
/**
|
||||
* Create a widget panel (container for widget instances).
|
||||
*/
|
||||
WidgetPanel* wm_widget_panel_create(void);
|
||||
|
||||
/**
|
||||
* Destroy a widget panel.
|
||||
*/
|
||||
void wm_widget_panel_destroy(WidgetPanel *panel);
|
||||
|
||||
/**
|
||||
* Add a widget instance to a panel.
|
||||
*/
|
||||
void wm_widget_panel_add(WidgetPanel *panel, WidgetInstance *instance,
|
||||
WmWidgetPosition position);
|
||||
|
||||
/**
|
||||
* Remove a widget instance from a panel.
|
||||
*/
|
||||
void wm_widget_panel_remove(WidgetPanel *panel, WidgetInstance *instance);
|
||||
|
||||
/**
|
||||
* Arrange widgets in a panel.
|
||||
*/
|
||||
void wm_widget_panel_arrange(WidgetPanel *panel, const WmRect *panel_geometry);
|
||||
|
||||
/**
|
||||
* Render all widgets in a panel.
|
||||
*/
|
||||
void wm_widget_panel_render(WidgetPanel *panel);
|
||||
|
||||
/**
|
||||
* Handle mouse event in a panel.
|
||||
*/
|
||||
bool wm_widget_panel_handle_event(WidgetPanel *panel,
|
||||
const WmWidgetEvent *event);
|
||||
|
||||
/*==============================================================================
|
||||
* Built-in Widgets
|
||||
*============================================================================*/
|
||||
|
||||
/* Workspace switcher widget */
|
||||
extern const WidgetPluginInterface wm_widget_workspaces;
|
||||
|
||||
/* Taskbar widget */
|
||||
extern const WidgetPluginInterface wm_widget_taskbar;
|
||||
|
||||
/* Clock widget */
|
||||
extern const WidgetPluginInterface wm_widget_clock;
|
||||
|
||||
/* System tray widget */
|
||||
extern const WidgetPluginInterface wm_widget_systray;
|
||||
|
||||
/* CPU/Memory monitor widget */
|
||||
extern const WidgetPluginInterface wm_widget_system_stats;
|
||||
|
||||
/* News ticker widget */
|
||||
extern const WidgetPluginInterface wm_widget_news;
|
||||
|
||||
/*==============================================================================
|
||||
* Plugin Entry Point
|
||||
*============================================================================*/
|
||||
|
||||
typedef const WidgetPluginInterface* (*WidgetPluginEntryFunc)(void);
|
||||
|
||||
#define WM_WIDGET_PLUGIN_ENTRY "wm_widget_plugin_entry"
|
||||
|
||||
/*==============================================================================
|
||||
* Helper Macros
|
||||
*============================================================================*/
|
||||
|
||||
#define WM_WIDGET_REGISTER(name, iface) \
|
||||
static const WidgetPluginInterface* wm_widget_plugin_entry(void) { return &(iface); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIDGET_PLUGIN_H */
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Window rules engine for auto-applying settings
|
||||
*/
|
||||
|
||||
#ifndef DWN_RULES_H
|
||||
#define DWN_RULES_H
|
||||
|
||||
#include "dwn.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAX_RULES 64
|
||||
#define RULE_PATTERN_SIZE 128
|
||||
|
||||
typedef enum {
|
||||
RULE_MATCH_CLASS,
|
||||
RULE_MATCH_TITLE,
|
||||
RULE_MATCH_CLASS_AND_TITLE
|
||||
} RuleMatchType;
|
||||
|
||||
typedef struct {
|
||||
RuleMatchType match_type;
|
||||
char class_pattern[RULE_PATTERN_SIZE];
|
||||
char title_pattern[RULE_PATTERN_SIZE];
|
||||
|
||||
bool has_workspace;
|
||||
int workspace;
|
||||
|
||||
bool has_floating;
|
||||
bool floating;
|
||||
|
||||
bool has_sticky;
|
||||
bool sticky;
|
||||
|
||||
bool has_fullscreen;
|
||||
bool fullscreen;
|
||||
|
||||
bool has_size;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
bool has_position;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
bool has_opacity;
|
||||
float opacity;
|
||||
} WindowRule;
|
||||
|
||||
void rules_init(void);
|
||||
void rules_cleanup(void);
|
||||
bool rules_load(const char *path);
|
||||
void rules_add(const WindowRule *rule);
|
||||
void rules_clear(void);
|
||||
int rules_count(void);
|
||||
|
||||
bool rules_apply_to_client(Client *client);
|
||||
bool rules_match_pattern(const char *str, const char *pattern);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Generic slider widget for panel controls
|
||||
*/
|
||||
|
||||
#ifndef DWN_SLIDER_H
|
||||
#define DWN_SLIDER_H
|
||||
|
||||
#include "dwn.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define SLIDER_WIDTH 30
|
||||
#define SLIDER_HEIGHT 120
|
||||
#define SLIDER_PADDING 8
|
||||
#define SLIDER_KNOB_HEIGHT 8
|
||||
|
||||
/* Forward declaration */
|
||||
typedef struct GenericSlider GenericSlider;
|
||||
|
||||
/* Callback type for value changes */
|
||||
typedef void (*SliderValueChangedCallback)(GenericSlider *slider, int value);
|
||||
|
||||
/* Generic slider structure */
|
||||
struct GenericSlider {
|
||||
Window window;
|
||||
int x, y;
|
||||
int width, height;
|
||||
bool visible;
|
||||
bool dragging;
|
||||
|
||||
/* Value (always 0-100 internally) */
|
||||
int value;
|
||||
|
||||
/* Display */
|
||||
const char *label_prefix;
|
||||
bool show_percentage;
|
||||
|
||||
/* Callback */
|
||||
SliderValueChangedCallback on_value_changed;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
/* Lifecycle */
|
||||
GenericSlider *slider_create(int x, int y,
|
||||
const char *label_prefix,
|
||||
bool show_percentage,
|
||||
SliderValueChangedCallback callback,
|
||||
void *user_data);
|
||||
void slider_destroy(GenericSlider *slider);
|
||||
|
||||
/* Visibility */
|
||||
void slider_show(GenericSlider *slider, int x, int y);
|
||||
void slider_hide(GenericSlider *slider);
|
||||
bool slider_is_visible(const GenericSlider *slider);
|
||||
|
||||
/* Rendering */
|
||||
void slider_render(GenericSlider *slider);
|
||||
|
||||
/* Event handling */
|
||||
void slider_handle_click(GenericSlider *slider, int x, int y);
|
||||
void slider_handle_motion(GenericSlider *slider, int x, int y);
|
||||
void slider_handle_release(GenericSlider *slider);
|
||||
|
||||
/* Value */
|
||||
void slider_set_value(GenericSlider *slider, int value);
|
||||
int slider_get_value(const GenericSlider *slider);
|
||||
|
||||
/* Hit testing */
|
||||
bool slider_hit_test(const GenericSlider *slider, int x, int y);
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#define DWN_SYSTRAY_H
|
||||
|
||||
#include "dwn.h"
|
||||
#include "slider.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAX_TRAY_ICONS 32
|
||||
@@ -84,12 +85,22 @@ typedef struct {
|
||||
bool dragging;
|
||||
} VolumeSlider;
|
||||
|
||||
/* Generic slider wrapper for fade controls */
|
||||
typedef struct {
|
||||
GenericSlider *slider;
|
||||
int icon_x; /* Position for popup */
|
||||
} FadeControl;
|
||||
|
||||
extern WifiState wifi_state;
|
||||
extern AudioState audio_state;
|
||||
extern BatteryState battery_state;
|
||||
extern MultiBatteryState multi_battery_state;
|
||||
extern VolumeSlider *volume_slider;
|
||||
|
||||
/* Fade control externs */
|
||||
extern FadeControl fade_speed_control;
|
||||
extern FadeControl fade_intensity_control;
|
||||
|
||||
void systray_init(void);
|
||||
void systray_cleanup(void);
|
||||
|
||||
@@ -113,6 +124,15 @@ void volume_slider_handle_click(VolumeSlider *slider, int x, int y);
|
||||
void volume_slider_handle_motion(VolumeSlider *slider, int x, int y);
|
||||
void volume_slider_handle_release(VolumeSlider *slider);
|
||||
|
||||
/* Fade control functions */
|
||||
void fade_controls_init(void);
|
||||
void fade_controls_cleanup(void);
|
||||
void fade_controls_render(Panel *panel, int x);
|
||||
int fade_controls_get_width(void);
|
||||
void fade_controls_handle_click(int control_id, int x, int y, int button);
|
||||
int fade_controls_hit_test(int x);
|
||||
void fade_controls_hide_all(void);
|
||||
|
||||
void systray_render(Panel *panel, int x, int *width);
|
||||
int systray_get_width(void);
|
||||
void systray_handle_click(int x, int y, int button);
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Specialized Worker Threads - High-Level API
|
||||
*
|
||||
* Pre-built worker types for common async operations:
|
||||
* - I/O Worker: File operations, networking
|
||||
* - Compute Worker: CPU-intensive tasks
|
||||
* - System Worker: /proc monitoring, system stats
|
||||
* - Deferred Worker: Delayed/scheduled execution
|
||||
*/
|
||||
|
||||
#ifndef DWN_THREAD_WORKERS_H
|
||||
#define DWN_THREAD_WORKERS_H
|
||||
|
||||
#include "threading.h"
|
||||
|
||||
/* ============================================================================
|
||||
* I/O Worker - Async File and Network Operations
|
||||
* ============================================================================ */
|
||||
|
||||
typedef void (*IoCallback)(void *result, size_t size, int error, void *user_data);
|
||||
typedef void (*IoProgressCallback)(size_t processed, size_t total, void *user_data);
|
||||
|
||||
/**
|
||||
* Initialize I/O worker subsystem
|
||||
*/
|
||||
bool io_worker_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown I/O worker subsystem
|
||||
*/
|
||||
void io_worker_shutdown(void);
|
||||
|
||||
/**
|
||||
* Read file asynchronously
|
||||
* @param path File path
|
||||
* @param callback Called with file contents
|
||||
* @param user_data Passed to callback
|
||||
* @return Task handle or NULL
|
||||
*/
|
||||
TaskHandle io_read_file_async(const char *path, IoCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Write file asynchronously
|
||||
*/
|
||||
TaskHandle io_write_file_async(const char *path, const void *data, size_t size,
|
||||
IoCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Read directory contents asynchronously
|
||||
* Result is a null-separated list of filenames
|
||||
*/
|
||||
TaskHandle io_read_dir_async(const char *path, IoCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* HTTP GET request asynchronously
|
||||
* @param url URL to fetch
|
||||
* @param callback Called with response body
|
||||
* @param user_data Passed to callback
|
||||
* @return Task handle or NULL
|
||||
*/
|
||||
TaskHandle io_http_get_async(const char *url, IoCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* HTTP POST request asynchronously
|
||||
*/
|
||||
TaskHandle io_http_post_async(const char *url, const void *data, size_t size,
|
||||
IoCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Download file with progress callback
|
||||
*/
|
||||
TaskHandle io_download_async(const char *url, const char *dest_path,
|
||||
IoProgressCallback progress,
|
||||
IoCallback callback, void *user_data);
|
||||
|
||||
/* ============================================================================
|
||||
* Compute Worker - CPU-Intensive Tasks
|
||||
* ============================================================================ */
|
||||
|
||||
typedef void (*ComputeCallback)(void *result, void *user_data);
|
||||
|
||||
/**
|
||||
* Initialize compute worker subsystem
|
||||
*/
|
||||
bool compute_worker_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown compute worker subsystem
|
||||
*/
|
||||
void compute_worker_shutdown(void);
|
||||
|
||||
/**
|
||||
* Parallel for - distribute work across threads
|
||||
* @param start Start index
|
||||
* @param end End index (exclusive)
|
||||
* @param func Function called for each index
|
||||
* @param user_data Passed to each invocation
|
||||
*/
|
||||
void compute_parallel_for(int start, int end,
|
||||
void (*func)(int index, void *user_data),
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Map operation - apply function to each element
|
||||
*/
|
||||
void* compute_map(void *array, size_t count, size_t elem_size,
|
||||
void (*func)(void *in, void *out, void *user_data),
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Reduce operation - aggregate values
|
||||
*/
|
||||
void* compute_reduce(void *array, size_t count, size_t elem_size,
|
||||
void (*func)(void *accum, void *elem, void *user_data),
|
||||
void *initial, void *user_data);
|
||||
|
||||
/**
|
||||
* Submit compute task
|
||||
*/
|
||||
TaskHandle compute_submit(void (*func)(void *user_data), void *user_data,
|
||||
ComputeCallback callback, void *callback_data);
|
||||
|
||||
/* ============================================================================
|
||||
* System Worker - System Monitoring
|
||||
* ============================================================================ */
|
||||
|
||||
typedef struct {
|
||||
float cpu_percent;
|
||||
uint64_t memory_used;
|
||||
uint64_t memory_total;
|
||||
float memory_percent;
|
||||
float load_avg[3];
|
||||
uint64_t uptime_seconds;
|
||||
} SystemStats;
|
||||
|
||||
typedef struct {
|
||||
uint32_t pid;
|
||||
char name[64];
|
||||
float cpu_percent;
|
||||
uint64_t memory_bytes;
|
||||
} ProcessInfo;
|
||||
|
||||
typedef void (*SystemStatsCallback)(const SystemStats *stats, void *user_data);
|
||||
typedef void (*ProcessListCallback)(ProcessInfo *processes, uint32_t count, void *user_data);
|
||||
|
||||
/**
|
||||
* Initialize system worker
|
||||
*/
|
||||
bool system_worker_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown system worker
|
||||
*/
|
||||
void system_worker_shutdown(void);
|
||||
|
||||
/**
|
||||
* Get cached system stats (non-blocking, updated periodically)
|
||||
*/
|
||||
bool system_worker_get_cached_stats(SystemStats *stats);
|
||||
|
||||
/**
|
||||
* Get fresh system stats (blocking)
|
||||
*/
|
||||
Future* system_worker_get_stats_async(void);
|
||||
|
||||
/**
|
||||
* Get process list asynchronously
|
||||
*/
|
||||
TaskHandle system_worker_get_processes_async(ProcessListCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Subscribe to periodic stats updates
|
||||
* @param interval_ms Update interval (0 to disable)
|
||||
* @param callback Called with new stats
|
||||
* @param user_data Passed to callback
|
||||
* @return Subscription ID
|
||||
*/
|
||||
uint32_t system_worker_subscribe_stats(uint32_t interval_ms,
|
||||
SystemStatsCallback callback,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Unsubscribe from stats updates
|
||||
*/
|
||||
bool system_worker_unsubscribe_stats(uint32_t subscription_id);
|
||||
|
||||
/* ============================================================================
|
||||
* Deferred Worker - Delayed Execution
|
||||
* ============================================================================ */
|
||||
|
||||
typedef uint64_t DeferredId;
|
||||
typedef void (*DeferredCallback)(DeferredId id, void *user_data);
|
||||
|
||||
/**
|
||||
* Initialize deferred worker
|
||||
*/
|
||||
bool deferred_worker_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown deferred worker
|
||||
*/
|
||||
void deferred_worker_shutdown(void);
|
||||
|
||||
/**
|
||||
* Execute after delay
|
||||
* @param delay_ms Milliseconds to wait
|
||||
* @param callback Function to call
|
||||
* @param user_data Passed to callback
|
||||
* @return Deferred ID
|
||||
*/
|
||||
DeferredId deferred_after(uint64_t delay_ms, DeferredCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Execute at regular interval
|
||||
*/
|
||||
DeferredId deferred_every(uint64_t interval_ms, DeferredCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Cancel deferred execution
|
||||
*/
|
||||
bool deferred_cancel(DeferredId id);
|
||||
|
||||
/**
|
||||
* Process deferred tasks (call from main loop)
|
||||
* @return Number of tasks executed
|
||||
*/
|
||||
uint32_t deferred_process(void);
|
||||
|
||||
/**
|
||||
* Get poll fd for select()
|
||||
*/
|
||||
int deferred_get_poll_fd(void);
|
||||
|
||||
/* ============================================================================
|
||||
* High-Level Integration API
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* Initialize all worker subsystems
|
||||
*/
|
||||
bool thread_workers_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown all worker subsystems
|
||||
*/
|
||||
void thread_workers_shutdown(void);
|
||||
|
||||
/**
|
||||
* Process all pending async work (call from main loop)
|
||||
* @return true if work was processed
|
||||
*/
|
||||
bool thread_workers_process_all(void);
|
||||
|
||||
/**
|
||||
* Get combined poll fds for select()
|
||||
* @param fds Array to fill (size at least 4)
|
||||
* @return Number of fds filled
|
||||
*/
|
||||
int thread_workers_get_poll_fds(int *fds);
|
||||
|
||||
#endif /* DWN_THREAD_WORKERS_H */
|
||||
@@ -0,0 +1,704 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Extensive Abstract Threading Framework
|
||||
*
|
||||
* This module provides a comprehensive, abstract threading system with:
|
||||
* - Lock-free data structures
|
||||
* - Thread pools with work stealing
|
||||
* - Async/await pattern support
|
||||
* - Thread-safe event bus
|
||||
* - Memory barriers and atomic operations
|
||||
*/
|
||||
|
||||
#ifndef DWN_THREADING_H
|
||||
#define DWN_THREADING_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
/* ============================================================================
|
||||
* Platform Abstraction Layer
|
||||
* ============================================================================ */
|
||||
|
||||
/* Cache line size (commonly 64 bytes on x86_64) */
|
||||
#define CACHE_LINE_SIZE 64
|
||||
|
||||
/* Align to cache line to prevent false sharing */
|
||||
#define CACHE_ALIGN __attribute__((aligned(CACHE_LINE_SIZE)))
|
||||
|
||||
/* Memory ordering shortcuts */
|
||||
#define ATOMIC_RELAXED memory_order_relaxed
|
||||
#define ATOMIC_ACQUIRE memory_order_acquire
|
||||
#define ATOMIC_RELEASE memory_order_release
|
||||
#define ATOMIC_ACQ_REL memory_order_acq_rel
|
||||
#define ATOMIC_SEQ_CST memory_order_seq_cst
|
||||
|
||||
/* ============================================================================
|
||||
* Core Types and Status Codes
|
||||
* ============================================================================ */
|
||||
|
||||
typedef enum {
|
||||
THREAD_OK = 0,
|
||||
THREAD_ERROR = -1,
|
||||
THREAD_ERROR_NOMEM = -2,
|
||||
THREAD_ERROR_BUSY = -3,
|
||||
THREAD_ERROR_CLOSED = -4,
|
||||
THREAD_ERROR_TIMEOUT = -5,
|
||||
THREAD_ERROR_INVALID = -6
|
||||
} ThreadStatus;
|
||||
|
||||
typedef enum {
|
||||
TASK_PRIORITY_CRITICAL = 0, /* UI-critical, must execute immediately */
|
||||
TASK_PRIORITY_HIGH = 1, /* User-initiated actions */
|
||||
TASK_PRIORITY_NORMAL = 2, /* Default background work */
|
||||
TASK_PRIORITY_LOW = 3, /* Maintenance tasks */
|
||||
TASK_PRIORITY_IDLE = 4, /* Only when system idle */
|
||||
TASK_PRIORITY_COUNT
|
||||
} TaskPriority;
|
||||
|
||||
typedef enum {
|
||||
TASK_STATE_PENDING = 0,
|
||||
TASK_STATE_RUNNING = 1,
|
||||
TASK_STATE_COMPLETED = 2,
|
||||
TASK_STATE_CANCELLED = 3,
|
||||
TASK_STATE_ERROR = 4
|
||||
} TaskState;
|
||||
|
||||
/* Forward declarations */
|
||||
typedef struct ThreadPool ThreadPool;
|
||||
typedef struct Task Task;
|
||||
typedef struct Channel Channel;
|
||||
typedef struct Future Future;
|
||||
typedef struct EventBus EventBus;
|
||||
typedef struct AsyncContext AsyncContext;
|
||||
typedef struct Worker Worker;
|
||||
|
||||
/* ============================================================================
|
||||
* Task System - Abstract Unit of Work
|
||||
* ============================================================================ */
|
||||
|
||||
/* Task function signature - receives user data and cancellation flag */
|
||||
typedef void (*TaskFunc)(void *user_data, atomic_int *cancelled);
|
||||
|
||||
/* Callback for task completion (called in worker thread) */
|
||||
typedef void (*TaskCallback)(Task *task, void *user_data, ThreadStatus status);
|
||||
|
||||
/* Task handle - opaque pointer */
|
||||
typedef Task* TaskHandle;
|
||||
|
||||
/**
|
||||
* Create a new task
|
||||
* @param func The function to execute
|
||||
* @param user_data Data passed to the function
|
||||
* @param priority Task priority level
|
||||
* @return Task handle or NULL on error
|
||||
*/
|
||||
TaskHandle task_create(TaskFunc func, void *user_data, TaskPriority priority);
|
||||
|
||||
/**
|
||||
* Create a task with completion callback
|
||||
*/
|
||||
TaskHandle task_create_with_callback(TaskFunc func, void *user_data,
|
||||
TaskPriority priority,
|
||||
TaskCallback on_complete,
|
||||
void *callback_data);
|
||||
|
||||
/**
|
||||
* Destroy a task (only if not submitted)
|
||||
*/
|
||||
void task_destroy(TaskHandle task);
|
||||
|
||||
/**
|
||||
* Cancel a task (best effort - may already be running)
|
||||
*/
|
||||
bool task_cancel(TaskHandle task);
|
||||
|
||||
/**
|
||||
* Get current task state
|
||||
*/
|
||||
TaskState task_get_state(TaskHandle task);
|
||||
|
||||
/**
|
||||
* Wait for task completion (blocking)
|
||||
*/
|
||||
ThreadStatus task_wait(TaskHandle task, uint64_t timeout_ms);
|
||||
|
||||
/**
|
||||
* Check if task was cancelled
|
||||
*/
|
||||
bool task_is_cancelled(TaskHandle task);
|
||||
|
||||
/* ============================================================================
|
||||
* Thread Pool - Manage Worker Threads
|
||||
* ============================================================================ */
|
||||
|
||||
/* Thread pool configuration */
|
||||
typedef struct {
|
||||
uint32_t min_threads; /* Minimum threads to keep alive */
|
||||
uint32_t max_threads; /* Maximum threads allowed */
|
||||
uint32_t queue_capacity; /* Task queue capacity per priority */
|
||||
uint32_t steal_attempts; /* Work stealing attempts before blocking */
|
||||
uint64_t idle_timeout_ms; /* Time before idle thread terminates */
|
||||
bool enable_work_stealing; /* Enable work stealing between queues */
|
||||
} ThreadPoolConfig;
|
||||
|
||||
/* Default configuration */
|
||||
#define THREAD_POOL_DEFAULT_CONFIG ((ThreadPoolConfig){ \
|
||||
.min_threads = 2, \
|
||||
.max_threads = 8, \
|
||||
.queue_capacity = 256, \
|
||||
.steal_attempts = 4, \
|
||||
.idle_timeout_ms = 60000, \
|
||||
.enable_work_stealing = true \
|
||||
})
|
||||
|
||||
/**
|
||||
* Create a thread pool
|
||||
*/
|
||||
ThreadPool* thread_pool_create(const ThreadPoolConfig *config);
|
||||
|
||||
/**
|
||||
* Destroy thread pool, cancelling pending tasks
|
||||
*/
|
||||
void thread_pool_destroy(ThreadPool *pool);
|
||||
|
||||
/**
|
||||
* Submit a task to the pool
|
||||
*/
|
||||
ThreadStatus thread_pool_submit(ThreadPool *pool, TaskHandle task);
|
||||
|
||||
/**
|
||||
* Submit a function as a task (convenience)
|
||||
*/
|
||||
ThreadStatus thread_pool_submit_func(ThreadPool *pool, TaskFunc func,
|
||||
void *user_data, TaskPriority priority);
|
||||
|
||||
/**
|
||||
* Get number of active threads
|
||||
*/
|
||||
uint32_t thread_pool_active_count(ThreadPool *pool);
|
||||
|
||||
/**
|
||||
* Get number of pending tasks
|
||||
*/
|
||||
uint32_t thread_pool_pending_count(ThreadPool *pool);
|
||||
|
||||
/**
|
||||
* Shutdown pool gracefully, waiting for tasks to complete
|
||||
*/
|
||||
ThreadStatus thread_pool_shutdown(ThreadPool *pool, uint64_t timeout_ms);
|
||||
|
||||
/**
|
||||
* Get the default/global thread pool
|
||||
*/
|
||||
ThreadPool* thread_pool_default(void);
|
||||
|
||||
/**
|
||||
* Initialize the default thread pool
|
||||
*/
|
||||
ThreadStatus thread_pool_init_default(const ThreadPoolConfig *config);
|
||||
|
||||
/**
|
||||
* Shutdown the default thread pool
|
||||
*/
|
||||
void thread_pool_shutdown_default(void);
|
||||
|
||||
/* ============================================================================
|
||||
* Lock-Free Queue - Single Producer Single Consumer
|
||||
* ============================================================================ */
|
||||
|
||||
#define SPSC_QUEUE_SIZE 1024
|
||||
|
||||
typedef struct {
|
||||
_Atomic uint64_t head CACHE_ALIGN; /* Write index - producer only */
|
||||
_Atomic uint64_t tail CACHE_ALIGN; /* Read index - consumer only */
|
||||
void *buffer[SPSC_QUEUE_SIZE];
|
||||
} SpscQueue;
|
||||
|
||||
/**
|
||||
* Initialize SPSC queue
|
||||
*/
|
||||
void spsc_queue_init(SpscQueue *q);
|
||||
|
||||
/**
|
||||
* Push item (producer only)
|
||||
* @return false if queue full
|
||||
*/
|
||||
bool spsc_queue_push(SpscQueue *q, void *item);
|
||||
|
||||
/**
|
||||
* Pop item (consumer only)
|
||||
* @return false if queue empty
|
||||
*/
|
||||
bool spsc_queue_pop(SpscQueue *q, void **item);
|
||||
|
||||
/**
|
||||
* Check if queue is empty (consumer only)
|
||||
*/
|
||||
bool spsc_queue_empty(SpscQueue *q);
|
||||
|
||||
/**
|
||||
* Get approximate size (not synchronized)
|
||||
*/
|
||||
uint64_t spsc_queue_size_approx(SpscQueue *q);
|
||||
|
||||
/* ============================================================================
|
||||
* Lock-Free Queue - Multi Producer Single Consumer
|
||||
* ============================================================================ */
|
||||
|
||||
typedef struct MpscQueue MpscQueue;
|
||||
|
||||
/**
|
||||
* Create MPSC queue
|
||||
*/
|
||||
MpscQueue* mpsc_queue_create(uint32_t capacity);
|
||||
|
||||
/**
|
||||
* Destroy MPSC queue
|
||||
*/
|
||||
void mpsc_queue_destroy(MpscQueue *q);
|
||||
|
||||
/**
|
||||
* Push item (thread-safe, any producer)
|
||||
* @return false if queue full
|
||||
*/
|
||||
bool mpsc_queue_push(MpscQueue *q, void *item);
|
||||
|
||||
/**
|
||||
* Pop item (consumer only - single thread)
|
||||
* @return false if queue empty
|
||||
*/
|
||||
bool mpsc_queue_pop(MpscQueue *q, void **item);
|
||||
|
||||
/**
|
||||
* Check if queue is empty
|
||||
*/
|
||||
bool mpsc_queue_empty(MpscQueue *q);
|
||||
|
||||
/* ============================================================================
|
||||
* Channel - Thread-Safe Communication
|
||||
* ============================================================================ */
|
||||
|
||||
typedef enum {
|
||||
CHANNEL_UNBUFFERED = 0, /* Synchronous - sender blocks until received */
|
||||
CHANNEL_BUFFERED = 1 /* Asynchronous - uses internal buffer */
|
||||
} ChannelType;
|
||||
|
||||
/**
|
||||
* Create a channel
|
||||
* @param capacity Buffer size (0 for unbuffered synchronous channel)
|
||||
*/
|
||||
Channel* channel_create(uint32_t capacity);
|
||||
|
||||
/**
|
||||
* Destroy channel
|
||||
*/
|
||||
void channel_destroy(Channel *ch);
|
||||
|
||||
/**
|
||||
* Send data through channel (blocking)
|
||||
* @return THREAD_OK on success, THREAD_ERROR_CLOSED if closed
|
||||
*/
|
||||
ThreadStatus channel_send(Channel *ch, void *data);
|
||||
|
||||
/**
|
||||
* Send with timeout
|
||||
*/
|
||||
ThreadStatus channel_send_timeout(Channel *ch, void *data, uint64_t timeout_ms);
|
||||
|
||||
/**
|
||||
* Try send (non-blocking)
|
||||
*/
|
||||
ThreadStatus channel_try_send(Channel *ch, void *data);
|
||||
|
||||
/**
|
||||
* Receive from channel (blocking)
|
||||
*/
|
||||
ThreadStatus channel_recv(Channel *ch, void **data);
|
||||
|
||||
/**
|
||||
* Receive with timeout
|
||||
*/
|
||||
ThreadStatus channel_recv_timeout(Channel *ch, void **data, uint64_t timeout_ms);
|
||||
|
||||
/**
|
||||
* Try receive (non-blocking)
|
||||
*/
|
||||
ThreadStatus channel_try_recv(Channel *ch, void **data);
|
||||
|
||||
/**
|
||||
* Close channel (no more sends allowed)
|
||||
*/
|
||||
void channel_close(Channel *ch);
|
||||
|
||||
/**
|
||||
* Check if channel is closed
|
||||
*/
|
||||
bool channel_is_closed(Channel *ch);
|
||||
|
||||
/**
|
||||
* Select on multiple channels (like Go's select)
|
||||
* Returns index of ready channel or -1 on timeout
|
||||
*/
|
||||
int channel_select(Channel **channels, uint32_t count, uint64_t timeout_ms,
|
||||
void **out_data);
|
||||
|
||||
/* ============================================================================
|
||||
* Future/Promise - Async Result Handling
|
||||
* ============================================================================ */
|
||||
|
||||
typedef void* FutureResult;
|
||||
typedef void (*FutureCallback)(Future *f, FutureResult result, void *user_data);
|
||||
|
||||
/**
|
||||
* Create a future
|
||||
*/
|
||||
Future* future_create(void);
|
||||
|
||||
/**
|
||||
* Destroy future
|
||||
*/
|
||||
void future_destroy(Future *f);
|
||||
|
||||
/**
|
||||
* Set the result (called by producer)
|
||||
*/
|
||||
void future_set_result(Future *f, FutureResult result);
|
||||
|
||||
/**
|
||||
* Set error result
|
||||
*/
|
||||
void future_set_error(Future *f, int error_code);
|
||||
|
||||
/**
|
||||
* Get result (blocking)
|
||||
*/
|
||||
FutureResult future_get(Future *f, ThreadStatus *status);
|
||||
|
||||
/**
|
||||
* Get result with timeout
|
||||
*/
|
||||
FutureResult future_get_timeout(Future *f, uint64_t timeout_ms, ThreadStatus *status);
|
||||
|
||||
/**
|
||||
* Check if future is ready
|
||||
*/
|
||||
bool future_is_ready(Future *f);
|
||||
|
||||
/**
|
||||
* Attach callback to be called when ready (thread-safe)
|
||||
*/
|
||||
void future_then(Future *f, FutureCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Create future that completes when all given futures complete
|
||||
*/
|
||||
Future* future_all(Future **futures, uint32_t count);
|
||||
|
||||
/**
|
||||
* Create future that completes when any given future completes
|
||||
*/
|
||||
Future* future_any(Future **futures, uint32_t count);
|
||||
|
||||
/* ============================================================================
|
||||
* Event Bus - Thread-Safe Pub/Sub
|
||||
* ============================================================================ */
|
||||
|
||||
typedef uint32_t EventType;
|
||||
typedef uint32_t SubscriptionId;
|
||||
|
||||
/* Event handler signature */
|
||||
typedef void (*EventHandler)(EventType type, void *event_data, void *user_data);
|
||||
|
||||
/* Event filter - return true to allow event */
|
||||
typedef bool (*EventFilter)(EventType type, void *event_data, void *user_data);
|
||||
|
||||
/**
|
||||
* Create event bus
|
||||
*/
|
||||
EventBus* event_bus_create(void);
|
||||
|
||||
/**
|
||||
* Destroy event bus
|
||||
*/
|
||||
void event_bus_destroy(EventBus *bus);
|
||||
|
||||
/**
|
||||
* Subscribe to event type
|
||||
* @return Subscription ID or 0 on error
|
||||
*/
|
||||
SubscriptionId event_bus_subscribe(EventBus *bus, EventType type,
|
||||
EventHandler handler, void *user_data);
|
||||
|
||||
/**
|
||||
* Subscribe with filter
|
||||
*/
|
||||
SubscriptionId event_bus_subscribe_filtered(EventBus *bus, EventType type,
|
||||
EventHandler handler, void *user_data,
|
||||
EventFilter filter, void *filter_data);
|
||||
|
||||
/**
|
||||
* Unsubscribe
|
||||
*/
|
||||
bool event_bus_unsubscribe(EventBus *bus, SubscriptionId id);
|
||||
|
||||
/**
|
||||
* Publish event (thread-safe)
|
||||
*/
|
||||
void event_bus_publish(EventBus *bus, EventType type, void *event_data);
|
||||
|
||||
/**
|
||||
* Publish event with custom free function
|
||||
*/
|
||||
void event_bus_publish_owned(EventBus *bus, EventType type, void *event_data,
|
||||
void (*free_fn)(void*));
|
||||
|
||||
/**
|
||||
* Process pending events (call from main thread)
|
||||
* @return number of events processed
|
||||
*/
|
||||
uint32_t event_bus_process(EventBus *bus);
|
||||
|
||||
/**
|
||||
* Set processing limit per call
|
||||
*/
|
||||
void event_bus_set_batch_size(EventBus *bus, uint32_t batch_size);
|
||||
|
||||
/**
|
||||
* Get the global/default event bus
|
||||
*/
|
||||
EventBus* event_bus_default(void);
|
||||
|
||||
/**
|
||||
* Initialize default event bus
|
||||
*/
|
||||
bool event_bus_init_default(void);
|
||||
|
||||
/**
|
||||
* Shutdown default event bus
|
||||
*/
|
||||
void event_bus_shutdown_default(void);
|
||||
|
||||
/* ============================================================================
|
||||
* Async Context - Per-Module Async State
|
||||
* ============================================================================ */
|
||||
|
||||
/* Context for managing async operations within a module */
|
||||
struct AsyncContext {
|
||||
ThreadPool *pool;
|
||||
EventBus *event_bus;
|
||||
Channel *completion_channel;
|
||||
atomic_int operation_count;
|
||||
atomic_int shutdown_requested;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create async context
|
||||
*/
|
||||
AsyncContext* async_context_create(const char *name);
|
||||
|
||||
/**
|
||||
* Destroy async context (cancels all pending operations)
|
||||
*/
|
||||
void async_context_destroy(AsyncContext *ctx);
|
||||
|
||||
/**
|
||||
* Submit work to context's thread pool
|
||||
*/
|
||||
TaskHandle async_submit(AsyncContext *ctx, TaskFunc func, void *user_data,
|
||||
TaskPriority priority);
|
||||
|
||||
/**
|
||||
* Submit work and get future
|
||||
*/
|
||||
Future* async_submit_future(AsyncContext *ctx, TaskFunc func, void *user_data,
|
||||
TaskPriority priority);
|
||||
|
||||
/**
|
||||
* Check for completed operations (call from main thread)
|
||||
*/
|
||||
uint32_t async_poll(AsyncContext *ctx);
|
||||
|
||||
/**
|
||||
* Get file descriptor for select() integration
|
||||
* Returns -1 if not available
|
||||
*/
|
||||
int async_get_poll_fd(AsyncContext *ctx);
|
||||
|
||||
/* ============================================================================
|
||||
* Timer/Scheduler - Delayed Execution
|
||||
* ============================================================================ */
|
||||
|
||||
typedef uint64_t TimerId;
|
||||
typedef void (*TimerCallback)(TimerId id, void *user_data);
|
||||
|
||||
/**
|
||||
* Schedule one-shot timer
|
||||
*/
|
||||
TimerId timer_schedule(uint64_t delay_ms, TimerCallback callback, void *user_data);
|
||||
|
||||
/**
|
||||
* Schedule repeating timer
|
||||
*/
|
||||
TimerId timer_schedule_repeating(uint64_t interval_ms, TimerCallback callback,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Cancel timer
|
||||
*/
|
||||
bool timer_cancel(TimerId id);
|
||||
|
||||
/**
|
||||
* Check if timer exists
|
||||
*/
|
||||
bool timer_exists(TimerId id);
|
||||
|
||||
/**
|
||||
* Process timer events (call from main thread)
|
||||
* @return Number of timers fired
|
||||
*/
|
||||
uint32_t timer_process(void);
|
||||
|
||||
/**
|
||||
* Get timer file descriptor for select()
|
||||
*/
|
||||
int timer_get_poll_fd(void);
|
||||
|
||||
/**
|
||||
* Initialize timer subsystem
|
||||
*/
|
||||
bool timer_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown timer subsystem
|
||||
*/
|
||||
void timer_shutdown(void);
|
||||
|
||||
/* ============================================================================
|
||||
* Thread-Local Storage Abstraction
|
||||
* ============================================================================ */
|
||||
|
||||
typedef struct TlsKey TlsKey;
|
||||
|
||||
/**
|
||||
* Create TLS key
|
||||
*/
|
||||
TlsKey* tls_create(void (*destructor)(void*));
|
||||
|
||||
/**
|
||||
* Destroy TLS key
|
||||
*/
|
||||
void tls_destroy(TlsKey *key);
|
||||
|
||||
/**
|
||||
* Set TLS value
|
||||
*/
|
||||
void tls_set(TlsKey *key, void *value);
|
||||
|
||||
/**
|
||||
* Get TLS value
|
||||
*/
|
||||
void* tls_get(TlsKey *key);
|
||||
|
||||
/* ============================================================================
|
||||
* Read-Write Lock Wrapper
|
||||
* ============================================================================ */
|
||||
|
||||
typedef struct RwLock RwLock;
|
||||
|
||||
RwLock* rwlock_create(void);
|
||||
void rwlock_destroy(RwLock *lock);
|
||||
void rwlock_read_lock(RwLock *lock);
|
||||
bool rwlock_read_trylock(RwLock *lock);
|
||||
void rwlock_read_unlock(RwLock *lock);
|
||||
void rwlock_write_lock(RwLock *lock);
|
||||
bool rwlock_write_trylock(RwLock *lock);
|
||||
void rwlock_write_unlock(RwLock *lock);
|
||||
|
||||
/* ============================================================================
|
||||
* Barrier and Synchronization
|
||||
* ============================================================================ */
|
||||
|
||||
typedef struct Barrier Barrier;
|
||||
|
||||
Barrier* barrier_create(uint32_t count);
|
||||
void barrier_destroy(Barrier *b);
|
||||
bool barrier_wait(Barrier *b, uint64_t timeout_ms);
|
||||
|
||||
/* ============================================================================
|
||||
* Initialization and Cleanup
|
||||
* ============================================================================ */
|
||||
|
||||
/**
|
||||
* Initialize entire threading subsystem
|
||||
*/
|
||||
bool threading_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown entire threading subsystem
|
||||
*/
|
||||
void threading_shutdown(void);
|
||||
|
||||
/**
|
||||
* Get number of hardware threads
|
||||
*/
|
||||
uint32_t threading_hw_concurrency(void);
|
||||
|
||||
/**
|
||||
* Current thread ID
|
||||
*/
|
||||
uint64_t threading_current_thread_id(void);
|
||||
|
||||
/**
|
||||
* Set current thread name (for debugging)
|
||||
*/
|
||||
void threading_set_name(const char *name);
|
||||
|
||||
/**
|
||||
* Yield current thread
|
||||
*/
|
||||
void threading_yield(void);
|
||||
|
||||
/* ============================================================================
|
||||
* Utility Macros
|
||||
* ============================================================================ */
|
||||
|
||||
/* Run function in background */
|
||||
#define ASYNC(func, data) \
|
||||
thread_pool_submit_func(thread_pool_default(), (func), (data), TASK_PRIORITY_NORMAL)
|
||||
|
||||
/* Run function with priority */
|
||||
#define ASYNC_PRIORITY(func, data, prio) \
|
||||
thread_pool_submit_func(thread_pool_default(), (func), (data), (prio))
|
||||
|
||||
/* Create future and submit */
|
||||
#define ASYNC_FUTURE(ctx, func, data) \
|
||||
async_submit_future((ctx), (func), (data), TASK_PRIORITY_NORMAL)
|
||||
|
||||
/* Synchronized block using mutex */
|
||||
#define WITH_MUTEX(mutex, code) do { \
|
||||
pthread_mutex_lock(&(mutex)); \
|
||||
code; \
|
||||
pthread_mutex_unlock(&(mutex)); \
|
||||
} while(0)
|
||||
|
||||
/* Read lock block */
|
||||
#define WITH_READ_LOCK(rwlock, code) do { \
|
||||
rwlock_read_lock((rwlock)); \
|
||||
code; \
|
||||
rwlock_read_unlock((rwlock)); \
|
||||
} while(0)
|
||||
|
||||
/* Write lock block */
|
||||
#define WITH_WRITE_LOCK(rwlock, code) do { \
|
||||
rwlock_write_lock((rwlock)); \
|
||||
code; \
|
||||
rwlock_write_unlock((rwlock)); \
|
||||
} while(0)
|
||||
|
||||
#endif /* DWN_THREADING_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* DWN - Desktop Window Manager
|
||||
* retoor <retoor@molodetz.nl>
|
||||
* Threading Integration Header
|
||||
*/
|
||||
|
||||
#ifndef DWN_THREADING_INTEGRATION_H
|
||||
#define DWN_THREADING_INTEGRATION_H
|
||||
|
||||
#include "threading.h"
|
||||
#include "thread_workers.h"
|
||||
#include <sys/select.h>
|
||||
|
||||
/**
|
||||
* Initialize threading integration with main loop
|
||||
*/
|
||||
bool threading_integration_init(void);
|
||||
|
||||
/**
|
||||
* Shutdown threading integration
|
||||
*/
|
||||
void threading_integration_shutdown(void);
|
||||
|
||||
/**
|
||||
* Prepare fd_set for select() - adds threading fds
|
||||
*/
|
||||
void threading_integration_prepare_select(int xfd, fd_set *fds, int *max_fd);
|
||||
|
||||
/**
|
||||
* Process threading events after select() returns
|
||||
*/
|
||||
void threading_integration_process(fd_set *fds);
|
||||
|
||||
/**
|
||||
* Non-blocking poll for async work
|
||||
*/
|
||||
void threading_integration_poll(void);
|
||||
|
||||
/**
|
||||
* Run one iteration with integrated threading
|
||||
*/
|
||||
void threading_integration_run_iteration(int xfd, void (*handle_xevent)(void));
|
||||
|
||||
/**
|
||||
* Get stats string for display
|
||||
*/
|
||||
void threading_integration_get_stats(char *buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* Initialize per-module async contexts
|
||||
*/
|
||||
bool threading_integration_init_module_contexts(void);
|
||||
|
||||
/**
|
||||
* Cleanup per-module async contexts
|
||||
*/
|
||||
void threading_integration_cleanup_module_contexts(void);
|
||||
|
||||
/**
|
||||
* Get module-specific async contexts
|
||||
*/
|
||||
AsyncContext* threading_integration_get_ai_context(void);
|
||||
AsyncContext* threading_integration_get_screenshot_context(void);
|
||||
AsyncContext* threading_integration_get_ocr_context(void);
|
||||
|
||||
/**
|
||||
* High-level task submission
|
||||
*/
|
||||
TaskHandle threading_integration_submit_ai(TaskFunc func, void *user_data);
|
||||
TaskHandle threading_integration_submit_screenshot(TaskFunc func, void *user_data);
|
||||
TaskHandle threading_integration_submit_ocr(TaskFunc func, void *user_data);
|
||||
TaskHandle threading_integration_submit_ui(TaskFunc func, void *user_data);
|
||||
TaskHandle threading_integration_submit_background(TaskFunc func, void *user_data);
|
||||
|
||||
#endif /* DWN_THREADING_INTEGRATION_H */
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DWN_ASSERT(cond) assert(cond)
|
||||
#define DWN_ASSERT_MSG(cond, msg) assert((cond) && (msg))
|
||||
@@ -46,6 +47,27 @@ bool str_ends_with(const char *str, const char *suffix);
|
||||
int str_split(char *str, char delim, char **parts, int max_parts);
|
||||
char *shell_escape(const char *str);
|
||||
|
||||
/* Safe string copy that always null-terminates */
|
||||
static inline void safe_strncpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
if (n == 0) return;
|
||||
size_t src_len = strlen(src);
|
||||
size_t copy_len = (src_len < n - 1) ? src_len : n - 1;
|
||||
memcpy(dest, src, copy_len);
|
||||
dest[copy_len] = '\0';
|
||||
}
|
||||
|
||||
/* Check if value is within valid range */
|
||||
static inline bool in_range_int(int val, int min, int max)
|
||||
{
|
||||
return val >= min && val <= max;
|
||||
}
|
||||
|
||||
static inline bool in_range_size_t(size_t val, size_t min, size_t max)
|
||||
{
|
||||
return val >= min && val <= max;
|
||||
}
|
||||
|
||||
bool file_exists(const char *path);
|
||||
char *file_read_all(const char *path);
|
||||
bool file_write_all(const char *path, const char *content);
|
||||
|
||||
Reference in New Issue
Block a user