Compare commits

..

4 Commits

10 changed files with 95 additions and 0 deletions

View File

@@ -3,9 +3,28 @@
#include <glib.h>
#include <string.h>
#include "client.h"
#include "monitor.h"
#include "types.h"
#include "wm.h"
void focus_client_in_same_tag(const user_action_arg_t *arg) {
bool next = arg->b;
tag_t *tag = wm.current_monitor->selected_tag;
task_in_tag_t *task = nullptr;
if (next) {
task = client_get_next_task_in_tag(wm.client_focused, tag);
} else {
task = client_get_previous_task_in_tag(wm.client_focused, tag);
}
if (!task) return;
client_stack_raise(task->client);
client_focus(task->client);
}
void select_tag_of_current_monitor(const user_action_arg_t *arg) {
monitor_select_tag(wm.current_monitor, arg->ui);
}

View File

@@ -48,6 +48,7 @@ typedef struct keyboard_t {
const user_action_arg_t arg;
} keyboard_t;
void focus_client_in_same_tag(const user_action_arg_t *arg);
void select_tag_of_current_monitor(const user_action_arg_t *arg);
void spawn(const user_action_arg_t *arg);
void quit(const user_action_arg_t *arg);

View File

@@ -58,6 +58,22 @@ task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag) {
return nullptr;
}
task_in_tag_t *client_get_next_task_in_tag(client_t *client, tag_t *tag) {
if (!tag->task_list) return nullptr;
task_in_tag_t *task = tag->task_list;
for (; task && task->client != client; task = task->next);
return task && task->next ? task->next : tag->task_list;
}
task_in_tag_t *client_get_previous_task_in_tag(client_t *client, tag_t *tag) {
if (!tag->task_list) return nullptr;
task_in_tag_t *task = tag->task_list;
for (; task && task->next && task->next->client != client; task = task->next);
return task ? task : tag->task_list;
}
static void client_add_to_tag(client_t *client, tag_t *tag) {
if (client_get_task_in_tag(client, tag)) return;
@@ -191,6 +207,9 @@ void client_manage(xcb_window_t window,
monitor_arrange(c->monitor);
monitor_draw_bar(c->monitor);
wm_restack_clients();
if (c->tags & c->monitor->selected_tag->mask) client_focus(c);
xcb_flush(wm.xcb_conn);
}
@@ -277,6 +296,8 @@ void client_unmanage(client_t *client) {
client_wipe(client);
wm_restack_clients();
monitor_deal_focus(m);
monitor_arrange(m);
monitor_draw_bar(m);
xcb_flush(wm.xcb_conn);
@@ -295,6 +316,17 @@ void client_apply_task_geometry(client_t *client, task_in_tag_t *task) {
}
}
void client_focus(client_t *client) {
wm.client_focused = client;
xwindow_focus(client ? client->window : XCB_WINDOW_NONE);
}
void client_stack_raise(client_t *client) {
client_detach_stack(client);
client_attach_stack(client);
wm_restack_clients();
}
bool client_is_visible(client_t *client) {
return client->tags & client->monitor->selected_tag->mask;
}

View File

@@ -7,6 +7,8 @@
client_t *client_get_by_window(xcb_window_t window);
task_in_tag_t *client_get_task_in_tag(client_t *client, tag_t *tag);
task_in_tag_t *client_get_next_task_in_tag(client_t *client, tag_t *tag);
task_in_tag_t *client_get_previous_task_in_tag(client_t *client, tag_t *tag);
void client_manage(xcb_window_t window,
xcb_get_geometry_reply_t *geometry_reply);
char **client_get_task_title(client_t *client);

View File

@@ -36,6 +36,8 @@ static const keyboard_t key_list[] = {
{modifier_alt, XK_p, spawn, {.ptr = launcher}},
{modifier_alt, XK_q, quit, {.b = false}},
{modifier_alt, XK_r, quit, {.b = true}},
{modifier_alt | modifier_shift, XK_j, focus_client_in_same_tag, {.b = true}},
{modifier_alt | modifier_shift, XK_k, focus_client_in_same_tag, {.b = false}},
};
static const layout_t layout_list[] = {

View File

@@ -48,17 +48,33 @@ uint32_t monitor_initialize_tag(monitor_t *monitor, const char **tags,
return tag_count;
}
void monitor_deal_focus(monitor_t *monitor) {
if (!monitor->selected_tag->task_list) return;
client_t *client = nullptr;
for (client_t *c = wm.client_stack_list; c; c = c->stack_next) {
if (client_get_task_in_tag(c, monitor->selected_tag)) {
client = c;
break;
}
}
client_focus(client);
}
void monitor_select_tag(monitor_t *monitor, uint32_t tag_mask) {
if (monitor->selected_tag->mask == tag_mask) return;
for (tag_t *tag = monitor->tag_list; tag; tag = tag->next) {
if (tag->mask == tag_mask) {
monitor->selected_tag = tag;
monitor_arrange(monitor);
monitor_draw_bar(monitor);
xcb_flush(wm.xcb_conn);
break;
}
}
monitor_deal_focus(monitor);
}
static void tag_clean(tag_t *tag) {

View File

@@ -6,6 +6,7 @@
uint32_t monitor_initialize_tag(monitor_t *monitor, const char **tags,
uint32_t tag_index_start_at);
void monitor_deal_focus(monitor_t *monitor);
void monitor_select_tag(monitor_t *monitor, uint32_t tag_mask);
void monitor_clean(monitor_t *monitor);
void monitor_init_bar(monitor_t *monitor);

View File

@@ -390,6 +390,25 @@ void wm_quit(void) {
}
}
void wm_restack_clients(void) {
xcb_window_t sibling_window = XCB_WINDOW_NONE;
for (client_t *c = wm.client_stack_list; c; c = c->stack_next) {
uint16_t mask = XCB_CONFIG_WINDOW_STACK_MODE;
xcb_params_configure_window_t params = {};
if (sibling_window == XCB_WINDOW_NONE) {
mask = XCB_CONFIG_WINDOW_STACK_MODE;
params.stack_mode = XCB_STACK_MODE_ABOVE;
} else {
mask = XCB_CONFIG_WINDOW_STACK_MODE | XCB_CONFIG_WINDOW_SIBLING;
params.stack_mode = XCB_STACK_MODE_BELOW;
params.sibling = sibling_window;
}
sibling_window = c->window;
xcb_aux_configure_window(wm.xcb_conn, c->window, mask, &params);
}
xcb_flush(wm.xcb_conn);
}
static void debug_show_monitor_list(void) {
logger("\n========================== monitors ==========================\n");
for (monitor_t *m = wm.monitor_list; m; m = m->next) {

View File

@@ -51,3 +51,4 @@ extern wm_t wm;
void wm_restart(void);
void wm_quit(void);
void wm_restack_clients(void);

View File

@@ -187,6 +187,8 @@ void xwindow_get_text_property(xcb_window_t window, xcb_atom_t property,
wm.xcb_conn, false, window, property, XCB_ATOM_ANY, 0, UINT32_MAX);
xcb_get_property_reply_t *reply =
xcb_get_property_reply(wm.xcb_conn, cookie, nullptr);
if (!reply) return;
int length = xcb_get_property_value_length(reply);
char *value = xcb_get_property_value(reply);