add a shaded button
@@ -42,6 +42,8 @@ pixmap_mask *ob_s_max_unset_mask;
pixmap_mask *ob_s_iconify_mask; pixmap_mask *ob_s_desk_set_mask; pixmap_mask *ob_s_desk_unset_mask; +pixmap_mask *ob_s_shade_set_mask; +pixmap_mask *ob_s_shade_unset_mask; pixmap_mask *ob_s_close_mask; /* global appearances */@@ -61,6 +63,12 @@ Appearance *ob_a_focused_pressed_set_desk;
Appearance *ob_a_unfocused_unpressed_desk; Appearance *ob_a_unfocused_pressed_desk; Appearance *ob_a_unfocused_pressed_set_desk; +Appearance *ob_a_focused_unpressed_shade; +Appearance *ob_a_focused_pressed_shade; +Appearance *ob_a_focused_pressed_set_shade; +Appearance *ob_a_unfocused_unpressed_shade; +Appearance *ob_a_unfocused_pressed_shade; +Appearance *ob_a_unfocused_pressed_set_shade; Appearance *ob_a_focused_unpressed_iconify; Appearance *ob_a_focused_pressed_iconify; Appearance *ob_a_unfocused_unpressed_iconify;@@ -92,6 +100,7 @@ g_quark_from_string("blcorner");
g_quark_from_string("brcorner"); g_quark_from_string("maximize"); g_quark_from_string("alldesktops"); + g_quark_from_string("shade"); g_quark_from_string("iconify"); g_quark_from_string("icon"); g_quark_from_string("close");@@ -109,6 +118,7 @@ ob_s_titlebut_unfocused_color = ob_s_titlebut_focused_color = NULL;
ob_s_winfont = NULL; ob_s_max_set_mask = ob_s_max_unset_mask = NULL; ob_s_desk_set_mask = ob_s_desk_unset_mask = NULL; + ob_s_shade_set_mask = ob_s_shade_unset_mask = NULL; ob_s_iconify_mask = ob_s_close_mask = NULL; ob_a_focused_unpressed_max = appearance_new(Surface_Planar, 1);@@ -127,6 +137,12 @@ ob_a_focused_pressed_set_desk = NULL;
ob_a_unfocused_unpressed_desk = NULL; ob_a_unfocused_pressed_desk = NULL; ob_a_unfocused_pressed_set_desk = NULL; + ob_a_focused_unpressed_shade = NULL; + ob_a_focused_pressed_shade = NULL; + ob_a_focused_pressed_set_shade = NULL; + ob_a_unfocused_unpressed_shade = NULL; + ob_a_unfocused_pressed_shade = NULL; + ob_a_unfocused_pressed_set_shade = NULL; ob_a_focused_unpressed_iconify = NULL; ob_a_focused_pressed_iconify = NULL; ob_a_unfocused_unpressed_iconify = NULL;@@ -154,6 +170,18 @@ RECT_SET(ob_a_unfocused_pressed_set_desk->area, 0, 0,
BUTTON_SIZE, BUTTON_SIZE); RECT_SET(ob_a_unfocused_unpressed_desk->area, 0, 0, BUTTON_SIZE, BUTTON_SIZE); + RECT_SET(ob_a_focused_pressed_shade->area, 0, 0, + BUTTON_SIZE, BUTTON_SIZE); + RECT_SET(ob_a_focused_pressed_set_shade->area, 0, 0, + BUTTON_SIZE, BUTTON_SIZE); + RECT_SET(ob_a_focused_unpressed_shade->area, 0, 0, + BUTTON_SIZE, BUTTON_SIZE); + RECT_SET(ob_a_unfocused_pressed_shade->area, 0, 0, + BUTTON_SIZE, BUTTON_SIZE); + RECT_SET(ob_a_unfocused_pressed_set_shade->area, 0, 0, + BUTTON_SIZE, BUTTON_SIZE); + RECT_SET(ob_a_unfocused_unpressed_shade->area, 0, 0, + BUTTON_SIZE, BUTTON_SIZE); RECT_SET(ob_a_focused_pressed_iconify->area, 0, 0, BUTTON_SIZE, BUTTON_SIZE); RECT_SET(ob_a_focused_unpressed_iconify->area, 0, 0,@@ -214,6 +242,10 @@ if (ob_s_desk_set_mask != NULL)
pixmap_mask_free(ob_s_desk_set_mask); if (ob_s_desk_unset_mask != NULL) pixmap_mask_free(ob_s_desk_unset_mask); + if (ob_s_shade_set_mask != NULL) + pixmap_mask_free(ob_s_shade_set_mask); + if (ob_s_shade_unset_mask != NULL) + pixmap_mask_free(ob_s_shade_unset_mask); if (ob_s_iconify_mask != NULL) pixmap_mask_free(ob_s_iconify_mask); if (ob_s_close_mask != NULL)@@ -243,6 +275,14 @@ if (ob_a_unfocused_unpressed_desk != NULL)
appearance_free(ob_a_unfocused_unpressed_desk); if (ob_a_unfocused_pressed_desk != NULL) appearance_free(ob_a_unfocused_pressed_desk); + if (ob_a_focused_unpressed_shade != NULL) + appearance_free(ob_a_focused_unpressed_shade); + if (ob_a_focused_pressed_shade != NULL) + appearance_free(ob_a_focused_pressed_shade); + if (ob_a_unfocused_unpressed_shade != NULL) + appearance_free(ob_a_unfocused_unpressed_shade); + if (ob_a_unfocused_pressed_shade != NULL) + appearance_free(ob_a_unfocused_pressed_shade); if (ob_a_focused_unpressed_iconify != NULL) appearance_free(ob_a_focused_unpressed_iconify); if (ob_a_focused_pressed_iconify != NULL)@@ -297,6 +337,7 @@ self->label = createWindow(self->title, mask, &attrib);
self->max = createWindow(self->title, mask, &attrib); self->close = createWindow(self->title, mask, &attrib); self->desk = createWindow(self->title, mask, &attrib); + self->shade = createWindow(self->title, mask, &attrib); self->icon = createWindow(self->title, mask, &attrib); self->iconify = createWindow(self->title, mask, &attrib); self->handle = createWindow(self->frame.window, mask, &attrib);@@ -323,6 +364,7 @@ XResizeWindow(ob_display, self->iconify, BUTTON_SIZE, BUTTON_SIZE);
XResizeWindow(ob_display, self->icon, BUTTON_SIZE, BUTTON_SIZE); XResizeWindow(ob_display, self->close, BUTTON_SIZE, BUTTON_SIZE); XResizeWindow(ob_display, self->desk, BUTTON_SIZE, BUTTON_SIZE); + XResizeWindow(ob_display, self->shade, BUTTON_SIZE, BUTTON_SIZE); XResizeWindow(ob_display, self->lgrip, GRIP_WIDTH, ob_s_handle_height); XResizeWindow(ob_display, self->rgrip, GRIP_WIDTH, ob_s_handle_height);@@ -336,7 +378,7 @@ self->a_focused_handle = appearance_copy(ob_a_focused_handle);
self->a_icon = appearance_copy(ob_a_icon); self->max_press = self->close_press = self->desk_press = - self->iconify_press = FALSE; + self->iconify_press = self->shade_press = FALSE; dispatch_register(Event_X_ButtonPress | Event_X_ButtonRelease, (EventHandler)mouse_event, self);@@ -451,6 +493,7 @@
/* they all default off, they're turned on in layout_title */ self->icon_x = -1; self->desk_x = -1; + self->shade_x = -1; self->icon_x = -1; self->label_x = -1; self->max_x = -1;@@ -470,13 +513,8 @@ self->width, TITLE_HEIGHT);
/* layout the title bar elements */ layout_title(self); - } else { + } else XUnmapWindow(ob_display, self->title); - /* make all the titlebar stuff not render */ - self->frame.client->decorations &= ~(Decor_Icon | Decor_Iconify | - Decor_Maximize | Decor_Close | - Decor_AllDesktops); - } if (self->frame.client->decorations & Decor_Handle) { XMoveResizeWindow(ob_display, self->handle,@@ -618,6 +656,7 @@ g_hash_table_insert(client_map, &self->label, client);
g_hash_table_insert(client_map, &self->max, client); g_hash_table_insert(client_map, &self->close, client); g_hash_table_insert(client_map, &self->desk, client); + g_hash_table_insert(client_map, &self->shade, client); g_hash_table_insert(client_map, &self->icon, client); g_hash_table_insert(client_map, &self->iconify, client); g_hash_table_insert(client_map, &self->handle, client);@@ -653,6 +692,7 @@ g_hash_table_remove(client_map, &self->label);
g_hash_table_remove(client_map, &self->max); g_hash_table_remove(client_map, &self->close); g_hash_table_remove(client_map, &self->desk); + g_hash_table_remove(client_map, &self->shade); g_hash_table_remove(client_map, &self->icon); g_hash_table_remove(client_map, &self->iconify); g_hash_table_remove(client_map, &self->handle);@@ -666,10 +706,10 @@ static void layout_title(ObFrame *self)
{ char *lc; int x; - gboolean n, d, i, l, m ,c; + gboolean n, d, i, l, m, c, s; ConfigValue layout; - n = d = i = l = m = c = FALSE; + n = d = i = l = m = c = s = FALSE; if (!config_get("titlebar.layout", Config_String, &layout)) { layout.string = "NDLIMC";@@ -692,6 +732,12 @@ if (d) { *lc = ' '; break; } /* rm duplicates */
d = TRUE; self->label_width -= BUTTON_SIZE + ob_s_bevel + 1; break; + case 'S': + if (!(self->frame.client->decorations & Decor_Shade)) break; + if (s) { *lc = ' '; break; } /* rm duplicates */ + s = TRUE; + self->label_width -= BUTTON_SIZE + ob_s_bevel + 1; + break; case 'I': if (!(self->frame.client->decorations & Decor_Iconify)) break; if (i) { *lc = ' '; break; } /* rm duplicates */@@ -723,6 +769,7 @@ LABEL_HEIGHT);
if (!n) XUnmapWindow(ob_display, self->icon); if (!d) XUnmapWindow(ob_display, self->desk); + if (!s) XUnmapWindow(ob_display, self->shade); if (!i) XUnmapWindow(ob_display, self->iconify); if (!l) XUnmapWindow(ob_display, self->label); if (!m) XUnmapWindow(ob_display, self->max);@@ -746,6 +793,13 @@ XMapWindow(ob_display, self->desk);
XMoveWindow(ob_display, self->desk, x, ob_s_bevel + 1); x += BUTTON_SIZE + ob_s_bevel + 1; break; + case 'S': + if (!s) break; + self->shade_x = x; + XMapWindow(ob_display, self->shade); + XMoveWindow(ob_display, self->shade, x, ob_s_bevel + 1); + x += BUTTON_SIZE + ob_s_bevel + 1; + break; case 'I': if (!i) break; self->iconify_x = x;@@ -801,6 +855,9 @@ obrender_frame(self);
} else if (win == self->desk) { self->desk_press = press; obrender_frame(self); + } else if (win == self->shade) { + self->shade_press = press; + obrender_frame(self); } }@@ -825,6 +882,7 @@ if (win == self->iconify) return g_quark_try_string("iconify");
if (win == self->close) return g_quark_try_string("close"); if (win == self->icon) return g_quark_try_string("icon"); if (win == self->desk) return g_quark_try_string("alldesktops"); + if (win == self->shade) return g_quark_try_string("shade"); return g_quark_try_string("none"); }
@@ -37,6 +37,8 @@ extern pixmap_mask *ob_s_max_unset_mask;
extern pixmap_mask *ob_s_iconify_mask; extern pixmap_mask *ob_s_desk_set_mask; extern pixmap_mask *ob_s_desk_unset_mask; +extern pixmap_mask *ob_s_shade_set_mask; +extern pixmap_mask *ob_s_shade_unset_mask; extern pixmap_mask *ob_s_close_mask; extern Appearance *ob_a_focused_unpressed_max;@@ -55,6 +57,12 @@ extern Appearance *ob_a_focused_pressed_set_desk;
extern Appearance *ob_a_unfocused_unpressed_desk; extern Appearance *ob_a_unfocused_pressed_desk; extern Appearance *ob_a_unfocused_pressed_set_desk; +extern Appearance *ob_a_focused_unpressed_shade; +extern Appearance *ob_a_focused_pressed_shade; +extern Appearance *ob_a_focused_pressed_set_shade; +extern Appearance *ob_a_unfocused_unpressed_shade; +extern Appearance *ob_a_unfocused_pressed_shade; +extern Appearance *ob_a_unfocused_pressed_set_shade; extern Appearance *ob_a_focused_unpressed_iconify; extern Appearance *ob_a_focused_pressed_iconify; extern Appearance *ob_a_unfocused_unpressed_iconify;@@ -77,6 +85,7 @@ Window label;
Window max; Window close; Window desk; + Window shade; Window icon; Window iconify; Window handle;@@ -101,6 +110,7 @@ int icon_x; /* x-position of the window icon button */
int label_x; /* x-position of the window title */ int iconify_x; /* x-position of the window iconify button */ int desk_x; /* x-position of the window all-desktops button */ + int shade_x; /* x-position of the window shade button */ int max_x; /* x-position of the window maximize button */ int close_x; /* x-position of the window close button */ int bwidth; /* border width */@@ -109,6 +119,7 @@
gboolean max_press; gboolean close_press; gboolean desk_press; + gboolean shade_press; gboolean iconify_press; } ObFrame;
@@ -7,6 +7,7 @@ static void obrender_max(ObFrame *self, Appearance *a);
static void obrender_icon(ObFrame *self, Appearance *a); static void obrender_iconify(ObFrame *self, Appearance *a); static void obrender_desk(ObFrame *self, Appearance *a); +static void obrender_shade(ObFrame *self, Appearance *a); static void obrender_close(ObFrame *self, Appearance *a); void obrender_frame(ObFrame *self)@@ -20,7 +21,7 @@ ob_s_cb_unfocused_color->pixel);
} if (self->frame.client->decorations & Decor_Titlebar) { - Appearance *t, *l, *m, *n, *i, *d, *c; + Appearance *t, *l, *m, *n, *i, *d, *s, *c; t = (client_focused(self->frame.client) ? self->a_focused_title : self->a_unfocused_title);@@ -51,6 +52,15 @@ (self->frame.client->desktop == DESKTOP_ALL ?
ob_a_unfocused_pressed_set_desk : (self->desk_press ? ob_a_unfocused_pressed_desk : ob_a_unfocused_unpressed_desk))); + s = (client_focused(self->frame.client) ? + (self->frame.client->shaded ? + ob_a_focused_pressed_set_shade : + (self->shade_press ? + ob_a_focused_pressed_shade : ob_a_focused_unpressed_shade)) : + (self->frame.client->shaded ? + ob_a_unfocused_pressed_set_shade : + (self->shade_press ? + ob_a_unfocused_pressed_shade :ob_a_unfocused_unpressed_shade))); c = (client_focused(self->frame.client) ? (self->close_press ? ob_a_focused_pressed_close : ob_a_focused_unpressed_close) :@@ -80,6 +90,10 @@ d->surface.data.planar.parent = t;
d->surface.data.planar.parentx = self->desk_x; d->surface.data.planar.parenty = ob_s_bevel + 1; + s->surface.data.planar.parent = t; + s->surface.data.planar.parentx = self->shade_x; + s->surface.data.planar.parenty = ob_s_bevel + 1; + c->surface.data.planar.parent = t; c->surface.data.planar.parentx = self->close_x; c->surface.data.planar.parenty = ob_s_bevel + 1;@@ -89,6 +103,7 @@ obrender_max(self, m);
obrender_icon(self, n); obrender_iconify(self, i); obrender_desk(self, d); + obrender_shade(self, s); obrender_close(self, c); }@@ -170,6 +185,14 @@ if (self->desk_x < 0) return;
RECT_SET(a->texture[0].position, 0, 0, BUTTON_SIZE,BUTTON_SIZE); paint(self->desk, a); +} + +static void obrender_shade(ObFrame *self, Appearance *a) +{ + if (self->shade_x < 0) return; + + RECT_SET(a->texture[0].position, 0, 0, BUTTON_SIZE,BUTTON_SIZE); + paint(self->shade, a); } static void obrender_close(ObFrame *self, Appearance *a)
@@ -396,6 +396,24 @@ ob_s_desk_set_mask = pixmap_mask_new(7, 7, data);
} } + if (read_mask(db, "window.button.shade.mask", + &ob_s_shade_unset_mask)) { + if (!read_mask(db, "window.button.shade.toggled.mask", + &ob_s_shade_set_mask)) { + ob_s_shade_set_mask = + pixmap_mask_copy(ob_s_shade_unset_mask); + } + } else { + { + char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 }; + ob_s_shade_unset_mask = pixmap_mask_new(7, 7, data); + } + { + char data[] = { 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x7f }; + ob_s_shade_set_mask = pixmap_mask_new(7, 7, data); + } + } + if (!read_mask(db, "window.button.close.mask", &ob_s_close_mask)) { char data[] = { 0x63, 0x77, 0x3e, 0x1c, 0x3e, 0x77, 0x63 };@@ -449,6 +467,14 @@ appearance_copy(ob_a_unfocused_pressed_max);
ob_a_focused_unpressed_desk = appearance_copy(ob_a_focused_unpressed_max); ob_a_focused_pressed_desk = appearance_copy(ob_a_focused_pressed_max); ob_a_focused_pressed_set_desk = appearance_copy(ob_a_focused_pressed_max); + ob_a_unfocused_unpressed_shade = + appearance_copy(ob_a_unfocused_unpressed_max); + ob_a_unfocused_pressed_shade = appearance_copy(ob_a_unfocused_pressed_max); + ob_a_unfocused_pressed_set_shade = + appearance_copy(ob_a_unfocused_pressed_max); + ob_a_focused_unpressed_shade = appearance_copy(ob_a_focused_unpressed_max); + ob_a_focused_pressed_shade = appearance_copy(ob_a_focused_pressed_max); + ob_a_focused_pressed_set_shade = appearance_copy(ob_a_focused_pressed_max); ob_a_unfocused_unpressed_iconify = appearance_copy(ob_a_unfocused_unpressed_max); ob_a_unfocused_pressed_iconify =@@ -496,6 +522,12 @@ ob_a_focused_pressed_set_desk->texture[0].type =
ob_a_unfocused_unpressed_desk->texture[0].type = ob_a_unfocused_pressed_desk->texture[0].type = ob_a_unfocused_pressed_set_desk->texture[0].type = + ob_a_focused_unpressed_shade->texture[0].type = + ob_a_focused_pressed_shade->texture[0].type = + ob_a_focused_pressed_set_shade->texture[0].type = + ob_a_unfocused_unpressed_shade->texture[0].type = + ob_a_unfocused_pressed_shade->texture[0].type = + ob_a_unfocused_pressed_set_shade->texture[0].type = ob_a_focused_unpressed_iconify->texture[0].type = ob_a_focused_pressed_iconify->texture[0].type = ob_a_unfocused_unpressed_iconify->texture[0].type =@@ -521,6 +553,14 @@ ob_s_desk_unset_mask;
ob_a_focused_pressed_set_desk->texture[0].data.mask.mask = ob_a_unfocused_pressed_set_desk->texture[0].data.mask.mask = ob_s_desk_set_mask; + ob_a_focused_unpressed_shade->texture[0].data.mask.mask = + ob_a_unfocused_unpressed_shade->texture[0].data.mask.mask = + ob_a_focused_pressed_shade->texture[0].data.mask.mask = + ob_a_unfocused_pressed_shade->texture[0].data.mask.mask = + ob_s_shade_unset_mask; + ob_a_focused_pressed_set_shade->texture[0].data.mask.mask = + ob_a_unfocused_pressed_set_shade->texture[0].data.mask.mask = + ob_s_shade_set_mask; ob_a_focused_unpressed_iconify->texture[0].data.mask.mask = ob_a_unfocused_unpressed_iconify->texture[0].data.mask.mask = ob_a_focused_pressed_iconify->texture[0].data.mask.mask =@@ -534,6 +574,9 @@ ob_a_focused_pressed_close->texture[0].data.mask.color =
ob_a_focused_unpressed_desk->texture[0].data.mask.color = ob_a_focused_pressed_desk->texture[0].data.mask.color = ob_a_focused_pressed_set_desk->texture[0].data.mask.color = + ob_a_focused_unpressed_shade->texture[0].data.mask.color = + ob_a_focused_pressed_shade->texture[0].data.mask.color = + ob_a_focused_pressed_set_shade->texture[0].data.mask.color = ob_a_focused_unpressed_iconify->texture[0].data.mask.color = ob_a_focused_pressed_iconify->texture[0].data.mask.color = ob_s_titlebut_focused_color;@@ -545,6 +588,9 @@ ob_a_unfocused_pressed_close->texture[0].data.mask.color =
ob_a_unfocused_unpressed_desk->texture[0].data.mask.color = ob_a_unfocused_pressed_desk->texture[0].data.mask.color = ob_a_unfocused_pressed_set_desk->texture[0].data.mask.color = + ob_a_unfocused_unpressed_shade->texture[0].data.mask.color = + ob_a_unfocused_pressed_shade->texture[0].data.mask.color = + ob_a_unfocused_pressed_set_shade->texture[0].data.mask.color = ob_a_unfocused_unpressed_iconify->texture[0].data.mask.color = ob_a_unfocused_pressed_iconify->texture[0].data.mask.color = ob_s_titlebut_unfocused_color;
@@ -747,7 +747,8 @@ void client_setup_decor_and_functions(Client *self)
{ /* start with everything (cept fullscreen) */ self->decorations = Decor_Titlebar | Decor_Handle | Decor_Border | - Decor_Icon | Decor_AllDesktops | Decor_Iconify | Decor_Maximize; + Decor_Icon | Decor_AllDesktops | Decor_Iconify | Decor_Maximize | + Decor_Shade; self->functions = Func_Resize | Func_Move | Func_Iconify | Func_Maximize | Func_Shade; if (self->delete_window) {@@ -842,6 +843,8 @@ if (self->disabled_decorations & Decor_Maximize)
self->decorations &= ~Decor_Maximize; if (self->disabled_decorations & Decor_AllDesktops) self->decorations &= ~Decor_AllDesktops; + if (self->disabled_decorations & Decor_Shade) + self->decorations &= ~Decor_Shade; if (self->disabled_decorations & Decor_Close) self->decorations &= ~Decor_Close;
@@ -100,7 +100,8 @@ Decor_Maximize = 1 << 5, /*!< Display a maximize button */
/*! Display a button to toggle the window's placement on all desktops */ Decor_AllDesktops = 1 << 6, - Decor_Close = 1 << 7 /*!< Display a close button */ + Decor_Shade = 1 << 7, /*!< Displays a shade button */ + Decor_Close = 1 << 8 /*!< Display a close button */ } Decoration;
@@ -150,6 +150,7 @@ Icon DoubleClick Left Close
Close Click Left Close Close Click Middle Kill AllDesktops Click Left ToggleOmnipresent +Shade Click Left ToggleShade Root Click Up NextDesktopWrap Root Click Down PreviousDesktopWrap