lib_LTLIBRARIES = \
render/libobrender.la \
- obt/libobt.la
+ obt/libobt.la \
+ engines/libconcept.la \
+ engines/libdefault.la
+# engines/libconcept2.la \
+# engines/libminimal.la
bin_PROGRAMS = \
openbox/openbox \
render/render.c \
render/theme.h \
render/theme.c
+## frame_default ##
+engines_libdefault_la_CPPFLAGS = \
+ $(X_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(XML_CFLAGS) \
+ $(PANGO_CFLAGS) \
+ $(XFT_CFLAGS) \
+ -DG_LOG_DOMAIN=\"ObRender\" \
+ -DDEFAULT_THEME=\"$(theme)\"
+engines_libdefault_la_LDFLAGS = \
+ -version-info $(RR_CURRENT):$(RR_REVISION):$(RR_AGE)
+engines_libdefault_la_LIBADD = \
+ render/libobrender.la \
+ $(X_LIBS) \
+ $(PANGO_LIBS) \
+ $(XFT_LIBS) \
+ $(GLIB_LIBS) \
+ $(XML_LIBS)
+engines_libdefault_la_SOURCES = \
+ gettext.h \
+ render/color.h \
+ render/color.c \
+ render/font.h \
+ render/font.c \
+ render/geom.h \
+ render/gradient.h \
+ render/gradient.c \
+ render/icon.h \
+ render/image.h \
+ render/image.c \
+ render/instance.h \
+ render/instance.c \
+ render/mask.h \
+ render/mask.c \
+ render/render.h \
+ render/render.c \
+ openbox/engine_interface.h \
+ openbox/engine_interface.c \
+ engines/default/config.h \
+ engines/default/config.c \
+ engines/default/render.h \
+ engines/default/render.c \
+ engines/default/plugin.h \
+ engines/default/plugin.c
+
+## frame_minimal ##
+#engines_libminimal_la_CPPFLAGS = \
+# $(X_CFLAGS) \
+# $(GLIB_CFLAGS) \
+# $(XML_CFLAGS) \
+# $(PANGO_CFLAGS) \
+# $(XFT_CFLAGS) \
+# -DG_LOG_DOMAIN=\"ObRender\" \
+# -DDEFAULT_THEME=\"$(theme)\"
+#engines_libminimal_la_LDFLAGS = \
+# -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
+#engines_libminimal_la_LIBADD = \
+# parser/libobparser.la \
+# $(X_LIBS) \
+# $(PANGO_LIBS) \
+# $(XFT_LIBS) \
+# $(GLIB_LIBS) \
+# $(XML_LIBS)
+#engines_libminimal_la_SOURCES = \
+# gettext.h \
+# render/color.h \
+# render/color.c \
+# render/font.h \
+# render/font.c \
+# render/geom.h \
+# render/gradient.h \
+# render/gradient.c \
+# render/icon.h \
+# render/image.h \
+# render/image.c \
+# render/instance.h \
+# render/instance.c \
+# render/mask.h \
+# render/mask.c \
+# render/render.h \
+# render/render.c \
+# openbox/engine_interface.h \
+# openbox/engine_interface.c \
+# engines/minimal/frame_minimal_config.h \
+# engines/minimal/frame_minimal_config.c \
+# engines/minimal/frame_minimal_render.h \
+# engines/minimal/frame_minimal_render.c \
+# engines/minimal/frame_minimal_plugin.h \
+# engines/minimal/frame_minimal_plugin.c
+
+## frame_concept ##
+engines_libconcept_la_CPPFLAGS = \
+ $(X_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(XML_CFLAGS) \
+ $(PANGO_CFLAGS) \
+ $(XFT_CFLAGS) \
+ $(IMLIB2_CFLAGS) \
+ $(GDK_PIXBUF_CFLAGS) \
+ $(GDK_PIXBUF_XLIB_CFLAGS) \
+ -DG_LOG_DOMAIN=\"ObRender\" \
+ -DDEFAULT_THEME=\"$(theme)\"
+engines_libconcept_la_LDFLAGS = \
+ -version-info $(RR_CURRENT):$(RR_REVISION):$(RR_AGE)
+engines_libconcept_la_LIBADD = \
+ render/libobrender.la \
+ $(X_LIBS) \
+ $(PANGO_LIBS) \
+ $(XFT_LIBS) \
+ $(GLIB_LIBS) \
+ $(IMLIB2_LIBS) \
+ $(GDK_PIXBUF_LIBS) \
+ $(GDK_PIXBUF_XLIB_LIBS) \
+ $(XML_LIBS)
+engines_libconcept_la_SOURCES = \
+ gettext.h \
+ render/color.h \
+ render/color.c \
+ render/font.h \
+ render/font.c \
+ render/geom.h \
+ render/gradient.h \
+ render/gradient.c \
+ render/icon.h \
+ render/image.h \
+ render/image.c \
+ render/instance.h \
+ render/instance.c \
+ render/mask.h \
+ render/mask.c \
+ render/render.h \
+ render/render.c \
+ openbox/engine_interface.h \
+ openbox/engine_interface.c \
+ engines/concept/config.h \
+ engines/concept/config.c \
+ engines/concept/plugin.h \
+ engines/concept/plugin.c
## obt ##
openbox/focus_cycle_indicator.h \
openbox/focus_cycle_popup.c \
openbox/focus_cycle_popup.h \
- openbox/frame.c \
- openbox/frame.h \
- openbox/framerender.c \
- openbox/framerender.h \
+ openbox/engine_interface.h \
+ openbox/engine_interface.c \
openbox/geom.h \
openbox/grab.c \
openbox/grab.h \
AC_SUBST(XML_CFLAGS)
AC_SUBST(XML_LIBS)
+PKG_CHECK_MODULES(GDK_PIXBUF, [gdk-pixbuf-2.0 >= 2.6.0])
+AC_SUBST(GDK_PIXBUF_CFLAGS)
+AC_SUBST(GDK_PIXBUF_LIBS)
+
+PKG_CHECK_MODULES(GDK_PIXBUF_XLIB, [gdk-pixbuf-xlib-2.0 >= 2.6.0])
+AC_SUBST(GDK_PIXBUF_XLIB_CFLAGS)
+AC_SUBST(GDK_PIXBUF_XLIB_LIBS)
+
AC_ARG_ENABLE(startup-notification,
AC_HELP_STRING(
[--disable-startup-notification],
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_config.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include <X11/Xlib.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "render/render.h"
+#include "render/color.h"
+#include "render/font.h"
+#include "render/mask.h"
+#include "render/icon.h"
+#include "obt/parse.h"
+
+#include "config.h"
+#include "plugin.h"
+
+void load_pixmap(const gchar * theme_name, const gchar * base_name,
+ GdkPixbuf ** gp, Pixmap * p);
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value);
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value);
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans);
+static int parse_inline_number(const char *p);
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
+static void set_default_appearance(RrAppearance *a);
+
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font)
+{
+ gchar *str;
+
+ if (!read_int(db, "concept.border_width", &theme_config.border_width)) {
+ theme_config.border_width = 2;
+ }
+ if (!read_color(db, inst, "concept.focus_border_color",
+ &theme_config.focus_border_color)) {
+ theme_config.focus_border_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ if (!read_color(db, inst, "concept.focus_corner_color",
+ &theme_config.focus_corner_color)) {
+ theme_config.focus_corner_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ if (!read_color(db, inst, "concept.unfocus_border_color",
+ &theme_config.unfocus_border_color)) {
+ theme_config.focus_border_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ if (!read_color(db, inst, "concept.unfocus_corner_color",
+ &theme_config.unfocus_corner_color)) {
+ theme_config.focus_corner_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ theme_config.inst = inst;
+ theme_config.name = g_strdup(name ? name : DEFAULT_THEME);
+
+ gdk_pixbuf_xlib_init(plugin.ob_display, plugin.ob_screen);
+
+ load_pixmap(name, "focus-top.png", &theme_config.focus_top,
+ &theme_config.px_focus_top);
+ load_pixmap(name, "focus-left.png", &theme_config.focus_left,
+ &theme_config.px_focus_left);
+ load_pixmap(name, "focus-right.png", &theme_config.focus_right,
+ &theme_config.px_focus_right);
+ load_pixmap(name, "focus-bottom.png", &theme_config.focus_bottom,
+ &theme_config.px_focus_bottom);
+
+ load_pixmap(name, "unfocus-top.png", &theme_config.unfocus_top,
+ &theme_config.px_unfocus_top);
+ load_pixmap(name, "unfocus-left.png", &theme_config.unfocus_left,
+ &theme_config.px_unfocus_left);
+ load_pixmap(name, "unfocus-right.png", &theme_config.unfocus_right,
+ &theme_config.px_unfocus_right);
+ load_pixmap(name, "unfocus-bottom.png", &theme_config.unfocus_bottom,
+ &theme_config.px_unfocus_bottom);
+
+ load_pixmap(name, "focus-topleft.png", &theme_config.focus_topleft,
+ &theme_config.px_focus_topleft);
+ load_pixmap(name, "focus-bottomleft.png", &theme_config.focus_bottomleft,
+ &theme_config.px_focus_bottomleft);
+ load_pixmap(name, "focus-topright.png", &theme_config.focus_topright,
+ &theme_config.px_focus_topright);
+ load_pixmap(name, "focus-bottomright.png", &theme_config.focus_bottomright,
+ &theme_config.px_focus_bottomright);
+
+ load_pixmap(name, "unfocus-topleft.png", &theme_config.unfocus_topleft,
+ &theme_config.px_unfocus_topleft);
+ load_pixmap(name, "unfocus-bottomleft.png",
+ &theme_config.unfocus_bottomleft,
+ &theme_config.px_unfocus_bottomleft);
+ load_pixmap(name, "unfocus-topright.png", &theme_config.unfocus_topright,
+ &theme_config.px_unfocus_topright);
+ load_pixmap(name, "unfocus-bottomright.png",
+ &theme_config.unfocus_bottomright,
+ &theme_config.px_unfocus_bottomright);
+
+ return 1;
+}
+
+void load_pixmap(const gchar * theme_name, const gchar * base_name,
+ GdkPixbuf ** gp, Pixmap * p)
+{
+ gchar * s = g_build_filename(g_get_home_dir(), ".themes", theme_name,
+ "openbox-3", base_name, NULL);
+ ob_debug("Load file %s.\n", s);
+ *gp = gdk_pixbuf_new_from_file(s, NULL);
+ //GdkPixbuff * mask = NULL;
+ gdk_pixbuf_xlib_render_pixmap_and_mask(*gp, p, NULL, 128);
+ g_free(s);
+}
+
+static gchar *create_class_name(const gchar *rname)
+{
+ gchar *rclass = g_strdup(rname);
+ gchar *p = rclass;
+
+ while (TRUE) {
+ *p = toupper(*p);
+ p = strchr(p+1, '.');
+ if (p == NULL)
+ break;
+ ++p;
+ if (*p == '\0')
+ break;
+ }
+ return rclass;
+}
+
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype, *end;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = (gint)strtol(retvalue.addr, &end, 10);
+ if (end != retvalue.addr)
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = retvalue.addr;
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ RrColor *c = RrColorParse(inst, retvalue.addr);
+ if (c != NULL) {
+ *value = c;
+ ret = TRUE;
+ }
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value)
+{
+ gboolean ret = FALSE;
+ gchar *s;
+ gint hx, hy; /* ignored */
+ guint w, h;
+ guchar *b;
+
+ s = g_build_filename(path, maskname, NULL);
+ if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
+ ret = TRUE;
+ *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
+ XFree(b);
+ }
+ g_free(s);
+
+ return ret;
+}
+
+static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
+ RrReliefType *relief, RrBevelType *bevel, gboolean *interlaced,
+ gboolean *border, gboolean allow_trans)
+{
+ gchar *t;
+
+ /* convert to all lowercase */
+ for (t = tex; *t != '\0'; ++t)
+ *t = g_ascii_tolower(*t);
+
+ if (allow_trans && strstr(tex, "parentrelative") != NULL) {
+ *grad = RR_SURFACE_PARENTREL;
+ }
+ else {
+ if (strstr(tex, "gradient") != NULL) {
+ if (strstr(tex, "crossdiagonal") != NULL)
+ *grad = RR_SURFACE_CROSS_DIAGONAL;
+ else if (strstr(tex, "pyramid") != NULL)
+ *grad = RR_SURFACE_PYRAMID;
+ else if (strstr(tex, "mirrorhorizontal") != NULL)
+ *grad = RR_SURFACE_MIRROR_HORIZONTAL;
+ else if (strstr(tex, "horizontal") != NULL)
+ *grad = RR_SURFACE_HORIZONTAL;
+ else if (strstr(tex, "splitvertical") != NULL)
+ *grad = RR_SURFACE_SPLIT_VERTICAL;
+ else if (strstr(tex, "vertical") != NULL)
+ *grad = RR_SURFACE_VERTICAL;
+ else
+ *grad = RR_SURFACE_DIAGONAL;
+ }
+ else {
+ *grad = RR_SURFACE_SOLID;
+ }
+ }
+
+ if (strstr(tex, "sunken") != NULL)
+ *relief = RR_RELIEF_SUNKEN;
+ else if (strstr(tex, "flat") != NULL)
+ *relief = RR_RELIEF_FLAT;
+ else if (strstr(tex, "raised") != NULL)
+ *relief = RR_RELIEF_RAISED;
+ else
+ *relief = (*grad == RR_SURFACE_PARENTREL) ? RR_RELIEF_FLAT
+ : RR_RELIEF_RAISED;
+
+ *border = FALSE;
+ if (*relief == RR_RELIEF_FLAT) {
+ if (strstr(tex, "border") != NULL)
+ *border = TRUE;
+ }
+ else {
+ if (strstr(tex, "bevel2") != NULL)
+ *bevel = RR_BEVEL_2;
+ else
+ *bevel = RR_BEVEL_1;
+ }
+
+ if (strstr(tex, "interlaced") != NULL)
+ *interlaced = TRUE;
+ else
+ *interlaced = FALSE;
+}
+
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
+ gchar *csplitname, *ctosplitname;
+ gchar *rettype;
+ XrmValue retvalue;
+ gint i;
+
+ cname = g_strconcat(rname, ".color", NULL);
+ ctoname = g_strconcat(rname, ".colorTo", NULL);
+ bcname = g_strconcat(rname, ".border.color", NULL);
+ icname = g_strconcat(rname, ".interlace.color", NULL);
+ hname = g_strconcat(rname, ".highlight", NULL);
+ sname = g_strconcat(rname, ".shadow", NULL);
+ csplitname = g_strconcat(rname, ".color.splitTo", NULL);
+ ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ parse_appearance(retvalue.addr, &value->surface.grad,
+ &value->surface.relief, &value->surface.bevel,
+ &value->surface.interlaced, &value->surface.border, allow_trans);
+ if (!read_color(db, inst, cname, &value->surface.primary))
+ value->surface.primary = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, ctoname, &value->surface.secondary))
+ value->surface.secondary = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.border)
+ if (!read_color(db, inst, bcname, &value->surface.border_color))
+ value->surface.border_color = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.interlaced)
+ if (!read_color(db, inst, icname, &value->surface.interlace_color))
+ value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
+ if (read_int(db, hname, &i) && i >= 0)
+ value->surface.bevel_light_adjust = i;
+ if (read_int(db, sname, &i) && i >= 0 && i <= 256)
+ value->surface.bevel_dark_adjust = i;
+
+ if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
+ gint r, g, b;
+
+ if (!read_color(db, inst, csplitname, &value->surface.split_primary)) {
+ r = value->surface.primary->r;
+ r += r >> 2;
+ g = value->surface.primary->g;
+ g += g >> 2;
+ b = value->surface.primary->b;
+ b += b >> 2;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_primary = RrColorNew(inst, r, g, b);
+ }
+
+ if (!read_color(db, inst, ctosplitname,
+ &value->surface.split_secondary)) {
+ r = value->surface.secondary->r;
+ r += r >> 4;
+ g = value->surface.secondary->g;
+ g += g >> 4;
+ b = value->surface.secondary->b;
+ b += b >> 4;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_secondary = RrColorNew(inst, r, g, b);
+ }
+ }
+
+ ret = TRUE;
+ }
+
+ g_free(ctosplitname);
+ g_free(csplitname);
+ g_free(sname);
+ g_free(hname);
+ g_free(icname);
+ g_free(bcname);
+ g_free(ctoname);
+ g_free(cname);
+ g_free(rclass);
+ return ret;
+}
+
+static int parse_inline_number(const char *p)
+{
+ int neg = 1;
+ int res = 0;
+ if (*p == '-') {
+ neg = -1;
+ ++p;
+ }
+ for (; isdigit(*p); ++p)
+ res = res * 10 + *p - '0';
+ res *= neg;
+ return res;
+}
+
+static void set_default_appearance(RrAppearance *a)
+{
+ a->surface.grad = RR_SURFACE_SOLID;
+ a->surface.relief = RR_RELIEF_FLAT;
+ a->surface.bevel = RR_BEVEL_1;
+ a->surface.interlaced = FALSE;
+ a->surface.border = FALSE;
+ a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
+ a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
+}
+
+/* Reads the output from gimp's C-Source file format into valid RGBA data for
+ an RrTextureRGBA. */
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
+{
+ RrPixel32 *im, *p;
+ gint i;
+
+ p = im = g_memdup(data, width * height * sizeof(RrPixel32));
+
+ for (i = 0; i < width * height; ++i) {
+ guchar a = ((*p >> 24) & 0xff);
+ guchar b = ((*p >> 16) & 0xff);
+ guchar g = ((*p >> 8) & 0xff);
+ guchar r = ((*p >> 0) & 0xff);
+
+ *p = ((r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + (b
+ << RrDefaultBlueOffset) + (a << RrDefaultAlphaOffset));
+ p++;
+ }
+
+ return im;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_config.h for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_CONCEPT_CONFIG_H_
+#define FRAME_CONCEPT_CONFIG_H_
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <X11/Xresource.h>
+#include "render/render.h"
+
+G_BEGIN_DECLS
+
+struct _ObFrameThemeConfig
+{
+ const RrInstance *inst;
+
+ gint border_width;
+ RrColor * focus_border_color;
+ RrColor * focus_corner_color;
+ RrColor * unfocus_border_color;
+ RrColor * unfocus_corner_color;
+
+ GdkPixbuf * focus_top;
+ GdkPixbuf * focus_left;
+ GdkPixbuf * focus_right;
+ GdkPixbuf * focus_bottom;
+
+ GdkPixbuf * focus_topleft;
+ GdkPixbuf * focus_bottomleft;
+ GdkPixbuf * focus_topright;
+ GdkPixbuf * focus_bottomright;
+
+ GdkPixbuf * unfocus_top;
+ GdkPixbuf * unfocus_left;
+ GdkPixbuf * unfocus_right;
+ GdkPixbuf * unfocus_bottom;
+
+ GdkPixbuf * unfocus_topleft;
+ GdkPixbuf * unfocus_bottomleft;
+ GdkPixbuf * unfocus_topright;
+ GdkPixbuf * unfocus_bottomright;
+
+ Pixmap px_focus_top;
+ Pixmap px_focus_left;
+ Pixmap px_focus_right;
+ Pixmap px_focus_bottom;
+
+ Pixmap px_focus_topleft;
+ Pixmap px_focus_bottomleft;
+ Pixmap px_focus_topright;
+ Pixmap px_focus_bottomright;
+
+ Pixmap px_unfocus_top;
+ Pixmap px_unfocus_left;
+ Pixmap px_unfocus_right;
+ Pixmap px_unfocus_bottom;
+
+ Pixmap px_unfocus_topleft;
+ Pixmap px_unfocus_bottomleft;
+ Pixmap px_unfocus_topright;
+ Pixmap px_unfocus_bottomright;
+
+ gchar *name;
+};
+
+typedef struct _ObFrameThemeConfig ObFrameThemeConfig;
+
+/*! The font values are all optional. If a NULL is used for any of them, then
+ the default font will be used. */
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font);
+
+G_END_DECLS
+
+#endif /*FRAME_CONCEPT_CONFIG_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_plugin.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "openbox/client.h"
+#include "openbox/openbox.h"
+#include "openbox/prop.h"
+#include "openbox/grab.h"
+#include "openbox/config.h"
+#include "obt/mainloop.h"
+#include "openbox/focus_cycle.h"
+#include "openbox/focus_cycle_indicator.h"
+#include "openbox/moveresize.h"
+#include "openbox/screen.h"
+#include "render/theme.h"
+
+#include "plugin.h"
+
+typedef enum
+{
+ OB_FLAG_MAX = 1 << 0,
+ OB_FLAG_CLOSE = 1 << 1,
+ OB_FLAG_DESK = 1 << 2,
+ OB_FLAG_SHADE = 1 << 3,
+ OB_FLAG_ICONIFY = 1 << 4
+} ObFrameFlags;
+
+#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
+ ButtonPressMask | ButtonReleaseMask | \
+ SubstructureRedirectMask | FocusChangeMask)
+#define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
+ ButtonMotionMask | PointerMotionMask | \
+ EnterWindowMask | LeaveWindowMask)
+
+#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
+#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
+
+#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b)
+
+static gulong frame_animate_iconify_time_left(gpointer _self,
+ const GTimeVal *now);
+
+Window createWindow(Window parent, Visual *visual, gulong mask,
+ XSetWindowAttributes *attrib)
+{
+ return XCreateWindow(plugin.ob_display, parent, 0, 0, 1, 1, 0, (visual ? 32
+ : RrDepth(plugin.ob_rr_inst)), InputOutput, (visual ? visual
+ : RrVisual(plugin.ob_rr_inst)), mask, attrib);
+
+}
+
+Visual *check_32bit_client(ObClient *c)
+{
+ XWindowAttributes wattrib;
+ Status ret;
+
+ /* we're already running at 32 bit depth, yay. we don't need to use their
+ visual */
+ if (RrDepth(plugin.ob_rr_inst) == 32)
+ return NULL;
+
+ ret = XGetWindowAttributes(plugin.ob_display, c->window, &wattrib);
+ g_assert(ret != BadDrawable);
+ g_assert(ret != BadWindow);
+
+ if (wattrib.depth == 32)
+ return wattrib.visual;
+ return NULL;
+}
+
+/* Not used */
+gint init(Display * display, gint screen)
+{
+ plugin.ob_display = display;
+ plugin.ob_screen = screen;
+}
+
+/* Create a frame */
+gpointer frame_new(struct _ObClient * client)
+{
+ XSetWindowAttributes attrib;
+ gulong mask;
+ ObConceptFrame *self;
+ Visual *visual;
+
+ self = g_new0(ObConceptFrame, 1);
+ self->client = client;
+
+ visual = check_32bit_client(client);
+
+ /* create the non-visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ /* create a colormap with the visual */
+ OBCONCEPTFRAME(self)->colormap = attrib.colormap = XCreateColormap(
+ plugin.ob_display, RootWindow(plugin.ob_display,
+ plugin.ob_screen), visual, AllocNone);
+ attrib.background_pixel = BlackPixel(plugin.ob_display,
+ plugin.ob_screen);
+ attrib.border_pixel = BlackPixel(plugin.ob_display, plugin.ob_screen);
+ }
+ self->window = createWindow(
+ RootWindow(plugin.ob_display, plugin.ob_screen), visual, mask,
+ &attrib);
+
+ /* create the visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ attrib.colormap = RrColormap(plugin.ob_rr_inst);
+ }
+
+ self->background = createWindow(self->window, NULL, mask, &attrib);
+
+ mask |= CWEventMask;
+ attrib.event_mask = ELEMENT_EVENTMASK;
+
+ self->title = createWindow(self->window, NULL, mask, &attrib);
+
+ self->top = createWindow(self->window, NULL, mask, &attrib);
+ self->bottom = createWindow(self->window, NULL, mask, &attrib);
+ self->left = createWindow(self->window, NULL, mask, &attrib);
+ self->right = createWindow(self->window, NULL, mask, &attrib);
+
+ self->top_left = createWindow(self->window, NULL, mask, &attrib);
+ self->top_right = createWindow(self->window, NULL, mask, &attrib);
+ self->bottom_left = createWindow(self->window, NULL, mask, &attrib);
+ self->bottom_right = createWindow(self->window, NULL, mask, &attrib);
+
+ XMapWindow(plugin.ob_display, self->background);
+
+ self->focused = FALSE;
+
+ self->hover_flag = OB_BUTTON_NONE;
+ self->press_flag = OB_BUTTON_NONE;
+
+ set_theme_statics(self);
+
+ return self;
+}
+
+void set_theme_statics(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* do this before changing the frame's status like max_horz max_vert */
+
+ XResizeWindow(plugin.ob_display, self->top_left, 5, 5);
+ XResizeWindow(plugin.ob_display, self->top_right, 5, 5);
+ XResizeWindow(plugin.ob_display, self->bottom_left, 5, 5);
+ XResizeWindow(plugin.ob_display, self->bottom_right, 5, 5);
+}
+
+void free_theme_statics(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+}
+
+void frame_free(gpointer self)
+{
+ free_theme_statics(OBCONCEPTFRAME(self));
+ XDestroyWindow(plugin.ob_display, OBCONCEPTFRAME(self)->window);
+ if (OBCONCEPTFRAME(self)->colormap)
+ XFreeColormap(plugin.ob_display, OBCONCEPTFRAME(self)->colormap);
+ g_free(self);
+}
+
+void frame_show(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ if (!self->visible) {
+ self->visible = TRUE;
+ frame_update_skin(self);
+ /* Grab the server to make sure that the frame window is mapped before
+ the client gets its MapNotify, i.e. to make sure the client is
+ _visible_ when it gets MapNotify. */
+ grab_server(TRUE);
+ XMapWindow(plugin.ob_display, self->client->window);
+ XMapWindow(plugin.ob_display, self->window);
+ grab_server(FALSE);
+ }
+}
+
+gint frame_hide(gpointer self)
+{
+ if (OBCONCEPTFRAME(self)->visible) {
+ OBCONCEPTFRAME(self)->visible = FALSE;
+ if (!frame_iconify_animating(self))
+ XUnmapWindow(plugin.ob_display, OBCONCEPTFRAME(self)->window);
+ /* we unmap the client itself so that we can get MapRequest
+ events, and because the ICCCM tells us to! */
+ XUnmapWindow(plugin.ob_display, OBCONCEPTFRAME(self)->client->window);
+ /* We ignore 1 unmap */
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void frame_adjust_theme(gpointer self)
+{
+ free_theme_statics(self);
+ set_theme_statics(self);
+}
+
+void frame_adjust_shape(gpointer _self)
+{
+#ifdef SHAPE
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ gint num;
+ XRectangle xrect[2];
+
+ if (!self->client->shaped)
+ {
+ /* clear the shape on the frame window */
+ XShapeCombineMask(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ None, ShapeSet);
+ }
+ else
+ {
+ /* make the frame's shape match the clients */
+ XShapeCombineShape(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ self->client->window,
+ ShapeBounding, ShapeSet);
+
+ num = 0;
+ if (self->decorations)
+ {
+ xrect[0].x = 0;
+ xrect[0].y = 0;
+ xrect[0].width = self->window_area.width;
+ xrect[0].height = self->size.top;
+ ++num;
+ }
+
+ XShapeCombineRectangles(plugin.ob_display, self->window,
+ ShapeBounding, 0, 0, xrect, num,
+ ShapeUnion, Unsorted);
+ }
+#endif
+}
+
+void frame_grab(gpointer _self, GHashTable * map)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* DO NOT map the client window here. we used to do that, but it is bogus.
+ we need to set up the client's dimensions and everything before we
+ send a mapnotify or we create race conditions.
+ */
+
+ /* reparent the client to the frame */
+ XReparentWindow(plugin.ob_display, self->client->window, self->window, 0, 0);
+
+ /*
+ When reparenting the client window, it is usually not mapped yet, since
+ this occurs from a MapRequest. However, in the case where Openbox is
+ starting up, the window is already mapped, so we'll see an unmap event
+ for it.
+ */
+ if (ob_state() == OB_STATE_STARTING)
+ ++self->client->ignore_unmaps;
+
+ /* select the event mask on the client's parent (to receive config/map
+ req's) the ButtonPress is to catch clicks on the client border */
+ XSelectInput(plugin.ob_display, self->window, FRAME_EVENTMASK);
+
+ /* set all the windows for the frame in the window_map */
+ g_hash_table_insert(map, &self->window, self->client);
+
+ g_hash_table_insert(map, &self->title, self->client);
+
+ g_hash_table_insert(map, &self->left, self->client);
+ g_hash_table_insert(map, &self->right, self->client);
+ g_hash_table_insert(map, &self->top, self->client);
+ g_hash_table_insert(map, &self->bottom, self->client);
+
+ g_hash_table_insert(map, &self->top_left, self->client);
+ g_hash_table_insert(map, &self->top_right, self->client);
+ g_hash_table_insert(map, &self->bottom_left, self->client);
+ g_hash_table_insert(map, &self->bottom_right, self->client);
+
+}
+
+void frame_ungrab(gpointer _self, GHashTable * map)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ XEvent ev;
+ gboolean reparent = TRUE;
+
+ /* if there was any animation going on, kill it */
+ obt_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+
+ /* check if the app has already reparented its window away */
+ while (XCheckTypedWindowEvent(plugin.ob_display, self->client->window,
+ ReparentNotify, &ev)) {
+ /* This check makes sure we don't catch our own reparent action to
+ our frame window. This doesn't count as the app reparenting itself
+ away of course.
+
+ Reparent events that are generated by us are just discarded here.
+ They are of no consequence to us anyhow.
+ */
+ if (ev.xreparent.parent != self->window) {
+ reparent = FALSE;
+ XPutBackEvent(plugin.ob_display, &ev);
+ break;
+ }
+ }
+
+ if (reparent) {
+ /* according to the ICCCM - if the client doesn't reparent itself,
+ then we will reparent the window to root for them */
+ XReparentWindow(plugin.ob_display, self->client->window, RootWindow(
+ plugin.ob_display, plugin.ob_screen), self->client->area.x,
+ self->client->area.y);
+ }
+
+ /* remove all the windows for the frame from the window_map */
+ g_hash_table_remove(map, &self->window);
+
+ g_hash_table_remove(map, &self->title);
+
+ g_hash_table_remove(map, &self->left);
+ g_hash_table_remove(map, &self->right);
+ g_hash_table_remove(map, &self->top);
+ g_hash_table_remove(map, &self->bottom);
+
+ g_hash_table_remove(map, &self->top_left);
+ g_hash_table_remove(map, &self->top_right);
+ g_hash_table_remove(map, &self->bottom_left);
+ g_hash_table_remove(map, &self->bottom_right);
+
+ obt_main_loop_timeout_remove_data(plugin.ob_main_loop, flash_timeout, self,
+ TRUE);
+}
+
+ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
+{
+ /* Here because client can be NULL */
+ ObConceptFrame *self = OBCONCEPTFRAME(_self);
+
+ if (self->shaded)
+ return OB_FRAME_CONTEXT_TITLEBAR;
+ if (win == self->title)
+ return OB_FRAME_CONTEXT_TITLEBAR;
+
+ if (win == self->window)
+ return OB_FRAME_CONTEXT_FRAME;
+
+ if (win == self->bottom)
+ return OB_FRAME_CONTEXT_BOTTOM;
+
+ if (win == self->bottom_left)
+ return OB_FRAME_CONTEXT_BLCORNER;
+
+ if (win == self->bottom_right)
+ return OB_FRAME_CONTEXT_BRCORNER;
+
+ if (win == self->top)
+ return OB_FRAME_CONTEXT_TOP;
+
+ if (win == self->top_left)
+ return OB_FRAME_CONTEXT_TLCORNER;
+
+ if (win == self->top_right)
+ return OB_FRAME_CONTEXT_TRCORNER;
+
+ if (win == self->left)
+ return OB_FRAME_CONTEXT_LEFT;
+ if (win == self->right)
+ return OB_FRAME_CONTEXT_RIGHT;
+
+ return OB_FRAME_CONTEXT_NONE;
+}
+
+void frame_set_is_visible(gpointer self, gboolean b)
+{
+ OBCONCEPTFRAME(self)->visible = b;
+ if (b) {
+ OBCONCEPTFRAME(self)->frame_stase_flags |= OB_FRAME_STASE_IS_VISIBLE;
+ }
+ else {
+ OBCONCEPTFRAME(self)->frame_stase_flags &= ~OB_FRAME_STASE_IS_VISIBLE;
+ }
+}
+
+void frame_set_is_focus(gpointer self, gboolean b)
+{
+ OBCONCEPTFRAME(self)->focused = b;
+ if (b) {
+ OBCONCEPTFRAME(self)->frame_stase_flags |= OB_FRAME_STASE_IS_FOCUS;
+ }
+ else {
+ OBCONCEPTFRAME(self)->frame_stase_flags &= ~OB_FRAME_STASE_IS_FOCUS;
+ }
+}
+
+void frame_set_is_max_vert(gpointer self, gboolean b)
+{
+ OBCONCEPTFRAME(self)->max_vert = b;
+ if (b) {
+ OBCONCEPTFRAME(self)->frame_stase_flags |= OB_FRAME_STASE_IS_MAX_VERT;
+ }
+ else {
+ OBCONCEPTFRAME(self)->frame_stase_flags &= ~OB_FRAME_STASE_IS_MAX_VERT;
+ }
+}
+
+void frame_set_is_max_horz(gpointer self, gboolean b)
+{
+ OBCONCEPTFRAME(self)->max_horz = b;
+ if (b) {
+ OBCONCEPTFRAME(self)->frame_stase_flags |= OB_FRAME_STASE_IS_MAX_HORZ;
+ }
+ else {
+ OBCONCEPTFRAME(self)->frame_stase_flags &= ~OB_FRAME_STASE_IS_MAX_HORZ;
+ }
+}
+
+void frame_set_is_shaded(gpointer self, gboolean b)
+{
+ OBCONCEPTFRAME(self)->shaded = b;
+ if (b) {
+ OBCONCEPTFRAME(self)->frame_stase_flags |= OB_FRAME_STASE_IS_SHADED;
+ }
+ else {
+ OBCONCEPTFRAME(self)->frame_stase_flags &= ~OB_FRAME_STASE_IS_SHADED;
+ }
+}
+
+void frame_unfocus(gpointer self)
+{
+ OBCONCEPTFRAME(self)->focused = FALSE;
+}
+
+void frame_flash_start(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->flash_on = self->focused;
+
+ if (!self->flashing)
+ obt_main_loop_timeout_add(plugin.ob_main_loop, G_USEC_PER_SEC * 0.6,
+ flash_timeout, self, g_direct_equal, flash_done);
+ g_get_current_time(&self->flash_end);
+ g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
+
+ self->flashing = TRUE;
+}
+
+void frame_flash_stop(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->flashing = FALSE;
+}
+
+void frame_begin_iconify_animation(gpointer _self, gboolean iconifying)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ gulong time;
+ gboolean new_anim = FALSE;
+ gboolean set_end = TRUE;
+ GTimeVal now;
+
+ /* if there is no titlebar, just don't animate for now
+ XXX it would be nice tho.. */
+ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ return;
+
+ /* get the current time */
+ g_get_current_time(&now);
+
+ /* get how long until the end */
+ time = FRAME_ANIMATE_ICONIFY_TIME;
+ if (self->iconify_animation_going) {
+ if (!!iconifying != (self->iconify_animation_going > 0)) {
+ /* animation was already going on in the opposite direction */
+ time = time - frame_animate_iconify_time_left(self, &now);
+ }
+ else
+ /* animation was already going in the same direction */
+ set_end = FALSE;
+ }
+ else
+ new_anim = TRUE;
+ self->iconify_animation_going = iconifying ? 1 : -1;
+
+ /* set the ending time */
+ if (set_end) {
+ self->iconify_animation_end.tv_sec = now.tv_sec;
+ self->iconify_animation_end.tv_usec = now.tv_usec;
+ g_time_val_add(&self->iconify_animation_end, time);
+ }
+
+ if (new_anim) {
+ obt_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+ obt_main_loop_timeout_add(plugin.ob_main_loop,
+ FRAME_ANIMATE_ICONIFY_STEP_TIME, frame_animate_iconify, self,
+ g_direct_equal, NULL);
+
+ /* do the first step */
+ frame_animate_iconify(self);
+
+ /* show it during the animation even if it is not "visible" */
+ if (!self->visible)
+ XMapWindow(plugin.ob_display, self->window);
+ }
+}
+
+void frame_end_iconify_animation(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* see if there is an animation going */
+ if (self->iconify_animation_going == 0)
+ return;
+
+ if (!self->visible)
+ XUnmapWindow(plugin.ob_display, self->window);
+ else {
+ /* Send a ConfigureNotify when the animation is done, this fixes
+ KDE's pager showing the window in the wrong place. since the
+ window is mapped at a different location and is then moved, we
+ need to send the synthetic configurenotify, since apps may have
+ read the position when the client mapped, apparently. */
+ client_reconfigure(self->client, TRUE);
+ }
+
+ /* we're not animating any more ! */
+ self->iconify_animation_going = 0;
+
+ XMoveResizeWindow(plugin.ob_display, self->window, self->window_area.x,
+ self->window_area.y, self->window_area.width,
+ self->window_area.height);
+ /* we delay re-rendering until after we're done animating */
+ frame_update_skin(self);
+ XFlush(plugin.ob_display);
+}
+
+gboolean frame_iconify_animating(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ return self->iconify_animation_going != 0;
+}
+
+void frame_set_decorations(gpointer self, ObFrameDecorations d)
+{
+ OBCONCEPTFRAME(self)->decorations = d;
+}
+
+Rect frame_get_window_area(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->window_area;
+}
+void frame_set_client_area(gpointer self, Rect r)
+{
+ OBCONCEPTFRAME(self)->client_area = r;
+}
+
+void frame_update_layout(gpointer _self, gboolean is_resize, gboolean is_fake)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+
+ /* do this before changing the frame's status like max_horz max_vert */
+ frame_adjust_cursors(self);
+
+ if (self->decorations && !self->shaded) {
+ self->cbwidth_l = 5;
+ self->cbwidth_r = 5;
+ self->cbwidth_t = 5;
+ self->cbwidth_b = 5;
+
+ self->title_width = 20;
+
+ STRUT_SET(self->size, self->cbwidth_l, self->cbwidth_t, self->cbwidth_r
+ + self->title_width, self->cbwidth_b);
+
+ RECT_SET_SIZE(self->window_area, self->client_area.width
+ + self->size.left + self->size.right, self->client_area.height
+ + self->size.top + self->size.bottom);
+
+ if (!is_fake) {
+
+ XMoveResizeWindow(plugin.ob_display, self->top, 5, 0,
+ self->window_area.width - 10, theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->top);
+
+ XMoveResizeWindow(plugin.ob_display, self->bottom, 5,
+ self->window_area.height - theme_config.border_width,
+ self->window_area.width - 10, theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->bottom);
+
+ XMoveResizeWindow(plugin.ob_display, self->left, 0,
+ theme_config.border_width, theme_config.border_width,
+ self->window_area.height - 2*theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->left);
+
+ XMoveResizeWindow(plugin.ob_display, self->right,
+ self->window_area.width - theme_config.border_width,
+ theme_config.border_width, theme_config.border_width,
+ self->window_area.height - 2 *theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->right);
+
+ XMoveWindow(plugin.ob_display, self->top_left, 0, 0);
+ XMapWindow(plugin.ob_display, self->top_left);
+ XMoveWindow(plugin.ob_display, self->top_right,
+ self->window_area.width - 5, 0);
+ XMapWindow(plugin.ob_display, self->top_right);
+ XMoveWindow(plugin.ob_display, self->bottom_left, 0,
+ self->window_area.height - theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->bottom_left);
+ XMoveWindow(plugin.ob_display, self->bottom_right,
+ self->window_area.width - 5, self->window_area.height
+ - theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->bottom_right);
+
+ XMoveResizeWindow(plugin.ob_display, self->title,
+ self->window_area.width - theme_config.border_width
+ - self->title_width, theme_config.border_width,
+ self->title_width, self->window_area.height - 2
+ *theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->title);
+
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->window_area.x = self->client_area.x;
+ self->window_area.y = self->client_area.y;
+ frame_client_gravity(self->client, &self->window_area.x,
+ &self->window_area.y);
+
+ XMoveResizeWindow(plugin.ob_display, self->background,
+ theme_config.border_width, theme_config.border_width,
+ self->window_area.width - 2 * theme_config.border_width
+ - self->title_width, self->window_area.height - 2
+ * theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->background);
+
+ if (!is_resize) {
+ XMoveResizeWindow(plugin.ob_display, self->client->window,
+ self->size.left, self->size.top,
+ self->window_area.width - self->size.left
+ - self->size.right, self->window_area.height
+ - self->size.top - self->size.bottom);
+ }
+ XMoveResizeWindow(plugin.ob_display, self->window,
+ self->window_area.x, self->window_area.y,
+ self->window_area.width, self->window_area.height);
+
+ }
+ }
+ else if (self->shaded) {
+ self->cbwidth_l = 0;
+ self->cbwidth_r = 0;
+ self->cbwidth_b = 0;
+ self->cbwidth_t = 0;
+
+ self->title_width = 20;
+
+ STRUT_SET(self->size, self->cbwidth_l, self->cbwidth_t, self->cbwidth_r
+ + self->title_width, self->cbwidth_b);
+
+ RECT_SET_SIZE(self->window_area, 30, 30);
+
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ frame_client_gravity(self->client, &self->window_area.x,
+ &self->window_area.y);
+
+ if (!is_fake) {
+ XUnmapWindow(plugin.ob_display, self->top);
+ XUnmapWindow(plugin.ob_display, self->bottom);
+ XUnmapWindow(plugin.ob_display, self->left);
+ XUnmapWindow(plugin.ob_display, self->right);
+ XUnmapWindow(plugin.ob_display, self->top_left);
+ XUnmapWindow(plugin.ob_display, self->top_right);
+ XUnmapWindow(plugin.ob_display, self->bottom_left);
+ XUnmapWindow(plugin.ob_display, self->bottom_right);
+
+ XUnmapWindow(plugin.ob_display, self->title);
+
+ XMoveResizeWindow(plugin.ob_display, self->background, 0, 0, 30, 30);
+ XMapWindow(plugin.ob_display, self->background);
+
+ XMoveWindow(plugin.ob_display, self->window, 35, 35);
+ XResizeWindow(plugin.ob_display, self->window, 30, 30);
+ }
+ }
+ else // No decord :)
+ {
+ self->cbwidth_l = 0;
+ self->cbwidth_r = 0;
+ self->cbwidth_b = 0;
+ self->cbwidth_t = 0;
+ STRUT_SET(self->size, self->cbwidth_l, self->cbwidth_t,
+ self->cbwidth_r, self->cbwidth_b);
+
+ RECT_SET_SIZE(self->window_area, self->client->area.width
+ + self->size.left + self->size.right, self->client->area.height
+ + self->size.top + self->size.bottom);
+
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->window_area.x = self->client_area.x;
+ self->window_area.y = self->client_area.y;
+ frame_client_gravity(self->client, &self->window_area.x,
+ &self->window_area.y);
+
+ if (!is_fake) {
+ XUnmapWindow(plugin.ob_display, self->top);
+ XUnmapWindow(plugin.ob_display, self->bottom);
+ XUnmapWindow(plugin.ob_display, self->left);
+ XUnmapWindow(plugin.ob_display, self->right);
+ XUnmapWindow(plugin.ob_display, self->top_left);
+ XUnmapWindow(plugin.ob_display, self->top_right);
+ XUnmapWindow(plugin.ob_display, self->bottom_left);
+ XUnmapWindow(plugin.ob_display, self->bottom_right);
+
+ XUnmapWindow(plugin.ob_display, self->title);
+
+ XMoveResizeWindow(plugin.ob_display, self->background, 0, 0,
+ self->window_area.width, self->window_area.height);
+ XMapWindow(plugin.ob_display, self->background);
+ if (!is_resize) {
+ XMoveResizeWindow(plugin.ob_display, self->client->window,
+ self->size.left, self->size.top,
+ self->window_area.width, self->window_area.height);
+ }
+ XMoveResizeWindow(plugin.ob_display, self->window,
+ self->window_area.x, self->window_area.y,
+ self->window_area.width, self->window_area.height);
+ }
+ }
+}
+
+void frame_update_skin(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ if (plugin.frame_iconify_animating(self))
+ return; /* delay redrawing until the animation is done */
+
+ if (!self->visible)
+ return;
+ self->need_render = FALSE;
+
+ gulong border_px, corner_px;
+
+ if (self->focused) {
+ border_px = RrColorPixel(theme_config.focus_border_color);
+ corner_px = RrColorPixel(theme_config.focus_corner_color);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->left,
+ theme_config.px_focus_left);
+ XClearWindow(plugin.ob_display, self->left);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->right,
+ theme_config.px_focus_right);
+ XClearWindow(plugin.ob_display, self->right);
+
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->top,
+ theme_config.px_focus_top);
+ XClearWindow(plugin.ob_display, self->top);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->bottom,
+ theme_config.px_focus_bottom);
+ XClearWindow(plugin.ob_display, self->bottom);
+
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->top_left,
+ theme_config.px_focus_topleft);
+ XClearWindow(plugin.ob_display, self->top_left);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->top_right,
+ theme_config.px_focus_topright);
+ XClearWindow(plugin.ob_display, self->top_right);
+
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->bottom_left,
+ theme_config.px_focus_bottomleft);
+ XClearWindow(plugin.ob_display, self->bottom_left);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->bottom_right,
+ theme_config.px_focus_bottomright);
+ XClearWindow(plugin.ob_display, self->bottom_right);
+
+ XSetWindowBackground(plugin.ob_display, self->title, 0x00ffff);
+ XClearWindow(plugin.ob_display, self->title);
+ XSetWindowBackground(plugin.ob_display, self->background, 0);
+ XClearWindow(plugin.ob_display, self->background);
+ }
+ else {
+ border_px = RrColorPixel(theme_config.unfocus_border_color);
+ corner_px = RrColorPixel(theme_config.unfocus_corner_color);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->left,
+ theme_config.px_unfocus_left);
+ XClearWindow(plugin.ob_display, self->left);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->right,
+ theme_config.px_unfocus_right);
+ XClearWindow(plugin.ob_display, self->right);
+
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->top,
+ theme_config.px_unfocus_top);
+ XClearWindow(plugin.ob_display, self->top);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->bottom,
+ theme_config.px_unfocus_bottom);
+ XClearWindow(plugin.ob_display, self->bottom);
+
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->top_left,
+ theme_config.px_unfocus_topleft);
+ XClearWindow(plugin.ob_display, self->top_left);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->top_right,
+ theme_config.px_unfocus_topright);
+ XClearWindow(plugin.ob_display, self->top_right);
+
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->bottom_left,
+ theme_config.px_unfocus_bottomleft);
+ XClearWindow(plugin.ob_display, self->bottom_left);
+ XSetWindowBackgroundPixmap(plugin.ob_display, self->bottom_right,
+ theme_config.px_unfocus_bottomright);
+ XClearWindow(plugin.ob_display, self->bottom_right);
+
+ XSetWindowBackground(plugin.ob_display, self->title, 0x00ffff);
+ XClearWindow(plugin.ob_display, self->title);
+ XSetWindowBackground(plugin.ob_display, self->background, 0);
+ XClearWindow(plugin.ob_display, self->background);
+ }
+ XFlush(plugin.ob_display);
+}
+
+void frame_set_hover_flag(gpointer self, ObFrameButton button)
+{
+ if (OBCONCEPTFRAME(self)->hover_flag != button) {
+ OBCONCEPTFRAME(self)->hover_flag = button;
+ frame_update_skin(self);
+ }
+}
+
+void frame_set_press_flag(gpointer self, ObFrameButton button)
+{
+ if (OBCONCEPTFRAME(self)->press_flag != button) {
+ OBCONCEPTFRAME(self)->press_flag = button;
+ frame_update_skin(self);
+ }
+}
+
+Window frame_get_window(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->window;
+}
+
+Strut frame_get_size(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->size;
+}
+
+gint frame_get_decorations(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->decorations;
+}
+
+gboolean frame_is_visible(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->visible;
+}
+
+gboolean frame_is_max_horz(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->max_horz;
+}
+
+gboolean frame_is_max_vert(gpointer self)
+{
+ return OBCONCEPTFRAME(self)->max_vert;
+}
+
+static gulong frame_animate_iconify_time_left(gpointer _self,
+ const GTimeVal *now)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ glong sec, usec;
+ sec = self->iconify_animation_end.tv_sec - now->tv_sec;
+ usec = self->iconify_animation_end.tv_usec - now->tv_usec;
+ if (usec < 0) {
+ usec += G_USEC_PER_SEC;
+ sec--;
+ }
+ /* no negative values */
+ return MAX(sec * G_USEC_PER_SEC + usec, 0);
+}
+
+gboolean frame_animate_iconify(gpointer p)
+{
+ ObConceptFrame *self = p;
+ gint x, y, w, h;
+ gint iconx, icony, iconw;
+ GTimeVal now;
+ gulong time;
+ gboolean iconifying;
+
+ if (self->client->icon_geometry.width == 0) {
+ /* there is no icon geometry set so just go straight down */
+ Rect
+ *a =
+ screen_physical_area_monitor(screen_find_monitor(&self->window_area));
+ iconx = self->window_area.x + self->window_area.width / 2 + 32;
+ icony = a->y + a->width;
+ iconw = 64;
+ g_free(a);
+ }
+ else {
+ iconx = self->client->icon_geometry.x;
+ icony = self->client->icon_geometry.y;
+ iconw = self->client->icon_geometry.width;
+ }
+
+ iconifying = self->iconify_animation_going > 0;
+
+ /* how far do we have left to go ? */
+ g_get_current_time(&now);
+ time = frame_animate_iconify_time_left(self, &now);
+
+ if (time == 0 || iconifying) {
+ /* start where the frame is supposed to be */
+ x = self->window_area.x;
+ y = self->window_area.y;
+ w = self->window_area.width;
+ h = self->window_area.height;
+ }
+ else {
+ /* start at the icon */
+ x = iconx;
+ y = icony;
+ w = iconw;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time > 0) {
+ glong dx, dy, dw;
+ glong elapsed;
+
+ dx = self->window_area.x - iconx;
+ dy = self->window_area.y - icony;
+ dw = self->window_area.width - iconw;
+ /* if restoring, we move in the opposite direction */
+ if (!iconifying) {
+ dx = -dx;
+ dy = -dy;
+ dw = -dw;
+ }
+
+ elapsed = FRAME_ANIMATE_ICONIFY_TIME - time;
+ x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time == 0)
+ frame_end_iconify_animation(self);
+ else {
+ XMoveResizeWindow(plugin.ob_display, self->window, x, y, w, h);
+ XFlush(plugin.ob_display);
+ }
+
+ return time > 0; /* repeat until we're out of time */
+}
+
+/* change the cursor */
+void frame_adjust_cursors(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+
+ XSetWindowAttributes a;
+ a.cursor = ob_cursor(OB_CURSOR_NORTH);
+ XChangeWindowAttributes(plugin.ob_display, self->top, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_SOUTH);
+ XChangeWindowAttributes(plugin.ob_display, self->bottom, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_WEST);
+ XChangeWindowAttributes(plugin.ob_display, self->left, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_EAST);
+ XChangeWindowAttributes(plugin.ob_display, self->right, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_NORTHWEST);
+ XChangeWindowAttributes(plugin.ob_display, self->top_left, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_NORTHEAST);
+ XChangeWindowAttributes(plugin.ob_display, self->top_right, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_SOUTHWEST);
+ XChangeWindowAttributes(plugin.ob_display, self->bottom_left, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_SOUTHEAST);
+ XChangeWindowAttributes(plugin.ob_display, self->bottom_right, CWCursor, &a);
+
+}
+
+void frame_adjust_client_area(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* adjust the window which is there to prevent flashing on unmap */
+ XMoveResizeWindow(plugin.ob_display, self->background, 0, 0,
+ self->client->area.width, self->client->area.height);
+}
+
+void frame_adjust_state(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+}
+
+void frame_adjust_focus(gpointer _self, gboolean hilite)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->focused = hilite;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+ XFlush(plugin.ob_display);
+}
+
+void frame_adjust_title(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+}
+
+void frame_adjust_icon(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+}
+
+/* is there anything present between us and the label? */
+static gboolean is_button_present(ObConceptFrame *_self, const gchar *lc,
+ gint dir)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ for (; *lc != '\0' && lc >= plugin.config_title_layout; lc += dir) {
+ if (*lc == ' ')
+ continue; /* it was invalid */
+ if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
+ return TRUE;
+ if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
+ return TRUE;
+ if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
+ return TRUE;
+ if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
+ return TRUE;
+ if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
+ return TRUE;
+ if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
+ return TRUE;
+ if (*lc == 'L')
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void flash_done(gpointer data)
+{
+ ObConceptFrame *self = data;
+
+ if (self->focused != self->flash_on)
+ frame_adjust_focus(self, self->focused);
+}
+
+gboolean flash_timeout(gpointer data)
+{
+ ObConceptFrame *self = data;
+ GTimeVal now;
+
+ g_get_current_time(&now);
+ if (now.tv_sec > self->flash_end.tv_sec
+ || (now.tv_sec == self->flash_end.tv_sec && now.tv_usec
+ >= self->flash_end.tv_usec))
+ self->flashing = FALSE;
+
+ if (!self->flashing)
+ return FALSE; /* we are done */
+
+ self->flash_on = !self->flash_on;
+ if (!self->focused) {
+ frame_adjust_focus(self, self->flash_on);
+ self->focused = FALSE;
+ }
+
+ return TRUE; /* go again */
+}
+
+ObFramePlugin plugin = { 0, //gpointer handler;
+ "libconcept.la", //gchar * filename;
+ "Concept", //gchar * name;
+ init, //gint (*init) (Display * display, gint screen);
+ 0, frame_new, //gpointer (*frame_new) (struct _ObClient *c);
+ frame_free, //void (*frame_free) (gpointer self);
+ frame_show, //void (*frame_show) (gpointer self);
+ frame_hide, //void (*frame_hide) (gpointer self);
+ frame_adjust_theme, //void (*frame_adjust_theme) (gpointer self);
+ frame_adjust_shape, //void (*frame_adjust_shape) (gpointer self);
+ frame_grab, //void (*frame_adjust_area) (gpointer self, gboolean moved, gboolean resized, gboolean fake);
+ frame_ungrab, frame_context, //void (*frame_adjust_state) (gpointer self);
+ frame_set_is_visible, frame_set_is_focus, frame_set_is_max_vert,
+ frame_set_is_max_horz, frame_set_is_shaded,
+
+ frame_flash_start, frame_flash_stop, frame_begin_iconify_animation,
+ frame_end_iconify_animation, frame_iconify_animating,
+
+ frame_set_decorations,
+ /* This give the window area */
+ frame_get_window_area, frame_set_client_area,
+ /* Draw the frame */
+ frame_update_layout, frame_update_skin,
+
+ frame_set_hover_flag, frame_set_press_flag,
+
+ frame_get_window,
+
+ frame_get_size, frame_get_decorations,
+
+ frame_is_visible, frame_is_max_horz, frame_is_max_vert,
+
+ load_theme_config,
+
+ /* This fields are fill by openbox. */
+ 0, //Display * ob_display;
+ 0, //gint ob_screen;
+ 0, //RrInstance *ob_rr_inst;
+ 0, //gboolean config_theme_keepborder;
+ 0, //struct _ObClient *focus_cycle_target;
+ 0, //gchar *config_title_layout;
+ FALSE, //gboolean moveresize_in_progress;
+ 0, //struct _ObMainLoop *ob_main_loop;
+};
+
+ObFramePlugin * get_info()
+{
+ return &plugin;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_plugin.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_CONCEPT_PLUGIN_H_
+#define FRAME_CONCEPT_PLUGIN_H_
+
+#include "config.h"
+
+#include "render/render.h"
+#include "openbox/engine_interface.h"
+
+ObFrameThemeConfig theme_config;
+
+typedef enum {
+ OB_FRAME_STASE_IS_VISIBLE = 1 << 0,
+ OB_FRAME_STASE_IS_FOCUS = 1 << 1,
+ OB_FRAME_STASE_IS_MAX_VERT = 1 << 2,
+ OB_FRAME_STASE_IS_MAX_HORZ = 1 << 3,
+ OB_FRAME_STASE_IS_SHADED = 1 << 4
+} ObFrameStaseFlags;
+
+struct _ObConceptFrame
+{
+ /* PUBLIC : */
+
+ /* PRIVATE: */
+ /* You are free to add what you want here */
+ Window window;
+
+ gboolean visible;
+
+ gboolean max_horz; /* when maxed some decorations are hidden */
+ gboolean max_vert; /* when maxed some decorations are hidden */
+
+ struct _ObClient *client;
+ guint decorations;
+
+ Strut size;
+ Rect client_area; /* the area of the client window */
+ Rect window_area; /* the area of the window with/without decorations */
+
+ ObFrameButton hover_flag;
+ ObFrameButton press_flag;
+
+ ObStyle style;
+
+ guint functions;
+
+ gint iconify_animation_going;
+ /* These are borders of the frame and its elements */
+
+ Window title;
+
+ Window top;
+ Window bottom;
+ Window left;
+ Window right;
+
+ Window top_left;
+ Window top_right;
+
+ Window bottom_left;
+ Window bottom_right;
+
+ Window background;
+
+ Colormap colormap;
+
+ RrAppearance *a_unfocused_title;
+ RrAppearance *a_focused_title;
+ RrAppearance *a_unfocused_label;
+ RrAppearance *a_focused_label;
+ RrAppearance *a_icon;
+ RrAppearance *a_unfocused_handle;
+ RrAppearance *a_focused_handle;
+
+ gint icon_on; /* if the window icon button is on */
+ gint label_on; /* if the window title is on */
+ gint iconify_on; /* if the window iconify button is on */
+ gint desk_on; /* if the window all-desktops button is on */
+ gint shade_on; /* if the window shade button is on */
+ gint max_on; /* if the window maximize button is on */
+ gint close_on; /* if the window close button is on */
+
+ gint title_width; /* width of the titlebar and handle */
+
+ gint label_width; /* width of the label in the titlebar */
+ gint icon_x; /* x-position of the window icon button */
+ gint label_x; /* x-position of the window title */
+ gint iconify_x; /* x-position of the window iconify button */
+ gint desk_x; /* x-position of the window all-desktops button */
+ gint shade_x; /* x-position of the window shade button */
+ gint max_x; /* x-position of the window maximize button */
+ gint close_x; /* x-position of the window close button */
+
+ gint cbwidth_l; /* client border width */
+ gint cbwidth_t; /* client border width */
+ gint cbwidth_r; /* client border width */
+ gint cbwidth_b; /* client border width */
+ gboolean shaded; /* decorations adjust when shaded */
+
+ /* the leftmost and rightmost elements in the titlebar */
+ ObFrameContext leftmost;
+ ObFrameContext rightmost;
+
+ gboolean focused;
+ gboolean need_render;
+
+ gboolean flashing;
+ gboolean flash_on;
+ GTimeVal flash_end;
+
+ GTimeVal iconify_animation_end;
+
+ ObFrameStaseFlags frame_stase_flags;
+
+};
+
+typedef struct _ObConceptFrame ObConceptFrame;
+
+/* Function use for interface */
+gint init(Display *, gint);
+
+gpointer frame_new(struct _ObClient *c);
+void frame_free(gpointer self);
+
+void frame_show(gpointer self);
+gint frame_hide(gpointer self);
+
+void frame_adjust_theme(gpointer self);
+void frame_adjust_shape(gpointer self);
+
+void frame_grab(gpointer self, GHashTable *);
+void frame_ungrab(gpointer self, GHashTable *);
+
+ObFrameContext frame_context(gpointer, Window, gint, gint);
+
+void frame_set_is_visible(gpointer, gboolean);
+void frame_set_is_focus(gpointer, gboolean);
+void frame_set_is_max_vert(gpointer, gboolean);
+void frame_set_is_max_horz(gpointer, gboolean);
+void frame_set_is_shaded(gpointer, gboolean);
+
+void frame_flash_start(gpointer self);
+void frame_flash_stop(gpointer self);
+void frame_begin_iconify_animation(gpointer self, gboolean iconifying);
+void frame_end_iconify_animation(gpointer self);
+gboolean frame_iconify_animating(gpointer _self);
+
+/* Set the layout wanted by client */
+void frame_update_state(gpointer, ObFrameState);
+/* This give the allowed area for client window */
+Rect frame_get_window_area(gpointer);
+void frame_set_client_area(gpointer, Rect);
+/* Draw the frame */
+void frame_update_layout(gpointer, gboolean, gboolean);
+void frame_update_skin(gpointer);
+
+void frame_set_hover_flag(gpointer, ObFrameButton);
+void frame_set_press_flag(gpointer, ObFrameButton);
+
+Window frame_get_window(gpointer);
+
+Strut frame_get_size(gpointer);
+
+gint frame_get_decorations(gpointer);
+
+gboolean frame_is_visible(gpointer);
+gboolean frame_is_max_horz(gpointer);
+gboolean frame_is_max_vert(gpointer);
+
+/* Internal function */
+void flash_done(gpointer data);
+gboolean flash_timeout(gpointer data);
+void set_theme_statics(gpointer self);
+void free_theme_statics(gpointer self);
+gboolean frame_animate_iconify(gpointer self);
+void frame_adjust_cursors(gpointer self);
+
+/* Global for frame_concept_render.c only */
+extern ObFramePlugin plugin;
+#define OBCONCEPTFRAME(x) ((ObConceptFrame *)(x))
+
+#endif /*FRAME_CONCEPT_PLUGIN_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_config.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "frame_concept2_config.h"
+#include "frame_concept2_plugin.h"
+
+#include "render/render.h"
+#include "render/color.h"
+#include "render/font.h"
+#include "render/mask.h"
+#include "render/icon.h"
+#include "parser/parse.h"
+
+#include <X11/Xlib.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+static XrmDatabase loaddb(const gchar *name, gchar **path);
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value);
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value);
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans);
+static int parse_inline_number(const char *p);
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
+static void set_default_appearance(RrAppearance *a);
+
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font)
+{
+ gchar *str;
+
+ if (!read_int(db, "concept.border_width", &theme_config.border_width)) {
+ theme_config.border_width = 2;
+ }
+ if (!read_int(db, "concept.left_width", &theme_config.left_width)) {
+ theme_config.left_width = 15;
+ }
+ if (!read_color(db, inst, "concept.focus_border_color",
+ &theme_config.focus_border_color)) {
+ theme_config.focus_border_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ if (!read_color(db, inst, "concept.focus_corner_color",
+ &theme_config.focus_corner_color)) {
+ theme_config.focus_corner_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ if (!read_color(db, inst, "concept.unfocus_border_color",
+ &theme_config.unfocus_border_color)) {
+ theme_config.focus_border_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ if (!read_color(db, inst, "concept.unfocus_corner_color",
+ &theme_config.unfocus_corner_color)) {
+ theme_config.focus_corner_color = RrColorNew(inst, 0, 0, 0);
+ }
+
+ theme_config.inst = inst;
+ theme_config.name = g_strdup(name ? name : DEFAULT_THEME);
+
+ return 1;
+}
+
+static XrmDatabase loaddb(const gchar *name, gchar **path)
+{
+ GSList *it;
+ XrmDatabase db = NULL;
+ gchar *s;
+
+ if (name[0] == '/') {
+ s = g_build_filename(name, "openbox-3", "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+ else {
+ /* XXX backwards compatibility, remove me sometime later */
+ s = g_build_filename(g_get_home_dir(), ".themes", name, "openbox-3",
+ "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+
+ for (it = parse_xdg_data_dir_paths(); !db && it; it = g_slist_next(it)) {
+ s = g_build_filename(it->data, "themes", name, "openbox-3",
+ "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+ }
+
+ if (db == NULL) {
+ s = g_build_filename(name, "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+
+ return db;
+}
+
+static gchar *create_class_name(const gchar *rname)
+{
+ gchar *rclass = g_strdup(rname);
+ gchar *p = rclass;
+
+ while (TRUE) {
+ *p = toupper(*p);
+ p = strchr(p+1, '.');
+ if (p == NULL)
+ break;
+ ++p;
+ if (*p == '\0')
+ break;
+ }
+ return rclass;
+}
+
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype, *end;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = (gint)strtol(retvalue.addr, &end, 10);
+ if (end != retvalue.addr)
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = retvalue.addr;
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ RrColor *c = RrColorParse(inst, retvalue.addr);
+ if (c != NULL) {
+ *value = c;
+ ret = TRUE;
+ }
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value)
+{
+ gboolean ret = FALSE;
+ gchar *s;
+ gint hx, hy; /* ignored */
+ guint w, h;
+ guchar *b;
+
+ s = g_build_filename(path, maskname, NULL);
+ if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
+ ret = TRUE;
+ *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
+ XFree(b);
+ }
+ g_free(s);
+
+ return ret;
+}
+
+static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
+ RrReliefType *relief, RrBevelType *bevel, gboolean *interlaced,
+ gboolean *border, gboolean allow_trans)
+{
+ gchar *t;
+
+ /* convert to all lowercase */
+ for (t = tex; *t != '\0'; ++t)
+ *t = g_ascii_tolower(*t);
+
+ if (allow_trans && strstr(tex, "parentrelative") != NULL) {
+ *grad = RR_SURFACE_PARENTREL;
+ }
+ else {
+ if (strstr(tex, "gradient") != NULL) {
+ if (strstr(tex, "crossdiagonal") != NULL)
+ *grad = RR_SURFACE_CROSS_DIAGONAL;
+ else if (strstr(tex, "pyramid") != NULL)
+ *grad = RR_SURFACE_PYRAMID;
+ else if (strstr(tex, "mirrorhorizontal") != NULL)
+ *grad = RR_SURFACE_MIRROR_HORIZONTAL;
+ else if (strstr(tex, "horizontal") != NULL)
+ *grad = RR_SURFACE_HORIZONTAL;
+ else if (strstr(tex, "splitvertical") != NULL)
+ *grad = RR_SURFACE_SPLIT_VERTICAL;
+ else if (strstr(tex, "vertical") != NULL)
+ *grad = RR_SURFACE_VERTICAL;
+ else
+ *grad = RR_SURFACE_DIAGONAL;
+ }
+ else {
+ *grad = RR_SURFACE_SOLID;
+ }
+ }
+
+ if (strstr(tex, "sunken") != NULL)
+ *relief = RR_RELIEF_SUNKEN;
+ else if (strstr(tex, "flat") != NULL)
+ *relief = RR_RELIEF_FLAT;
+ else if (strstr(tex, "raised") != NULL)
+ *relief = RR_RELIEF_RAISED;
+ else
+ *relief = (*grad == RR_SURFACE_PARENTREL) ? RR_RELIEF_FLAT
+ : RR_RELIEF_RAISED;
+
+ *border = FALSE;
+ if (*relief == RR_RELIEF_FLAT) {
+ if (strstr(tex, "border") != NULL)
+ *border = TRUE;
+ }
+ else {
+ if (strstr(tex, "bevel2") != NULL)
+ *bevel = RR_BEVEL_2;
+ else
+ *bevel = RR_BEVEL_1;
+ }
+
+ if (strstr(tex, "interlaced") != NULL)
+ *interlaced = TRUE;
+ else
+ *interlaced = FALSE;
+}
+
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
+ gchar *csplitname, *ctosplitname;
+ gchar *rettype;
+ XrmValue retvalue;
+ gint i;
+
+ cname = g_strconcat(rname, ".color", NULL);
+ ctoname = g_strconcat(rname, ".colorTo", NULL);
+ bcname = g_strconcat(rname, ".border.color", NULL);
+ icname = g_strconcat(rname, ".interlace.color", NULL);
+ hname = g_strconcat(rname, ".highlight", NULL);
+ sname = g_strconcat(rname, ".shadow", NULL);
+ csplitname = g_strconcat(rname, ".color.splitTo", NULL);
+ ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ parse_appearance(retvalue.addr, &value->surface.grad,
+ &value->surface.relief, &value->surface.bevel,
+ &value->surface.interlaced, &value->surface.border, allow_trans);
+ if (!read_color(db, inst, cname, &value->surface.primary))
+ value->surface.primary = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, ctoname, &value->surface.secondary))
+ value->surface.secondary = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.border)
+ if (!read_color(db, inst, bcname, &value->surface.border_color))
+ value->surface.border_color = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.interlaced)
+ if (!read_color(db, inst, icname, &value->surface.interlace_color))
+ value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
+ if (read_int(db, hname, &i) && i >= 0)
+ value->surface.bevel_light_adjust = i;
+ if (read_int(db, sname, &i) && i >= 0 && i <= 256)
+ value->surface.bevel_dark_adjust = i;
+
+ if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
+ gint r, g, b;
+
+ if (!read_color(db, inst, csplitname, &value->surface.split_primary)) {
+ r = value->surface.primary->r;
+ r += r >> 2;
+ g = value->surface.primary->g;
+ g += g >> 2;
+ b = value->surface.primary->b;
+ b += b >> 2;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_primary = RrColorNew(inst, r, g, b);
+ }
+
+ if (!read_color(db, inst, ctosplitname,
+ &value->surface.split_secondary)) {
+ r = value->surface.secondary->r;
+ r += r >> 4;
+ g = value->surface.secondary->g;
+ g += g >> 4;
+ b = value->surface.secondary->b;
+ b += b >> 4;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_secondary = RrColorNew(inst, r, g, b);
+ }
+ }
+
+ ret = TRUE;
+ }
+
+ g_free(ctosplitname);
+ g_free(csplitname);
+ g_free(sname);
+ g_free(hname);
+ g_free(icname);
+ g_free(bcname);
+ g_free(ctoname);
+ g_free(cname);
+ g_free(rclass);
+ return ret;
+}
+
+static int parse_inline_number(const char *p)
+{
+ int neg = 1;
+ int res = 0;
+ if (*p == '-') {
+ neg = -1;
+ ++p;
+ }
+ for (; isdigit(*p); ++p)
+ res = res * 10 + *p - '0';
+ res *= neg;
+ return res;
+}
+
+static void set_default_appearance(RrAppearance *a)
+{
+ a->surface.grad = RR_SURFACE_SOLID;
+ a->surface.relief = RR_RELIEF_FLAT;
+ a->surface.bevel = RR_BEVEL_1;
+ a->surface.interlaced = FALSE;
+ a->surface.border = FALSE;
+ a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
+ a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
+}
+
+/* Reads the output from gimp's C-Source file format into valid RGBA data for
+ an RrTextureRGBA. */
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
+{
+ RrPixel32 *im, *p;
+ gint i;
+
+ p = im = g_memdup(data, width * height * sizeof(RrPixel32));
+
+ for (i = 0; i < width * height; ++i) {
+ guchar a = ((*p >> 24) & 0xff);
+ guchar b = ((*p >> 16) & 0xff);
+ guchar g = ((*p >> 8) & 0xff);
+ guchar r = ((*p >> 0) & 0xff);
+
+ *p = ((r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + (b
+ << RrDefaultBlueOffset) + (a << RrDefaultAlphaOffset));
+ p++;
+ }
+
+ return im;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_config.h for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_CONCEPT2_CONFIG_H_
+#define FRAME_CONCEPT2_CONFIG_H_
+
+#include <X11/Xresource.h>
+#include "render/render.h"
+
+G_BEGIN_DECLS
+
+struct _ObFrameThemeConfig
+{
+ const RrInstance *inst;
+
+ gint border_width;
+ gint left_width;
+ RrColor * focus_border_color;
+ RrColor * focus_corner_color;
+ RrColor * unfocus_border_color;
+ RrColor * unfocus_corner_color;
+
+ gchar *name;
+};
+
+typedef struct _ObFrameThemeConfig ObFrameThemeConfig;
+
+/*! The font values are all optional. If a NULL is used for any of them, then
+ the default font will be used. */
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font);
+
+G_END_DECLS
+
+#endif /*FRAME_CONCEPT2_CONFIG_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_plugin.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "frame_concept2_plugin.h"
+#include "frame_concept2_render.h"
+
+#include "openbox/frame.h"
+#include "openbox/client.h"
+#include "openbox/openbox.h"
+#include "openbox/extensions.h"
+#include "openbox/prop.h"
+#include "openbox/grab.h"
+#include "openbox/config.h"
+#include "openbox/mainloop.h"
+#include "openbox/focus_cycle.h"
+#include "openbox/focus_cycle_indicator.h"
+#include "openbox/moveresize.h"
+#include "openbox/screen.h"
+#include "render/theme.h"
+
+typedef enum
+{
+ OB_FLAG_MAX = 1 << 0,
+ OB_FLAG_CLOSE = 1 << 1,
+ OB_FLAG_DESK = 1 << 2,
+ OB_FLAG_SHADE = 1 << 3,
+ OB_FLAG_ICONIFY = 1 << 4
+} ObFrameFlags;
+
+#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
+ ButtonPressMask | ButtonReleaseMask | \
+ SubstructureRedirectMask | FocusChangeMask)
+#define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
+ ButtonMotionMask | PointerMotionMask | \
+ EnterWindowMask | LeaveWindowMask)
+
+#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
+#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
+
+#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b)
+
+Window createWindow(Window parent, Visual *visual, gulong mask,
+ XSetWindowAttributes *attrib)
+{
+ return XCreateWindow(plugin.ob_display, parent, 0, 0, 1, 1, 0, (visual ? 32
+ : RrDepth(plugin.ob_rr_inst)), InputOutput, (visual ? visual
+ : RrVisual(plugin.ob_rr_inst)), mask, attrib);
+
+}
+
+Visual *check_32bit_client(ObClient *c)
+{
+ XWindowAttributes wattrib;
+ Status ret;
+
+ /* we're already running at 32 bit depth, yay. we don't need to use their
+ visual */
+ if (RrDepth(plugin.ob_rr_inst) == 32)
+ return NULL;
+
+ ret = XGetWindowAttributes(plugin.ob_display, c->window, &wattrib);
+ g_assert(ret != BadDrawable);
+ g_assert(ret != BadWindow);
+
+ if (wattrib.depth == 32)
+ return wattrib.visual;
+ return NULL;
+}
+
+/* Not used */
+gint init(Display * display, gint screen)
+{
+ plugin.ob_display = display;
+ plugin.ob_screen = screen;
+}
+
+gpointer frame_new(struct _ObClient * client)
+{
+ XSetWindowAttributes attrib;
+ gulong mask;
+ ObConceptFrame *self;
+ Visual *visual;
+
+ self = g_new0(ObConceptFrame, 1);
+ self->client = client;
+
+ visual = check_32bit_client(client);
+
+ /* create the non-visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ /* create a colormap with the visual */
+ OBCONCEPTFRAME(self)->colormap = attrib.colormap = XCreateColormap(
+ plugin.ob_display, RootWindow(plugin.ob_display,
+ plugin.ob_screen), visual, AllocNone);
+ attrib.background_pixel = BlackPixel(plugin.ob_display,
+ plugin.ob_screen);
+ attrib.border_pixel = BlackPixel(plugin.ob_display, plugin.ob_screen);
+ }
+ self->window = createWindow(
+ RootWindow(plugin.ob_display, plugin.ob_screen), visual, mask,
+ &attrib);
+
+ /* create the visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ attrib.colormap = RrColormap(plugin.ob_rr_inst);
+ }
+
+ self->background = createWindow(self->window, NULL, mask, &attrib);
+
+ mask |= CWEventMask;
+ attrib.event_mask = ELEMENT_EVENTMASK;
+
+ self->top = createWindow(self->window, NULL, mask, &attrib);
+ self->bottom = createWindow(self->window, NULL, mask, &attrib);
+ self->left = createWindow(self->window, NULL, mask, &attrib);
+ self->right = createWindow(self->window, NULL, mask, &attrib);
+
+ self->left_close = createWindow(self->left, NULL, mask, &attrib);
+ self->left_iconify = createWindow(self->left, NULL, mask, &attrib);
+ self->left_maximize = createWindow(self->left, NULL, mask, &attrib);
+ self->left_shade = createWindow(self->left, NULL, mask, &attrib);
+
+ self->handle = createWindow(self->left, NULL, mask, &attrib);
+
+ self->top_left = createWindow(self->window, NULL, mask, &attrib);
+ self->top_right = createWindow(self->window, NULL, mask, &attrib);
+
+ self->bottom_left = createWindow(self->window, NULL, mask, &attrib);
+ self->bottom_right = createWindow(self->window, NULL, mask, &attrib);
+
+ XMapWindow(plugin.ob_display, self->background);
+
+ self->focused = FALSE;
+
+ self->max_press = FALSE;
+ self->close_press = FALSE;
+ self->desk_press = FALSE;
+ self->iconify_press = FALSE;
+ self->shade_press = FALSE;
+ self->max_hover = FALSE;
+ self->close_hover = FALSE;
+ self->desk_hover = FALSE;
+ self->iconify_hover = FALSE;
+ self->shade_hover = FALSE;
+
+ set_theme_statics(self);
+
+ return (ObFrame*)self;
+}
+
+void set_theme_statics(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* do this before changing the frame's status like max_horz max_vert */
+
+ XResizeWindow(plugin.ob_display, self->top_left, 15,
+ theme_config.border_width);
+ XResizeWindow(plugin.ob_display, self->top_right, 15,
+ theme_config.border_width);
+ XResizeWindow(plugin.ob_display, self->bottom_left, 15,
+ theme_config.border_width);
+ XResizeWindow(plugin.ob_display, self->bottom_right, 15,
+ theme_config.border_width);
+
+ XResizeWindow(plugin.ob_display, self->left_close, theme_config.left_width,
+ 15);
+ XResizeWindow(plugin.ob_display, self->left_iconify,
+ theme_config.left_width, 15);
+ XResizeWindow(plugin.ob_display, self->left_maximize,
+ theme_config.left_width, 15);
+ XResizeWindow(plugin.ob_display, self->left_shade, theme_config.left_width,
+ 15);
+ XResizeWindow(plugin.ob_display, self->handle, theme_config.left_width, 15);
+
+ XMoveWindow(plugin.ob_display, self->left_close, 0, 0);
+ XMoveWindow(plugin.ob_display, self->left_iconify, 0, 15);
+ XMoveWindow(plugin.ob_display, self->left_maximize, 0, 30);
+ XMoveWindow(plugin.ob_display, self->left_shade, 0, 45);
+ XMoveWindow(plugin.ob_display, self->handle, 0, 60);
+
+}
+
+void free_theme_statics(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+}
+
+void frame_free(gpointer self)
+{
+ free_theme_statics(OBCONCEPTFRAME(self));
+ XDestroyWindow(plugin.ob_display, OBCONCEPTFRAME(self)->window);
+ if (OBCONCEPTFRAME(self)->colormap)
+ XFreeColormap(plugin.ob_display, OBCONCEPTFRAME(self)->colormap);
+ g_free(self);
+}
+
+void frame_show(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ if (!self->visible) {
+ self->visible = TRUE;
+ frame_update_skin(self);
+ /* Grab the server to make sure that the frame window is mapped before
+ the client gets its MapNotify, i.e. to make sure the client is
+ _visible_ when it gets MapNotify. */
+ grab_server(TRUE);
+ XMapWindow(plugin.ob_display, self->client->window);
+ XMapWindow(plugin.ob_display, self->window);
+ grab_server(FALSE);
+ }
+}
+
+void frame_hide(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ if (self->visible) {
+ self->visible = FALSE;
+ if (!frame_iconify_animating(self))
+ XUnmapWindow(plugin.ob_display, self->window);
+ /* we unmap the client itself so that we can get MapRequest
+ events, and because the ICCCM tells us to! */
+ XUnmapWindow(plugin.ob_display, self->client->window);
+ self->client->ignore_unmaps += 1;
+ }
+}
+
+void frame_adjust_theme(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ free_theme_statics(self);
+ set_theme_statics(self);
+}
+
+void frame_adjust_shape(gpointer _self)
+{
+#ifdef SHAPE
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ gint num;
+ XRectangle xrect[2];
+
+ if (!self->client->shaped)
+ {
+ /* clear the shape on the frame window */
+ XShapeCombineMask(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ None, ShapeSet);
+ }
+ else
+ {
+ /* make the frame's shape match the clients */
+ XShapeCombineShape(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ self->client->window,
+ ShapeBounding, ShapeSet);
+
+ num = 0;
+ if (self->decorations)
+ {
+ xrect[0].x = 0;
+ xrect[0].y = 0;
+ xrect[0].width = self->area.width;
+ xrect[0].height = self->size.top;
+ ++num;
+ }
+
+ XShapeCombineRectangles(plugin.ob_display, self->window,
+ ShapeBounding, 0, 0, xrect, num,
+ ShapeUnion, Unsorted);
+ }
+#endif
+}
+
+void frame_adjust_area(gpointer _self, gboolean moved, gboolean resized,
+ gboolean fake)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+
+ /* do this before changing the frame's status like max_horz max_vert */
+ frame_adjust_cursors(self);
+
+ /* Copy client status */
+ self->functions = self->client->functions;
+ self->decorations = self->client->decorations;
+ self->max_horz = self->client->max_horz;
+ self->max_vert = self->client->max_vert;
+ self->shaded = self->client->shaded;
+
+ if (self->decorations && !self->shaded) {
+ self->cbwidth_l = theme_config.left_width;
+ self->cbwidth_r = theme_config.border_width;
+ self->cbwidth_t = theme_config.border_width;
+ self->cbwidth_b = theme_config.border_width;
+
+ if (self->max_horz) {
+ self->cbwidth_l = theme_config.left_width;
+ self->cbwidth_r = 0;
+ }
+
+ if (self->max_vert) {
+ self->cbwidth_b = 0;
+ self->cbwidth_t = 0;
+ }
+
+ STRUT_SET(self->size, self->cbwidth_l, self->cbwidth_t,
+ self->cbwidth_r, self->cbwidth_b);
+
+ RECT_SET_SIZE(self->area, self->client->area.width + self->size.left
+ + self->size.right, self->client->area.height + self->size.top
+ + self->size.bottom);
+
+ self->width = self->area.width;
+
+ if (!fake) {
+
+ XMoveResizeWindow(plugin.ob_display, self->top, 15, 0,
+ self->area.width - 30, theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->top);
+
+ XMoveResizeWindow(plugin.ob_display, self->bottom, 15,
+ self->area.height - theme_config.border_width,
+ self->area.width - 30, theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->bottom);
+
+ XMoveResizeWindow(plugin.ob_display, self->left, 0,
+ theme_config.border_width, theme_config.left_width,
+ self->area.height - 2*theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->left);
+
+ XMoveResizeWindow(plugin.ob_display, self->right, self->area.width
+ - theme_config.border_width, theme_config.border_width,
+ theme_config.border_width, self->area.height - 2
+ *theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->right);
+
+ XMoveWindow(plugin.ob_display, self->top_left, 0, 0);
+ XMapWindow(plugin.ob_display, self->top_left);
+ XMoveWindow(plugin.ob_display, self->top_right, self->area.width
+ - 15, 0);
+ XMapWindow(plugin.ob_display, self->top_right);
+ XMoveWindow(plugin.ob_display, self->bottom_left, 0,
+ self->area.height - theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->bottom_left);
+ XMoveWindow(plugin.ob_display, self->bottom_right, self->area.width
+ - 15, self->area.height - theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->bottom_right);
+
+ XMapWindow(plugin.ob_display, self->left_close);
+ XMapWindow(plugin.ob_display, self->left_iconify);
+ XMapWindow(plugin.ob_display, self->left_maximize);
+ XMapWindow(plugin.ob_display, self->left_shade);
+ XMapWindow(plugin.ob_display, self->handle);
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->area.x = self->client->area.x;
+ self->area.y = self->client->area.y;
+ frame_client_gravity(self, &self->area.x, &self->area.y);
+
+ XMoveResizeWindow(plugin.ob_display, self->background,
+ theme_config.border_width, theme_config.border_width,
+ self->area.width - 2 * theme_config.border_width,
+ self->area.height - 2 * theme_config.border_width);
+ XMapWindow(plugin.ob_display, self->background);
+ }
+
+ XMoveWindow(plugin.ob_display, self->client->window, self->size.left,
+ self->size.top);
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+
+ }
+ else if (self->shaded) {
+ self->cbwidth_l = theme_config.left_width;
+ self->cbwidth_r = 0;
+ self->cbwidth_b = 0;
+ self->cbwidth_t = 0;
+ STRUT_SET(self->size, self->cbwidth_l, self->cbwidth_t,
+ self->cbwidth_r, self->cbwidth_b);
+
+ RECT_SET_SIZE(self->area, theme_config.left_width, self->area.height);
+
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->area.x = self->client->area.x;
+ self->area.y = self->client->area.y;
+ //frame_client_gravity(self, &self->area.x, &self->area.y);
+ self->width = self->area.width;
+ if (!fake) {
+ XUnmapWindow(plugin.ob_display, self->top);
+ XUnmapWindow(plugin.ob_display, self->bottom);
+ XUnmapWindow(plugin.ob_display, self->right);
+ XUnmapWindow(plugin.ob_display, self->top_left);
+ XUnmapWindow(plugin.ob_display, self->top_right);
+ XUnmapWindow(plugin.ob_display, self->bottom_left);
+ XUnmapWindow(plugin.ob_display, self->bottom_right);
+
+ XMoveResizeWindow(plugin.ob_display, self->left, 0, 0,
+ theme_config.left_width, self->area.height);
+ XMapWindow(plugin.ob_display, self->left);
+ }
+
+ XMoveWindow(plugin.ob_display, self->client->window,
+ theme_config.left_width, 0);
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+ }
+ else {
+ self->cbwidth_l = 0;
+ self->cbwidth_r = 0;
+ self->cbwidth_b = 0;
+ self->cbwidth_t = 0;
+ STRUT_SET(self->size, self->cbwidth_l, self->cbwidth_t,
+ self->cbwidth_r, self->cbwidth_b);
+
+ RECT_SET_SIZE(self->area, self->client->area.width + self->size.left
+ + self->size.right, self->client->area.height + self->size.top
+ + self->size.bottom);
+
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->area.x = self->client->area.x;
+ self->area.y = self->client->area.y;
+ frame_client_gravity(self, &self->area.x, &self->area.y);
+
+ self->width = self->area.width;
+ if (!fake) {
+ XUnmapWindow(plugin.ob_display, self->top);
+ XUnmapWindow(plugin.ob_display, self->bottom);
+ XUnmapWindow(plugin.ob_display, self->left);
+ XUnmapWindow(plugin.ob_display, self->right);
+ XUnmapWindow(plugin.ob_display, self->top_left);
+ XUnmapWindow(plugin.ob_display, self->top_right);
+ XUnmapWindow(plugin.ob_display, self->bottom_left);
+ XUnmapWindow(plugin.ob_display, self->bottom_right);
+
+ XUnmapWindow(plugin.ob_display, self->handle);
+
+ XMoveResizeWindow(plugin.ob_display, self->background, 0, 0,
+ self->area.width, self->area.height);
+ XMapWindow(plugin.ob_display, self->background);
+ }
+
+ XMoveWindow(plugin.ob_display, self->client->window, self->size.left,
+ self->size.top);
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+ }
+}
+
+void frame_adjust_cursors(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+
+ XSetWindowAttributes a;
+ a.cursor = ob_cursor(OB_CURSOR_NORTH);
+ XChangeWindowAttributes(plugin.ob_display, self->top, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_SOUTH);
+ XChangeWindowAttributes(plugin.ob_display, self->bottom, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_WEST);
+ XChangeWindowAttributes(plugin.ob_display, self->left, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_EAST);
+ XChangeWindowAttributes(plugin.ob_display, self->right, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_NORTHWEST);
+ XChangeWindowAttributes(plugin.ob_display, self->top_left, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_NORTHEAST);
+ XChangeWindowAttributes(plugin.ob_display, self->top_right, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_SOUTHWEST);
+ XChangeWindowAttributes(plugin.ob_display, self->bottom_left, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_SOUTHEAST);
+ XChangeWindowAttributes(plugin.ob_display, self->bottom_right, CWCursor, &a);
+
+ a.cursor = ob_cursor(OB_CURSOR_POINTER);
+ XChangeWindowAttributes(plugin.ob_display, self->left_close, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->left_iconify, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->left_maximize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->left_shade, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handle, CWCursor, &a);
+
+}
+
+void frame_adjust_client_area(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* adjust the window which is there to prevent flashing on unmap */
+ XMoveResizeWindow(plugin.ob_display, self->background, 0, 0,
+ self->client->area.width, self->client->area.height);
+}
+
+void frame_adjust_state(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->need_render = TRUE;
+ framerender_frame(self);
+}
+
+void frame_adjust_focus(gpointer _self, gboolean hilite)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->focused = hilite;
+ self->need_render = TRUE;
+ framerender_frame(self);
+ XFlush(plugin.ob_display);
+}
+
+void frame_adjust_title(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->need_render = TRUE;
+ framerender_frame(self);
+}
+
+void frame_adjust_icon(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->need_render = TRUE;
+ framerender_frame(self);
+}
+
+void frame_grab_client(gpointer _self, GHashTable * map)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* DO NOT map the client window here. we used to do that, but it is bogus.
+ we need to set up the client's dimensions and everything before we
+ send a mapnotify or we create race conditions.
+ */
+
+ /* reparent the client to the frame */
+ XReparentWindow(plugin.ob_display, self->client->window, self->window, 0, 0);
+
+ /*
+ When reparenting the client window, it is usually not mapped yet, since
+ this occurs from a MapRequest. However, in the case where Openbox is
+ starting up, the window is already mapped, so we'll see an unmap event
+ for it.
+ */
+ if (ob_state() == OB_STATE_STARTING)
+ ++self->client->ignore_unmaps;
+
+ /* select the event mask on the client's parent (to receive config/map
+ req's) the ButtonPress is to catch clicks on the client border */
+ XSelectInput(plugin.ob_display, self->window, FRAME_EVENTMASK);
+
+ /* set all the windows for the frame in the window_map */
+ g_hash_table_insert(map, &self->window, self->client);
+ g_hash_table_insert(map, &self->left, self->client);
+ g_hash_table_insert(map, &self->right, self->client);
+
+ g_hash_table_insert(map, &self->top, self->client);
+ g_hash_table_insert(map, &self->bottom, self->client);
+
+ g_hash_table_insert(map, &self->top_left, self->client);
+ g_hash_table_insert(map, &self->top_right, self->client);
+
+ g_hash_table_insert(map, &self->bottom_left, self->client);
+ g_hash_table_insert(map, &self->bottom_right, self->client);
+
+ g_hash_table_insert(map, &self->left_close, self->client);
+ g_hash_table_insert(map, &self->left_iconify, self->client);
+ g_hash_table_insert(map, &self->left_maximize, self->client);
+ g_hash_table_insert(map, &self->left_shade, self->client);
+
+ g_hash_table_insert(map, &self->handle, self->client);
+
+}
+
+void frame_release_client(gpointer _self, GHashTable * map)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ XEvent ev;
+ gboolean reparent = TRUE;
+
+ /* if there was any animation going on, kill it */
+ ob_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+
+ /* check if the app has already reparented its window away */
+ while (XCheckTypedWindowEvent(plugin.ob_display, self->client->window,
+ ReparentNotify, &ev)) {
+ /* This check makes sure we don't catch our own reparent action to
+ our frame window. This doesn't count as the app reparenting itself
+ away of course.
+
+ Reparent events that are generated by us are just discarded here.
+ They are of no consequence to us anyhow.
+ */
+ if (ev.xreparent.parent != self->window) {
+ reparent = FALSE;
+ XPutBackEvent(plugin.ob_display, &ev);
+ break;
+ }
+ }
+
+ if (reparent) {
+ /* according to the ICCCM - if the client doesn't reparent itself,
+ then we will reparent the window to root for them */
+ XReparentWindow(plugin.ob_display, self->client->window, RootWindow(
+ plugin.ob_display, plugin.ob_screen), self->client->area.x,
+ self->client->area.y);
+ }
+
+ /* remove all the windows for the frame from the window_map */
+ g_hash_table_remove(map, &self->window);
+
+ g_hash_table_remove(map, &self->left);
+ g_hash_table_remove(map, &self->right);
+
+ g_hash_table_remove(map, &self->top);
+ g_hash_table_remove(map, &self->bottom);
+
+ g_hash_table_remove(map, &self->top_left);
+ g_hash_table_remove(map, &self->top_right);
+
+ g_hash_table_remove(map, &self->bottom_left);
+ g_hash_table_remove(map, &self->bottom_right);
+
+ g_hash_table_remove(map, &self->left_close);
+ g_hash_table_remove(map, &self->left_iconify);
+ g_hash_table_remove(map, &self->left_maximize);
+ g_hash_table_remove(map, &self->left_shade);
+
+ g_hash_table_remove(map, &self->handle);
+
+ ob_main_loop_timeout_remove_data(plugin.ob_main_loop, flash_timeout, self,
+ TRUE);
+}
+
+/* is there anything present between us and the label? */
+static gboolean is_button_present(ObConceptFrame *_self, const gchar *lc,
+ gint dir)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ for (; *lc != '\0' && lc >= plugin.config_title_layout; lc += dir) {
+ if (*lc == ' ')
+ continue; /* it was invalid */
+ if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
+ return TRUE;
+ if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
+ return TRUE;
+ if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
+ return TRUE;
+ if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
+ return TRUE;
+ if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
+ return TRUE;
+ if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
+ return TRUE;
+ if (*lc == 'L')
+ return FALSE;
+ }
+ return FALSE;
+}
+
+ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
+{
+ /* Here because client can be NULL */
+ ObConceptFrame *self = OBCONCEPTFRAME(_self);
+
+ if (win == self->window)
+ return OB_FRAME_CONTEXT_FRAME;
+
+ if (win == self->bottom)
+ return OB_FRAME_CONTEXT_BOTTOM;
+
+ if (win == self->bottom_left)
+ return OB_FRAME_CONTEXT_BLCORNER;
+
+ if (win == self->bottom_right)
+ return OB_FRAME_CONTEXT_BRCORNER;
+
+ if (win == self->top)
+ return OB_FRAME_CONTEXT_TOP;
+
+ if (win == self->top_left)
+ return OB_FRAME_CONTEXT_TLCORNER;
+
+ if (win == self->top_right)
+ return OB_FRAME_CONTEXT_TRCORNER;
+
+ if (win == self->left_close)
+ return OB_FRAME_CONTEXT_CLOSE;
+ if (win == self->left_iconify)
+ return OB_FRAME_CONTEXT_ICONIFY;
+ if (win == self->left_maximize)
+ return OB_FRAME_CONTEXT_MAXIMIZE;
+ if (win == self->left_shade)
+ return OB_FRAME_CONTEXT_SHADE;
+ if (win == self->handle)
+ return OB_FRAME_CONTEXT_TITLEBAR;
+
+ if (win == self->left)
+ return OB_FRAME_CONTEXT_LEFT;
+ if (win == self->right)
+ return OB_FRAME_CONTEXT_RIGHT;
+
+ return OB_FRAME_CONTEXT_NONE;
+}
+
+void frame_client_gravity(gpointer _self, gint *x, gint *y)
+{
+ ObConceptFrame * self = OBCONCEPTFRAME(_self);
+ /* horizontal */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case SouthWestGravity:
+ case WestGravity:
+ break;
+
+ case NorthGravity:
+ case SouthGravity:
+ case CenterGravity:
+ /* the middle of the client will be the middle of the frame */
+ *x -= (self->size.right - self->size.left) / 2;
+ break;
+
+ case NorthEastGravity:
+ case SouthEastGravity:
+ case EastGravity:
+ /* the right side of the client will be the right side of the frame */
+ *x -= self->size.right + self->size.left - self->client->border_width
+ * 2;
+ break;
+
+ case ForgetGravity:
+ case StaticGravity:
+ /* the client's position won't move */
+ *x -= self->size.left - self->client->border_width;
+ break;
+ }
+
+ /* vertical */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case NorthEastGravity:
+ case NorthGravity:
+ break;
+
+ case CenterGravity:
+ case EastGravity:
+ case WestGravity:
+ /* the middle of the client will be the middle of the frame */
+ *y -= (self->size.bottom - self->size.top) / 2;
+ break;
+
+ case SouthWestGravity:
+ case SouthEastGravity:
+ case SouthGravity:
+ /* the bottom of the client will be the bottom of the frame */
+ *y -= self->size.bottom + self->size.top - self->client->border_width
+ * 2;
+ break;
+
+ case ForgetGravity:
+ case StaticGravity:
+ /* the client's position won't move */
+ *y -= self->size.top - self->client->border_width;
+ break;
+ }
+}
+
+void frame_frame_gravity(gpointer _self, gint *x, gint *y)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* horizontal */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case WestGravity:
+ case SouthWestGravity:
+ break;
+ case NorthGravity:
+ case CenterGravity:
+ case SouthGravity:
+ /* the middle of the client will be the middle of the frame */
+ *x += (self->size.right - self->size.left) / 2;
+ break;
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
+ /* the right side of the client will be the right side of the frame */
+ *x += self->size.right + self->size.left - self->client->border_width
+ * 2;
+ break;
+ case StaticGravity:
+ case ForgetGravity:
+ /* the client's position won't move */
+ *x += self->size.left - self->client->border_width;
+ break;
+ }
+
+ /* vertical */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case NorthGravity:
+ case NorthEastGravity:
+ break;
+ case WestGravity:
+ case CenterGravity:
+ case EastGravity:
+ /* the middle of the client will be the middle of the frame */
+ *y += (self->size.bottom - self->size.top) / 2;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ case SouthEastGravity:
+ /* the bottom of the client will be the bottom of the frame */
+ *y += self->size.bottom + self->size.top - self->client->border_width
+ * 2;
+ break;
+ case StaticGravity:
+ case ForgetGravity:
+ /* the client's position won't move */
+ *y += self->size.top - self->client->border_width;
+ break;
+ }
+}
+
+void frame_rect_to_frame(gpointer _self, Rect *r)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ r->width += self->size.left + self->size.right;
+ r->height += self->size.top + self->size.bottom;
+ frame_client_gravity(self, &r->x, &r->y);
+}
+
+void frame_rect_to_client(gpointer _self, Rect *r)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ r->width -= self->size.left + self->size.right;
+ r->height -= self->size.top + self->size.bottom;
+ frame_frame_gravity(self, &r->x, &r->y);
+}
+
+void flash_done(gpointer data)
+{
+ ObConceptFrame *self = data;
+
+ if (self->focused != self->flash_on)
+ frame_adjust_focus(self, self->focused);
+}
+
+gboolean flash_timeout(gpointer data)
+{
+ ObConceptFrame *self = data;
+ GTimeVal now;
+
+ g_get_current_time(&now);
+ if (now.tv_sec > self->flash_end.tv_sec
+ || (now.tv_sec == self->flash_end.tv_sec && now.tv_usec
+ >= self->flash_end.tv_usec))
+ self->flashing = FALSE;
+
+ if (!self->flashing)
+ return FALSE; /* we are done */
+
+ self->flash_on = !self->flash_on;
+ if (!self->focused) {
+ frame_adjust_focus(self, self->flash_on);
+ self->focused = FALSE;
+ }
+
+ return TRUE; /* go again */
+}
+
+void frame_flash_start(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->flash_on = self->focused;
+
+ if (!self->flashing)
+ ob_main_loop_timeout_add(plugin.ob_main_loop, G_USEC_PER_SEC * 0.6,
+ flash_timeout, self, g_direct_equal, flash_done);
+ g_get_current_time(&self->flash_end);
+ g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
+
+ self->flashing = TRUE;
+}
+
+void frame_flash_stop(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ self->flashing = FALSE;
+}
+
+static gulong frame_animate_iconify_time_left(gpointer _self,
+ const GTimeVal *now)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ glong sec, usec;
+ sec = self->iconify_animation_end.tv_sec - now->tv_sec;
+ usec = self->iconify_animation_end.tv_usec - now->tv_usec;
+ if (usec < 0) {
+ usec += G_USEC_PER_SEC;
+ sec--;
+ }
+ /* no negative values */
+ return MAX(sec * G_USEC_PER_SEC + usec, 0);
+}
+
+gboolean frame_animate_iconify(gpointer p)
+{
+ ObConceptFrame *self = p;
+ gint x, y, w, h;
+ gint iconx, icony, iconw;
+ GTimeVal now;
+ gulong time;
+ gboolean iconifying;
+
+ if (self->client->icon_geometry.width == 0) {
+ /* there is no icon geometry set so just go straight down */
+ Rect *a =
+ screen_physical_area_monitor(screen_find_monitor(&self->area));
+ iconx = self->area.x + self->area.width / 2 + 32;
+ icony = a->y + a->width;
+ iconw = 64;
+ g_free(a);
+ }
+ else {
+ iconx = self->client->icon_geometry.x;
+ icony = self->client->icon_geometry.y;
+ iconw = self->client->icon_geometry.width;
+ }
+
+ iconifying = self->iconify_animation_going > 0;
+
+ /* how far do we have left to go ? */
+ g_get_current_time(&now);
+ time = frame_animate_iconify_time_left(self, &now);
+
+ if (time == 0 || iconifying) {
+ /* start where the frame is supposed to be */
+ x = self->area.x;
+ y = self->area.y;
+ w = self->area.width;
+ h = self->area.height;
+ }
+ else {
+ /* start at the icon */
+ x = iconx;
+ y = icony;
+ w = iconw;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time > 0) {
+ glong dx, dy, dw;
+ glong elapsed;
+
+ dx = self->area.x - iconx;
+ dy = self->area.y - icony;
+ dw = self->area.width - self->bwidth * 2 - iconw;
+ /* if restoring, we move in the opposite direction */
+ if (!iconifying) {
+ dx = -dx;
+ dy = -dy;
+ dw = -dw;
+ }
+
+ elapsed = FRAME_ANIMATE_ICONIFY_TIME - time;
+ x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time == 0)
+ frame_end_iconify_animation(self);
+ else {
+ XMoveResizeWindow(plugin.ob_display, self->window, x, y, w, h);
+ XFlush(plugin.ob_display);
+ }
+
+ return time > 0; /* repeat until we're out of time */
+}
+
+void frame_end_iconify_animation(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ /* see if there is an animation going */
+ if (self->iconify_animation_going == 0)
+ return;
+
+ if (!self->visible)
+ XUnmapWindow(plugin.ob_display, self->window);
+ else {
+ /* Send a ConfigureNotify when the animation is done, this fixes
+ KDE's pager showing the window in the wrong place. since the
+ window is mapped at a different location and is then moved, we
+ need to send the synthetic configurenotify, since apps may have
+ read the position when the client mapped, apparently. */
+ client_reconfigure(self->client, TRUE);
+ }
+
+ /* we're not animating any more ! */
+ self->iconify_animation_going = 0;
+
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+ /* we delay re-rendering until after we're done animating */
+ framerender_frame(self);
+ XFlush(plugin.ob_display);
+}
+
+void frame_begin_iconify_animation(gpointer _self, gboolean iconifying)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ gulong time;
+ gboolean new_anim = FALSE;
+ gboolean set_end = TRUE;
+ GTimeVal now;
+
+ /* if there is no titlebar, just don't animate for now
+ XXX it would be nice tho.. */
+ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ return;
+
+ /* get the current time */
+ g_get_current_time(&now);
+
+ /* get how long until the end */
+ time = FRAME_ANIMATE_ICONIFY_TIME;
+ if (self->iconify_animation_going) {
+ if (!!iconifying != (self->iconify_animation_going > 0)) {
+ /* animation was already going on in the opposite direction */
+ time = time - frame_animate_iconify_time_left(self, &now);
+ }
+ else
+ /* animation was already going in the same direction */
+ set_end = FALSE;
+ }
+ else
+ new_anim = TRUE;
+ self->iconify_animation_going = iconifying ? 1 : -1;
+
+ /* set the ending time */
+ if (set_end) {
+ self->iconify_animation_end.tv_sec = now.tv_sec;
+ self->iconify_animation_end.tv_usec = now.tv_usec;
+ g_time_val_add(&self->iconify_animation_end, time);
+ }
+
+ if (new_anim) {
+ ob_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+ ob_main_loop_timeout_add(plugin.ob_main_loop,
+ FRAME_ANIMATE_ICONIFY_STEP_TIME, frame_animate_iconify, self,
+ g_direct_equal, NULL);
+
+ /* do the first step */
+ frame_animate_iconify(self);
+
+ /* show it during the animation even if it is not "visible" */
+ if (!self->visible)
+ XMapWindow(plugin.ob_display, self->window);
+ }
+}
+
+gboolean frame_iconify_animating(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ return self->iconify_animation_going != 0;
+}
+
+ObFramePlugin plugin = { 0, //gpointer handler;
+ "libdefault.la", //gchar * filename;
+ "Default", //gchar * name;
+ init, //gint (*init) (Display * display, gint screen);
+ 0, // release
+ frame_new, //gpointer (*frame_new) (struct _ObClient *c);
+ frame_free, //void (*frame_free) (gpointer self);
+ frame_show, //void (*frame_show) (gpointer self);
+ frame_hide, //void (*frame_hide) (gpointer self);
+ frame_adjust_theme, //void (*frame_adjust_theme) (gpointer self);
+ frame_adjust_shape, //void (*frame_adjust_shape) (gpointer self);
+ frame_adjust_area, //void (*frame_adjust_area) (gpointer self, gboolean moved, gboolean resized, gboolean fake);
+ frame_adjust_client_area, //void (*frame_adjust_client_area) (gpointer self);
+ frame_adjust_state, //void (*frame_adjust_state) (gpointer self);
+ frame_adjust_focus, //void (*frame_adjust_focus) (gpointer self, gboolean hilite);
+ frame_adjust_title, //void (*frame_adjust_title) (gpointer self);
+ frame_adjust_icon, //void (*frame_adjust_icon) (gpointer self);
+ frame_grab_client, //void (*frame_grab_client) (gpointer self);
+ frame_release_client, //void (*frame_release_client) (gpointer self);
+ frame_context, //ObFrameContext (*frame_context) (struct _ObClient *self, Window win, gint x, gint y);
+ frame_client_gravity, //void (*frame_client_gravity) (gpointer self, gint *x, gint *y);
+ frame_frame_gravity, //void (*frame_frame_gravity) (gpointer self, gint *x, gint *y);
+ frame_rect_to_frame, //void (*frame_rect_to_frame) (gpointer self, Rect *r);
+ frame_rect_to_client, //void (*frame_rect_to_client) (gpointer self, Rect *r);
+ frame_flash_start, //void (*frame_flash_start) (gpointer self);
+ frame_flash_stop, //void (*frame_flash_stop) (gpointer self);
+ frame_begin_iconify_animation, //void (*frame_begin_iconify_animation) (gpointer self, gboolean iconifying);
+ frame_end_iconify_animation, //void (*frame_end_iconify_animation) (gpointer self);
+ frame_iconify_animating, // gboolean (*frame_iconify_animating)(gpointer p);
+ load_theme_config,
+
+ /* This fields are fill by openbox. */
+ 0, //Display * ob_display;
+ 0, //gint ob_screen;
+ 0, //RrInstance *ob_rr_inst;
+ 0, //gboolean config_theme_keepborder;
+ 0, //struct _ObClient *focus_cycle_target;
+ 0, //gchar *config_title_layout;
+ FALSE, //gboolean moveresize_in_progress;
+ 0, //struct _ObMainLoop *ob_main_loop;
+};
+
+ObFramePlugin * get_info()
+{
+ return &plugin;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_plugin.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_CONCEPT2_PLUGIN_H_
+#define FRAME_CONCEPT2_PLUGIN_H_
+
+#include "frame_concept2_config.h"
+
+#include "render/render.h"
+#include "openbox/engine_interface.h"
+
+ObFrameThemeConfig theme_config;
+
+struct _ObConceptFrame
+{
+ // PUBLIC :
+ struct _ObClient *client;
+
+ Window window;
+
+ Strut size;
+ Rect area;
+ gint bwidth; /* border width */
+ guint decorations;
+
+ gboolean visible;
+
+ gboolean max_horz; /* when maxed some decorations are hidden */
+ gboolean max_vert; /* when maxed some decorations are hidden */
+
+ gboolean max_press;
+ gboolean close_press;
+ gboolean desk_press;
+ gboolean shade_press;
+ gboolean iconify_press;
+
+ gboolean max_hover;
+ gboolean close_hover;
+ gboolean desk_hover;
+ gboolean shade_hover;
+ gboolean iconify_hover;
+
+ gint iconify_animation_going;
+
+ /* PRIVATE: */
+ /* You are free to add what you want here */
+
+ ObStyle style;
+
+ guint functions;
+
+ /* These are borders of the frame and its elements */
+
+ Window top;
+ Window bottom;
+ Window left;
+ Window right;
+
+ Window top_left;
+ Window top_right;
+
+ Window bottom_left;
+ Window bottom_right;
+
+ Window background;
+
+ Window left_shade;
+ Window left_close;
+ Window left_iconify;
+ Window left_maximize;
+
+ Window handle;
+
+ Colormap colormap;
+
+ RrAppearance *a_unfocused_title;
+ RrAppearance *a_focused_title;
+ RrAppearance *a_unfocused_label;
+ RrAppearance *a_focused_label;
+ RrAppearance *a_icon;
+ RrAppearance *a_unfocused_handle;
+ RrAppearance *a_focused_handle;
+
+ gint icon_on; /* if the window icon button is on */
+ gint label_on; /* if the window title is on */
+ gint iconify_on; /* if the window iconify button is on */
+ gint desk_on; /* if the window all-desktops button is on */
+ gint shade_on; /* if the window shade button is on */
+ gint max_on; /* if the window maximize button is on */
+ gint close_on; /* if the window close button is on */
+
+ gint width; /* width of the titlebar and handle */
+
+ gint label_width; /* width of the label in the titlebar */
+ gint icon_x; /* x-position of the window icon button */
+ gint label_x; /* x-position of the window title */
+ gint iconify_x; /* x-position of the window iconify button */
+ gint desk_x; /* x-position of the window all-desktops button */
+ gint shade_x; /* x-position of the window shade button */
+ gint max_x; /* x-position of the window maximize button */
+ gint close_x; /* x-position of the window close button */
+
+ gint cbwidth_l; /* client border width */
+ gint cbwidth_t; /* client border width */
+ gint cbwidth_r; /* client border width */
+ gint cbwidth_b; /* client border width */
+ gboolean shaded; /* decorations adjust when shaded */
+
+ /* the leftmost and rightmost elements in the titlebar */
+ ObFrameContext leftmost;
+ ObFrameContext rightmost;
+
+ gboolean focused;
+ gboolean need_render;
+
+ gboolean flashing;
+ gboolean flash_on;
+ GTimeVal flash_end;
+
+ GTimeVal iconify_animation_end;
+
+};
+
+typedef struct _ObConceptFrame ObConceptFrame;
+
+/* Function use for interface */
+gint init(Display *, gint);
+gpointer frame_new(struct _ObClient *c);
+void frame_free(gpointer self);
+void frame_show(gpointer self);
+void frame_hide(gpointer self);
+void frame_adjust_theme(gpointer self);
+void frame_adjust_shape(gpointer self);
+void frame_adjust_area(gpointer self, gboolean moved, gboolean resized,
+ gboolean fake);
+void frame_adjust_client_area(gpointer self);
+void frame_adjust_state(gpointer self);
+void frame_adjust_focus(gpointer self, gboolean hilite);
+void frame_adjust_title(gpointer self);
+void frame_adjust_icon(gpointer self);
+void frame_grab_client(gpointer self, GHashTable *);
+void frame_release_client(gpointer self, GHashTable *);
+
+ObFrameContext frame_context(gpointer, Window, gint, gint);
+void frame_client_gravity(gpointer self, gint *x, gint *y);
+void frame_frame_gravity(gpointer self, gint *x, gint *y);
+void frame_rect_to_frame(gpointer self, Rect *r);
+void frame_rect_to_client(gpointer self, Rect *r);
+void frame_flash_start(gpointer self);
+void frame_flash_stop(gpointer self);
+void frame_begin_iconify_animation(gpointer self, gboolean iconifying);
+void frame_end_iconify_animation(gpointer self);
+gboolean frame_iconify_animating(gpointer _self);
+
+void flash_done(gpointer data);
+gboolean flash_timeout(gpointer data);
+
+void set_theme_statics(gpointer self);
+void free_theme_statics(gpointer self);
+gboolean frame_animate_iconify(gpointer self);
+void frame_adjust_cursors(gpointer self);
+
+/* Global for frame_concept_render.c only */
+extern ObFramePlugin plugin;
+#define OBCONCEPTFRAME(x) ((ObConceptFrame *)(x))
+
+#endif /*FRAME_CONCEPT2_PLUGIN_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_render.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#include "frame_concept2_render.h"
+#include "frame_concept2_plugin.h"
+
+#include "openbox/engine_interface.h"
+#include "openbox/openbox.h"
+#include "openbox/screen.h"
+#include "openbox/client.h"
+
+#include "render/theme.h"
+
+static void framerender_label(ObConceptFrame *self, RrAppearance *a);
+static void framerender_icon(ObConceptFrame *self, RrAppearance *a);
+static void framerender_max(ObConceptFrame *self, RrAppearance *a);
+static void framerender_iconify(ObConceptFrame *self, RrAppearance *a);
+static void framerender_desk(ObConceptFrame *self, RrAppearance *a);
+static void framerender_shade(ObConceptFrame *self, RrAppearance *a);
+static void framerender_close(ObConceptFrame *self, RrAppearance *a);
+
+void framerender_frame(gpointer _self)
+{
+ ObConceptFrame * self = (ObConceptFrame *) _self;
+ if (plugin.frame_iconify_animating(self))
+ return; /* delay redrawing until the animation is done */
+ if (!self->need_render)
+ return;
+ if (!self->visible)
+ return;
+ self->need_render = FALSE;
+
+ gulong border_px, corner_px;
+
+ if (self->focused) {
+ border_px = RrColorPixel(theme_config.focus_border_color);
+ corner_px = RrColorPixel(theme_config.focus_corner_color);
+ }
+ else {
+ border_px = RrColorPixel(theme_config.unfocus_border_color);
+ corner_px = RrColorPixel(theme_config.unfocus_corner_color);
+ }
+
+ XSetWindowBackground(plugin.ob_display, self->left, border_px);
+ XClearWindow(plugin.ob_display, self->left);
+ XSetWindowBackground(plugin.ob_display, self->right, border_px);
+ XClearWindow(plugin.ob_display, self->right);
+
+ XSetWindowBackground(plugin.ob_display, self->top, border_px);
+ XClearWindow(plugin.ob_display, self->top);
+ XSetWindowBackground(plugin.ob_display, self->bottom, border_px);
+ XClearWindow(plugin.ob_display, self->bottom);
+
+ XSetWindowBackground(plugin.ob_display, self->top_left, corner_px);
+ XClearWindow(plugin.ob_display, self->top_left);
+ XSetWindowBackground(plugin.ob_display, self->top_right, corner_px);
+ XClearWindow(plugin.ob_display, self->top_right);
+
+ XSetWindowBackground(plugin.ob_display, self->bottom_left, corner_px);
+ XClearWindow(plugin.ob_display, self->bottom_left);
+ XSetWindowBackground(plugin.ob_display, self->bottom_right, corner_px);
+ XClearWindow(plugin.ob_display, self->bottom_right);
+
+ XSetWindowBackground(plugin.ob_display, self->background, 0);
+ XClearWindow(plugin.ob_display, self->background);
+
+ XSetWindowBackground(plugin.ob_display, self->left_close, 0xff0000);
+ XClearWindow(plugin.ob_display, self->left_close);
+ XSetWindowBackground(plugin.ob_display, self->left_iconify, 0x00ff00);
+ XClearWindow(plugin.ob_display, self->left_iconify);
+ XSetWindowBackground(plugin.ob_display, self->left_maximize, 0x0000ff);
+ XClearWindow(plugin.ob_display, self->left_maximize);
+ XSetWindowBackground(plugin.ob_display, self->left_shade, 0xffff00);
+ XClearWindow(plugin.ob_display, self->left_shade);
+
+ XSetWindowBackground(plugin.ob_display, self->handle, 0x00ffff);
+ XClearWindow(plugin.ob_display, self->handle);
+
+ XFlush(plugin.ob_display);
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_render.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#ifndef FRAME_CONCEPT2_RENDER_H_
+#define FRAME_CONCEPT2_RENDER_H_
+
+#include "frame_concept2_plugin.h"
+
+void framerender_frame(gpointer self);
+
+#endif
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_config.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "config.h"
+#include "plugin.h"
+
+#include "render/render.h"
+#include "render/color.h"
+#include "render/font.h"
+#include "render/mask.h"
+#include "render/icon.h"
+#include "obt/parse.h"
+
+#include <X11/Xlib.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+static XrmDatabase loaddb(const gchar *name, gchar **path);
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value);
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value);
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans);
+static int parse_inline_number(const char *p);
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
+static void set_default_appearance(RrAppearance *a);
+
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font)
+{
+ RrJustify winjust, mtitlejust;
+ gchar *str;
+ ObFrameThemeConfig * theme = &theme_config;
+ gboolean userdef;
+
+ //theme = g_new0(ObFrameTheme, 1);
+
+ theme->inst = inst;
+ theme->name = g_strdup(name ? name : DEFAULT_THEME);
+
+ theme->a_disabled_focused_max = RrAppearanceNew(inst, 1);
+ theme->a_disabled_unfocused_max = RrAppearanceNew(inst, 1);
+ theme->a_hover_focused_max = RrAppearanceNew(inst, 1);
+ theme->a_hover_unfocused_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_focused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_unfocused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_hover_focused_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_hover_unfocused_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_focused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_unfocused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_focused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_focused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_unfocused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_unfocused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_focused_grip = RrAppearanceNew(inst, 0);
+ theme->a_unfocused_grip = RrAppearanceNew(inst, 0);
+ theme->a_focused_title = RrAppearanceNew(inst, 0);
+ theme->a_unfocused_title = RrAppearanceNew(inst, 0);
+ theme->a_focused_label = RrAppearanceNew(inst, 1);
+ theme->a_unfocused_label = RrAppearanceNew(inst, 1);
+ theme->a_icon = RrAppearanceNew(inst, 1);
+ theme->a_focused_handle = RrAppearanceNew(inst, 0);
+ theme->a_unfocused_handle = RrAppearanceNew(inst, 0);
+ theme->a_menu = RrAppearanceNew(inst, 0);
+ theme->a_menu_title = RrAppearanceNew(inst, 0);
+ theme->a_menu_text_title = RrAppearanceNew(inst, 1);
+ theme->a_menu_normal = RrAppearanceNew(inst, 0);
+ theme->a_menu_selected = RrAppearanceNew(inst, 0);
+ theme->a_menu_disabled = RrAppearanceNew(inst, 0);
+ theme->a_menu_disabled_selected = RrAppearanceNew(inst, 0);
+ theme->a_menu_text_normal = RrAppearanceNew(inst, 1);
+ theme->a_menu_text_selected = RrAppearanceNew(inst, 1);
+ theme->a_menu_text_disabled = RrAppearanceNew(inst, 1);
+ theme->a_menu_text_disabled_selected = RrAppearanceNew(inst, 1);
+ theme->a_menu_bullet_normal = RrAppearanceNew(inst, 1);
+ theme->a_menu_bullet_selected = RrAppearanceNew(inst, 1);
+ theme->a_clear = RrAppearanceNew(inst, 0);
+ theme->a_clear_tex = RrAppearanceNew(inst, 1);
+ theme->osd_hilite_bg = RrAppearanceNew(inst, 0);
+ theme->osd_hilite_label = RrAppearanceNew(inst, 1);
+ theme->osd_hilite_fg = RrAppearanceNew(inst, 0);
+ theme->osd_unhilite_fg = RrAppearanceNew(inst, 0);
+
+ /* load the font stuff */
+ if (active_window_font) {
+ theme->win_font_focused = active_window_font;
+ RrFontRef(active_window_font);
+ }
+ else
+ theme->win_font_focused = RrFontOpenDefault(inst);
+
+ if (inactive_window_font) {
+ theme->win_font_unfocused = inactive_window_font;
+ RrFontRef(inactive_window_font);
+ }
+ else
+ theme->win_font_unfocused = RrFontOpenDefault(inst);
+
+ winjust = RR_JUSTIFY_LEFT;
+ if (read_string(db, "window.label.text.justify", &str)) {
+ if (!g_ascii_strcasecmp(str, "right"))
+ winjust = RR_JUSTIFY_RIGHT;
+ else if (!g_ascii_strcasecmp(str, "center"))
+ winjust = RR_JUSTIFY_CENTER;
+ }
+
+ if (menu_title_font) {
+ theme->menu_title_font = menu_title_font;
+ RrFontRef(menu_title_font);
+ }
+ else
+ theme->menu_title_font = RrFontOpenDefault(inst);
+
+ mtitlejust = RR_JUSTIFY_LEFT;
+ if (read_string(db, "menu.title.text.justify", &str)) {
+ if (!g_ascii_strcasecmp(str, "right"))
+ mtitlejust = RR_JUSTIFY_RIGHT;
+ else if (!g_ascii_strcasecmp(str, "center"))
+ mtitlejust = RR_JUSTIFY_CENTER;
+ }
+
+ if (menu_item_font) {
+ theme->menu_font = menu_item_font;
+ RrFontRef(menu_item_font);
+ }
+ else
+ theme->menu_font = RrFontOpenDefault(inst);
+
+ if (osd_font) {
+ theme->osd_font = osd_font;
+ RrFontRef(osd_font);
+ }
+ else
+ theme->osd_font = RrFontOpenDefault(inst);
+
+ /* load direct dimensions */
+ if (!read_int(db, "menu.overlap", &theme->menu_overlap)
+ || theme->menu_overlap < -100 || theme->menu_overlap > 100)
+ theme->menu_overlap = 0;
+ if (!read_int(db, "window.handle.width", &theme->handle_height)
+ || theme->handle_height < 0 || theme->handle_height > 100)
+ theme->handle_height = 6;
+ if (!read_int(db, "padding.width", &theme->paddingx) || theme->paddingx < 0
+ || theme->paddingx > 100)
+ theme->paddingx = 3;
+ if (!read_int(db, "padding.height", &theme->paddingy) || theme->paddingy
+ < 0 || theme->paddingy > 100)
+ theme->paddingy = theme->paddingx;
+ if (!read_int(db, "border.width", &theme->fbwidth) || theme->fbwidth < 0
+ || theme->fbwidth > 100)
+ theme->fbwidth = 1;
+ /* menu border width inherits from the frame border width */
+ if (!read_int(db, "menu.border.width", &theme->mbwidth) || theme->mbwidth
+ < 0 || theme->mbwidth > 100)
+ theme->mbwidth = theme->fbwidth;
+ /* osd border width inherits from the frame border width */
+ if (!read_int(db, "osd.border.width", &theme->obwidth) || theme->obwidth
+ < 0 || theme->obwidth > 100)
+ theme->obwidth = theme->fbwidth;
+ if (!read_int(db, "window.client.padding.width", &theme->cbwidthx)
+ || theme->cbwidthx < 0 || theme->cbwidthx > 100)
+ theme->cbwidthx = theme->paddingx;
+ if (!read_int(db, "window.client.padding.height", &theme->cbwidthy)
+ || theme->cbwidthy < 0 || theme->cbwidthy > 100)
+ theme->cbwidthy = theme->cbwidthx;
+
+ /* load colors */
+ if (!read_color(db, inst, "window.active.border.color",
+ &theme->frame_focused_border_color) && !read_color(db, inst,
+ "border.color", &theme->frame_focused_border_color))
+ theme->frame_focused_border_color = RrColorNew(inst, 0, 0, 0);
+ /* title separator focused color inherits from focused boder color */
+ if (!read_color(db, inst, "window.active.title.separator.color",
+ &theme->title_separator_focused_color))
+ theme->title_separator_focused_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ /* unfocused border color inherits from frame focused border color */
+ if (!read_color(db, inst, "window.inactive.border.color",
+ &theme->frame_unfocused_border_color))
+ theme->frame_unfocused_border_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ /* title separator unfocused color inherits from unfocused boder color */
+ if (!read_color(db, inst, "window.inactive.title.separator.color",
+ &theme->title_separator_unfocused_color))
+ theme->title_separator_unfocused_color = RrColorNew(inst,
+ theme->frame_unfocused_border_color->r,
+ theme->frame_unfocused_border_color->g,
+ theme->frame_unfocused_border_color->b);
+
+ /* menu border color inherits from frame focused border color */
+ if (!read_color(db, inst, "menu.border.color", &theme->menu_border_color))
+ theme->menu_border_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ /* osd border color inherits from frame focused border color */
+ if (!read_color(db, inst, "osd.border.color", &theme->osd_border_color))
+ theme->osd_border_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ if (!read_color(db, inst, "window.active.client.color",
+ &theme->cb_focused_color))
+ theme->cb_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ if (!read_color(db, inst, "window.inactive.client.color",
+ &theme->cb_unfocused_color))
+ theme->cb_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ if (!read_color(db, inst, "window.active.label.text.color",
+ &theme->title_focused_color))
+ theme->title_focused_color = RrColorNew(inst, 0x0, 0x0, 0x0);
+ if (!read_color(db, inst, "osd.label.text.color", &theme->osd_color))
+ theme->osd_color = RrColorNew(inst, theme->title_focused_color->r,
+ theme->title_focused_color->g, theme->title_focused_color->b);
+ if (!read_color(db, inst, "window.inactive.label.text.color",
+ &theme->title_unfocused_color))
+ theme->title_unfocused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ if (!read_color(db, inst, "window.active.button.unpressed.image.color",
+ &theme->titlebut_focused_unpressed_color))
+ theme->titlebut_focused_unpressed_color = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, "window.inactive.button.unpressed.image.color",
+ &theme->titlebut_unfocused_unpressed_color))
+ theme->titlebut_unfocused_unpressed_color = RrColorNew(inst, 0xff,
+ 0xff, 0xff);
+ if (!read_color(db, inst, "window.active.button.pressed.image.color",
+ &theme->titlebut_focused_pressed_color))
+ theme->titlebut_focused_pressed_color = RrColorNew(inst,
+ theme->titlebut_focused_unpressed_color->r,
+ theme->titlebut_focused_unpressed_color->g,
+ theme->titlebut_focused_unpressed_color->b);
+ if (!read_color(db, inst, "window.inactive.button.pressed.image.color",
+ &theme->titlebut_unfocused_pressed_color))
+ theme->titlebut_unfocused_pressed_color = RrColorNew(inst,
+ theme->titlebut_unfocused_unpressed_color->r,
+ theme->titlebut_unfocused_unpressed_color->g,
+ theme->titlebut_unfocused_unpressed_color->b);
+ if (!read_color(db, inst, "window.active.button.disabled.image.color",
+ &theme->titlebut_disabled_focused_color))
+ theme->titlebut_disabled_focused_color = RrColorNew(inst, 0xff, 0xff,
+ 0xff);
+ if (!read_color(db, inst, "window.inactive.button.disabled.image.color",
+ &theme->titlebut_disabled_unfocused_color))
+ theme->titlebut_disabled_unfocused_color = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, "window.active.button.hover.image.color",
+ &theme->titlebut_hover_focused_color))
+ theme->titlebut_hover_focused_color = RrColorNew(inst,
+ theme->titlebut_focused_unpressed_color->r,
+ theme->titlebut_focused_unpressed_color->g,
+ theme->titlebut_focused_unpressed_color->b);
+ if (!read_color(db, inst, "window.inactive.button.hover.image.color",
+ &theme->titlebut_hover_unfocused_color))
+ theme->titlebut_hover_unfocused_color = RrColorNew(inst,
+ theme->titlebut_unfocused_unpressed_color->r,
+ theme->titlebut_unfocused_unpressed_color->g,
+ theme->titlebut_unfocused_unpressed_color->b);
+ if (!read_color(db, inst,
+ "window.active.button.toggled.unpressed.image.color",
+ &theme->titlebut_toggled_focused_unpressed_color) && !read_color(
+ db, inst, "window.active.button.toggled.image.color",
+ &theme->titlebut_toggled_focused_unpressed_color))
+ theme->titlebut_toggled_focused_unpressed_color = RrColorNew(inst,
+ theme->titlebut_focused_pressed_color->r,
+ theme->titlebut_focused_pressed_color->g,
+ theme->titlebut_focused_pressed_color->b);
+ if (!read_color(db, inst,
+ "window.inactive.button.toggled.unpressed.image.color",
+ &theme->titlebut_toggled_unfocused_unpressed_color) && !read_color(
+ db, inst, "window.inactive.button.toggled.image.color",
+ &theme->titlebut_toggled_unfocused_unpressed_color))
+ theme->titlebut_toggled_unfocused_unpressed_color = RrColorNew(inst,
+ theme->titlebut_unfocused_pressed_color->r,
+ theme->titlebut_unfocused_pressed_color->g,
+ theme->titlebut_unfocused_pressed_color->b);
+ if (!read_color(db, inst, "window.active.button.toggled.hover.image.color",
+ &theme->titlebut_toggled_hover_focused_color))
+ theme->titlebut_toggled_hover_focused_color = RrColorNew(inst,
+ theme->titlebut_toggled_focused_unpressed_color->r,
+ theme->titlebut_toggled_focused_unpressed_color->g,
+ theme->titlebut_toggled_focused_unpressed_color->b);
+ if (!read_color(db, inst,
+ "window.inactive.button.toggled.hover.image.color",
+ &theme->titlebut_toggled_hover_unfocused_color))
+ theme->titlebut_toggled_hover_unfocused_color = RrColorNew(inst,
+ theme->titlebut_toggled_unfocused_unpressed_color->r,
+ theme->titlebut_toggled_unfocused_unpressed_color->g,
+ theme->titlebut_toggled_unfocused_unpressed_color->b);
+ if (!read_color(db, inst,
+ "window.active.button.toggled.pressed.image.color",
+ &theme->titlebut_toggled_focused_pressed_color))
+ theme->titlebut_toggled_focused_pressed_color = RrColorNew(inst,
+ theme->titlebut_focused_pressed_color->r,
+ theme->titlebut_focused_pressed_color->g,
+ theme->titlebut_focused_pressed_color->b);
+ if (!read_color(db, inst,
+ "window.inactive.button.toggled.pressed.image.color",
+ &theme->titlebut_toggled_unfocused_pressed_color))
+ theme->titlebut_toggled_unfocused_pressed_color = RrColorNew(inst,
+ theme->titlebut_unfocused_pressed_color->r,
+ theme->titlebut_unfocused_pressed_color->g,
+ theme->titlebut_unfocused_pressed_color->b);
+ if (!read_color(db, inst, "menu.title.text.color", &theme->menu_title_color))
+ theme->menu_title_color = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, "menu.items.text.color", &theme->menu_color))
+ theme->menu_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ if (!read_color(db, inst, "menu.items.disabled.text.color",
+ &theme->menu_disabled_color))
+ theme->menu_disabled_color = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, "menu.items.active.disabled.text.color",
+ &theme->menu_disabled_selected_color))
+ theme->menu_disabled_selected_color = RrColorNew(inst,
+ theme->menu_disabled_color->r, theme->menu_disabled_color->g,
+ theme->menu_disabled_color->b);
+ if (!read_color(db, inst, "menu.items.active.text.color",
+ &theme->menu_selected_color))
+ theme->menu_selected_color = RrColorNew(inst, 0, 0, 0);
+
+ /* load the image masks */
+
+ /* maximize button masks */
+ userdef = TRUE;
+ if (!read_mask(inst, path, theme, "max.xbm", &theme->max_mask)) {
+ guchar data[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
+ theme->max_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ userdef = FALSE;
+ }
+ if (!read_mask(inst, path, theme, "max_toggled.xbm",
+ &theme->max_toggled_mask)) {
+ if (userdef)
+ theme->max_toggled_mask = RrPixmapMaskCopy(theme->max_mask);
+ else {
+ guchar data[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f };
+ theme->max_toggled_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ }
+ if (!read_mask(inst, path, theme, "max_pressed.xbm",
+ &theme->max_pressed_mask))
+ theme->max_pressed_mask = RrPixmapMaskCopy(theme->max_mask);
+ if (!read_mask(inst, path, theme, "max_disabled.xbm",
+ &theme->max_disabled_mask))
+ theme->max_disabled_mask = RrPixmapMaskCopy(theme->max_mask);
+ if (!read_mask(inst, path, theme, "max_hover.xbm", &theme->max_hover_mask))
+ theme->max_hover_mask = RrPixmapMaskCopy(theme->max_mask);
+ if (!read_mask(inst, path, theme, "max_toggled_pressed.xbm",
+ &theme->max_toggled_pressed_mask))
+ theme->max_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->max_toggled_mask);
+ if (!read_mask(inst, path, theme, "max_toggled_hover.xbm",
+ &theme->max_toggled_hover_mask))
+ theme->max_toggled_hover_mask
+ = RrPixmapMaskCopy(theme->max_toggled_mask);
+
+ /* iconify button masks */
+ if (!read_mask(inst, path, theme, "iconify.xbm", &theme->iconify_mask)) {
+ guchar data[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f };
+ theme->iconify_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ if (!read_mask(inst, path, theme, "iconify_pressed.xbm",
+ &theme->iconify_pressed_mask))
+ theme->iconify_pressed_mask = RrPixmapMaskCopy(theme->iconify_mask);
+ if (!read_mask(inst, path, theme, "iconify_disabled.xbm",
+ &theme->iconify_disabled_mask))
+ theme->iconify_disabled_mask = RrPixmapMaskCopy(theme->iconify_mask);
+ if (!read_mask(inst, path, theme, "iconify_hover.xbm",
+ &theme->iconify_hover_mask))
+ theme->iconify_hover_mask = RrPixmapMaskCopy(theme->iconify_mask);
+
+ /* all desktops button masks */
+ userdef = TRUE;
+ if (!read_mask(inst, path, theme, "desk.xbm", &theme->desk_mask)) {
+ guchar data[] = { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 };
+ theme->desk_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ userdef = FALSE;
+ }
+ if (!read_mask(inst, path, theme, "desk_toggled.xbm",
+ &theme->desk_toggled_mask)) {
+ if (userdef)
+ theme->desk_toggled_mask = RrPixmapMaskCopy(theme->desk_mask);
+ else {
+ guchar data[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 };
+ theme->desk_toggled_mask
+ = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ }
+ if (!read_mask(inst, path, theme, "desk_pressed.xbm",
+ &theme->desk_pressed_mask))
+ theme->desk_pressed_mask = RrPixmapMaskCopy(theme->desk_mask);
+ if (!read_mask(inst, path, theme, "desk_disabled.xbm",
+ &theme->desk_disabled_mask))
+ theme->desk_disabled_mask = RrPixmapMaskCopy(theme->desk_mask);
+ if (!read_mask(inst, path, theme, "desk_hover.xbm", &theme->desk_hover_mask))
+ theme->desk_hover_mask = RrPixmapMaskCopy(theme->desk_mask);
+ if (!read_mask(inst, path, theme, "desk_toggled_pressed.xbm",
+ &theme->desk_toggled_pressed_mask))
+ theme->desk_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->desk_toggled_mask);
+ if (!read_mask(inst, path, theme, "desk_toggled_hover.xbm",
+ &theme->desk_toggled_hover_mask))
+ theme->desk_toggled_hover_mask
+ = RrPixmapMaskCopy(theme->desk_toggled_mask);
+
+ /* shade button masks */
+ if (!read_mask(inst, path, theme, "shade.xbm", &theme->shade_mask)) {
+ guchar data[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 };
+ theme->shade_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ if (!read_mask(inst, path, theme, "shade_toggled.xbm",
+ &theme->shade_toggled_mask))
+ theme->shade_toggled_mask = RrPixmapMaskCopy(theme->shade_mask);
+ if (!read_mask(inst, path, theme, "shade_pressed.xbm",
+ &theme->shade_pressed_mask))
+ theme->shade_pressed_mask = RrPixmapMaskCopy(theme->shade_mask);
+ if (!read_mask(inst, path, theme, "shade_disabled.xbm",
+ &theme->shade_disabled_mask))
+ theme->shade_disabled_mask = RrPixmapMaskCopy(theme->shade_mask);
+ if (!read_mask(inst, path, theme, "shade_hover.xbm",
+ &theme->shade_hover_mask))
+ theme->shade_hover_mask = RrPixmapMaskCopy(theme->shade_mask);
+ if (!read_mask(inst, path, theme, "shade_toggled_pressed.xbm",
+ &theme->shade_toggled_pressed_mask))
+ theme->shade_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+ if (!read_mask(inst, path, theme, "shade_toggled_hover.xbm",
+ &theme->shade_toggled_hover_mask))
+ theme->shade_toggled_hover_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+
+ /* close button masks */
+ if (!read_mask(inst, path, theme, "close.xbm", &theme->close_mask)) {
+ guchar data[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 };
+ theme->close_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ if (!read_mask(inst, path, theme, "close_pressed.xbm",
+ &theme->close_pressed_mask))
+ theme->close_pressed_mask = RrPixmapMaskCopy(theme->close_mask);
+ if (!read_mask(inst, path, theme, "close_disabled.xbm",
+ &theme->close_disabled_mask))
+ theme->close_disabled_mask = RrPixmapMaskCopy(theme->close_mask);
+ if (!read_mask(inst, path, theme, "close_hover.xbm",
+ &theme->close_hover_mask))
+ theme->close_hover_mask = RrPixmapMaskCopy(theme->close_mask);
+
+ /* submenu bullet mask */
+ if (!read_mask(inst, path, theme, "bullet.xbm", &theme->menu_bullet_mask)) {
+ guchar data[] = { 0x01, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01 };
+ theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data);
+ }
+
+ /* setup the default window icon */
+ theme->def_win_icon = read_c_image(OB_DEFAULT_ICON_WIDTH,
+ OB_DEFAULT_ICON_HEIGHT, OB_DEFAULT_ICON_pixel_data);
+
+ /* the toggled hover mask = the toggled unpressed mask (i.e. no change) */
+ theme->max_toggled_hover_mask = RrPixmapMaskCopy(theme->max_toggled_mask);
+ theme->desk_toggled_hover_mask = RrPixmapMaskCopy(theme->desk_toggled_mask);
+ theme->shade_toggled_hover_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+ /* the toggled pressed mask = the toggled unpressed mask (i.e. no change)*/
+ theme->max_toggled_pressed_mask = RrPixmapMaskCopy(theme->max_toggled_mask);
+ theme->desk_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->desk_toggled_mask);
+ theme->shade_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+
+ /* read the decoration textures */
+ if (!read_appearance(db, inst, "window.active.title.bg",
+ theme->a_focused_title, FALSE))
+ set_default_appearance(theme->a_focused_title);
+ if (!read_appearance(db, inst, "window.inactive.title.bg",
+ theme->a_unfocused_title, FALSE))
+ set_default_appearance(theme->a_unfocused_title);
+ if (!read_appearance(db, inst, "window.active.label.bg",
+ theme->a_focused_label, TRUE))
+ set_default_appearance(theme->a_focused_label);
+ if (!read_appearance(db, inst, "window.inactive.label.bg",
+ theme->a_unfocused_label, TRUE))
+ set_default_appearance(theme->a_unfocused_label);
+ if (!read_appearance(db, inst, "window.active.handle.bg",
+ theme->a_focused_handle, FALSE))
+ set_default_appearance(theme->a_focused_handle);
+ if (!read_appearance(db, inst, "window.inactive.handle.bg",
+ theme->a_unfocused_handle, FALSE))
+ set_default_appearance(theme->a_unfocused_handle);
+ if (!read_appearance(db, inst, "window.active.grip.bg",
+ theme->a_focused_grip, TRUE))
+ set_default_appearance(theme->a_focused_grip);
+ if (!read_appearance(db, inst, "window.inactive.grip.bg",
+ theme->a_unfocused_grip, TRUE))
+ set_default_appearance(theme->a_unfocused_grip);
+ if (!read_appearance(db, inst, "menu.items.bg", theme->a_menu, FALSE))
+ set_default_appearance(theme->a_menu);
+ if (!read_appearance(db, inst, "menu.title.bg", theme->a_menu_title, TRUE))
+ set_default_appearance(theme->a_menu_title);
+ if (!read_appearance(db, inst, "menu.items.active.bg",
+ theme->a_menu_selected, TRUE))
+ set_default_appearance(theme->a_menu_selected);
+ theme->a_menu_disabled_selected = RrAppearanceCopy(theme->a_menu_selected);
+
+ /* read appearances for non-decorations (on-screen-display) */
+ if (!read_appearance(db, inst, "osd.bg", theme->osd_hilite_bg, FALSE)) {
+ RrAppearanceFree(theme->osd_hilite_bg);
+ theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title);
+ }
+ if (!read_appearance(db, inst, "osd.label.bg", theme->osd_hilite_label,
+ TRUE)) {
+ RrAppearanceFree(theme->osd_hilite_label);
+ theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label);
+ }
+ /* osd_hilite_fg can't be parentrel */
+ if (!read_appearance(db, inst, "osd.hilight.bg", theme->osd_hilite_fg,
+ FALSE)) {
+ RrAppearanceFree(theme->osd_hilite_fg);
+ if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL)
+ theme->osd_hilite_fg = RrAppearanceCopy(theme->a_focused_label);
+ else
+ theme->osd_hilite_fg = RrAppearanceCopy(theme->a_focused_title);
+ }
+ /* osd_unhilite_fg can't be parentrel either */
+ if (!read_appearance(db, inst, "osd.unhilight.bg", theme->osd_unhilite_fg,
+ FALSE)) {
+ RrAppearanceFree(theme->osd_unhilite_fg);
+ if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL)
+ theme->osd_unhilite_fg=RrAppearanceCopy(theme->a_unfocused_label);
+ else
+ theme->osd_unhilite_fg=RrAppearanceCopy(theme->a_unfocused_title);
+ }
+
+ /* read buttons textures */
+ if (!read_appearance(db, inst, "window.active.button.disabled.bg",
+ theme->a_disabled_focused_max, TRUE))
+ set_default_appearance(theme->a_disabled_focused_max);
+ if (!read_appearance(db, inst, "window.inactive.button.disabled.bg",
+ theme->a_disabled_unfocused_max, TRUE))
+ set_default_appearance(theme->a_disabled_unfocused_max);
+ if (!read_appearance(db, inst, "window.active.button.pressed.bg",
+ theme->a_focused_pressed_max, TRUE))
+ set_default_appearance(theme->a_focused_pressed_max);
+ if (!read_appearance(db, inst, "window.inactive.button.pressed.bg",
+ theme->a_unfocused_pressed_max, TRUE))
+ set_default_appearance(theme->a_unfocused_pressed_max);
+ if (!read_appearance(db, inst, "window.active.button.toggled.unpressed.bg",
+ theme->a_toggled_focused_unpressed_max, TRUE) && !read_appearance(
+ db, inst, "window.active.button.toggled.bg",
+ theme->a_toggled_focused_unpressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_focused_unpressed_max);
+ theme->a_toggled_focused_unpressed_max
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ }
+ if (!read_appearance(db, inst,
+ "window.inactive.button.toggled.unpressed.bg",
+ theme->a_toggled_unfocused_unpressed_max, TRUE)
+ && !read_appearance(db, inst, "window.inactive.button.toggled.bg",
+ theme->a_toggled_unfocused_unpressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max);
+ theme->a_toggled_unfocused_unpressed_max
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ }
+ if (!read_appearance(db, inst, "window.active.button.toggled.hover.bg",
+ theme->a_toggled_hover_focused_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_hover_focused_max);
+ theme->a_toggled_hover_focused_max
+ = RrAppearanceCopy(theme->a_toggled_focused_unpressed_max);
+ }
+ if (!read_appearance(db, inst, "window.inactive.button.toggled.hover.bg",
+ theme->a_toggled_hover_unfocused_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_hover_unfocused_max);
+ theme->a_toggled_hover_unfocused_max
+ = RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max);
+ }
+ if (!read_appearance(db, inst, "window.active.button.toggled.pressed.bg",
+ theme->a_toggled_focused_pressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_focused_pressed_max);
+ theme->a_toggled_focused_pressed_max
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ }
+ if (!read_appearance(db, inst, "window.inactive.button.toggled.pressed.bg",
+ theme->a_toggled_unfocused_pressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_unfocused_pressed_max);
+ theme->a_toggled_unfocused_pressed_max
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ }
+ if (!read_appearance(db, inst, "window.active.button.unpressed.bg",
+ theme->a_focused_unpressed_max, TRUE))
+ set_default_appearance(theme->a_focused_unpressed_max);
+ if (!read_appearance(db, inst, "window.inactive.button.unpressed.bg",
+ theme->a_unfocused_unpressed_max, TRUE))
+ set_default_appearance(theme->a_unfocused_unpressed_max);
+ if (!read_appearance(db, inst, "window.active.button.hover.bg",
+ theme->a_hover_focused_max, TRUE)) {
+ RrAppearanceFree(theme->a_hover_focused_max);
+ theme->a_hover_focused_max
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ }
+ if (!read_appearance(db, inst, "window.inactive.button.hover.bg",
+ theme->a_hover_unfocused_max, TRUE)) {
+ RrAppearanceFree(theme->a_hover_unfocused_max);
+ theme->a_hover_unfocused_max
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ }
+
+ theme->a_disabled_focused_close
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_close
+ = RrAppearanceCopy(theme->a_disabled_unfocused_max);
+ theme->a_hover_focused_close = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_close
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_unfocused_unpressed_close
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_close
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_close
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_close
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ theme->a_disabled_focused_desk
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_desk
+ = RrAppearanceCopy(theme->a_disabled_unfocused_max);
+ theme->a_hover_focused_desk = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_desk
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_toggled_hover_focused_desk
+ = RrAppearanceCopy(theme->a_toggled_hover_focused_max);
+ theme->a_toggled_hover_unfocused_desk
+ = RrAppearanceCopy(theme->a_toggled_hover_unfocused_max);
+ theme->a_toggled_focused_unpressed_desk
+ = RrAppearanceCopy(theme->a_toggled_focused_unpressed_max);
+ theme->a_toggled_unfocused_unpressed_desk
+ = RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max);
+ theme->a_toggled_focused_pressed_desk
+ = RrAppearanceCopy(theme->a_toggled_focused_pressed_max);
+ theme->a_toggled_unfocused_pressed_desk
+ = RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max);
+ theme->a_unfocused_unpressed_desk
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_desk
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_desk
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_desk
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ theme->a_disabled_focused_shade
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_shade
+ = RrAppearanceCopy(theme->a_disabled_unfocused_max);
+ theme->a_hover_focused_shade = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_shade
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_toggled_hover_focused_shade
+ = RrAppearanceCopy(theme->a_toggled_hover_focused_max);
+ theme->a_toggled_hover_unfocused_shade
+ = RrAppearanceCopy(theme->a_toggled_hover_unfocused_max);
+ theme->a_toggled_focused_unpressed_shade
+ = RrAppearanceCopy(theme->a_toggled_focused_unpressed_max);
+ theme->a_toggled_unfocused_unpressed_shade
+ = RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max);
+ theme->a_toggled_focused_pressed_shade
+ = RrAppearanceCopy(theme->a_toggled_focused_pressed_max);
+ theme->a_toggled_unfocused_pressed_shade
+ = RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max);
+ theme->a_unfocused_unpressed_shade
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_shade
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_shade
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_shade
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ theme->a_disabled_focused_iconify
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_iconify
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_hover_focused_iconify
+ = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_iconify
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_unfocused_unpressed_iconify
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_iconify
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_iconify
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_iconify
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+
+ theme->a_icon->surface.grad
+ = theme->a_clear->surface.grad
+ = theme->a_clear_tex->surface.grad
+ = theme->a_menu_text_title->surface.grad
+ = theme->a_menu_normal->surface.grad
+ = theme->a_menu_disabled->surface.grad
+ = theme->a_menu_text_normal->surface.grad
+ = theme->a_menu_text_selected->surface.grad
+ = theme->a_menu_text_disabled->surface.grad
+ = theme->a_menu_text_disabled_selected->surface.grad
+ = theme->a_menu_bullet_normal->surface.grad
+ = theme->a_menu_bullet_selected->surface.grad
+ = RR_SURFACE_PARENTREL;
+
+ /* set up the textures */
+ theme->a_focused_label->texture[0].type = RR_TEXTURE_TEXT;
+ theme->a_focused_label->texture[0].data.text.justify = winjust;
+ theme->a_focused_label->texture[0].data.text.font=theme->win_font_focused;
+ theme->a_focused_label->texture[0].data.text.color
+ = theme->title_focused_color;
+
+ if (read_string(db, "window.active.label.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
+ theme->title_focused_shadow_alpha = i;
+ }
+ else {
+ theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->title_focused_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_focused_label->texture[0].data.text.shadow_color
+ = theme->title_focused_shadow_color;
+ theme->a_focused_label->texture[0].data.text.shadow_alpha
+ = theme->title_focused_shadow_alpha;
+
+ theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
+ theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
+ theme->osd_hilite_label->texture[0].data.text.font = theme->osd_font;
+ theme->osd_hilite_label->texture[0].data.text.color = theme->osd_color;
+
+ if (read_string(db, "osd.label.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i;
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
+ theme->title_focused_shadow_alpha = i;
+ theme->osd_shadow_color = RrColorNew(inst, j, j, j);
+ theme->osd_shadow_alpha = i;
+ }
+ else {
+ theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->title_focused_shadow_alpha = 50;
+ theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->osd_shadow_alpha = 50;
+ }
+ }
+ else {
+ /* inherit the font settings from the focused label */
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_x
+ = theme->a_focused_label->texture[0].data.text.shadow_offset_x;
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_y
+ = theme->a_focused_label->texture[0].data.text.shadow_offset_y;
+ if (theme->title_focused_shadow_color)
+ theme->osd_shadow_color = RrColorNew(inst,
+ theme->title_focused_shadow_color->r,
+ theme->title_focused_shadow_color->g,
+ theme->title_focused_shadow_color->b);
+ else
+ theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->osd_shadow_alpha = theme->title_focused_shadow_alpha;
+ }
+
+ theme->osd_hilite_label->texture[0].data.text.shadow_color
+ = theme->osd_shadow_color;
+ theme->osd_hilite_label->texture[0].data.text.shadow_alpha
+ = theme->osd_shadow_alpha;
+
+ theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT;
+ theme->a_unfocused_label->texture[0].data.text.justify = winjust;
+ theme->a_unfocused_label->texture[0].data.text.font
+ = theme->win_font_unfocused;
+ theme->a_unfocused_label->texture[0].data.text.color
+ = theme->title_unfocused_color;
+
+ if (read_string(db, "window.inactive.label.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i;
+ theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->title_unfocused_shadow_color = RrColorNew(inst, j, j, j);
+ theme->title_unfocused_shadow_alpha = i;
+ }
+ else {
+ theme->title_unfocused_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->title_unfocused_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_unfocused_label->texture[0].data.text.shadow_color
+ = theme->title_unfocused_shadow_color;
+ theme->a_unfocused_label->texture[0].data.text.shadow_alpha
+ = theme->title_unfocused_shadow_alpha;
+
+ theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
+ theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
+ theme->a_menu_text_title->texture[0].data.text.font
+ = theme->menu_title_font;
+ theme->a_menu_text_title->texture[0].data.text.color
+ = theme->menu_title_color;
+
+ if (read_string(db, "menu.title.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->menu_title_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_title_shadow_alpha = i;
+ }
+ else {
+ theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_title_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_menu_text_title->texture[0].data.text.shadow_color
+ = theme->menu_title_shadow_color;
+ theme->a_menu_text_title->texture[0].data.text.shadow_alpha
+ = theme->menu_title_shadow_alpha;
+
+ theme->a_menu_text_normal->texture[0].type
+ = theme->a_menu_text_selected->texture[0].type
+ = theme->a_menu_text_disabled->texture[0].type
+ = theme->a_menu_text_disabled_selected->texture[0].type
+ = RR_TEXTURE_TEXT;
+ theme->a_menu_text_normal->texture[0].data.text.justify
+ = theme->a_menu_text_selected->texture[0].data.text.justify
+ = theme->a_menu_text_disabled->texture[0].data.text.justify
+ = theme->a_menu_text_disabled_selected->texture[0].data.text.justify
+ = RR_JUSTIFY_LEFT;
+ theme->a_menu_text_normal->texture[0].data.text.font
+ = theme->a_menu_text_selected->texture[0].data.text.font
+ = theme->a_menu_text_disabled->texture[0].data.text.font
+ = theme->a_menu_text_disabled_selected->texture[0].data.text.font
+ = theme->menu_font;
+ theme->a_menu_text_normal->texture[0].data.text.color = theme->menu_color;
+ theme->a_menu_text_selected->texture[0].data.text.color
+ = theme->menu_selected_color;
+ theme->a_menu_text_disabled->texture[0].data.text.color
+ = theme->menu_disabled_color;
+ theme->a_menu_text_disabled_selected->texture[0].data.text.color
+ = theme->menu_disabled_selected_color;
+
+ if (read_string(db, "menu.items.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_menu_text_normal->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_normal->
+ texture[0].data.text.shadow_offset_y = i;
+ theme->a_menu_text_selected->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_selected->
+ texture[0].data.text.shadow_offset_y = i;
+ theme->a_menu_text_disabled->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_disabled->
+ texture[0].data.text.shadow_offset_y = i;
+ theme->a_menu_text_disabled_selected->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_disabled_selected->
+ texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_text_normal_shadow_alpha = i;
+ theme->menu_text_selected_shadow_alpha = i;
+ theme->menu_text_disabled_shadow_alpha = i;
+ theme->menu_text_disabled_selected_shadow_alpha = i;
+ }
+ else {
+ theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_text_normal_shadow_alpha = 50;
+ theme->menu_text_selected_shadow_alpha = 50;
+ theme->menu_text_disabled_selected_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_menu_text_normal->texture[0].data.text.shadow_color
+ = theme->menu_text_normal_shadow_color;
+ theme->a_menu_text_normal->texture[0].data.text.shadow_alpha
+ = theme->menu_text_normal_shadow_alpha;
+ theme->a_menu_text_selected->texture[0].data.text.shadow_color
+ = theme->menu_text_selected_shadow_color;
+ theme->a_menu_text_selected->texture[0].data.text.shadow_alpha
+ = theme->menu_text_selected_shadow_alpha;
+ theme->a_menu_text_disabled->texture[0].data.text.shadow_color
+ = theme->menu_text_disabled_shadow_color;
+ theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha
+ = theme->menu_text_disabled_shadow_alpha;
+ theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color
+ = theme->menu_text_disabled_shadow_color;
+ theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha
+ = theme->menu_text_disabled_shadow_alpha;
+
+ theme->a_disabled_focused_max->texture[0].type
+ = theme->a_disabled_unfocused_max->texture[0].type
+ = theme->a_hover_focused_max->texture[0].type
+ = theme->a_hover_unfocused_max->texture[0].type
+ = theme->a_toggled_hover_focused_max->texture[0].type
+ = theme->a_toggled_hover_unfocused_max->texture[0].type
+ = theme->a_toggled_focused_unpressed_max->texture[0].type
+ = theme->a_toggled_unfocused_unpressed_max->texture[0].type
+ = theme->a_toggled_focused_pressed_max->texture[0].type
+ = theme->a_toggled_unfocused_pressed_max->texture[0].type
+ = theme->a_focused_unpressed_max->texture[0].type
+ = theme->a_focused_pressed_max->texture[0].type
+ = theme->a_unfocused_unpressed_max->texture[0].type
+ = theme->a_unfocused_pressed_max->texture[0].type
+ = theme->a_disabled_focused_close->texture[0].type
+ = theme->a_disabled_unfocused_close->texture[0].type
+ = theme->a_hover_focused_close->texture[0].type
+ = theme->a_hover_unfocused_close->texture[0].type
+ = theme->a_focused_unpressed_close->texture[0].type
+ = theme->a_focused_pressed_close->texture[0].type
+ = theme->a_unfocused_unpressed_close->texture[0].type
+ = theme->a_unfocused_pressed_close->texture[0].type
+ = theme->a_disabled_focused_desk->texture[0].type
+ = theme->a_disabled_unfocused_desk->texture[0].type
+ = theme->a_hover_focused_desk->texture[0].type
+ = theme->a_hover_unfocused_desk->texture[0].type
+ = theme->a_toggled_hover_focused_desk->texture[0].type
+ = theme->a_toggled_hover_unfocused_desk->texture[0].type
+ = theme->a_toggled_focused_unpressed_desk->texture[0].type
+ = theme->a_toggled_unfocused_unpressed_desk->texture[0].type
+ = theme->a_toggled_focused_pressed_desk->texture[0].type
+ = theme->a_toggled_unfocused_pressed_desk->texture[0].type
+ = theme->a_focused_unpressed_desk->texture[0].type
+ = theme->a_focused_pressed_desk->texture[0].type
+ = theme->a_unfocused_unpressed_desk->texture[0].type
+ = theme->a_unfocused_pressed_desk->texture[0].type
+ = theme->a_disabled_focused_shade->texture[0].type
+ = theme->a_disabled_unfocused_shade->texture[0].type
+ = theme->a_hover_focused_shade->texture[0].type
+ = theme->a_hover_unfocused_shade->texture[0].type
+ = theme->a_toggled_hover_focused_shade->texture[0].type
+ = theme->a_toggled_hover_unfocused_shade->texture[0].type
+ = theme->a_toggled_focused_unpressed_shade->texture[0].type
+ = theme->a_toggled_unfocused_unpressed_shade->texture[0].type
+ = theme->a_toggled_focused_pressed_shade->texture[0].type
+ = theme->a_toggled_unfocused_pressed_shade->texture[0].type
+ = theme->a_focused_unpressed_shade->texture[0].type
+ = theme->a_focused_pressed_shade->texture[0].type
+ = theme->a_unfocused_unpressed_shade->texture[0].type
+ = theme->a_unfocused_pressed_shade->texture[0].type
+ = theme->a_disabled_focused_iconify->texture[0].type
+ = theme->a_disabled_unfocused_iconify->texture[0].type
+ = theme->a_hover_focused_iconify->texture[0].type
+ = theme->a_hover_unfocused_iconify->texture[0].type
+ = theme->a_focused_unpressed_iconify->texture[0].type
+ = theme->a_focused_pressed_iconify->texture[0].type
+ = theme->a_unfocused_unpressed_iconify->texture[0].type
+ = theme->a_unfocused_pressed_iconify->texture[0].type
+ = theme->a_menu_bullet_normal->texture[0].type
+ = theme->a_menu_bullet_selected->texture[0].type
+ = RR_TEXTURE_MASK;
+
+ theme->a_disabled_focused_max->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_max->texture[0].data.mask.mask
+ = theme->max_disabled_mask;
+ theme->a_hover_focused_max->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_max->texture[0].data.mask.mask
+ = theme->max_hover_mask;
+ theme->a_focused_pressed_max->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_max->texture[0].data.mask.mask
+ = theme->max_pressed_mask;
+ theme->a_focused_unpressed_max->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_max->texture[0].data.mask.mask
+ = theme->max_mask;
+ theme->a_toggled_hover_focused_max->texture[0].data.mask.mask
+ = theme->a_toggled_hover_unfocused_max->texture[0].data.mask.mask
+ = theme->max_toggled_hover_mask;
+ theme->a_toggled_focused_unpressed_max->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.mask
+ = theme->max_toggled_mask;
+ theme->a_toggled_focused_pressed_max->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.mask
+ = theme->max_toggled_pressed_mask;
+ theme->a_disabled_focused_close->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_close->texture[0].data.mask.mask
+ = theme->close_disabled_mask;
+ theme->a_hover_focused_close->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_close->texture[0].data.mask.mask
+ = theme->close_hover_mask;
+ theme->a_focused_pressed_close->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_close->texture[0].data.mask.mask
+ = theme->close_pressed_mask;
+ theme->a_focused_unpressed_close->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_close->texture[0].data.mask.mask
+ = theme->close_mask;
+ theme->a_disabled_focused_desk->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_desk->texture[0].data.mask.mask
+ = theme->desk_disabled_mask;
+ theme->a_hover_focused_desk->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_desk->texture[0].data.mask.mask
+ = theme->desk_hover_mask;
+ theme->a_focused_pressed_desk->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_desk->texture[0].data.mask.mask
+ = theme->desk_pressed_mask;
+ theme->a_focused_unpressed_desk->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask
+ = theme->desk_mask;
+ theme->a_toggled_hover_focused_desk->texture[0].data.mask.mask
+ = theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.mask
+ = theme->desk_toggled_hover_mask;
+ theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.mask
+ = theme->desk_toggled_mask;
+ theme->a_toggled_focused_pressed_desk->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.mask
+ = theme->desk_toggled_pressed_mask;
+ theme->a_disabled_focused_shade->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_shade->texture[0].data.mask.mask
+ = theme->shade_disabled_mask;
+ theme->a_hover_focused_shade->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_shade->texture[0].data.mask.mask
+ = theme->shade_hover_mask;
+ theme->a_focused_pressed_shade->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_shade->texture[0].data.mask.mask
+ = theme->shade_pressed_mask;
+ theme->a_focused_unpressed_shade->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask
+ = theme->shade_mask;
+ theme->a_toggled_hover_focused_shade->texture[0].data.mask.mask
+ = theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.mask
+ = theme->shade_toggled_hover_mask;
+ theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.mask
+ = theme->shade_toggled_mask;
+ theme->a_toggled_focused_pressed_shade->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.mask
+ = theme->shade_toggled_pressed_mask;
+ theme->a_disabled_focused_iconify->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask
+ = theme->iconify_disabled_mask;
+ theme->a_hover_focused_iconify->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_iconify->texture[0].data.mask.mask
+ = theme->iconify_hover_mask;
+ theme->a_focused_pressed_iconify->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask
+ = theme->iconify_pressed_mask;
+ theme->a_focused_unpressed_iconify->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask
+ = theme->iconify_mask;
+ theme->a_menu_bullet_normal->texture[0].data.mask.mask
+ = theme->a_menu_bullet_selected->texture[0].data.mask.mask
+ = theme->menu_bullet_mask;
+ theme->a_disabled_focused_max->texture[0].data.mask.color
+ = theme->a_disabled_focused_close->texture[0].data.mask.color
+ = theme->a_disabled_focused_desk->texture[0].data.mask.color
+ = theme->a_disabled_focused_shade->texture[0].data.mask.color
+ = theme->a_disabled_focused_iconify->texture[0].data.mask.color
+ = theme->titlebut_disabled_focused_color;
+ theme->a_disabled_unfocused_max->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_close->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_desk->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_shade->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_iconify->texture[0].data.mask.color
+ = theme->titlebut_disabled_unfocused_color;
+ theme->a_hover_focused_max->texture[0].data.mask.color
+ = theme->a_hover_focused_close->texture[0].data.mask.color
+ = theme->a_hover_focused_desk->texture[0].data.mask.color
+ = theme->a_hover_focused_shade->texture[0].data.mask.color
+ = theme->a_hover_focused_iconify->texture[0].data.mask.color
+ = theme->titlebut_hover_focused_color;
+ theme->a_hover_unfocused_max->texture[0].data.mask.color
+ = theme->a_hover_unfocused_close->texture[0].data.mask.color
+ = theme->a_hover_unfocused_desk->texture[0].data.mask.color
+ = theme->a_hover_unfocused_shade->texture[0].data.mask.color
+ = theme->a_hover_unfocused_iconify->texture[0].data.mask.color
+ = theme->titlebut_hover_unfocused_color;
+ theme->a_toggled_hover_focused_max->texture[0].data.mask.color
+ = theme->a_toggled_hover_focused_desk->texture[0].data.mask.color
+ = theme->a_toggled_hover_focused_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_hover_focused_color;
+ theme->a_toggled_hover_unfocused_max->texture[0].data.mask.color
+ = theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.color
+ = theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_hover_unfocused_color;
+ theme->a_toggled_focused_unpressed_max->texture[0].data.mask.color
+ = theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_focused_unpressed_color;
+ theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_unfocused_unpressed_color;
+ theme->a_toggled_focused_pressed_max->texture[0].data.mask.color
+ = theme->a_toggled_focused_pressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_focused_pressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_focused_pressed_color;
+ theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_unfocused_pressed_color;
+ theme->a_focused_unpressed_max->texture[0].data.mask.color
+ = theme->a_focused_unpressed_close->texture[0].data.mask.color
+ = theme->a_focused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_focused_unpressed_shade->texture[0].data.mask.color
+ = theme->a_focused_unpressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_focused_unpressed_color;
+ theme->a_focused_pressed_max->texture[0].data.mask.color
+ = theme->a_focused_pressed_close->texture[0].data.mask.color
+ = theme->a_focused_pressed_desk->texture[0].data.mask.color
+ = theme->a_focused_pressed_shade->texture[0].data.mask.color
+ = theme->a_focused_pressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_focused_pressed_color;
+ theme->a_unfocused_unpressed_max->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_close->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_shade->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_unfocused_unpressed_color;
+ theme->a_unfocused_pressed_max->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_close->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_desk->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_shade->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_unfocused_pressed_color;
+ theme->a_menu_bullet_normal->texture[0].data.mask.color = theme->menu_color;
+ theme->a_menu_bullet_selected->texture[0].data.mask.color
+ = theme->menu_selected_color;
+
+ /* set the font heights */
+ theme->win_font_height = RrFontHeight(theme->win_font_focused,
+ theme->a_focused_label->texture[0].data.text.shadow_offset_y);
+ theme->win_font_height = MAX(theme->win_font_height, RrFontHeight(
+ theme->win_font_focused,
+ theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
+ theme->menu_title_font_height = RrFontHeight(theme->menu_title_font,
+ theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
+ theme->menu_font_height = RrFontHeight(theme->menu_font,
+ theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
+
+ /* calculate some last extents */
+ {
+ gint ft, fb, fl, fr, ut, ub, ul, ur;
+
+ RrMargins(theme->a_focused_label, &fl, &ft, &fr, &fb);
+ RrMargins(theme->a_unfocused_label, &ul, &ut, &ur, &ub);
+ theme->label_height = theme->win_font_height + MAX(ft + fb, ut + ub);
+ theme->label_height += theme->label_height % 2;
+
+ /* this would be nice I think, since padding.width can now be 0,
+ but it breaks frame.c horribly and I don't feel like fixing that
+ right now, so if anyone complains, here is how to keep text from
+ going over the title's bevel/border with a padding.width of 0 and a
+ bevelless/borderless label
+ RrMargins(theme->a_focused_title, &fl, &ft, &fr, &fb);
+ RrMargins(theme->a_unfocused_title, &ul, &ut, &ur, &ub);
+ theme->title_height = theme->label_height +
+ MAX(MAX(theme->padding * 2, ft + fb),
+ MAX(theme->padding * 2, ut + ub));
+ */
+ theme->title_height = theme->label_height + theme->paddingy * 2;
+
+ RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub);
+ theme->menu_title_label_height = theme->menu_title_font_height+ut+ub;
+ theme->menu_title_height = theme->menu_title_label_height
+ + theme->paddingy * 2;
+ }
+ theme->button_size = theme->label_height - 2;
+ theme->grip_width = 25;
+
+ return 1;
+}
+
+static gchar *create_class_name(const gchar *rname)
+{
+ gchar *rclass = g_strdup(rname);
+ gchar *p = rclass;
+
+ while (TRUE) {
+ *p = toupper(*p);
+ p = strchr(p+1, '.');
+ if (p == NULL)
+ break;
+ ++p;
+ if (*p == '\0')
+ break;
+ }
+ return rclass;
+}
+
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype, *end;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = (gint)strtol(retvalue.addr, &end, 10);
+ if (end != retvalue.addr)
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = retvalue.addr;
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ RrColor *c = RrColorParse(inst, retvalue.addr);
+ if (c != NULL) {
+ *value = c;
+ ret = TRUE;
+ }
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value)
+{
+ gboolean ret = FALSE;
+ gchar *s;
+ gint hx, hy; /* ignored */
+ guint w, h;
+ guchar *b;
+
+ s = g_build_filename(path, maskname, NULL);
+ if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
+ ret = TRUE;
+ *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
+ XFree(b);
+ }
+ g_free(s);
+
+ return ret;
+}
+
+static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
+ RrReliefType *relief, RrBevelType *bevel, gboolean *interlaced,
+ gboolean *border, gboolean allow_trans)
+{
+ gchar *t;
+
+ /* convert to all lowercase */
+ for (t = tex; *t != '\0'; ++t)
+ *t = g_ascii_tolower(*t);
+
+ if (allow_trans && strstr(tex, "parentrelative") != NULL) {
+ *grad = RR_SURFACE_PARENTREL;
+ }
+ else {
+ if (strstr(tex, "gradient") != NULL) {
+ if (strstr(tex, "crossdiagonal") != NULL)
+ *grad = RR_SURFACE_CROSS_DIAGONAL;
+ else if (strstr(tex, "pyramid") != NULL)
+ *grad = RR_SURFACE_PYRAMID;
+ else if (strstr(tex, "mirrorhorizontal") != NULL)
+ *grad = RR_SURFACE_MIRROR_HORIZONTAL;
+ else if (strstr(tex, "horizontal") != NULL)
+ *grad = RR_SURFACE_HORIZONTAL;
+ else if (strstr(tex, "splitvertical") != NULL)
+ *grad = RR_SURFACE_SPLIT_VERTICAL;
+ else if (strstr(tex, "vertical") != NULL)
+ *grad = RR_SURFACE_VERTICAL;
+ else
+ *grad = RR_SURFACE_DIAGONAL;
+ }
+ else {
+ *grad = RR_SURFACE_SOLID;
+ }
+ }
+
+ if (strstr(tex, "sunken") != NULL)
+ *relief = RR_RELIEF_SUNKEN;
+ else if (strstr(tex, "flat") != NULL)
+ *relief = RR_RELIEF_FLAT;
+ else if (strstr(tex, "raised") != NULL)
+ *relief = RR_RELIEF_RAISED;
+ else
+ *relief = (*grad == RR_SURFACE_PARENTREL) ? RR_RELIEF_FLAT
+ : RR_RELIEF_RAISED;
+
+ *border = FALSE;
+ if (*relief == RR_RELIEF_FLAT) {
+ if (strstr(tex, "border") != NULL)
+ *border = TRUE;
+ }
+ else {
+ if (strstr(tex, "bevel2") != NULL)
+ *bevel = RR_BEVEL_2;
+ else
+ *bevel = RR_BEVEL_1;
+ }
+
+ if (strstr(tex, "interlaced") != NULL)
+ *interlaced = TRUE;
+ else
+ *interlaced = FALSE;
+}
+
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
+ gchar *csplitname, *ctosplitname;
+ gchar *rettype;
+ XrmValue retvalue;
+ gint i;
+
+ cname = g_strconcat(rname, ".color", NULL);
+ ctoname = g_strconcat(rname, ".colorTo", NULL);
+ bcname = g_strconcat(rname, ".border.color", NULL);
+ icname = g_strconcat(rname, ".interlace.color", NULL);
+ hname = g_strconcat(rname, ".highlight", NULL);
+ sname = g_strconcat(rname, ".shadow", NULL);
+ csplitname = g_strconcat(rname, ".color.splitTo", NULL);
+ ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ parse_appearance(retvalue.addr, &value->surface.grad,
+ &value->surface.relief, &value->surface.bevel,
+ &value->surface.interlaced, &value->surface.border, allow_trans);
+ if (!read_color(db, inst, cname, &value->surface.primary))
+ value->surface.primary = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, ctoname, &value->surface.secondary))
+ value->surface.secondary = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.border)
+ if (!read_color(db, inst, bcname, &value->surface.border_color))
+ value->surface.border_color = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.interlaced)
+ if (!read_color(db, inst, icname, &value->surface.interlace_color))
+ value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
+ if (read_int(db, hname, &i) && i >= 0)
+ value->surface.bevel_light_adjust = i;
+ if (read_int(db, sname, &i) && i >= 0 && i <= 256)
+ value->surface.bevel_dark_adjust = i;
+
+ if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
+ gint r, g, b;
+
+ if (!read_color(db, inst, csplitname, &value->surface.split_primary)) {
+ r = value->surface.primary->r;
+ r += r >> 2;
+ g = value->surface.primary->g;
+ g += g >> 2;
+ b = value->surface.primary->b;
+ b += b >> 2;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_primary = RrColorNew(inst, r, g, b);
+ }
+
+ if (!read_color(db, inst, ctosplitname,
+ &value->surface.split_secondary)) {
+ r = value->surface.secondary->r;
+ r += r >> 4;
+ g = value->surface.secondary->g;
+ g += g >> 4;
+ b = value->surface.secondary->b;
+ b += b >> 4;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_secondary = RrColorNew(inst, r, g, b);
+ }
+ }
+
+ ret = TRUE;
+ }
+
+ g_free(ctosplitname);
+ g_free(csplitname);
+ g_free(sname);
+ g_free(hname);
+ g_free(icname);
+ g_free(bcname);
+ g_free(ctoname);
+ g_free(cname);
+ g_free(rclass);
+ return ret;
+}
+
+static int parse_inline_number(const char *p)
+{
+ int neg = 1;
+ int res = 0;
+ if (*p == '-') {
+ neg = -1;
+ ++p;
+ }
+ for (; isdigit(*p); ++p)
+ res = res * 10 + *p - '0';
+ res *= neg;
+ return res;
+}
+
+static void set_default_appearance(RrAppearance *a)
+{
+ a->surface.grad = RR_SURFACE_SOLID;
+ a->surface.relief = RR_RELIEF_FLAT;
+ a->surface.bevel = RR_BEVEL_1;
+ a->surface.interlaced = FALSE;
+ a->surface.border = FALSE;
+ a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
+ a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
+}
+
+/* Reads the output from gimp's C-Source file format into valid RGBA data for
+ an RrTextureRGBA. */
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
+{
+ RrPixel32 *im, *p;
+ gint i;
+
+ p = im = g_memdup(data, width * height * sizeof(RrPixel32));
+
+ for (i = 0; i < width * height; ++i) {
+ guchar a = ((*p >> 24) & 0xff);
+ guchar b = ((*p >> 16) & 0xff);
+ guchar g = ((*p >> 8) & 0xff);
+ guchar r = ((*p >> 0) & 0xff);
+
+ *p = ((r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + (b
+ << RrDefaultBlueOffset) + (a << RrDefaultAlphaOffset));
+ p++;
+ }
+
+ return im;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_config.h for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_DEFAULT_CONFIG_H_
+#define FRAME_DEFAULT_CONFIG_H_
+
+#include <X11/Xresource.h>
+#include "render/render.h"
+
+G_BEGIN_DECLS
+
+struct _ObFrameThemeConfig
+{
+ const RrInstance *inst;
+
+ /* style settings - fonts */
+ RrFont *win_font_focused;
+ RrFont *win_font_unfocused;
+ RrFont *menu_title_font;
+ RrFont *menu_font;
+ RrFont *osd_font;
+
+ /* style settings - geometry */
+ gint paddingx;
+ gint paddingy;
+ gint handle_height;
+ gint fbwidth; /*!< frame border width */
+ gint mbwidth; /*!< menu border width */
+ gint obwidth; /*!< osd border width */
+ gint cbwidthx;
+ gint cbwidthy;
+ gint menu_overlap;
+ /* these ones are calculated, not set directly by the theme file */
+ gint win_font_height;
+ gint menu_title_font_height;
+ gint menu_font_height;
+ gint label_height;
+ gint title_height;
+ gint button_size;
+ gint grip_width;
+ gint menu_title_label_height;
+ gint menu_title_height;
+
+ /* style settings - colors */
+ RrColor *menu_border_color;
+ RrColor *osd_border_color;
+ RrColor *frame_focused_border_color;
+ RrColor *frame_unfocused_border_color;
+ RrColor *title_separator_focused_color;
+ RrColor *title_separator_unfocused_color;
+ RrColor *cb_focused_color;
+ RrColor *cb_unfocused_color;
+ RrColor *title_focused_color;
+ RrColor *title_unfocused_color;
+ RrColor *titlebut_disabled_focused_color;
+ RrColor *titlebut_disabled_unfocused_color;
+ RrColor *titlebut_hover_focused_color;
+ RrColor *titlebut_hover_unfocused_color;
+ RrColor *titlebut_toggled_hover_focused_color;
+ RrColor *titlebut_toggled_hover_unfocused_color;
+ RrColor *titlebut_toggled_focused_pressed_color;
+ RrColor *titlebut_toggled_unfocused_pressed_color;
+ RrColor *titlebut_toggled_focused_unpressed_color;
+ RrColor *titlebut_toggled_unfocused_unpressed_color;
+ RrColor *titlebut_focused_pressed_color;
+ RrColor *titlebut_unfocused_pressed_color;
+ RrColor *titlebut_focused_unpressed_color;
+ RrColor *titlebut_unfocused_unpressed_color;
+ RrColor *menu_title_color;
+ RrColor *menu_color;
+ RrColor *menu_selected_color;
+ RrColor *menu_disabled_color;
+ RrColor *menu_disabled_selected_color;
+ RrColor *title_focused_shadow_color;
+ gchar title_focused_shadow_alpha;
+ RrColor *title_unfocused_shadow_color;
+ gchar title_unfocused_shadow_alpha;
+ RrColor *osd_color;
+ RrColor *osd_shadow_color;
+ gchar osd_shadow_alpha;
+ RrColor *menu_title_shadow_color;
+ gchar menu_title_shadow_alpha;
+ RrColor *menu_text_normal_shadow_color;
+ gchar menu_text_normal_shadow_alpha;
+ RrColor *menu_text_selected_shadow_color;
+ gchar menu_text_selected_shadow_alpha;
+ RrColor *menu_text_disabled_shadow_color;
+ gchar menu_text_disabled_shadow_alpha;
+ RrColor *menu_text_disabled_selected_shadow_color;
+ gchar menu_text_disabled_selected_shadow_alpha;
+
+ /* style settings - pics */
+ RrPixel32 *def_win_icon; /* 48x48 RGBA */
+
+ /* style settings - masks */
+ RrPixmapMask *max_mask;
+ RrPixmapMask *max_hover_mask;
+ RrPixmapMask *max_pressed_mask;
+ RrPixmapMask *max_toggled_mask;
+ RrPixmapMask *max_toggled_hover_mask;
+ RrPixmapMask *max_toggled_pressed_mask;
+ RrPixmapMask *max_disabled_mask;
+ RrPixmapMask *iconify_mask;
+ RrPixmapMask *iconify_hover_mask;
+ RrPixmapMask *iconify_pressed_mask;
+ RrPixmapMask *iconify_disabled_mask;
+ RrPixmapMask *desk_mask;
+ RrPixmapMask *desk_hover_mask;
+ RrPixmapMask *desk_pressed_mask;
+ RrPixmapMask *desk_toggled_mask;
+ RrPixmapMask *desk_toggled_hover_mask;
+ RrPixmapMask *desk_toggled_pressed_mask;
+ RrPixmapMask *desk_disabled_mask;
+ RrPixmapMask *shade_mask;
+ RrPixmapMask *shade_hover_mask;
+ RrPixmapMask *shade_pressed_mask;
+ RrPixmapMask *shade_toggled_mask;
+ RrPixmapMask *shade_toggled_hover_mask;
+ RrPixmapMask *shade_toggled_pressed_mask;
+ RrPixmapMask *shade_disabled_mask;
+ RrPixmapMask *close_mask;
+ RrPixmapMask *close_hover_mask;
+ RrPixmapMask *close_disabled_mask;
+ RrPixmapMask *close_pressed_mask;
+
+ RrPixmapMask *menu_bullet_mask; /* submenu pointer */
+#if 0
+ RrPixmapMask *menu_toggle_mask; /* menu boolean */
+#endif
+
+ /* global appearances */
+ RrAppearance *a_disabled_focused_max;
+ RrAppearance *a_disabled_unfocused_max;
+ RrAppearance *a_hover_focused_max;
+ RrAppearance *a_hover_unfocused_max;
+ RrAppearance *a_focused_unpressed_max;
+ RrAppearance *a_focused_pressed_max;
+ RrAppearance *a_unfocused_unpressed_max;
+ RrAppearance *a_unfocused_pressed_max;
+ RrAppearance *a_toggled_hover_focused_max;
+ RrAppearance *a_toggled_hover_unfocused_max;
+ RrAppearance *a_toggled_focused_unpressed_max;
+ RrAppearance *a_toggled_focused_pressed_max;
+ RrAppearance *a_toggled_unfocused_unpressed_max;
+ RrAppearance *a_toggled_unfocused_pressed_max;
+ RrAppearance *a_disabled_focused_close;
+ RrAppearance *a_disabled_unfocused_close;
+ RrAppearance *a_hover_focused_close;
+ RrAppearance *a_hover_unfocused_close;
+ RrAppearance *a_focused_unpressed_close;
+ RrAppearance *a_focused_pressed_close;
+ RrAppearance *a_unfocused_unpressed_close;
+ RrAppearance *a_unfocused_pressed_close;
+ RrAppearance *a_disabled_focused_desk;
+ RrAppearance *a_disabled_unfocused_desk;
+ RrAppearance *a_hover_focused_desk;
+ RrAppearance *a_hover_unfocused_desk;
+ RrAppearance *a_focused_unpressed_desk;
+ RrAppearance *a_focused_pressed_desk;
+ RrAppearance *a_unfocused_unpressed_desk;
+ RrAppearance *a_unfocused_pressed_desk;
+ RrAppearance *a_toggled_hover_focused_desk;
+ RrAppearance *a_toggled_hover_unfocused_desk;
+ RrAppearance *a_toggled_focused_unpressed_desk;
+ RrAppearance *a_toggled_focused_pressed_desk;
+ RrAppearance *a_toggled_unfocused_unpressed_desk;
+ RrAppearance *a_toggled_unfocused_pressed_desk;
+ RrAppearance *a_disabled_focused_shade;
+ RrAppearance *a_disabled_unfocused_shade;
+ RrAppearance *a_hover_focused_shade;
+ RrAppearance *a_hover_unfocused_shade;
+ RrAppearance *a_focused_unpressed_shade;
+ RrAppearance *a_focused_pressed_shade;
+ RrAppearance *a_unfocused_unpressed_shade;
+ RrAppearance *a_unfocused_pressed_shade;
+ RrAppearance *a_toggled_hover_focused_shade;
+ RrAppearance *a_toggled_hover_unfocused_shade;
+ RrAppearance *a_toggled_focused_unpressed_shade;
+ RrAppearance *a_toggled_focused_pressed_shade;
+ RrAppearance *a_toggled_unfocused_unpressed_shade;
+ RrAppearance *a_toggled_unfocused_pressed_shade;
+ RrAppearance *a_disabled_focused_iconify;
+ RrAppearance *a_disabled_unfocused_iconify;
+ RrAppearance *a_hover_focused_iconify;
+ RrAppearance *a_hover_unfocused_iconify;
+ RrAppearance *a_focused_unpressed_iconify;
+ RrAppearance *a_focused_pressed_iconify;
+ RrAppearance *a_unfocused_unpressed_iconify;
+ RrAppearance *a_unfocused_pressed_iconify;
+ RrAppearance *a_focused_grip;
+ RrAppearance *a_unfocused_grip;
+ RrAppearance *a_focused_title;
+ RrAppearance *a_unfocused_title;
+ RrAppearance *a_focused_label;
+ RrAppearance *a_unfocused_label;
+ /* always parentrelative, so no focused/unfocused */
+ RrAppearance *a_icon;
+ RrAppearance *a_focused_handle;
+ RrAppearance *a_unfocused_handle;
+ RrAppearance *a_menu_text_title;
+ RrAppearance *a_menu_title;
+ RrAppearance *a_menu;
+ RrAppearance *a_menu_normal;
+ RrAppearance *a_menu_selected;
+ RrAppearance *a_menu_disabled;
+ RrAppearance *a_menu_disabled_selected;
+ RrAppearance *a_menu_text_normal;
+ RrAppearance *a_menu_text_disabled;
+ RrAppearance *a_menu_text_disabled_selected;
+ RrAppearance *a_menu_text_selected;
+ RrAppearance *a_menu_bullet_normal;
+ RrAppearance *a_menu_bullet_selected;
+ RrAppearance *a_clear; /* clear with no texture */
+ RrAppearance *a_clear_tex; /* clear with a texture */
+
+ RrAppearance *osd_hilite_bg; /* can never be parent relative */
+ RrAppearance *osd_hilite_fg; /* can never be parent relative */
+ RrAppearance *osd_hilite_label; /* can be parent relative */
+ RrAppearance *osd_unhilite_fg; /* can never be parent relative */
+
+ gchar *name;
+};
+
+typedef struct _ObFrameThemeConfig ObFrameThemeConfig;
+
+/*! The font values are all optional. If a NULL is used for any of them, then
+ the default font will be used. */
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font);
+
+G_END_DECLS
+
+#endif /*FRAME_DEFAULT_CONFIG_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_plugin.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "openbox/client.h"
+#include "openbox/openbox.h"
+#include "obt/prop.h"
+#include "openbox/grab.h"
+#include "openbox/config.h"
+#include "obt/mainloop.h"
+#include "openbox/focus_cycle.h"
+#include "openbox/focus_cycle_indicator.h"
+#include "openbox/moveresize.h"
+#include "openbox/screen.h"
+#include "render/theme.h"
+
+#include "plugin.h"
+#include "render.h"
+
+typedef enum
+{
+ OB_FLAG_MAX = 1 << 0,
+ OB_FLAG_CLOSE = 1 << 1,
+ OB_FLAG_DESK = 1 << 2,
+ OB_FLAG_SHADE = 1 << 3,
+ OB_FLAG_ICONIFY = 1 << 4
+} ObFrameFlags;
+
+#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
+ ButtonPressMask | ButtonReleaseMask | \
+ SubstructureRedirectMask | FocusChangeMask)
+#define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
+ ButtonMotionMask | PointerMotionMask | \
+ EnterWindowMask | LeaveWindowMask)
+
+#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
+#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
+
+#define FRAME_HANDLE_Y(f) (f->size.top + f->client_area.height + f->cbwidth_b)
+
+Window createWindow(Window parent, Visual *visual, gulong mask,
+ XSetWindowAttributes *attrib)
+{
+ return XCreateWindow(plugin.ob_display, parent, 0, 0, 1, 1, 0, (visual ? 32
+ : RrDepth(plugin.ob_rr_inst)), InputOutput, (visual ? visual
+ : RrVisual(plugin.ob_rr_inst)), mask, attrib);
+
+}
+
+Visual *check_32bit_client(ObClient *c)
+{
+ XWindowAttributes wattrib;
+ Status ret;
+
+ /* we're already running at 32 bit depth, yay. we don't need to use their
+ visual */
+ if (RrDepth(plugin.ob_rr_inst) == 32)
+ return NULL;
+
+ ret = XGetWindowAttributes(plugin.ob_display, c->window, &wattrib);
+ g_assert(ret != BadDrawable);
+ g_assert(ret != BadWindow);
+
+ if (wattrib.depth == 32)
+ return wattrib.visual;
+ return NULL;
+}
+
+/* Not used */
+gint init(Display * display, gint screen)
+{
+ plugin.ob_display = display;
+ plugin.ob_screen = screen;
+}
+
+gpointer frame_new(struct _ObClient * client)
+{
+ XSetWindowAttributes attrib;
+ gulong mask;
+ ObDefaultFrame *self;
+ Visual *visual;
+
+ self = g_new0(ObDefaultFrame, 1);
+ self->client = client;
+
+ visual = check_32bit_client(client);
+
+ /* create the non-visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ /* create a colormap with the visual */
+ OBDEFAULTFRAME(self)->colormap = attrib.colormap = XCreateColormap(
+ plugin.ob_display, RootWindow(plugin.ob_display,
+ plugin.ob_screen), visual, AllocNone);
+ attrib.background_pixel = BlackPixel(plugin.ob_display,
+ plugin.ob_screen);
+ attrib.border_pixel = BlackPixel(plugin.ob_display, plugin.ob_screen);
+ }
+ self->window = createWindow(
+ RootWindow(plugin.ob_display, plugin.ob_screen), visual, mask,
+ &attrib);
+
+ /* create the visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ attrib.colormap = RrColormap(plugin.ob_rr_inst);
+ }
+
+ self->backback = createWindow(self->window, NULL, mask, &attrib);
+ self->backfront = createWindow(self->backback, NULL, mask, &attrib);
+
+ mask |= CWEventMask;
+ attrib.event_mask = ELEMENT_EVENTMASK;
+ self->innerleft = createWindow(self->window, NULL, mask, &attrib);
+ self->innertop = createWindow(self->window, NULL, mask, &attrib);
+ self->innerright = createWindow(self->window, NULL, mask, &attrib);
+ self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
+
+ self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib);
+ self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib);
+ self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib);
+ self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib);
+
+ self->title = createWindow(self->window, NULL, mask, &attrib);
+ self->titleleft = createWindow(self->window, NULL, mask, &attrib);
+ self->titletop = createWindow(self->window, NULL, mask, &attrib);
+ self->titletopleft = createWindow(self->window, NULL, mask, &attrib);
+ self->titletopright = createWindow(self->window, NULL, mask, &attrib);
+ self->titleright = createWindow(self->window, NULL, mask, &attrib);
+ self->titlebottom = createWindow(self->window, NULL, mask, &attrib);
+
+ self->topresize = createWindow(self->title, NULL, mask, &attrib);
+ self->tltresize = createWindow(self->title, NULL, mask, &attrib);
+ self->tllresize = createWindow(self->title, NULL, mask, &attrib);
+ self->trtresize = createWindow(self->title, NULL, mask, &attrib);
+ self->trrresize = createWindow(self->title, NULL, mask, &attrib);
+
+ self->left = createWindow(self->window, NULL, mask, &attrib);
+ self->right = createWindow(self->window, NULL, mask, &attrib);
+
+ self->label = createWindow(self->title, NULL, mask, &attrib);
+ self->max = createWindow(self->title, NULL, mask, &attrib);
+ self->close = createWindow(self->title, NULL, mask, &attrib);
+ self->desk = createWindow(self->title, NULL, mask, &attrib);
+ self->shade = createWindow(self->title, NULL, mask, &attrib);
+ self->icon = createWindow(self->title, NULL, mask, &attrib);
+ self->iconify = createWindow(self->title, NULL, mask, &attrib);
+
+ self->handle = createWindow(self->window, NULL, mask, &attrib);
+ self->lgrip = createWindow(self->handle, NULL, mask, &attrib);
+ self->rgrip = createWindow(self->handle, NULL, mask, &attrib);
+
+ self->handleleft = createWindow(self->handle, NULL, mask, &attrib);
+ self->handleright = createWindow(self->handle, NULL, mask, &attrib);
+
+ self->handletop = createWindow(self->window, NULL, mask, &attrib);
+ self->handlebottom = createWindow(self->window, NULL, mask, &attrib);
+ self->lgripleft = createWindow(self->window, NULL, mask, &attrib);
+ self->lgriptop = createWindow(self->window, NULL, mask, &attrib);
+ self->lgripbottom = createWindow(self->window, NULL, mask, &attrib);
+ self->rgripright = createWindow(self->window, NULL, mask, &attrib);
+ self->rgriptop = createWindow(self->window, NULL, mask, &attrib);
+ self->rgripbottom = createWindow(self->window, NULL, mask, &attrib);
+
+ self->focused = FALSE;
+
+ /* the other stuff is shown based on decor settings */
+ XMapWindow(plugin.ob_display, self->label);
+ XMapWindow(plugin.ob_display, self->backback);
+ XMapWindow(plugin.ob_display, self->backfront);
+
+ self->hover_flag = OB_BUTTON_NONE;
+ self->press_flag = OB_BUTTON_NONE;
+
+ set_theme_statics(self);
+
+ return self;
+}
+
+void set_theme_statics(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* set colors/appearance/sizes for stuff that doesn't change */
+ XResizeWindow(plugin.ob_display, self->max, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->iconify, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->icon, theme_config.button_size + 2,
+ theme_config.button_size + 2);
+ XResizeWindow(plugin.ob_display, self->close, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->desk, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->shade, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->tltresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+ XResizeWindow(plugin.ob_display, self->trtresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+ XResizeWindow(plugin.ob_display, self->tllresize,
+ theme_config.paddingx + 1, theme_config.title_height);
+ XResizeWindow(plugin.ob_display, self->trrresize,
+ theme_config.paddingx + 1, theme_config.title_height);
+
+ /* set up the dynamic appearances */
+ self->a_unfocused_title = RrAppearanceCopy(theme_config.a_unfocused_title);
+ self->a_focused_title = RrAppearanceCopy(theme_config.a_focused_title);
+ self->a_unfocused_label = RrAppearanceCopy(theme_config.a_unfocused_label);
+ self->a_focused_label = RrAppearanceCopy(theme_config.a_focused_label);
+ self->a_unfocused_handle
+ = RrAppearanceCopy(theme_config.a_unfocused_handle);
+ self->a_focused_handle = RrAppearanceCopy(theme_config.a_focused_handle);
+ self->a_icon = RrAppearanceCopy(theme_config.a_icon);
+}
+
+void free_theme_statics(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ RrAppearanceFree(self->a_unfocused_title);
+ RrAppearanceFree(self->a_focused_title);
+ RrAppearanceFree(self->a_unfocused_label);
+ RrAppearanceFree(self->a_focused_label);
+ RrAppearanceFree(self->a_unfocused_handle);
+ RrAppearanceFree(self->a_focused_handle);
+ RrAppearanceFree(self->a_icon);
+}
+
+void frame_free(gpointer self)
+{
+ free_theme_statics(OBDEFAULTFRAME(self));
+ XDestroyWindow(plugin.ob_display, OBDEFAULTFRAME(self)->window);
+ if (OBDEFAULTFRAME(self)->colormap)
+ XFreeColormap(plugin.ob_display, OBDEFAULTFRAME(self)->colormap);
+ g_free(self);
+}
+
+void frame_show(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if (!self->visible) {
+ self->visible = TRUE;
+ frame_update_skin(self);
+ /* Grab the server to make sure that the frame window is mapped before
+ the client gets its MapNotify, i.e. to make sure the client is
+ _visible_ when it gets MapNotify. */
+ grab_server(TRUE);
+ XMapWindow(plugin.ob_display, self->client->window);
+ XMapWindow(plugin.ob_display, self->window);
+ grab_server(FALSE);
+ }
+}
+
+gint frame_hide(gpointer self)
+{
+ if (OBDEFAULTFRAME(self)->visible) {
+ OBDEFAULTFRAME(self)->visible = FALSE;
+ if (!frame_iconify_animating(self))
+ XUnmapWindow(plugin.ob_display, OBDEFAULTFRAME(self)->window);
+ /* we unmap the client itself so that we can get MapRequest
+ events, and because the ICCCM tells us to! */
+ XUnmapWindow(plugin.ob_display, OBDEFAULTFRAME(self)->client->window);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+void frame_adjust_theme(gpointer self)
+{
+ free_theme_statics(self);
+ set_theme_statics(self);
+}
+
+void frame_adjust_shape(gpointer _self)
+{
+#ifdef SHAPE
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ gint num;
+ XRectangle xrect[2];
+
+ if (!self->client->shaped)
+ {
+ /* clear the shape on the frame window */
+ XShapeCombineMask(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ None, ShapeSet);
+ }
+ else
+ {
+ /* make the frame's shape match the clients */
+ XShapeCombineShape(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ self->client->window,
+ ShapeBounding, ShapeSet);
+
+ num = 0;
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
+ {
+ xrect[0].x = 0;
+ xrect[0].y = 0;
+ xrect[0].width = self->area.width;
+ xrect[0].height = self->size.top;
+ ++num;
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE &&
+ theme_config.handle_height> 0)
+ {
+ xrect[1].x = 0;
+ xrect[1].y = FRAME_HANDLE_Y(self);
+ xrect[1].width = self->area.width;
+ xrect[1].height = theme_config.handle_height +
+ self->bwidth * 2;
+ ++num;
+ }
+
+ XShapeCombineRectangles(plugin.ob_display, self->window,
+ ShapeBounding, 0, 0, xrect, num,
+ ShapeUnion, Unsorted);
+ }
+#endif
+}
+
+void frame_grab(gpointer _self, GHashTable * window_map)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* DO NOT map the client window here. we used to do that, but it is bogus.
+ we need to set up the client's dimensions and everything before we
+ send a mapnotify or we create race conditions.
+ */
+
+ /* reparent the client to the frame */
+ XReparentWindow(plugin.ob_display, self->client->window, self->window, 0, 0);
+
+ /*
+ When reparenting the client window, it is usually not mapped yet, since
+ this occurs from a MapRequest. However, in the case where Openbox is
+ starting up, the window is already mapped, so we'll see an unmap event
+ for it.
+ */
+ if (ob_state() == OB_STATE_STARTING)
+ ++self->client->ignore_unmaps;
+
+ /* select the event mask on the client's parent (to receive config/map
+ req's) the ButtonPress is to catch clicks on the client border */
+ XSelectInput(plugin.ob_display, self->window, FRAME_EVENTMASK);
+
+ /* set all the windows for the frame in the window_map */
+ g_hash_table_insert(window_map, &self->window, self->client);
+ g_hash_table_insert(window_map, &self->backback, self->client);
+ g_hash_table_insert(window_map, &self->backfront, self->client);
+ g_hash_table_insert(window_map, &self->innerleft, self->client);
+ g_hash_table_insert(window_map, &self->innertop, self->client);
+ g_hash_table_insert(window_map, &self->innerright, self->client);
+ g_hash_table_insert(window_map, &self->innerbottom, self->client);
+ g_hash_table_insert(window_map, &self->title, self->client);
+ g_hash_table_insert(window_map, &self->label, self->client);
+ g_hash_table_insert(window_map, &self->max, self->client);
+ g_hash_table_insert(window_map, &self->close, self->client);
+ g_hash_table_insert(window_map, &self->desk, self->client);
+ g_hash_table_insert(window_map, &self->shade, self->client);
+ g_hash_table_insert(window_map, &self->icon, self->client);
+ g_hash_table_insert(window_map, &self->iconify, self->client);
+ g_hash_table_insert(window_map, &self->handle, self->client);
+ g_hash_table_insert(window_map, &self->lgrip, self->client);
+ g_hash_table_insert(window_map, &self->rgrip, self->client);
+ g_hash_table_insert(window_map, &self->topresize, self->client);
+ g_hash_table_insert(window_map, &self->tltresize, self->client);
+ g_hash_table_insert(window_map, &self->tllresize, self->client);
+ g_hash_table_insert(window_map, &self->trtresize, self->client);
+ g_hash_table_insert(window_map, &self->trrresize, self->client);
+ g_hash_table_insert(window_map, &self->left, self->client);
+ g_hash_table_insert(window_map, &self->right, self->client);
+ g_hash_table_insert(window_map, &self->titleleft, self->client);
+ g_hash_table_insert(window_map, &self->titletop, self->client);
+ g_hash_table_insert(window_map, &self->titletopleft, self->client);
+ g_hash_table_insert(window_map, &self->titletopright, self->client);
+ g_hash_table_insert(window_map, &self->titleright, self->client);
+ g_hash_table_insert(window_map, &self->titlebottom, self->client);
+ g_hash_table_insert(window_map, &self->handleleft, self->client);
+ g_hash_table_insert(window_map, &self->handletop, self->client);
+ g_hash_table_insert(window_map, &self->handleright, self->client);
+ g_hash_table_insert(window_map, &self->handlebottom, self->client);
+ g_hash_table_insert(window_map, &self->lgripleft, self->client);
+ g_hash_table_insert(window_map, &self->lgriptop, self->client);
+ g_hash_table_insert(window_map, &self->lgripbottom, self->client);
+ g_hash_table_insert(window_map, &self->rgripright, self->client);
+ g_hash_table_insert(window_map, &self->rgriptop, self->client);
+ g_hash_table_insert(window_map, &self->rgripbottom, self->client);
+}
+
+void frame_ungrab(gpointer _self, GHashTable * window_map)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ XEvent ev;
+ gboolean reparent = TRUE;
+
+ /* if there was any animation going on, kill it */
+ obt_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+
+ /* check if the app has already reparented its window away */
+ while (XCheckTypedWindowEvent(plugin.ob_display, self->client->window,
+ ReparentNotify, &ev)) {
+ /* This check makes sure we don't catch our own reparent action to
+ our frame window. This doesn't count as the app reparenting itself
+ away of course.
+
+ Reparent events that are generated by us are just discarded here.
+ They are of no consequence to us anyhow.
+ */
+ if (ev.xreparent.parent != self->window) {
+ reparent = FALSE;
+ XPutBackEvent(plugin.ob_display, &ev);
+ break;
+ }
+ }
+
+ if (reparent) {
+ /* according to the ICCCM - if the client doesn't reparent itself,
+ then we will reparent the window to root for them */
+ XReparentWindow(plugin.ob_display, self->client->window, RootWindow(
+ plugin.ob_display, plugin.ob_screen), self->client_area.x,
+ self->client_area.y);
+ }
+
+ /* remove all the windows for the frame from the window_map */
+ g_hash_table_remove(window_map, &self->window);
+ g_hash_table_remove(window_map, &self->backback);
+ g_hash_table_remove(window_map, &self->backfront);
+ g_hash_table_remove(window_map, &self->innerleft);
+ g_hash_table_remove(window_map, &self->innertop);
+ g_hash_table_remove(window_map, &self->innerright);
+ g_hash_table_remove(window_map, &self->innerbottom);
+ g_hash_table_remove(window_map, &self->title);
+ g_hash_table_remove(window_map, &self->label);
+ g_hash_table_remove(window_map, &self->max);
+ g_hash_table_remove(window_map, &self->close);
+ g_hash_table_remove(window_map, &self->desk);
+ g_hash_table_remove(window_map, &self->shade);
+ g_hash_table_remove(window_map, &self->icon);
+ g_hash_table_remove(window_map, &self->iconify);
+ g_hash_table_remove(window_map, &self->handle);
+ g_hash_table_remove(window_map, &self->lgrip);
+ g_hash_table_remove(window_map, &self->rgrip);
+ g_hash_table_remove(window_map, &self->topresize);
+ g_hash_table_remove(window_map, &self->tltresize);
+ g_hash_table_remove(window_map, &self->tllresize);
+ g_hash_table_remove(window_map, &self->trtresize);
+ g_hash_table_remove(window_map, &self->trrresize);
+ g_hash_table_remove(window_map, &self->left);
+ g_hash_table_remove(window_map, &self->right);
+ g_hash_table_remove(window_map, &self->titleleft);
+ g_hash_table_remove(window_map, &self->titletop);
+ g_hash_table_remove(window_map, &self->titletopleft);
+ g_hash_table_remove(window_map, &self->titletopright);
+ g_hash_table_remove(window_map, &self->titleright);
+ g_hash_table_remove(window_map, &self->titlebottom);
+ g_hash_table_remove(window_map, &self->handleleft);
+ g_hash_table_remove(window_map, &self->handletop);
+ g_hash_table_remove(window_map, &self->handleright);
+ g_hash_table_remove(window_map, &self->handlebottom);
+ g_hash_table_remove(window_map, &self->lgripleft);
+ g_hash_table_remove(window_map, &self->lgriptop);
+ g_hash_table_remove(window_map, &self->lgripbottom);
+ g_hash_table_remove(window_map, &self->rgripright);
+ g_hash_table_remove(window_map, &self->rgriptop);
+ g_hash_table_remove(window_map, &self->rgripbottom);
+
+ obt_main_loop_timeout_remove_data(plugin.ob_main_loop, flash_timeout, self,
+ TRUE);
+}
+
+ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
+{
+ ObDefaultFrame * self = OBDEFAULTFRAME(_self);
+
+ /* 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 += theme_config.grip_width + self->bwidth;
+ /* titletopright is way to the right edge */
+ else if (win == self->titletopright)
+ fx += self->area.width - (theme_config.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 + theme_config.paddingy + 1
+ + theme_config.button_size) {
+ if (fx < (self->bwidth + theme_config.paddingx + 1
+ + theme_config.button_size)) {
+ if (self->leftmost != OB_FRAME_CONTEXT_NONE)
+ return self->leftmost;
+ }
+ else if (fx >= (self->area.width - (self->bwidth
+ + theme_config.paddingx + 1 + theme_config.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_set_is_visible(gpointer self, gboolean b)
+{
+ OBDEFAULTFRAME(self)->visible = b;
+}
+
+void frame_set_is_focus(gpointer self, gboolean b)
+{
+ OBDEFAULTFRAME(self)->focused = b;
+}
+
+void frame_set_is_max_vert(gpointer self, gboolean b)
+{
+ OBDEFAULTFRAME(self)->max_vert = b;
+}
+
+void frame_set_is_max_horz(gpointer self, gboolean b)
+{
+ OBDEFAULTFRAME(self)->max_horz = b;
+}
+
+void frame_set_is_shaded(gpointer self, gboolean b)
+{
+ OBDEFAULTFRAME(self)->shaded = b;
+}
+
+void frame_unfocus(gpointer self)
+{
+ OBDEFAULTFRAME(self)->focused = FALSE;
+}
+
+void frame_flash_start(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->flash_on = self->focused;
+
+ if (!self->flashing)
+ obt_main_loop_timeout_add(plugin.ob_main_loop, G_USEC_PER_SEC * 0.6,
+ flash_timeout, self, g_direct_equal, flash_done);
+ g_get_current_time(&self->flash_end);
+ g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
+
+ self->flashing = TRUE;
+}
+
+void frame_flash_stop(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->flashing = FALSE;
+}
+
+void frame_begin_iconify_animation(gpointer _self, gboolean iconifying)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ gulong time;
+ gboolean new_anim = FALSE;
+ gboolean set_end = TRUE;
+ GTimeVal now;
+
+ /* if there is no titlebar, just don't animate for now
+ XXX it would be nice tho.. */
+ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ return;
+
+ /* get the current time */
+ g_get_current_time(&now);
+
+ /* get how long until the end */
+ time = FRAME_ANIMATE_ICONIFY_TIME;
+ if (self->iconify_animation_going) {
+ if (!!iconifying != (self->iconify_animation_going > 0)) {
+ /* animation was already going on in the opposite direction */
+ time = time - frame_animate_iconify_time_left(_self, &now);
+ }
+ else
+ /* animation was already going in the same direction */
+ set_end = FALSE;
+ }
+ else
+ new_anim = TRUE;
+ self->iconify_animation_going = iconifying ? 1 : -1;
+
+ /* set the ending time */
+ if (set_end) {
+ self->iconify_animation_end.tv_sec = now.tv_sec;
+ self->iconify_animation_end.tv_usec = now.tv_usec;
+ g_time_val_add(&self->iconify_animation_end, time);
+ }
+
+ if (new_anim) {
+ obt_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+ obt_main_loop_timeout_add(plugin.ob_main_loop,
+ FRAME_ANIMATE_ICONIFY_STEP_TIME, frame_animate_iconify, self,
+ g_direct_equal, NULL);
+
+ /* do the first step */
+ frame_animate_iconify(self);
+
+ /* show it during the animation even if it is not "visible" */
+ if (!self->visible)
+ XMapWindow(plugin.ob_display, self->window);
+ }
+}
+
+void frame_end_iconify_animation(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* see if there is an animation going */
+ if (self->iconify_animation_going == 0)
+ return;
+
+ if (!self->visible)
+ XUnmapWindow(plugin.ob_display, self->window);
+ else {
+ /* Send a ConfigureNotify when the animation is done, this fixes
+ KDE's pager showing the window in the wrong place. since the
+ window is mapped at a different location and is then moved, we
+ need to send the synthetic configurenotify, since apps may have
+ read the position when the client mapped, apparently. */
+ client_reconfigure(self->client, TRUE);
+ }
+
+ /* we're not animating any more ! */
+ self->iconify_animation_going = 0;
+
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+ /* we delay re-rendering until after we're done animating */
+ frame_update_skin(self);
+ XFlush(plugin.ob_display);
+}
+
+gboolean frame_iconify_animating(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ return self->iconify_animation_going != 0;
+}
+
+void frame_set_decorations(gpointer self, ObFrameDecorations d)
+{
+ OBDEFAULTFRAME(self)->decorations = d;
+}
+
+Rect frame_get_window_area(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->area;
+}
+void frame_set_client_area(gpointer self, Rect r)
+{
+ OBDEFAULTFRAME(self)->client_area = r;
+}
+
+void frame_update_layout(gpointer _self, gboolean is_resize, gboolean is_fake)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ Strut oldsize;
+
+ oldsize = self->size;
+ self->area = self->client_area;
+
+ /* do this before changing the frame's status like max_horz max_vert */
+ frame_adjust_cursors(self);
+
+ if (self->decorations & OB_FRAME_DECOR_BORDER
+ || (plugin.config_theme_keepborder)) {
+ self->bwidth = theme_config.fbwidth;
+ }
+ else {
+ self->bwidth = 0;
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_BORDER) {
+ self->cbwidth_l = theme_config.cbwidthx;
+ self->cbwidth_r = theme_config.cbwidthx;
+ self->cbwidth_t = theme_config.cbwidthy;
+ self->cbwidth_b = theme_config.cbwidthy;
+ }
+ else {
+ self->cbwidth_l = 0;
+ self->cbwidth_t = 0;
+ self->cbwidth_r = 0;
+ self->cbwidth_b = 0;
+ }
+
+ if (self->max_horz) {
+ self->cbwidth_l = 0;
+ self->cbwidth_r = 0;
+ self->width = self->client_area.width;
+ if (self->max_vert)
+ self->cbwidth_b = 0;
+ }
+ else {
+ self->width = self->client_area.width + self->cbwidth_l
+ + self->cbwidth_r;
+ }
+
+ /* some elements are sized based of the width, so don't let them have
+ negative values */
+ self->width = MAX(self->width, (theme_config.grip_width + self->bwidth) * 2
+ + 1);
+
+ STRUT_SET(self->size, self->cbwidth_l
+ + (!self->max_horz ? self->bwidth : 0), self->cbwidth_t
+ + self->bwidth, self->cbwidth_r + (!self->max_horz ? self->bwidth
+ : 0), self->cbwidth_b
+ + (!self->max_horz || !self->max_vert ? self->bwidth : 0));
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
+ self->size.top += theme_config.title_height + self->bwidth;
+ if (self->decorations & OB_FRAME_DECOR_HANDLE && theme_config.handle_height
+ > 0) {
+ self->size.bottom += theme_config.handle_height + self->bwidth;
+ }
+
+ /* position/size and map/unmap all the windows */
+ if (!is_fake) {
+ gint innercornerheight = theme_config.grip_width - self->size.bottom;
+
+ if (self->cbwidth_l) {
+ XMoveResizeWindow(plugin.ob_display, self->innerleft,
+ self->size.left - self->cbwidth_l, self->size.top,
+ self->cbwidth_l, self->client_area.height);
+
+ XMapWindow(plugin.ob_display, self->innerleft);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerleft);
+
+ if (self->cbwidth_l && innercornerheight > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->innerbll, 0,
+ self->client_area.height - (theme_config.grip_width
+ - self->size.bottom), self->cbwidth_l,
+ theme_config.grip_width - self->size.bottom);
+
+ XMapWindow(plugin.ob_display, self->innerbll);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerbll);
+
+ if (self->cbwidth_r) {
+ XMoveResizeWindow(plugin.ob_display, self->innerright,
+ self->size.left + self->client_area.width, self->size.top,
+ self->cbwidth_r, self->client_area.height);
+
+ XMapWindow(plugin.ob_display, self->innerright);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerright);
+
+ if (self->cbwidth_r && innercornerheight > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->innerbrr, 0,
+ self->client_area.height - (theme_config.grip_width
+ - self->size.bottom), self->cbwidth_r,
+ theme_config.grip_width - self->size.bottom);
+
+ XMapWindow(plugin.ob_display, self->innerbrr);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerbrr);
+
+ if (self->cbwidth_t) {
+ XMoveResizeWindow(plugin.ob_display, self->innertop,
+ self->size.left - self->cbwidth_l, self->size.top
+ - self->cbwidth_t, self->client_area.width
+ + self->cbwidth_l + self->cbwidth_r,
+ self->cbwidth_t);
+
+ XMapWindow(plugin.ob_display, self->innertop);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innertop);
+
+ if (self->cbwidth_b) {
+ XMoveResizeWindow(plugin.ob_display, self->innerbottom,
+ self->size.left - self->cbwidth_l, self->size.top
+ + self->client_area.height, self->client_area.width
+ + self->cbwidth_l + self->cbwidth_r,
+ self->cbwidth_b);
+
+ XMoveResizeWindow(plugin.ob_display, self->innerblb, 0, 0,
+ theme_config.grip_width + self->bwidth, self->cbwidth_b);
+ XMoveResizeWindow(plugin.ob_display, self->innerbrb,
+ self->client_area.width + self->cbwidth_l + self->cbwidth_r
+ - (theme_config.grip_width + self->bwidth), 0,
+ theme_config.grip_width + self->bwidth, self->cbwidth_b);
+
+ XMapWindow(plugin.ob_display, self->innerbottom);
+ XMapWindow(plugin.ob_display, self->innerblb);
+ XMapWindow(plugin.ob_display, self->innerbrb);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->innerbottom);
+ XUnmapWindow(plugin.ob_display, self->innerblb);
+ XUnmapWindow(plugin.ob_display, self->innerbrb);
+ }
+
+ if (self->bwidth) {
+ gint titlesides;
+
+ /* height of titleleft and titleright */
+ titlesides = (!self->max_horz ? theme_config.grip_width : 0);
+
+ XMoveResizeWindow(plugin.ob_display, self->titletop,
+ theme_config.grip_width + self->bwidth, 0,
+ /* width + bwidth*2 - bwidth*2 - grips*2 */
+ self->width - theme_config.grip_width * 2, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->titletopleft, 0, 0,
+ theme_config.grip_width + self->bwidth, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->titletopright,
+ self->client_area.width + self->size.left
+ + self->size.right - theme_config.grip_width
+ - self->bwidth, 0, theme_config.grip_width
+ + self->bwidth, self->bwidth);
+
+ if (titlesides > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->titleleft, 0,
+ self->bwidth, self->bwidth, titlesides);
+ XMoveResizeWindow(plugin.ob_display, self->titleright,
+ self->client_area.width + self->size.left
+ + self->size.right - self->bwidth,
+ self->bwidth, self->bwidth, titlesides);
+
+ XMapWindow(plugin.ob_display, self->titleleft);
+ XMapWindow(plugin.ob_display, self->titleright);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->titleleft);
+ XUnmapWindow(plugin.ob_display, self->titleright);
+ }
+
+ XMapWindow(plugin.ob_display, self->titletop);
+ XMapWindow(plugin.ob_display, self->titletopleft);
+ XMapWindow(plugin.ob_display, self->titletopright);
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
+ XMoveResizeWindow(plugin.ob_display, self->titlebottom,
+ (self->max_horz ? 0 : self->bwidth),
+ theme_config.title_height + self->bwidth, self->width,
+ self->bwidth);
+
+ XMapWindow(plugin.ob_display, self->titlebottom);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->titlebottom);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->titlebottom);
+
+ XUnmapWindow(plugin.ob_display, self->titletop);
+ XUnmapWindow(plugin.ob_display, self->titletopleft);
+ XUnmapWindow(plugin.ob_display, self->titletopright);
+ XUnmapWindow(plugin.ob_display, self->titleleft);
+ XUnmapWindow(plugin.ob_display, self->titleright);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
+ XMoveResizeWindow(plugin.ob_display, self->title,
+ (self->max_horz ? 0 : self->bwidth), self->bwidth,
+ self->width, theme_config.title_height);
+
+ XMapWindow(plugin.ob_display, self->title);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ XMoveResizeWindow(plugin.ob_display, self->topresize,
+ theme_config.grip_width, 0, self->width
+ - theme_config.grip_width *2,
+ theme_config.paddingy + 1);
+
+ XMoveWindow(plugin.ob_display, self->tltresize, 0, 0);
+ XMoveWindow(plugin.ob_display, self->tllresize, 0, 0);
+ XMoveWindow(plugin.ob_display, self->trtresize, self->width
+ - theme_config.grip_width, 0);
+ XMoveWindow(plugin.ob_display, self->trrresize, self->width
+ - theme_config.paddingx - 1, 0);
+
+ XMapWindow(plugin.ob_display, self->topresize);
+ XMapWindow(plugin.ob_display, self->tltresize);
+ XMapWindow(plugin.ob_display, self->tllresize);
+ XMapWindow(plugin.ob_display, self->trtresize);
+ XMapWindow(plugin.ob_display, self->trrresize);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->topresize);
+ XUnmapWindow(plugin.ob_display, self->tltresize);
+ XUnmapWindow(plugin.ob_display, self->tllresize);
+ XUnmapWindow(plugin.ob_display, self->trtresize);
+ XUnmapWindow(plugin.ob_display, self->trrresize);
+ }
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->title);
+ }
+
+ if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ /* layout the title bar elements */
+ layout_title(self);
+
+ if (!is_fake) {
+ gint sidebwidth = self->max_horz ? 0 : self->bwidth;
+
+ if (self->bwidth && self->size.bottom) {
+ XMoveResizeWindow(plugin.ob_display, self->handlebottom,
+ theme_config.grip_width + self->bwidth + sidebwidth,
+ self->size.top + self->client_area.height
+ + self->size.bottom - self->bwidth, self->width
+ - (theme_config.grip_width + sidebwidth) * 2,
+ self->bwidth);
+
+ if (sidebwidth) {
+ XMoveResizeWindow(plugin.ob_display, self->lgripleft, 0,
+ self->size.top + self->client_area.height
+ + self->size.bottom
+ - (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom - self->cbwidth_b),
+ self->bwidth,
+ (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom - self->cbwidth_b));
+ XMoveResizeWindow(plugin.ob_display, self->rgripright,
+ self->size.left + self->client_area.width
+ + self->size.right - self->bwidth,
+ self->size.top + self->client_area.height
+ + self->size.bottom
+ - (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom - self->cbwidth_b),
+ self->bwidth,
+ (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom - self->cbwidth_b));
+
+ XMapWindow(plugin.ob_display, self->lgripleft);
+ XMapWindow(plugin.ob_display, self->rgripright);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->lgripleft);
+ XUnmapWindow(plugin.ob_display, self->rgripright);
+ }
+
+ XMoveResizeWindow(plugin.ob_display, self->lgripbottom, sidebwidth,
+ self->size.top + self->client_area.height
+ + self->size.bottom - self->bwidth,
+ theme_config.grip_width + self->bwidth, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->rgripbottom,
+ self->size.left + self->client_area.width
+ + self->size.right - self->bwidth - sidebwidth
+ - theme_config.grip_width, self->size.top
+ + self->client_area.height + self->size.bottom
+ - self->bwidth, theme_config.grip_width
+ + self->bwidth, self->bwidth);
+
+ XMapWindow(plugin.ob_display, self->handlebottom);
+ XMapWindow(plugin.ob_display, self->lgripbottom);
+ XMapWindow(plugin.ob_display, self->rgripbottom);
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE
+ && theme_config.handle_height > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->handletop,
+ theme_config.grip_width + self->bwidth + sidebwidth,
+ FRAME_HANDLE_Y(self), self->width - (theme_config.grip_width
+ + sidebwidth) * 2, self->bwidth);
+ XMapWindow(plugin.ob_display, self->handletop);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ XMoveResizeWindow(plugin.ob_display, self->handleleft,
+ theme_config.grip_width, 0, self->bwidth,
+ theme_config.handle_height);
+ XMoveResizeWindow(plugin.ob_display, self->handleright,
+ self->width - theme_config.grip_width
+ - self->bwidth, 0, self->bwidth,
+ theme_config.handle_height);
+
+ XMoveResizeWindow(plugin.ob_display, self->lgriptop,
+ sidebwidth,
+ FRAME_HANDLE_Y(self), theme_config.grip_width
+ + self->bwidth, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->rgriptop,
+ self->size.left + self->client_area.width
+ + self->size.right - self->bwidth
+ - sidebwidth - theme_config.grip_width,
+ FRAME_HANDLE_Y(self), theme_config.grip_width
+ + self->bwidth, self->bwidth);
+
+ XMapWindow(plugin.ob_display, self->handleleft);
+ XMapWindow(plugin.ob_display, self->handleright);
+ XMapWindow(plugin.ob_display, self->lgriptop);
+ XMapWindow(plugin.ob_display, self->rgriptop);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->handleleft);
+ XUnmapWindow(plugin.ob_display, self->handleright);
+ XUnmapWindow(plugin.ob_display, self->lgriptop);
+ XUnmapWindow(plugin.ob_display, self->rgriptop);
+ }
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->handleleft);
+ XUnmapWindow(plugin.ob_display, self->handleright);
+ XUnmapWindow(plugin.ob_display, self->lgriptop);
+ XUnmapWindow(plugin.ob_display, self->rgriptop);
+
+ XUnmapWindow(plugin.ob_display, self->handletop);
+ }
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->handleleft);
+ XUnmapWindow(plugin.ob_display, self->handleright);
+ XUnmapWindow(plugin.ob_display, self->lgriptop);
+ XUnmapWindow(plugin.ob_display, self->rgriptop);
+
+ XUnmapWindow(plugin.ob_display, self->handletop);
+
+ XUnmapWindow(plugin.ob_display, self->handlebottom);
+ XUnmapWindow(plugin.ob_display, self->lgripleft);
+ XUnmapWindow(plugin.ob_display, self->rgripright);
+ XUnmapWindow(plugin.ob_display, self->lgripbottom);
+ XUnmapWindow(plugin.ob_display, self->rgripbottom);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE
+ && theme_config.handle_height > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->handle, sidebwidth,
+ FRAME_HANDLE_Y(self) + self->bwidth, self->width,
+ theme_config.handle_height);
+ XMapWindow(plugin.ob_display, self->handle);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ XMoveResizeWindow(plugin.ob_display, self->lgrip, 0, 0,
+ theme_config.grip_width, theme_config.handle_height);
+ XMoveResizeWindow(plugin.ob_display, self->rgrip, self->width
+ - theme_config.grip_width, 0, theme_config.grip_width,
+ theme_config.handle_height);
+
+ XMapWindow(plugin.ob_display, self->lgrip);
+ XMapWindow(plugin.ob_display, self->rgrip);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->lgrip);
+ XUnmapWindow(plugin.ob_display, self->rgrip);
+ }
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->lgrip);
+ XUnmapWindow(plugin.ob_display, self->rgrip);
+
+ XUnmapWindow(plugin.ob_display, self->handle);
+ }
+
+ if (self->bwidth && !self->max_horz && (self->client_area.height
+ + self->size.top + self->size.bottom) > theme_config.grip_width
+ * 2) {
+ XMoveResizeWindow(plugin.ob_display, self->left, 0, self->bwidth
+ + theme_config.grip_width, self->bwidth,
+ self->client_area.height + self->size.top
+ + self->size.bottom - theme_config.grip_width * 2);
+
+ XMapWindow(plugin.ob_display, self->left);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->left);
+
+ if (self->bwidth && !self->max_horz && (self->client_area.height
+ + self->size.top + self->size.bottom) > theme_config.grip_width
+ * 2) {
+ XMoveResizeWindow(plugin.ob_display, self->right,
+ self->client_area.width + self->cbwidth_l + self->cbwidth_r
+ + self->bwidth, self->bwidth
+ + theme_config.grip_width, self->bwidth,
+ self->client_area.height + self->size.top
+ + self->size.bottom - theme_config.grip_width * 2);
+
+ XMapWindow(plugin.ob_display, self->right);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->right);
+
+ XMoveResizeWindow(plugin.ob_display, self->backback, self->size.left,
+ self->size.top, self->client_area.width,
+ self->client_area.height);
+ }
+
+ /* shading can change without being moved or resized */
+ RECT_SET_SIZE(self->area, self->client_area.width + self->size.left
+ + self->size.right, (self->shaded ? theme_config.title_height
+ + self->bwidth * 2 : self->client_area.height + self->size.top
+ + self->size.bottom));
+
+ if ((is_resize) && !is_fake) {
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->area.x = self->client_area.x;
+ self->area.y = self->client_area.y;
+ frame_client_gravity(OBDEFAULTFRAME(_self)->client, &self->area.x, &self->area.y);
+ }
+
+ if (!is_fake) {
+ if (!frame_iconify_animating(self))
+ /* move and resize the top level frame.
+ shading can change without being moved or resized.
+
+ but don't do this during an iconify animation. it will be
+ reflected afterwards.
+ */
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+
+ /* when the client has StaticGravity, it likes to move around.
+ also this correctly positions the client when it maps.
+ this also needs to be run when the frame's decorations sizes change!
+ */
+ if (!is_resize)
+ XMoveResizeWindow(plugin.ob_display, self->client->window,
+ self->size.left, self->size.top, self->client_area.width,
+ self->client_area.height);
+
+ if (is_resize) {
+ self->need_render = TRUE;
+ frame_update_skin(self);
+ frame_adjust_shape(self);
+ }
+
+ if (!STRUT_EQUAL(self->size, oldsize)) {
+ gulong vals[4];
+ vals[0] = self->size.left;
+ vals[1] = self->size.right;
+ vals[2] = self->size.top;
+ vals[3] = self->size.bottom;
+ OBT_PROP_SETA32(self->client->window, NET_FRAME_EXTENTS, CARDINAL,
+ vals, 4);
+ OBT_PROP_SETA32(self->client->window, KDE_NET_WM_FRAME_STRUT,
+ CARDINAL, vals, 4);
+ }
+
+ /* if this occurs while we are focus cycling, the indicator needs to
+ match the changes */
+ if (plugin.focus_cycle_target == self->client)
+ focus_cycle_draw_indicator(self->client);
+ }
+ if (is_resize && (self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ XResizeWindow(plugin.ob_display, self->label, self->label_width,
+ theme_config.label_height);
+}
+
+void frame_set_hover_flag(gpointer self, ObFrameButton button)
+{
+ if (OBDEFAULTFRAME(self)->hover_flag != button) {
+ OBDEFAULTFRAME(self)->hover_flag = button;
+ frame_update_skin(self);
+ }
+}
+
+void frame_set_press_flag(gpointer self, ObFrameButton button)
+{
+ if (OBDEFAULTFRAME(self)->press_flag != button) {
+ OBDEFAULTFRAME(self)->press_flag = button;
+ frame_update_skin(self);
+ }
+}
+
+Window frame_get_window(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->window;
+}
+
+Strut frame_get_size(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->size;
+}
+
+gint frame_get_decorations(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->decorations;
+}
+
+gboolean frame_is_visible(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->visible;
+}
+
+gboolean frame_is_max_horz(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->max_horz;
+}
+
+gboolean frame_is_max_vert(gpointer self)
+{
+ return OBDEFAULTFRAME(self)->max_vert;
+}
+
+gulong frame_animate_iconify_time_left(gpointer _self, const GTimeVal *now)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ glong sec, usec;
+ sec = self->iconify_animation_end.tv_sec - now->tv_sec;
+ usec = self->iconify_animation_end.tv_usec - now->tv_usec;
+ if (usec < 0) {
+ usec += G_USEC_PER_SEC;
+ sec--;
+ }
+ /* no negative values */
+ return MAX(sec * G_USEC_PER_SEC + usec, 0);
+}
+
+gboolean frame_animate_iconify(gpointer p)
+{
+ ObDefaultFrame *self = p;
+ gint x, y, w, h;
+ gint iconx, icony, iconw;
+ GTimeVal now;
+ gulong time;
+ gboolean iconifying;
+
+ if (self->client->icon_geometry.width == 0) {
+ /* there is no icon geometry set so just go straight down */
+ Rect *a =
+ screen_physical_area_monitor(screen_find_monitor(&self->area));
+ iconx = self->area.x + self->area.width / 2 + 32;
+ icony = a->y + a->width;
+ iconw = 64;
+ g_free(a);
+ }
+ else {
+ iconx = self->client->icon_geometry.x;
+ icony = self->client->icon_geometry.y;
+ iconw = self->client->icon_geometry.width;
+ }
+
+ iconifying = self->iconify_animation_going > 0;
+
+ /* how far do we have left to go ? */
+ g_get_current_time(&now);
+ time = frame_animate_iconify_time_left(self, &now);
+
+ if (time == 0 || iconifying) {
+ /* start where the frame is supposed to be */
+ x = self->area.x;
+ y = self->area.y;
+ w = self->area.width;
+ h = self->area.height;
+ }
+ else {
+ /* start at the icon */
+ x = iconx;
+ y = icony;
+ w = iconw;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time > 0) {
+ glong dx, dy, dw;
+ glong elapsed;
+
+ dx = self->area.x - iconx;
+ dy = self->area.y - icony;
+ dw = self->area.width - self->bwidth * 2 - iconw;
+ /* if restoring, we move in the opposite direction */
+ if (!iconifying) {
+ dx = -dx;
+ dy = -dy;
+ dw = -dw;
+ }
+
+ elapsed = FRAME_ANIMATE_ICONIFY_TIME - time;
+ x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time == 0)
+ frame_end_iconify_animation(self);
+ else {
+ XMoveResizeWindow(plugin.ob_display, self->window, x, y, w, h);
+ XFlush(plugin.ob_display);
+ }
+
+ return time > 0; /* repeat until we're out of time */
+}
+
+void frame_adjust_cursors(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if ((self->functions & OB_CLIENT_FUNC_RESIZE) != (self->functions
+ & OB_CLIENT_FUNC_RESIZE) || self->max_horz != self->max_horz
+ || self->max_vert != self->max_vert || self->shaded != self->shaded) {
+ gboolean r = (self->functions & OB_CLIENT_FUNC_RESIZE)
+ && !(self->max_horz && self->max_vert);
+ gboolean topbot = !self->max_vert;
+ gboolean sh = self->shaded;
+ XSetWindowAttributes a;
+
+ /* these ones turn off when max vert, and some when shaded */
+ a.cursor = ob_cursor(r && topbot && !sh ? OB_CURSOR_NORTH
+ : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->topresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->titletop, CWCursor, &a);
+ a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->handle, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handletop, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handlebottom,
+ CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbottom, CWCursor,
+ &a);
+
+ /* these ones change when shaded */
+ a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST)
+ : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->titleleft, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->tltresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->tllresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->titletopleft,
+ CWCursor, &a);
+ a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST)
+ : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->titleright, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->trtresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->trrresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->titletopright,
+ CWCursor, &a);
+
+ /* these ones are pretty static */
+ a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->left, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerleft, CWCursor,
+ &a);
+ a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->right, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerright, CWCursor,
+ &a);
+ a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->lgrip, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handleleft, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->lgripleft, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->lgriptop, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->lgripbottom, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbll, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerblb, CWCursor, &a);
+ a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->rgrip, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handleright, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->rgripright, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->rgriptop, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->rgripbottom, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbrr, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbrb, CWCursor, &a);
+ }
+}
+
+void frame_adjust_client_area(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* adjust the window which is there to prevent flashing on unmap */
+ XMoveResizeWindow(plugin.ob_display, self->backfront, 0, 0,
+ self->client_area.width, self->client_area.height);
+}
+
+void frame_adjust_state(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+}
+
+void frame_adjust_focus(gpointer _self, gboolean hilite)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->focused = hilite;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+ XFlush(plugin.ob_display);
+}
+
+void frame_adjust_title(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+}
+
+void frame_adjust_icon(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->need_render = TRUE;
+ frame_update_skin(self);
+}
+
+/* is there anything present between us and the label? */
+static gboolean is_button_present(ObDefaultFrame *_self, const gchar *lc,
+ gint dir)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ for (; *lc != '\0' && lc >= plugin.config_title_layout; lc += dir) {
+ if (*lc == ' ')
+ continue; /* it was invalid */
+ if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
+ return TRUE;
+ if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
+ return TRUE;
+ if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
+ return TRUE;
+ if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
+ return TRUE;
+ if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
+ return TRUE;
+ if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
+ return TRUE;
+ if (*lc == 'L')
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void flash_done(gpointer data)
+{
+ ObDefaultFrame *self = data;
+
+ if (self->focused != self->flash_on)
+ frame_adjust_focus(self, self->focused);
+}
+
+gboolean flash_timeout(gpointer data)
+{
+ ObDefaultFrame *self = data;
+ GTimeVal now;
+
+ g_get_current_time(&now);
+ if (now.tv_sec > self->flash_end.tv_sec
+ || (now.tv_sec == self->flash_end.tv_sec && now.tv_usec
+ >= self->flash_end.tv_usec))
+ self->flashing = FALSE;
+
+ if (!self->flashing)
+ return FALSE; /* we are done */
+
+ self->flash_on = !self->flash_on;
+ if (!self->focused) {
+ frame_adjust_focus(self, self->flash_on);
+ self->focused = FALSE;
+ }
+
+ return TRUE; /* go again */
+}
+
+void layout_title(ObDefaultFrame * self)
+{
+ gchar *lc;
+ gint i;
+
+ const gint bwidth = theme_config.button_size + theme_config.paddingx + 1;
+ /* position of the left most button */
+ const gint left = theme_config.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 - (theme_config.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 = plugin.config_title_layout;
+ firstcon = &self->leftmost;
+ }
+ else {
+ x = right;
+ lc = plugin.config_title_layout
+ + strlen(plugin.config_title_layout)-1;
+ firstcon = &self->rightmost;
+ }
+
+ /* stop at the end of the string (or the label, which calls break) */
+ for (; *lc != '\0' && lc >= plugin.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(plugin.ob_display, self->icon);
+ XMoveWindow(plugin.ob_display, self->icon, self->icon_x,
+ theme_config.paddingy);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->icon);
+
+ if (self->desk_on) {
+ XMapWindow(plugin.ob_display, self->desk);
+ XMoveWindow(plugin.ob_display, self->desk, self->desk_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->desk);
+
+ if (self->shade_on) {
+ XMapWindow(plugin.ob_display, self->shade);
+ XMoveWindow(plugin.ob_display, self->shade, self->shade_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->shade);
+
+ if (self->iconify_on) {
+ XMapWindow(plugin.ob_display, self->iconify);
+ XMoveWindow(plugin.ob_display, self->iconify, self->iconify_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->iconify);
+
+ if (self->max_on) {
+ XMapWindow(plugin.ob_display, self->max);
+ XMoveWindow(plugin.ob_display, self->max, self->max_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->max);
+
+ if (self->close_on) {
+ XMapWindow(plugin.ob_display, self->close);
+ XMoveWindow(plugin.ob_display, self->close, self->close_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->close);
+
+ if (self->label_on) {
+ self->label_width = MAX(1, self->label_width); /* no lower than 1 */
+ XMapWindow(plugin.ob_display, self->label);
+ XMoveWindow(plugin.ob_display, self->label, self->label_x,
+ theme_config.paddingy);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->label);
+}
+
+ObFramePlugin plugin = { 0, //gpointer handler;
+ "libdefault.la", //gchar * filename;
+ "Default", //gchar * name;
+ init, //gint (*init) (Display * display, gint screen);
+ 0, frame_new, //gpointer (*frame_new) (struct _ObClient *c);
+ frame_free, //void (*frame_free) (gpointer self);
+ frame_show, //void (*frame_show) (gpointer self);
+ frame_hide, //void (*frame_hide) (gpointer self);
+ frame_adjust_theme, //void (*frame_adjust_theme) (gpointer self);
+ frame_adjust_shape, //void (*frame_adjust_shape) (gpointer self);
+ frame_grab, //void (*frame_adjust_area) (gpointer self, gboolean moved, gboolean resized, gboolean fake);
+ frame_ungrab, frame_context, //void (*frame_adjust_state) (gpointer self);
+ frame_set_is_visible, frame_set_is_focus, frame_set_is_max_vert,
+ frame_set_is_max_horz, frame_set_is_shaded,
+
+ frame_flash_start, frame_flash_stop, frame_begin_iconify_animation,
+ frame_end_iconify_animation, frame_iconify_animating,
+
+ frame_set_decorations,
+ /* This give the window area */
+ frame_get_window_area, frame_set_client_area,
+ /* Draw the frame */
+ frame_update_layout, frame_update_skin,
+
+ frame_set_hover_flag, frame_set_press_flag,
+
+ frame_get_window,
+
+ frame_get_size, frame_get_decorations,
+
+ frame_is_visible, frame_is_max_horz, frame_is_max_vert,
+
+ load_theme_config,
+
+ /* This fields are fill by openbox. */
+ 0, //Display * ob_display;
+ 0, //gint ob_screen;
+ 0, //RrInstance *ob_rr_inst;
+ // 0, //RrTheme *ob_rr_theme;
+ 0, //gboolean config_theme_keepborder;
+ 0, //struct _ObClient *focus_cycle_target;
+ 0, //gchar *config_title_layout;
+ FALSE, //gboolean moveresize_in_progress;
+ 0, //struct _ObMainLoop *ob_main_loop;
+};
+
+ObFramePlugin * get_info()
+{
+ return &plugin;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_plugin.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_DEFAULT_PLUGIN_H_
+#define FRAME_DEFAULT_PLUGIN_H_
+
+#include "config.h"
+#include "render/render.h"
+#include "openbox/engine_interface.h"
+
+ObFrameThemeConfig theme_config;
+
+struct _ObDefaultFrame
+{
+ /* PUBLIC : */
+
+ /* PRIVATE: */
+ /* You are free to add what you want here */
+
+ Window window;
+
+ gboolean visible;
+
+ gboolean max_horz; /* when maxed some decorations are hidden */
+ gboolean max_vert; /* when maxed some decorations are hidden */
+
+ struct _ObClient *client;
+ guint decorations;
+
+ Strut size;
+ Rect area;
+ Rect client_area;
+
+ gint bwidth;
+
+ ObFrameButton hover_flag;
+ ObFrameButton press_flag;
+
+ gint iconify_animation_going;
+ ObStyle style;
+
+ guint functions;
+
+ Window title;
+ Window label;
+ Window max;
+ Window close;
+ Window desk;
+ Window shade;
+ Window icon;
+ Window iconify;
+ Window handle;
+ Window lgrip;
+ Window rgrip;
+
+ /* These are borders of the frame and its elements */
+ Window titleleft;
+ Window titletop;
+ Window titletopleft;
+ Window titletopright;
+ Window titleright;
+ Window titlebottom;
+ Window left;
+ Window right;
+ Window handleleft;
+ Window handletop;
+ Window handleright;
+ Window handlebottom;
+ Window lgriptop;
+ Window lgripleft;
+ Window lgripbottom;
+ Window rgriptop;
+ Window rgripright;
+ Window rgripbottom;
+ Window innerleft; /*!< For drawing the inner client border */
+ Window innertop; /*!< For drawing the inner client border */
+ Window innerright; /*!< For drawing the inner client border */
+ Window innerbottom; /*!< For drawing the inner client border */
+ Window innerblb;
+ Window innerbll;
+ Window innerbrb;
+ Window innerbrr;
+ Window backback; /*!< A colored window shown while resizing */
+ Window backfront; /*!< An undrawn-in window, to prevent flashing on unmap */
+
+ /* These are resize handles inside the titlebar */
+ Window topresize;
+ Window tltresize;
+ Window tllresize;
+ Window trtresize;
+ Window trrresize;
+
+ Colormap colormap;
+
+ RrAppearance *a_unfocused_title;
+ RrAppearance *a_focused_title;
+ RrAppearance *a_unfocused_label;
+ RrAppearance *a_focused_label;
+ RrAppearance *a_icon;
+ RrAppearance *a_unfocused_handle;
+ RrAppearance *a_focused_handle;
+
+ gint icon_on; /* if the window icon button is on */
+ gint label_on; /* if the window title is on */
+ gint iconify_on; /* if the window iconify button is on */
+ gint desk_on; /* if the window all-desktops button is on */
+ gint shade_on; /* if the window shade button is on */
+ gint max_on; /* if the window maximize button is on */
+ gint close_on; /* if the window close button is on */
+
+ gint width; /* width of the titlebar and handle */
+ gint label_width; /* width of the label in the titlebar */
+ gint icon_x; /* x-position of the window icon button */
+ gint label_x; /* x-position of the window title */
+ gint iconify_x; /* x-position of the window iconify button */
+ gint desk_x; /* x-position of the window all-desktops button */
+ gint shade_x; /* x-position of the window shade button */
+ gint max_x; /* x-position of the window maximize button */
+ gint close_x; /* x-position of the window close button */
+
+ gint cbwidth_l; /* client border width */
+ gint cbwidth_t; /* client border width */
+ gint cbwidth_r; /* client border width */
+ gint cbwidth_b; /* client border width */
+ gboolean shaded; /* decorations adjust when shaded */
+
+ /* the leftmost and rightmost elements in the titlebar */
+ ObFrameContext leftmost;
+ ObFrameContext rightmost;
+
+ gboolean focused;
+ gboolean need_render;
+
+ gboolean flashing;
+ gboolean flash_on;
+ GTimeVal flash_end;
+
+ GTimeVal iconify_animation_end;
+
+};
+
+typedef struct _ObDefaultFrame ObDefaultFrame;
+
+/* Function use for interface */
+gint init(Display *, gint);
+gpointer frame_new(struct _ObClient *c);
+void frame_free(gpointer self);
+void frame_show(gpointer self);
+gint frame_hide(gpointer self);
+void frame_adjust_theme(gpointer self);
+void frame_adjust_shape(gpointer self);
+
+void frame_grab(gpointer self, GHashTable *);
+void frame_ungrab(gpointer self, GHashTable *);
+
+ObFrameContext frame_context(gpointer, Window, gint, gint);
+
+void frame_set_is_visible(gpointer, gboolean);
+void frame_set_is_focus(gpointer, gboolean);
+void frame_set_is_max_vert(gpointer, gboolean);
+void frame_set_is_max_horz(gpointer, gboolean);
+void frame_set_is_shaded(gpointer, gboolean);
+
+void frame_update_layout(gpointer, gboolean, gboolean);
+void frame_adjust_client_area(gpointer self);
+void frame_adjust_state(gpointer self);
+void frame_adjust_focus(gpointer self, gboolean hilite);
+void frame_adjust_title(gpointer self);
+void frame_adjust_icon(gpointer self);
+
+static gulong frame_animate_iconify_time_left(gpointer _self,
+ const GTimeVal *now);
+
+ObFrameContext frame_context(gpointer, Window win, gint x, gint y);
+//void frame_client_gravity(gpointer self, gint *x, gint *y);
+//void frame_frame_gravity(gpointer self, gint *x, gint *y);
+//void frame_rect_to_frame(gpointer self, Rect *r);
+//void frame_rect_to_client(gpointer self, Rect *r);
+void frame_flash_start(gpointer self);
+void frame_flash_stop(gpointer self);
+void frame_begin_iconify_animation(gpointer self, gboolean iconifying);
+void frame_end_iconify_animation(gpointer self);
+gboolean frame_iconify_animating(gpointer _self);
+
+void frame_set_hover_flag(gpointer, ObFrameButton);
+void frame_set_press_flag(gpointer, ObFrameButton);
+
+Window frame_get_window(gpointer);
+
+Strut frame_get_size(gpointer self);
+Rect frame_get_area(gpointer self);
+gint frame_get_decorations(gpointer self);
+
+gboolean frame_is_visible(gpointer self);
+gboolean frame_is_max_horz(gpointer self);
+gboolean frame_is_max_vert(gpointer self);
+
+void flash_done(gpointer data);
+gboolean flash_timeout(gpointer data);
+
+void layout_title(ObDefaultFrame *);
+void set_theme_statics(gpointer self);
+void free_theme_statics(gpointer self);
+gboolean frame_animate_iconify(gpointer self);
+void frame_adjust_cursors(gpointer self);
+
+/* Global for renderframe.c only */
+extern ObFramePlugin plugin;
+#define OBDEFAULTFRAME(x) ((ObDefaultFrame *)(x))
+
+#endif /*FRAME_DEFAULT_PLUGIN_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_render.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#include "render.h"
+#include "plugin.h"
+
+#include "openbox/engine_interface.h"
+#include "openbox/client.h"
+#include "openbox/screen.h"
+
+#include "render/theme.h"
+
+static void framerender_label(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_icon(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_max(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_iconify(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_desk(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_shade(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_close(ObDefaultFrame *self, RrAppearance *a);
+
+void frame_update_skin(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if (plugin.frame_iconify_animating(self))
+ return; /* delay redrawing until the animation is done */
+ if (!self->visible)
+ return;
+
+ {
+ gulong px;
+
+ px = (self->focused ? RrColorPixel(theme_config.cb_focused_color)
+ : RrColorPixel(theme_config.cb_unfocused_color));
+
+ XSetWindowBackground(plugin.ob_display, self->backback, px);
+ XClearWindow(plugin.ob_display, self->backback);
+ XSetWindowBackground(plugin.ob_display, self->innerleft, px);
+ XClearWindow(plugin.ob_display, self->innerleft);
+ XSetWindowBackground(plugin.ob_display, self->innertop, px);
+ XClearWindow(plugin.ob_display, self->innertop);
+ XSetWindowBackground(plugin.ob_display, self->innerright, px);
+ XClearWindow(plugin.ob_display, self->innerright);
+ XSetWindowBackground(plugin.ob_display, self->innerbottom, px);
+ XClearWindow(plugin.ob_display, self->innerbottom);
+ XSetWindowBackground(plugin.ob_display, self->innerbll, px);
+ XClearWindow(plugin.ob_display, self->innerbll);
+ XSetWindowBackground(plugin.ob_display, self->innerbrr, px);
+ XClearWindow(plugin.ob_display, self->innerbrr);
+ XSetWindowBackground(plugin.ob_display, self->innerblb, px);
+ XClearWindow(plugin.ob_display, self->innerblb);
+ XSetWindowBackground(plugin.ob_display, self->innerbrb, px);
+ XClearWindow(plugin.ob_display, self->innerbrb);
+
+ px
+ = (self->focused ? RrColorPixel(theme_config.frame_focused_border_color)
+ : RrColorPixel(theme_config.frame_unfocused_border_color));
+
+ XSetWindowBackground(plugin.ob_display, self->left, px);
+ XClearWindow(plugin.ob_display, self->left);
+ XSetWindowBackground(plugin.ob_display, self->right, px);
+ XClearWindow(plugin.ob_display, self->right);
+
+ XSetWindowBackground(plugin.ob_display, self->titleleft, px);
+ XClearWindow(plugin.ob_display, self->titleleft);
+ XSetWindowBackground(plugin.ob_display, self->titletop, px);
+ XClearWindow(plugin.ob_display, self->titletop);
+ XSetWindowBackground(plugin.ob_display, self->titletopleft, px);
+ XClearWindow(plugin.ob_display, self->titletopleft);
+ XSetWindowBackground(plugin.ob_display, self->titletopright, px);
+ XClearWindow(plugin.ob_display, self->titletopright);
+ XSetWindowBackground(plugin.ob_display, self->titleright, px);
+ XClearWindow(plugin.ob_display, self->titleright);
+
+ XSetWindowBackground(plugin.ob_display, self->handleleft, px);
+ XClearWindow(plugin.ob_display, self->handleleft);
+ XSetWindowBackground(plugin.ob_display, self->handletop, px);
+ XClearWindow(plugin.ob_display, self->handletop);
+ XSetWindowBackground(plugin.ob_display, self->handleright, px);
+ XClearWindow(plugin.ob_display, self->handleright);
+ XSetWindowBackground(plugin.ob_display, self->handlebottom, px);
+ XClearWindow(plugin.ob_display, self->handlebottom);
+
+ XSetWindowBackground(plugin.ob_display, self->lgripleft, px);
+ XClearWindow(plugin.ob_display, self->lgripleft);
+ XSetWindowBackground(plugin.ob_display, self->lgriptop, px);
+ XClearWindow(plugin.ob_display, self->lgriptop);
+ XSetWindowBackground(plugin.ob_display, self->lgripbottom, px);
+ XClearWindow(plugin.ob_display, self->lgripbottom);
+
+ XSetWindowBackground(plugin.ob_display, self->rgripright, px);
+ XClearWindow(plugin.ob_display, self->rgripright);
+ XSetWindowBackground(plugin.ob_display, self->rgriptop, px);
+ XClearWindow(plugin.ob_display, self->rgriptop);
+ XSetWindowBackground(plugin.ob_display, self->rgripbottom, px);
+ XClearWindow(plugin.ob_display, self->rgripbottom);
+
+ /* don't use the separator color for shaded windows */
+ if (!self->shaded)
+ px
+ = (self->focused ? RrColorPixel(theme_config.title_separator_focused_color)
+ : RrColorPixel(theme_config.title_separator_unfocused_color));
+
+ XSetWindowBackground(plugin.ob_display, self->titlebottom, px);
+ XClearWindow(plugin.ob_display, self->titlebottom);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
+ RrAppearance *t, *l, *m, *n, *i, *d, *s, *c, *clear;
+ if (self->focused) {
+
+ t = self->a_focused_title;
+ l = self->a_focused_label;
+
+ m
+ = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ? theme_config.a_disabled_focused_max
+ : (self->max_vert || self->max_horz ? (self->press_flag
+ == OB_BUTTON_MAX ? theme_config.a_toggled_focused_pressed_max
+ : (self->hover_flag == OB_BUTTON_MAX ? theme_config.a_toggled_hover_focused_max
+ : theme_config.a_toggled_focused_unpressed_max))
+ : (self->press_flag == OB_BUTTON_MAX ? theme_config.a_focused_pressed_max
+ : (self->hover_flag
+ == OB_BUTTON_MAX ? theme_config.a_hover_focused_max
+ : theme_config.a_focused_unpressed_max))));
+ n = self->a_icon;
+ i
+ = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ? theme_config.a_disabled_focused_iconify
+ : (self->press_flag == OB_BUTTON_ICONIFY ? theme_config.a_focused_pressed_iconify
+ : (self->hover_flag == OB_BUTTON_ICONIFY ? theme_config.a_hover_focused_iconify
+ : theme_config.a_focused_unpressed_iconify)));
+ d
+ = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ? theme_config.a_disabled_focused_desk
+ : (self->client->desktop == DESKTOP_ALL ? (self->press_flag
+ == OB_BUTTON_DESK ? theme_config.a_toggled_focused_pressed_desk
+ : (self->hover_flag == OB_BUTTON_DESK ? theme_config.a_toggled_hover_focused_desk
+ : theme_config.a_toggled_focused_unpressed_desk))
+ : (self->press_flag == OB_BUTTON_DESK ? theme_config.a_focused_pressed_desk
+ : (self->hover_flag
+ == OB_BUTTON_DESK ? theme_config.a_hover_focused_desk
+ : theme_config.a_focused_unpressed_desk))));
+ s
+ = (!(self->decorations & OB_FRAME_DECOR_SHADE) ? theme_config.a_disabled_focused_shade
+ : (self->shaded ? (self->press_flag
+ == OB_BUTTON_SHADE ? theme_config.a_toggled_focused_pressed_shade
+ : (self->hover_flag == OB_BUTTON_SHADE ? theme_config.a_toggled_hover_focused_shade
+ : theme_config.a_toggled_focused_unpressed_shade))
+ : (self->press_flag == OB_BUTTON_SHADE ? theme_config.a_focused_pressed_shade
+ : (self->hover_flag
+ == OB_BUTTON_SHADE ? theme_config.a_hover_focused_shade
+ : theme_config.a_focused_unpressed_shade))));
+ c
+ = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ? theme_config.a_disabled_focused_close
+ : (self->press_flag == OB_BUTTON_CLOSE ? theme_config.a_focused_pressed_close
+ : (self->hover_flag == OB_BUTTON_CLOSE ? theme_config.a_hover_focused_close
+ : theme_config.a_focused_unpressed_close)));
+ }
+ else {
+ t = self->a_unfocused_title;
+ l = self->a_unfocused_label;
+ m
+ = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ? theme_config.a_disabled_unfocused_max
+ : (self->max_vert || self->max_horz ? (self->press_flag
+ == OB_BUTTON_MAX ? theme_config.a_toggled_unfocused_pressed_max
+ : (self->hover_flag == OB_BUTTON_MAX ? theme_config.a_toggled_hover_unfocused_max
+ : theme_config.a_toggled_unfocused_unpressed_max))
+ : (self->press_flag == OB_BUTTON_MAX ? theme_config.a_unfocused_pressed_max
+ : (self->hover_flag
+ == OB_BUTTON_MAX ? theme_config.a_hover_unfocused_max
+ : theme_config.a_unfocused_unpressed_max))));
+ n = self->a_icon;
+ i
+ = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ? theme_config.a_disabled_unfocused_iconify
+ : (self->press_flag == OB_BUTTON_ICONIFY ? theme_config.a_unfocused_pressed_iconify
+ : (self->hover_flag == OB_BUTTON_ICONIFY ? theme_config.a_hover_unfocused_iconify
+ : theme_config.a_unfocused_unpressed_iconify)));
+ d
+ = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ? theme_config.a_disabled_unfocused_desk
+ : (self->client->desktop == DESKTOP_ALL ? (self->press_flag
+ == OB_BUTTON_DESK ? theme_config.a_toggled_unfocused_pressed_desk
+ : (self->hover_flag == OB_BUTTON_DESK ? theme_config.a_toggled_hover_unfocused_desk
+ : theme_config.a_toggled_unfocused_unpressed_desk))
+ : (self->hover_flag == OB_BUTTON_DESK ? theme_config.a_unfocused_pressed_desk
+ : (self->hover_flag
+ == OB_BUTTON_DESK ? theme_config.a_hover_unfocused_desk
+ : theme_config.a_unfocused_unpressed_desk))));
+ s
+ = (!(self->decorations & OB_FRAME_DECOR_SHADE) ? theme_config.a_disabled_unfocused_shade
+ : (self->shaded ? (self->press_flag
+ == OB_BUTTON_SHADE ? theme_config.a_toggled_unfocused_pressed_shade
+ : (self->hover_flag == OB_BUTTON_SHADE ? theme_config.a_toggled_hover_unfocused_shade
+ : theme_config.a_toggled_unfocused_unpressed_shade))
+ : (self->press_flag == OB_BUTTON_SHADE ? theme_config.a_unfocused_pressed_shade
+ : (self->hover_flag
+ == OB_BUTTON_SHADE ? theme_config.a_hover_unfocused_shade
+ : theme_config.a_unfocused_unpressed_shade))));
+ c
+ = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ? theme_config.a_disabled_unfocused_close
+ : (self->press_flag == OB_BUTTON_CLOSE ? theme_config.a_unfocused_pressed_close
+ : (self->hover_flag == OB_BUTTON_CLOSE ? theme_config.a_hover_unfocused_close
+ : theme_config.a_unfocused_unpressed_close)));
+ }
+ clear = theme_config.a_clear;
+
+ RrPaint(t, self->title, self->width, theme_config.title_height);
+
+ clear->surface.parent = t;
+ clear->surface.parenty = 0;
+
+ clear->surface.parentx = theme_config.grip_width;
+
+ RrPaint(clear, self->topresize, self->width - theme_config.grip_width
+ * 2, theme_config.paddingy + 1);
+
+ clear->surface.parentx = 0;
+
+ if (theme_config.grip_width > 0)
+ RrPaint(clear, self->tltresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+ if (theme_config.title_height > 0)
+ RrPaint(clear, self->tllresize, theme_config.paddingx + 1,
+ theme_config.title_height);
+
+ clear->surface.parentx = self->width - theme_config.grip_width;
+
+ if (theme_config.grip_width > 0)
+ RrPaint(clear, self->trtresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+
+ clear->surface.parentx = self->width - (theme_config.paddingx + 1);
+
+ if (theme_config.title_height > 0)
+ RrPaint(clear, self->trrresize, theme_config.paddingx + 1,
+ theme_config.title_height);
+
+ /* set parents for any parent relative guys */
+ l->surface.parent = t;
+ l->surface.parentx = self->label_x;
+ l->surface.parenty = theme_config.paddingy;
+
+ m->surface.parent = t;
+ m->surface.parentx = self->max_x;
+ m->surface.parenty = theme_config.paddingy + 1;
+
+ n->surface.parent = t;
+ n->surface.parentx = self->icon_x;
+ n->surface.parenty = theme_config.paddingy;
+
+ i->surface.parent = t;
+ i->surface.parentx = self->iconify_x;
+ i->surface.parenty = theme_config.paddingy + 1;
+
+ d->surface.parent = t;
+ d->surface.parentx = self->desk_x;
+ d->surface.parenty = theme_config.paddingy + 1;
+
+ s->surface.parent = t;
+ s->surface.parentx = self->shade_x;
+ s->surface.parenty = theme_config.paddingy + 1;
+
+ c->surface.parent = t;
+ c->surface.parentx = self->close_x;
+ c->surface.parenty = theme_config.paddingy + 1;
+
+ framerender_label(self, l);
+ framerender_max(self, m);
+ framerender_icon(self, n);
+ framerender_iconify(self, i);
+ framerender_desk(self, d);
+ framerender_shade(self, s);
+ framerender_close(self, c);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE && theme_config.handle_height
+ > 0) {
+ RrAppearance *h, *g;
+
+ h = (self->focused ? self->a_focused_handle : self->a_unfocused_handle);
+
+ RrPaint(h, self->handle, self->width, theme_config.handle_height);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ g = (self->focused ? theme_config.a_focused_grip
+ : theme_config.a_unfocused_grip);
+
+ if (g->surface.grad == RR_SURFACE_PARENTREL)
+ g->surface.parent = h;
+
+ g->surface.parentx = 0;
+ g->surface.parenty = 0;
+
+ RrPaint(g, self->lgrip, theme_config.grip_width,
+ theme_config.handle_height);
+
+ g->surface.parentx = self->width - theme_config.grip_width;
+ g->surface.parenty = 0;
+
+ RrPaint(g, self->rgrip, theme_config.grip_width,
+ theme_config.handle_height);
+ }
+ }
+
+ XFlush(plugin.ob_display);
+}
+
+static void framerender_label(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->label_on)
+ return;
+ /* set the texture's text! */
+ a->texture[0].data.text.string = self->client->title;
+ RrPaint(a, self->label, self->label_width, theme_config.label_height);
+}
+
+static void framerender_icon(ObDefaultFrame *self, RrAppearance *a)
+{
+ const ObClientIcon *icon;
+
+ if (!self->icon_on)
+ return;
+
+ icon = client_icon(self->client, theme_config.button_size + 2,
+ theme_config.button_size + 2);
+ if (icon) {
+ a->texture[0].type = RR_TEXTURE_RGBA;
+ a->texture[0].data.rgba.width = icon->width;
+ a->texture[0].data.rgba.height = icon->height;
+ a->texture[0].data.rgba.alpha = 0xff;
+ a->texture[0].data.rgba.data = icon->data;
+ }
+ else
+ a->texture[0].type = RR_TEXTURE_NONE;
+
+ RrPaint(a, self->icon, theme_config.button_size + 2,
+ theme_config.button_size + 2);
+}
+
+static void framerender_max(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->max_on)
+ return;
+ RrPaint(a, self->max, theme_config.button_size, theme_config.button_size);
+}
+
+static void framerender_iconify(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->iconify_on)
+ return;
+ RrPaint(a, self->iconify, theme_config.button_size,
+ theme_config.button_size);
+}
+
+static void framerender_desk(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->desk_on)
+ return;
+ RrPaint(a, self->desk, theme_config.button_size, theme_config.button_size);
+}
+
+static void framerender_shade(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->shade_on)
+ return;
+ RrPaint(a, self->shade, theme_config.button_size, theme_config.button_size);
+}
+
+static void framerender_close(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->close_on)
+ return;
+ RrPaint(a, self->close, theme_config.button_size, theme_config.button_size);
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_default_render.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#ifndef FRAME_DEFAULT_RENDER_H_
+#define FRAME_DEFAULT_RENDER_H_
+
+#include "plugin.h"
+
+void frame_update_skin(gpointer self);
+
+#endif
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_minimal_config.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "frame_minimal_config.h"
+#include "frame_minimal_plugin.h"
+
+#include "render/render.h"
+#include "render/color.h"
+#include "render/font.h"
+#include "render/mask.h"
+#include "render/icon.h"
+#include "parser/parse.h"
+
+#include <X11/Xlib.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+static XrmDatabase loaddb(const gchar *name, gchar **path);
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value);
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value);
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value);
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans);
+static int parse_inline_number(const char *p);
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
+static void set_default_appearance(RrAppearance *a);
+
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font)
+{
+ RrJustify winjust, mtitlejust;
+ gchar *str;
+ ObFrameThemeConfig * theme = &theme_config;
+ gboolean userdef;
+
+ //theme = g_new0(ObFrameTheme, 1);
+
+ theme->inst = inst;
+ theme->name = g_strdup(name ? name : DEFAULT_THEME);
+
+ theme->a_disabled_focused_max = RrAppearanceNew(inst, 1);
+ theme->a_disabled_unfocused_max = RrAppearanceNew(inst, 1);
+ theme->a_hover_focused_max = RrAppearanceNew(inst, 1);
+ theme->a_hover_unfocused_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_focused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_unfocused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_hover_focused_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_hover_unfocused_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_focused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_toggled_unfocused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_focused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_focused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_unfocused_unpressed_max = RrAppearanceNew(inst, 1);
+ theme->a_unfocused_pressed_max = RrAppearanceNew(inst, 1);
+ theme->a_focused_grip = RrAppearanceNew(inst, 0);
+ theme->a_unfocused_grip = RrAppearanceNew(inst, 0);
+ theme->a_focused_title = RrAppearanceNew(inst, 0);
+ theme->a_unfocused_title = RrAppearanceNew(inst, 0);
+ theme->a_focused_label = RrAppearanceNew(inst, 1);
+ theme->a_unfocused_label = RrAppearanceNew(inst, 1);
+ theme->a_icon = RrAppearanceNew(inst, 1);
+ theme->a_focused_handle = RrAppearanceNew(inst, 0);
+ theme->a_unfocused_handle = RrAppearanceNew(inst, 0);
+ theme->a_menu = RrAppearanceNew(inst, 0);
+ theme->a_menu_title = RrAppearanceNew(inst, 0);
+ theme->a_menu_text_title = RrAppearanceNew(inst, 1);
+ theme->a_menu_normal = RrAppearanceNew(inst, 0);
+ theme->a_menu_selected = RrAppearanceNew(inst, 0);
+ theme->a_menu_disabled = RrAppearanceNew(inst, 0);
+ theme->a_menu_disabled_selected = RrAppearanceNew(inst, 0);
+ theme->a_menu_text_normal = RrAppearanceNew(inst, 1);
+ theme->a_menu_text_selected = RrAppearanceNew(inst, 1);
+ theme->a_menu_text_disabled = RrAppearanceNew(inst, 1);
+ theme->a_menu_text_disabled_selected = RrAppearanceNew(inst, 1);
+ theme->a_menu_bullet_normal = RrAppearanceNew(inst, 1);
+ theme->a_menu_bullet_selected = RrAppearanceNew(inst, 1);
+ theme->a_clear = RrAppearanceNew(inst, 0);
+ theme->a_clear_tex = RrAppearanceNew(inst, 1);
+ theme->osd_hilite_bg = RrAppearanceNew(inst, 0);
+ theme->osd_hilite_label = RrAppearanceNew(inst, 1);
+ theme->osd_hilite_fg = RrAppearanceNew(inst, 0);
+ theme->osd_unhilite_fg = RrAppearanceNew(inst, 0);
+
+ /* load the font stuff */
+ if (active_window_font) {
+ theme->win_font_focused = active_window_font;
+ RrFontRef(active_window_font);
+ }
+ else
+ theme->win_font_focused = RrFontOpenDefault(inst);
+
+ if (inactive_window_font) {
+ theme->win_font_unfocused = inactive_window_font;
+ RrFontRef(inactive_window_font);
+ }
+ else
+ theme->win_font_unfocused = RrFontOpenDefault(inst);
+
+ winjust = RR_JUSTIFY_LEFT;
+ str = "center";
+ if (!g_ascii_strcasecmp(str, "right"))
+ winjust = RR_JUSTIFY_RIGHT;
+ else if (!g_ascii_strcasecmp(str, "center"))
+ winjust = RR_JUSTIFY_CENTER;
+
+ if (menu_title_font) {
+ theme->menu_title_font = menu_title_font;
+ RrFontRef(menu_title_font);
+ }
+ else
+ theme->menu_title_font = RrFontOpenDefault(inst);
+
+ mtitlejust = RR_JUSTIFY_LEFT;
+ str = "center";
+ if (!g_ascii_strcasecmp(str, "right"))
+ mtitlejust = RR_JUSTIFY_RIGHT;
+ else if (!g_ascii_strcasecmp(str, "center"))
+ mtitlejust = RR_JUSTIFY_CENTER;
+
+ if (menu_item_font) {
+ theme->menu_font = menu_item_font;
+ RrFontRef(menu_item_font);
+ }
+ else
+ theme->menu_font = RrFontOpenDefault(inst);
+
+ if (osd_font) {
+ theme->osd_font = osd_font;
+ RrFontRef(osd_font);
+ }
+ else
+ theme->osd_font = RrFontOpenDefault(inst);
+
+ /* load direct dimensions */
+ theme->menu_overlap = 0;
+ theme->handle_height = 6;
+ theme->paddingx = 3;
+ theme->paddingy = theme->paddingx;
+ theme->fbwidth = 1;
+ /* menu border width inherits from the frame border width */
+ theme->mbwidth = theme->fbwidth;
+ /* osd border width inherits from the frame border width */
+ theme->obwidth = theme->fbwidth;
+ theme->cbwidthx = theme->paddingx;
+ theme->cbwidthy = theme->cbwidthx;
+
+ /* load colors */
+ theme->frame_focused_border_color = RrColorNew(inst, 0, 0, 0);
+ /* title separator focused color inherits from focused boder color */
+ theme->title_separator_focused_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ /* unfocused border color inherits from frame focused border color */
+ theme->frame_unfocused_border_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ /* title separator unfocused color inherits from unfocused boder color */
+ theme->title_separator_unfocused_color = RrColorNew(inst,
+ theme->frame_unfocused_border_color->r,
+ theme->frame_unfocused_border_color->g,
+ theme->frame_unfocused_border_color->b);
+
+ /* menu border color inherits from frame focused border color */
+ theme->menu_border_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ /* osd border color inherits from frame focused border color */
+ theme->osd_border_color = RrColorNew(inst,
+ theme->frame_focused_border_color->r,
+ theme->frame_focused_border_color->g,
+ theme->frame_focused_border_color->b);
+ theme->cb_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ theme->cb_unfocused_color = RrColorNew(inst, 0x44, 0x44, 0x44);
+ theme->title_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ theme->osd_color = RrColorNew(inst, theme->title_focused_color->r,
+ theme->title_focused_color->g, theme->title_focused_color->b);
+ theme->title_unfocused_color = RrColorNew(inst, 0x44, 0x44, 0x44);
+ theme->titlebut_focused_unpressed_color
+ = RrColorNew(inst, 0xff, 0xff, 0xff);
+ theme->titlebut_unfocused_unpressed_color = RrColorNew(inst, 0x44, 0x44,
+ 0x44);
+ theme->titlebut_focused_pressed_color = RrColorNew(inst,
+ theme->titlebut_focused_unpressed_color->r,
+ theme->titlebut_focused_unpressed_color->g,
+ theme->titlebut_focused_unpressed_color->b);
+ theme->titlebut_unfocused_pressed_color = RrColorNew(inst,
+ theme->titlebut_unfocused_unpressed_color->r,
+ theme->titlebut_unfocused_unpressed_color->g,
+ theme->titlebut_unfocused_unpressed_color->b);
+ theme->titlebut_disabled_focused_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ theme->titlebut_disabled_unfocused_color = RrColorNew(inst, 0, 0, 0);
+ theme->titlebut_hover_focused_color = RrColorNew(inst,
+ theme->titlebut_focused_unpressed_color->r,
+ theme->titlebut_focused_unpressed_color->g,
+ theme->titlebut_focused_unpressed_color->b);
+ theme->titlebut_hover_unfocused_color = RrColorNew(inst,
+ theme->titlebut_unfocused_unpressed_color->r,
+ theme->titlebut_unfocused_unpressed_color->g,
+ theme->titlebut_unfocused_unpressed_color->b);
+ theme->titlebut_toggled_focused_unpressed_color = RrColorNew(inst,
+ theme->titlebut_focused_pressed_color->r,
+ theme->titlebut_focused_pressed_color->g,
+ theme->titlebut_focused_pressed_color->b);
+ theme->titlebut_toggled_unfocused_unpressed_color = RrColorNew(inst,
+ theme->titlebut_unfocused_pressed_color->r,
+ theme->titlebut_unfocused_pressed_color->g,
+ theme->titlebut_unfocused_pressed_color->b);
+ theme->titlebut_toggled_hover_focused_color = RrColorNew(inst,
+ theme->titlebut_toggled_focused_unpressed_color->r,
+ theme->titlebut_toggled_focused_unpressed_color->g,
+ theme->titlebut_toggled_focused_unpressed_color->b);
+ theme->titlebut_toggled_hover_unfocused_color = RrColorNew(inst,
+ theme->titlebut_toggled_unfocused_unpressed_color->r,
+ theme->titlebut_toggled_unfocused_unpressed_color->g,
+ theme->titlebut_toggled_unfocused_unpressed_color->b);
+ theme->titlebut_toggled_focused_pressed_color = RrColorNew(inst,
+ theme->titlebut_focused_pressed_color->r,
+ theme->titlebut_focused_pressed_color->g,
+ theme->titlebut_focused_pressed_color->b);
+ theme->titlebut_toggled_unfocused_pressed_color = RrColorNew(inst,
+ theme->titlebut_unfocused_pressed_color->r,
+ theme->titlebut_unfocused_pressed_color->g,
+ theme->titlebut_unfocused_pressed_color->b);
+ theme->menu_title_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_color = RrColorNew(inst, 0xff, 0xff, 0xff);
+ theme->menu_disabled_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_disabled_selected_color = RrColorNew(inst,
+ theme->menu_disabled_color->r, theme->menu_disabled_color->g,
+ theme->menu_disabled_color->b);
+ theme->menu_selected_color = RrColorNew(inst, 0, 0, 0);
+
+ /* load the image masks */
+
+ /* maximize button masks */
+ userdef = TRUE;
+ if (!read_mask(inst, path, theme, "max.xbm", &theme->max_mask)) {
+ guchar data[] = { 0x3f, 0x3f, 0x21, 0x21, 0x21, 0x3f };
+ theme->max_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ userdef = FALSE;
+ }
+ if (!read_mask(inst, path, theme, "max_toggled.xbm",
+ &theme->max_toggled_mask)) {
+ if (userdef)
+ theme->max_toggled_mask = RrPixmapMaskCopy(theme->max_mask);
+ else {
+ guchar data[] = { 0x3e, 0x22, 0x2f, 0x29, 0x39, 0x0f };
+ theme->max_toggled_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ }
+
+ theme->max_pressed_mask = RrPixmapMaskCopy(theme->max_mask);
+ theme->max_disabled_mask = RrPixmapMaskCopy(theme->max_mask);
+ theme->max_hover_mask = RrPixmapMaskCopy(theme->max_mask);
+ theme->max_toggled_pressed_mask = RrPixmapMaskCopy(theme->max_toggled_mask);
+ theme->max_toggled_hover_mask = RrPixmapMaskCopy(theme->max_toggled_mask);
+
+ /* iconify button masks */
+ if (!read_mask(inst, path, theme, "iconify.xbm", &theme->iconify_mask)) {
+ guchar data[] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f };
+ theme->iconify_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ theme->iconify_pressed_mask = RrPixmapMaskCopy(theme->iconify_mask);
+ theme->iconify_disabled_mask = RrPixmapMaskCopy(theme->iconify_mask);
+ theme->iconify_hover_mask = RrPixmapMaskCopy(theme->iconify_mask);
+
+ /* all desktops button masks */
+ userdef = TRUE;
+ if (!read_mask(inst, path, theme, "desk.xbm", &theme->desk_mask)) {
+ guchar data[] = { 0x33, 0x33, 0x00, 0x00, 0x33, 0x33 };
+ theme->desk_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ userdef = FALSE;
+ }
+ if (!read_mask(inst, path, theme, "desk_toggled.xbm",
+ &theme->desk_toggled_mask)) {
+ if (userdef)
+ theme->desk_toggled_mask = RrPixmapMaskCopy(theme->desk_mask);
+ else {
+ guchar data[] = { 0x00, 0x1e, 0x1a, 0x16, 0x1e, 0x00 };
+ theme->desk_toggled_mask
+ = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ }
+ theme->desk_pressed_mask = RrPixmapMaskCopy(theme->desk_mask);
+ theme->desk_disabled_mask = RrPixmapMaskCopy(theme->desk_mask);
+ theme->desk_hover_mask = RrPixmapMaskCopy(theme->desk_mask);
+ theme->desk_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->desk_toggled_mask);
+ theme->desk_toggled_hover_mask = RrPixmapMaskCopy(theme->desk_toggled_mask);
+
+ /* shade button masks */
+ if (!read_mask(inst, path, theme, "shade.xbm", &theme->shade_mask)) {
+ guchar data[] = { 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00 };
+ theme->shade_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ theme->shade_toggled_mask = RrPixmapMaskCopy(theme->shade_mask);
+ theme->shade_pressed_mask = RrPixmapMaskCopy(theme->shade_mask);
+ theme->shade_disabled_mask = RrPixmapMaskCopy(theme->shade_mask);
+ theme->shade_hover_mask = RrPixmapMaskCopy(theme->shade_mask);
+ theme->shade_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+ theme->shade_toggled_hover_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+
+ /* close button masks */
+ if (!read_mask(inst, path, theme, "close.xbm", &theme->close_mask)) {
+ guchar data[] = { 0x33, 0x3f, 0x1e, 0x1e, 0x3f, 0x33 };
+ theme->close_mask = RrPixmapMaskNew(inst, 6, 6, (gchar*)data);
+ }
+ theme->close_pressed_mask = RrPixmapMaskCopy(theme->close_mask);
+ theme->close_disabled_mask = RrPixmapMaskCopy(theme->close_mask);
+ theme->close_hover_mask = RrPixmapMaskCopy(theme->close_mask);
+
+ /* submenu bullet mask */
+ if (!read_mask(inst, path, theme, "bullet.xbm", &theme->menu_bullet_mask)) {
+ guchar data[] = { 0x01, 0x03, 0x07, 0x0f, 0x07, 0x03, 0x01 };
+ theme->menu_bullet_mask = RrPixmapMaskNew(inst, 4, 7, (gchar*)data);
+ }
+
+ /* setup the default window icon */
+ theme->def_win_icon = read_c_image(OB_DEFAULT_ICON_WIDTH,
+ OB_DEFAULT_ICON_HEIGHT, OB_DEFAULT_ICON_pixel_data);
+
+ /* the toggled hover mask = the toggled unpressed mask (i.e. no change) */
+ theme->max_toggled_hover_mask = RrPixmapMaskCopy(theme->max_toggled_mask);
+ theme->desk_toggled_hover_mask = RrPixmapMaskCopy(theme->desk_toggled_mask);
+ theme->shade_toggled_hover_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+ /* the toggled pressed mask = the toggled unpressed mask (i.e. no change)*/
+ theme->max_toggled_pressed_mask = RrPixmapMaskCopy(theme->max_toggled_mask);
+ theme->desk_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->desk_toggled_mask);
+ theme->shade_toggled_pressed_mask
+ = RrPixmapMaskCopy(theme->shade_toggled_mask);
+
+ /* read the decoration textures */
+ set_default_appearance(theme->a_focused_title);
+ set_default_appearance(theme->a_unfocused_title);
+ set_default_appearance(theme->a_focused_label);
+ set_default_appearance(theme->a_unfocused_label);
+ set_default_appearance(theme->a_focused_handle);
+ set_default_appearance(theme->a_unfocused_handle);
+ set_default_appearance(theme->a_focused_grip);
+ set_default_appearance(theme->a_unfocused_grip);
+ set_default_appearance(theme->a_menu);
+ set_default_appearance(theme->a_menu_title);
+ set_default_appearance(theme->a_menu_selected);
+ theme->a_menu_disabled_selected = RrAppearanceCopy(theme->a_menu_selected);
+
+ /* read appearances for non-decorations (on-screen-display) */
+ if (!read_appearance(db, inst, "osd.bg", theme->osd_hilite_bg, FALSE)) {
+ RrAppearanceFree(theme->osd_hilite_bg);
+ theme->osd_hilite_bg = RrAppearanceCopy(theme->a_focused_title);
+ }
+ if (!read_appearance(db, inst, "osd.label.bg", theme->osd_hilite_label,
+ TRUE)) {
+ RrAppearanceFree(theme->osd_hilite_label);
+ theme->osd_hilite_label = RrAppearanceCopy(theme->a_focused_label);
+ }
+ /* osd_hilite_fg can't be parentrel */
+ if (!read_appearance(db, inst, "osd.hilight.bg", theme->osd_hilite_fg,
+ FALSE)) {
+ RrAppearanceFree(theme->osd_hilite_fg);
+ if (theme->a_focused_label->surface.grad != RR_SURFACE_PARENTREL)
+ theme->osd_hilite_fg = RrAppearanceCopy(theme->a_focused_label);
+ else
+ theme->osd_hilite_fg = RrAppearanceCopy(theme->a_focused_title);
+ }
+ /* osd_unhilite_fg can't be parentrel either */
+ if (!read_appearance(db, inst, "osd.unhilight.bg", theme->osd_unhilite_fg,
+ FALSE)) {
+ RrAppearanceFree(theme->osd_unhilite_fg);
+ if (theme->a_unfocused_label->surface.grad != RR_SURFACE_PARENTREL)
+ theme->osd_unhilite_fg=RrAppearanceCopy(theme->a_unfocused_label);
+ else
+ theme->osd_unhilite_fg=RrAppearanceCopy(theme->a_unfocused_title);
+ }
+
+ /* read buttons textures */
+ set_default_appearance(theme->a_disabled_focused_max);
+ set_default_appearance(theme->a_disabled_unfocused_max);
+ set_default_appearance(theme->a_focused_pressed_max);
+ set_default_appearance(theme->a_unfocused_pressed_max);
+ if (!read_appearance(db, inst, "window.active.button.toggled.unpressed.bg",
+ theme->a_toggled_focused_unpressed_max, TRUE) && !read_appearance(
+ db, inst, "window.active.button.toggled.bg",
+ theme->a_toggled_focused_unpressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_focused_unpressed_max);
+ theme->a_toggled_focused_unpressed_max
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ }
+ if (!read_appearance(db, inst,
+ "window.inactive.button.toggled.unpressed.bg",
+ theme->a_toggled_unfocused_unpressed_max, TRUE)
+ && !read_appearance(db, inst, "window.inactive.button.toggled.bg",
+ theme->a_toggled_unfocused_unpressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_unfocused_unpressed_max);
+ theme->a_toggled_unfocused_unpressed_max
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ }
+ if (!read_appearance(db, inst, "window.active.button.toggled.hover.bg",
+ theme->a_toggled_hover_focused_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_hover_focused_max);
+ theme->a_toggled_hover_focused_max
+ = RrAppearanceCopy(theme->a_toggled_focused_unpressed_max);
+ }
+ if (!read_appearance(db, inst, "window.inactive.button.toggled.hover.bg",
+ theme->a_toggled_hover_unfocused_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_hover_unfocused_max);
+ theme->a_toggled_hover_unfocused_max
+ = RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max);
+ }
+ if (!read_appearance(db, inst, "window.active.button.toggled.pressed.bg",
+ theme->a_toggled_focused_pressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_focused_pressed_max);
+ theme->a_toggled_focused_pressed_max
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ }
+ if (!read_appearance(db, inst, "window.inactive.button.toggled.pressed.bg",
+ theme->a_toggled_unfocused_pressed_max, TRUE)) {
+ RrAppearanceFree(theme->a_toggled_unfocused_pressed_max);
+ theme->a_toggled_unfocused_pressed_max
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ }
+ set_default_appearance(theme->a_focused_unpressed_max);
+ set_default_appearance(theme->a_unfocused_unpressed_max);
+ if (!read_appearance(db, inst, "window.active.button.hover.bg",
+ theme->a_hover_focused_max, TRUE)) {
+ RrAppearanceFree(theme->a_hover_focused_max);
+ theme->a_hover_focused_max
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ }
+ if (!read_appearance(db, inst, "window.inactive.button.hover.bg",
+ theme->a_hover_unfocused_max, TRUE)) {
+ RrAppearanceFree(theme->a_hover_unfocused_max);
+ theme->a_hover_unfocused_max
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ }
+
+ theme->a_disabled_focused_close
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_close
+ = RrAppearanceCopy(theme->a_disabled_unfocused_max);
+ theme->a_hover_focused_close = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_close
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_unfocused_unpressed_close
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_close
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_close
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_close
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ theme->a_disabled_focused_desk
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_desk
+ = RrAppearanceCopy(theme->a_disabled_unfocused_max);
+ theme->a_hover_focused_desk = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_desk
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_toggled_hover_focused_desk
+ = RrAppearanceCopy(theme->a_toggled_hover_focused_max);
+ theme->a_toggled_hover_unfocused_desk
+ = RrAppearanceCopy(theme->a_toggled_hover_unfocused_max);
+ theme->a_toggled_focused_unpressed_desk
+ = RrAppearanceCopy(theme->a_toggled_focused_unpressed_max);
+ theme->a_toggled_unfocused_unpressed_desk
+ = RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max);
+ theme->a_toggled_focused_pressed_desk
+ = RrAppearanceCopy(theme->a_toggled_focused_pressed_max);
+ theme->a_toggled_unfocused_pressed_desk
+ = RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max);
+ theme->a_unfocused_unpressed_desk
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_desk
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_desk
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_desk
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ theme->a_disabled_focused_shade
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_shade
+ = RrAppearanceCopy(theme->a_disabled_unfocused_max);
+ theme->a_hover_focused_shade = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_shade
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_toggled_hover_focused_shade
+ = RrAppearanceCopy(theme->a_toggled_hover_focused_max);
+ theme->a_toggled_hover_unfocused_shade
+ = RrAppearanceCopy(theme->a_toggled_hover_unfocused_max);
+ theme->a_toggled_focused_unpressed_shade
+ = RrAppearanceCopy(theme->a_toggled_focused_unpressed_max);
+ theme->a_toggled_unfocused_unpressed_shade
+ = RrAppearanceCopy(theme->a_toggled_unfocused_unpressed_max);
+ theme->a_toggled_focused_pressed_shade
+ = RrAppearanceCopy(theme->a_toggled_focused_pressed_max);
+ theme->a_toggled_unfocused_pressed_shade
+ = RrAppearanceCopy(theme->a_toggled_unfocused_pressed_max);
+ theme->a_unfocused_unpressed_shade
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_shade
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_shade
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_shade
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+ theme->a_disabled_focused_iconify
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_disabled_unfocused_iconify
+ = RrAppearanceCopy(theme->a_disabled_focused_max);
+ theme->a_hover_focused_iconify
+ = RrAppearanceCopy(theme->a_hover_focused_max);
+ theme->a_hover_unfocused_iconify
+ = RrAppearanceCopy(theme->a_hover_unfocused_max);
+ theme->a_unfocused_unpressed_iconify
+ = RrAppearanceCopy(theme->a_unfocused_unpressed_max);
+ theme->a_unfocused_pressed_iconify
+ = RrAppearanceCopy(theme->a_unfocused_pressed_max);
+ theme->a_focused_unpressed_iconify
+ = RrAppearanceCopy(theme->a_focused_unpressed_max);
+ theme->a_focused_pressed_iconify
+ = RrAppearanceCopy(theme->a_focused_pressed_max);
+
+ theme->a_icon->surface.grad
+ = theme->a_clear->surface.grad
+ = theme->a_clear_tex->surface.grad
+ = theme->a_menu_text_title->surface.grad
+ = theme->a_menu_normal->surface.grad
+ = theme->a_menu_disabled->surface.grad
+ = theme->a_menu_text_normal->surface.grad
+ = theme->a_menu_text_selected->surface.grad
+ = theme->a_menu_text_disabled->surface.grad
+ = theme->a_menu_text_disabled_selected->surface.grad
+ = theme->a_menu_bullet_normal->surface.grad
+ = theme->a_menu_bullet_selected->surface.grad
+ = RR_SURFACE_PARENTREL;
+
+ /* set up the textures */
+ theme->a_focused_label->texture[0].type = RR_TEXTURE_TEXT;
+ theme->a_focused_label->texture[0].data.text.justify = winjust;
+ theme->a_focused_label->texture[0].data.text.font=theme->win_font_focused;
+ theme->a_focused_label->texture[0].data.text.color
+ = theme->title_focused_color;
+
+ if (read_string(db, "window.active.label.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
+ theme->title_focused_shadow_alpha = i;
+ }
+ else {
+ theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->title_focused_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_focused_label->texture[0].data.text.shadow_color
+ = theme->title_focused_shadow_color;
+ theme->a_focused_label->texture[0].data.text.shadow_alpha
+ = theme->title_focused_shadow_alpha;
+
+ theme->osd_hilite_label->texture[0].type = RR_TEXTURE_TEXT;
+ theme->osd_hilite_label->texture[0].data.text.justify = RR_JUSTIFY_LEFT;
+ theme->osd_hilite_label->texture[0].data.text.font = theme->osd_font;
+ theme->osd_hilite_label->texture[0].data.text.color = theme->osd_color;
+
+ if (read_string(db, "osd.label.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_x = i;
+ theme->a_focused_label->texture[0].data.text.shadow_offset_y = i;
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_x = i;
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->title_focused_shadow_color = RrColorNew(inst, j, j, j);
+ theme->title_focused_shadow_alpha = i;
+ theme->osd_shadow_color = RrColorNew(inst, j, j, j);
+ theme->osd_shadow_alpha = i;
+ }
+ else {
+ theme->title_focused_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->title_focused_shadow_alpha = 50;
+ theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->osd_shadow_alpha = 50;
+ }
+ }
+ else {
+ /* inherit the font settings from the focused label */
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_x
+ = theme->a_focused_label->texture[0].data.text.shadow_offset_x;
+ theme->osd_hilite_label->texture[0].data.text.shadow_offset_y
+ = theme->a_focused_label->texture[0].data.text.shadow_offset_y;
+ if (theme->title_focused_shadow_color)
+ theme->osd_shadow_color = RrColorNew(inst,
+ theme->title_focused_shadow_color->r,
+ theme->title_focused_shadow_color->g,
+ theme->title_focused_shadow_color->b);
+ else
+ theme->osd_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->osd_shadow_alpha = theme->title_focused_shadow_alpha;
+ }
+
+ theme->osd_hilite_label->texture[0].data.text.shadow_color
+ = theme->osd_shadow_color;
+ theme->osd_hilite_label->texture[0].data.text.shadow_alpha
+ = theme->osd_shadow_alpha;
+
+ theme->a_unfocused_label->texture[0].type = RR_TEXTURE_TEXT;
+ theme->a_unfocused_label->texture[0].data.text.justify = winjust;
+ theme->a_unfocused_label->texture[0].data.text.font
+ = theme->win_font_unfocused;
+ theme->a_unfocused_label->texture[0].data.text.color
+ = theme->title_unfocused_color;
+
+ if (read_string(db, "window.inactive.label.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_unfocused_label->texture[0].data.text.shadow_offset_x = i;
+ theme->a_unfocused_label->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->title_unfocused_shadow_color = RrColorNew(inst, j, j, j);
+ theme->title_unfocused_shadow_alpha = i;
+ }
+ else {
+ theme->title_unfocused_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->title_unfocused_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_unfocused_label->texture[0].data.text.shadow_color
+ = theme->title_unfocused_shadow_color;
+ theme->a_unfocused_label->texture[0].data.text.shadow_alpha
+ = theme->title_unfocused_shadow_alpha;
+
+ theme->a_menu_text_title->texture[0].type = RR_TEXTURE_TEXT;
+ theme->a_menu_text_title->texture[0].data.text.justify = mtitlejust;
+ theme->a_menu_text_title->texture[0].data.text.font
+ = theme->menu_title_font;
+ theme->a_menu_text_title->texture[0].data.text.color
+ = theme->menu_title_color;
+
+ if (read_string(db, "menu.title.text.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_menu_text_title->texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_title->texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->menu_title_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_title_shadow_alpha = i;
+ }
+ else {
+ theme->menu_title_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_title_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_menu_text_title->texture[0].data.text.shadow_color
+ = theme->menu_title_shadow_color;
+ theme->a_menu_text_title->texture[0].data.text.shadow_alpha
+ = theme->menu_title_shadow_alpha;
+
+ theme->a_menu_text_normal->texture[0].type
+ = theme->a_menu_text_selected->texture[0].type
+ = theme->a_menu_text_disabled->texture[0].type
+ = theme->a_menu_text_disabled_selected->texture[0].type
+ = RR_TEXTURE_TEXT;
+ theme->a_menu_text_normal->texture[0].data.text.justify
+ = theme->a_menu_text_selected->texture[0].data.text.justify
+ = theme->a_menu_text_disabled->texture[0].data.text.justify
+ = theme->a_menu_text_disabled_selected->texture[0].data.text.justify
+ = RR_JUSTIFY_LEFT;
+ theme->a_menu_text_normal->texture[0].data.text.font
+ = theme->a_menu_text_selected->texture[0].data.text.font
+ = theme->a_menu_text_disabled->texture[0].data.text.font
+ = theme->a_menu_text_disabled_selected->texture[0].data.text.font
+ = theme->menu_font;
+ theme->a_menu_text_normal->texture[0].data.text.color = theme->menu_color;
+ theme->a_menu_text_selected->texture[0].data.text.color
+ = theme->menu_selected_color;
+ theme->a_menu_text_disabled->texture[0].data.text.color
+ = theme->menu_disabled_color;
+ theme->a_menu_text_disabled_selected->texture[0].data.text.color
+ = theme->menu_disabled_selected_color;
+
+ if (read_string(db, "menu.items.font", &str)) {
+ char *p;
+ gint i = 0;
+ gint j;
+ if (strstr(str, "shadow=y")) {
+ if ((p = strstr(str, "shadowoffset=")))
+ i = parse_inline_number(p + strlen("shadowoffset="));
+ else
+ i = 1;
+ theme->a_menu_text_normal->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_normal->
+ texture[0].data.text.shadow_offset_y = i;
+ theme->a_menu_text_selected->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_selected->
+ texture[0].data.text.shadow_offset_y = i;
+ theme->a_menu_text_disabled->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_disabled->
+ texture[0].data.text.shadow_offset_y = i;
+ theme->a_menu_text_disabled_selected->
+ texture[0].data.text.shadow_offset_x = i;
+ theme->a_menu_text_disabled_selected->
+ texture[0].data.text.shadow_offset_y = i;
+ }
+ if ((p = strstr(str, "shadowtint="))) {
+ i = parse_inline_number(p + strlen("shadowtint="));
+ j = (i > 0 ? 0 : 255);
+ i = ABS(i*255/100);
+
+ theme->menu_text_normal_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_text_selected_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_text_disabled_shadow_color = RrColorNew(inst, j, j, j);
+ theme->menu_text_normal_shadow_alpha = i;
+ theme->menu_text_selected_shadow_alpha = i;
+ theme->menu_text_disabled_shadow_alpha = i;
+ theme->menu_text_disabled_selected_shadow_alpha = i;
+ }
+ else {
+ theme->menu_text_normal_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_text_selected_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_text_disabled_shadow_color = RrColorNew(inst, 0, 0, 0);
+ theme->menu_text_normal_shadow_alpha = 50;
+ theme->menu_text_selected_shadow_alpha = 50;
+ theme->menu_text_disabled_selected_shadow_alpha = 50;
+ }
+ }
+
+ theme->a_menu_text_normal->texture[0].data.text.shadow_color
+ = theme->menu_text_normal_shadow_color;
+ theme->a_menu_text_normal->texture[0].data.text.shadow_alpha
+ = theme->menu_text_normal_shadow_alpha;
+ theme->a_menu_text_selected->texture[0].data.text.shadow_color
+ = theme->menu_text_selected_shadow_color;
+ theme->a_menu_text_selected->texture[0].data.text.shadow_alpha
+ = theme->menu_text_selected_shadow_alpha;
+ theme->a_menu_text_disabled->texture[0].data.text.shadow_color
+ = theme->menu_text_disabled_shadow_color;
+ theme->a_menu_text_disabled->texture[0].data.text.shadow_alpha
+ = theme->menu_text_disabled_shadow_alpha;
+ theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_color
+ = theme->menu_text_disabled_shadow_color;
+ theme->a_menu_text_disabled_selected->texture[0].data.text.shadow_alpha
+ = theme->menu_text_disabled_shadow_alpha;
+
+ theme->a_disabled_focused_max->texture[0].type
+ = theme->a_disabled_unfocused_max->texture[0].type
+ = theme->a_hover_focused_max->texture[0].type
+ = theme->a_hover_unfocused_max->texture[0].type
+ = theme->a_toggled_hover_focused_max->texture[0].type
+ = theme->a_toggled_hover_unfocused_max->texture[0].type
+ = theme->a_toggled_focused_unpressed_max->texture[0].type
+ = theme->a_toggled_unfocused_unpressed_max->texture[0].type
+ = theme->a_toggled_focused_pressed_max->texture[0].type
+ = theme->a_toggled_unfocused_pressed_max->texture[0].type
+ = theme->a_focused_unpressed_max->texture[0].type
+ = theme->a_focused_pressed_max->texture[0].type
+ = theme->a_unfocused_unpressed_max->texture[0].type
+ = theme->a_unfocused_pressed_max->texture[0].type
+ = theme->a_disabled_focused_close->texture[0].type
+ = theme->a_disabled_unfocused_close->texture[0].type
+ = theme->a_hover_focused_close->texture[0].type
+ = theme->a_hover_unfocused_close->texture[0].type
+ = theme->a_focused_unpressed_close->texture[0].type
+ = theme->a_focused_pressed_close->texture[0].type
+ = theme->a_unfocused_unpressed_close->texture[0].type
+ = theme->a_unfocused_pressed_close->texture[0].type
+ = theme->a_disabled_focused_desk->texture[0].type
+ = theme->a_disabled_unfocused_desk->texture[0].type
+ = theme->a_hover_focused_desk->texture[0].type
+ = theme->a_hover_unfocused_desk->texture[0].type
+ = theme->a_toggled_hover_focused_desk->texture[0].type
+ = theme->a_toggled_hover_unfocused_desk->texture[0].type
+ = theme->a_toggled_focused_unpressed_desk->texture[0].type
+ = theme->a_toggled_unfocused_unpressed_desk->texture[0].type
+ = theme->a_toggled_focused_pressed_desk->texture[0].type
+ = theme->a_toggled_unfocused_pressed_desk->texture[0].type
+ = theme->a_focused_unpressed_desk->texture[0].type
+ = theme->a_focused_pressed_desk->texture[0].type
+ = theme->a_unfocused_unpressed_desk->texture[0].type
+ = theme->a_unfocused_pressed_desk->texture[0].type
+ = theme->a_disabled_focused_shade->texture[0].type
+ = theme->a_disabled_unfocused_shade->texture[0].type
+ = theme->a_hover_focused_shade->texture[0].type
+ = theme->a_hover_unfocused_shade->texture[0].type
+ = theme->a_toggled_hover_focused_shade->texture[0].type
+ = theme->a_toggled_hover_unfocused_shade->texture[0].type
+ = theme->a_toggled_focused_unpressed_shade->texture[0].type
+ = theme->a_toggled_unfocused_unpressed_shade->texture[0].type
+ = theme->a_toggled_focused_pressed_shade->texture[0].type
+ = theme->a_toggled_unfocused_pressed_shade->texture[0].type
+ = theme->a_focused_unpressed_shade->texture[0].type
+ = theme->a_focused_pressed_shade->texture[0].type
+ = theme->a_unfocused_unpressed_shade->texture[0].type
+ = theme->a_unfocused_pressed_shade->texture[0].type
+ = theme->a_disabled_focused_iconify->texture[0].type
+ = theme->a_disabled_unfocused_iconify->texture[0].type
+ = theme->a_hover_focused_iconify->texture[0].type
+ = theme->a_hover_unfocused_iconify->texture[0].type
+ = theme->a_focused_unpressed_iconify->texture[0].type
+ = theme->a_focused_pressed_iconify->texture[0].type
+ = theme->a_unfocused_unpressed_iconify->texture[0].type
+ = theme->a_unfocused_pressed_iconify->texture[0].type
+ = theme->a_menu_bullet_normal->texture[0].type
+ = theme->a_menu_bullet_selected->texture[0].type
+ = RR_TEXTURE_MASK;
+
+ theme->a_disabled_focused_max->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_max->texture[0].data.mask.mask
+ = theme->max_disabled_mask;
+ theme->a_hover_focused_max->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_max->texture[0].data.mask.mask
+ = theme->max_hover_mask;
+ theme->a_focused_pressed_max->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_max->texture[0].data.mask.mask
+ = theme->max_pressed_mask;
+ theme->a_focused_unpressed_max->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_max->texture[0].data.mask.mask
+ = theme->max_mask;
+ theme->a_toggled_hover_focused_max->texture[0].data.mask.mask
+ = theme->a_toggled_hover_unfocused_max->texture[0].data.mask.mask
+ = theme->max_toggled_hover_mask;
+ theme->a_toggled_focused_unpressed_max->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.mask
+ = theme->max_toggled_mask;
+ theme->a_toggled_focused_pressed_max->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.mask
+ = theme->max_toggled_pressed_mask;
+ theme->a_disabled_focused_close->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_close->texture[0].data.mask.mask
+ = theme->close_disabled_mask;
+ theme->a_hover_focused_close->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_close->texture[0].data.mask.mask
+ = theme->close_hover_mask;
+ theme->a_focused_pressed_close->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_close->texture[0].data.mask.mask
+ = theme->close_pressed_mask;
+ theme->a_focused_unpressed_close->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_close->texture[0].data.mask.mask
+ = theme->close_mask;
+ theme->a_disabled_focused_desk->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_desk->texture[0].data.mask.mask
+ = theme->desk_disabled_mask;
+ theme->a_hover_focused_desk->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_desk->texture[0].data.mask.mask
+ = theme->desk_hover_mask;
+ theme->a_focused_pressed_desk->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_desk->texture[0].data.mask.mask
+ = theme->desk_pressed_mask;
+ theme->a_focused_unpressed_desk->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_desk->texture[0].data.mask.mask
+ = theme->desk_mask;
+ theme->a_toggled_hover_focused_desk->texture[0].data.mask.mask
+ = theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.mask
+ = theme->desk_toggled_hover_mask;
+ theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.mask
+ = theme->desk_toggled_mask;
+ theme->a_toggled_focused_pressed_desk->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.mask
+ = theme->desk_toggled_pressed_mask;
+ theme->a_disabled_focused_shade->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_shade->texture[0].data.mask.mask
+ = theme->shade_disabled_mask;
+ theme->a_hover_focused_shade->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_shade->texture[0].data.mask.mask
+ = theme->shade_hover_mask;
+ theme->a_focused_pressed_shade->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_shade->texture[0].data.mask.mask
+ = theme->shade_pressed_mask;
+ theme->a_focused_unpressed_shade->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_shade->texture[0].data.mask.mask
+ = theme->shade_mask;
+ theme->a_toggled_hover_focused_shade->texture[0].data.mask.mask
+ = theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.mask
+ = theme->shade_toggled_hover_mask;
+ theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.mask
+ = theme->shade_toggled_mask;
+ theme->a_toggled_focused_pressed_shade->texture[0].data.mask.mask
+ = theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.mask
+ = theme->shade_toggled_pressed_mask;
+ theme->a_disabled_focused_iconify->texture[0].data.mask.mask
+ = theme->a_disabled_unfocused_iconify->texture[0].data.mask.mask
+ = theme->iconify_disabled_mask;
+ theme->a_hover_focused_iconify->texture[0].data.mask.mask
+ = theme->a_hover_unfocused_iconify->texture[0].data.mask.mask
+ = theme->iconify_hover_mask;
+ theme->a_focused_pressed_iconify->texture[0].data.mask.mask
+ = theme->a_unfocused_pressed_iconify->texture[0].data.mask.mask
+ = theme->iconify_pressed_mask;
+ theme->a_focused_unpressed_iconify->texture[0].data.mask.mask
+ = theme->a_unfocused_unpressed_iconify->texture[0].data.mask.mask
+ = theme->iconify_mask;
+ theme->a_menu_bullet_normal->texture[0].data.mask.mask
+ = theme->a_menu_bullet_selected->texture[0].data.mask.mask
+ = theme->menu_bullet_mask;
+ theme->a_disabled_focused_max->texture[0].data.mask.color
+ = theme->a_disabled_focused_close->texture[0].data.mask.color
+ = theme->a_disabled_focused_desk->texture[0].data.mask.color
+ = theme->a_disabled_focused_shade->texture[0].data.mask.color
+ = theme->a_disabled_focused_iconify->texture[0].data.mask.color
+ = theme->titlebut_disabled_focused_color;
+ theme->a_disabled_unfocused_max->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_close->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_desk->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_shade->texture[0].data.mask.color
+ = theme->a_disabled_unfocused_iconify->texture[0].data.mask.color
+ = theme->titlebut_disabled_unfocused_color;
+ theme->a_hover_focused_max->texture[0].data.mask.color
+ = theme->a_hover_focused_close->texture[0].data.mask.color
+ = theme->a_hover_focused_desk->texture[0].data.mask.color
+ = theme->a_hover_focused_shade->texture[0].data.mask.color
+ = theme->a_hover_focused_iconify->texture[0].data.mask.color
+ = theme->titlebut_hover_focused_color;
+ theme->a_hover_unfocused_max->texture[0].data.mask.color
+ = theme->a_hover_unfocused_close->texture[0].data.mask.color
+ = theme->a_hover_unfocused_desk->texture[0].data.mask.color
+ = theme->a_hover_unfocused_shade->texture[0].data.mask.color
+ = theme->a_hover_unfocused_iconify->texture[0].data.mask.color
+ = theme->titlebut_hover_unfocused_color;
+ theme->a_toggled_hover_focused_max->texture[0].data.mask.color
+ = theme->a_toggled_hover_focused_desk->texture[0].data.mask.color
+ = theme->a_toggled_hover_focused_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_hover_focused_color;
+ theme->a_toggled_hover_unfocused_max->texture[0].data.mask.color
+ = theme->a_toggled_hover_unfocused_desk->texture[0].data.mask.color
+ = theme->a_toggled_hover_unfocused_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_hover_unfocused_color;
+ theme->a_toggled_focused_unpressed_max->texture[0].data.mask.color
+ = theme->a_toggled_focused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_focused_unpressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_focused_unpressed_color;
+ theme->a_toggled_unfocused_unpressed_max->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_unpressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_unfocused_unpressed_color;
+ theme->a_toggled_focused_pressed_max->texture[0].data.mask.color
+ = theme->a_toggled_focused_pressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_focused_pressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_focused_pressed_color;
+ theme->a_toggled_unfocused_pressed_max->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_pressed_desk->texture[0].data.mask.color
+ = theme->a_toggled_unfocused_pressed_shade->texture[0].data.mask.color
+ = theme->titlebut_toggled_unfocused_pressed_color;
+ theme->a_focused_unpressed_max->texture[0].data.mask.color
+ = theme->a_focused_unpressed_close->texture[0].data.mask.color
+ = theme->a_focused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_focused_unpressed_shade->texture[0].data.mask.color
+ = theme->a_focused_unpressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_focused_unpressed_color;
+ theme->a_focused_pressed_max->texture[0].data.mask.color
+ = theme->a_focused_pressed_close->texture[0].data.mask.color
+ = theme->a_focused_pressed_desk->texture[0].data.mask.color
+ = theme->a_focused_pressed_shade->texture[0].data.mask.color
+ = theme->a_focused_pressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_focused_pressed_color;
+ theme->a_unfocused_unpressed_max->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_close->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_desk->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_shade->texture[0].data.mask.color
+ = theme->a_unfocused_unpressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_unfocused_unpressed_color;
+ theme->a_unfocused_pressed_max->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_close->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_desk->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_shade->texture[0].data.mask.color
+ = theme->a_unfocused_pressed_iconify->texture[0].data.mask.color
+ = theme->titlebut_unfocused_pressed_color;
+ theme->a_menu_bullet_normal->texture[0].data.mask.color = theme->menu_color;
+ theme->a_menu_bullet_selected->texture[0].data.mask.color
+ = theme->menu_selected_color;
+
+ /* set the font heights */
+ theme->win_font_height = RrFontHeight(theme->win_font_focused,
+ theme->a_focused_label->texture[0].data.text.shadow_offset_y);
+ theme->win_font_height = MAX(theme->win_font_height, RrFontHeight(
+ theme->win_font_focused,
+ theme->a_unfocused_label->texture[0].data.text.shadow_offset_y));
+ theme->menu_title_font_height = RrFontHeight(theme->menu_title_font,
+ theme->a_menu_text_title->texture[0].data.text.shadow_offset_y);
+ theme->menu_font_height = RrFontHeight(theme->menu_font,
+ theme->a_menu_text_normal->texture[0].data.text.shadow_offset_y);
+
+ /* calculate some last extents */
+ {
+ gint ft, fb, fl, fr, ut, ub, ul, ur;
+
+ RrMargins(theme->a_focused_label, &fl, &ft, &fr, &fb);
+ RrMargins(theme->a_unfocused_label, &ul, &ut, &ur, &ub);
+ theme->label_height = theme->win_font_height + MAX(ft + fb, ut + ub);
+ theme->label_height += theme->label_height % 2;
+
+ /* this would be nice I think, since padding.width can now be 0,
+ but it breaks frame.c horribly and I don't feel like fixing that
+ right now, so if anyone complains, here is how to keep text from
+ going over the title's bevel/border with a padding.width of 0 and a
+ bevelless/borderless label
+ RrMargins(theme->a_focused_title, &fl, &ft, &fr, &fb);
+ RrMargins(theme->a_unfocused_title, &ul, &ut, &ur, &ub);
+ theme->title_height = theme->label_height +
+ MAX(MAX(theme->padding * 2, ft + fb),
+ MAX(theme->padding * 2, ut + ub));
+ */
+ theme->title_height = theme->label_height + theme->paddingy * 2;
+
+ RrMargins(theme->a_menu_title, &ul, &ut, &ur, &ub);
+ theme->menu_title_label_height = theme->menu_title_font_height+ut+ub;
+ theme->menu_title_height = theme->menu_title_label_height
+ + theme->paddingy * 2;
+ }
+ theme->button_size = theme->label_height - 2;
+ theme->grip_width = 25;
+
+ return 1;
+}
+
+static XrmDatabase loaddb(const gchar *name, gchar **path)
+{
+ GSList *it;
+ XrmDatabase db = NULL;
+ gchar *s;
+
+ if (name[0] == '/') {
+ s = g_build_filename(name, "openbox-3", "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+ else {
+ /* XXX backwards compatibility, remove me sometime later */
+ s = g_build_filename(g_get_home_dir(), ".themes", name, "openbox-3",
+ "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+
+ for (it = parse_xdg_data_dir_paths(); !db && it; it = g_slist_next(it)) {
+ s = g_build_filename(it->data, "themes", name, "openbox-3",
+ "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+ }
+
+ if (db == NULL) {
+ s = g_build_filename(name, "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+
+ return db;
+}
+
+static gchar *create_class_name(const gchar *rname)
+{
+ gchar *rclass = g_strdup(rname);
+ gchar *p = rclass;
+
+ while (TRUE) {
+ *p = toupper(*p);
+ p = strchr(p+1, '.');
+ if (p == NULL)
+ break;
+ ++p;
+ if (*p == '\0')
+ break;
+ }
+ return rclass;
+}
+
+static gboolean read_int(XrmDatabase db, const gchar *rname, gint *value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype, *end;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = (gint)strtol(retvalue.addr, &end, 10);
+ if (end != retvalue.addr)
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = retvalue.addr;
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_color(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrColor **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ RrColor *c = RrColorParse(inst, retvalue.addr);
+ if (c != NULL) {
+ *value = c;
+ ret = TRUE;
+ }
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+static gboolean read_mask(const RrInstance *inst, const gchar *path,
+ ObFrameThemeConfig *theme, const gchar *maskname, RrPixmapMask **value)
+{
+ gboolean ret = FALSE;
+ gchar *s;
+ gint hx, hy; /* ignored */
+ guint w, h;
+ guchar *b;
+
+ s = g_build_filename(path, maskname, NULL);
+ if (XReadBitmapFileData(s, &w, &h, &b, &hx, &hy) == BitmapSuccess) {
+ ret = TRUE;
+ *value = RrPixmapMaskNew(inst, w, h, (gchar*)b);
+ XFree(b);
+ }
+ g_free(s);
+
+ return ret;
+}
+
+static void parse_appearance(gchar *tex, RrSurfaceColorType *grad,
+ RrReliefType *relief, RrBevelType *bevel, gboolean *interlaced,
+ gboolean *border, gboolean allow_trans)
+{
+ gchar *t;
+
+ /* convert to all lowercase */
+ for (t = tex; *t != '\0'; ++t)
+ *t = g_ascii_tolower(*t);
+
+ if (allow_trans && strstr(tex, "parentrelative") != NULL) {
+ *grad = RR_SURFACE_PARENTREL;
+ }
+ else {
+ if (strstr(tex, "gradient") != NULL) {
+ if (strstr(tex, "crossdiagonal") != NULL)
+ *grad = RR_SURFACE_CROSS_DIAGONAL;
+ else if (strstr(tex, "pyramid") != NULL)
+ *grad = RR_SURFACE_PYRAMID;
+ else if (strstr(tex, "mirrorhorizontal") != NULL)
+ *grad = RR_SURFACE_MIRROR_HORIZONTAL;
+ else if (strstr(tex, "horizontal") != NULL)
+ *grad = RR_SURFACE_HORIZONTAL;
+ else if (strstr(tex, "splitvertical") != NULL)
+ *grad = RR_SURFACE_SPLIT_VERTICAL;
+ else if (strstr(tex, "vertical") != NULL)
+ *grad = RR_SURFACE_VERTICAL;
+ else
+ *grad = RR_SURFACE_DIAGONAL;
+ }
+ else {
+ *grad = RR_SURFACE_SOLID;
+ }
+ }
+
+ if (strstr(tex, "sunken") != NULL)
+ *relief = RR_RELIEF_SUNKEN;
+ else if (strstr(tex, "flat") != NULL)
+ *relief = RR_RELIEF_FLAT;
+ else if (strstr(tex, "raised") != NULL)
+ *relief = RR_RELIEF_RAISED;
+ else
+ *relief = (*grad == RR_SURFACE_PARENTREL) ? RR_RELIEF_FLAT
+ : RR_RELIEF_RAISED;
+
+ *border = FALSE;
+ if (*relief == RR_RELIEF_FLAT) {
+ if (strstr(tex, "border") != NULL)
+ *border = TRUE;
+ }
+ else {
+ if (strstr(tex, "bevel2") != NULL)
+ *bevel = RR_BEVEL_2;
+ else
+ *bevel = RR_BEVEL_1;
+ }
+
+ if (strstr(tex, "interlaced") != NULL)
+ *interlaced = TRUE;
+ else
+ *interlaced = FALSE;
+}
+
+static gboolean read_appearance(XrmDatabase db, const RrInstance *inst,
+ const gchar *rname, RrAppearance *value, gboolean allow_trans)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *cname, *ctoname, *bcname, *icname, *hname, *sname;
+ gchar *csplitname, *ctosplitname;
+ gchar *rettype;
+ XrmValue retvalue;
+ gint i;
+
+ cname = g_strconcat(rname, ".color", NULL);
+ ctoname = g_strconcat(rname, ".colorTo", NULL);
+ bcname = g_strconcat(rname, ".border.color", NULL);
+ icname = g_strconcat(rname, ".interlace.color", NULL);
+ hname = g_strconcat(rname, ".highlight", NULL);
+ sname = g_strconcat(rname, ".shadow", NULL);
+ csplitname = g_strconcat(rname, ".color.splitTo", NULL);
+ ctosplitname = g_strconcat(rname, ".colorTo.splitTo", NULL);
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ parse_appearance(retvalue.addr, &value->surface.grad,
+ &value->surface.relief, &value->surface.bevel,
+ &value->surface.interlaced, &value->surface.border, allow_trans);
+ if (!read_color(db, inst, cname, &value->surface.primary))
+ value->surface.primary = RrColorNew(inst, 0, 0, 0);
+ if (!read_color(db, inst, ctoname, &value->surface.secondary))
+ value->surface.secondary = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.border)
+ if (!read_color(db, inst, bcname, &value->surface.border_color))
+ value->surface.border_color = RrColorNew(inst, 0, 0, 0);
+ if (value->surface.interlaced)
+ if (!read_color(db, inst, icname, &value->surface.interlace_color))
+ value->surface.interlace_color = RrColorNew(inst, 0, 0, 0);
+ if (read_int(db, hname, &i) && i >= 0)
+ value->surface.bevel_light_adjust = i;
+ if (read_int(db, sname, &i) && i >= 0 && i <= 256)
+ value->surface.bevel_dark_adjust = i;
+
+ if (value->surface.grad == RR_SURFACE_SPLIT_VERTICAL) {
+ gint r, g, b;
+
+ if (!read_color(db, inst, csplitname, &value->surface.split_primary)) {
+ r = value->surface.primary->r;
+ r += r >> 2;
+ g = value->surface.primary->g;
+ g += g >> 2;
+ b = value->surface.primary->b;
+ b += b >> 2;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_primary = RrColorNew(inst, r, g, b);
+ }
+
+ if (!read_color(db, inst, ctosplitname,
+ &value->surface.split_secondary)) {
+ r = value->surface.secondary->r;
+ r += r >> 4;
+ g = value->surface.secondary->g;
+ g += g >> 4;
+ b = value->surface.secondary->b;
+ b += b >> 4;
+ if (r > 0xFF)
+ r = 0xFF;
+ if (g > 0xFF)
+ g = 0xFF;
+ if (b > 0xFF)
+ b = 0xFF;
+ value->surface.split_secondary = RrColorNew(inst, r, g, b);
+ }
+ }
+
+ ret = TRUE;
+ }
+
+ g_free(ctosplitname);
+ g_free(csplitname);
+ g_free(sname);
+ g_free(hname);
+ g_free(icname);
+ g_free(bcname);
+ g_free(ctoname);
+ g_free(cname);
+ g_free(rclass);
+ return ret;
+}
+
+static int parse_inline_number(const char *p)
+{
+ int neg = 1;
+ int res = 0;
+ if (*p == '-') {
+ neg = -1;
+ ++p;
+ }
+ for (; isdigit(*p); ++p)
+ res = res * 10 + *p - '0';
+ res *= neg;
+ return res;
+}
+
+static void set_default_appearance(RrAppearance *a)
+{
+ a->surface.grad = RR_SURFACE_SOLID;
+ a->surface.relief = RR_RELIEF_FLAT;
+ a->surface.bevel = RR_BEVEL_1;
+ a->surface.interlaced = FALSE;
+ a->surface.border = FALSE;
+ a->surface.primary = RrColorNew(a->inst, 0, 0, 0);
+ a->surface.secondary = RrColorNew(a->inst, 0, 0, 0);
+}
+
+/* Reads the output from gimp's C-Source file format into valid RGBA data for
+ an RrTextureRGBA. */
+static RrPixel32* read_c_image(gint width, gint height, const guint8 *data)
+{
+ RrPixel32 *im, *p;
+ gint i;
+
+ p = im = g_memdup(data, width * height * sizeof(RrPixel32));
+
+ for (i = 0; i < width * height; ++i) {
+ guchar a = ((*p >> 24) & 0xff);
+ guchar b = ((*p >> 16) & 0xff);
+ guchar g = ((*p >> 8) & 0xff);
+ guchar r = ((*p >> 0) & 0xff);
+
+ *p = ((r << RrDefaultRedOffset) + (g << RrDefaultGreenOffset) + (b
+ << RrDefaultBlueOffset) + (a << RrDefaultAlphaOffset));
+ p++;
+ }
+
+ return im;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_minimal_config.h for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_MINIMAL_CONFIG_H_
+#define FRAME_MINIMAL_CONFIG_H_
+
+#include <X11/Xresource.h>
+#include "render/render.h"
+
+G_BEGIN_DECLS
+
+/* This store frame layout configuration. */
+struct _ObFrameThemeConfig
+{
+ const RrInstance *inst;
+
+ /* style settings - fonts */
+ RrFont *win_font_focused;
+ RrFont *win_font_unfocused;
+ RrFont *menu_title_font;
+ RrFont *menu_font;
+ RrFont *osd_font;
+
+ /* style settings - geometry */
+ gint paddingx;
+ gint paddingy;
+ gint handle_height;
+ gint fbwidth; /*!< frame border width */
+ gint mbwidth; /*!< menu border width */
+ gint obwidth; /*!< osd border width */
+ gint cbwidthx;
+ gint cbwidthy;
+ gint menu_overlap;
+ /* these ones are calculated, not set directly by the theme file */
+ gint win_font_height;
+ gint menu_title_font_height;
+ gint menu_font_height;
+ gint label_height;
+ gint title_height;
+ gint button_size;
+ gint grip_width;
+ gint menu_title_label_height;
+ gint menu_title_height;
+
+ /* style settings - colors */
+ RrColor *menu_border_color;
+ RrColor *osd_border_color;
+ RrColor *frame_focused_border_color;
+ RrColor *frame_unfocused_border_color;
+ RrColor *title_separator_focused_color;
+ RrColor *title_separator_unfocused_color;
+ RrColor *cb_focused_color;
+ RrColor *cb_unfocused_color;
+ RrColor *title_focused_color;
+ RrColor *title_unfocused_color;
+ RrColor *titlebut_disabled_focused_color;
+ RrColor *titlebut_disabled_unfocused_color;
+ RrColor *titlebut_hover_focused_color;
+ RrColor *titlebut_hover_unfocused_color;
+ RrColor *titlebut_toggled_hover_focused_color;
+ RrColor *titlebut_toggled_hover_unfocused_color;
+ RrColor *titlebut_toggled_focused_pressed_color;
+ RrColor *titlebut_toggled_unfocused_pressed_color;
+ RrColor *titlebut_toggled_focused_unpressed_color;
+ RrColor *titlebut_toggled_unfocused_unpressed_color;
+ RrColor *titlebut_focused_pressed_color;
+ RrColor *titlebut_unfocused_pressed_color;
+ RrColor *titlebut_focused_unpressed_color;
+ RrColor *titlebut_unfocused_unpressed_color;
+ RrColor *menu_title_color;
+ RrColor *menu_color;
+ RrColor *menu_selected_color;
+ RrColor *menu_disabled_color;
+ RrColor *menu_disabled_selected_color;
+ RrColor *title_focused_shadow_color;
+ gchar title_focused_shadow_alpha;
+ RrColor *title_unfocused_shadow_color;
+ gchar title_unfocused_shadow_alpha;
+ RrColor *osd_color;
+ RrColor *osd_shadow_color;
+ gchar osd_shadow_alpha;
+ RrColor *menu_title_shadow_color;
+ gchar menu_title_shadow_alpha;
+ RrColor *menu_text_normal_shadow_color;
+ gchar menu_text_normal_shadow_alpha;
+ RrColor *menu_text_selected_shadow_color;
+ gchar menu_text_selected_shadow_alpha;
+ RrColor *menu_text_disabled_shadow_color;
+ gchar menu_text_disabled_shadow_alpha;
+ RrColor *menu_text_disabled_selected_shadow_color;
+ gchar menu_text_disabled_selected_shadow_alpha;
+
+ /* style settings - pics */
+ RrPixel32 *def_win_icon; /* 48x48 RGBA */
+
+ /* style settings - masks */
+ RrPixmapMask *max_mask;
+ RrPixmapMask *max_hover_mask;
+ RrPixmapMask *max_pressed_mask;
+ RrPixmapMask *max_toggled_mask;
+ RrPixmapMask *max_toggled_hover_mask;
+ RrPixmapMask *max_toggled_pressed_mask;
+ RrPixmapMask *max_disabled_mask;
+ RrPixmapMask *iconify_mask;
+ RrPixmapMask *iconify_hover_mask;
+ RrPixmapMask *iconify_pressed_mask;
+ RrPixmapMask *iconify_disabled_mask;
+ RrPixmapMask *desk_mask;
+ RrPixmapMask *desk_hover_mask;
+ RrPixmapMask *desk_pressed_mask;
+ RrPixmapMask *desk_toggled_mask;
+ RrPixmapMask *desk_toggled_hover_mask;
+ RrPixmapMask *desk_toggled_pressed_mask;
+ RrPixmapMask *desk_disabled_mask;
+ RrPixmapMask *shade_mask;
+ RrPixmapMask *shade_hover_mask;
+ RrPixmapMask *shade_pressed_mask;
+ RrPixmapMask *shade_toggled_mask;
+ RrPixmapMask *shade_toggled_hover_mask;
+ RrPixmapMask *shade_toggled_pressed_mask;
+ RrPixmapMask *shade_disabled_mask;
+ RrPixmapMask *close_mask;
+ RrPixmapMask *close_hover_mask;
+ RrPixmapMask *close_disabled_mask;
+ RrPixmapMask *close_pressed_mask;
+
+ RrPixmapMask *menu_bullet_mask; /* submenu pointer */
+#if 0
+ RrPixmapMask *menu_toggle_mask; /* menu boolean */
+#endif
+
+ /* global appearances */
+ RrAppearance *a_disabled_focused_max;
+ RrAppearance *a_disabled_unfocused_max;
+ RrAppearance *a_hover_focused_max;
+ RrAppearance *a_hover_unfocused_max;
+ RrAppearance *a_focused_unpressed_max;
+ RrAppearance *a_focused_pressed_max;
+ RrAppearance *a_unfocused_unpressed_max;
+ RrAppearance *a_unfocused_pressed_max;
+ RrAppearance *a_toggled_hover_focused_max;
+ RrAppearance *a_toggled_hover_unfocused_max;
+ RrAppearance *a_toggled_focused_unpressed_max;
+ RrAppearance *a_toggled_focused_pressed_max;
+ RrAppearance *a_toggled_unfocused_unpressed_max;
+ RrAppearance *a_toggled_unfocused_pressed_max;
+ RrAppearance *a_disabled_focused_close;
+ RrAppearance *a_disabled_unfocused_close;
+ RrAppearance *a_hover_focused_close;
+ RrAppearance *a_hover_unfocused_close;
+ RrAppearance *a_focused_unpressed_close;
+ RrAppearance *a_focused_pressed_close;
+ RrAppearance *a_unfocused_unpressed_close;
+ RrAppearance *a_unfocused_pressed_close;
+ RrAppearance *a_disabled_focused_desk;
+ RrAppearance *a_disabled_unfocused_desk;
+ RrAppearance *a_hover_focused_desk;
+ RrAppearance *a_hover_unfocused_desk;
+ RrAppearance *a_focused_unpressed_desk;
+ RrAppearance *a_focused_pressed_desk;
+ RrAppearance *a_unfocused_unpressed_desk;
+ RrAppearance *a_unfocused_pressed_desk;
+ RrAppearance *a_toggled_hover_focused_desk;
+ RrAppearance *a_toggled_hover_unfocused_desk;
+ RrAppearance *a_toggled_focused_unpressed_desk;
+ RrAppearance *a_toggled_focused_pressed_desk;
+ RrAppearance *a_toggled_unfocused_unpressed_desk;
+ RrAppearance *a_toggled_unfocused_pressed_desk;
+ RrAppearance *a_disabled_focused_shade;
+ RrAppearance *a_disabled_unfocused_shade;
+ RrAppearance *a_hover_focused_shade;
+ RrAppearance *a_hover_unfocused_shade;
+ RrAppearance *a_focused_unpressed_shade;
+ RrAppearance *a_focused_pressed_shade;
+ RrAppearance *a_unfocused_unpressed_shade;
+ RrAppearance *a_unfocused_pressed_shade;
+ RrAppearance *a_toggled_hover_focused_shade;
+ RrAppearance *a_toggled_hover_unfocused_shade;
+ RrAppearance *a_toggled_focused_unpressed_shade;
+ RrAppearance *a_toggled_focused_pressed_shade;
+ RrAppearance *a_toggled_unfocused_unpressed_shade;
+ RrAppearance *a_toggled_unfocused_pressed_shade;
+ RrAppearance *a_disabled_focused_iconify;
+ RrAppearance *a_disabled_unfocused_iconify;
+ RrAppearance *a_hover_focused_iconify;
+ RrAppearance *a_hover_unfocused_iconify;
+ RrAppearance *a_focused_unpressed_iconify;
+ RrAppearance *a_focused_pressed_iconify;
+ RrAppearance *a_unfocused_unpressed_iconify;
+ RrAppearance *a_unfocused_pressed_iconify;
+ RrAppearance *a_focused_grip;
+ RrAppearance *a_unfocused_grip;
+ RrAppearance *a_focused_title;
+ RrAppearance *a_unfocused_title;
+ RrAppearance *a_focused_label;
+ RrAppearance *a_unfocused_label;
+ /* always parentrelative, so no focused/unfocused */
+ RrAppearance *a_icon;
+ RrAppearance *a_focused_handle;
+ RrAppearance *a_unfocused_handle;
+ RrAppearance *a_menu_text_title;
+ RrAppearance *a_menu_title;
+ RrAppearance *a_menu;
+ RrAppearance *a_menu_normal;
+ RrAppearance *a_menu_selected;
+ RrAppearance *a_menu_disabled;
+ RrAppearance *a_menu_disabled_selected;
+ RrAppearance *a_menu_text_normal;
+ RrAppearance *a_menu_text_disabled;
+ RrAppearance *a_menu_text_disabled_selected;
+ RrAppearance *a_menu_text_selected;
+ RrAppearance *a_menu_bullet_normal;
+ RrAppearance *a_menu_bullet_selected;
+ RrAppearance *a_clear; /* clear with no texture */
+ RrAppearance *a_clear_tex; /* clear with a texture */
+
+ RrAppearance *osd_hilite_bg; /* can never be parent relative */
+ RrAppearance *osd_hilite_fg; /* can never be parent relative */
+ RrAppearance *osd_hilite_label; /* can be parent relative */
+ RrAppearance *osd_unhilite_fg; /* can never be parent relative */
+
+ gchar *name;
+};
+
+typedef struct _ObFrameThemeConfig ObFrameThemeConfig;
+
+/*! The font values are all optional. If a NULL is used for any of them, then
+ the default font will be used. */
+gint load_theme_config(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font);
+
+G_END_DECLS
+
+#endif /*FRAME_MINIMAL_CONFIG_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_minimal_plugin.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "frame_minimal_plugin.h"
+#include "frame_minimal_render.h"
+
+#include "openbox/frame.h"
+#include "openbox/client.h"
+#include "openbox/openbox.h"
+#include "openbox/extensions.h"
+#include "openbox/prop.h"
+#include "openbox/grab.h"
+#include "openbox/config.h"
+#include "openbox/mainloop.h"
+#include "openbox/focus_cycle.h"
+#include "openbox/focus_cycle_indicator.h"
+#include "openbox/moveresize.h"
+#include "openbox/screen.h"
+#include "render/theme.h"
+
+typedef enum
+{
+ OB_FLAG_MAX = 1 << 0,
+ OB_FLAG_CLOSE = 1 << 1,
+ OB_FLAG_DESK = 1 << 2,
+ OB_FLAG_SHADE = 1 << 3,
+ OB_FLAG_ICONIFY = 1 << 4
+} ObFrameFlags;
+
+#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
+ ButtonPressMask | ButtonReleaseMask | \
+ SubstructureRedirectMask | FocusChangeMask)
+#define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
+ ButtonMotionMask | PointerMotionMask | \
+ EnterWindowMask | LeaveWindowMask)
+
+#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
+#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
+
+#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b)
+
+Window createWindow(Window parent, Visual *visual, gulong mask,
+ XSetWindowAttributes *attrib)
+{
+ return XCreateWindow(plugin.ob_display, parent, 0, 0, 1, 1, 0, (visual ? 32
+ : RrDepth(plugin.ob_rr_inst)), InputOutput, (visual ? visual
+ : RrVisual(plugin.ob_rr_inst)), mask, attrib);
+
+}
+
+Visual *check_32bit_client(ObClient *c)
+{
+ XWindowAttributes wattrib;
+ Status ret;
+
+ /* we're already running at 32 bit depth, yay. we don't need to use their
+ visual */
+ if (RrDepth(plugin.ob_rr_inst) == 32)
+ return NULL;
+
+ ret = XGetWindowAttributes(plugin.ob_display, c->window, &wattrib);
+ g_assert(ret != BadDrawable);
+ g_assert(ret != BadWindow);
+
+ if (wattrib.depth == 32)
+ return wattrib.visual;
+ return NULL;
+}
+
+/* Not used */
+gint init(Display * display, gint screen)
+{
+ plugin.ob_display = display;
+ plugin.ob_screen = screen;
+}
+
+/* init a new frame */
+gpointer frame_new(struct _ObClient * client)
+{
+ XSetWindowAttributes attrib;
+ gulong mask;
+ ObDefaultFrame *self;
+ Visual *visual;
+
+ self = g_new0(ObDefaultFrame, 1);
+ self->client = client;
+
+ visual = check_32bit_client(client);
+
+ /* create the non-visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ /* create a colormap with the visual */
+ OBDEFAULTFRAME(self)->colormap = attrib.colormap = XCreateColormap(
+ plugin.ob_display, RootWindow(plugin.ob_display,
+ plugin.ob_screen), visual, AllocNone);
+ attrib.background_pixel = BlackPixel(plugin.ob_display,
+ plugin.ob_screen);
+ attrib.border_pixel = BlackPixel(plugin.ob_display, plugin.ob_screen);
+ }
+ self->window = createWindow(
+ RootWindow(plugin.ob_display, plugin.ob_screen), visual, mask,
+ &attrib);
+
+ /* create the visible decor windows */
+
+ mask = 0;
+ if (visual) {
+ /* client has a 32-bit visual */
+ mask |= CWColormap | CWBackPixel | CWBorderPixel;
+ attrib.colormap = RrColormap(plugin.ob_rr_inst);
+ }
+
+ self->backback = createWindow(self->window, NULL, mask, &attrib);
+ self->backfront = createWindow(self->backback, NULL, mask, &attrib);
+
+ mask |= CWEventMask;
+ attrib.event_mask = ELEMENT_EVENTMASK;
+ self->innerleft = createWindow(self->window, NULL, mask, &attrib);
+ self->innertop = createWindow(self->window, NULL, mask, &attrib);
+ self->innerright = createWindow(self->window, NULL, mask, &attrib);
+ self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
+
+ self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib);
+ self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib);
+ self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib);
+ self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib);
+
+ self->title = createWindow(self->window, NULL, mask, &attrib);
+ self->titleleft = createWindow(self->window, NULL, mask, &attrib);
+ self->titletop = createWindow(self->window, NULL, mask, &attrib);
+ self->titletopleft = createWindow(self->window, NULL, mask, &attrib);
+ self->titletopright = createWindow(self->window, NULL, mask, &attrib);
+ self->titleright = createWindow(self->window, NULL, mask, &attrib);
+ self->titlebottom = createWindow(self->window, NULL, mask, &attrib);
+
+ self->topresize = createWindow(self->title, NULL, mask, &attrib);
+ self->tltresize = createWindow(self->title, NULL, mask, &attrib);
+ self->tllresize = createWindow(self->title, NULL, mask, &attrib);
+ self->trtresize = createWindow(self->title, NULL, mask, &attrib);
+ self->trrresize = createWindow(self->title, NULL, mask, &attrib);
+
+ self->left = createWindow(self->window, NULL, mask, &attrib);
+ self->right = createWindow(self->window, NULL, mask, &attrib);
+
+ self->label = createWindow(self->title, NULL, mask, &attrib);
+ self->max = createWindow(self->title, NULL, mask, &attrib);
+ self->close = createWindow(self->title, NULL, mask, &attrib);
+ self->desk = createWindow(self->title, NULL, mask, &attrib);
+ self->shade = createWindow(self->title, NULL, mask, &attrib);
+ self->icon = createWindow(self->title, NULL, mask, &attrib);
+ self->iconify = createWindow(self->title, NULL, mask, &attrib);
+
+ self->handle = createWindow(self->window, NULL, mask, &attrib);
+ self->lgrip = createWindow(self->handle, NULL, mask, &attrib);
+ self->rgrip = createWindow(self->handle, NULL, mask, &attrib);
+
+ self->handleleft = createWindow(self->handle, NULL, mask, &attrib);
+ self->handleright = createWindow(self->handle, NULL, mask, &attrib);
+
+ self->handletop = createWindow(self->window, NULL, mask, &attrib);
+ self->handlebottom = createWindow(self->window, NULL, mask, &attrib);
+ self->lgripleft = createWindow(self->window, NULL, mask, &attrib);
+ self->lgriptop = createWindow(self->window, NULL, mask, &attrib);
+ self->lgripbottom = createWindow(self->window, NULL, mask, &attrib);
+ self->rgripright = createWindow(self->window, NULL, mask, &attrib);
+ self->rgriptop = createWindow(self->window, NULL, mask, &attrib);
+ self->rgripbottom = createWindow(self->window, NULL, mask, &attrib);
+
+ self->focused = FALSE;
+
+ /* the other stuff is shown based on decor settings */
+ XMapWindow(plugin.ob_display, self->label);
+ XMapWindow(plugin.ob_display, self->backback);
+ XMapWindow(plugin.ob_display, self->backfront);
+
+ self->max_press = self->close_press = self->desk_press
+ = self->iconify_press = self->shade_press = FALSE;
+ self->max_hover = self->close_hover = self->desk_hover
+ = self->iconify_hover = self->shade_hover = FALSE;
+
+ set_theme_statics(self);
+
+ return (ObFrame*)self;
+}
+
+void set_theme_statics(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* set colors/appearance/sizes for stuff that doesn't change */
+ XResizeWindow(plugin.ob_display, self->max, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->iconify, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->icon, theme_config.button_size + 2,
+ theme_config.button_size + 2);
+ XResizeWindow(plugin.ob_display, self->close, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->desk, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->shade, theme_config.button_size,
+ theme_config.button_size);
+ XResizeWindow(plugin.ob_display, self->tltresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+ XResizeWindow(plugin.ob_display, self->trtresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+ XResizeWindow(plugin.ob_display, self->tllresize,
+ theme_config.paddingx + 1, theme_config.title_height);
+ XResizeWindow(plugin.ob_display, self->trrresize,
+ theme_config.paddingx + 1, theme_config.title_height);
+
+ /* set up the dynamic appearances */
+ self->a_unfocused_title = RrAppearanceCopy(theme_config.a_unfocused_title);
+ self->a_focused_title = RrAppearanceCopy(theme_config.a_focused_title);
+ self->a_unfocused_label = RrAppearanceCopy(theme_config.a_unfocused_label);
+ self->a_focused_label = RrAppearanceCopy(theme_config.a_focused_label);
+ self->a_unfocused_handle
+ = RrAppearanceCopy(theme_config.a_unfocused_handle);
+ self->a_focused_handle = RrAppearanceCopy(theme_config.a_focused_handle);
+ self->a_icon = RrAppearanceCopy(theme_config.a_icon);
+}
+
+void free_theme_statics(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ RrAppearanceFree(self->a_unfocused_title);
+ RrAppearanceFree(self->a_focused_title);
+ RrAppearanceFree(self->a_unfocused_label);
+ RrAppearanceFree(self->a_focused_label);
+ RrAppearanceFree(self->a_unfocused_handle);
+ RrAppearanceFree(self->a_focused_handle);
+ RrAppearanceFree(self->a_icon);
+}
+
+void frame_free(gpointer self)
+{
+ free_theme_statics(OBDEFAULTFRAME(self));
+ XDestroyWindow(plugin.ob_display, OBDEFAULTFRAME(self)->window);
+ if (OBDEFAULTFRAME(self)->colormap)
+ XFreeColormap(plugin.ob_display, OBDEFAULTFRAME(self)->colormap);
+ g_free(self);
+}
+
+void frame_show(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if (!self->visible) {
+ self->visible = TRUE;
+ framerender_frame(self);
+ /* Grab the server to make sure that the frame window is mapped before
+ the client gets its MapNotify, i.e. to make sure the client is
+ _visible_ when it gets MapNotify. */
+ grab_server(TRUE);
+ XMapWindow(plugin.ob_display, self->client->window);
+ XMapWindow(plugin.ob_display, self->window);
+ grab_server(FALSE);
+ }
+}
+
+void frame_hide(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if (self->visible) {
+ self->visible = FALSE;
+ if (!frame_iconify_animating(self))
+ XUnmapWindow(plugin.ob_display, self->window);
+ /* we unmap the client itself so that we can get MapRequest
+ events, and because the ICCCM tells us to! */
+ XUnmapWindow(plugin.ob_display, self->client->window);
+ self->client->ignore_unmaps += 1;
+ }
+}
+
+void frame_adjust_theme(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ free_theme_statics(self);
+ set_theme_statics(self);
+}
+
+void frame_adjust_shape(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+#ifdef SHAPE
+ gint num;
+ XRectangle xrect[2];
+
+ if (!self->client->shaped)
+ {
+ /* clear the shape on the frame window */
+ XShapeCombineMask(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ None, ShapeSet);
+ }
+ else
+ {
+ /* make the frame's shape match the clients */
+ XShapeCombineShape(plugin.ob_display, self->window, ShapeBounding,
+ self->size.left,
+ self->size.top,
+ self->client->window,
+ ShapeBounding, ShapeSet);
+
+ num = 0;
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
+ {
+ xrect[0].x = 0;
+ xrect[0].y = 0;
+ xrect[0].width = self->area.width;
+ xrect[0].height = self->size.top;
+ ++num;
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE &&
+ theme_config.handle_height> 0)
+ {
+ xrect[1].x = 0;
+ xrect[1].y = FRAME_HANDLE_Y(self);
+ xrect[1].width = self->area.width;
+ xrect[1].height = theme_config.handle_height +
+ self->bwidth * 2;
+ ++num;
+ }
+
+ XShapeCombineRectangles(plugin.ob_display, self->window,
+ ShapeBounding, 0, 0, xrect, num,
+ ShapeUnion, Unsorted);
+ }
+#endif
+}
+
+void frame_adjust_area(gpointer _self, gboolean moved, gboolean resized,
+ gboolean fake)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ Strut oldsize;
+
+ oldsize = self->size;
+
+ if (resized) {
+ /* do this before changing the frame's status like max_horz max_vert */
+ frame_adjust_cursors(self);
+
+ self->functions = self->client->functions;
+ self->decorations = self->client->decorations;
+ self->max_horz = self->client->max_horz;
+ self->max_vert = self->client->max_vert;
+ self->shaded = self->client->shaded;
+
+ if (self->decorations & OB_FRAME_DECOR_BORDER
+ || (self->client->undecorated && plugin.config_theme_keepborder))
+ self->bwidth = theme_config.fbwidth;
+ else
+ self->bwidth = 0;
+
+ if (self->decorations & OB_FRAME_DECOR_BORDER) {
+ self->cbwidth_l = self->cbwidth_r = theme_config.cbwidthx;
+ self->cbwidth_t = self->cbwidth_b = theme_config.cbwidthy;
+ }
+ else
+ self->cbwidth_l = self->cbwidth_t = self->cbwidth_r
+ = self->cbwidth_b = 0;
+
+ if (self->max_horz) {
+ self->cbwidth_l = self->cbwidth_r = 0;
+ self->width = self->client->area.width;
+ if (self->max_vert)
+ self->cbwidth_b = 0;
+ }
+ else
+ self->width = self->client->area.width + self->cbwidth_l
+ + self->cbwidth_r;
+
+ /* some elements are sized based of the width, so don't let them have
+ negative values */
+ self->width = MAX(self->width, (theme_config.grip_width + self->bwidth)
+ * 2 + 1);
+
+ STRUT_SET(self->size, self->cbwidth_l + (!self->max_horz ? self->bwidth
+ : 0), self->cbwidth_t + self->bwidth, self->cbwidth_r
+ + (!self->max_horz ? self->bwidth : 0), self->cbwidth_b
+ + (!self->max_horz || !self->max_vert ? self->bwidth : 0));
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
+ self->size.top += theme_config.title_height + self->bwidth;
+ if (self->decorations & OB_FRAME_DECOR_HANDLE
+ && theme_config.handle_height > 0) {
+ self->size.bottom += theme_config.handle_height + self->bwidth;
+ }
+
+ /* position/size and map/unmap all the windows */
+
+ if (!fake) {
+ gint innercornerheight = theme_config.grip_width
+ - self->size.bottom;
+
+ if (self->cbwidth_l) {
+ XMoveResizeWindow(plugin.ob_display, self->innerleft,
+ self->size.left - self->cbwidth_l, self->size.top,
+ self->cbwidth_l, self->client->area.height);
+
+ XMapWindow(plugin.ob_display, self->innerleft);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerleft);
+
+ if (self->cbwidth_l && innercornerheight > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->innerbll, 0,
+ self->client->area.height - (theme_config.grip_width
+ - self->size.bottom), self->cbwidth_l,
+ theme_config.grip_width - self->size.bottom);
+
+ XMapWindow(plugin.ob_display, self->innerbll);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerbll);
+
+ if (self->cbwidth_r) {
+ XMoveResizeWindow(plugin.ob_display, self->innerright,
+ self->size.left + self->client->area.width,
+ self->size.top, self->cbwidth_r,
+ self->client->area.height);
+
+ XMapWindow(plugin.ob_display, self->innerright);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerright);
+
+ if (self->cbwidth_r && innercornerheight > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->innerbrr, 0,
+ self->client->area.height - (theme_config.grip_width
+ - self->size.bottom), self->cbwidth_r,
+ theme_config.grip_width - self->size.bottom);
+
+ XMapWindow(plugin.ob_display, self->innerbrr);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innerbrr);
+
+ if (self->cbwidth_t) {
+ XMoveResizeWindow(plugin.ob_display, self->innertop,
+ self->size.left - self->cbwidth_l, self->size.top
+ - self->cbwidth_t, self->client->area.width
+ + self->cbwidth_l + self->cbwidth_r,
+ self->cbwidth_t);
+
+ XMapWindow(plugin.ob_display, self->innertop);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->innertop);
+
+ if (self->cbwidth_b) {
+ XMoveResizeWindow(plugin.ob_display, self->innerbottom,
+ self->size.left - self->cbwidth_l, self->size.top
+ + self->client->area.height,
+ self->client->area.width + self->cbwidth_l
+ + self->cbwidth_r, self->cbwidth_b);
+
+ XMoveResizeWindow(plugin.ob_display, self->innerblb, 0, 0,
+ theme_config.grip_width + self->bwidth, self->cbwidth_b);
+ XMoveResizeWindow(plugin.ob_display, self->innerbrb,
+ self->client->area.width + self->cbwidth_l
+ + self->cbwidth_r - (theme_config.grip_width
+ + self->bwidth), 0, theme_config.grip_width
+ + self->bwidth, self->cbwidth_b);
+
+ XMapWindow(plugin.ob_display, self->innerbottom);
+ XMapWindow(plugin.ob_display, self->innerblb);
+ XMapWindow(plugin.ob_display, self->innerbrb);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->innerbottom);
+ XUnmapWindow(plugin.ob_display, self->innerblb);
+ XUnmapWindow(plugin.ob_display, self->innerbrb);
+ }
+
+ if (self->bwidth) {
+ gint titlesides;
+
+ /* height of titleleft and titleright */
+ titlesides = (!self->max_horz ? theme_config.grip_width : 0);
+
+ XMoveResizeWindow(plugin.ob_display, self->titletop,
+ theme_config.grip_width + self->bwidth, 0,
+ /* width + bwidth*2 - bwidth*2 - grips*2 */
+ self->width - theme_config.grip_width * 2, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->titletopleft, 0, 0,
+ theme_config.grip_width + self->bwidth, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->titletopright,
+ self->client->area.width + self->size.left
+ + self->size.right - theme_config.grip_width
+ - self->bwidth, 0, theme_config.grip_width
+ + self->bwidth, self->bwidth);
+
+ if (titlesides > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->titleleft, 0,
+ self->bwidth, self->bwidth, titlesides);
+ XMoveResizeWindow(plugin.ob_display, self->titleright,
+ self->client->area.width + self->size.left
+ + self->size.right - self->bwidth,
+ self->bwidth, self->bwidth, titlesides);
+
+ XMapWindow(plugin.ob_display, self->titleleft);
+ XMapWindow(plugin.ob_display, self->titleright);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->titleleft);
+ XUnmapWindow(plugin.ob_display, self->titleright);
+ }
+
+ XMapWindow(plugin.ob_display, self->titletop);
+ XMapWindow(plugin.ob_display, self->titletopleft);
+ XMapWindow(plugin.ob_display, self->titletopright);
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
+ XMoveResizeWindow(plugin.ob_display, self->titlebottom,
+ (self->max_horz ? 0 : self->bwidth),
+ theme_config.title_height + self->bwidth,
+ self->width, self->bwidth);
+
+ XMapWindow(plugin.ob_display, self->titlebottom);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->titlebottom);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->titlebottom);
+
+ XUnmapWindow(plugin.ob_display, self->titletop);
+ XUnmapWindow(plugin.ob_display, self->titletopleft);
+ XUnmapWindow(plugin.ob_display, self->titletopright);
+ XUnmapWindow(plugin.ob_display, self->titleleft);
+ XUnmapWindow(plugin.ob_display, self->titleright);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
+ XMoveResizeWindow(plugin.ob_display, self->title,
+ (self->max_horz ? 0 : self->bwidth), self->bwidth,
+ self->width, theme_config.title_height);
+
+ XMapWindow(plugin.ob_display, self->title);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ XMoveResizeWindow(plugin.ob_display, self->topresize,
+ theme_config.grip_width, 0, self->width
+ - theme_config.grip_width *2,
+ theme_config.paddingy + 1);
+
+ XMoveWindow(plugin.ob_display, self->tltresize, 0, 0);
+ XMoveWindow(plugin.ob_display, self->tllresize, 0, 0);
+ XMoveWindow(plugin.ob_display, self->trtresize, self->width
+ - theme_config.grip_width, 0);
+ XMoveWindow(plugin.ob_display, self->trrresize, self->width
+ - theme_config.paddingx - 1, 0);
+
+ XMapWindow(plugin.ob_display, self->topresize);
+ XMapWindow(plugin.ob_display, self->tltresize);
+ XMapWindow(plugin.ob_display, self->tllresize);
+ XMapWindow(plugin.ob_display, self->trtresize);
+ XMapWindow(plugin.ob_display, self->trrresize);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->topresize);
+ XUnmapWindow(plugin.ob_display, self->tltresize);
+ XUnmapWindow(plugin.ob_display, self->tllresize);
+ XUnmapWindow(plugin.ob_display, self->trtresize);
+ XUnmapWindow(plugin.ob_display, self->trrresize);
+ }
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->title);
+ }
+
+ if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ /* layout the title bar elements */
+ layout_title(self);
+
+ if (!fake) {
+ gint sidebwidth = self->max_horz ? 0 : self->bwidth;
+
+ if (self->bwidth && self->size.bottom) {
+ XMoveResizeWindow(plugin.ob_display, self->handlebottom,
+ theme_config.grip_width + self->bwidth + sidebwidth,
+ self->size.top + self->client->area.height
+ + self->size.bottom - self->bwidth, self->width
+ - (theme_config.grip_width + sidebwidth) * 2,
+ self->bwidth);
+
+ if (sidebwidth) {
+ XMoveResizeWindow(
+ plugin.ob_display,
+ self->lgripleft,
+ 0,
+ self->size.top + self->client->area.height
+ + self->size.bottom
+ - (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom
+ - self->cbwidth_b),
+ self->bwidth,
+ (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom - self->cbwidth_b));
+ XMoveResizeWindow(
+ plugin.ob_display,
+ self->rgripright,
+ self->size.left + self->client->area.width
+ + self->size.right - self->bwidth,
+ self->size.top + self->client->area.height
+ + self->size.bottom
+ - (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom
+ - self->cbwidth_b),
+ self->bwidth,
+ (!self->max_horz ? theme_config.grip_width
+ : self->size.bottom - self->cbwidth_b));
+
+ XMapWindow(plugin.ob_display, self->lgripleft);
+ XMapWindow(plugin.ob_display, self->rgripright);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->lgripleft);
+ XUnmapWindow(plugin.ob_display, self->rgripright);
+ }
+
+ XMoveResizeWindow(plugin.ob_display, self->lgripbottom,
+ sidebwidth, self->size.top + self->client->area.height
+ + self->size.bottom - self->bwidth,
+ theme_config.grip_width + self->bwidth, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->rgripbottom,
+ self->size.left + self->client->area.width
+ + self->size.right - self->bwidth - sidebwidth
+ - theme_config.grip_width, self->size.top
+ + self->client->area.height + self->size.bottom
+ - self->bwidth, theme_config.grip_width
+ + self->bwidth, self->bwidth);
+
+ XMapWindow(plugin.ob_display, self->handlebottom);
+ XMapWindow(plugin.ob_display, self->lgripbottom);
+ XMapWindow(plugin.ob_display, self->rgripbottom);
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE
+ && theme_config.handle_height > 0) {
+ XMoveResizeWindow(
+ plugin.ob_display,
+ self->handletop,
+ theme_config.grip_width + self->bwidth + sidebwidth,
+ FRAME_HANDLE_Y(self), self->width
+ - (theme_config.grip_width + sidebwidth)
+ * 2, self->bwidth);
+ XMapWindow(plugin.ob_display, self->handletop);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ XMoveResizeWindow(plugin.ob_display, self->handleleft,
+ theme_config.grip_width, 0, self->bwidth,
+ theme_config.handle_height);
+ XMoveResizeWindow(plugin.ob_display, self->handleright,
+ self->width - theme_config.grip_width
+ - self->bwidth, 0, self->bwidth,
+ theme_config.handle_height);
+
+ XMoveResizeWindow(plugin.ob_display, self->lgriptop,
+ sidebwidth,
+ FRAME_HANDLE_Y(self), theme_config.grip_width
+ + self->bwidth, self->bwidth);
+ XMoveResizeWindow(plugin.ob_display, self->rgriptop,
+ self->size.left + self->client->area.width
+ + self->size.right - self->bwidth
+ - sidebwidth - theme_config.grip_width,
+ FRAME_HANDLE_Y(self), theme_config.grip_width
+ + self->bwidth, self->bwidth);
+
+ XMapWindow(plugin.ob_display, self->handleleft);
+ XMapWindow(plugin.ob_display, self->handleright);
+ XMapWindow(plugin.ob_display, self->lgriptop);
+ XMapWindow(plugin.ob_display, self->rgriptop);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->handleleft);
+ XUnmapWindow(plugin.ob_display, self->handleright);
+ XUnmapWindow(plugin.ob_display, self->lgriptop);
+ XUnmapWindow(plugin.ob_display, self->rgriptop);
+ }
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->handleleft);
+ XUnmapWindow(plugin.ob_display, self->handleright);
+ XUnmapWindow(plugin.ob_display, self->lgriptop);
+ XUnmapWindow(plugin.ob_display, self->rgriptop);
+
+ XUnmapWindow(plugin.ob_display, self->handletop);
+ }
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->handleleft);
+ XUnmapWindow(plugin.ob_display, self->handleright);
+ XUnmapWindow(plugin.ob_display, self->lgriptop);
+ XUnmapWindow(plugin.ob_display, self->rgriptop);
+
+ XUnmapWindow(plugin.ob_display, self->handletop);
+
+ XUnmapWindow(plugin.ob_display, self->handlebottom);
+ XUnmapWindow(plugin.ob_display, self->lgripleft);
+ XUnmapWindow(plugin.ob_display, self->rgripright);
+ XUnmapWindow(plugin.ob_display, self->lgripbottom);
+ XUnmapWindow(plugin.ob_display, self->rgripbottom);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE
+ && theme_config.handle_height > 0) {
+ XMoveResizeWindow(plugin.ob_display, self->handle, sidebwidth,
+ FRAME_HANDLE_Y(self) + self->bwidth, self->width,
+ theme_config.handle_height);
+ XMapWindow(plugin.ob_display, self->handle);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ XMoveResizeWindow(plugin.ob_display, self->lgrip, 0, 0,
+ theme_config.grip_width, theme_config.handle_height);
+ XMoveResizeWindow(plugin.ob_display, self->rgrip,
+ self->width - theme_config.grip_width, 0,
+ theme_config.grip_width, theme_config.handle_height);
+
+ XMapWindow(plugin.ob_display, self->lgrip);
+ XMapWindow(plugin.ob_display, self->rgrip);
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->lgrip);
+ XUnmapWindow(plugin.ob_display, self->rgrip);
+ }
+ }
+ else {
+ XUnmapWindow(plugin.ob_display, self->lgrip);
+ XUnmapWindow(plugin.ob_display, self->rgrip);
+
+ XUnmapWindow(plugin.ob_display, self->handle);
+ }
+
+ if (self->bwidth && !self->max_horz && (self->client->area.height
+ + self->size.top + self->size.bottom)
+ > theme_config.grip_width * 2) {
+ XMoveResizeWindow(plugin.ob_display, self->left, 0,
+ self->bwidth + theme_config.grip_width, self->bwidth,
+ self->client->area.height + self->size.top
+ + self->size.bottom - theme_config.grip_width
+ * 2);
+
+ XMapWindow(plugin.ob_display, self->left);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->left);
+
+ if (self->bwidth && !self->max_horz && (self->client->area.height
+ + self->size.top + self->size.bottom)
+ > theme_config.grip_width * 2) {
+ XMoveResizeWindow(plugin.ob_display, self->right,
+ self->client->area.width + self->cbwidth_l
+ + self->cbwidth_r + self->bwidth, self->bwidth
+ + theme_config.grip_width, self->bwidth,
+ self->client->area.height + self->size.top
+ + self->size.bottom - theme_config.grip_width
+ * 2);
+
+ XMapWindow(plugin.ob_display, self->right);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->right);
+
+ XMoveResizeWindow(plugin.ob_display, self->backback,
+ self->size.left, self->size.top, self->client->area.width,
+ self->client->area.height);
+ }
+ }
+
+ /* shading can change without being moved or resized */
+ RECT_SET_SIZE(self->area, self->client->area.width + self->size.left
+ + self->size.right,
+ (self->client->shaded ? theme_config.title_height + self->bwidth
+ * 2 : self->client->area.height + self->size.top
+ + self->size.bottom));
+
+ if ((moved || resized) && !fake) {
+ /* find the new coordinates, done after setting the frame.size, for
+ frame_client_gravity. */
+ self->area.x = self->client->area.x;
+ self->area.y = self->client->area.y;
+ frame_client_gravity(self, &self->area.x, &self->area.y);
+ }
+
+ if (!fake) {
+ if (!frame_iconify_animating(self))
+ /* move and resize the top level frame.
+ shading can change without being moved or resized.
+
+ but don't do this during an iconify animation. it will be
+ reflected afterwards.
+ */
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+
+ /* when the client has StaticGravity, it likes to move around.
+ also this correctly positions the client when it maps.
+ this also needs to be run when the frame's decorations sizes change!
+ */
+ XMoveWindow(plugin.ob_display, self->client->window, self->size.left,
+ self->size.top);
+
+ if (resized) {
+ self->need_render = TRUE;
+ framerender_frame(self);
+ frame_adjust_shape(self);
+ }
+
+ if (!STRUT_EQUAL(self->size, oldsize)) {
+ gulong vals[4];
+ vals[0] = self->size.left;
+ vals[1] = self->size.right;
+ vals[2] = self->size.top;
+ vals[3] = self->size.bottom;
+ PROP_SETA32(self->client->window, net_frame_extents, cardinal,
+ vals, 4);
+ PROP_SETA32(self->client->window, kde_net_wm_frame_strut, cardinal,
+ vals, 4);
+ }
+
+ /* if this occurs while we are focus cycling, the indicator needs to
+ match the changes */
+ if (plugin.focus_cycle_target == self->client)
+ focus_cycle_draw_indicator(self->client);
+ }
+ if (resized && (self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ XResizeWindow(plugin.ob_display, self->label, self->label_width,
+ theme_config.label_height);
+
+}
+
+void frame_adjust_cursors(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if ((self->functions & OB_CLIENT_FUNC_RESIZE) != (self->client->functions
+ & OB_CLIENT_FUNC_RESIZE) || self->max_horz
+ != self->client->max_horz || self->max_vert
+ != self->client->max_vert || self->shaded != self->client->shaded) {
+ gboolean r = (self->client->functions & OB_CLIENT_FUNC_RESIZE)
+ && !(self->client->max_horz && self->client->max_vert);
+ gboolean topbot = !self->client->max_vert;
+ gboolean sh = self->client->shaded;
+ XSetWindowAttributes a;
+
+ /* these ones turn off when max vert, and some when shaded */
+ a.cursor = ob_cursor(r && topbot && !sh ? OB_CURSOR_NORTH
+ : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->topresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->titletop, CWCursor, &a);
+ a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->handle, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handletop, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handlebottom,
+ CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbottom, CWCursor,
+ &a);
+
+ /* these ones change when shaded */
+ a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST)
+ : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->titleleft, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->tltresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->tllresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->titletopleft,
+ CWCursor, &a);
+ a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST)
+ : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->titleright, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->trtresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->trrresize, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->titletopright,
+ CWCursor, &a);
+
+ /* these ones are pretty static */
+ a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->left, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerleft, CWCursor,
+ &a);
+ a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->right, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerright, CWCursor,
+ &a);
+ a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->lgrip, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handleleft, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->lgripleft, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->lgriptop, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->lgripbottom, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbll, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerblb, CWCursor, &a);
+ a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
+ XChangeWindowAttributes(plugin.ob_display, self->rgrip, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->handleright, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->rgripright, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->rgriptop, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->rgripbottom, CWCursor,
+ &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbrr, CWCursor, &a);
+ XChangeWindowAttributes(plugin.ob_display, self->innerbrb, CWCursor, &a);
+ }
+}
+
+void frame_adjust_client_area(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* adjust the window which is there to prevent flashing on unmap */
+ XMoveResizeWindow(plugin.ob_display, self->backfront, 0, 0,
+ self->client->area.width, self->client->area.height);
+}
+
+void frame_adjust_state(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->need_render = TRUE;
+ framerender_frame(self);
+}
+
+void frame_adjust_focus(gpointer _self, gboolean hilite)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->focused = hilite;
+ self->need_render = TRUE;
+ framerender_frame(self);
+ XFlush(plugin.ob_display);
+}
+
+void frame_adjust_title(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->need_render = TRUE;
+ framerender_frame(self);
+}
+
+void frame_adjust_icon(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->need_render = TRUE;
+ framerender_frame(self);
+}
+
+void frame_grab_client(gpointer _self, GHashTable * window_map)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* DO NOT map the client window here. we used to do that, but it is bogus.
+ we need to set up the client's dimensions and everything before we
+ send a mapnotify or we create race conditions.
+ */
+
+ /* reparent the client to the frame */
+ XReparentWindow(plugin.ob_display, self->client->window, self->window, 0, 0);
+
+ /*
+ When reparenting the client window, it is usually not mapped yet, since
+ this occurs from a MapRequest. However, in the case where Openbox is
+ starting up, the window is already mapped, so we'll see an unmap event
+ for it.
+ */
+ if (ob_state() == OB_STATE_STARTING)
+ ++self->client->ignore_unmaps;
+
+ /* select the event mask on the client's parent (to receive config/map
+ req's) the ButtonPress is to catch clicks on the client border */
+ XSelectInput(plugin.ob_display, self->window, FRAME_EVENTMASK);
+
+ /* set all the windows for the frame in the window_map */
+ g_hash_table_insert(window_map, &self->window, self->client);
+ g_hash_table_insert(window_map, &self->backback, self->client);
+ g_hash_table_insert(window_map, &self->backfront, self->client);
+ g_hash_table_insert(window_map, &self->innerleft, self->client);
+ g_hash_table_insert(window_map, &self->innertop, self->client);
+ g_hash_table_insert(window_map, &self->innerright, self->client);
+ g_hash_table_insert(window_map, &self->innerbottom, self->client);
+ g_hash_table_insert(window_map, &self->title, self->client);
+ g_hash_table_insert(window_map, &self->label, self->client);
+ g_hash_table_insert(window_map, &self->max, self->client);
+ g_hash_table_insert(window_map, &self->close, self->client);
+ g_hash_table_insert(window_map, &self->desk, self->client);
+ g_hash_table_insert(window_map, &self->shade, self->client);
+ g_hash_table_insert(window_map, &self->icon, self->client);
+ g_hash_table_insert(window_map, &self->iconify, self->client);
+ g_hash_table_insert(window_map, &self->handle, self->client);
+ g_hash_table_insert(window_map, &self->lgrip, self->client);
+ g_hash_table_insert(window_map, &self->rgrip, self->client);
+ g_hash_table_insert(window_map, &self->topresize, self->client);
+ g_hash_table_insert(window_map, &self->tltresize, self->client);
+ g_hash_table_insert(window_map, &self->tllresize, self->client);
+ g_hash_table_insert(window_map, &self->trtresize, self->client);
+ g_hash_table_insert(window_map, &self->trrresize, self->client);
+ g_hash_table_insert(window_map, &self->left, self->client);
+ g_hash_table_insert(window_map, &self->right, self->client);
+ g_hash_table_insert(window_map, &self->titleleft, self->client);
+ g_hash_table_insert(window_map, &self->titletop, self->client);
+ g_hash_table_insert(window_map, &self->titletopleft, self->client);
+ g_hash_table_insert(window_map, &self->titletopright, self->client);
+ g_hash_table_insert(window_map, &self->titleright, self->client);
+ g_hash_table_insert(window_map, &self->titlebottom, self->client);
+ g_hash_table_insert(window_map, &self->handleleft, self->client);
+ g_hash_table_insert(window_map, &self->handletop, self->client);
+ g_hash_table_insert(window_map, &self->handleright, self->client);
+ g_hash_table_insert(window_map, &self->handlebottom, self->client);
+ g_hash_table_insert(window_map, &self->lgripleft, self->client);
+ g_hash_table_insert(window_map, &self->lgriptop, self->client);
+ g_hash_table_insert(window_map, &self->lgripbottom, self->client);
+ g_hash_table_insert(window_map, &self->rgripright, self->client);
+ g_hash_table_insert(window_map, &self->rgriptop, self->client);
+ g_hash_table_insert(window_map, &self->rgripbottom, self->client);
+}
+
+void frame_release_client(gpointer _self, GHashTable * window_map)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ XEvent ev;
+ gboolean reparent = TRUE;
+
+ /* if there was any animation going on, kill it */
+ ob_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+
+ /* check if the app has already reparented its window away */
+ while (XCheckTypedWindowEvent(plugin.ob_display, self->client->window,
+ ReparentNotify, &ev)) {
+ /* This check makes sure we don't catch our own reparent action to
+ our frame window. This doesn't count as the app reparenting itself
+ away of course.
+
+ Reparent events that are generated by us are just discarded here.
+ They are of no consequence to us anyhow.
+ */
+ if (ev.xreparent.parent != self->window) {
+ reparent = FALSE;
+ XPutBackEvent(plugin.ob_display, &ev);
+ break;
+ }
+ }
+
+ if (reparent) {
+ /* according to the ICCCM - if the client doesn't reparent itself,
+ then we will reparent the window to root for them */
+ XReparentWindow(plugin.ob_display, self->client->window, RootWindow(
+ plugin.ob_display, plugin.ob_screen), self->client->area.x,
+ self->client->area.y);
+ }
+
+ /* remove all the windows for the frame from the window_map */
+ g_hash_table_remove(window_map, &self->window);
+ g_hash_table_remove(window_map, &self->backback);
+ g_hash_table_remove(window_map, &self->backfront);
+ g_hash_table_remove(window_map, &self->innerleft);
+ g_hash_table_remove(window_map, &self->innertop);
+ g_hash_table_remove(window_map, &self->innerright);
+ g_hash_table_remove(window_map, &self->innerbottom);
+ g_hash_table_remove(window_map, &self->title);
+ g_hash_table_remove(window_map, &self->label);
+ g_hash_table_remove(window_map, &self->max);
+ g_hash_table_remove(window_map, &self->close);
+ g_hash_table_remove(window_map, &self->desk);
+ g_hash_table_remove(window_map, &self->shade);
+ g_hash_table_remove(window_map, &self->icon);
+ g_hash_table_remove(window_map, &self->iconify);
+ g_hash_table_remove(window_map, &self->handle);
+ g_hash_table_remove(window_map, &self->lgrip);
+ g_hash_table_remove(window_map, &self->rgrip);
+ g_hash_table_remove(window_map, &self->topresize);
+ g_hash_table_remove(window_map, &self->tltresize);
+ g_hash_table_remove(window_map, &self->tllresize);
+ g_hash_table_remove(window_map, &self->trtresize);
+ g_hash_table_remove(window_map, &self->trrresize);
+ g_hash_table_remove(window_map, &self->left);
+ g_hash_table_remove(window_map, &self->right);
+ g_hash_table_remove(window_map, &self->titleleft);
+ g_hash_table_remove(window_map, &self->titletop);
+ g_hash_table_remove(window_map, &self->titletopleft);
+ g_hash_table_remove(window_map, &self->titletopright);
+ g_hash_table_remove(window_map, &self->titleright);
+ g_hash_table_remove(window_map, &self->titlebottom);
+ g_hash_table_remove(window_map, &self->handleleft);
+ g_hash_table_remove(window_map, &self->handletop);
+ g_hash_table_remove(window_map, &self->handleright);
+ g_hash_table_remove(window_map, &self->handlebottom);
+ g_hash_table_remove(window_map, &self->lgripleft);
+ g_hash_table_remove(window_map, &self->lgriptop);
+ g_hash_table_remove(window_map, &self->lgripbottom);
+ g_hash_table_remove(window_map, &self->rgripright);
+ g_hash_table_remove(window_map, &self->rgriptop);
+ g_hash_table_remove(window_map, &self->rgripbottom);
+
+ ob_main_loop_timeout_remove_data(plugin.ob_main_loop, flash_timeout, self,
+ TRUE);
+}
+
+/* is there anything present between us and the label? */
+static gboolean is_button_present(ObDefaultFrame *_self, const gchar *lc,
+ gint dir)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ for (; *lc != '\0' && lc >= plugin.config_title_layout; lc += dir) {
+ if (*lc == ' ')
+ continue; /* it was invalid */
+ if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
+ return TRUE;
+ if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
+ return TRUE;
+ if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
+ return TRUE;
+ if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
+ return TRUE;
+ if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
+ return TRUE;
+ if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
+ return TRUE;
+ if (*lc == 'L')
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void layout_title(ObDefaultFrame * self)
+{
+ gchar *lc;
+ gint i;
+
+ const gint bwidth = theme_config.button_size + theme_config.paddingx + 1;
+ /* position of the left most button */
+ const gint left = theme_config.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 - (theme_config.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 = plugin.config_title_layout;
+ firstcon = &self->leftmost;
+ }
+ else {
+ x = right;
+ lc = plugin.config_title_layout
+ + strlen(plugin.config_title_layout)-1;
+ firstcon = &self->rightmost;
+ }
+
+ /* stop at the end of the string (or the label, which calls break) */
+ for (; *lc != '\0' && lc >= plugin.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(plugin.ob_display, self->icon);
+ XMoveWindow(plugin.ob_display, self->icon, self->icon_x,
+ theme_config.paddingy);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->icon);
+
+ if (self->desk_on) {
+ XMapWindow(plugin.ob_display, self->desk);
+ XMoveWindow(plugin.ob_display, self->desk, self->desk_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->desk);
+
+ if (self->shade_on) {
+ XMapWindow(plugin.ob_display, self->shade);
+ XMoveWindow(plugin.ob_display, self->shade, self->shade_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->shade);
+
+ if (self->iconify_on) {
+ XMapWindow(plugin.ob_display, self->iconify);
+ XMoveWindow(plugin.ob_display, self->iconify, self->iconify_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->iconify);
+
+ if (self->max_on) {
+ XMapWindow(plugin.ob_display, self->max);
+ XMoveWindow(plugin.ob_display, self->max, self->max_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->max);
+
+ if (self->close_on) {
+ XMapWindow(plugin.ob_display, self->close);
+ XMoveWindow(plugin.ob_display, self->close, self->close_x,
+ theme_config.paddingy + 1);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->close);
+
+ if (self->label_on) {
+ self->label_width = MAX(1, self->label_width); /* no lower than 1 */
+ XMapWindow(plugin.ob_display, self->label);
+ XMoveWindow(plugin.ob_display, self->label, self->label_x,
+ theme_config.paddingy);
+ }
+ else
+ XUnmapWindow(plugin.ob_display, self->label);
+}
+
+ObFrameContext frame_context(gpointer _self, Window win, gint x, gint y)
+{
+ ObDefaultFrame * self = OBDEFAULTFRAME(_self);
+
+ /* 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 += theme_config.grip_width + self->bwidth;
+ /* titletopright is way to the right edge */
+ else if (win == self->titletopright)
+ fx += self->area.width - (theme_config.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 + theme_config.paddingy + 1
+ + theme_config.button_size) {
+ if (fx < (self->bwidth + theme_config.paddingx + 1
+ + theme_config.button_size)) {
+ if (self->leftmost != OB_FRAME_CONTEXT_NONE)
+ return self->leftmost;
+ }
+ else if (fx >= (self->area.width - (self->bwidth
+ + theme_config.paddingx + 1 + theme_config.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(gpointer _self, gint *x, gint *y)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* horizontal */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case SouthWestGravity:
+ case WestGravity:
+ break;
+
+ case NorthGravity:
+ case SouthGravity:
+ case CenterGravity:
+ /* the middle of the client will be the middle of the frame */
+ *x -= (self->size.right - self->size.left) / 2;
+ break;
+
+ case NorthEastGravity:
+ case SouthEastGravity:
+ case EastGravity:
+ /* the right side of the client will be the right side of the frame */
+ *x -= self->size.right + self->size.left - self->client->border_width
+ * 2;
+ break;
+
+ case ForgetGravity:
+ case StaticGravity:
+ /* the client's position won't move */
+ *x -= self->size.left - self->client->border_width;
+ break;
+ }
+
+ /* vertical */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case NorthEastGravity:
+ case NorthGravity:
+ break;
+
+ case CenterGravity:
+ case EastGravity:
+ case WestGravity:
+ /* the middle of the client will be the middle of the frame */
+ *y -= (self->size.bottom - self->size.top) / 2;
+ break;
+
+ case SouthWestGravity:
+ case SouthEastGravity:
+ case SouthGravity:
+ /* the bottom of the client will be the bottom of the frame */
+ *y -= self->size.bottom + self->size.top - self->client->border_width
+ * 2;
+ break;
+
+ case ForgetGravity:
+ case StaticGravity:
+ /* the client's position won't move */
+ *y -= self->size.top - self->client->border_width;
+ break;
+ }
+}
+
+void frame_frame_gravity(gpointer _self, gint *x, gint *y)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* horizontal */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case WestGravity:
+ case SouthWestGravity:
+ break;
+ case NorthGravity:
+ case CenterGravity:
+ case SouthGravity:
+ /* the middle of the client will be the middle of the frame */
+ *x += (self->size.right - self->size.left) / 2;
+ break;
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
+ /* the right side of the client will be the right side of the frame */
+ *x += self->size.right + self->size.left - self->client->border_width
+ * 2;
+ break;
+ case StaticGravity:
+ case ForgetGravity:
+ /* the client's position won't move */
+ *x += self->size.left - self->client->border_width;
+ break;
+ }
+
+ /* vertical */
+ switch (self->client->gravity) {
+ default:
+ case NorthWestGravity:
+ case NorthGravity:
+ case NorthEastGravity:
+ break;
+ case WestGravity:
+ case CenterGravity:
+ case EastGravity:
+ /* the middle of the client will be the middle of the frame */
+ *y += (self->size.bottom - self->size.top) / 2;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ case SouthEastGravity:
+ /* the bottom of the client will be the bottom of the frame */
+ *y += self->size.bottom + self->size.top - self->client->border_width
+ * 2;
+ break;
+ case StaticGravity:
+ case ForgetGravity:
+ /* the client's position won't move */
+ *y += self->size.top - self->client->border_width;
+ break;
+ }
+}
+
+void frame_rect_to_frame(gpointer _self, Rect *r)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ r->width += self->size.left + self->size.right;
+ r->height += self->size.top + self->size.bottom;
+ frame_client_gravity(self, &r->x, &r->y);
+}
+
+void frame_rect_to_client(gpointer _self, Rect *r)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ r->width -= self->size.left + self->size.right;
+ r->height -= self->size.top + self->size.bottom;
+ frame_frame_gravity(self, &r->x, &r->y);
+}
+
+void flash_done(gpointer data)
+{
+ ObDefaultFrame *self = data;
+
+ if (self->focused != self->flash_on)
+ frame_adjust_focus(self, self->focused);
+}
+
+gboolean flash_timeout(gpointer data)
+{
+ ObDefaultFrame *self = data;
+ GTimeVal now;
+
+ g_get_current_time(&now);
+ if (now.tv_sec > self->flash_end.tv_sec
+ || (now.tv_sec == self->flash_end.tv_sec && now.tv_usec
+ >= self->flash_end.tv_usec))
+ self->flashing = FALSE;
+
+ if (!self->flashing)
+ return FALSE; /* we are done */
+
+ self->flash_on = !self->flash_on;
+ if (!self->focused) {
+ frame_adjust_focus(self, self->flash_on);
+ self->focused = FALSE;
+ }
+
+ return TRUE; /* go again */
+}
+
+void frame_flash_start(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->flash_on = self->focused;
+
+ if (!self->flashing)
+ ob_main_loop_timeout_add(plugin.ob_main_loop, G_USEC_PER_SEC * 0.6,
+ flash_timeout, self, g_direct_equal, flash_done);
+ g_get_current_time(&self->flash_end);
+ g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
+
+ self->flashing = TRUE;
+}
+
+void frame_flash_stop(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ self->flashing = FALSE;
+}
+
+static gulong frame_animate_iconify_time_left(gpointer _self,
+ const GTimeVal *now)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ glong sec, usec;
+ sec = self->iconify_animation_end.tv_sec - now->tv_sec;
+ usec = self->iconify_animation_end.tv_usec - now->tv_usec;
+ if (usec < 0) {
+ usec += G_USEC_PER_SEC;
+ sec--;
+ }
+ /* no negative values */
+ return MAX(sec * G_USEC_PER_SEC + usec, 0);
+}
+
+gboolean frame_animate_iconify(gpointer p)
+{
+ ObDefaultFrame *self = p;
+ gint x, y, w, h;
+ gint iconx, icony, iconw;
+ GTimeVal now;
+ gulong time;
+ gboolean iconifying;
+
+ if (self->client->icon_geometry.width == 0) {
+ /* there is no icon geometry set so just go straight down */
+ Rect *a =
+ screen_physical_area_monitor(screen_find_monitor(&self->area));
+ iconx = self->area.x + self->area.width / 2 + 32;
+ icony = a->y + a->width;
+ iconw = 64;
+ g_free(a);
+ }
+ else {
+ iconx = self->client->icon_geometry.x;
+ icony = self->client->icon_geometry.y;
+ iconw = self->client->icon_geometry.width;
+ }
+
+ iconifying = self->iconify_animation_going > 0;
+
+ /* how far do we have left to go ? */
+ g_get_current_time(&now);
+ time = frame_animate_iconify_time_left(self, &now);
+
+ if (time == 0 || iconifying) {
+ /* start where the frame is supposed to be */
+ x = self->area.x;
+ y = self->area.y;
+ w = self->area.width;
+ h = self->area.height;
+ }
+ else {
+ /* start at the icon */
+ x = iconx;
+ y = icony;
+ w = iconw;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time > 0) {
+ glong dx, dy, dw;
+ glong elapsed;
+
+ dx = self->area.x - iconx;
+ dy = self->area.y - icony;
+ dw = self->area.width - self->bwidth * 2 - iconw;
+ /* if restoring, we move in the opposite direction */
+ if (!iconifying) {
+ dx = -dx;
+ dy = -dy;
+ dw = -dw;
+ }
+
+ elapsed = FRAME_ANIMATE_ICONIFY_TIME - time;
+ x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
+ h = self->size.top; /* just the titlebar */
+ }
+
+ if (time == 0)
+ frame_end_iconify_animation(self);
+ else {
+ XMoveResizeWindow(plugin.ob_display, self->window, x, y, w, h);
+ XFlush(plugin.ob_display);
+ }
+
+ return time > 0; /* repeat until we're out of time */
+}
+
+void frame_end_iconify_animation(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ /* see if there is an animation going */
+ if (self->iconify_animation_going == 0)
+ return;
+
+ if (!self->visible)
+ XUnmapWindow(plugin.ob_display, self->window);
+ else {
+ /* Send a ConfigureNotify when the animation is done, this fixes
+ KDE's pager showing the window in the wrong place. since the
+ window is mapped at a different location and is then moved, we
+ need to send the synthetic configurenotify, since apps may have
+ read the position when the client mapped, apparently. */
+ client_reconfigure(self->client, TRUE);
+ }
+
+ /* we're not animating any more ! */
+ self->iconify_animation_going = 0;
+
+ XMoveResizeWindow(plugin.ob_display, self->window, self->area.x,
+ self->area.y, self->area.width, self->area.height);
+ /* we delay re-rendering until after we're done animating */
+ framerender_frame(self);
+ XFlush(plugin.ob_display);
+}
+
+void frame_begin_iconify_animation(gpointer _self, gboolean iconifying)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ gulong time;
+ gboolean new_anim = FALSE;
+ gboolean set_end = TRUE;
+ GTimeVal now;
+
+ /* if there is no titlebar, just don't animate for now
+ XXX it would be nice tho.. */
+ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
+ return;
+
+ /* get the current time */
+ g_get_current_time(&now);
+
+ /* get how long until the end */
+ time = FRAME_ANIMATE_ICONIFY_TIME;
+ if (self->iconify_animation_going) {
+ if (!!iconifying != (self->iconify_animation_going > 0)) {
+ /* animation was already going on in the opposite direction */
+ time = time - frame_animate_iconify_time_left(self, &now);
+ }
+ else
+ /* animation was already going in the same direction */
+ set_end = FALSE;
+ }
+ else
+ new_anim = TRUE;
+ self->iconify_animation_going = iconifying ? 1 : -1;
+
+ /* set the ending time */
+ if (set_end) {
+ self->iconify_animation_end.tv_sec = now.tv_sec;
+ self->iconify_animation_end.tv_usec = now.tv_usec;
+ g_time_val_add(&self->iconify_animation_end, time);
+ }
+
+ if (new_anim) {
+ ob_main_loop_timeout_remove_data(plugin.ob_main_loop,
+ frame_animate_iconify, self, FALSE);
+ ob_main_loop_timeout_add(plugin.ob_main_loop,
+ FRAME_ANIMATE_ICONIFY_STEP_TIME, frame_animate_iconify, self,
+ g_direct_equal, NULL);
+
+ /* do the first step */
+ frame_animate_iconify(self);
+
+ /* show it during the animation even if it is not "visible" */
+ if (!self->visible)
+ XMapWindow(plugin.ob_display, self->window);
+ }
+}
+
+gboolean frame_iconify_animating(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ return self->iconify_animation_going != 0;
+}
+
+ObFramePlugin plugin = { 0, //gpointer handler;
+ "libminimal.la", //gchar * filename;
+ "minimal", //gchar * name;
+ init, //gint (*init) (Display * display, gint screen);
+ 0, frame_new, //gpointer (*frame_new) (struct _ObClient *c);
+ frame_free, //void (*frame_free) (gpointer self);
+ frame_show, //void (*frame_show) (gpointer self);
+ frame_hide, //void (*frame_hide) (gpointer self);
+ frame_adjust_theme, //void (*frame_adjust_theme) (gpointer self);
+ frame_adjust_shape, //void (*frame_adjust_shape) (gpointer self);
+ frame_adjust_area, //void (*frame_adjust_area) (gpointer self, gboolean moved, gboolean resized, gboolean fake);
+ frame_adjust_client_area, //void (*frame_adjust_client_area) (gpointer self);
+ frame_adjust_state, //void (*frame_adjust_state) (gpointer self);
+ frame_adjust_focus, //void (*frame_adjust_focus) (gpointer self, gboolean hilite);
+ frame_adjust_title, //void (*frame_adjust_title) (gpointer self);
+ frame_adjust_icon, //void (*frame_adjust_icon) (gpointer self);
+ frame_grab_client, //void (*frame_grab_client) (gpointer self);
+ frame_release_client, //void (*frame_release_client) (gpointer self);
+ // frame_context_from_string, //ObFrameContext (*frame_context_from_string) (const gchar *name);
+ frame_context, //ObFrameContext (*frame_context) (struct _ObClient *self, Window win, gint x, gint y);
+ frame_client_gravity, //void (*frame_client_gravity) (gpointer self, gint *x, gint *y);
+ frame_frame_gravity, //void (*frame_frame_gravity) (gpointer self, gint *x, gint *y);
+ frame_rect_to_frame, //void (*frame_rect_to_frame) (gpointer self, Rect *r);
+ frame_rect_to_client, //void (*frame_rect_to_client) (gpointer self, Rect *r);
+ frame_flash_start, //void (*frame_flash_start) (gpointer self);
+ frame_flash_stop, //void (*frame_flash_stop) (gpointer self);
+ frame_begin_iconify_animation, //void (*frame_begin_iconify_animation) (gpointer self, gboolean iconifying);
+ frame_end_iconify_animation, //void (*frame_end_iconify_animation) (gpointer self);
+ frame_iconify_animating, // gboolean (*frame_iconify_animating)(gpointer p);
+ load_theme_config,
+
+ /* This fields are fill by openbox. */
+ 0, //Display * ob_display;
+ 0, //gint ob_screen;
+ 0, //RrInstance *ob_rr_inst;
+ // 0, //RrTheme *ob_rr_theme;
+ 0, //gboolean config_theme_keepborder;
+ 0, //struct _ObClient *focus_cycle_target;
+ 0, //gchar *config_title_layout;
+ FALSE, //gboolean moveresize_in_progress;
+ 0, //struct _ObMainLoop *ob_main_loop;
+};
+
+ObFramePlugin * get_info()
+{
+ return &plugin;
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_minimal_plugin.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef FRAME_DEFAULT_PLUGIN_H_
+#define FRAME_DEFAULT_PLUGIN_H_
+
+#include "frame_minimal_config.h"
+
+#include "render/render.h"
+#include "openbox/engine_interface.h"
+
+ObFrameThemeConfig theme_config;
+
+struct _ObDefaultFrame
+{
+ // PUBLIC :
+ struct _ObClient *client;
+
+ Window window;
+
+ Strut size;
+ Rect area;
+ gint bwidth; /* border width */
+ guint decorations;
+
+ gboolean visible;
+
+ gboolean max_horz; /* when maxed some decorations are hidden */
+ gboolean max_vert; /* when maxed some decorations are hidden */
+
+ gboolean max_press;
+ gboolean close_press;
+ gboolean desk_press;
+ gboolean shade_press;
+ gboolean iconify_press;
+
+ gboolean max_hover;
+ gboolean close_hover;
+ gboolean desk_hover;
+ gboolean shade_hover;
+ gboolean iconify_hover;
+
+ gint iconify_animation_going;
+
+ /* PRIVATE: */
+ /* You are free to add what you want here */
+
+ ObStyle style;
+
+ guint functions;
+
+ Window title;
+ Window label;
+ Window max;
+ Window close;
+ Window desk;
+ Window shade;
+ Window icon;
+ Window iconify;
+ Window handle;
+ Window lgrip;
+ Window rgrip;
+
+ /* These are borders of the frame and its elements */
+ Window titleleft;
+ Window titletop;
+ Window titletopleft;
+ Window titletopright;
+ Window titleright;
+ Window titlebottom;
+ Window left;
+ Window right;
+ Window handleleft;
+ Window handletop;
+ Window handleright;
+ Window handlebottom;
+ Window lgriptop;
+ Window lgripleft;
+ Window lgripbottom;
+ Window rgriptop;
+ Window rgripright;
+ Window rgripbottom;
+ Window innerleft; /*!< For drawing the inner client border */
+ Window innertop; /*!< For drawing the inner client border */
+ Window innerright; /*!< For drawing the inner client border */
+ Window innerbottom; /*!< For drawing the inner client border */
+ Window innerblb;
+ Window innerbll;
+ Window innerbrb;
+ Window innerbrr;
+ Window backback; /*!< A colored window shown while resizing */
+ Window backfront; /*!< An undrawn-in window, to prevent flashing on unmap */
+
+ /* These are resize handles inside the titlebar */
+ Window topresize;
+ Window tltresize;
+ Window tllresize;
+ Window trtresize;
+ Window trrresize;
+
+ Colormap colormap;
+
+ RrAppearance *a_unfocused_title;
+ RrAppearance *a_focused_title;
+ RrAppearance *a_unfocused_label;
+ RrAppearance *a_focused_label;
+ RrAppearance *a_icon;
+ RrAppearance *a_unfocused_handle;
+ RrAppearance *a_focused_handle;
+
+ gint icon_on; /* if the window icon button is on */
+ gint label_on; /* if the window title is on */
+ gint iconify_on; /* if the window iconify button is on */
+ gint desk_on; /* if the window all-desktops button is on */
+ gint shade_on; /* if the window shade button is on */
+ gint max_on; /* if the window maximize button is on */
+ gint close_on; /* if the window close button is on */
+
+ gint width; /* width of the titlebar and handle */
+ gint label_width; /* width of the label in the titlebar */
+ gint icon_x; /* x-position of the window icon button */
+ gint label_x; /* x-position of the window title */
+ gint iconify_x; /* x-position of the window iconify button */
+ gint desk_x; /* x-position of the window all-desktops button */
+ gint shade_x; /* x-position of the window shade button */
+ gint max_x; /* x-position of the window maximize button */
+ gint close_x; /* x-position of the window close button */
+
+ gint cbwidth_l; /* client border width */
+ gint cbwidth_t; /* client border width */
+ gint cbwidth_r; /* client border width */
+ gint cbwidth_b; /* client border width */
+ gboolean shaded; /* decorations adjust when shaded */
+
+ /* the leftmost and rightmost elements in the titlebar */
+ ObFrameContext leftmost;
+ ObFrameContext rightmost;
+
+ gboolean focused;
+ gboolean need_render;
+
+ gboolean flashing;
+ gboolean flash_on;
+ GTimeVal flash_end;
+
+ GTimeVal iconify_animation_end;
+
+};
+
+typedef struct _ObDefaultFrame ObDefaultFrame;
+
+/* Function use for interface */
+gint init(Display *, gint);
+gpointer frame_new(struct _ObClient *c);
+void frame_free(gpointer self);
+void frame_show(gpointer self);
+void frame_hide(gpointer self);
+void frame_adjust_theme(gpointer self);
+void frame_adjust_shape(gpointer self);
+void frame_adjust_area(gpointer self, gboolean moved, gboolean resized,
+ gboolean fake);
+void frame_adjust_client_area(gpointer self);
+void frame_adjust_state(gpointer self);
+void frame_adjust_focus(gpointer self, gboolean hilite);
+void frame_adjust_title(gpointer self);
+void frame_adjust_icon(gpointer self);
+void frame_grab_client(gpointer self, GHashTable *);
+void frame_release_client(gpointer self, GHashTable *);
+ObFrameContext frame_context(gpointer, Window win, gint x, gint y);
+void frame_client_gravity(gpointer self, gint *x, gint *y);
+void frame_frame_gravity(gpointer self, gint *x, gint *y);
+void frame_rect_to_frame(gpointer self, Rect *r);
+void frame_rect_to_client(gpointer self, Rect *r);
+void frame_flash_start(gpointer self);
+void frame_flash_stop(gpointer self);
+void frame_begin_iconify_animation(gpointer self, gboolean iconifying);
+void frame_end_iconify_animation(gpointer self);
+gboolean frame_iconify_animating(gpointer _self);
+
+void flash_done(gpointer data);
+gboolean flash_timeout(gpointer data);
+
+void layout_title(ObDefaultFrame *);
+void set_theme_statics(gpointer self);
+void free_theme_statics(gpointer self);
+gboolean frame_animate_iconify(gpointer self);
+void frame_adjust_cursors(gpointer self);
+
+/* Global for renderframe.c only */
+extern ObFramePlugin plugin;
+#define OBDEFAULTFRAME(x) ((ObDefaultFrame *)(x))
+
+#endif /*FRAME_DEFAULT_PLUGIN_H_*/
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_minimal_render.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "frame_minimal_plugin.h"
+#include "frame_minimal_render.h"
+
+#include "openbox/engine_interface.h"
+#include "openbox/openbox.h"
+#include "openbox/screen.h"
+#include "openbox/client.h"
+
+#include "render/theme.h"
+
+static void framerender_label(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_icon(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_max(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_iconify(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_desk(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_shade(ObDefaultFrame *self, RrAppearance *a);
+static void framerender_close(ObDefaultFrame *self, RrAppearance *a);
+
+void framerender_frame(gpointer _self)
+{
+ ObDefaultFrame * self = (ObDefaultFrame *) _self;
+ if (plugin.frame_iconify_animating(self))
+ return; /* delay redrawing until the animation is done */
+ if (!self->need_render)
+ return;
+ if (!self->visible)
+ return;
+ self->need_render = FALSE;
+
+ {
+ gulong px;
+
+ px = (self->focused ? RrColorPixel(theme_config.cb_focused_color)
+ : RrColorPixel(theme_config.cb_unfocused_color));
+
+ XSetWindowBackground(plugin.ob_display, self->backback, px);
+ XClearWindow(plugin.ob_display, self->backback);
+ XSetWindowBackground(plugin.ob_display, self->innerleft, px);
+ XClearWindow(plugin.ob_display, self->innerleft);
+ XSetWindowBackground(plugin.ob_display, self->innertop, px);
+ XClearWindow(plugin.ob_display, self->innertop);
+ XSetWindowBackground(plugin.ob_display, self->innerright, px);
+ XClearWindow(plugin.ob_display, self->innerright);
+ XSetWindowBackground(plugin.ob_display, self->innerbottom, px);
+ XClearWindow(plugin.ob_display, self->innerbottom);
+ XSetWindowBackground(plugin.ob_display, self->innerbll, px);
+ XClearWindow(plugin.ob_display, self->innerbll);
+ XSetWindowBackground(plugin.ob_display, self->innerbrr, px);
+ XClearWindow(plugin.ob_display, self->innerbrr);
+ XSetWindowBackground(plugin.ob_display, self->innerblb, px);
+ XClearWindow(plugin.ob_display, self->innerblb);
+ XSetWindowBackground(plugin.ob_display, self->innerbrb, px);
+ XClearWindow(plugin.ob_display, self->innerbrb);
+
+ px
+ = (self->focused ? RrColorPixel(theme_config.frame_focused_border_color)
+ : RrColorPixel(theme_config.frame_unfocused_border_color));
+
+ XSetWindowBackground(plugin.ob_display, self->left, px);
+ XClearWindow(plugin.ob_display, self->left);
+ XSetWindowBackground(plugin.ob_display, self->right, px);
+ XClearWindow(plugin.ob_display, self->right);
+
+ XSetWindowBackground(plugin.ob_display, self->titleleft, px);
+ XClearWindow(plugin.ob_display, self->titleleft);
+ XSetWindowBackground(plugin.ob_display, self->titletop, px);
+ XClearWindow(plugin.ob_display, self->titletop);
+ XSetWindowBackground(plugin.ob_display, self->titletopleft, px);
+ XClearWindow(plugin.ob_display, self->titletopleft);
+ XSetWindowBackground(plugin.ob_display, self->titletopright, px);
+ XClearWindow(plugin.ob_display, self->titletopright);
+ XSetWindowBackground(plugin.ob_display, self->titleright, px);
+ XClearWindow(plugin.ob_display, self->titleright);
+
+ XSetWindowBackground(plugin.ob_display, self->handleleft, px);
+ XClearWindow(plugin.ob_display, self->handleleft);
+ XSetWindowBackground(plugin.ob_display, self->handletop, px);
+ XClearWindow(plugin.ob_display, self->handletop);
+ XSetWindowBackground(plugin.ob_display, self->handleright, px);
+ XClearWindow(plugin.ob_display, self->handleright);
+ XSetWindowBackground(plugin.ob_display, self->handlebottom, px);
+ XClearWindow(plugin.ob_display, self->handlebottom);
+
+ XSetWindowBackground(plugin.ob_display, self->lgripleft, px);
+ XClearWindow(plugin.ob_display, self->lgripleft);
+ XSetWindowBackground(plugin.ob_display, self->lgriptop, px);
+ XClearWindow(plugin.ob_display, self->lgriptop);
+ XSetWindowBackground(plugin.ob_display, self->lgripbottom, px);
+ XClearWindow(plugin.ob_display, self->lgripbottom);
+
+ XSetWindowBackground(plugin.ob_display, self->rgripright, px);
+ XClearWindow(plugin.ob_display, self->rgripright);
+ XSetWindowBackground(plugin.ob_display, self->rgriptop, px);
+ XClearWindow(plugin.ob_display, self->rgriptop);
+ XSetWindowBackground(plugin.ob_display, self->rgripbottom, px);
+ XClearWindow(plugin.ob_display, self->rgripbottom);
+
+ /* don't use the separator color for shaded windows */
+ if (!self->client->shaded)
+ px
+ = (self->focused ? RrColorPixel(theme_config.title_separator_focused_color)
+ : RrColorPixel(theme_config.title_separator_unfocused_color));
+
+ XSetWindowBackground(plugin.ob_display, self->titlebottom, px);
+ XClearWindow(plugin.ob_display, self->titlebottom);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
+ RrAppearance *t, *l, *m, *n, *i, *d, *s, *c, *clear;
+ if (self->focused) {
+
+ t = self->a_focused_title;
+ l = self->a_focused_label;
+
+ m
+ = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ? theme_config.a_disabled_focused_max
+ : (self->client->max_vert || self->client->max_horz ? (self->max_press ? theme_config.a_toggled_focused_pressed_max
+ : (self->max_hover ? theme_config.a_toggled_hover_focused_max
+ : theme_config.a_toggled_focused_unpressed_max))
+ : (self->max_press ? theme_config.a_focused_pressed_max
+ : (self->max_hover ? theme_config.a_hover_focused_max
+ : theme_config.a_focused_unpressed_max))));
+ n = self->a_icon;
+ i
+ = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ? theme_config.a_disabled_focused_iconify
+ : (self->iconify_press ? theme_config.a_focused_pressed_iconify
+ : (self->iconify_hover ? theme_config.a_hover_focused_iconify
+ : theme_config.a_focused_unpressed_iconify)));
+ d
+ = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ? theme_config.a_disabled_focused_desk
+ : (self->client->desktop == DESKTOP_ALL ? (self->desk_press ? theme_config.a_toggled_focused_pressed_desk
+ : (self->desk_hover ? theme_config.a_toggled_hover_focused_desk
+ : theme_config.a_toggled_focused_unpressed_desk))
+ : (self->desk_press ? theme_config.a_focused_pressed_desk
+ : (self->desk_hover ? theme_config.a_hover_focused_desk
+ : theme_config.a_focused_unpressed_desk))));
+ s
+ = (!(self->decorations & OB_FRAME_DECOR_SHADE) ? theme_config.a_disabled_focused_shade
+ : (self->client->shaded ? (self->shade_press ? theme_config.a_toggled_focused_pressed_shade
+ : (self->shade_hover ? theme_config.a_toggled_hover_focused_shade
+ : theme_config.a_toggled_focused_unpressed_shade))
+ : (self->shade_press ? theme_config.a_focused_pressed_shade
+ : (self->shade_hover ? theme_config.a_hover_focused_shade
+ : theme_config.a_focused_unpressed_shade))));
+ c
+ = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ? theme_config.a_disabled_focused_close
+ : (self->close_press ? theme_config.a_focused_pressed_close
+ : (self->close_hover ? theme_config.a_hover_focused_close
+ : theme_config.a_focused_unpressed_close)));
+ }
+ else {
+ t = self->a_unfocused_title;
+ l = self->a_unfocused_label;
+ m
+ = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ? theme_config.a_disabled_unfocused_max
+ : (self->client->max_vert || self->client->max_horz ? (self->max_press ? theme_config.a_toggled_unfocused_pressed_max
+ : (self->max_hover ? theme_config.a_toggled_hover_unfocused_max
+ : theme_config.a_toggled_unfocused_unpressed_max))
+ : (self->max_press ? theme_config.a_unfocused_pressed_max
+ : (self->max_hover ? theme_config.a_hover_unfocused_max
+ : theme_config.a_unfocused_unpressed_max))));
+ n = self->a_icon;
+ i
+ = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ? theme_config.a_disabled_unfocused_iconify
+ : (self->iconify_press ? theme_config.a_unfocused_pressed_iconify
+ : (self->iconify_hover ? theme_config.a_hover_unfocused_iconify
+ : theme_config.a_unfocused_unpressed_iconify)));
+ d
+ = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ? theme_config.a_disabled_unfocused_desk
+ : (self->client->desktop == DESKTOP_ALL ? (self->desk_press ? theme_config.a_toggled_unfocused_pressed_desk
+ : (self->desk_hover ? theme_config.a_toggled_hover_unfocused_desk
+ : theme_config.a_toggled_unfocused_unpressed_desk))
+ : (self->desk_press ? theme_config.a_unfocused_pressed_desk
+ : (self->desk_hover ? theme_config.a_hover_unfocused_desk
+ : theme_config.a_unfocused_unpressed_desk))));
+ s
+ = (!(self->decorations & OB_FRAME_DECOR_SHADE) ? theme_config.a_disabled_unfocused_shade
+ : (self->client->shaded ? (self->shade_press ? theme_config.a_toggled_unfocused_pressed_shade
+ : (self->shade_hover ? theme_config.a_toggled_hover_unfocused_shade
+ : theme_config.a_toggled_unfocused_unpressed_shade))
+ : (self->shade_press ? theme_config.a_unfocused_pressed_shade
+ : (self->shade_hover ? theme_config.a_hover_unfocused_shade
+ : theme_config.a_unfocused_unpressed_shade))));
+ c
+ = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ? theme_config.a_disabled_unfocused_close
+ : (self->close_press ? theme_config.a_unfocused_pressed_close
+ : (self->close_hover ? theme_config.a_hover_unfocused_close
+ : theme_config.a_unfocused_unpressed_close)));
+ }
+ clear = theme_config.a_clear;
+
+ RrPaint(t, self->title, self->width, theme_config.title_height);
+
+ clear->surface.parent = t;
+ clear->surface.parenty = 0;
+
+ clear->surface.parentx = theme_config.grip_width;
+
+ RrPaint(clear, self->topresize, self->width - theme_config.grip_width
+ * 2, theme_config.paddingy + 1);
+
+ clear->surface.parentx = 0;
+
+ if (theme_config.grip_width > 0)
+ RrPaint(clear, self->tltresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+ if (theme_config.title_height > 0)
+ RrPaint(clear, self->tllresize, theme_config.paddingx + 1,
+ theme_config.title_height);
+
+ clear->surface.parentx = self->width - theme_config.grip_width;
+
+ if (theme_config.grip_width > 0)
+ RrPaint(clear, self->trtresize, theme_config.grip_width,
+ theme_config.paddingy + 1);
+
+ clear->surface.parentx = self->width - (theme_config.paddingx + 1);
+
+ if (theme_config.title_height > 0)
+ RrPaint(clear, self->trrresize, theme_config.paddingx + 1,
+ theme_config.title_height);
+
+ /* set parents for any parent relative guys */
+ l->surface.parent = t;
+ l->surface.parentx = self->label_x;
+ l->surface.parenty = theme_config.paddingy;
+
+ m->surface.parent = t;
+ m->surface.parentx = self->max_x;
+ m->surface.parenty = theme_config.paddingy + 1;
+
+ n->surface.parent = t;
+ n->surface.parentx = self->icon_x;
+ n->surface.parenty = theme_config.paddingy;
+
+ i->surface.parent = t;
+ i->surface.parentx = self->iconify_x;
+ i->surface.parenty = theme_config.paddingy + 1;
+
+ d->surface.parent = t;
+ d->surface.parentx = self->desk_x;
+ d->surface.parenty = theme_config.paddingy + 1;
+
+ s->surface.parent = t;
+ s->surface.parentx = self->shade_x;
+ s->surface.parenty = theme_config.paddingy + 1;
+
+ c->surface.parent = t;
+ c->surface.parentx = self->close_x;
+ c->surface.parenty = theme_config.paddingy + 1;
+
+ framerender_label(self, l);
+ framerender_max(self, m);
+ framerender_icon(self, n);
+ framerender_iconify(self, i);
+ framerender_desk(self, d);
+ framerender_shade(self, s);
+ framerender_close(self, c);
+ }
+
+ if (self->decorations & OB_FRAME_DECOR_HANDLE && theme_config.handle_height
+ > 0) {
+ RrAppearance *h, *g;
+
+ h = (self->focused ? self->a_focused_handle : self->a_unfocused_handle);
+
+ RrPaint(h, self->handle, self->width, theme_config.handle_height);
+
+ if (self->decorations & OB_FRAME_DECOR_GRIPS) {
+ g = (self->focused ? theme_config.a_focused_grip
+ : theme_config.a_unfocused_grip);
+
+ if (g->surface.grad == RR_SURFACE_PARENTREL)
+ g->surface.parent = h;
+
+ g->surface.parentx = 0;
+ g->surface.parenty = 0;
+
+ RrPaint(g, self->lgrip, theme_config.grip_width,
+ theme_config.handle_height);
+
+ g->surface.parentx = self->width - theme_config.grip_width;
+ g->surface.parenty = 0;
+
+ RrPaint(g, self->rgrip, theme_config.grip_width,
+ theme_config.handle_height);
+ }
+ }
+
+ XFlush(plugin.ob_display);
+}
+
+static void framerender_label(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->label_on)
+ return;
+ /* set the texture's text! */
+ a->texture[0].data.text.string = self->client->title;
+ RrPaint(a, self->label, self->label_width, theme_config.label_height);
+}
+
+static void framerender_icon(ObDefaultFrame *self, RrAppearance *a)
+{
+ const ObClientIcon *icon;
+
+ if (!self->icon_on)
+ return;
+
+ icon = client_icon(self->client, theme_config.button_size + 2,
+ theme_config.button_size + 2);
+ if (icon) {
+ a->texture[0].type = RR_TEXTURE_RGBA;
+ a->texture[0].data.rgba.width = icon->width;
+ a->texture[0].data.rgba.height = icon->height;
+ a->texture[0].data.rgba.alpha = 0xff;
+ a->texture[0].data.rgba.data = icon->data;
+ }
+ else
+ a->texture[0].type = RR_TEXTURE_NONE;
+
+ RrPaint(a, self->icon, theme_config.button_size + 2,
+ theme_config.button_size + 2);
+}
+
+static void framerender_max(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->max_on)
+ return;
+ RrPaint(a, self->max, theme_config.button_size, theme_config.button_size);
+}
+
+static void framerender_iconify(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->iconify_on)
+ return;
+ RrPaint(a, self->iconify, theme_config.button_size,
+ theme_config.button_size);
+}
+
+static void framerender_desk(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->desk_on)
+ return;
+ RrPaint(a, self->desk, theme_config.button_size, theme_config.button_size);
+}
+
+static void framerender_shade(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->shade_on)
+ return;
+ RrPaint(a, self->shade, theme_config.button_size, theme_config.button_size);
+}
+
+static void framerender_close(ObDefaultFrame *self, RrAppearance *a)
+{
+ if (!self->close_on)
+ return;
+ RrPaint(a, self->close, theme_config.button_size, theme_config.button_size);
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ frame_minimal_render.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#ifndef FRAME_MINIMAL_RENDER_H_
+#define __framerender_h
+
+#include "frame_minimal_plugin.h"
+
+void framerender_frame(gpointer self);
+
+#endif
*/
#include "misc.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "obt/parse.h"
#include <glib.h>
#include "openbox/actions.h"
#include "openbox/misc.h"
#include "openbox/client.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
#include "openbox/screen.h"
#include <glib.h>
#include "openbox/actions.h"
#include "openbox/misc.h"
#include "openbox/client.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
#include "openbox/screen.h"
#include "openbox/focus.h"
#include <glib.h>
#include "openbox/actions.h"
#include "openbox/client.h"
#include "openbox/screen.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
#include <stdlib.h> /* for atoi */
typedef struct {
#include "openbox/actions.h"
#include "openbox/client.h"
#include "openbox/screen.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
+#include "openbox/openbox.h"
+
#include <stdlib.h> /* for atoi */
enum {
y = c->area.y;
client_try_configure(c, &x, &y, &w, &h, &lw, &lh, TRUE);
+ Strut c_size = render_plugin->frame_get_size(c->frame);
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
/* get the frame's size */
- w += c->frame->size.left + c->frame->size.right;
- h += c->frame->size.top + c->frame->size.bottom;
+ w += c_size.left + c_size.right;
+ h += c_size.top + c_size.bottom;
x = o->x;
if (o->xcenter) x = (area->width - w) / 2;
- else if (x == G_MININT) x = c->frame->area.x - carea->x;
+ else if (x == G_MININT) x = c_area.x - carea->x;
else if (o->xopposite) x = area->width - w;
x += area->x;
y = o->y;
if (o->ycenter) y = (area->height - h) / 2;
- else if (y == G_MININT) y = c->frame->area.y - carea->y;
+ else if (y == G_MININT) y = c_area.y - carea->y;
else if (o->yopposite) y = area->height - h;
y += area->y;
/* get the client's size back */
- w -= c->frame->size.left + c->frame->size.right;
- h -= c->frame->size.top + c->frame->size.bottom;
+ w -= c_size.left + c_size.right;
+ h -= c_size.top + c_size.bottom;
- frame_frame_gravity(c->frame, &x, &y); /* get the client coords */
+ frame_frame_gravity(c, &x, &y); /* get the client coords */
client_try_configure(c, &x, &y, &w, &h, &lw, &lh, TRUE);
/* force it on screen if its moving to another monitor */
client_find_onscreen(c, &x, &y, w, h, mon != cmon);
#include "openbox/actions.h"
#include "openbox/misc.h"
#include "openbox/client.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
#include "openbox/geom.h"
#include <glib.h>
#include "openbox/actions.h"
#include "openbox/moveresize.h"
#include "openbox/client.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
+
+#include "openbox/openbox.h"
+
#include "obt/prop.h"
typedef struct {
ObClient *c = data->client;
guint32 corner;
+ Strut c_size = render_plugin->frame_get_size(c->frame);
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
if (!data->button)
corner = OBT_PROP_ATOM(NET_WM_MOVERESIZE_SIZE_KEYBOARD);
else if (o->corner_specified)
corner = o->corner; /* it was specified in the binding */
else
corner = pick_corner(data->x, data->y,
- c->frame->area.x, c->frame->area.y,
+ c_area.x, c_area.y,
/* use the client size because the frame
can be differently sized (shaded
windows) and we want this based on the
clients size */
- c->area.width + c->frame->size.left +
- c->frame->size.right,
- c->area.height + c->frame->size.top +
- c->frame->size.bottom, c->shaded);
+ c->area.width + c_size.left +
+ c_size.right,
+ c->area.height + c_size.top +
+ c_size.bottom, c->shaded);
moveresize_start(c, data->x, data->y, data->button, corner);
}
#include "openbox/actions.h"
#include "openbox/client.h"
#include "openbox/screen.h"
-#include "openbox/frame.h"
+#include "openbox/engine_interface.h"
#include <stdlib.h> /* for atoi */
typedef struct {
#include "moveresize.h"
#include "ping.h"
#include "place.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "session.h"
#include "event.h"
#include "grab.h"
#include "gettext.h"
#include "obt/display.h"
#include "obt/prop.h"
+#include "window.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
XChangeSaveSet(obt_display, window, SetModeInsert);
/* create the decoration frame for the client window */
- self->frame = frame_new(self);
-
- frame_grab_client(self->frame);
+ self->frame = render_plugin->frame_new(self);
+ render_plugin->frame_grab(self->frame, window_map);
/* we've grabbed everything and set everything that we need to at mapping
time now */
/* adjust the frame to the client's size before showing or placing
the window */
- frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
- frame_adjust_client_area(self->frame);
+ render_plugin->frame_set_client_area (self->frame, self->area);
+ render_plugin->frame_set_hover_flag (self->frame, OB_BUTTON_NONE);
+ render_plugin->frame_set_press_flag (self->frame, OB_BUTTON_NONE);
+ render_plugin->frame_set_is_focus (self->frame, FALSE);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, FALSE, TRUE);
+ render_plugin->frame_update_skin (self->frame);
/* where the frame was placed is where the window was originally */
place = self->area;
{
Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &place);
+ Strut size = render_plugin->frame_get_size(self->frame);
/* get the size of the frame */
- place.width += self->frame->size.left + self->frame->size.right;
- place.height += self->frame->size.top + self->frame->size.bottom;
+ place.width += size.left + size.right;
+ place.height += size.top + size.bottom;
/* fit the window inside the area */
place.width = MIN(place.width, a->width);
ob_debug("setting window size to %dx%d", place.width, place.height);
/* get the size of the client back */
- place.width -= self->frame->size.left + self->frame->size.right;
- place.height -= self->frame->size.top + self->frame->size.bottom;
+ place.width -= size.left + size.right;
+ place.height -= size.top + size.bottom;
g_free(a);
}
self->window, map_time, launch_time,
event_last_user_time);
- if (menu_frame_visible || moveresize_in_progress) {
+ if (menu_frame_visible || render_plugin->moveresize_in_progress) {
activate = FALSE;
raise = TRUE;
ob_debug_type(OB_DEBUG_FOCUS,
g_free(settings);
ob_debug("Managed window 0x%lx plate 0x%x (%s)",
- window, self->frame->window, self->class);
+ window, render_plugin->frame_get_window(self->frame), self->class);
}
client_setup_decor_and_functions(self, FALSE);
/* create the decoration frame for the client window and adjust its size */
- self->frame = frame_new(self);
- frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
+ self->frame = render_plugin->frame_new(self);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, FALSE, FALSE);
ob_debug("gave extents left %d right %d top %d bottom %d",
- self->frame->size.left, self->frame->size.right,
- self->frame->size.top, self->frame->size.bottom);
+ render_plugin->frame_get_size(self->frame).left, render_plugin->frame_get_size(self->frame).right,
+ render_plugin->frame_get_size(self->frame).top, render_plugin->frame_get_size(self->frame).bottom);
/* free the ObAppSettings shallow copy */
g_free(settings);
gulong ignore_start;
ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)",
- self->window, self->frame->window,
+ self->window, render_plugin->frame_get_window(self->frame),
self->class, self->title ? self->title : "");
g_assert(self != NULL);
if (!config_focus_under_mouse)
ignore_start = event_start_ignore_all_enters();
- frame_hide(self->frame);
+ self->ignore_unmaps += render_plugin->frame_hide(self->frame);
/* flush to send the hide to the server quickly */
XFlush(obt_display);
}
/* reparent the window out of the frame, and free the frame */
- frame_release_client(self->frame);
- frame_free(self->frame);
+ render_plugin->frame_ungrab(self->frame, window_map);
+ render_plugin->frame_free(self->frame);
self->frame = NULL;
if (ob_state() != OB_STATE_EXITING) {
{
/* this is all that got allocated to get the decorations */
- frame_free(self->frame);
+ render_plugin->frame_free(self->frame);
g_free(self);
}
self->max_horz = self->session->max_horz;
self->max_vert = self->session->max_vert;
self->undecorated = self->session->undecorated;
+
+ render_plugin->frame_set_is_max_horz (self->frame, self->max_horz);
+ render_plugin->frame_set_is_max_vert (self->frame, self->max_vert);
}
static gboolean client_restore_session_stacking(ObClient *self)
gboolean found_mon;
RECT_SET(desired, *x, *y, w, h);
- frame_rect_to_frame(self->frame, &desired);
+ frame_rect_to_frame(self, &desired);
/* get where the frame would be */
- frame_client_gravity(self->frame, x, y);
+ frame_client_gravity(self, x, y);
+
+ Strut size = render_plugin->frame_get_size(self->frame);
/* get the requested size of the window with decorations */
- fw = self->frame->size.left + w + self->frame->size.right;
- fh = self->frame->size.top + h + self->frame->size.bottom;
+ fw = size.left + w + size.right;
+ fh = size.top + h + size.bottom;
/* If rudeness wasn't requested, then still be rude in a given direction
if the client is not moving, only resizing in that direction */
Point newtl, newtr, newbl, newbr;
gboolean stationary_l, stationary_r, stationary_t, stationary_b;
- POINT_SET(oldtl, self->frame->area.x, self->frame->area.y);
- POINT_SET(oldbr, self->frame->area.x + self->frame->area.width - 1,
- self->frame->area.y + self->frame->area.height - 1);
+ Rect area = render_plugin->frame_get_window_area(self->frame);
+ POINT_SET(oldtl, area.x, area.y);
+ POINT_SET(oldbr, area.x + area.width - 1,
+ area.y + area.height - 1);
POINT_SET(oldtr, oldbr.x, oldtl.y);
POINT_SET(oldbl, oldtl.x, oldbr.y);
}
/* get where the client should be */
- frame_frame_gravity(self->frame, x, y);
+ frame_frame_gravity(self, x, y);
return ox != *x || oy != *y;
}
self->max_vert)) {
if (self->frame) client_maximize(self, FALSE, 0);
else self->max_vert = self->max_horz = FALSE;
+ render_plugin->frame_set_is_max_horz (self->frame, self->max_horz);
+ render_plugin->frame_set_is_max_vert (self->frame, self->max_vert);
}
}
self->title = visible;
if (self->frame)
- frame_adjust_title(self->frame);
+ render_plugin->frame_update_layout (self->frame, FALSE, FALSE);
/* update the icon title */
data = NULL;
OBT_PROP_SETA32(self->window, NET_WM_ICON, CARDINAL, data, 48*48+2);
g_free(data);
} else if (self->frame)
+ render_plugin->frame_update_skin (self->frame);
/* don't draw the icon empty if we're just setting one now anyways,
we'll get the property change any second */
- frame_adjust_icon(self->frame);
+ //frame_adjust_icon(self->frame);
}
void client_update_icon_geometry(ObClient *self)
OBT_PROP_SETA32(self->window, NET_WM_STATE, ATOM, netstate, num);
if (self->frame)
- frame_adjust_state(self->frame);
+ render_plugin->frame_update_layout (self->frame, FALSE, FALSE);
}
ObClient *client_search_focus_tree(ObClient *self)
should be going to something under the window */
mouse_replay_pointer();
- frame_show(self->frame);
+ render_plugin->frame_show(self->frame);
show = TRUE;
/* According to the ICCCM (sec 4.1.3.1) when a window is not visible,
should be going to the window */
mouse_replay_pointer();
- frame_hide(self->frame);
+ self->ignore_unmaps += render_plugin->frame_hide(self->frame);
hide = TRUE;
/* According to the ICCCM (sec 4.1.3.1) when a window is not visible,
/* save the area, and make it where it should be for the premax stuff */
oldarea = self->area;
RECT_SET(self->area, x, y, w, h);
+ render_plugin->frame_set_client_area (self->frame, self->area);
/* apply the states. these are in a carefully crafted order.. */
not, so this needs to be called even if we have fullscreened/maxed
*/
self->area = oldarea;
+ render_plugin->frame_set_client_area (self->frame, self->area);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, FALSE, FALSE);
+ render_plugin->frame_set_is_max_horz (self->frame, self->max_horz);
+ render_plugin->frame_set_is_max_vert (self->frame, self->max_vert);
client_configure(self, x, y, w, h, FALSE, TRUE, FALSE);
/* set the desktop hint, to make sure that it always exists */
gboolean user)
{
Rect desired = {*x, *y, *w, *h};
- frame_rect_to_frame(self->frame, &desired);
+ frame_rect_to_frame(self, &desired);
/* make the frame recalculate its dimentions n shit without changing
anything visible for real, this way the constraints below can work with
the updated frame dimensions. */
- frame_adjust_area(self->frame, FALSE, TRUE, TRUE);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, FALSE, TRUE);
/* gets the frame's position */
- frame_client_gravity(self->frame, x, y);
+ frame_client_gravity(self, x, y);
/* these positions are frame positions, not client positions */
a = screen_area(self->desktop, i,
(self->max_horz && self->max_vert ? NULL : &desired));
+ Strut size = render_plugin->frame_get_size(self->frame);
/* set the size and position if maximized */
if (self->max_horz) {
*x = a->x;
- *w = a->width - self->frame->size.left - self->frame->size.right;
+ *w = a->width - size.left - size.right;
}
if (self->max_vert) {
*y = a->y;
- *h = a->height - self->frame->size.top - self->frame->size.bottom;
+ *h = a->height - size.top - size.bottom;
}
user = FALSE; /* ignore if the client can't be moved/resized when it
}
/* gets the client's position */
- frame_frame_gravity(self->frame, x, y);
+ frame_frame_gravity(self, x, y);
/* work within the prefered sizes given by the window */
if (!(*w == self->area.width && *h == self->area.height)) {
gboolean send_resize_client;
gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
gboolean fmoved, fresized;
- guint fdecor = self->frame->decorations;
- gboolean fhorz = self->frame->max_horz;
- gboolean fvert = self->frame->max_vert;
+ guint fdecor = render_plugin->frame_get_decorations(self->frame);
+ gboolean fhorz = render_plugin->frame_is_max_horz(self->frame);
+ gboolean fvert = render_plugin->frame_is_max_vert(self->frame);
gint logicalw, logicalh;
+ Strut size = render_plugin->frame_get_size(self->frame);
+ Rect area = render_plugin->frame_get_window_area(self->frame);
+
/* find the new x, y, width, and height (and logical size) */
client_try_configure(self, &x, &y, &w, &h, &logicalw, &logicalh, user);
oldw = self->area.width;
oldh = self->area.height;
- oldframe = self->frame->area;
+ oldframe = render_plugin->frame_get_window_area(self->frame);
RECT_SET(self->area, x, y, w, h);
+ render_plugin->frame_set_client_area (self->frame, self->area);
+
/* for app-requested resizes, always resize if 'resized' is true.
for user-requested ones, only resize if final is true, or when
resizing in redraw mode */
/* if the client is enlarging, then resize the client before the frame */
if (send_resize_client && (w > oldw || h > oldh)) {
- XMoveResizeWindow(obt_display, self->window,
- self->frame->size.left, self->frame->size.top,
- MAX(w, oldw), MAX(h, oldh));
- frame_adjust_client_area(self->frame);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, FALSE, FALSE);
}
/* find the frame's dimensions and move/resize it */
would change what window gets the event */
mouse_replay_pointer();
- frame_adjust_area(self->frame, fmoved, fresized, FALSE);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, TRUE, FALSE);
if (!user)
event_end_ignore_all_enters(ignore_start);
/* we have reset the client to 0 border width, so don't include
it in these coords */
POINT_SET(self->root_pos,
- self->frame->area.x + self->frame->size.left -
+ area.x + size.left -
self->border_width,
- self->frame->area.y + self->frame->size.top -
+ area.y + size.top -
self->border_width);
if (self->root_pos.x != oldrx || self->root_pos.y != oldry)
rootmoved = TRUE;
in the direction that is growing
*/
if (send_resize_client && (w <= oldw || h <= oldh)) {
- frame_adjust_client_area(self->frame);
- XMoveResizeWindow(obt_display, self->window,
- self->frame->size.left, self->frame->size.top, w, h);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout (self->frame, FALSE, FALSE);
}
XFlush(obt_display);
/* if it moved between monitors, then this can affect the stacking
layer of this window or others - for fullscreen windows */
- if (screen_find_monitor(&self->frame->area) !=
+ Rect current_frame = render_plugin->frame_get_window_area(self->frame);
+ if (screen_find_monitor(¤t_frame) !=
screen_find_monitor(&oldframe))
{
client_calc_layer(self);
if (changed) {
client_change_state(self);
if (config_animate_iconify && !hide_animation)
- frame_begin_iconify_animation(self->frame, iconic);
+ render_plugin->frame_begin_iconify_animation(self->frame, iconic);
/* do this after starting the animation so it doesn't flash */
client_showhide(self);
}
if (dir == 0 || dir == 2) /* vert */
self->max_vert = max;
+ render_plugin->frame_set_is_max_horz (self->frame, self->max_horz);
+ render_plugin->frame_set_is_max_vert (self->frame, self->max_vert);
+
client_change_state(self); /* change the state hints on the client */
client_setup_decor_and_functions(self, FALSE);
client_change_state(self);
client_change_wm_state(self); /* the window is being hidden/shown */
/* resize the frame to just the titlebar */
- frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+ render_plugin->frame_set_is_shaded (self->frame, self->shaded);
+ render_plugin->frame_update_layout(self->frame, FALSE, FALSE);
}
static void client_ping_event(ObClient *self, gboolean dead)
self->demands_attention = hilite && !client_focused(self);
if (self->frame != NULL) { /* if we're mapping, just set the state */
if (self->demands_attention)
- frame_flash_start(self->frame);
+ render_plugin->frame_flash_start(self->frame);
else
- frame_flash_stop(self->frame);
+ render_plugin->frame_flash_stop(self->frame);
client_change_state(self);
}
}
self->desktop = target;
OBT_PROP_SET32(self->window, NET_WM_DESKTOP, CARDINAL, target);
/* the frame can display the current desktop state */
- frame_adjust_state(self->frame);
+ render_plugin->frame_set_decorations (self->frame, self->decorations);
+ render_plugin->frame_update_layout(self->frame, FALSE, FALSE);
/* 'move' the window to the new desktop */
if (!donthide)
client_hide(self);
/* choose the correct target */
self = client_focus_target(self);
- if (!self->frame->visible)
+ if (!render_plugin->frame_is_visible(self->frame))
return FALSE;
if (!(self->can_focus || self->focus_notify))
client_set_desktop(self, screen_desktop, FALSE, TRUE);
else
screen_set_desktop(self->desktop, FALSE);
- } else if (!self->frame->visible)
+ } else if (!render_plugin->frame_is_visible(self->frame))
/* if its not visible for other reasons, then don't mess
with it */
return;
guint client_monitor(ObClient *self)
{
- return screen_find_monitor(&self->frame->area);
+ Rect area = render_plugin->frame_get_window_area(self->frame);
+ return screen_find_monitor(&area);
}
ObClient *client_direct_parent(ObClient *self)
Rect dock_area;
gint edge;
+ Strut size = render_plugin->frame_get_size(self->frame);
+ Rect area = render_plugin->frame_get_window_area(self->frame);
+
a = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS,
- &self->frame->area);
+ &area);
mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR,
- &self->frame->area);
+ &area);
switch (dir) {
case OB_DIRECTION_NORTH:
ob_debug("trying window %s", cur->title);
- detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start,
+ detect_edge(render_plugin->frame_get_window_area(cur->frame), dir, my_head, my_size, my_edge_start,
my_edge_size, dest, near_edge);
}
dock_get_area(&dock_area);
gint e, e_start, e_size;
gboolean near;
+
+ Rect area = render_plugin->frame_get_window_area(self->frame);
+
switch (dir) {
case OB_DIRECTION_EAST:
- head = RECT_RIGHT(self->frame->area);
- size = self->frame->area.width;
- e_start = RECT_TOP(self->frame->area);
- e_size = self->frame->area.height;
+ head = RECT_RIGHT(area);
+ size = area.width;
+ e_start = RECT_TOP(area);
+ e_size = area.height;
break;
case OB_DIRECTION_WEST:
- head = RECT_LEFT(self->frame->area);
- size = self->frame->area.width;
- e_start = RECT_TOP(self->frame->area);
- e_size = self->frame->area.height;
+ head = RECT_LEFT(area);
+ size = area.width;
+ e_start = RECT_TOP(area);
+ e_size = area.height;
break;
case OB_DIRECTION_NORTH:
- head = RECT_TOP(self->frame->area);
- size = self->frame->area.height;
- e_start = RECT_LEFT(self->frame->area);
- e_size = self->frame->area.width;
+ head = RECT_TOP(area);
+ size = area.height;
+ e_start = RECT_LEFT(area);
+ e_size = area.width;
break;
case OB_DIRECTION_SOUTH:
- head = RECT_BOTTOM(self->frame->area);
- size = self->frame->area.height;
- e_start = RECT_LEFT(self->frame->area);
- e_size = self->frame->area.width;
+ head = RECT_BOTTOM(area);
+ size = area.height;
+ e_start = RECT_LEFT(area);
+ e_size = area.width;
break;
default:
g_assert_not_reached();
client_find_edge_directional(self, dir, head, size,
e_start, e_size, &e, &near);
- *x = self->frame->area.x;
- *y = self->frame->area.y;
+ *x = area.x;
+ *y = area.y;
switch (dir) {
case OB_DIRECTION_EAST:
- if (near) e -= self->frame->area.width;
+ if (near) e -= area.width;
else e++;
*x = e;
break;
case OB_DIRECTION_WEST:
if (near) e++;
- else e -= self->frame->area.width;
+ else e -= area.width;
*x = e;
break;
case OB_DIRECTION_NORTH:
if (near) e++;
- else e -= self->frame->area.height;
+ else e -= area.height;
*y = e;
break;
case OB_DIRECTION_SOUTH:
- if (near) e -= self->frame->area.height;
+ if (near) e -= area.height;
else e++;
*y = e;
break;
default:
g_assert_not_reached();
}
- frame_frame_gravity(self->frame, x, y);
+ frame_frame_gravity(self, x, y);
}
void client_find_resize_directional(ObClient *self, ObDirection side,
gboolean near;
ObDirection dir;
+ Rect area = render_plugin->frame_get_window_area(self->frame);
+ Strut size = render_plugin->frame_get_size(self->frame);
+
switch (side) {
case OB_DIRECTION_EAST:
- head = RECT_RIGHT(self->frame->area) +
+ head = RECT_RIGHT(area) +
(self->size_inc.width - 1) * (grow ? 1 : -1);
- e_start = RECT_TOP(self->frame->area);
- e_size = self->frame->area.height;
+ e_start = RECT_TOP(area);
+ e_size = area.height;
dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST;
break;
case OB_DIRECTION_WEST:
- head = RECT_LEFT(self->frame->area) -
+ head = RECT_LEFT(area) -
(self->size_inc.width - 1) * (grow ? 1 : -1);
- e_start = RECT_TOP(self->frame->area);
- e_size = self->frame->area.height;
+ e_start = RECT_TOP(area);
+ e_size = area.height;
dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST;
break;
case OB_DIRECTION_NORTH:
- head = RECT_TOP(self->frame->area) -
+ head = RECT_TOP(area) -
(self->size_inc.height - 1) * (grow ? 1 : -1);
- e_start = RECT_LEFT(self->frame->area);
- e_size = self->frame->area.width;
+ e_start = RECT_LEFT(area);
+ e_size = area.width;
dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH;
break;
case OB_DIRECTION_SOUTH:
- head = RECT_BOTTOM(self->frame->area) +
+ head = RECT_BOTTOM(area) +
(self->size_inc.height - 1) * (grow ? 1 : -1);
- e_start = RECT_LEFT(self->frame->area);
- e_size = self->frame->area.width;
+ e_start = RECT_LEFT(area);
+ e_size = area.width;
dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH;
break;
default:
client_find_edge_directional(self, dir, head, 1,
e_start, e_size, &e, &near);
ob_debug("edge %d", e);
- *x = self->frame->area.x;
- *y = self->frame->area.y;
- *w = self->frame->area.width;
- *h = self->frame->area.height;
+ *x = area.x;
+ *y = area.y;
+ *w = area.width;
+ *h = area.height;
switch (side) {
case OB_DIRECTION_EAST:
if (grow == near) --e;
- delta = e - RECT_RIGHT(self->frame->area);
+ delta = e - RECT_RIGHT(area);
*w += delta;
break;
case OB_DIRECTION_WEST:
if (grow == near) ++e;
- delta = RECT_LEFT(self->frame->area) - e;
+ delta = RECT_LEFT(area) - e;
*x -= delta;
*w += delta;
break;
case OB_DIRECTION_NORTH:
if (grow == near) ++e;
- delta = RECT_TOP(self->frame->area) - e;
+ delta = RECT_TOP(area) - e;
*y -= delta;
*h += delta;
break;
case OB_DIRECTION_SOUTH:
if (grow == near) --e;
- delta = e - RECT_BOTTOM(self->frame->area);
+ delta = e - RECT_BOTTOM(area);
*h += delta;
break;
default:
g_assert_not_reached();
}
- frame_frame_gravity(self->frame, x, y);
- *w -= self->frame->size.left + self->frame->size.right;
- *h -= self->frame->size.top + self->frame->size.bottom;
+ frame_frame_gravity(self, x, y);
+ *w -= size.left + size.right;
+ *h -= size.top + size.bottom;
}
ObClient* client_under_pointer(void)
for (it = stacking_list; it; it = g_list_next(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = WINDOW_AS_CLIENT(it->data);
- if (c->frame->visible &&
+ if (render_plugin->frame_is_visible(c->frame) &&
/* check the desktop, this is done during desktop
switching and windows are shown/hidden status is not
reliable */
(c->desktop == screen_desktop ||
c->desktop == DESKTOP_ALL) &&
/* ignore all animating windows */
- !frame_iconify_animating(c->frame) &&
- RECT_CONTAINS(c->frame->area, x, y))
+ !(render_plugin->frame_iconify_animating(c->frame)) &&
+ RECT_CONTAINS(render_plugin->frame_get_window_area(c->frame), x, y))
{
ret = c;
break;
#include "client.h"
#include "client_menu.h"
#include "openbox.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "moveresize.h"
#include "event.h"
#include "gettext.h"
gint dx, dy;
if (!mouse && frame->client) {
- *x = frame->client->frame->area.x;
+
+ Strut size = render_plugin->frame_get_size(frame->client->frame);
+ Rect area = render_plugin->frame_get_window_area(frame->client->frame);
+
+ *x = area.x;
/* try below the titlebar */
- *y = frame->client->frame->area.y + frame->client->frame->size.top -
- frame->client->frame->bwidth;
+ *y = area.y + size.top;
menu_frame_move_on_screen(frame, *x, *y, &dx, &dy);
if (dy != 0) {
/* try above the titlebar */
- *y = frame->client->frame->area.y + frame->client->frame->bwidth -
+ *y = area.y -
frame->area.height;
menu_frame_move_on_screen(frame, *x, *y, &dx, &dy);
}
if (dy != 0) {
/* didnt fit either way, use move on screen's values */
- *y = frame->client->frame->area.y + frame->client->frame->size.top;
+ *y = area.y + size.top;
menu_frame_move_on_screen(frame, *x, *y, &dx, &dy);
}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ keyboard.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+
+#include "engine_interface.h"
+#include "config.h"
+#include "debug.h"
+#include "openbox.h"
+#include "obt/paths.h"
+
+#define SHARED_SUFFIX ".la"
+#define PLUGIN_PATH "/.config/openbox/engines/"
+
+gchar *create_class_name(const gchar *rname);
+
+/* Load XrmDatabase */
+XrmDatabase loaddb(const gchar *name, gchar **path);
+
+/* Read string in XrmDatabase */
+gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value);
+
+ObFramePlugin * init_frame_plugin(const gchar *name, gboolean allow_fallback,
+ RrFont *active_window_font, RrFont *inactive_window_font,
+ RrFont *menu_title_font, RrFont *menu_item_font, RrFont *osd_font)
+{
+ XrmDatabase db = NULL;
+ gchar *path;
+
+ if (name) {
+ db = loaddb(name, &path);
+ if (db == NULL) {
+ g_message("Unable to load the theme '%s'", name);
+ if (allow_fallback)
+ //g_message("Falling back to the default theme '%s'", DEFAULT_THEME);
+ /* fallback to the default theme */
+ name = NULL;
+ }
+ }
+ if (name == NULL) {
+ if (allow_fallback) {
+ //db = loaddb(DEFAULT_THEME, &path);
+ db = NULL;
+ if (db == NULL) {
+ //g_message("Unable to load the theme '%s'", DEFAULT_THEME);
+ return 0;
+ }
+ }
+ else
+ return 0;
+ }
+
+ gchar * plugin_filename;
+ if (!read_string(db, "frame.theme.engine", &plugin_filename)) {
+ plugin_filename = "libdefault.la";
+ }
+ ob_debug("Try to init : %s", plugin_filename);
+ gchar * absolute_plugin_filename = g_build_filename(g_get_home_dir(),
+ ".config", "openbox", "engines", plugin_filename, NULL);
+ ObFramePlugin * p = load_frame_plugin(absolute_plugin_filename);
+ g_free(absolute_plugin_filename);
+
+ update_frame_plugin(p);
+
+ (p->load_theme_config)(ob_rr_inst, name, path, db, active_window_font,
+ inactive_window_font, menu_title_font, menu_item_font, osd_font);
+
+ g_free(path);
+ XrmDestroyDatabase(db);
+
+ return p;
+}
+
+void update_frame_plugin(ObFramePlugin * self)
+{
+ self->ob_display = obt_display;
+ self->ob_screen = ob_screen;
+ self->ob_rr_inst = ob_rr_inst;
+ self->config_theme_keepborder = config_theme_keepborder;
+ self->config_title_layout = config_title_layout;
+ self->ob_main_loop = ob_main_loop;
+}
+
+ObFramePlugin * load_frame_plugin(const gchar * filename)
+{
+ GModule *module;
+ gpointer func;
+
+ if (!(module = g_module_open(filename, G_MODULE_BIND_LOCAL))) {
+ ob_debug_type(OB_DEBUG_SM, "Failed to load plugin (%s): %s\n",
+ filename, g_module_error());
+ exit(1);
+ }
+
+ if (g_module_symbol(module, "get_info", &func)) {
+ ObFramePlugin *plugin = (ObFramePlugin *) ((ObFramePluginFunc) func)();
+ return plugin;
+ }
+ else {
+ ob_debug_type(OB_DEBUG_SM,
+ "Failed to get \"get_info\" function (%s): %s\n", filename,
+ g_module_error());
+ exit(1);
+ }
+
+ ob_debug_type(OB_DEBUG_SM, "Invalid plugin (%s)\n", filename);
+ g_module_close(module);
+ exit(1);
+}
+/*
+ static gboolean scan_plugin_func(const gchar * path, const gchar * basename,
+ gpointer data)
+ {
+ if (!str_has_suffix_nocase(basename, SHARED_SUFFIX))
+ return FALSE;
+
+ if (!g_file_test(path, G_FILE_TEST_IS_REGULAR))
+ return FALSE;
+
+ add_plugin(path);
+
+ return FALSE;
+ }
+
+ static void scan_plugins(const gchar * path)
+ {
+ dir_foreach(path, scan_plugin_func, NULL, NULL);
+ }
+ */
+gboolean read_string(XrmDatabase db, const gchar *rname, gchar **value)
+{
+ gboolean ret = FALSE;
+ gchar *rclass = create_class_name(rname);
+ gchar *rettype;
+ XrmValue retvalue;
+
+ if (XrmGetResource(db, rname, rclass, &rettype, &retvalue) && retvalue.addr
+ != NULL) {
+ *value = retvalue.addr;
+ ret = TRUE;
+ }
+
+ g_free(rclass);
+ return ret;
+}
+
+XrmDatabase loaddb(const gchar *name, gchar **path)
+{
+ GSList *it;
+ XrmDatabase db = NULL;
+ gchar *s;
+
+ if (name[0] == '/') {
+ s = g_build_filename(name, "openbox-3", "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+ else {
+ ObtPaths *p;
+
+ p = obt_paths_new();
+ /* XXX backwards compatibility, remove me sometime later */
+ s = g_build_filename(g_get_home_dir(), ".themes", name, "openbox-3",
+ "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+
+ for (it = obt_paths_data_dirs(p); !db && it; it = g_slist_next(it)) {
+ s = g_build_filename(it->data, "themes", name, "openbox-3",
+ "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+ }
+
+ if (db == NULL) {
+ s = g_build_filename(name, "themerc", NULL);
+ if ((db = XrmGetFileDatabase(s)))
+ *path = g_path_get_dirname(s);
+ g_free(s);
+ }
+
+ return db;
+}
+
+gchar *create_class_name(const gchar *rname)
+{
+ gchar *rclass = g_strdup(rname);
+ gchar *p = rclass;
+
+ while (TRUE) {
+ *p = toupper(*p);
+ p = strchr(p+1, '.');
+ if (p == NULL)
+ break;
+ ++p;
+ if (*p == '\0')
+ break;
+ }
+ return rclass;
+}
+
+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("Handle", 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 plugin_frame_context(ObClient *client, Window win, gint x, gint y)
+{
+ /* this part is commun to all plugin */
+ if (render_plugin->moveresize_in_progress)
+ return OB_FRAME_CONTEXT_MOVE_RESIZE;
+ if (win == obt_root(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;
+ }
+ /* this part is specific to the plugin */
+ return render_plugin->frame_context(client->frame, win, x, y);
+
+}
+
+void frame_client_gravity(ObClient *self, gint *x, gint *y)
+{
+ Strut size = render_plugin->frame_get_size(self->frame);
+ /* horizontal */
+ switch (self->gravity) {
+ default:
+ case NorthWestGravity:
+ case SouthWestGravity:
+ case WestGravity:
+ break;
+
+ case NorthGravity:
+ case SouthGravity:
+ case CenterGravity:
+ /* the middle of the client will be the middle of the frame */
+ *x -= (size.right - size.left) / 2;
+ break;
+
+ case NorthEastGravity:
+ case SouthEastGravity:
+ case EastGravity:
+ /* the right side of the client will be the right side of the frame */
+ *x -= size.right + size.left - self->border_width * 2;
+ break;
+
+ case ForgetGravity:
+ case StaticGravity:
+ /* the client's position won't move */
+ *x -= size.left - self->border_width;
+ break;
+ }
+
+ /* vertical */
+ switch (self->gravity) {
+ default:
+ case NorthWestGravity:
+ case NorthEastGravity:
+ case NorthGravity:
+ break;
+
+ case CenterGravity:
+ case EastGravity:
+ case WestGravity:
+ /* the middle of the client will be the middle of the frame */
+ *y -= (size.bottom - size.top) / 2;
+ break;
+
+ case SouthWestGravity:
+ case SouthEastGravity:
+ case SouthGravity:
+ /* the bottom of the client will be the bottom of the frame */
+ *y -= size.bottom + size.top - self->border_width * 2;
+ break;
+
+ case ForgetGravity:
+ case StaticGravity:
+ /* the client's position won't move */
+ *y -= size.top - self->border_width;
+ break;
+ }
+}
+
+void frame_frame_gravity(ObClient *self, gint *x, gint *y)
+{
+ Strut size = render_plugin->frame_get_size(self->frame);
+ /* horizontal */
+ switch (self->gravity) {
+ default:
+ case NorthWestGravity:
+ case WestGravity:
+ case SouthWestGravity:
+ break;
+ case NorthGravity:
+ case CenterGravity:
+ case SouthGravity:
+ /* the middle of the client will be the middle of the frame */
+ *x += (size.right - size.left) / 2;
+ break;
+ case NorthEastGravity:
+ case EastGravity:
+ case SouthEastGravity:
+ /* the right side of the client will be the right side of the frame */
+ *x += size.right + size.left - self->border_width * 2;
+ break;
+ case StaticGravity:
+ case ForgetGravity:
+ /* the client's position won't move */
+ *x += size.left - self->border_width;
+ break;
+ }
+
+ /* vertical */
+ switch (self->gravity) {
+ default:
+ case NorthWestGravity:
+ case NorthGravity:
+ case NorthEastGravity:
+ break;
+ case WestGravity:
+ case CenterGravity:
+ case EastGravity:
+ /* the middle of the client will be the middle of the frame */
+ *y += (size.bottom - size.top) / 2;
+ break;
+ case SouthWestGravity:
+ case SouthGravity:
+ case SouthEastGravity:
+ /* the bottom of the client will be the bottom of the frame */
+ *y += size.bottom + size.top - self->border_width * 2;
+ break;
+ case StaticGravity:
+ case ForgetGravity:
+ /* the client's position won't move */
+ *y += size.top - self->border_width;
+ break;
+ }
+}
+
+void frame_rect_to_frame(ObClient * self, Rect *r)
+{
+ Strut size = render_plugin->frame_get_size(self->frame);
+ r->width += size.left + size.right;
+ r->height += size.top + size.bottom;
+ frame_client_gravity(self, &r->x, &r->y);
+}
+
+void frame_rect_to_client(ObClient * self, Rect *r)
+{
+ Strut size = render_plugin->frame_get_size(self);
+ r->width -= size.left + size.right;
+ r->height -= size.top + size.bottom;
+ frame_frame_gravity(self, &r->x, &r->y);
+}
--- /dev/null
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+ plugin.h for the Openbox window manager
+ Copyright (c) 2003-2007 Dana Jansens
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ See the COPYING file for a copy of the GNU General Public License.
+ */
+#ifndef ENGINE_INTERFACE_H_
+#define ENGINE_INTERFACE_H_
+/* Thanks to BMP, XMMS, Audacious and glib project to enable plugin */
+#include "geom.h"
+#include "render/render.h"
+#include "render/theme.h"
+#include "obt/parse.h"
+#include "client.h"
+
+#include "obt/mainloop.h"
+
+#include <X11/Xresource.h>
+#include <gmodule.h>
+
+struct _RrTheme;
+struct _ObClient;
+
+typedef enum
+{
+ OB_FRAME_CONTEXT_NONE,
+ OB_FRAME_CONTEXT_DESKTOP,
+ OB_FRAME_CONTEXT_ROOT,
+ OB_FRAME_CONTEXT_CLIENT,
+ OB_FRAME_CONTEXT_TITLEBAR,
+ OB_FRAME_CONTEXT_FRAME,
+ OB_FRAME_CONTEXT_BLCORNER,
+ OB_FRAME_CONTEXT_BRCORNER,
+ OB_FRAME_CONTEXT_TLCORNER,
+ OB_FRAME_CONTEXT_TRCORNER,
+ OB_FRAME_CONTEXT_TOP,
+ OB_FRAME_CONTEXT_BOTTOM,
+ OB_FRAME_CONTEXT_LEFT,
+ OB_FRAME_CONTEXT_RIGHT,
+ OB_FRAME_CONTEXT_MAXIMIZE,
+ OB_FRAME_CONTEXT_ALLDESKTOPS,
+ OB_FRAME_CONTEXT_SHADE,
+ OB_FRAME_CONTEXT_ICONIFY,
+ OB_FRAME_CONTEXT_ICON,
+ OB_FRAME_CONTEXT_CLOSE,
+ /*! This is a special context, which occurs while dragging a window in
+ a move/resize */
+ OB_FRAME_CONTEXT_MOVE_RESIZE,
+ OB_FRAME_NUM_CONTEXTS
+} ObFrameContext;
+
+/*! The decorations the client window wants to be displayed on it */
+typedef enum
+{
+ OB_FRAME_DECOR_TITLEBAR = 1 << 0, /*!< Display a titlebar */
+ OB_FRAME_DECOR_HANDLE = 1 << 1, /*!< Display a handle (bottom) */
+ OB_FRAME_DECOR_GRIPS = 1 << 2, /*!< Display grips in the handle */
+ OB_FRAME_DECOR_BORDER = 1 << 3, /*!< Display a border */
+ OB_FRAME_DECOR_ICON = 1 << 4, /*!< Display the window's icon */
+ OB_FRAME_DECOR_ICONIFY = 1 << 5, /*!< Display an iconify button */
+ OB_FRAME_DECOR_MAXIMIZE = 1 << 6, /*!< Display a maximize button */
+ /*! Display a button to toggle the window's placement on
+ all desktops */
+ OB_FRAME_DECOR_ALLDESKTOPS = 1 << 7,
+ OB_FRAME_DECOR_SHADE = 1 << 8, /*!< Displays a shade button */
+ OB_FRAME_DECOR_CLOSE = 1 << 9 /*!< Display a close button */
+} ObFrameDecorations;
+
+typedef enum
+{
+ OB_BUTTON_NONE = 0,
+ OB_BUTTON_MAX = 1,
+ OB_BUTTON_CLOSE = 2,
+ OB_BUTTON_DESK = 3,
+ OB_BUTTON_SHADE = 4,
+ OB_BUTTON_ICONIFY = 5
+} ObFrameButton;
+
+typedef enum
+{
+ OB_FRAME_STATE_NORMAL,
+ OB_FRAME_STATE_INCONIFIED,
+ OB_FRAME_STATE_SHADED,
+ OB_FRAME_STATE_MAX,
+ OB_FRAME_STATE_MAX_VERT,
+ OB_FRAME_STATE_MAX_HORZ,
+ OB_FRAME_STATE_NO_BORDER
+} ObFrameState;
+
+struct _ObFramePlugin
+{
+ gpointer handler; // Currently not used.
+
+ gchar * filename;
+ gchar * name;
+
+ /* Function to init module */
+ gint (*init)(Display * display, gint screen);
+ /* Not curently used */
+ gint (*release)(void);
+
+ /* create a new frame, return the ID of frame */
+ gpointer (*frame_new)(struct _ObClient *c);
+ /* Free the frame */
+ void (*frame_free)(gpointer self);
+
+ void (*frame_show)(gpointer self);
+ gint (*frame_hide)(gpointer self);
+
+ void (*frame_adjust_theme)(gpointer self);
+ void (*frame_adjust_shape)(gpointer self);
+
+ /* Grab or Ungrab event */
+ void (*frame_grab)(gpointer self, GHashTable *);
+ void (*frame_ungrab)(gpointer self, GHashTable *);
+
+ /* Provide the context of the mouse */
+ ObFrameContext (*frame_context)(gpointer self, Window win, gint x, gint y);
+
+ void (*frame_set_is_visible)(gpointer, gboolean);
+ void (*frame_set_is_focus)(gpointer, gboolean);
+ void (*frame_set_is_max_vert)(gpointer, gboolean);
+ void (*frame_set_is_max_horz)(gpointer, gboolean);
+ void (*frame_set_is_shaded)(gpointer, gboolean);
+
+ void (*frame_flash_start)(gpointer self);
+ void (*frame_flash_stop)(gpointer self);
+ void (*frame_begin_iconify_animation)(gpointer self, gboolean iconifying);
+ void (*frame_end_iconify_animation)(gpointer self);
+ gboolean (*frame_iconify_animating)(gpointer p);
+
+ /* Set the layout wanted by client */
+ void (*frame_set_decorations)(gpointer, ObFrameDecorations);
+
+ /* get the current window area */
+ Rect (*frame_get_window_area)(gpointer);
+ /* set the requested client area */
+ void (*frame_set_client_area)(gpointer, Rect);
+ /* Draw the frame */
+ void (*frame_update_layout)(gpointer self, gboolean is_resize,
+ gboolean is_fake);
+ void (*frame_update_skin)(gpointer);
+
+ void (*frame_set_hover_flag)(gpointer, ObFrameButton);
+ void (*frame_set_press_flag)(gpointer, ObFrameButton);
+
+ Window (*frame_get_window)(gpointer);
+
+ Strut (*frame_get_size)(gpointer);
+ gint (*frame_get_decorations)(gpointer);
+
+ gboolean (*frame_is_visible)(gpointer);
+ gboolean (*frame_is_max_horz)(gpointer);
+ gboolean (*frame_is_max_vert)(gpointer);
+
+ gint (*load_theme_config)(const RrInstance *inst, const gchar *name,
+ const gchar * path, XrmDatabase db, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font);
+
+ /* Filled by openbox-core */
+ Display * ob_display;
+ gint ob_screen;
+ RrInstance *ob_rr_inst;
+ // Not more needed
+ //struct _RrTheme * ob_rr_theme;
+ gboolean config_theme_keepborder;
+ struct _ObClient *focus_cycle_target;
+ gchar *config_title_layout;
+ gboolean moveresize_in_progress;
+ struct _ObtMainLoop *ob_main_loop;
+};
+/* Define how to draw the current windows */
+enum _ObStyle
+{
+ OBSTYLE_DECOR,
+ OBSTYLE_NODECOR,
+ OBSTYLE_SHADE,
+ OBSTYLE_ICON,
+ OBSTYLE_MAXVERT,
+ OBSTYLE_MAXHORIZ,
+ OBSTYLE_MAX,
+};
+
+typedef enum _ObStyle ObStyle;
+typedef struct _ObFramePlugin ObFramePlugin;
+typedef ObFramePlugin * (*ObFramePluginFunc)(void);
+
+#define OBFRAME(x) (ObFrame *) (x);
+
+/* initialize theme plugin, it read themerc and load
+ * the plugin needed */
+ObFramePlugin * init_frame_plugin(const gchar *name, gboolean allow_fallback,
+ RrFont *active_window_font, RrFont *inactive_window_font,
+ RrFont *menu_title_font, RrFont *menu_item_font, RrFont *osd_font);
+
+/* Update plugin data */
+void update_frame_plugin(ObFramePlugin *);
+
+/* Load modules specified in filename */
+ObFramePlugin * load_frame_plugin(const gchar * filename);
+
+/* Give context from string, it's used to parse config file */
+ObFrameContext frame_context_from_string(const gchar *name);
+ObFrameContext plugin_frame_context(ObClient *, Window, gint, gint);
+
+void frame_client_gravity(ObClient * self, gint *x, gint *y);
+void frame_frame_gravity(ObClient * self, gint *x, gint *y);
+
+void frame_rect_to_frame(ObClient * self, Rect *r);
+void frame_rect_to_client(ObClient * self, Rect *r);
+
+#endif /*FRAME_PLUGIN_H_*/
#include "client.h"
#include "config.h"
#include "screen.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "grab.h"
#include "menu.h"
#include "prompt.h"
/* We don't get a FocusOut for this case, because it's just moving
from our Inferior up to us. This happens when iconifying a
window with RevertToParent focus */
- frame_adjust_focus(client->frame, FALSE);
+ render_plugin->frame_set_is_focus(client->frame, FALSE);
+ render_plugin->frame_update_layout (client->frame, FALSE, FALSE);
+ render_plugin->frame_update_skin(client->frame);
/* focus_set_client(NULL) has already been called */
}
else if (e->xfocus.detail == NotifyPointerRoot ||
}
else if (client != focus_client) {
focus_left_screen = FALSE;
- frame_adjust_focus(client->frame, TRUE);
+ render_plugin->frame_set_is_focus(client->frame, TRUE);
+ render_plugin->frame_update_layout (client->frame, FALSE, FALSE);
+ render_plugin->frame_update_skin (client->frame);
focus_set_client(client);
client_calc_layer(client);
client_bring_helper_windows(client);
}
if (client && client != focus_client) {
- frame_adjust_focus(client->frame, FALSE);
+ render_plugin->frame_set_is_focus(client->frame, FALSE);
+ render_plugin->frame_update_layout (client->frame, FALSE, FALSE);
+ render_plugin->frame_update_skin(client->frame);
/* focus_set_client(NULL) has already been called in this
section or by focus_fallback */
}
gulong vals[4];
/* set the frame extents on the window */
- vals[0] = c->frame->size.left;
- vals[1] = c->frame->size.right;
- vals[2] = c->frame->size.top;
- vals[3] = c->frame->size.bottom;
+ Strut size = render_plugin->frame_get_size(c->frame);
+ vals[0] = size.left;
+ vals[1] = size.right;
+ vals[2] = size.top;
+ vals[3] = size.bottom;
OBT_PROP_SETA32(e->xclient.window, NET_FRAME_EXTENTS,
CARDINAL, vals, 4);
e->type == obt_display_extension_sync_basep + XSyncAlarmNotify)
{
XSyncAlarmNotifyEvent *se = (XSyncAlarmNotifyEvent*)e;
- if (se->alarm == moveresize_alarm && moveresize_in_progress)
+ if (se->alarm == moveresize_alarm && render_plugin->moveresize_in_progress)
moveresize_event(e);
}
#endif
!grab_on_keyboard())
{
/* use where the press occured */
- con = frame_context(client, e->xbutton.window, px, py);
+ con = plugin_frame_context(client, e->xbutton.window, px, py);
con = mouse_button_frame_context(con, e->xbutton.button,
e->xbutton.state);
if (e->type == ButtonRelease && e->xbutton.button == pb)
pb = 0, px = py = -1;
+ ObFrameButton current_button = OB_BUTTON_NONE;
+
switch (con) {
case OB_FRAME_CONTEXT_MAXIMIZE:
- client->frame->max_press = (e->type == ButtonPress);
- frame_adjust_state(client->frame);
+ current_button = OB_BUTTON_MAX;
break;
case OB_FRAME_CONTEXT_CLOSE:
- client->frame->close_press = (e->type == ButtonPress);
- frame_adjust_state(client->frame);
+ current_button = OB_BUTTON_CLOSE;
break;
case OB_FRAME_CONTEXT_ICONIFY:
- client->frame->iconify_press = (e->type == ButtonPress);
- frame_adjust_state(client->frame);
+ current_button = OB_BUTTON_ICONIFY;
break;
case OB_FRAME_CONTEXT_ALLDESKTOPS:
- client->frame->desk_press = (e->type == ButtonPress);
- frame_adjust_state(client->frame);
+ current_button = OB_BUTTON_DESK;
break;
case OB_FRAME_CONTEXT_SHADE:
- client->frame->shade_press = (e->type == ButtonPress);
- frame_adjust_state(client->frame);
+ current_button = OB_BUTTON_SHADE;
break;
default:
/* nothing changes with clicks for any other contexts */
break;
}
+
+ if (current_button)
+ render_plugin->frame_set_hover_flag (client->frame, current_button);
}
break;
case MotionNotify:
notifies, but we still get motion events */
if (grab_on_pointer()) break;
- con = frame_context(client, e->xmotion.window,
+ con = plugin_frame_context(client, e->xmotion.window,
e->xmotion.x, e->xmotion.y);
switch (con) {
case OB_FRAME_CONTEXT_TITLEBAR:
case OB_FRAME_CONTEXT_TLCORNER:
case OB_FRAME_CONTEXT_TRCORNER:
/* we've left the button area inside the titlebar */
- if (client->frame->max_hover || client->frame->desk_hover ||
- client->frame->shade_hover || client->frame->iconify_hover ||
- client->frame->close_hover)
- {
- client->frame->max_hover = FALSE;
- client->frame->desk_hover = FALSE;
- client->frame->shade_hover = FALSE;
- client->frame->iconify_hover = FALSE;
- client->frame->close_hover = FALSE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_MAXIMIZE:
- if (!client->frame->max_hover) {
- client->frame->max_hover = TRUE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_MAX);
break;
case OB_FRAME_CONTEXT_ALLDESKTOPS:
- if (!client->frame->desk_hover) {
- client->frame->desk_hover = TRUE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_DESK);
break;
case OB_FRAME_CONTEXT_SHADE:
- if (!client->frame->shade_hover) {
- client->frame->shade_hover = TRUE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_SHADE);
break;
case OB_FRAME_CONTEXT_ICONIFY:
- if (!client->frame->iconify_hover) {
- client->frame->iconify_hover = TRUE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_ICONIFY);
break;
case OB_FRAME_CONTEXT_CLOSE:
- if (!client->frame->close_hover) {
- client->frame->close_hover = TRUE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_CLOSE);
break;
default:
break;
}
break;
case LeaveNotify:
- con = frame_context(client, e->xcrossing.window,
+ con = plugin_frame_context(client, e->xcrossing.window,
e->xcrossing.x, e->xcrossing.y);
switch (con) {
case OB_FRAME_CONTEXT_TITLEBAR:
case OB_FRAME_CONTEXT_TLCORNER:
case OB_FRAME_CONTEXT_TRCORNER:
/* we've left the button area inside the titlebar */
- if (client->frame->max_hover || client->frame->desk_hover ||
- client->frame->shade_hover || client->frame->iconify_hover ||
- client->frame->close_hover)
- {
- client->frame->max_hover = FALSE;
- client->frame->desk_hover = FALSE;
- client->frame->shade_hover = FALSE;
- client->frame->iconify_hover = FALSE;
- client->frame->close_hover = FALSE;
- frame_adjust_state(client->frame);
- }
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_MAXIMIZE:
- client->frame->max_hover = FALSE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_ALLDESKTOPS:
- client->frame->desk_hover = FALSE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_SHADE:
- client->frame->shade_hover = FALSE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_ICONIFY:
- client->frame->iconify_hover = FALSE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_CLOSE:
- client->frame->close_hover = FALSE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_NONE);
break;
case OB_FRAME_CONTEXT_FRAME:
/* When the mouse leaves an animating window, don't use the
corresponding enter events. Pretend like the animating window
doesn't even exist..! */
- if (frame_iconify_animating(client->frame))
+ if (render_plugin->frame_iconify_animating(client->frame))
event_end_ignore_all_enters(event_start_ignore_all_enters());
ob_debug_type(OB_DEBUG_FOCUS,
break;
case EnterNotify:
{
- con = frame_context(client, e->xcrossing.window,
+ con = plugin_frame_context(client, e->xcrossing.window,
e->xcrossing.x, e->xcrossing.y);
switch (con) {
case OB_FRAME_CONTEXT_MAXIMIZE:
- client->frame->max_hover = TRUE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_MAX);
break;
case OB_FRAME_CONTEXT_ALLDESKTOPS:
- client->frame->desk_hover = TRUE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_DESK);
break;
case OB_FRAME_CONTEXT_SHADE:
- client->frame->shade_hover = TRUE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_SHADE);
break;
case OB_FRAME_CONTEXT_ICONIFY:
- client->frame->iconify_hover = TRUE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_ICONIFY);
break;
case OB_FRAME_CONTEXT_CLOSE:
- client->frame->close_hover = TRUE;
- frame_adjust_state(client->frame);
+ render_plugin->frame_set_hover_flag(client->frame, OB_BUTTON_CLOSE);
break;
case OB_FRAME_CONTEXT_FRAME:
if (grab_on_keyboard())
ob_debug("ConfigureRequest for \"%s\" desktop %d wmstate %d "
"visibile %d",
client->title,
- screen_desktop, client->wmstate, client->frame->visible);
- ob_debug(" x %d y %d w %d h %d b %d",
+ screen_desktop, client->wmstate, render_plugin->frame_is_visible(client->frame),
x, y, w, h, client->border_width);
if (e->xconfigurerequest.value_mask & CWBorderWidth)
desktop. eg. open amarok window on desktop 1, switch to desktop
2, click amarok tray icon. it will move by its decoration size.
*/
+ Strut size = render_plugin->frame_get_size(client->frame);
+ Rect area = render_plugin->frame_get_window_area(client->frame);
if (x != client->area.x &&
- x == (client->frame->area.x + client->frame->size.left -
+ x == (area.x + size.left -
(gint)client->border_width) &&
y != client->area.y &&
- y == (client->frame->area.y + client->frame->size.top -
+ y == (area.y + size.top -
(gint)client->border_width) &&
w == client->area.width &&
h == client->area.height)
break;
case ReparentNotify:
/* this is when the client is first taken captive in the frame */
- if (e->xreparent.parent == client->frame->window) break;
+ if (e->xreparent.parent == render_plugin->frame_get_window(client->frame)) break;
/*
This event is quite rare and is usually handled in unmapHandler.
e->type == obt_display_extension_shape_basep)
{
client->shaped = ((XShapeEvent*)e)->shaped;
- frame_adjust_shape(client->frame);
+ render_plugin->frame_adjust_shape(client->frame);
}
#endif
}
/* if the keyboard interactive action uses the event then dont
use it for bindings. likewise is moveresize uses the event. */
if (!actions_interactive_input_event(e) && !moveresize_event(e)) {
- if (moveresize_in_progress)
+ if (render_plugin->moveresize_in_progress)
/* make further actions work on the client being
moved/resized */
client = moveresize_client;
{
/* the frame may not be "visible" but they can still click on it
in the case where it is animating before disappearing */
- if (!client || !frame_iconify_animating(client->frame))
+ if (!client || !render_plugin->frame_iconify_animating(client->frame))
mouse_event(client, e);
} else
- keyboard_event((focus_cycle_target ? focus_cycle_target :
+ keyboard_event((render_plugin->focus_cycle_target ? render_plugin->focus_cycle_target :
(client ? client : focus_client)), e);
}
}
Time old = event_curtime;
/* don't move focus and kill the menu or the move/resize */
- if (menu_frame_visible || moveresize_in_progress) return FALSE;
+ if (menu_frame_visible || render_plugin->moveresize_in_progress) return FALSE;
event_curtime = d->time;
event_curserial = d->serial;
menu_frame_hide_all();
ob_debug("KILLED open menus");
}
- else if (moveresize_in_progress) {
+ else if (render_plugin->moveresize_in_progress) {
moveresize_end(TRUE);
ob_debug("KILLED interactive moveresize");
}
#include "focus_cycle.h"
#include "focus_cycle_indicator.h"
#include "client.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "focus.h"
#include "screen.h"
#include "openbox.h"
#include <X11/Xlib.h>
#include <glib.h>
-ObClient *focus_cycle_target = NULL;
+//ObClient *focus_cycle_target = NULL;
static gboolean focus_cycle_iconic_windows;
static gboolean focus_cycle_all_desktops;
static gboolean focus_cycle_dock_windows;
{
/* stop focus cycling if the given client is a valid focus target,
and so the cycling is being disrupted */
- if (focus_cycle_target && ifclient &&
+ if (render_plugin->focus_cycle_target && ifclient &&
focus_valid_target(ifclient, TRUE,
focus_cycle_iconic_windows,
focus_cycle_all_desktops,
if (interactive) {
if (cancel) {
- focus_cycle_target = NULL;
+ render_plugin->focus_cycle_target = NULL;
goto done_cycle;
} else if (done)
goto done_cycle;
}
- if (focus_cycle_target == NULL) {
+ if (render_plugin->focus_cycle_target == NULL) {
focus_cycle_iconic_windows = TRUE;
focus_cycle_all_desktops = all_desktops;
focus_cycle_dock_windows = dock_windows;
focus_cycle_desktop_windows = desktop_windows;
start = it = g_list_find(list, focus_client);
} else
- start = it = g_list_find(list, focus_cycle_target);
+ start = it = g_list_find(list, render_plugin->focus_cycle_target);
if (!start) /* switched desktops or something? */
start = it = forward ? g_list_last(list) : g_list_first(list);
focus_cycle_desktop_windows))
{
if (interactive) {
- if (ft != focus_cycle_target) { /* prevents flicker */
- focus_cycle_target = ft;
+ if (ft != render_plugin->focus_cycle_target) { /* prevents flicker */
+ render_plugin->focus_cycle_target = ft;
focus_cycle_draw_indicator(showbar ? ft : NULL);
}
/* same arguments as focus_target_valid */
focus_cycle_dock_windows,
focus_cycle_desktop_windows,
mode);
- return focus_cycle_target;
- } else if (ft != focus_cycle_target) {
- focus_cycle_target = ft;
+ return render_plugin->focus_cycle_target;
+ } else if (ft != render_plugin->focus_cycle_target) {
+ render_plugin->focus_cycle_target = ft;
done = TRUE;
break;
}
} while (it != start);
done_cycle:
- if (done && !cancel) ret = focus_cycle_target;
+ if (done && !cancel) ret = render_plugin->focus_cycle_target;
t = NULL;
- focus_cycle_target = NULL;
+ render_plugin->focus_cycle_target = NULL;
g_list_free(order);
order = NULL;
if (!client_list)
return NULL;
+ Rect area = render_plugin->frame_get_window_area(c->frame);
/* first, find the centre coords of the currently focused window */
- my_cx = c->frame->area.x + c->frame->area.width / 2;
- my_cy = c->frame->area.y + c->frame->area.height / 2;
+ my_cx = area.x + area.width / 2;
+ my_cy = area.y + area.height / 2;
best_score = -1;
best_client = c;
desktop_windows))
continue;
+ Rect cur_area = render_plugin->frame_get_window_area(cur->frame);
/* find the centre coords of this window, from the
* currently focused window's point of view */
- his_cx = (cur->frame->area.x - my_cx)
- + cur->frame->area.width / 2;
- his_cy = (cur->frame->area.y - my_cy)
- + cur->frame->area.height / 2;
+ his_cx = (cur_area.x - my_cx)
+ + cur_area.width / 2;
+ his_cy = (cur_area.y - my_cy)
+ + cur_area.height / 2;
if (dir == OB_DIRECTION_NORTHEAST || dir == OB_DIRECTION_SOUTHEAST ||
dir == OB_DIRECTION_SOUTHWEST || dir == OB_DIRECTION_NORTHWEST)
ObClient *ret = NULL;
if (cancel) {
- focus_cycle_target = NULL;
+ render_plugin->focus_cycle_target = NULL;
goto done_cycle;
} else if (done && interactive)
goto done_cycle;
if (!focus_order)
goto done_cycle;
- if (focus_cycle_target == NULL) {
+ if (render_plugin->focus_cycle_target == NULL) {
focus_cycle_iconic_windows = FALSE;
focus_cycle_all_desktops = FALSE;
focus_cycle_dock_windows = dock_windows;
if (!first) first = focus_client;
- if (focus_cycle_target)
- ft = focus_find_directional(focus_cycle_target, dir, dock_windows,
+ if (render_plugin->focus_cycle_target)
+ ft = focus_find_directional(render_plugin->focus_cycle_target, dir, dock_windows,
desktop_windows);
else if (first)
ft = focus_find_directional(first, dir, dock_windows, desktop_windows);
ft = it->data;
}
- if (ft && ft != focus_cycle_target) {/* prevents flicker */
- focus_cycle_target = ft;
+ if (ft && ft != render_plugin->focus_cycle_target) {/* prevents flicker */
+ render_plugin->focus_cycle_target = ft;
if (!interactive)
goto done_cycle;
focus_cycle_draw_indicator(showbar ? ft : NULL);
}
- if (focus_cycle_target && dialog)
+ if (render_plugin->focus_cycle_target && dialog)
/* same arguments as focus_target_valid */
- focus_cycle_popup_single_show(focus_cycle_target,
+ focus_cycle_popup_single_show(render_plugin->focus_cycle_target,
focus_cycle_iconic_windows,
focus_cycle_all_desktops,
focus_cycle_dock_windows,
focus_cycle_desktop_windows);
- return focus_cycle_target;
+ return render_plugin->focus_cycle_target;
done_cycle:
- if (done && !cancel) ret = focus_cycle_target;
+ if (done && !cancel) ret = render_plugin->focus_cycle_target;
first = NULL;
- focus_cycle_target = NULL;
+ render_plugin->focus_cycle_target = NULL;
focus_cycle_draw_indicator(NULL);
focus_cycle_popup_single_hide();
struct _ObClient;
/*! The client which appears focused during a focus cycle operation */
-extern struct _ObClient *focus_cycle_target;
+//extern struct _ObClient *focus_cycle_target;
void focus_cycle_startup(gboolean reconfig);
void focus_cycle_shutdown(gboolean reconfig);
#include "focus_cycle_indicator.h"
#include "client.h"
#include "openbox.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "event.h"
#include "render/render.h"
visible = FALSE;
}
else if (c) {
+ Rect area = render_plugin->frame_get_window_area(c->frame);
/*
if (c)
frame_adjust_focus(c->frame, FALSE);
wt = wl = wr = wb = FOCUS_INDICATOR_WIDTH;
- x = c->frame->area.x;
- y = c->frame->area.y;
- w = c->frame->area.width;
+ x = area.x;
+ y = area.y;
+ w = area.width;
h = wt;
/* kill enter events cause by this moving */
RrPaint(a_focus_indicator, focus_indicator.top.window,
w, h);
- x = c->frame->area.x;
- y = c->frame->area.y;
+ x = area.x;
+ y = area.y;
w = wl;
- h = c->frame->area.height;
+ h = area.height;
XMoveResizeWindow(obt_display, focus_indicator.left.window,
x, y, w, h);
RrPaint(a_focus_indicator, focus_indicator.left.window,
w, h);
- x = c->frame->area.x + c->frame->area.width - wr;
- y = c->frame->area.y;
+ x = area.x + area.width - wr;
+ y = area.y;
w = wr;
- h = c->frame->area.height ;
+ h = area.height ;
XMoveResizeWindow(obt_display, focus_indicator.right.window,
x, y, w, h);
RrPaint(a_focus_indicator, focus_indicator.right.window,
w, h);
- x = c->frame->area.x;
- y = c->frame->area.y + c->frame->area.height - wb;
- w = c->frame->area.width;
+ x = area.x;
+ y = area.y + area.height - wb;
+ w = area.width;
h = wb;
XMoveResizeWindow(obt_display, focus_indicator.bottom.window,
+++ /dev/null
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
- frame.c for the Openbox window manager
- Copyright (c) 2006 Mikael Magnusson
- Copyright (c) 2003-2007 Dana Jansens
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#include "frame.h"
-#include "client.h"
-#include "openbox.h"
-#include "grab.h"
-#include "config.h"
-#include "framerender.h"
-#include "focus_cycle.h"
-#include "focus_cycle_indicator.h"
-#include "moveresize.h"
-#include "screen.h"
-#include "render/theme.h"
-#include "obt/display.h"
-#include "obt/prop.h"
-
-#define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
- ButtonPressMask | ButtonReleaseMask | \
- SubstructureRedirectMask | FocusChangeMask)
-#define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
- ButtonMotionMask | PointerMotionMask | \
- EnterWindowMask | LeaveWindowMask)
-
-#define FRAME_ANIMATE_ICONIFY_TIME 150000 /* .15 seconds */
-#define FRAME_ANIMATE_ICONIFY_STEP_TIME (G_USEC_PER_SEC / 60) /* 60 Hz */
-
-#define FRAME_HANDLE_Y(f) (f->size.top + f->client->area.height + f->cbwidth_b)
-
-static void flash_done(gpointer data);
-static gboolean flash_timeout(gpointer data);
-
-static void layout_title(ObFrame *self);
-static void set_theme_statics(ObFrame *self);
-static void free_theme_statics(ObFrame *self);
-static gboolean frame_animate_iconify(gpointer self);
-static void frame_adjust_cursors(ObFrame *self);
-
-static Window createWindow(Window parent, Visual *visual,
- gulong mask, XSetWindowAttributes *attrib)
-{
- return XCreateWindow(obt_display, parent, 0, 0, 1, 1, 0,
- (visual ? 32 : RrDepth(ob_rr_inst)), InputOutput,
- (visual ? visual : RrVisual(ob_rr_inst)),
- mask, attrib);
-
-}
-
-static Visual *check_32bit_client(ObClient *c)
-{
- XWindowAttributes wattrib;
- Status ret;
-
- /* we're already running at 32 bit depth, yay. we don't need to use their
- visual */
- if (RrDepth(ob_rr_inst) == 32)
- return NULL;
-
- ret = XGetWindowAttributes(obt_display, c->window, &wattrib);
- g_assert(ret != BadDrawable);
- g_assert(ret != BadWindow);
-
- if (wattrib.depth == 32)
- return wattrib.visual;
- return NULL;
-}
-
-ObFrame *frame_new(ObClient *client)
-{
- XSetWindowAttributes attrib;
- gulong mask;
- ObFrame *self;
- Visual *visual;
-
- self = g_new0(ObFrame, 1);
- self->client = client;
-
- visual = check_32bit_client(client);
-
- /* create the non-visible decor windows */
-
- mask = 0;
- if (visual) {
- /* client has a 32-bit visual */
- mask |= CWColormap | CWBackPixel | CWBorderPixel;
- /* create a colormap with the visual */
- self->colormap = attrib.colormap =
- XCreateColormap(obt_display, obt_root(ob_screen),
- visual, AllocNone);
- attrib.background_pixel = BlackPixel(obt_display, ob_screen);
- attrib.border_pixel = BlackPixel(obt_display, ob_screen);
- }
- self->window = createWindow(obt_root(ob_screen), visual,
- mask, &attrib);
-
- /* create the visible decor windows */
-
- mask = 0;
- if (visual) {
- /* client has a 32-bit visual */
- mask |= CWColormap | CWBackPixel | CWBorderPixel;
- attrib.colormap = RrColormap(ob_rr_inst);
- }
-
- self->backback = createWindow(self->window, NULL, mask, &attrib);
- self->backfront = createWindow(self->backback, NULL, mask, &attrib);
-
- mask |= CWEventMask;
- attrib.event_mask = ELEMENT_EVENTMASK;
- self->innerleft = createWindow(self->window, NULL, mask, &attrib);
- self->innertop = createWindow(self->window, NULL, mask, &attrib);
- self->innerright = createWindow(self->window, NULL, mask, &attrib);
- self->innerbottom = createWindow(self->window, NULL, mask, &attrib);
-
- self->innerblb = createWindow(self->innerbottom, NULL, mask, &attrib);
- self->innerbrb = createWindow(self->innerbottom, NULL, mask, &attrib);
- self->innerbll = createWindow(self->innerleft, NULL, mask, &attrib);
- self->innerbrr = createWindow(self->innerright, NULL, mask, &attrib);
-
- self->title = createWindow(self->window, NULL, mask, &attrib);
- self->titleleft = createWindow(self->window, NULL, mask, &attrib);
- self->titletop = createWindow(self->window, NULL, mask, &attrib);
- self->titletopleft = createWindow(self->window, NULL, mask, &attrib);
- self->titletopright = createWindow(self->window, NULL, mask, &attrib);
- self->titleright = createWindow(self->window, NULL, mask, &attrib);
- self->titlebottom = createWindow(self->window, NULL, mask, &attrib);
-
- self->topresize = createWindow(self->title, NULL, mask, &attrib);
- self->tltresize = createWindow(self->title, NULL, mask, &attrib);
- self->tllresize = createWindow(self->title, NULL, mask, &attrib);
- self->trtresize = createWindow(self->title, NULL, mask, &attrib);
- self->trrresize = createWindow(self->title, NULL, mask, &attrib);
-
- self->left = createWindow(self->window, NULL, mask, &attrib);
- self->right = createWindow(self->window, NULL, mask, &attrib);
-
- self->label = createWindow(self->title, NULL, mask, &attrib);
- self->max = createWindow(self->title, NULL, mask, &attrib);
- self->close = createWindow(self->title, NULL, mask, &attrib);
- self->desk = createWindow(self->title, NULL, mask, &attrib);
- self->shade = createWindow(self->title, NULL, mask, &attrib);
- self->icon = createWindow(self->title, NULL, mask, &attrib);
- self->iconify = createWindow(self->title, NULL, mask, &attrib);
-
- self->handle = createWindow(self->window, NULL, mask, &attrib);
- self->lgrip = createWindow(self->handle, NULL, mask, &attrib);
- self->rgrip = createWindow(self->handle, NULL, mask, &attrib);
-
- self->handleleft = createWindow(self->handle, NULL, mask, &attrib);
- self->handleright = createWindow(self->handle, NULL, mask, &attrib);
-
- self->handletop = createWindow(self->window, NULL, mask, &attrib);
- self->handlebottom = createWindow(self->window, NULL, mask, &attrib);
- self->lgripleft = createWindow(self->window, NULL, mask, &attrib);
- self->lgriptop = createWindow(self->window, NULL, mask, &attrib);
- self->lgripbottom = createWindow(self->window, NULL, mask, &attrib);
- self->rgripright = createWindow(self->window, NULL, mask, &attrib);
- self->rgriptop = createWindow(self->window, NULL, mask, &attrib);
- self->rgripbottom = createWindow(self->window, NULL, mask, &attrib);
-
- self->focused = FALSE;
-
- /* the other stuff is shown based on decor settings */
- XMapWindow(obt_display, self->label);
- XMapWindow(obt_display, self->backback);
- XMapWindow(obt_display, self->backfront);
-
- self->max_press = self->close_press = self->desk_press =
- self->iconify_press = self->shade_press = FALSE;
- self->max_hover = self->close_hover = self->desk_hover =
- self->iconify_hover = self->shade_hover = FALSE;
-
- set_theme_statics(self);
-
- return (ObFrame*)self;
-}
-
-static void set_theme_statics(ObFrame *self)
-{
- /* set colors/appearance/sizes for stuff that doesn't change */
- XResizeWindow(obt_display, self->max,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
- XResizeWindow(obt_display, self->iconify,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
- XResizeWindow(obt_display, self->icon,
- ob_rr_theme->button_size + 2, ob_rr_theme->button_size + 2);
- XResizeWindow(obt_display, self->close,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
- XResizeWindow(obt_display, self->desk,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
- XResizeWindow(obt_display, self->shade,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
- XResizeWindow(obt_display, self->tltresize,
- ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
- XResizeWindow(obt_display, self->trtresize,
- ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
- XResizeWindow(obt_display, self->tllresize,
- ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
- XResizeWindow(obt_display, self->trrresize,
- ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
-}
-
-static void free_theme_statics(ObFrame *self)
-{
-}
-
-void frame_free(ObFrame *self)
-{
- free_theme_statics(self);
-
- XDestroyWindow(obt_display, self->window);
- if (self->colormap)
- XFreeColormap(obt_display, self->colormap);
-
- g_free(self);
-}
-
-void frame_show(ObFrame *self)
-{
- if (!self->visible) {
- self->visible = TRUE;
- framerender_frame(self);
- /* Grab the server to make sure that the frame window is mapped before
- the client gets its MapNotify, i.e. to make sure the client is
- _visible_ when it gets MapNotify. */
- grab_server(TRUE);
- XMapWindow(obt_display, self->client->window);
- XMapWindow(obt_display, self->window);
- grab_server(FALSE);
- }
-}
-
-void frame_hide(ObFrame *self)
-{
- if (self->visible) {
- self->visible = FALSE;
- if (!frame_iconify_animating(self))
- XUnmapWindow(obt_display, self->window);
- /* we unmap the client itself so that we can get MapRequest
- events, and because the ICCCM tells us to! */
- XUnmapWindow(obt_display, self->client->window);
- self->client->ignore_unmaps += 1;
- }
-}
-
-void frame_adjust_theme(ObFrame *self)
-{
- free_theme_statics(self);
- set_theme_statics(self);
-}
-
-void frame_adjust_shape(ObFrame *self)
-{
-#ifdef SHAPE
- gint num;
- XRectangle xrect[2];
-
- if (!self->client->shaped) {
- /* clear the shape on the frame window */
- XShapeCombineMask(obt_display, self->window, ShapeBounding,
- self->size.left,
- self->size.top,
- None, ShapeSet);
- } else {
- /* make the frame's shape match the clients */
- XShapeCombineShape(obt_display, self->window, ShapeBounding,
- self->size.left,
- self->size.top,
- self->client->window,
- ShapeBounding, ShapeSet);
-
- num = 0;
- if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
- xrect[0].x = 0;
- xrect[0].y = 0;
- xrect[0].width = self->area.width;
- xrect[0].height = self->size.top;
- ++num;
- }
-
- if (self->decorations & OB_FRAME_DECOR_HANDLE &&
- ob_rr_theme->handle_height > 0)
- {
- xrect[1].x = 0;
- xrect[1].y = FRAME_HANDLE_Y(self);
- xrect[1].width = self->area.width;
- xrect[1].height = ob_rr_theme->handle_height +
- self->bwidth * 2;
- ++num;
- }
-
- XShapeCombineRectangles(obt_display, self->window,
- ShapeBounding, 0, 0, xrect, num,
- ShapeUnion, Unsorted);
- }
-#endif
-}
-
-void frame_adjust_area(ObFrame *self, gboolean moved,
- gboolean resized, gboolean fake)
-{
- Strut oldsize;
-
- oldsize = self->size;
-
- if (resized) {
- /* do this before changing the frame's status like max_horz max_vert */
- frame_adjust_cursors(self);
-
- self->functions = self->client->functions;
- self->decorations = self->client->decorations;
- self->max_horz = self->client->max_horz;
- self->max_vert = self->client->max_vert;
- self->shaded = self->client->shaded;
-
- if (self->decorations & OB_FRAME_DECOR_BORDER ||
- (self->client->undecorated && config_theme_keepborder))
- self->bwidth = ob_rr_theme->fbwidth;
- else
- self->bwidth = 0;
-
- if (self->decorations & OB_FRAME_DECOR_BORDER) {
- self->cbwidth_l = self->cbwidth_r = ob_rr_theme->cbwidthx;
- self->cbwidth_t = self->cbwidth_b = ob_rr_theme->cbwidthy;
- } else
- self->cbwidth_l = self->cbwidth_t =
- self->cbwidth_r = self->cbwidth_b = 0;
-
- if (self->max_horz) {
- self->cbwidth_l = self->cbwidth_r = 0;
- self->width = self->client->area.width;
- if (self->max_vert)
- self->cbwidth_b = 0;
- } else
- self->width = self->client->area.width +
- self->cbwidth_l + self->cbwidth_r;
-
- /* some elements are sized based of the width, so don't let them have
- negative values */
- self->width = MAX(self->width,
- (ob_rr_theme->grip_width + self->bwidth) * 2 + 1);
-
- STRUT_SET(self->size,
- self->cbwidth_l + (!self->max_horz ? self->bwidth : 0),
- self->cbwidth_t +
- (!self->max_horz || !self->max_vert ||
- !self->client->undecorated ? self->bwidth : 0),
- self->cbwidth_r + (!self->max_horz ? self->bwidth : 0),
- self->cbwidth_b +
- (!self->max_horz || !self->max_vert ? self->bwidth : 0));
-
- if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
- self->size.top += ob_rr_theme->title_height + self->bwidth;
- if (self->decorations & OB_FRAME_DECOR_HANDLE &&
- ob_rr_theme->handle_height > 0)
- {
- self->size.bottom += ob_rr_theme->handle_height + self->bwidth;
- }
-
- /* position/size and map/unmap all the windows */
-
- if (!fake) {
- gint innercornerheight =
- ob_rr_theme->grip_width - self->size.bottom;
-
- if (self->cbwidth_l) {
- XMoveResizeWindow(obt_display, self->innerleft,
- self->size.left - self->cbwidth_l,
- self->size.top,
- self->cbwidth_l, self->client->area.height);
-
- XMapWindow(obt_display, self->innerleft);
- } else
- XUnmapWindow(obt_display, self->innerleft);
-
- if (self->cbwidth_l && innercornerheight > 0) {
- XMoveResizeWindow(obt_display, self->innerbll,
- 0,
- self->client->area.height -
- (ob_rr_theme->grip_width -
- self->size.bottom),
- self->cbwidth_l,
- ob_rr_theme->grip_width - self->size.bottom);
-
- XMapWindow(obt_display, self->innerbll);
- } else
- XUnmapWindow(obt_display, self->innerbll);
-
- if (self->cbwidth_r) {
- XMoveResizeWindow(obt_display, self->innerright,
- self->size.left + self->client->area.width,
- self->size.top,
- self->cbwidth_r, self->client->area.height);
-
- XMapWindow(obt_display, self->innerright);
- } else
- XUnmapWindow(obt_display, self->innerright);
-
- if (self->cbwidth_r && innercornerheight > 0) {
- XMoveResizeWindow(obt_display, self->innerbrr,
- 0,
- self->client->area.height -
- (ob_rr_theme->grip_width -
- self->size.bottom),
- self->cbwidth_r,
- ob_rr_theme->grip_width - self->size.bottom);
-
- XMapWindow(obt_display, self->innerbrr);
- } else
- XUnmapWindow(obt_display, self->innerbrr);
-
- if (self->cbwidth_t) {
- XMoveResizeWindow(obt_display, self->innertop,
- self->size.left - self->cbwidth_l,
- self->size.top - self->cbwidth_t,
- self->client->area.width +
- self->cbwidth_l + self->cbwidth_r,
- self->cbwidth_t);
-
- XMapWindow(obt_display, self->innertop);
- } else
- XUnmapWindow(obt_display, self->innertop);
-
- if (self->cbwidth_b) {
- XMoveResizeWindow(obt_display, self->innerbottom,
- self->size.left - self->cbwidth_l,
- self->size.top + self->client->area.height,
- self->client->area.width +
- self->cbwidth_l + self->cbwidth_r,
- self->cbwidth_b);
-
- XMoveResizeWindow(obt_display, self->innerblb,
- 0, 0,
- ob_rr_theme->grip_width + self->bwidth,
- self->cbwidth_b);
- XMoveResizeWindow(obt_display, self->innerbrb,
- self->client->area.width +
- self->cbwidth_l + self->cbwidth_r -
- (ob_rr_theme->grip_width + self->bwidth),
- 0,
- ob_rr_theme->grip_width + self->bwidth,
- self->cbwidth_b);
-
- XMapWindow(obt_display, self->innerbottom);
- XMapWindow(obt_display, self->innerblb);
- XMapWindow(obt_display, self->innerbrb);
- } else {
- XUnmapWindow(obt_display, self->innerbottom);
- XUnmapWindow(obt_display, self->innerblb);
- XUnmapWindow(obt_display, self->innerbrb);
- }
-
- if (self->bwidth) {
- gint titlesides;
-
- /* height of titleleft and titleright */
- titlesides = (!self->max_horz ? ob_rr_theme->grip_width : 0);
-
- XMoveResizeWindow(obt_display, self->titletop,
- ob_rr_theme->grip_width + self->bwidth, 0,
- /* width + bwidth*2 - bwidth*2 - grips*2 */
- self->width - ob_rr_theme->grip_width * 2,
- self->bwidth);
- XMoveResizeWindow(obt_display, self->titletopleft,
- 0, 0,
- ob_rr_theme->grip_width + self->bwidth,
- self->bwidth);
- XMoveResizeWindow(obt_display, self->titletopright,
- self->client->area.width +
- self->size.left + self->size.right -
- ob_rr_theme->grip_width - self->bwidth,
- 0,
- ob_rr_theme->grip_width + self->bwidth,
- self->bwidth);
-
- if (titlesides > 0) {
- XMoveResizeWindow(obt_display, self->titleleft,
- 0, self->bwidth,
- self->bwidth,
- titlesides);
- XMoveResizeWindow(obt_display, self->titleright,
- self->client->area.width +
- self->size.left + self->size.right -
- self->bwidth,
- self->bwidth,
- self->bwidth,
- titlesides);
-
- XMapWindow(obt_display, self->titleleft);
- XMapWindow(obt_display, self->titleright);
- } else {
- XUnmapWindow(obt_display, self->titleleft);
- XUnmapWindow(obt_display, self->titleright);
- }
-
- XMapWindow(obt_display, self->titletop);
- XMapWindow(obt_display, self->titletopleft);
- XMapWindow(obt_display, self->titletopright);
-
- if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
- XMoveResizeWindow(obt_display, self->titlebottom,
- (self->max_horz ? 0 : self->bwidth),
- ob_rr_theme->title_height + self->bwidth,
- self->width,
- self->bwidth);
-
- XMapWindow(obt_display, self->titlebottom);
- } else
- XUnmapWindow(obt_display, self->titlebottom);
- } else {
- XUnmapWindow(obt_display, self->titlebottom);
-
- XUnmapWindow(obt_display, self->titletop);
- XUnmapWindow(obt_display, self->titletopleft);
- XUnmapWindow(obt_display, self->titletopright);
- XUnmapWindow(obt_display, self->titleleft);
- XUnmapWindow(obt_display, self->titleright);
- }
-
- if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
- XMoveResizeWindow(obt_display, self->title,
- (self->max_horz ? 0 : self->bwidth),
- self->bwidth,
- self->width, ob_rr_theme->title_height);
-
- XMapWindow(obt_display, self->title);
-
- if (self->decorations & OB_FRAME_DECOR_GRIPS) {
- XMoveResizeWindow(obt_display, self->topresize,
- ob_rr_theme->grip_width,
- 0,
- self->width - ob_rr_theme->grip_width *2,
- ob_rr_theme->paddingy + 1);
-
- XMoveWindow(obt_display, self->tltresize, 0, 0);
- XMoveWindow(obt_display, self->tllresize, 0, 0);
- XMoveWindow(obt_display, self->trtresize,
- self->width - ob_rr_theme->grip_width, 0);
- XMoveWindow(obt_display, self->trrresize,
- self->width - ob_rr_theme->paddingx - 1, 0);
-
- XMapWindow(obt_display, self->topresize);
- XMapWindow(obt_display, self->tltresize);
- XMapWindow(obt_display, self->tllresize);
- XMapWindow(obt_display, self->trtresize);
- XMapWindow(obt_display, self->trrresize);
- } else {
- XUnmapWindow(obt_display, self->topresize);
- XUnmapWindow(obt_display, self->tltresize);
- XUnmapWindow(obt_display, self->tllresize);
- XUnmapWindow(obt_display, self->trtresize);
- XUnmapWindow(obt_display, self->trrresize);
- }
- } else
- XUnmapWindow(obt_display, self->title);
- }
-
- if ((self->decorations & OB_FRAME_DECOR_TITLEBAR))
- /* layout the title bar elements */
- layout_title(self);
-
- if (!fake) {
- gint sidebwidth = self->max_horz ? 0 : self->bwidth;
-
- if (self->bwidth && self->size.bottom) {
- XMoveResizeWindow(obt_display, self->handlebottom,
- ob_rr_theme->grip_width +
- self->bwidth + sidebwidth,
- self->size.top + self->client->area.height +
- self->size.bottom - self->bwidth,
- self->width - (ob_rr_theme->grip_width +
- sidebwidth) * 2,
- self->bwidth);
-
-
- if (sidebwidth) {
- XMoveResizeWindow(obt_display, self->lgripleft,
- 0,
- self->size.top +
- self->client->area.height +
- self->size.bottom -
- (!self->max_horz ?
- ob_rr_theme->grip_width :
- self->size.bottom - self->cbwidth_b),
- self->bwidth,
- (!self->max_horz ?
- ob_rr_theme->grip_width :
- self->size.bottom - self->cbwidth_b));
- XMoveResizeWindow(obt_display, self->rgripright,
- self->size.left +
- self->client->area.width +
- self->size.right - self->bwidth,
- self->size.top +
- self->client->area.height +
- self->size.bottom -
- (!self->max_horz ?
- ob_rr_theme->grip_width :
- self->size.bottom - self->cbwidth_b),
- self->bwidth,
- (!self->max_horz ?
- ob_rr_theme->grip_width :
- self->size.bottom - self->cbwidth_b));
-
- XMapWindow(obt_display, self->lgripleft);
- XMapWindow(obt_display, self->rgripright);
- } else {
- XUnmapWindow(obt_display, self->lgripleft);
- XUnmapWindow(obt_display, self->rgripright);
- }
-
- XMoveResizeWindow(obt_display, self->lgripbottom,
- sidebwidth,
- self->size.top + self->client->area.height +
- self->size.bottom - self->bwidth,
- ob_rr_theme->grip_width + self->bwidth,
- self->bwidth);
- XMoveResizeWindow(obt_display, self->rgripbottom,
- self->size.left + self->client->area.width +
- self->size.right - self->bwidth - sidebwidth-
- ob_rr_theme->grip_width,
- self->size.top + self->client->area.height +
- self->size.bottom - self->bwidth,
- ob_rr_theme->grip_width + self->bwidth,
- self->bwidth);
-
- XMapWindow(obt_display, self->handlebottom);
- XMapWindow(obt_display, self->lgripbottom);
- XMapWindow(obt_display, self->rgripbottom);
-
- if (self->decorations & OB_FRAME_DECOR_HANDLE &&
- ob_rr_theme->handle_height > 0)
- {
- XMoveResizeWindow(obt_display, self->handletop,
- ob_rr_theme->grip_width +
- self->bwidth + sidebwidth,
- FRAME_HANDLE_Y(self),
- self->width - (ob_rr_theme->grip_width +
- sidebwidth) * 2,
- self->bwidth);
- XMapWindow(obt_display, self->handletop);
-
- if (self->decorations & OB_FRAME_DECOR_GRIPS) {
- XMoveResizeWindow(obt_display, self->handleleft,
- ob_rr_theme->grip_width,
- 0,
- self->bwidth,
- ob_rr_theme->handle_height);
- XMoveResizeWindow(obt_display, self->handleright,
- self->width -
- ob_rr_theme->grip_width -
- self->bwidth,
- 0,
- self->bwidth,
- ob_rr_theme->handle_height);
-
- XMoveResizeWindow(obt_display, self->lgriptop,
- sidebwidth,
- FRAME_HANDLE_Y(self),
- ob_rr_theme->grip_width +
- self->bwidth,
- self->bwidth);
- XMoveResizeWindow(obt_display, self->rgriptop,
- self->size.left +
- self->client->area.width +
- self->size.right - self->bwidth -
- sidebwidth - ob_rr_theme->grip_width,
- FRAME_HANDLE_Y(self),
- ob_rr_theme->grip_width +
- self->bwidth,
- self->bwidth);
-
- XMapWindow(obt_display, self->handleleft);
- XMapWindow(obt_display, self->handleright);
- XMapWindow(obt_display, self->lgriptop);
- XMapWindow(obt_display, self->rgriptop);
- } else {
- XUnmapWindow(obt_display, self->handleleft);
- XUnmapWindow(obt_display, self->handleright);
- XUnmapWindow(obt_display, self->lgriptop);
- XUnmapWindow(obt_display, self->rgriptop);
- }
- } else {
- XUnmapWindow(obt_display, self->handleleft);
- XUnmapWindow(obt_display, self->handleright);
- XUnmapWindow(obt_display, self->lgriptop);
- XUnmapWindow(obt_display, self->rgriptop);
-
- XUnmapWindow(obt_display, self->handletop);
- }
- } else {
- XUnmapWindow(obt_display, self->handleleft);
- XUnmapWindow(obt_display, self->handleright);
- XUnmapWindow(obt_display, self->lgriptop);
- XUnmapWindow(obt_display, self->rgriptop);
-
- XUnmapWindow(obt_display, self->handletop);
-
- XUnmapWindow(obt_display, self->handlebottom);
- XUnmapWindow(obt_display, self->lgripleft);
- XUnmapWindow(obt_display, self->rgripright);
- XUnmapWindow(obt_display, self->lgripbottom);
- XUnmapWindow(obt_display, self->rgripbottom);
- }
-
- if (self->decorations & OB_FRAME_DECOR_HANDLE &&
- ob_rr_theme->handle_height > 0)
- {
- XMoveResizeWindow(obt_display, self->handle,
- sidebwidth,
- FRAME_HANDLE_Y(self) + self->bwidth,
- self->width, ob_rr_theme->handle_height);
- XMapWindow(obt_display, self->handle);
-
- if (self->decorations & OB_FRAME_DECOR_GRIPS) {
- XMoveResizeWindow(obt_display, self->lgrip,
- 0, 0,
- ob_rr_theme->grip_width,
- ob_rr_theme->handle_height);
- XMoveResizeWindow(obt_display, self->rgrip,
- self->width - ob_rr_theme->grip_width,
- 0,
- ob_rr_theme->grip_width,
- ob_rr_theme->handle_height);
-
- XMapWindow(obt_display, self->lgrip);
- XMapWindow(obt_display, self->rgrip);
- } else {
- XUnmapWindow(obt_display, self->lgrip);
- XUnmapWindow(obt_display, self->rgrip);
- }
- } else {
- XUnmapWindow(obt_display, self->lgrip);
- XUnmapWindow(obt_display, self->rgrip);
-
- XUnmapWindow(obt_display, self->handle);
- }
-
- if (self->bwidth && !self->max_horz &&
- (self->client->area.height + self->size.top +
- self->size.bottom) > ob_rr_theme->grip_width * 2)
- {
- XMoveResizeWindow(obt_display, self->left,
- 0,
- self->bwidth + ob_rr_theme->grip_width,
- self->bwidth,
- self->client->area.height +
- self->size.top + self->size.bottom -
- ob_rr_theme->grip_width * 2);
-
- XMapWindow(obt_display, self->left);
- } else
- XUnmapWindow(obt_display, self->left);
-
- if (self->bwidth && !self->max_horz &&
- (self->client->area.height + self->size.top +
- self->size.bottom) > ob_rr_theme->grip_width * 2)
- {
- XMoveResizeWindow(obt_display, self->right,
- self->client->area.width + self->cbwidth_l +
- self->cbwidth_r + self->bwidth,
- self->bwidth + ob_rr_theme->grip_width,
- self->bwidth,
- self->client->area.height +
- self->size.top + self->size.bottom -
- ob_rr_theme->grip_width * 2);
-
- XMapWindow(obt_display, self->right);
- } else
- XUnmapWindow(obt_display, self->right);
-
- XMoveResizeWindow(obt_display, self->backback,
- self->size.left, self->size.top,
- self->client->area.width,
- self->client->area.height);
- }
- }
-
- /* shading can change without being moved or resized */
- RECT_SET_SIZE(self->area,
- self->client->area.width +
- self->size.left + self->size.right,
- (self->client->shaded ?
- ob_rr_theme->title_height + self->bwidth * 2:
- self->client->area.height +
- self->size.top + self->size.bottom));
-
- if ((moved || resized) && !fake) {
- /* find the new coordinates, done after setting the frame.size, for
- frame_client_gravity. */
- self->area.x = self->client->area.x;
- self->area.y = self->client->area.y;
- frame_client_gravity(self, &self->area.x, &self->area.y);
- }
-
- if (!fake) {
- if (!frame_iconify_animating(self))
- /* move and resize the top level frame.
- shading can change without being moved or resized.
-
- but don't do this during an iconify animation. it will be
- reflected afterwards.
- */
- XMoveResizeWindow(obt_display, self->window,
- self->area.x,
- self->area.y,
- self->area.width,
- self->area.height);
-
- /* when the client has StaticGravity, it likes to move around.
- also this correctly positions the client when it maps.
- this also needs to be run when the frame's decorations sizes change!
- */
- XMoveWindow(obt_display, self->client->window,
- self->size.left, self->size.top);
-
- if (resized) {
- self->need_render = TRUE;
- framerender_frame(self);
- frame_adjust_shape(self);
- }
-
- if (!STRUT_EQUAL(self->size, oldsize)) {
- gulong vals[4];
- vals[0] = self->size.left;
- vals[1] = self->size.right;
- vals[2] = self->size.top;
- vals[3] = self->size.bottom;
- OBT_PROP_SETA32(self->client->window, NET_FRAME_EXTENTS,
- CARDINAL, vals, 4);
- OBT_PROP_SETA32(self->client->window, KDE_NET_WM_FRAME_STRUT,
- CARDINAL, vals, 4);
- }
-
- /* if this occurs while we are focus cycling, the indicator needs to
- match the changes */
- if (focus_cycle_target == self->client)
- focus_cycle_draw_indicator(self->client);
- }
- if (resized && (self->decorations & OB_FRAME_DECOR_TITLEBAR))
- XResizeWindow(obt_display, self->label, self->label_width,
- ob_rr_theme->label_height);
-
-}
-
-static void frame_adjust_cursors(ObFrame *self)
-{
- if ((self->functions & OB_CLIENT_FUNC_RESIZE) !=
- (self->client->functions & OB_CLIENT_FUNC_RESIZE) ||
- self->max_horz != self->client->max_horz ||
- self->max_vert != self->client->max_vert ||
- self->shaded != self->client->shaded)
- {
- gboolean r = (self->client->functions & OB_CLIENT_FUNC_RESIZE) &&
- !(self->client->max_horz && self->client->max_vert);
- gboolean topbot = !self->client->max_vert;
- gboolean sh = self->client->shaded;
- XSetWindowAttributes a;
-
- /* these ones turn off when max vert, and some when shaded */
- a.cursor = ob_cursor(r && topbot && !sh ?
- OB_CURSOR_NORTH : OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->topresize, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->titletop, CWCursor, &a);
- a.cursor = ob_cursor(r && topbot ? OB_CURSOR_SOUTH : OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->handle, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->handletop, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->handlebottom, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerbottom, CWCursor, &a);
-
- /* these ones change when shaded */
- a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_WEST : OB_CURSOR_NORTHWEST) :
- OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->titleleft, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->tltresize, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->tllresize, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->titletopleft, CWCursor, &a);
- a.cursor = ob_cursor(r ? (sh ? OB_CURSOR_EAST : OB_CURSOR_NORTHEAST) :
- OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->titleright, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->trtresize, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->trrresize, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->titletopright, CWCursor,&a);
-
- /* these ones are pretty static */
- a.cursor = ob_cursor(r ? OB_CURSOR_WEST : OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->left, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerleft, CWCursor, &a);
- a.cursor = ob_cursor(r ? OB_CURSOR_EAST : OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->right, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerright, CWCursor, &a);
- a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHWEST : OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->lgrip, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->handleleft, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->lgripleft, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->lgriptop, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->lgripbottom, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerbll, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerblb, CWCursor, &a);
- a.cursor = ob_cursor(r ? OB_CURSOR_SOUTHEAST : OB_CURSOR_NONE);
- XChangeWindowAttributes(obt_display, self->rgrip, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->handleright, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->rgripright, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->rgriptop, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->rgripbottom, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerbrr, CWCursor, &a);
- XChangeWindowAttributes(obt_display, self->innerbrb, CWCursor, &a);
- }
-}
-
-void frame_adjust_client_area(ObFrame *self)
-{
- /* adjust the window which is there to prevent flashing on unmap */
- XMoveResizeWindow(obt_display, self->backfront, 0, 0,
- self->client->area.width,
- self->client->area.height);
-}
-
-void frame_adjust_state(ObFrame *self)
-{
- self->need_render = TRUE;
- framerender_frame(self);
-}
-
-void frame_adjust_focus(ObFrame *self, gboolean hilite)
-{
- self->focused = hilite;
- self->need_render = TRUE;
- framerender_frame(self);
- XFlush(obt_display);
-}
-
-void frame_adjust_title(ObFrame *self)
-{
- self->need_render = TRUE;
- framerender_frame(self);
-}
-
-void frame_adjust_icon(ObFrame *self)
-{
- self->need_render = TRUE;
- framerender_frame(self);
-}
-
-void frame_grab_client(ObFrame *self)
-{
- /* DO NOT map the client window here. we used to do that, but it is bogus.
- we need to set up the client's dimensions and everything before we
- send a mapnotify or we create race conditions.
- */
-
- /* reparent the client to the frame */
- XReparentWindow(obt_display, self->client->window, self->window, 0, 0);
-
- /*
- When reparenting the client window, it is usually not mapped yet, since
- this occurs from a MapRequest. However, in the case where Openbox is
- starting up, the window is already mapped, so we'll see an unmap event
- for it.
- */
- if (ob_state() == OB_STATE_STARTING)
- ++self->client->ignore_unmaps;
-
- /* select the event mask on the client's parent (to receive config/map
- req's) the ButtonPress is to catch clicks on the client border */
- XSelectInput(obt_display, self->window, FRAME_EVENTMASK);
-
- /* set all the windows for the frame in the window_map */
- window_add(&self->window, CLIENT_AS_WINDOW(self->client));
- window_add(&self->backback, CLIENT_AS_WINDOW(self->client));
- window_add(&self->backfront, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerleft, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innertop, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerright, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerbottom, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerblb, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerbll, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerbrb, CLIENT_AS_WINDOW(self->client));
- window_add(&self->innerbrr, CLIENT_AS_WINDOW(self->client));
- window_add(&self->title, CLIENT_AS_WINDOW(self->client));
- window_add(&self->label, CLIENT_AS_WINDOW(self->client));
- window_add(&self->max, CLIENT_AS_WINDOW(self->client));
- window_add(&self->close, CLIENT_AS_WINDOW(self->client));
- window_add(&self->desk, CLIENT_AS_WINDOW(self->client));
- window_add(&self->shade, CLIENT_AS_WINDOW(self->client));
- window_add(&self->icon, CLIENT_AS_WINDOW(self->client));
- window_add(&self->iconify, CLIENT_AS_WINDOW(self->client));
- window_add(&self->handle, CLIENT_AS_WINDOW(self->client));
- window_add(&self->lgrip, CLIENT_AS_WINDOW(self->client));
- window_add(&self->rgrip, CLIENT_AS_WINDOW(self->client));
- window_add(&self->topresize, CLIENT_AS_WINDOW(self->client));
- window_add(&self->tltresize, CLIENT_AS_WINDOW(self->client));
- window_add(&self->tllresize, CLIENT_AS_WINDOW(self->client));
- window_add(&self->trtresize, CLIENT_AS_WINDOW(self->client));
- window_add(&self->trrresize, CLIENT_AS_WINDOW(self->client));
- window_add(&self->left, CLIENT_AS_WINDOW(self->client));
- window_add(&self->right, CLIENT_AS_WINDOW(self->client));
- window_add(&self->titleleft, CLIENT_AS_WINDOW(self->client));
- window_add(&self->titletop, CLIENT_AS_WINDOW(self->client));
- window_add(&self->titletopleft, CLIENT_AS_WINDOW(self->client));
- window_add(&self->titletopright, CLIENT_AS_WINDOW(self->client));
- window_add(&self->titleright, CLIENT_AS_WINDOW(self->client));
- window_add(&self->titlebottom, CLIENT_AS_WINDOW(self->client));
- window_add(&self->handleleft, CLIENT_AS_WINDOW(self->client));
- window_add(&self->handletop, CLIENT_AS_WINDOW(self->client));
- window_add(&self->handleright, CLIENT_AS_WINDOW(self->client));
- window_add(&self->handlebottom, CLIENT_AS_WINDOW(self->client));
- window_add(&self->lgripleft, CLIENT_AS_WINDOW(self->client));
- window_add(&self->lgriptop, CLIENT_AS_WINDOW(self->client));
- window_add(&self->lgripbottom, CLIENT_AS_WINDOW(self->client));
- window_add(&self->rgripright, CLIENT_AS_WINDOW(self->client));
- window_add(&self->rgriptop, CLIENT_AS_WINDOW(self->client));
- window_add(&self->rgripbottom, CLIENT_AS_WINDOW(self->client));
-}
-
-void frame_release_client(ObFrame *self)
-{
- XEvent ev;
- gboolean reparent = TRUE;
-
- /* if there was any animation going on, kill it */
- obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
- self, FALSE);
-
- /* check if the app has already reparented its window away */
- while (XCheckTypedWindowEvent(obt_display, self->client->window,
- ReparentNotify, &ev))
- {
- /* This check makes sure we don't catch our own reparent action to
- our frame window. This doesn't count as the app reparenting itself
- away of course.
-
- Reparent events that are generated by us are just discarded here.
- They are of no consequence to us anyhow.
- */
- if (ev.xreparent.parent != self->window) {
- reparent = FALSE;
- XPutBackEvent(obt_display, &ev);
- break;
- }
- }
-
- if (reparent) {
- /* according to the ICCCM - if the client doesn't reparent itself,
- then we will reparent the window to root for them */
- XReparentWindow(obt_display, self->client->window, obt_root(ob_screen),
- self->client->area.x, self->client->area.y);
- }
-
- /* remove all the windows for the frame from the window_map */
- window_remove(self->window);
- window_remove(self->backback);
- window_remove(self->backfront);
- window_remove(self->innerleft);
- window_remove(self->innertop);
- window_remove(self->innerright);
- window_remove(self->innerbottom);
- window_remove(self->innerblb);
- window_remove(self->innerbll);
- window_remove(self->innerbrb);
- window_remove(self->innerbrr);
- window_remove(self->title);
- window_remove(self->label);
- window_remove(self->max);
- window_remove(self->close);
- window_remove(self->desk);
- window_remove(self->shade);
- window_remove(self->icon);
- window_remove(self->iconify);
- window_remove(self->handle);
- window_remove(self->lgrip);
- window_remove(self->rgrip);
- window_remove(self->topresize);
- window_remove(self->tltresize);
- window_remove(self->tllresize);
- window_remove(self->trtresize);
- window_remove(self->trrresize);
- window_remove(self->left);
- window_remove(self->right);
- window_remove(self->titleleft);
- window_remove(self->titletop);
- window_remove(self->titletopleft);
- window_remove(self->titletopright);
- window_remove(self->titleright);
- window_remove(self->titlebottom);
- window_remove(self->handleleft);
- window_remove(self->handletop);
- window_remove(self->handleright);
- window_remove(self->handlebottom);
- window_remove(self->lgripleft);
- window_remove(self->lgriptop);
- window_remove(self->lgripbottom);
- window_remove(self->rgripright);
- window_remove(self->rgriptop);
- window_remove(self->rgripbottom);
-
- obt_main_loop_timeout_remove_data(ob_main_loop, flash_timeout, self, TRUE);
-}
-
-/* is there anything present between us and the label? */
-static gboolean is_button_present(ObFrame *self, const gchar *lc, gint dir) {
- for (; *lc != '\0' && lc >= config_title_layout; lc += dir) {
- if (*lc == ' ') continue; /* it was invalid */
- if (*lc == 'N' && self->decorations & OB_FRAME_DECOR_ICON)
- return TRUE;
- if (*lc == 'D' && self->decorations & OB_FRAME_DECOR_ALLDESKTOPS)
- return TRUE;
- if (*lc == 'S' && self->decorations & OB_FRAME_DECOR_SHADE)
- return TRUE;
- if (*lc == 'I' && self->decorations & OB_FRAME_DECOR_ICONIFY)
- return TRUE;
- if (*lc == 'M' && self->decorations & OB_FRAME_DECOR_MAXIMIZE)
- return TRUE;
- if (*lc == 'C' && self->decorations & OB_FRAME_DECOR_CLOSE)
- return TRUE;
- if (*lc == 'L') return FALSE;
- }
- return FALSE;
-}
-
-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(obt_display, self->icon);
- XMoveWindow(obt_display, self->icon, self->icon_x,
- ob_rr_theme->paddingy);
- } else
- XUnmapWindow(obt_display, self->icon);
-
- if (self->desk_on) {
- XMapWindow(obt_display, self->desk);
- XMoveWindow(obt_display, self->desk, self->desk_x,
- ob_rr_theme->paddingy + 1);
- } else
- XUnmapWindow(obt_display, self->desk);
-
- if (self->shade_on) {
- XMapWindow(obt_display, self->shade);
- XMoveWindow(obt_display, self->shade, self->shade_x,
- ob_rr_theme->paddingy + 1);
- } else
- XUnmapWindow(obt_display, self->shade);
-
- if (self->iconify_on) {
- XMapWindow(obt_display, self->iconify);
- XMoveWindow(obt_display, self->iconify, self->iconify_x,
- ob_rr_theme->paddingy + 1);
- } else
- XUnmapWindow(obt_display, self->iconify);
-
- if (self->max_on) {
- XMapWindow(obt_display, self->max);
- XMoveWindow(obt_display, self->max, self->max_x,
- ob_rr_theme->paddingy + 1);
- } else
- XUnmapWindow(obt_display, self->max);
-
- if (self->close_on) {
- XMapWindow(obt_display, self->close);
- XMoveWindow(obt_display, self->close, self->close_x,
- ob_rr_theme->paddingy + 1);
- } else
- XUnmapWindow(obt_display, self->close);
-
- if (self->label_on) {
- self->label_width = MAX(1, self->label_width); /* no lower than 1 */
- XMapWindow(obt_display, self->label);
- XMoveWindow(obt_display, self->label, self->label_x,
- ob_rr_theme->paddingy);
- } else
- XUnmapWindow(obt_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 == obt_root(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_BRCORNER;
- if (win == self->rgriptop) return OB_FRAME_CONTEXT_BRCORNER;
- if (win == self->rgripbottom) return OB_FRAME_CONTEXT_BRCORNER;
- 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->innerbll) return OB_FRAME_CONTEXT_BLCORNER;
- if (win == self->innerblb) return OB_FRAME_CONTEXT_BLCORNER;
- if (win == self->innerbrr) return OB_FRAME_CONTEXT_BRCORNER;
- if (win == self->innerbrb) return OB_FRAME_CONTEXT_BRCORNER;
- 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)
-{
- /* horizontal */
- switch (self->client->gravity) {
- default:
- case NorthWestGravity:
- case SouthWestGravity:
- case WestGravity:
- break;
-
- case NorthGravity:
- case SouthGravity:
- case CenterGravity:
- /* the middle of the client will be the middle of the frame */
- *x -= (self->size.right - self->size.left) / 2;
- break;
-
- case NorthEastGravity:
- case SouthEastGravity:
- case EastGravity:
- /* the right side of the client will be the right side of the frame */
- *x -= self->size.right + self->size.left -
- self->client->border_width * 2;
- break;
-
- case ForgetGravity:
- case StaticGravity:
- /* the client's position won't move */
- *x -= self->size.left - self->client->border_width;
- break;
- }
-
- /* vertical */
- switch (self->client->gravity) {
- default:
- case NorthWestGravity:
- case NorthEastGravity:
- case NorthGravity:
- break;
-
- case CenterGravity:
- case EastGravity:
- case WestGravity:
- /* the middle of the client will be the middle of the frame */
- *y -= (self->size.bottom - self->size.top) / 2;
- break;
-
- case SouthWestGravity:
- case SouthEastGravity:
- case SouthGravity:
- /* the bottom of the client will be the bottom of the frame */
- *y -= self->size.bottom + self->size.top -
- self->client->border_width * 2;
- break;
-
- case ForgetGravity:
- case StaticGravity:
- /* the client's position won't move */
- *y -= self->size.top - self->client->border_width;
- break;
- }
-}
-
-void frame_frame_gravity(ObFrame *self, gint *x, gint *y)
-{
- /* horizontal */
- switch (self->client->gravity) {
- default:
- case NorthWestGravity:
- case WestGravity:
- case SouthWestGravity:
- break;
- case NorthGravity:
- case CenterGravity:
- case SouthGravity:
- /* the middle of the client will be the middle of the frame */
- *x += (self->size.right - self->size.left) / 2;
- break;
- case NorthEastGravity:
- case EastGravity:
- case SouthEastGravity:
- /* the right side of the client will be the right side of the frame */
- *x += self->size.right + self->size.left -
- self->client->border_width * 2;
- break;
- case StaticGravity:
- case ForgetGravity:
- /* the client's position won't move */
- *x += self->size.left - self->client->border_width;
- break;
- }
-
- /* vertical */
- switch (self->client->gravity) {
- default:
- case NorthWestGravity:
- case NorthGravity:
- case NorthEastGravity:
- break;
- case WestGravity:
- case CenterGravity:
- case EastGravity:
- /* the middle of the client will be the middle of the frame */
- *y += (self->size.bottom - self->size.top) / 2;
- break;
- case SouthWestGravity:
- case SouthGravity:
- case SouthEastGravity:
- /* the bottom of the client will be the bottom of the frame */
- *y += self->size.bottom + self->size.top -
- self->client->border_width * 2;
- break;
- case StaticGravity:
- case ForgetGravity:
- /* the client's position won't move */
- *y += self->size.top - self->client->border_width;
- break;
- }
-}
-
-void frame_rect_to_frame(ObFrame *self, Rect *r)
-{
- r->width += self->size.left + self->size.right;
- r->height += self->size.top + self->size.bottom;
- frame_client_gravity(self, &r->x, &r->y);
-}
-
-void frame_rect_to_client(ObFrame *self, Rect *r)
-{
- r->width -= self->size.left + self->size.right;
- r->height -= self->size.top + self->size.bottom;
- frame_frame_gravity(self, &r->x, &r->y);
-}
-
-static void flash_done(gpointer data)
-{
- ObFrame *self = data;
-
- if (self->focused != self->flash_on)
- frame_adjust_focus(self, self->focused);
-}
-
-static gboolean flash_timeout(gpointer data)
-{
- ObFrame *self = data;
- GTimeVal now;
-
- g_get_current_time(&now);
- if (now.tv_sec > self->flash_end.tv_sec ||
- (now.tv_sec == self->flash_end.tv_sec &&
- now.tv_usec >= self->flash_end.tv_usec))
- self->flashing = FALSE;
-
- if (!self->flashing)
- return FALSE; /* we are done */
-
- self->flash_on = !self->flash_on;
- if (!self->focused) {
- frame_adjust_focus(self, self->flash_on);
- self->focused = FALSE;
- }
-
- return TRUE; /* go again */
-}
-
-void frame_flash_start(ObFrame *self)
-{
- self->flash_on = self->focused;
-
- if (!self->flashing)
- obt_main_loop_timeout_add(ob_main_loop,
- G_USEC_PER_SEC * 0.6,
- flash_timeout,
- self,
- g_direct_equal,
- flash_done);
- g_get_current_time(&self->flash_end);
- g_time_val_add(&self->flash_end, G_USEC_PER_SEC * 5);
-
- self->flashing = TRUE;
-}
-
-void frame_flash_stop(ObFrame *self)
-{
- self->flashing = FALSE;
-}
-
-static gulong frame_animate_iconify_time_left(ObFrame *self,
- const GTimeVal *now)
-{
- glong sec, usec;
- sec = self->iconify_animation_end.tv_sec - now->tv_sec;
- usec = self->iconify_animation_end.tv_usec - now->tv_usec;
- if (usec < 0) {
- usec += G_USEC_PER_SEC;
- sec--;
- }
- /* no negative values */
- return MAX(sec * G_USEC_PER_SEC + usec, 0);
-}
-
-static gboolean frame_animate_iconify(gpointer p)
-{
- ObFrame *self = p;
- gint x, y, w, h;
- gint iconx, icony, iconw;
- GTimeVal now;
- gulong time;
- gboolean iconifying;
-
- if (self->client->icon_geometry.width == 0) {
- /* there is no icon geometry set so just go straight down */
- Rect *a = screen_physical_area_monitor
- (screen_find_monitor(&self->area));
- iconx = self->area.x + self->area.width / 2 + 32;
- icony = a->y + a->width;
- iconw = 64;
- g_free(a);
- } else {
- iconx = self->client->icon_geometry.x;
- icony = self->client->icon_geometry.y;
- iconw = self->client->icon_geometry.width;
- }
-
- iconifying = self->iconify_animation_going > 0;
-
- /* how far do we have left to go ? */
- g_get_current_time(&now);
- time = frame_animate_iconify_time_left(self, &now);
-
- if (time == 0 || iconifying) {
- /* start where the frame is supposed to be */
- x = self->area.x;
- y = self->area.y;
- w = self->area.width;
- h = self->area.height;
- } else {
- /* start at the icon */
- x = iconx;
- y = icony;
- w = iconw;
- h = self->size.top; /* just the titlebar */
- }
-
- if (time > 0) {
- glong dx, dy, dw;
- glong elapsed;
-
- dx = self->area.x - iconx;
- dy = self->area.y - icony;
- dw = self->area.width - self->bwidth * 2 - iconw;
- /* if restoring, we move in the opposite direction */
- if (!iconifying) { dx = -dx; dy = -dy; dw = -dw; }
-
- elapsed = FRAME_ANIMATE_ICONIFY_TIME - time;
- x = x - (dx * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
- y = y - (dy * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
- w = w - (dw * elapsed) / FRAME_ANIMATE_ICONIFY_TIME;
- h = self->size.top; /* just the titlebar */
- }
-
- if (time == 0)
- frame_end_iconify_animation(self);
- else {
- XMoveResizeWindow(obt_display, self->window, x, y, w, h);
- XFlush(obt_display);
- }
-
- return time > 0; /* repeat until we're out of time */
-}
-
-void frame_end_iconify_animation(ObFrame *self)
-{
- /* see if there is an animation going */
- if (self->iconify_animation_going == 0) return;
-
- if (!self->visible)
- XUnmapWindow(obt_display, self->window);
- else {
- /* Send a ConfigureNotify when the animation is done, this fixes
- KDE's pager showing the window in the wrong place. since the
- window is mapped at a different location and is then moved, we
- need to send the synthetic configurenotify, since apps may have
- read the position when the client mapped, apparently. */
- client_reconfigure(self->client, TRUE);
- }
-
- /* we're not animating any more ! */
- self->iconify_animation_going = 0;
-
- XMoveResizeWindow(obt_display, self->window,
- self->area.x, self->area.y,
- self->area.width, self->area.height);
- /* we delay re-rendering until after we're done animating */
- framerender_frame(self);
- XFlush(obt_display);
-}
-
-void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying)
-{
- gulong time;
- gboolean new_anim = FALSE;
- gboolean set_end = TRUE;
- GTimeVal now;
-
- /* if there is no titlebar, just don't animate for now
- XXX it would be nice tho.. */
- if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
- return;
-
- /* get the current time */
- g_get_current_time(&now);
-
- /* get how long until the end */
- time = FRAME_ANIMATE_ICONIFY_TIME;
- if (self->iconify_animation_going) {
- if (!!iconifying != (self->iconify_animation_going > 0)) {
- /* animation was already going on in the opposite direction */
- time = time - frame_animate_iconify_time_left(self, &now);
- } else
- /* animation was already going in the same direction */
- set_end = FALSE;
- } else
- new_anim = TRUE;
- self->iconify_animation_going = iconifying ? 1 : -1;
-
- /* set the ending time */
- if (set_end) {
- self->iconify_animation_end.tv_sec = now.tv_sec;
- self->iconify_animation_end.tv_usec = now.tv_usec;
- g_time_val_add(&self->iconify_animation_end, time);
- }
-
- if (new_anim) {
- obt_main_loop_timeout_remove_data(ob_main_loop, frame_animate_iconify,
- self, FALSE);
- obt_main_loop_timeout_add(ob_main_loop,
- FRAME_ANIMATE_ICONIFY_STEP_TIME,
- frame_animate_iconify, self,
- g_direct_equal, NULL);
-
- /* do the first step */
- frame_animate_iconify(self);
-
- /* show it during the animation even if it is not "visible" */
- if (!self->visible)
- XMapWindow(obt_display, self->window);
- }
-}
+++ /dev/null
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
- frame.h for the Openbox window manager
- Copyright (c) 2006 Mikael Magnusson
- Copyright (c) 2003-2007 Dana Jansens
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#ifndef __frame_h
-#define __frame_h
-
-#include "geom.h"
-#include "render/render.h"
-
-typedef struct _ObFrame ObFrame;
-
-struct _ObClient;
-
-typedef void (*ObFrameIconifyAnimateFunc)(gpointer data);
-
-typedef enum {
- OB_FRAME_CONTEXT_NONE,
- OB_FRAME_CONTEXT_DESKTOP,
- OB_FRAME_CONTEXT_ROOT,
- OB_FRAME_CONTEXT_CLIENT,
- OB_FRAME_CONTEXT_TITLEBAR,
- OB_FRAME_CONTEXT_FRAME,
- OB_FRAME_CONTEXT_BLCORNER,
- OB_FRAME_CONTEXT_BRCORNER,
- OB_FRAME_CONTEXT_TLCORNER,
- OB_FRAME_CONTEXT_TRCORNER,
- OB_FRAME_CONTEXT_TOP,
- OB_FRAME_CONTEXT_BOTTOM,
- OB_FRAME_CONTEXT_LEFT,
- OB_FRAME_CONTEXT_RIGHT,
- OB_FRAME_CONTEXT_MAXIMIZE,
- OB_FRAME_CONTEXT_ALLDESKTOPS,
- OB_FRAME_CONTEXT_SHADE,
- OB_FRAME_CONTEXT_ICONIFY,
- OB_FRAME_CONTEXT_ICON,
- OB_FRAME_CONTEXT_CLOSE,
- /*! This is a special context, which occurs while dragging a window in
- a move/resize */
- OB_FRAME_CONTEXT_MOVE_RESIZE,
- OB_FRAME_NUM_CONTEXTS
-} ObFrameContext;
-
-/*! The decorations the client window wants to be displayed on it */
-typedef enum {
- OB_FRAME_DECOR_TITLEBAR = 1 << 0, /*!< Display a titlebar */
- OB_FRAME_DECOR_HANDLE = 1 << 1, /*!< Display a handle (bottom) */
- OB_FRAME_DECOR_GRIPS = 1 << 2, /*!< Display grips in the handle */
- OB_FRAME_DECOR_BORDER = 1 << 3, /*!< Display a border */
- OB_FRAME_DECOR_ICON = 1 << 4, /*!< Display the window's icon */
- OB_FRAME_DECOR_ICONIFY = 1 << 5, /*!< Display an iconify button */
- OB_FRAME_DECOR_MAXIMIZE = 1 << 6, /*!< Display a maximize button */
- /*! Display a button to toggle the window's placement on
- all desktops */
- OB_FRAME_DECOR_ALLDESKTOPS = 1 << 7,
- OB_FRAME_DECOR_SHADE = 1 << 8, /*!< Displays a shade button */
- OB_FRAME_DECOR_CLOSE = 1 << 9 /*!< Display a close button */
-} ObFrameDecorations;
-
-struct _ObFrame
-{
- struct _ObClient *client;
-
- Window window;
-
- Strut size;
- Rect area;
- gboolean visible;
-
- guint functions;
- guint decorations;
-
- Window title;
- Window label;
- Window max;
- Window close;
- Window desk;
- Window shade;
- Window icon;
- Window iconify;
- Window handle;
- Window lgrip;
- Window rgrip;
-
- /* These are borders of the frame and its elements */
- Window titleleft;
- Window titletop;
- Window titletopleft;
- Window titletopright;
- Window titleright;
- Window titlebottom;
- Window left;
- Window right;
- Window handleleft;
- Window handletop;
- Window handleright;
- Window handlebottom;
- Window lgriptop;
- Window lgripleft;
- Window lgripbottom;
- Window rgriptop;
- Window rgripright;
- Window rgripbottom;
- Window innerleft; /*!< For drawing the inner client border */
- Window innertop; /*!< For drawing the inner client border */
- Window innerright; /*!< For drawing the inner client border */
- Window innerbottom; /*!< For drawing the inner client border */
- Window innerblb;
- Window innerbll;
- Window innerbrb;
- Window innerbrr;
- Window backback; /*!< A colored window shown while resizing */
- Window backfront; /*!< An undrawn-in window, to prevent flashing on
- unmap */
-
- /* These are resize handles inside the titlebar */
- Window topresize;
- Window tltresize;
- Window tllresize;
- Window trtresize;
- Window trrresize;
-
- Colormap colormap;
-
- gint icon_on; /* if the window icon button is on */
- gint label_on; /* if the window title is on */
- gint iconify_on; /* if the window iconify button is on */
- gint desk_on; /* if the window all-desktops button is on */
- gint shade_on; /* if the window shade button is on */
- gint max_on; /* if the window maximize button is on */
- gint close_on; /* if the window close button is on */
-
- gint width; /* width of the titlebar and handle */
- gint label_width; /* width of the label in the titlebar */
- gint icon_x; /* x-position of the window icon button */
- gint label_x; /* x-position of the window title */
- gint iconify_x; /* x-position of the window iconify button */
- gint desk_x; /* x-position of the window all-desktops button */
- gint shade_x; /* x-position of the window shade button */
- gint max_x; /* x-position of the window maximize button */
- gint close_x; /* x-position of the window close button */
- gint bwidth; /* border width */
- gint cbwidth_l; /* client border width */
- gint cbwidth_t; /* client border width */
- gint cbwidth_r; /* client border width */
- gint cbwidth_b; /* client border width */
- gboolean max_horz; /* when maxed some decorations are hidden */
- gboolean max_vert; /* when maxed some decorations are hidden */
- gboolean shaded; /* decorations adjust when shaded */
-
- /* the leftmost and rightmost elements in the titlebar */
- ObFrameContext leftmost;
- ObFrameContext rightmost;
-
- gboolean max_press;
- gboolean close_press;
- gboolean desk_press;
- gboolean shade_press;
- gboolean iconify_press;
- gboolean max_hover;
- gboolean close_hover;
- gboolean desk_hover;
- gboolean shade_hover;
- gboolean iconify_hover;
-
- gboolean focused;
- gboolean need_render;
-
- gboolean flashing;
- gboolean flash_on;
- GTimeVal flash_end;
-
- /*! Is the frame currently in an animation for iconify or restore.
- 0 means that it is not animating. > 0 means it is animating an iconify.
- < 0 means it is animating a restore.
- */
- gint iconify_animation_going;
- GTimeVal iconify_animation_end;
-};
-
-ObFrame *frame_new(struct _ObClient *c);
-void frame_free(ObFrame *self);
-
-void frame_show(ObFrame *self);
-void frame_hide(ObFrame *self);
-void frame_adjust_theme(ObFrame *self);
-void frame_adjust_shape(ObFrame *self);
-void frame_adjust_area(ObFrame *self, gboolean moved,
- gboolean resized, gboolean fake);
-void frame_adjust_client_area(ObFrame *self);
-void frame_adjust_state(ObFrame *self);
-void frame_adjust_focus(ObFrame *self, gboolean hilite);
-void frame_adjust_title(ObFrame *self);
-void frame_adjust_icon(ObFrame *self);
-void frame_grab_client(ObFrame *self);
-void frame_release_client(ObFrame *self);
-
-ObFrameContext frame_context_from_string(const gchar *name);
-
-ObFrameContext frame_context(struct _ObClient *self, Window win,
- gint x, gint y);
-
-/*! Applies gravity to the client's position to find where the frame should
- be positioned.
- @return The proper coordinates for the frame, based on the client.
-*/
-void frame_client_gravity(ObFrame *self, gint *x, gint *y);
-
-/*! Reversly applies gravity to the frame's position to find where the client
- should be positioned.
- @return The proper coordinates for the client, based on the frame.
-*/
-void frame_frame_gravity(ObFrame *self, gint *x, gint *y);
-
-/*! Convert a rectangle in client coordinates/sizes to what it would be
- for the frame, given its current decorations sizes */
-void frame_rect_to_frame(ObFrame *self, Rect *r);
-
-/*! Convert a rectangle in frame coordinates/sizes to what it would be for the
- client, given its current decorations sizes */
-void frame_rect_to_client(ObFrame *self, Rect *r);
-
-void frame_flash_start(ObFrame *self);
-void frame_flash_stop(ObFrame *self);
-
-/*! Start an animation for iconifying or restoring a frame. The callback
- will be called when the animation finishes. But if another animation is
- started in the meantime, the callback will never get called. */
-void frame_begin_iconify_animation(ObFrame *self, gboolean iconifying);
-void frame_end_iconify_animation(ObFrame *self);
-
-#define frame_iconify_animating(f) (f->iconify_animation_going != 0)
-
-#endif
+++ /dev/null
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
- framerender.c for the Openbox window manager
- Copyright (c) 2006 Mikael Magnusson
- Copyright (c) 2003-2007 Dana Jansens
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#include "frame.h"
-#include "openbox.h"
-#include "screen.h"
-#include "client.h"
-#include "framerender.h"
-#include "render/theme.h"
-
-static void framerender_label(ObFrame *self, RrAppearance *a);
-static void framerender_icon(ObFrame *self, RrAppearance *a);
-static void framerender_max(ObFrame *self, RrAppearance *a);
-static void framerender_iconify(ObFrame *self, RrAppearance *a);
-static void framerender_desk(ObFrame *self, RrAppearance *a);
-static void framerender_shade(ObFrame *self, RrAppearance *a);
-static void framerender_close(ObFrame *self, RrAppearance *a);
-
-void framerender_frame(ObFrame *self)
-{
- if (frame_iconify_animating(self))
- return; /* delay redrawing until the animation is done */
- if (!self->need_render)
- return;
- if (!self->visible)
- return;
- self->need_render = FALSE;
-
- {
- gulong px;
-
- px = (self->focused ?
- RrColorPixel(ob_rr_theme->cb_focused_color) :
- RrColorPixel(ob_rr_theme->cb_unfocused_color));
-
- XSetWindowBackground(obt_display, self->backback, px);
- XClearWindow(obt_display, self->backback);
- XSetWindowBackground(obt_display, self->innerleft, px);
- XClearWindow(obt_display, self->innerleft);
- XSetWindowBackground(obt_display, self->innertop, px);
- XClearWindow(obt_display, self->innertop);
- XSetWindowBackground(obt_display, self->innerright, px);
- XClearWindow(obt_display, self->innerright);
- XSetWindowBackground(obt_display, self->innerbottom, px);
- XClearWindow(obt_display, self->innerbottom);
- XSetWindowBackground(obt_display, self->innerbll, px);
- XClearWindow(obt_display, self->innerbll);
- XSetWindowBackground(obt_display, self->innerbrr, px);
- XClearWindow(obt_display, self->innerbrr);
- XSetWindowBackground(obt_display, self->innerblb, px);
- XClearWindow(obt_display, self->innerblb);
- XSetWindowBackground(obt_display, self->innerbrb, px);
- XClearWindow(obt_display, self->innerbrb);
-
- px = (self->focused ?
- RrColorPixel(ob_rr_theme->frame_focused_border_color) :
- RrColorPixel(ob_rr_theme->frame_unfocused_border_color));
-
- XSetWindowBackground(obt_display, self->left, px);
- XClearWindow(obt_display, self->left);
- XSetWindowBackground(obt_display, self->right, px);
- XClearWindow(obt_display, self->right);
-
- XSetWindowBackground(obt_display, self->titleleft, px);
- XClearWindow(obt_display, self->titleleft);
- XSetWindowBackground(obt_display, self->titletop, px);
- XClearWindow(obt_display, self->titletop);
- XSetWindowBackground(obt_display, self->titletopleft, px);
- XClearWindow(obt_display, self->titletopleft);
- XSetWindowBackground(obt_display, self->titletopright, px);
- XClearWindow(obt_display, self->titletopright);
- XSetWindowBackground(obt_display, self->titleright, px);
- XClearWindow(obt_display, self->titleright);
-
- XSetWindowBackground(obt_display, self->handleleft, px);
- XClearWindow(obt_display, self->handleleft);
- XSetWindowBackground(obt_display, self->handletop, px);
- XClearWindow(obt_display, self->handletop);
- XSetWindowBackground(obt_display, self->handleright, px);
- XClearWindow(obt_display, self->handleright);
- XSetWindowBackground(obt_display, self->handlebottom, px);
- XClearWindow(obt_display, self->handlebottom);
-
- XSetWindowBackground(obt_display, self->lgripleft, px);
- XClearWindow(obt_display, self->lgripleft);
- XSetWindowBackground(obt_display, self->lgriptop, px);
- XClearWindow(obt_display, self->lgriptop);
- XSetWindowBackground(obt_display, self->lgripbottom, px);
- XClearWindow(obt_display, self->lgripbottom);
-
- XSetWindowBackground(obt_display, self->rgripright, px);
- XClearWindow(obt_display, self->rgripright);
- XSetWindowBackground(obt_display, self->rgriptop, px);
- XClearWindow(obt_display, self->rgriptop);
- XSetWindowBackground(obt_display, self->rgripbottom, px);
- XClearWindow(obt_display, self->rgripbottom);
-
- /* don't use the separator color for shaded windows */
- if (!self->client->shaded)
- px = (self->focused ?
- RrColorPixel(ob_rr_theme->title_separator_focused_color) :
- RrColorPixel(ob_rr_theme->title_separator_unfocused_color));
-
- XSetWindowBackground(obt_display, self->titlebottom, px);
- XClearWindow(obt_display, self->titlebottom);
- }
-
- if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
- RrAppearance *t, *l, *m, *n, *i, *d, *s, *c, *clear;
- if (self->focused) {
- t = ob_rr_theme->a_focused_title;
- l = ob_rr_theme->a_focused_label;
- m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
- ob_rr_theme->a_disabled_focused_max :
- (self->client->max_vert || self->client->max_horz ?
- (self->max_press ?
- ob_rr_theme->a_toggled_focused_pressed_max :
- (self->max_hover ?
- ob_rr_theme->a_toggled_hover_focused_max :
- ob_rr_theme->a_toggled_focused_unpressed_max)) :
- (self->max_press ?
- ob_rr_theme->a_focused_pressed_max :
- (self->max_hover ?
- ob_rr_theme->a_hover_focused_max :
- ob_rr_theme->a_focused_unpressed_max))));
- n = ob_rr_theme->a_icon;
- i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
- ob_rr_theme->a_disabled_focused_iconify :
- (self->iconify_press ?
- ob_rr_theme->a_focused_pressed_iconify :
- (self->iconify_hover ?
- ob_rr_theme->a_hover_focused_iconify :
- ob_rr_theme->a_focused_unpressed_iconify)));
- d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
- ob_rr_theme->a_disabled_focused_desk :
- (self->client->desktop == DESKTOP_ALL ?
- (self->desk_press ?
- ob_rr_theme->a_toggled_focused_pressed_desk :
- (self->desk_hover ?
- ob_rr_theme->a_toggled_hover_focused_desk :
- ob_rr_theme->a_toggled_focused_unpressed_desk)) :
- (self->desk_press ?
- ob_rr_theme->a_focused_pressed_desk :
- (self->desk_hover ?
- ob_rr_theme->a_hover_focused_desk :
- ob_rr_theme->a_focused_unpressed_desk))));
- s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
- ob_rr_theme->a_disabled_focused_shade :
- (self->client->shaded ?
- (self->shade_press ?
- ob_rr_theme->a_toggled_focused_pressed_shade :
- (self->shade_hover ?
- ob_rr_theme->a_toggled_hover_focused_shade :
- ob_rr_theme->a_toggled_focused_unpressed_shade)) :
- (self->shade_press ?
- ob_rr_theme->a_focused_pressed_shade :
- (self->shade_hover ?
- ob_rr_theme->a_hover_focused_shade :
- ob_rr_theme->a_focused_unpressed_shade))));
- c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
- ob_rr_theme->a_disabled_focused_close :
- (self->close_press ?
- ob_rr_theme->a_focused_pressed_close :
- (self->close_hover ?
- ob_rr_theme->a_hover_focused_close :
- ob_rr_theme->a_focused_unpressed_close)));
- } else {
- t = ob_rr_theme->a_unfocused_title;
- l = ob_rr_theme->a_unfocused_label;
- m = (!(self->decorations & OB_FRAME_DECOR_MAXIMIZE) ?
- ob_rr_theme->a_disabled_unfocused_max :
- (self->client->max_vert || self->client->max_horz ?
- (self->max_press ?
- ob_rr_theme->a_toggled_unfocused_pressed_max :
- (self->max_hover ?
- ob_rr_theme->a_toggled_hover_unfocused_max :
- ob_rr_theme->a_toggled_unfocused_unpressed_max)) :
- (self->max_press ?
- ob_rr_theme->a_unfocused_pressed_max :
- (self->max_hover ?
- ob_rr_theme->a_hover_unfocused_max :
- ob_rr_theme->a_unfocused_unpressed_max))));
- n = ob_rr_theme->a_icon;
- i = (!(self->decorations & OB_FRAME_DECOR_ICONIFY) ?
- ob_rr_theme->a_disabled_unfocused_iconify :
- (self->iconify_press ?
- ob_rr_theme->a_unfocused_pressed_iconify :
- (self->iconify_hover ?
- ob_rr_theme->a_hover_unfocused_iconify :
- ob_rr_theme->a_unfocused_unpressed_iconify)));
- d = (!(self->decorations & OB_FRAME_DECOR_ALLDESKTOPS) ?
- ob_rr_theme->a_disabled_unfocused_desk :
- (self->client->desktop == DESKTOP_ALL ?
- (self->desk_press ?
- ob_rr_theme->a_toggled_unfocused_pressed_desk :
- (self->desk_hover ?
- ob_rr_theme->a_toggled_hover_unfocused_desk :
- ob_rr_theme->a_toggled_unfocused_unpressed_desk)) :
- (self->desk_press ?
- ob_rr_theme->a_unfocused_pressed_desk :
- (self->desk_hover ?
- ob_rr_theme->a_hover_unfocused_desk :
- ob_rr_theme->a_unfocused_unpressed_desk))));
- s = (!(self->decorations & OB_FRAME_DECOR_SHADE) ?
- ob_rr_theme->a_disabled_unfocused_shade :
- (self->client->shaded ?
- (self->shade_press ?
- ob_rr_theme->a_toggled_unfocused_pressed_shade :
- (self->shade_hover ?
- ob_rr_theme->a_toggled_hover_unfocused_shade :
- ob_rr_theme->a_toggled_unfocused_unpressed_shade)) :
- (self->shade_press ?
- ob_rr_theme->a_unfocused_pressed_shade :
- (self->shade_hover ?
- ob_rr_theme->a_hover_unfocused_shade :
- ob_rr_theme->a_unfocused_unpressed_shade))));
- c = (!(self->decorations & OB_FRAME_DECOR_CLOSE) ?
- ob_rr_theme->a_disabled_unfocused_close :
- (self->close_press ?
- ob_rr_theme->a_unfocused_pressed_close :
- (self->close_hover ?
- ob_rr_theme->a_hover_unfocused_close :
- ob_rr_theme->a_unfocused_unpressed_close)));
- }
- clear = ob_rr_theme->a_clear;
-
- RrPaint(t, self->title, self->width, ob_rr_theme->title_height);
-
- clear->surface.parent = t;
- clear->surface.parenty = 0;
-
- clear->surface.parentx = ob_rr_theme->grip_width;
-
- RrPaint(clear, self->topresize,
- self->width - ob_rr_theme->grip_width * 2,
- ob_rr_theme->paddingy + 1);
-
- clear->surface.parentx = 0;
-
- if (ob_rr_theme->grip_width > 0)
- RrPaint(clear, self->tltresize,
- ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
- if (ob_rr_theme->title_height > 0)
- RrPaint(clear, self->tllresize,
- ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
-
- clear->surface.parentx = self->width - ob_rr_theme->grip_width;
-
- if (ob_rr_theme->grip_width > 0)
- RrPaint(clear, self->trtresize,
- ob_rr_theme->grip_width, ob_rr_theme->paddingy + 1);
-
- clear->surface.parentx = self->width - (ob_rr_theme->paddingx + 1);
-
- if (ob_rr_theme->title_height > 0)
- RrPaint(clear, self->trrresize,
- ob_rr_theme->paddingx + 1, ob_rr_theme->title_height);
-
- /* set parents for any parent relative guys */
- l->surface.parent = t;
- l->surface.parentx = self->label_x;
- l->surface.parenty = ob_rr_theme->paddingy;
-
- m->surface.parent = t;
- m->surface.parentx = self->max_x;
- m->surface.parenty = ob_rr_theme->paddingy + 1;
-
- n->surface.parent = t;
- n->surface.parentx = self->icon_x;
- n->surface.parenty = ob_rr_theme->paddingy;
-
- i->surface.parent = t;
- i->surface.parentx = self->iconify_x;
- i->surface.parenty = ob_rr_theme->paddingy + 1;
-
- d->surface.parent = t;
- d->surface.parentx = self->desk_x;
- d->surface.parenty = ob_rr_theme->paddingy + 1;
-
- s->surface.parent = t;
- s->surface.parentx = self->shade_x;
- s->surface.parenty = ob_rr_theme->paddingy + 1;
-
- c->surface.parent = t;
- c->surface.parentx = self->close_x;
- c->surface.parenty = ob_rr_theme->paddingy + 1;
-
- framerender_label(self, l);
- framerender_max(self, m);
- framerender_icon(self, n);
- framerender_iconify(self, i);
- framerender_desk(self, d);
- framerender_shade(self, s);
- framerender_close(self, c);
- }
-
- if (self->decorations & OB_FRAME_DECOR_HANDLE &&
- ob_rr_theme->handle_height > 0)
- {
- RrAppearance *h, *g;
-
- h = (self->focused ?
- ob_rr_theme->a_focused_handle : ob_rr_theme->a_unfocused_handle);
-
- RrPaint(h, self->handle, self->width, ob_rr_theme->handle_height);
-
- if (self->decorations & OB_FRAME_DECOR_GRIPS) {
- g = (self->focused ?
- ob_rr_theme->a_focused_grip : ob_rr_theme->a_unfocused_grip);
-
- if (g->surface.grad == RR_SURFACE_PARENTREL)
- g->surface.parent = h;
-
- g->surface.parentx = 0;
- g->surface.parenty = 0;
-
- RrPaint(g, self->lgrip,
- ob_rr_theme->grip_width, ob_rr_theme->handle_height);
-
- g->surface.parentx = self->width - ob_rr_theme->grip_width;
- g->surface.parenty = 0;
-
- RrPaint(g, self->rgrip,
- ob_rr_theme->grip_width, ob_rr_theme->handle_height);
- }
- }
-
- XFlush(obt_display);
-}
-
-static void framerender_label(ObFrame *self, RrAppearance *a)
-{
- if (!self->label_on) return;
- /* set the texture's text! */
- a->texture[0].data.text.string = self->client->title;
- RrPaint(a, self->label, self->label_width, ob_rr_theme->label_height);
-}
-
-static void framerender_icon(ObFrame *self, RrAppearance *a)
-{
- const ObClientIcon *icon;
-
- if (!self->icon_on) return;
-
- icon = client_icon(self->client,
- ob_rr_theme->button_size + 2,
- ob_rr_theme->button_size + 2);
- if (icon) {
- a->texture[0].type = RR_TEXTURE_RGBA;
- a->texture[0].data.rgba.width = icon->width;
- a->texture[0].data.rgba.height = icon->height;
- a->texture[0].data.rgba.alpha = 0xff;
- a->texture[0].data.rgba.data = icon->data;
- } else
- a->texture[0].type = RR_TEXTURE_NONE;
-
- RrPaint(a, self->icon,
- ob_rr_theme->button_size + 2, ob_rr_theme->button_size + 2);
-}
-
-static void framerender_max(ObFrame *self, RrAppearance *a)
-{
- if (!self->max_on) return;
- RrPaint(a, self->max, ob_rr_theme->button_size, ob_rr_theme->button_size);
-}
-
-static void framerender_iconify(ObFrame *self, RrAppearance *a)
-{
- if (!self->iconify_on) return;
- RrPaint(a, self->iconify,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
-}
-
-static void framerender_desk(ObFrame *self, RrAppearance *a)
-{
- if (!self->desk_on) return;
- RrPaint(a, self->desk, ob_rr_theme->button_size, ob_rr_theme->button_size);
-}
-
-static void framerender_shade(ObFrame *self, RrAppearance *a)
-{
- if (!self->shade_on) return;
- RrPaint(a, self->shade,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
-}
-
-static void framerender_close(ObFrame *self, RrAppearance *a)
-{
- if (!self->close_on) return;
- RrPaint(a, self->close,
- ob_rr_theme->button_size, ob_rr_theme->button_size);
-}
+++ /dev/null
-/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
- framerender.h for the Openbox window manager
- Copyright (c) 2003-2007 Dana Jansens
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- See the COPYING file for a copy of the GNU General Public License.
-*/
-
-#ifndef __framerender_h
-#define __framerender_h
-
-struct _ObFrame;
-
-void framerender_frame(struct _ObFrame *self);
-
-#endif
#include "focus.h"
#include "screen.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "openbox.h"
#include "event.h"
#include "grab.h"
#define ob__keybaord_h
#include "keytree.h"
-#include "frame.h"
+#include "engine_interface.h"
#include <glib.h>
#include <X11/Xlib.h>
#include "event.h"
#include "client.h"
#include "grab.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "translate.h"
#include "mouse.h"
#include "gettext.h"
guint mask;
if (FRAME_CONTEXT(i, client)) {
- win = client->frame->window;
+ win = render_plugin->frame_get_window(client->frame);
mode = GrabModeAsync;
mask = ButtonPressMask | ButtonMotionMask | ButtonReleaseMask;
} else if (CLIENT_CONTEXT(i, client)) {
switch (e->type) {
case ButtonPress:
- context = frame_context(client, e->xbutton.window,
+ context = plugin_frame_context(client, e->xbutton.window,
e->xbutton.x, e->xbutton.y);
context = mouse_button_frame_context(context, e->xbutton.button,
e->xbutton.state);
case ButtonRelease:
/* use where the press occured in the window */
- context = frame_context(client, e->xbutton.window, pwx, pwy);
+ context = plugin_frame_context(client, e->xbutton.window, pwx, pwy);
context = mouse_button_frame_context(context, e->xbutton.button,
e->xbutton.state);
case MotionNotify:
if (button) {
- context = frame_context(client, e->xmotion.window, pwx, pwy);
+ context = plugin_frame_context(client, e->xmotion.window, pwx, pwy);
context = mouse_button_frame_context(context, button, state);
if (ABS(e->xmotion.x_root - px) >= config_mouse_threshold ||
#ifndef ob__mouse_h
#define ob__mouse_h
-#include "frame.h"
+#include "engine_interface.h"
#include "misc.h"
#include <X11/Xlib.h>
*/
#include "grab.h"
-#include "framerender.h"
#include "screen.h"
#include "client.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "openbox.h"
#include "resist.h"
#include "popup.h"
/* how far windows move and resize with the keyboard arrows */
#define KEY_DIST 8
-gboolean moveresize_in_progress = FALSE;
+//gboolean moveresize_in_progress = FALSE;
ObClient *moveresize_client = NULL;
#ifdef SYNC
XSyncAlarm moveresize_alarm = None;
void moveresize_shutdown(gboolean reconfig)
{
if (!reconfig) {
- if (moveresize_in_progress)
+ if (render_plugin->moveresize_in_progress)
moveresize_end(FALSE);
client_remove_destroy_notify(client_dest);
}
{
gchar *text;
+ Strut size = render_plugin->frame_get_size(c->frame);
+ Rect area = render_plugin->frame_get_window_area(c->frame);
text = g_strdup_printf(format, a, b);
if (config_resize_popup_pos == OB_RESIZE_POS_TOP)
popup_position(popup, SouthGravity,
- c->frame->area.x
- + c->frame->area.width/2,
- c->frame->area.y - ob_rr_theme->fbwidth);
+ area.x
+ + area.width/2,
+ area.y - ob_rr_theme->fbwidth);
else if (config_resize_popup_pos == OB_RESIZE_POS_CENTER)
popup_position(popup, CenterGravity,
- c->frame->area.x + c->frame->size.left +
+ area.x + size.left +
c->area.width / 2,
- c->frame->area.y + c->frame->size.top +
+ area.y + size.top +
c->area.height / 2);
else /* Fixed */ {
Rect *area = screen_physical_area_active();
gint up = 1;
gint left = 1;
- if (moveresize_in_progress || !c->frame->visible ||
+ if (render_plugin->moveresize_in_progress || !render_plugin->frame_is_visible(c->frame) ||
!(mv ?
(c->functions & OB_CLIENT_FUNC_MOVE) :
(c->functions & OB_CLIENT_FUNC_RESIZE)))
return;
}
- frame_end_iconify_animation(c->frame);
+ render_plugin->frame_end_iconify_animation(c->frame);
moving = mv;
moveresize_client = c;
cur_w = start_cw;
cur_h = start_ch;
- moveresize_in_progress = TRUE;
+ render_plugin->moveresize_in_progress = TRUE;
#ifdef SYNC
if (config_resize_redraw && !moving && obt_display_extension_sync &&
/* dont edge warp after its ended */
cancel_edge_warp();
- moveresize_in_progress = FALSE;
+ render_plugin->moveresize_in_progress = FALSE;
moveresize_client = NULL;
}
TRUE, FALSE, FALSE);
if (config_resize_popup_show == 2) /* == "Always" */
popup_coords(moveresize_client, "%d x %d",
- moveresize_client->frame->area.x,
- moveresize_client->frame->area.y);
+ render_plugin->frame_get_window_area(moveresize_client->frame).x,
+ render_plugin->frame_get_window_area(moveresize_client->frame).y);
}
trydh = nh - oh;
}
+
+ Strut size = render_plugin->frame_get_size(moveresize_client->frame);
/* resist_size_* needs the frame size */
- nw += moveresize_client->frame->size.left +
- moveresize_client->frame->size.right;
- nh += moveresize_client->frame->size.top +
- moveresize_client->frame->size.bottom;
+ nw += size.left +
+ size.right;
+ nh += size.top +
+ size.bottom;
if (keyboard) resist = keydist - 1; /* resist for one key press */
else resist = config_resist_win;
if (!keyboard) resist = config_resist_edge;
resist_size_monitors(moveresize_client, resist, &nw, &nh, dir);
- nw -= moveresize_client->frame->size.left +
- moveresize_client->frame->size.right;
- nh -= moveresize_client->frame->size.top +
- moveresize_client->frame->size.bottom;
+ nw -= size.left +
+ size.right;
+ nh -= size.top +
+ size.bottom;
*dw = nw - ow;
*dh = nh - oh;
{
gboolean used = FALSE;
- if (!moveresize_in_progress) return FALSE;
+ if (!render_plugin->moveresize_in_progress) return FALSE;
if (e->type == ButtonPress) {
if (!button) {
OB_RESIZE_POS_FIXED
} ObResizePopupPos;
-extern gboolean moveresize_in_progress;
+//extern gboolean moveresize_in_progress;
extern struct _ObClient *moveresize_client;
#ifdef SYNC
extern XSyncAlarm moveresize_alarm;
#include "focus_cycle_indicator.h"
#include "focus_cycle_popup.h"
#include "moveresize.h"
-#include "frame.h"
-#include "framerender.h"
+#include "engine_interface.h"
#include "keyboard.h"
#include "mouse.h"
#include "menuframe.h"
gchar *ob_sm_save_file = NULL;
gboolean ob_sm_restore = TRUE;
gboolean ob_debug_xinerama = FALSE;
+ObFramePlugin *render_plugin = NULL;
static ObState state;
static gboolean xsync = FALSE;
}
/* load the theme specified in the rc file */
- {
+ {
+ ob_debug("Entering LoadThemeConfig");
+ render_plugin = init_frame_plugin (
+ config_theme, TRUE, config_font_activewindow,
+ config_font_inactivewindow, config_font_menutitle,
+ config_font_menuitem, config_font_osd);
+ ob_debug("Exiting LoadThemeConfig");
+ /* load the theme specified in the rc file */
RrTheme *theme;
if ((theme = RrThemeNew(ob_rr_inst, config_theme, TRUE,
config_font_activewindow,
/* update all existing windows for the new theme */
for (it = client_list; it; it = g_list_next(it)) {
ObClient *c = it->data;
- frame_adjust_theme(c->frame);
- }
- }
+ render_plugin->frame_adjust_theme(c->frame);
+ }
+ }
event_startup(reconfigure);
/* focus_backup is used for stacking, so this needs to come before
anything that calls stacking_add */
/* the new config can change the window's decorations */
client_setup_decor_and_functions(c, FALSE);
/* redraw the frames */
- frame_adjust_area(c->frame, TRUE, TRUE, FALSE);
+ render_plugin->frame_update_layout (c->frame, FALSE, FALSE);
/* the decor sizes may have changed, so the windows may
end up in new positions */
client_reconfigure(c, FALSE);
XSync(obt_display, FALSE);
- RrThemeFree(ob_rr_theme);
- RrInstanceFree(ob_rr_inst);
-
+ if (render_plugin)
+ {
+ //RrThemeFree(render_plugin->ob_rr_theme);
+ RrInstanceFree(render_plugin->ob_rr_inst);
+ }
session_shutdown(being_replaced);
obt_display_close(obt_display);
#include "render/render.h"
#include "render/theme.h"
+#include "engine_interface.h"
#include "obt/mainloop.h"
#include "obt/display.h"
extern gboolean ob_replace_wm;
extern gboolean ob_debug_xinerama;
+/* render function */
+extern ObFramePlugin *render_plugin;
+
/* The state of execution of the window manager */
ObState ob_state();
#include "client.h"
#include "group.h"
#include "screen.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "focus.h"
#include "config.h"
#include "dock.h"
#include "debug.h"
+#include "openbox.h"
extern ObDock *dock;
Rect **areas;
guint i;
+ Rect area = render_plugin->frame_get_window_area(client->frame);
+
areas = pick_head(client);
i = (config_place_monitor != OB_PLACE_MONITOR_ANY) ?
0 : g_random_int_range(0, screen_num_monitors);
l = areas[i]->x;
t = areas[i]->y;
- r = areas[i]->x + areas[i]->width - client->frame->area.width;
- b = areas[i]->y + areas[i]->height - client->frame->area.height;
+ r = areas[i]->x + areas[i]->width - area.width;
+ b = areas[i]->y + areas[i]->height - area.height;
if (r > l) *x = g_random_int_range(l, r + 1);
else *x = areas[i]->x;
*/
/* don't ignore this window, so remove it from the available
area */
- spaces = area_remove(spaces, &test->frame->area);
+ Rect test_area = render_plugin->frame_get_window_area(test->frame);
+ spaces = area_remove(spaces, &test_area);
}
if (ignore < IGNORE_DOCK) {
spaces = area_remove(spaces, &a);
}
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
for (sit = spaces; sit; sit = g_slist_next(sit)) {
Rect *r = sit->data;
- if (r->width >= c->frame->area.width &&
- r->height >= c->frame->area.height &&
+ if (r->width >= c_area.width &&
+ r->height >= c_area.height &&
r->width * r->height > maxsize)
{
maxsize = r->width * r->height;
*x = r->x;
*y = r->y;
if (config_place_center) {
- *x += (r->width - c->frame->area.width) / 2;
- *y += (r->height - c->frame->area.height) / 2;
+ *x += (r->width - c_area.width) / 2;
+ *y += (r->height - c_area.height) / 2;
}
ret = TRUE;
}
gint px, py;
Rect *area;
+ Strut fsize = render_plugin->frame_get_size(client->frame);
+ Rect farea = render_plugin->frame_get_window_area(client->frame);
+
if (!screen_pointer_pos(&px, &py))
return FALSE;
area = pick_pointer_head(client);
l = area->x;
t = area->y;
- r = area->x + area->width - client->frame->area.width;
- b = area->y + area->height - client->frame->area.height;
+ r = area->x + area->width - farea.width;
+ b = area->y + area->height - farea.height;
- *x = px - client->area.width / 2 - client->frame->size.left;
+ *x = px - client->area.width / 2 - fsize.left;
*x = MIN(MAX(*x, l), r);
- *y = py - client->area.height / 2 - client->frame->size.top;
+ *y = py - client->area.height / 2 - fsize.top;
*y = MIN(MAX(*y, t), b);
return TRUE;
g_free(areas);
}
+ Rect farea = render_plugin->frame_get_window_area(client->frame);
if (settings->position.x.center)
*x = screen->x + screen->width / 2 - client->area.width / 2;
else if (settings->position.x.opposite)
- *x = screen->x + screen->width - client->frame->area.width -
+ *x = screen->x + screen->width - farea.width -
settings->position.x.pos;
else
*x = screen->x + settings->position.x.pos;
if (settings->position.y.center)
*y = screen->y + screen->height / 2 - client->area.height / 2;
else if (settings->position.y.opposite)
- *y = screen->y + screen->height - client->frame->area.height -
+ *y = screen->y + screen->height - farea.height -
settings->position.y.pos;
else
*y = screen->y + settings->position.y.pos;
gint l, r, t, b;
for (it = client->parents; it; it = g_slist_next(it)) {
ObClient *m = it->data;
+ Rect area = render_plugin->frame_get_window_area(m->frame);
if (!m->iconic) {
if (first) {
- l = RECT_LEFT(m->frame->area);
- t = RECT_TOP(m->frame->area);
- r = RECT_RIGHT(m->frame->area);
- b = RECT_BOTTOM(m->frame->area);
+ l = RECT_LEFT(area);
+ t = RECT_TOP(area);
+ r = RECT_RIGHT(area);
+ b = RECT_BOTTOM(area);
first = FALSE;
} else {
- l = MIN(l, RECT_LEFT(m->frame->area));
- t = MIN(t, RECT_TOP(m->frame->area));
- r = MAX(r, RECT_RIGHT(m->frame->area));
- b = MAX(b, RECT_BOTTOM(m->frame->area));
+ l = MIN(l, RECT_LEFT(area));
+ t = MIN(t, RECT_TOP(area));
+ r = MAX(r, RECT_RIGHT(area));
+ b = MAX(b, RECT_BOTTOM(area));
}
}
if (!first) {
- *x = ((r + 1 - l) - client->frame->area.width) / 2 + l;
- *y = ((b + 1 - t) - client->frame->area.height) / 2 + t;
+ *x = ((r + 1 - l) - area.width) / 2 + l;
+ *y = ((b + 1 - t) - area.height) / 2 + t;
return TRUE;
}
}
client->type == OB_CLIENT_TYPE_SPLASH)
{
Rect **areas;
+ Rect area = render_plugin->frame_get_window_area(client->frame);
guint i;
areas = pick_head(client);
- *x = (areas[0]->width - client->frame->area.width) / 2 + areas[0]->x;
- *y = (areas[0]->height - client->frame->area.height) / 2 + areas[0]->y;
+ *x = (areas[0]->width - area.width) / 2 + areas[0]->x;
+ *y = (areas[0]->height - area.height) / 2 + areas[0]->y;
for (i = 0; i < screen_num_monitors; ++i)
g_free(areas[i]);
g_assert(ret);
/* get where the client should be */
- frame_frame_gravity(client->frame, x, y);
+ frame_frame_gravity(client, x, y);
return !userplaced;
}
#include "popup.h"
#include "openbox.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "client.h"
#include "stacking.h"
#include "event.h"
#include "resist.h"
#include "client.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "stacking.h"
#include "screen.h"
#include "dock.h"
#include "config.h"
+#include "openbox.h"
#include <glib.h>
GList *it;
Rect dock_area;
- if (!resist) return;
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
- frame_client_gravity(c->frame, x, y);
+ if (!resist) return;
+ frame_client_gravity(c, x, y);
for (it = stacking_list; it; it = g_list_next(it)) {
ObClient *target;
target = it->data;
/* don't snap to self or non-visibles */
- if (!target->frame->visible || target == c)
+ if (!render_plugin->frame_is_visible(target->frame) || target == c)
continue;
/* don't snap to windows set to below and skip_taskbar (desklets) */
if (target->below && !c->below && target->skip_taskbar)
continue;
- if (resist_move_window(c->frame->area, target->frame->area,
+ Rect target_area = render_plugin->frame_get_window_area(target->frame);
+ if (resist_move_window(c_area, target_area,
resist, x, y))
break;
}
dock_get_area(&dock_area);
- resist_move_window(c->frame->area, dock_area, resist, x, y);
+ resist_move_window(c_area, dock_area, resist, x, y);
- frame_frame_gravity(c->frame, x, y);
+ frame_frame_gravity(c, x, y);
}
void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y)
gint w, h; /* current size */
Rect desired_area;
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
+
if (!resist) return;
- frame_client_gravity(c->frame, x, y);
+ frame_client_gravity(c, x, y);
- w = c->frame->area.width;
- h = c->frame->area.height;
+ w = c_area.width;
+ h = c_area.height;
l = *x;
t = *y;
r = l + w - 1;
b = t + h - 1;
- cl = RECT_LEFT(c->frame->area);
- ct = RECT_TOP(c->frame->area);
- cr = RECT_RIGHT(c->frame->area);
- cb = RECT_BOTTOM(c->frame->area);
+ cl = RECT_LEFT(c_area);
+ ct = RECT_TOP(c_area);
+ cr = RECT_RIGHT(c_area);
+ cb = RECT_BOTTOM(c_area);
RECT_SET(desired_area, *x, *y, c->area.width, c->area.height);
for (i = 0; i < screen_num_monitors; ++i) {
parea = screen_physical_area_monitor(i);
- if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) {
+ if (!RECT_INTERSECTS_RECT(*parea, c_area)) {
g_free(parea);
continue;
}
g_free(parea);
}
- frame_frame_gravity(c->frame, x, y);
+ frame_frame_gravity(c, x, y);
}
static gboolean resist_size_window(Rect window, Rect target, gint resist,
ObClient *target; /* target */
Rect dock_area;
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
if (!resist) return;
for (it = stacking_list; it; it = g_list_next(it)) {
target = it->data;
/* don't snap to invisibles or ourself */
- if (!target->frame->visible || target == c)
+ if (!render_plugin->frame_is_visible(target->frame) || target == c)
continue;
/* don't snap to windows set to below and skip_taskbar (desklets) */
if (target->below && !c->below && target->skip_taskbar)
continue;
- if (resist_size_window(c->frame->area, target->frame->area,
+ Rect target_area = render_plugin->frame_get_window_area(target->frame);
+ if (resist_size_window(c_area, target_area,
resist, w, h, dir))
break;
}
dock_get_area(&dock_area);
- resist_size_window(c->frame->area, dock_area,
+ resist_size_window(c_area, dock_area,
resist, w, h, dir);
}
guint i;
Rect desired_area;
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
+
if (!resist) return;
- l = RECT_LEFT(c->frame->area);
- r = RECT_RIGHT(c->frame->area);
- t = RECT_TOP(c->frame->area);
- b = RECT_BOTTOM(c->frame->area);
+ l = RECT_LEFT(c_area);
+ r = RECT_RIGHT(c_area);
+ t = RECT_TOP(c_area);
+ b = RECT_BOTTOM(c_area);
incw = c->size_inc.width;
inch = c->size_inc.height;
for (i = 0; i < screen_num_monitors; ++i) {
parea = screen_physical_area_monitor(i);
- if (!RECT_INTERSECTS_RECT(*parea, c->frame->area)) {
+ if (!RECT_INTERSECTS_RECT(*parea, c_area)) {
g_free(parea);
continue;
}
case OB_DIRECTION_NORTH:
case OB_DIRECTION_SOUTH:
dlt = l;
- drb = r + *w - c->frame->area.width;
+ drb = r + *w - c_area.width;
if (r <= ar && drb > ar && drb <= ar + resist)
*w = ar - l + 1;
else if (r <= pr && drb > pr && drb <= pr + resist)
case OB_DIRECTION_WEST:
case OB_DIRECTION_NORTHWEST:
case OB_DIRECTION_SOUTHWEST:
- dlt = l - *w + c->frame->area.width;
+ dlt = l - *w + c_area.width;
drb = r;
if (l >= al && dlt < al && dlt >= al - resist)
*w = r - al + 1;
case OB_DIRECTION_WEST:
case OB_DIRECTION_EAST:
dlt = t;
- drb = b + *h - c->frame->area.height;
+ drb = b + *h - c_area.height;
if (b <= ab && drb > ab && drb <= ab + resist)
*h = ab - t + 1;
else if (b <= pb && drb > pb && drb <= pb + resist)
case OB_DIRECTION_NORTH:
case OB_DIRECTION_NORTHWEST:
case OB_DIRECTION_NORTHEAST:
- dlt = t - *h + c->frame->area.height;
+ dlt = t - *h + c_area.height;
drb = b;
if (t >= at && dlt < at && dlt >= at - resist)
*h = b - at + 1;
#include "screen.h"
#include "client.h"
#include "session.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "event.h"
#include "focus.h"
#include "popup.h"
if (c->can_focus) {
/* reduce flicker by hiliting now rather than waiting for the
server FocusIn event */
- frame_adjust_focus(c->frame, TRUE);
+ render_plugin->frame_set_is_focus (c->frame, TRUE);
+ render_plugin->frame_update_layout (c->frame, FALSE, FALSE);
+ render_plugin->frame_update_skin (c->frame);
/* do this here so that if you switch desktops to a window with
helper windows then the helper windows won't flash */
client_bring_helper_windows(c);
if (c->can_focus) {
/* reduce flicker by hiliting now rather than waiting for the
server FocusIn event */
- frame_adjust_focus(c->frame, TRUE);
+ render_plugin->frame_set_is_focus(c->frame, TRUE);
+ render_plugin->frame_update_layout (c->frame, FALSE, FALSE);
+ render_plugin->frame_update_skin (c->frame);
}
}
}
#include "focus.h"
#include "client.h"
#include "group.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "window.h"
#include "event.h"
#include "debug.h"
gboolean occluded = FALSE;
gboolean found = FALSE;
+ Rect client_area = render_plugin->frame_get_window_area(client->frame);
/* no need for any looping in this case */
if (sibling && client->layer != sibling->layer)
return occluded;
c->desktop == client->desktop) &&
!client_search_transient(client, c))
{
- if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area))
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
+ if (RECT_INTERSECTS_RECT(c_area, client_area))
{
if (sibling != NULL) {
if (c == sibling) {
gboolean occludes = FALSE;
gboolean found = FALSE;
+ Rect client_area = render_plugin->frame_get_window_area(client->frame);
+
/* no need for any looping in this case */
if (sibling && client->layer != sibling->layer)
return occludes;
c->desktop == client->desktop) &&
!client_search_transient(c, client))
{
- if (RECT_INTERSECTS_RECT(c->frame->area, client->frame->area))
+ Rect c_area = render_plugin->frame_get_window_area(c->frame);
+ if (RECT_INTERSECTS_RECT(c_area, client_area))
{
if (sibling != NULL) {
if (c == sibling) {
#include "config.h"
#include "dock.h"
#include "client.h"
-#include "frame.h"
+#include "engine_interface.h"
#include "openbox.h"
#include "prompt.h"
#include "debug.h"
#include "grab.h"
-static GHashTable *window_map;
+GHashTable *window_map;
static guint window_hash(Window *w) { return *w; }
static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
case OB_WINDOW_CLASS_DOCK:
return WINDOW_AS_DOCK(self)->frame;
case OB_WINDOW_CLASS_CLIENT:
- return WINDOW_AS_CLIENT(self)->frame->window;
+ return render_plugin->frame_get_window(WINDOW_AS_CLIENT(self)->frame);
case OB_WINDOW_CLASS_INTERNAL:
return WINDOW_AS_INTERNAL(self)->window;
case OB_WINDOW_CLASS_PROMPT:
void window_manage(Window win);
void window_unmanage_all(void);
+extern GHashTable *window_map;
+
#endif
#include "theme.h"
#include "icon.h"
#include "obt/paths.h"
+#include "openbox/engine_interface.h"
#include <X11/Xlib.h>
#include <X11/Xresource.h>
static RrPixel32* read_c_image(gint width, gint height, const guint8 *data);
static void set_default_appearance(RrAppearance *a);
+gint LoadThemeConfig(ObFramePlugin * p, const RrInstance *inst,
+ const gchar *name, gboolean allow_fallback, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font)
+ {
+ XrmDatabase db = NULL;
+ gchar *path;
+
+ if (name)
+ {
+ db = loaddb(name, &path);
+ if (db == NULL)
+ {
+ g_message("Unable to load the theme '%s'", name);
+ if (allow_fallback)
+ g_message("Falling back to the default theme '%s'", DEFAULT_THEME);
+ /* fallback to the default theme */
+ name = NULL;
+ }
+ }
+ if (name == NULL)
+ {
+ if (allow_fallback)
+ {
+ db = loaddb(DEFAULT_THEME, &path);
+ if (db == NULL)
+ {
+ g_message("Unable to load the theme '%s'", DEFAULT_THEME);
+ return 0;
+ }
+ }
+ else
+ return 0;
+ }
+
+ gint i = (p->load_theme_config)(inst, name, path, db, active_window_font,
+ inactive_window_font, menu_title_font, menu_item_font, osd_font);
+
+ g_free(path);
+ XrmDestroyDatabase(db);
+
+ return i;
+ }
+
RrTheme* RrThemeNew(const RrInstance *inst, const gchar *name,
gboolean allow_fallback,
RrFont *active_window_font, RrFont *inactive_window_font,
#define __theme_h
#include "render.h"
+#include "openbox/engine_interface.h"
G_BEGIN_DECLS
gchar *name;
};
+struct _ObFramePlugin;
+/*! The font values are all optional. If a NULL is used for any of them, then
+ the default font will be used. */
+gint LoadThemeConfig(struct _ObFramePlugin * p, const RrInstance *inst,
+ const gchar *name, gboolean allow_fallback, RrFont *active_window_font,
+ RrFont *inactive_window_font, RrFont *menu_title_font,
+ RrFont *menu_item_font, RrFont *osd_font);
+
/*! The font values are all optional. If a NULL is used for any of them, then
the default font will be used. */
RrTheme* RrThemeNew(const RrInstance *inst, const gchar *theme,