Re-implement support for the urgency hint, extend t/13-urgent.t

The actual rendering will follow
This commit is contained in:
Michael Stapelberg
2010-06-02 17:51:58 +02:00
parent 03c8da0a74
commit 32be3af109
9 changed files with 137 additions and 75 deletions

View File

@ -91,6 +91,10 @@ void con_focus(Con *con) {
con_focus(con->parent);
focused = con;
if (con->urgent) {
con->urgent = false;
workspace_update_urgent_flag(con_get_workspace(con));
}
}
/*

View File

@ -810,6 +810,7 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
return 1;
}
#endif
/*
* Handles the WM_HINTS property for extracting the urgency state of the window.
@ -817,46 +818,49 @@ int handle_normal_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_w
*/
int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
xcb_atom_t name, xcb_get_property_reply_t *reply) {
Client *client = table_get(&by_child, window);
if (client == NULL) {
DLOG("Received WM_HINTS for unknown client\n");
return 1;
}
xcb_wm_hints_t hints;
if (reply != NULL) {
if (!xcb_get_wm_hints_from_reply(&hints, reply))
return 1;
} else {
if (!xcb_get_wm_hints_reply(conn, xcb_get_wm_hints_unchecked(conn, client->child), &hints, NULL))
return 1;
}
Client *last_focused = SLIST_FIRST(&(c_ws->focus_stack));
if (!client->urgent && client == last_focused) {
DLOG("Ignoring urgency flag for current client\n");
return 1;
}
/* Update the flag on the client directly */
client->urgent = (xcb_wm_hints_get_urgency(&hints) != 0);
CLIENT_LOG(client);
LOG("Urgency flag changed to %d\n", client->urgent);
workspace_update_urgent_flag(client->workspace);
redecorate_window(conn, client);
/* If the workspace this client is on is not visible, we need to redraw
* the workspace bar */
if (!workspace_is_visible(client->workspace)) {
Output *output = client->workspace->output;
render_workspace(conn, output, output->current_workspace);
xcb_flush(conn);
}
Con *con = con_by_window_id(window);
if (con == NULL) {
DLOG("Received WM_HINTS for unknown client\n");
return 1;
}
xcb_wm_hints_t hints;
if (reply != NULL) {
if (!xcb_get_wm_hints_from_reply(&hints, reply))
return 1;
} else {
if (!xcb_get_wm_hints_reply(conn, xcb_get_wm_hints_unchecked(conn, con->window->id), &hints, NULL))
return 1;
}
if (!con->urgent && focused == con) {
DLOG("Ignoring urgency flag for current client\n");
return 1;
}
/* Update the flag on the client directly */
con->urgent = (xcb_wm_hints_get_urgency(&hints) != 0);
//CLIENT_LOG(con);
LOG("Urgency flag changed to %d\n", con->urgent);
workspace_update_urgent_flag(con_get_workspace(con));
#if 0
/* If the workspace this client is on is not visible, we need to redraw
* the workspace bar */
if (!workspace_is_visible(client->workspace)) {
Output *output = client->workspace->output;
render_workspace(conn, output, output->current_workspace);
xcb_flush(conn);
}
#endif
return 1;
}
#if 0
/*
* Handles the transient for hints set by a window, signalizing that this window is a popup window
* for some other window.

View File

@ -137,6 +137,9 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
ystr("orientation");
y(integer, con->orientation);
ystr("urgent");
y(integer, con->urgent);
ystr("layout");
y(integer, con->layout);

View File

@ -2,6 +2,7 @@
* vim:ts=4:sw=4:expandtab
*/
#include <ev.h>
#include <limits.h>
#include "all.h"
static int xkb_event_base;
@ -254,6 +255,9 @@ int main(int argc, char *argv[]) {
/* Watch _NET_WM_NAME (title of the window encoded in UTF-8) */
xcb_property_set_handler(&prophs, atoms[_NET_WM_NAME], 128, handle_windowname_change, NULL);
/* Watch WM_HINTS (contains the urgent property) */
xcb_property_set_handler(&prophs, WM_HINTS, UINT_MAX, handle_hints, NULL);
/* Watch WM_NAME (title of the window encoded in COMPOUND_TEXT) */
xcb_watch_wm_name(&prophs, 128, handle_windowname_change_legacy, NULL);

View File

@ -429,31 +429,37 @@ void workspace_unmap_clients(xcb_connection_t *conn, Workspace *u_ws) {
ignore_enter_notify_forall(conn, u_ws, false);
}
#endif
static bool get_urgency_flag(Con *con) {
Con *child;
TAILQ_FOREACH(child, &(con->nodes_head), nodes)
if (child->urgent || get_urgency_flag(child))
return true;
TAILQ_FOREACH(child, &(con->floating_head), floating_windows)
if (child->urgent || get_urgency_flag(child))
return true;
return false;
}
/*
* Goes through all clients on the given workspace and updates the workspaces
* urgent flag accordingly.
*
*/
void workspace_update_urgent_flag(Workspace *ws) {
Client *current;
bool old_flag = ws->urgent;
bool urgent = false;
void workspace_update_urgent_flag(Con *ws) {
bool old_flag = ws->urgent;
ws->urgent = get_urgency_flag(ws);
DLOG("Workspace urgency flag changed from %d to %d\n", old_flag, ws->urgent);
SLIST_FOREACH(current, &(ws->focus_stack), focus_clients) {
if (!current->urgent)
continue;
urgent = true;
break;
}
ws->urgent = urgent;
if (old_flag != urgent)
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"urgent\"}");
if (old_flag != ws->urgent)
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"urgent\"}");
}
#if 0
/*
* Returns the width of the workspace.
*