/* * DWN - Desktop Window Manager * retoor * Window marks implementation */ #include "marks.h" #include "client.h" #include "workspace.h" #include "notifications.h" #include "util.h" #include #include typedef enum { MARKS_MODE_NONE, MARKS_MODE_SET, MARKS_MODE_GOTO } MarksMode; static Client *marked_clients[MAX_MARKS]; static MarksMode current_mode = MARKS_MODE_NONE; void marks_init(void) { memset(marked_clients, 0, sizeof(marked_clients)); current_mode = MARKS_MODE_NONE; LOG_INFO("Window marks system initialized"); } void marks_cleanup(void) { marks_clear_all(); } static int mark_to_index(char mark) { char lower = (char)tolower((unsigned char)mark); if (lower >= 'a' && lower <= 'z') { return lower - 'a'; } return -1; } void marks_set(char mark, Client *client) { int idx = mark_to_index(mark); if (idx < 0 || client == NULL) { return; } for (int i = 0; i < MAX_MARKS; i++) { if (marked_clients[i] == client) { marked_clients[i] = NULL; } } marked_clients[idx] = client; char msg[128]; snprintf(msg, sizeof(msg), "Window marked as '%c'", mark); notification_show("DWN Marks", "Mark Set", msg, NULL, 1500); LOG_DEBUG("Set mark '%c' for window '%s'", mark, client->title); } Client *marks_get(char mark) { int idx = mark_to_index(mark); if (idx < 0) { return NULL; } return marked_clients[idx]; } void marks_clear(char mark) { int idx = mark_to_index(mark); if (idx >= 0) { marked_clients[idx] = NULL; } } void marks_clear_all(void) { memset(marked_clients, 0, sizeof(marked_clients)); } void marks_remove_client(Client *client) { if (client == NULL) { return; } for (int i = 0; i < MAX_MARKS; i++) { if (marked_clients[i] == client) { marked_clients[i] = NULL; } } } bool marks_is_waiting_for_mark(void) { return current_mode == MARKS_MODE_SET; } bool marks_is_waiting_for_goto(void) { return current_mode == MARKS_MODE_GOTO; } void marks_start_set_mode(void) { Workspace *ws = workspace_get_current(); if (ws == NULL || ws->focused == NULL) { notification_show("DWN Marks", "No Window", "Focus a window first to set a mark", NULL, 2000); return; } current_mode = MARKS_MODE_SET; notification_show("DWN Marks", "Set Mark", "Press a-z to set mark for this window", NULL, 0); } void marks_start_goto_mode(void) { current_mode = MARKS_MODE_GOTO; notification_show("DWN Marks", "Go to Mark", "Press a-z to jump to marked window", NULL, 0); } void marks_cancel_mode(void) { if (current_mode != MARKS_MODE_NONE) { current_mode = MARKS_MODE_NONE; notification_close_all(); } } bool marks_handle_key(char key) { if (current_mode == MARKS_MODE_NONE) { return false; } char lower = (char)tolower((unsigned char)key); if (lower < 'a' || lower > 'z') { marks_cancel_mode(); return true; } notification_close_all(); if (current_mode == MARKS_MODE_SET) { Workspace *ws = workspace_get_current(); if (ws != NULL && ws->focused != NULL) { marks_set(lower, ws->focused); } } else if (current_mode == MARKS_MODE_GOTO) { Client *c = marks_get(lower); if (c != NULL) { if (c->workspace != (unsigned int)dwn->current_workspace) { workspace_switch((int)c->workspace); } client_focus(c, true); client_raise(c); } else { char msg[64]; snprintf(msg, sizeof(msg), "No window marked as '%c'", lower); notification_show("DWN Marks", "Mark Not Found", msg, NULL, 1500); } } current_mode = MARKS_MODE_NONE; return true; } char marks_get_mark_for_client(Client *client) { if (client == NULL) { return '\0'; } for (int i = 0; i < MAX_MARKS; i++) { if (marked_clients[i] == client) { return (char)('a' + i); } } return '\0'; }