- RECT_SET(self->a_focused_label->area, 0, 0,
- self->label_width, theme_label_height);
- RECT_SET(self->a_unfocused_label->area, 0, 0,
- self->label_width, theme_label_height);
-}
-
-Context frame_context_from_string(char *name)
-{
- if (!g_ascii_strcasecmp("root", name))
- return Context_Root;
- else if (!g_ascii_strcasecmp("client", name))
- return Context_Client;
- else if (!g_ascii_strcasecmp("titlebar", name))
- return Context_Titlebar;
- else if (!g_ascii_strcasecmp("handle", name))
- return Context_Handle;
- else if (!g_ascii_strcasecmp("frame", name))
- return Context_Frame;
- else if (!g_ascii_strcasecmp("blcorner", name))
- return Context_BLCorner;
- else if (!g_ascii_strcasecmp("tlcorner", name))
- return Context_TLCorner;
- else if (!g_ascii_strcasecmp("brcorner", name))
- return Context_BRCorner;
- else if (!g_ascii_strcasecmp("trcorner", name))
- return Context_TRCorner;
- else if (!g_ascii_strcasecmp("maximize", name))
- return Context_Maximize;
- else if (!g_ascii_strcasecmp("alldesktops", name))
- return Context_AllDesktops;
- else if (!g_ascii_strcasecmp("shade", name))
- return Context_Shade;
- else if (!g_ascii_strcasecmp("iconify", name))
- return Context_Iconify;
- else if (!g_ascii_strcasecmp("icon", name))
- return Context_Icon;
- else if (!g_ascii_strcasecmp("close", name))
- return Context_Close;
- return Context_None;
-}
-
-Context frame_context(Frame *self, Window win)
-{
- if (win == ob_root) return Context_Root;
- if (self == NULL) return Context_None;
- if (win == self->client->window) return Context_Client;
-
- if (win == self->window) return Context_Frame;
- if (win == self->plate) return Context_Client;
- if (win == self->title) return Context_Titlebar;
- if (win == self->label) return Context_Titlebar;
- if (win == self->handle) return Context_Handle;
- if (win == self->lgrip) return Context_BLCorner;
- if (win == self->rgrip) return Context_BRCorner;
- if (win == self->max) return Context_Maximize;
- if (win == self->iconify)return Context_Iconify;
- if (win == self->close) return Context_Close;
- if (win == self->icon) return Context_Icon;
- if (win == self->desk) return Context_AllDesktops;
- if (win == self->shade) return Context_Shade;
-
- return Context_None;
-}
-
-void frame_client_gravity(Frame *self, int *x, int *y)
+static void layout_title(ObFrame *self)
+{
+ gchar *lc;
+ gint i;
+
+ const gint bwidth = ob_rr_theme->button_size + ob_rr_theme->paddingx + 1;
+ /* position of the left most button */
+ const gint left = ob_rr_theme->paddingx + 1;
+ /* position of the right most button */
+ const gint right = self->width;
+
+ /* turn them all off */
+ self->icon_on = self->desk_on = self->shade_on = self->iconify_on =
+ self->max_on = self->close_on = self->label_on = FALSE;
+ self->label_width = self->width - (ob_rr_theme->paddingx + 1) * 2;
+ self->leftmost = self->rightmost = OB_FRAME_CONTEXT_NONE;
+
+ /* figure out what's being show, find each element's position, and the
+ width of the label
+
+ do the ones before the label, then after the label,
+ i will be +1 the first time through when working to the left,
+ and -1 the second time through when working to the right */
+ for (i = 1; i >= -1; i-=2) {
+ gint x;
+ ObFrameContext *firstcon;
+
+ if (i > 0) {
+ x = left;
+ lc = config_title_layout;
+ firstcon = &self->leftmost;
+ } else {
+ x = right;
+ lc = config_title_layout + strlen(config_title_layout)-1;
+ firstcon = &self->rightmost;
+ }
+
+ /* stop at the end of the string (or the label, which calls break) */
+ for (; *lc != '\0' && lc >= config_title_layout; lc+=i) {
+ if (*lc == 'L') {
+ if (i > 0) {
+ self->label_on = TRUE;
+ self->label_x = x;
+ }
+ break; /* break the for loop, do other side of label */
+ } else if (*lc == 'N') {
+ if (firstcon) *firstcon = OB_FRAME_CONTEXT_ICON;
+ if ((self->icon_on = is_button_present(self, lc, i))) {
+ /* icon is bigger than buttons */
+ self->label_width -= bwidth + 2;
+ if (i > 0) self->icon_x = x;
+ x += i * (bwidth + 2);
+ if (i < 0) self->icon_x = x;
+ }
+ } else if (*lc == 'D') {
+ if (firstcon) *firstcon = OB_FRAME_CONTEXT_ALLDESKTOPS;
+ if ((self->desk_on = is_button_present(self, lc, i))) {
+ self->label_width -= bwidth;
+ if (i > 0) self->desk_x = x;
+ x += i * bwidth;
+ if (i < 0) self->desk_x = x;
+ }
+ } else if (*lc == 'S') {
+ if (firstcon) *firstcon = OB_FRAME_CONTEXT_SHADE;
+ if ((self->shade_on = is_button_present(self, lc, i))) {
+ self->label_width -= bwidth;
+ if (i > 0) self->shade_x = x;
+ x += i * bwidth;
+ if (i < 0) self->shade_x = x;
+ }
+ } else if (*lc == 'I') {
+ if (firstcon) *firstcon = OB_FRAME_CONTEXT_ICONIFY;
+ if ((self->iconify_on = is_button_present(self, lc, i))) {
+ self->label_width -= bwidth;
+ if (i > 0) self->iconify_x = x;
+ x += i * bwidth;
+ if (i < 0) self->iconify_x = x;
+ }
+ } else if (*lc == 'M') {
+ if (firstcon) *firstcon = OB_FRAME_CONTEXT_MAXIMIZE;
+ if ((self->max_on = is_button_present(self, lc, i))) {
+ self->label_width -= bwidth;
+ if (i > 0) self->max_x = x;
+ x += i * bwidth;
+ if (i < 0) self->max_x = x;
+ }
+ } else if (*lc == 'C') {
+ if (firstcon) *firstcon = OB_FRAME_CONTEXT_CLOSE;
+ if ((self->close_on = is_button_present(self, lc, i))) {
+ self->label_width -= bwidth;
+ if (i > 0) self->close_x = x;
+ x += i * bwidth;
+ if (i < 0) self->close_x = x;
+ }
+ } else
+ continue; /* don't set firstcon */
+ firstcon = NULL;
+ }
+ }
+
+ /* position and map the elements */
+ if (self->icon_on) {
+ XMapWindow(ob_display, self->icon);
+ XMoveWindow(ob_display, self->icon, self->icon_x,
+ ob_rr_theme->paddingy);
+ } else
+ XUnmapWindow(ob_display, self->icon);
+
+ if (self->desk_on) {
+ XMapWindow(ob_display, self->desk);
+ XMoveWindow(ob_display, self->desk, self->desk_x,
+ ob_rr_theme->paddingy + 1);
+ } else
+ XUnmapWindow(ob_display, self->desk);
+
+ if (self->shade_on) {
+ XMapWindow(ob_display, self->shade);
+ XMoveWindow(ob_display, self->shade, self->shade_x,
+ ob_rr_theme->paddingy + 1);
+ } else
+ XUnmapWindow(ob_display, self->shade);
+
+ if (self->iconify_on) {
+ XMapWindow(ob_display, self->iconify);
+ XMoveWindow(ob_display, self->iconify, self->iconify_x,
+ ob_rr_theme->paddingy + 1);
+ } else
+ XUnmapWindow(ob_display, self->iconify);
+
+ if (self->max_on) {
+ XMapWindow(ob_display, self->max);
+ XMoveWindow(ob_display, self->max, self->max_x,
+ ob_rr_theme->paddingy + 1);
+ } else
+ XUnmapWindow(ob_display, self->max);
+
+ if (self->close_on) {
+ XMapWindow(ob_display, self->close);
+ XMoveWindow(ob_display, self->close, self->close_x,
+ ob_rr_theme->paddingy + 1);
+ } else
+ XUnmapWindow(ob_display, self->close);
+
+ if (self->label_on) {
+ self->label_width = MAX(1, self->label_width); /* no lower than 1 */
+ XMapWindow(ob_display, self->label);
+ XMoveWindow(ob_display, self->label, self->label_x,
+ ob_rr_theme->paddingy);
+ } else
+ XUnmapWindow(ob_display, self->label);
+}
+
+ObFrameContext frame_context_from_string(const gchar *name)
+{
+ if (!g_ascii_strcasecmp("Desktop", name))
+ return OB_FRAME_CONTEXT_DESKTOP;
+ else if (!g_ascii_strcasecmp("Root", name))
+ return OB_FRAME_CONTEXT_ROOT;
+ else if (!g_ascii_strcasecmp("Client", name))
+ return OB_FRAME_CONTEXT_CLIENT;
+ else if (!g_ascii_strcasecmp("Titlebar", name))
+ return OB_FRAME_CONTEXT_TITLEBAR;
+ else if (!g_ascii_strcasecmp("Frame", name))
+ return OB_FRAME_CONTEXT_FRAME;
+ else if (!g_ascii_strcasecmp("TLCorner", name))
+ return OB_FRAME_CONTEXT_TLCORNER;
+ else if (!g_ascii_strcasecmp("TRCorner", name))
+ return OB_FRAME_CONTEXT_TRCORNER;
+ else if (!g_ascii_strcasecmp("BLCorner", name))
+ return OB_FRAME_CONTEXT_BLCORNER;
+ else if (!g_ascii_strcasecmp("BRCorner", name))
+ return OB_FRAME_CONTEXT_BRCORNER;
+ else if (!g_ascii_strcasecmp("Top", name))
+ return OB_FRAME_CONTEXT_TOP;
+ else if (!g_ascii_strcasecmp("Bottom", name))
+ return OB_FRAME_CONTEXT_BOTTOM;
+ else if (!g_ascii_strcasecmp("Left", name))
+ return OB_FRAME_CONTEXT_LEFT;
+ else if (!g_ascii_strcasecmp("Right", name))
+ return OB_FRAME_CONTEXT_RIGHT;
+ else if (!g_ascii_strcasecmp("Maximize", name))
+ return OB_FRAME_CONTEXT_MAXIMIZE;
+ else if (!g_ascii_strcasecmp("AllDesktops", name))
+ return OB_FRAME_CONTEXT_ALLDESKTOPS;
+ else if (!g_ascii_strcasecmp("Shade", name))
+ return OB_FRAME_CONTEXT_SHADE;
+ else if (!g_ascii_strcasecmp("Iconify", name))
+ return OB_FRAME_CONTEXT_ICONIFY;
+ else if (!g_ascii_strcasecmp("Icon", name))
+ return OB_FRAME_CONTEXT_ICON;
+ else if (!g_ascii_strcasecmp("Close", name))
+ return OB_FRAME_CONTEXT_CLOSE;
+ else if (!g_ascii_strcasecmp("MoveResize", name))
+ return OB_FRAME_CONTEXT_MOVE_RESIZE;
+ return OB_FRAME_CONTEXT_NONE;
+}
+
+ObFrameContext frame_context(ObClient *client, Window win, gint x, gint y)
+{
+ ObFrame *self;
+
+ if (moveresize_in_progress)
+ return OB_FRAME_CONTEXT_MOVE_RESIZE;
+
+ if (win == RootWindow(ob_display, ob_screen))
+ return OB_FRAME_CONTEXT_ROOT ;
+ if (client == NULL) return OB_FRAME_CONTEXT_NONE;
+ if (win == client->window) {
+ /* conceptually, this is the desktop, as far as users are
+ concerned */
+ if (client->type == OB_CLIENT_TYPE_DESKTOP)
+ return OB_FRAME_CONTEXT_DESKTOP;
+ return OB_FRAME_CONTEXT_CLIENT;
+ }
+
+ self = client->frame;
+
+ /* when the user clicks in the corners of the titlebar and the client
+ is fully maximized, then treat it like they clicked in the
+ button that is there */
+ if (self->max_horz && self->max_vert &&
+ (win == self->title || win == self->titletop ||
+ win == self->titleleft || win == self->titletopleft ||
+ win == self->titleright || win == self->titletopright))
+ {
+ /* get the mouse coords in reference to the whole frame */
+ gint fx = x;
+ gint fy = y;
+
+ /* these windows are down a border width from the top of the frame */
+ if (win == self->title ||
+ win == self->titleleft || win == self->titleright)
+ fy += self->bwidth;
+
+ /* title is a border width in from the edge */
+ if (win == self->title)
+ fx += self->bwidth;
+ /* titletop is a bit to the right */
+ else if (win == self->titletop)
+ fx += ob_rr_theme->grip_width + self->bwidth;
+ /* titletopright is way to the right edge */
+ else if (win == self->titletopright)
+ fx += self->area.width - (ob_rr_theme->grip_width + self->bwidth);
+ /* titleright is even more way to the right edge */
+ else if (win == self->titleright)
+ fx += self->area.width - self->bwidth;
+
+ /* figure out if we're over the area that should be considered a
+ button */
+ if (fy < self->bwidth + ob_rr_theme->paddingy + 1 +
+ ob_rr_theme->button_size)
+ {
+ if (fx < (self->bwidth + ob_rr_theme->paddingx + 1 +
+ ob_rr_theme->button_size))
+ {
+ if (self->leftmost != OB_FRAME_CONTEXT_NONE)
+ return self->leftmost;
+ }
+ else if (fx >= (self->area.width -
+ (self->bwidth + ob_rr_theme->paddingx + 1 +
+ ob_rr_theme->button_size)))
+ {
+ if (self->rightmost != OB_FRAME_CONTEXT_NONE)
+ return self->rightmost;
+ }
+ }
+
+ /* there is no resizing maximized windows so make them the titlebar
+ context */
+ return OB_FRAME_CONTEXT_TITLEBAR;
+ }
+ else if (self->max_vert &&
+ (win == self->titletop || win == self->topresize))
+ /* can't resize vertically when max vert */
+ return OB_FRAME_CONTEXT_TITLEBAR;
+ else if (self->shaded &&
+ (win == self->titletop || win == self->topresize))
+ /* can't resize vertically when shaded */
+ return OB_FRAME_CONTEXT_TITLEBAR;
+
+ if (win == self->window) return OB_FRAME_CONTEXT_FRAME;
+ if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR;
+ if (win == self->handle) return OB_FRAME_CONTEXT_BOTTOM;
+ if (win == self->handletop) return OB_FRAME_CONTEXT_BOTTOM;
+ if (win == self->handlebottom) return OB_FRAME_CONTEXT_BOTTOM;
+ if (win == self->handleleft) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->lgripleft) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->lgriptop) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->lgripbottom) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->handleright) return OB_FRAME_CONTEXT_BRCORNER;
+ if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER;
+ if (win == self->rgripright) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->rgriptop) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->rgripbottom) return OB_FRAME_CONTEXT_BLCORNER;
+ if (win == self->title) return OB_FRAME_CONTEXT_TITLEBAR;
+ if (win == self->titlebottom) return OB_FRAME_CONTEXT_TITLEBAR;
+ if (win == self->titleleft) return OB_FRAME_CONTEXT_TLCORNER;
+ if (win == self->titletopleft) return OB_FRAME_CONTEXT_TLCORNER;
+ if (win == self->titleright) return OB_FRAME_CONTEXT_TRCORNER;
+ if (win == self->titletopright) return OB_FRAME_CONTEXT_TRCORNER;
+ if (win == self->titletop) return OB_FRAME_CONTEXT_TOP;
+ if (win == self->topresize) return OB_FRAME_CONTEXT_TOP;
+ if (win == self->tltresize) return OB_FRAME_CONTEXT_TLCORNER;
+ if (win == self->tllresize) return OB_FRAME_CONTEXT_TLCORNER;
+ if (win == self->trtresize) return OB_FRAME_CONTEXT_TRCORNER;
+ if (win == self->trrresize) return OB_FRAME_CONTEXT_TRCORNER;
+ if (win == self->left) return OB_FRAME_CONTEXT_LEFT;
+ if (win == self->right) return OB_FRAME_CONTEXT_RIGHT;
+ if (win == self->innertop) return OB_FRAME_CONTEXT_TITLEBAR;
+ if (win == self->innerleft) return OB_FRAME_CONTEXT_LEFT;
+ if (win == self->innerbottom) return OB_FRAME_CONTEXT_BOTTOM;
+ if (win == self->innerright) return OB_FRAME_CONTEXT_RIGHT;
+ if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE;
+ if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY;
+ if (win == self->close) return OB_FRAME_CONTEXT_CLOSE;
+ if (win == self->icon) return OB_FRAME_CONTEXT_ICON;
+ if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS;
+ if (win == self->shade) return OB_FRAME_CONTEXT_SHADE;
+
+ return OB_FRAME_CONTEXT_NONE;
+}
+
+void frame_client_gravity(ObFrame *self, gint *x, gint *y, gint w, gint h)