GETATOM(WM_DELETE_WINDOW)
GETATOM(WM_TAKE_FOCUS)
GETATOM(_BSPWM_FLOATING_WINDOW)
+ GETATOM(_NET_WM_WINDOW_OPACITY)
#undef GETATOM
const xcb_query_extension_reply_t *qep = xcb_get_extension_data(dpy, &xcb_randr_id);
#define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY)
#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE)
-#define CLIENT_EVENT_MASK_FFP (CLIENT_EVENT_MASK | XCB_EVENT_MASK_ENTER_WINDOW)
xcb_connection_t *dpy;
int default_screen, screen_width, screen_height;
xcb_window_t motion_recorder;
xcb_atom_t WM_TAKE_FOCUS;
xcb_atom_t WM_DELETE_WINDOW;
+xcb_atom_t _NET_WM_WINDOW_OPACITY;
xcb_atom_t _BSPWM_FLOATING_WINDOW;
int exit_status;
_bspc() {
local commands='window desktop monitor query pointer rule restore control config quit'
- local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color focused_sticky_border_color normal_sticky_border_color urgent_border_color border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio growth_factor borderless_monocle gapless_monocle focus_follows_pointer pointer_follows_monitor apply_floating_atom auto_alternate auto_cancel history_aware_focus honor_ewmh_focus'
+ local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color focused_sticky_border_color normal_sticky_border_color urgent_border_color focused_frame_opacity active_frame_opacity normal_frame_opacity border_width window_gap top_padding right_padding bottom_padding left_padding split_ratio growth_factor borderless_monocle gapless_monocle focus_follows_pointer pointer_follows_monitor apply_floating_atom auto_alternate auto_cancel history_aware_focus honor_ewmh_focus'
COMPREPLY=()
--- /dev/null
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <xcb/xcb.h>
+#include <xcb/xcb_event.h>
+#include <xcb/xcb_icccm.h>
+
+#define FRAME_CLASS_NAME "BSPWM_FRAME"
+#define FRAME_INSTANCE_NAME "bspwm_frame"
+
+xcb_connection_t *dpy;
+
+bool get_atom(char *name, xcb_atom_t *atom)
+{
+ bool ack = true;
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(dpy, xcb_intern_atom(dpy, 0, strlen(name), name), NULL);
+ if (reply != NULL)
+ *atom = reply->atom;
+ else
+ ack = false;
+ free(reply);
+ return ack;
+}
+
+int main(int argc, char *argv[])
+{
+ dpy = xcb_connect(NULL, NULL);
+ if (dpy == NULL)
+ return EXIT_FAILURE;
+ xcb_atom_t WM_PROTOCOLS, WM_DELETE_WINDOW;
+ if (!get_atom("WM_PROTOCOLS", &WM_PROTOCOLS)
+ || !get_atom("WM_DELETE_WINDOW", &WM_DELETE_WINDOW)) {
+ xcb_disconnect(dpy);
+ return EXIT_FAILURE;
+ }
+ xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data;
+ if (screen == NULL)
+ return EXIT_FAILURE;
+ xcb_window_t root = screen->root;
+ xcb_window_t win = xcb_generate_id(dpy);
+ xcb_create_window(dpy, XCB_COPY_FROM_PARENT, win, root, 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, NULL);
+ xcb_icccm_set_wm_class(dpy, win, strlen(FRAME_CLASS_NAME) + strlen(FRAME_INSTANCE_NAME) + 1, FRAME_INSTANCE_NAME "\0" FRAME_CLASS_NAME);
+ xcb_map_window(dpy, win);
+ xcb_flush(dpy);
+ xcb_generic_event_t *evt;
+ bool running = true;
+ while (running && (evt = xcb_wait_for_event(dpy)) != NULL) {
+ uint8_t rt = XCB_EVENT_RESPONSE_TYPE(evt);
+ if (rt == XCB_CLIENT_MESSAGE) {
+ xcb_client_message_event_t *cme = (xcb_client_message_event_t *) evt;
+ if (cme->type == WM_PROTOCOLS && cme->data.data32[0] == WM_DELETE_WINDOW)
+ running = false;
+ }
+ free(evt);
+ }
+ xcb_destroy_window(dpy, win);
+ xcb_disconnect(dpy);
+ return EXIT_SUCCESS;
+}
_bspc() {
local -a commands settings
commands=('window' 'desktop' 'monitor' 'query' 'pointer' 'rule' 'restore' 'control' 'config' 'quit')
- settings=('focused_border_color' 'active_border_color' 'normal_border_color' 'presel_border_color' 'focused_locked_border_color' 'active_locked_border_color' 'normal_locked_border_color' 'focused_sticky_border_color' 'normal_sticky_border_color' 'urgent_border_color' 'border_width' 'window_gap' 'top_padding' 'right_padding' 'bottom_padding' 'left_padding' 'split_ratio' 'growth_factor' 'borderless_monocle' 'gapless_monocle' 'focus_follows_pointer' 'pointer_follows_monitor' 'apply_floating_atom' 'auto_alternate' 'auto_cancel' 'history_aware_focus' 'honor_ewmh_focus')
+ settings=('focused_border_color' 'active_border_color' 'normal_border_color' 'presel_border_color' 'focused_locked_border_color' 'active_locked_border_color' 'normal_locked_border_color' 'focused_sticky_border_color' 'normal_sticky_border_color' 'urgent_border_color' 'focused_frame_opacity' 'active_frame_opacity' 'normal_frame_opacity' 'border_width' 'window_gap' 'top_padding' 'right_padding' 'bottom_padding' 'left_padding' 'split_ratio' 'growth_factor' 'borderless_monocle' 'gapless_monocle' 'focus_follows_pointer' 'pointer_follows_monitor' 'apply_floating_atom' 'auto_alternate' 'auto_cancel' 'history_aware_focus' 'honor_ewmh_focus')
if (( CURRENT == 2 )) ; then
_values 'command' "$commands[@]"
elif (( CURRENT == 3 )) ; then
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
-.\" Date: 10/08/2013
+.\" Date: 10/10/2013
.\" Manual: Bspwm Manual
.\" Source: Bspwm 0.8.5
.\" Language: English
.\"
-.TH "BSPWM" "1" "10/08/2013" "Bspwm 0\&.8\&.5" "Bspwm Manual"
+.TH "BSPWM" "1" "10/10/2013" "Bspwm 0\&.8\&.5" "Bspwm Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
\fBOptions\fR
.RS 4
.PP
-\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name> [\-d \fIDESKTOP_SEL\fR [\-\-follow]] [\-\-tags <name>|^<n>[,\&...]][\-\-floating] [\-\-fullscreen] [\-\-locked] [\-\-sticky] [\-\-focus] [\-\-unmanage] [\-\-one\-shot]
+\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name> [\-d \fIDESKTOP_SEL\fR [\-\-follow]] [\-\-tags <name>|^<n>[,\&...]][\-\-floating] [\-\-fullscreen] [\-\-locked] [\-\-sticky] [\-\-focus] [\-\-frame] [\-\-unmanage] [\-\-one\-shot]
.RS 4
Create a new rule\&.
.RE
Color of the border of an urgent window\&.
.RE
.PP
+\fIfocused_frame_opacity\fR
+.RS 4
+Opacity of a focused frame of a focused monitor\&.
+.RE
+.PP
+\fIactive_frame_opacity\fR
+.RS 4
+Opacity of a focused frame of an unfocused monitor\&.
+.RE
+.PP
+\fInormal_frame_opacity\fR
+.RS 4
+Opacity of an unfocused frame\&.
+.RE
+.PP
\fIsplit_ratio\fR
.RS 4
Default split ratio\&.
Options
^^^^^^^
-*-a*, *--add* <class_name>|<instance_name> [-d 'DESKTOP_SEL' [--follow]] [--tags <name>|^<n>[,...]][--floating] [--fullscreen] [--locked] [--sticky] [--focus] [--unmanage] [--one-shot]::
+*-a*, *--add* <class_name>|<instance_name> [-d 'DESKTOP_SEL' [--follow]] [--tags <name>|^<n>[,...]][--floating] [--fullscreen] [--locked] [--sticky] [--focus] [--frame] [--unmanage] [--one-shot]::
Create a new rule.
*-r*, *--remove* <name>|^<n>|tail|head...::
'urgent_border_color'::
Color of the border of an urgent window.
+'focused_frame_opacity'::
+ Opacity of a focused frame of a focused monitor.
+
+'active_frame_opacity'::
+ Opacity of a focused frame of an unfocused monitor.
+
+'normal_frame_opacity'::
+ Opacity of an unfocused frame.
+
'split_ratio'::
Default split ratio.
case XCB_FOCUS_IN:
focus_in(evt);
break;
+ case XCB_EXPOSE:
+ expose(evt);
+ break;
default:
if (randr && resp_type == randr_base + XCB_RANDR_SCREEN_CHANGE_NOTIFY)
import_monitors();
update_input_focus();
}
+void expose(xcb_generic_event_t *evt)
+{
+ xcb_expose_event_t *e = (xcb_expose_event_t *) evt;
+
+ PRINTF("expose %X\n", e->window);
+
+ coordinates_t loc;
+ if (locate_window(e->window, &loc) && loc.node->client->frame)
+ draw_frame_background(loc.node, loc.desktop->focus == loc.node, loc.monitor == mon);
+}
+
void enter_notify(xcb_generic_event_t *evt)
{
xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt;
void property_notify(xcb_generic_event_t *evt);
void client_message(xcb_generic_event_t *evt);
void focus_in(xcb_generic_event_t *evt);
+void expose(xcb_generic_event_t *evt);
void enter_notify(xcb_generic_event_t *evt);
void motion_notify(xcb_generic_event_t *evt);
void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action);
rule->effect.follow = true;
} else if (streq("--focus", *args)) {
rule->effect.focus = true;
+ } else if (streq("--frame", *args)) {
+ rule->effect.frame = true;
} else if (streq("--unmanage", *args)) {
rule->effect.unmanage = true;
} else if (streq("--one-shot", *args)) {
else
return false;
return true;
+#define SETOPACITY(s) \
+ } else if (streq(#s, name)) { \
+ double o; \
+ if (sscanf(value, "%lf", &o) == 1 && o >= 0 && o <= 1) \
+ s = o; \
+ else \
+ return false; \
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) \
+ for (node_t *n = first_extrema(m->desk->root); n != NULL; n = next_leaf(n, m->desk->root)) \
+ if (is_visible(m->desk, n) && n->client->frame) \
+ draw_frame_background(n, m->desk->focus == n, m == mon);
+ SETOPACITY(focused_frame_opacity)
+ SETOPACITY(active_frame_opacity)
+ SETOPACITY(normal_frame_opacity)
+#undef SETOPACITY
#define SETCOLOR(s) \
} else if (streq(#s, name)) { \
snprintf(s, sizeof(s), "%s", value);
} else if (streq("focus_follows_pointer", name)) {
bool b;
if (parse_bool(value, &b) && b != focus_follows_pointer) {
- uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK : CLIENT_EVENT_MASK_FFP)};
+ focus_follows_pointer = b;
for (monitor_t *m = mon_head; m != NULL; m = m->next)
for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
- for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
+ for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
+ uint32_t values[] = {get_event_mask(n->client)};
xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
+ }
if (focus_follows_pointer) {
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- window_hide(m->root);
- disable_motion_recorder();
- } else {
for (monitor_t *m = mon_head; m != NULL; m = m->next)
window_show(m->root);
enable_motion_recorder();
+ } else {
+ for (monitor_t *m = mon_head; m != NULL; m = m->next)
+ window_hide(m->root);
+ disable_motion_recorder();
}
- focus_follows_pointer = b;
return true;
} else {
return false;
MONGET(bottom_padding)
MONGET(left_padding)
#undef MONGET
+#define GETOPACITY(s) \
+ else if (streq(#s, name)) \
+ snprintf(rsp, BUFSIZ, "%lf", s);
+ GETOPACITY(focused_frame_opacity)
+ GETOPACITY(active_frame_opacity)
+ GETOPACITY(normal_frame_opacity)
+#undef GETOPACITY
#define GETCOLOR(s) \
else if (streq(#s, name)) \
snprintf(rsp, BUFSIZ, "%s", s);
if (is_leaf(n)) {
client_t *c = n->client;
- snprintf(line, sizeof(line), "%c %s 0x%X %u %u %ux%u%+i%+i %c %c%c%c%c%c%c%c", (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), c->class_name, c->window, c->tags_field, c->border_width, c->floating_rectangle.width, c->floating_rectangle.height, c->floating_rectangle.x, c->floating_rectangle.y, (n->split_dir == DIR_UP ? 'U' : (n->split_dir == DIR_RIGHT ? 'R' : (n->split_dir == DIR_DOWN ? 'D' : 'L'))), (c->floating ? 'f' : '-'), (c->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (n->split_mode ? 'p' : '-'));
+ snprintf(line, sizeof(line), "%c %s 0x%X %u %u %ux%u%+i%+i %c %c%c%c%c%c%c%c%c", (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), c->class_name, c->window, c->tags_field, c->border_width, c->floating_rectangle.width, c->floating_rectangle.height, c->floating_rectangle.x, c->floating_rectangle.y, (n->split_dir == DIR_UP ? 'U' : (n->split_dir == DIR_RIGHT ? 'R' : (n->split_dir == DIR_DOWN ? 'D' : 'L'))), (c->floating ? 'f' : '-'), (c->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->frame ? 'e' : '-'), (n->split_mode ? 'p' : '-'));
} else {
snprintf(line, sizeof(line), "%c %c %.2f", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'), (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), n->split_ratio);
}
} else {
client_t *c = make_client(XCB_NONE);
num_clients++;
- char floating, transient, fullscreen, urgent, locked, sticky, sd, sm, end = 0;
- sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->tags_field, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &transient, &fullscreen, &urgent, &locked, &sticky, &sm, &end);
+ char floating, transient, fullscreen, urgent, locked, sticky, frame, sd, sm, end = 0;
+ sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->tags_field, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &transient, &fullscreen, &urgent, &locked, &sticky, &frame, &sm, &end);
c->floating = (floating == '-' ? false : true);
c->transient = (transient == '-' ? false : true);
c->fullscreen = (fullscreen == '-' ? false : true);
c->urgent = (urgent == '-' ? false : true);
c->locked = (locked == '-' ? false : true);
c->sticky = (sticky == '-' ? false : true);
+ c->frame = (frame == '-' ? false : true);
n->split_mode = (sm == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
if (sd == 'U')
n->split_dir = DIR_UP;
for (monitor_t *m = mon_head; m != NULL; m = m->next)
for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
- uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
+ uint32_t values[] = {get_event_mask(n->client)};
xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
if (n->client->floating || !is_visible(d, n)) {
n->vacant = true;
r->effect.sticky = false;
r->effect.follow = false;
r->effect.focus = false;
+ r->effect.frame = false;
r->effect.unmanage = false;
r->one_shot = false;
r->effect.desc[0] = '\0';
return false;
}
-void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *manage)
+void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *frame, bool *manage)
{
xcb_ewmh_get_atoms_reply_t win_type;
*follow = true;
if (efc.focus)
*takes_focus = true;
+ if (efc.frame)
+ *frame = true;
if (efc.unmanage)
*manage = false;
if (efc.desc[0] != '\0') {
strncat(rsp, " --follow", REMLEN(rsp));
if (r->effect.focus)
strncat(rsp, " --focus", REMLEN(rsp));
+ if (r->effect.frame)
+ strncat(rsp, " --frame", REMLEN(rsp));
if (r->effect.unmanage)
strncat(rsp, " --unmanage", REMLEN(rsp));
if (r->one_shot)
void remove_rule_by_name(char *name);
bool remove_rule_by_index(int idx);
bool is_match(rule_t *r, xcb_window_t win);
-void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *manage);
+void handle_rules(xcb_window_t win, monitor_t **m, desktop_t **d, unsigned int *tags_field, bool *floating, bool *fullscreen, bool *locked, bool *sticky, bool *follow, bool *transient, bool *takes_focus, bool *frame, bool *manage);
void list_rules(char *pattern, char *rsp);
#endif
snprintf(normal_sticky_border_color, sizeof(normal_sticky_border_color), "%s", NORMAL_STICKY_BORDER_COLOR);
snprintf(urgent_border_color, sizeof(urgent_border_color), "%s", URGENT_BORDER_COLOR);
+ focused_frame_opacity = FOCUSED_FRAME_OPACITY;
+ active_frame_opacity = ACTIVE_FRAME_OPACITY;
+ normal_frame_opacity = NORMAL_FRAME_OPACITY;
+
split_ratio = SPLIT_RATIO;
growth_factor = GROWTH_FACTOR;
#define NORMAL_STICKY_BORDER_COLOR "#3F3E3B"
#define URGENT_BORDER_COLOR "#EFA29A"
+#define FOCUSED_FRAME_OPACITY 0.5
+#define ACTIVE_FRAME_OPACITY 0.25
+#define NORMAL_FRAME_OPACITY 0.125
+
#define SPLIT_RATIO 0.5
#define GROWTH_FACTOR 1.1
char normal_sticky_border_color[MAXLEN];
char urgent_border_color[MAXLEN];
+double focused_frame_opacity;
+double active_frame_opacity;
+double normal_frame_opacity;
+
double split_ratio;
double growth_factor;
n->client->floating_rectangle.height += ds;
}
- if ((borderless_monocle && is_tiled(n->client) && d->layout == LAYOUT_MONOCLE) ||
- n->client->fullscreen)
+ if ((borderless_monocle && is_tiled(n->client) && d->layout == LAYOUT_MONOCLE)
+ || n->client->fullscreen
+ || n->client->frame)
n->client->border_width = 0;
else
n->client->border_width = d->border_width;
window_move_resize(n->client->window, r.x, r.y, r.width, r.height);
window_border_width(n->client->window, n->client->border_width);
- window_draw_border(n, n == d->focus, m == mon);
+ window_draw_border(n, d->focus == n, m == mon);
} else {
xcb_rectangle_t first_rect;
c->border_width = BORDER_WIDTH;
c->window = win;
c->floating = c->transient = c->fullscreen = c->locked = c->sticky = c->urgent = false;
- c->icccm_focus = false;
+ c->frame = c->icccm_focus = false;
xcb_icccm_get_wm_protocols_reply_t protocols;
if (xcb_icccm_get_wm_protocols_reply(dpy, xcb_icccm_get_wm_protocols(dpy, win, ewmh->WM_PROTOCOLS), &protocols, NULL) == 1) {
if (has_proto(WM_TAKE_FOCUS, &protocols))
bool locked; /* protects window from being closed */
bool sticky;
bool urgent;
+ bool frame;
bool icccm_focus;
xcb_rectangle_t floating_rectangle;
xcb_rectangle_t tiled_rectangle;
bool follow;
bool focus;
bool unmanage;
+ bool frame;
char desc[MAXLEN];
char tags[MAXLEN];
} rule_effect_t;
if (override_redirect || locate_window(win, &loc))
return;
- bool floating = false, fullscreen = false, locked = false, sticky = false, follow = false, transient = false, takes_focus = true, manage = true;
+ bool floating = false, fullscreen = false, locked = false, sticky = false, follow = false, transient = false, takes_focus = true, frame = false, manage = true;
unsigned int tags_field = 0;
- handle_rules(win, &m, &d, &tags_field, &floating, &fullscreen, &locked, &sticky, &follow, &transient, &takes_focus, &manage);
+ handle_rules(win, &m, &d, &tags_field, &floating, &fullscreen, &locked, &sticky, &follow, &transient, &takes_focus, &frame, &manage);
if (!manage) {
disable_floating_atom(win);
client_t *c = make_client(win);
update_floating_rectangle(c);
c->tags_field = (tags_field == 0 ? d->tags_field : tags_field);
+ c->frame = frame;
xcb_icccm_get_wm_class_reply_t reply;
if (xcb_icccm_get_wm_class_reply(dpy, xcb_icccm_get_wm_class(dpy, win), &reply, NULL) == 1) {
tag_node(m, d, n, d, n->client->tags_field);
+ xcb_rectangle_t *frect = &n->client->floating_rectangle;
+ if (frect->x == 0 && frect->y == 0)
+ center(m->rectangle, frect);
+ fit_monitor(m, n->client);
+
+ arrange(m, d);
+
bool give_focus = (takes_focus && (d == mon->desk || follow));
if (is_visible(d, n)) {
stack_under(n);
}
- xcb_rectangle_t *frect = &n->client->floating_rectangle;
- if (frect->x == 0 && frect->y == 0)
- center(m->rectangle, frect);
-
- fit_monitor(m, n->client);
-
- arrange(m, d);
+ uint32_t values[] = {get_event_mask(n->client)};
+ xcb_change_window_attributes(dpy, c->window, XCB_CW_EVENT_MASK, values);
if (visible && is_visible(d, n)) {
if (d == m->desk)
if (give_focus)
xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
- uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
- xcb_change_window_attributes(dpy, c->window, XCB_CW_EVENT_MASK, values);
-
num_clients++;
ewmh_set_wm_desktop(n, d);
ewmh_update_client_list();
void window_draw_border(node_t *n, bool focused_window, bool focused_monitor)
{
- if (n == NULL || n->client->border_width < 1)
+ if (n == NULL || (n->client->border_width < 1 && !n->client->frame)) {
+ return;
+ }
+
+ if (n->client->frame) {
+ draw_frame_background(n, focused_window, focused_monitor);
return;
+ }
xcb_window_t win = n->client->window;
uint32_t border_color_pxl = get_border_color(n->client, focused_window, focused_monitor);
}
}
+void draw_frame_background(node_t *n, bool focused_window, bool focused_monitor)
+{
+ if (n == NULL)
+ return;
+
+ xcb_window_t win = n->client->window;
+ uint32_t border_color_pxl = get_border_color(n->client, focused_window, focused_monitor);
+ uint32_t opacity = (focused_window ? (focused_monitor ? focused_frame_opacity : active_frame_opacity) : normal_frame_opacity) * 0xffffffff;
+ xcb_change_property(dpy, XCB_PROP_MODE_REPLACE, win, _NET_WM_WINDOW_OPACITY, XCB_ATOM_CARDINAL, 32, 1, &opacity);
+ uint8_t win_depth = root_depth;
+ xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
+ if (geo != NULL)
+ win_depth = geo->depth;
+ free(geo);
+ xcb_rectangle_t rectangle = get_rectangle(n->client);
+ rectangle.x = rectangle.y = 0;
+ uint16_t width = rectangle.width;
+ uint16_t height = rectangle.height;
+ xcb_pixmap_t pixmap = xcb_generate_id(dpy);
+ xcb_create_pixmap(dpy, win_depth, pixmap, win, width, height);
+ xcb_gcontext_t gc = xcb_generate_id(dpy);
+ xcb_create_gc(dpy, gc, pixmap, 0, NULL);
+ xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &border_color_pxl);
+ xcb_poly_fill_rectangle(dpy, pixmap, gc, 1, &rectangle);
+ if (n->split_mode == MODE_MANUAL) {
+ xcb_rectangle_t presel_rectangle = rectangle;
+ uint32_t presel_border_color_pxl;
+ get_color(presel_border_color, win, &presel_border_color_pxl);
+ xcb_change_gc(dpy, gc, XCB_GC_FOREGROUND, &presel_border_color_pxl);
+ switch (n->split_dir) {
+ case DIR_UP:
+ presel_rectangle.height = n->split_ratio * rectangle.height;
+ break;
+ case DIR_RIGHT:
+ presel_rectangle.width = (1 - n->split_ratio) * rectangle.width;
+ presel_rectangle.x = rectangle.width - presel_rectangle.width;
+ break;
+ case DIR_DOWN:
+ presel_rectangle.height = (1 - n->split_ratio) * rectangle.height;
+ presel_rectangle.y = rectangle.height - presel_rectangle.height;
+ break;
+ case DIR_LEFT:
+ presel_rectangle.width = n->split_ratio * rectangle.width;
+ break;
+ }
+ xcb_poly_fill_rectangle(dpy, pixmap, gc, 1, &presel_rectangle);
+ }
+ xcb_copy_area(dpy, pixmap, win, gc, 0, 0, 0, 0, width, height);
+ xcb_free_gc(dpy, gc);
+ xcb_free_pixmap(dpy, pixmap);
+}
+
pointer_state_t *make_pointer_state(void)
{
pointer_state_t *p = malloc(sizeof(pointer_state_t));
void set_fullscreen(node_t *n, bool value)
{
- if (n == NULL || n->client->fullscreen == value)
+ if (n == NULL || n->client->frame || n->client->fullscreen == value)
return;
client_t *c = n->client;
void set_floating(node_t *n, bool value)
{
- if (n == NULL || n->client->transient || n->client->fullscreen || n->client->floating == value)
+ if (n == NULL || n->client->transient || n->client->fullscreen || n->client->frame || n->client->floating == value)
return;
PRINTF("floating %X: %s\n", n->client->window, BOOLSTR(value));
m->num_sticky--;
}
- window_draw_border(n, mon->desk->focus == n, m == mon);
+ window_draw_border(n, d->focus == n, m == mon);
}
void set_urgency(monitor_t *m, desktop_t *d, node_t *n, bool value)
xcb_send_event(dpy, false, win, XCB_EVENT_MASK_NO_EVENT, (char *) &e);
}
+
+uint32_t get_event_mask(client_t *c)
+{
+ return CLIENT_EVENT_MASK | (c->frame ? XCB_EVENT_MASK_EXPOSURE : 0) | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0);
+}
void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win);
void window_draw_border(node_t *n, bool focused_window, bool focused_monitor);
+void draw_frame_background(node_t *n, bool focused_window, bool focused_monitor);
pointer_state_t *make_pointer_state(void);
void center(xcb_rectangle_t a, xcb_rectangle_t *b);
bool contains(xcb_rectangle_t a, xcb_rectangle_t b);
void set_atom(xcb_window_t win, xcb_atom_t atom, uint32_t value);
bool has_proto(xcb_atom_t atom, xcb_icccm_get_wm_protocols_reply_t *protocols);
void send_client_message(xcb_window_t win, xcb_atom_t property, xcb_atom_t value);
+uint32_t get_event_mask(client_t *c);
#endif