194 lines
4.1 KiB
C
Raw Normal View History

/*
* DWN - Desktop Window Manager
* retoor <retoor@molodetz.nl>
* Window marks implementation
*/
#include "marks.h"
#include "client.h"
#include "workspace.h"
#include "notifications.h"
#include "util.h"
#include <string.h>
#include <ctype.h>
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';
}