From e7395b916e867d0c632b88785406ce9fc8f1a7cf Mon Sep 17 00:00:00 2001 From: =?utf8?q?Beno=C3=AEt=20Gschwind?= Date: Wed, 13 Feb 2008 21:06:12 -0500 Subject: [PATCH] Implement plugin engine to draw frame (Follow Master patch) --- Makefile.am | 150 +- configure.ac | 8 + engines/concept/config.c | 432 +++++ engines/concept/config.h | 92 ++ engines/concept/plugin.c | 1158 +++++++++++++ engines/concept/plugin.h | 198 +++ engines/concept2/frame_concept2_config.c | 421 +++++ engines/concept2/frame_concept2_config.h | 52 + engines/concept2/frame_concept2_plugin.c | 1144 +++++++++++++ engines/concept2/frame_concept2_plugin.h | 181 +++ engines/concept2/frame_concept2_render.c | 95 ++ engines/concept2/frame_concept2_render.h | 26 + engines/default/config.c | 1552 ++++++++++++++++++ engines/default/config.h | 250 +++ engines/default/plugin.c | 1830 +++++++++++++++++++++ engines/default/plugin.h | 225 +++ engines/default/render.c | 385 +++++ engines/default/render.h | 26 + engines/minimal/frame_minimal_config.c | 1430 ++++++++++++++++ engines/minimal/frame_minimal_config.h | 251 +++ engines/minimal/frame_minimal_plugin.c | 1895 ++++++++++++++++++++++ engines/minimal/frame_minimal_plugin.h | 207 +++ engines/minimal/frame_minimal_render.c | 378 +++++ engines/minimal/frame_minimal_render.h | 26 + openbox/actions.h | 2 +- openbox/actions/growtoedge.c | 2 +- openbox/actions/if.c | 2 +- openbox/actions/moverelative.c | 2 +- openbox/actions/moveresizeto.c | 20 +- openbox/actions/movetoedge.c | 2 +- openbox/actions/resize.c | 17 +- openbox/actions/resizerelative.c | 2 +- openbox/client.c | 273 ++-- openbox/client_menu.c | 15 +- openbox/engine_interface.c | 420 +++++ openbox/engine_interface.h | 224 +++ openbox/event.c | 157 +- openbox/focus_cycle.c | 62 +- openbox/focus_cycle.h | 2 +- openbox/focus_cycle_indicator.c | 27 +- openbox/frame.c | 1811 --------------------- openbox/frame.h | 249 --- openbox/framerender.c | 408 ----- openbox/framerender.h | 26 - openbox/keyboard.c | 2 +- openbox/keyboard.h | 2 +- openbox/mouse.c | 10 +- openbox/mouse.h | 2 +- openbox/moveresize.c | 51 +- openbox/moveresize.h | 2 +- openbox/openbox.c | 29 +- openbox/openbox.h | 4 + openbox/place.c | 65 +- openbox/popup.c | 2 +- openbox/resist.c | 65 +- openbox/screen.c | 10 +- openbox/stacking.c | 11 +- openbox/window.c | 6 +- openbox/window.h | 2 + render/theme.c | 45 + render/theme.h | 9 + 61 files changed, 13563 insertions(+), 2889 deletions(-) create mode 100644 engines/concept/config.c create mode 100644 engines/concept/config.h create mode 100644 engines/concept/plugin.c create mode 100644 engines/concept/plugin.h create mode 100644 engines/concept2/frame_concept2_config.c create mode 100644 engines/concept2/frame_concept2_config.h create mode 100644 engines/concept2/frame_concept2_plugin.c create mode 100644 engines/concept2/frame_concept2_plugin.h create mode 100644 engines/concept2/frame_concept2_render.c create mode 100644 engines/concept2/frame_concept2_render.h create mode 100644 engines/default/config.c create mode 100644 engines/default/config.h create mode 100644 engines/default/plugin.c create mode 100644 engines/default/plugin.h create mode 100644 engines/default/render.c create mode 100644 engines/default/render.h create mode 100644 engines/minimal/frame_minimal_config.c create mode 100644 engines/minimal/frame_minimal_config.h create mode 100644 engines/minimal/frame_minimal_plugin.c create mode 100644 engines/minimal/frame_minimal_plugin.h create mode 100644 engines/minimal/frame_minimal_render.c create mode 100644 engines/minimal/frame_minimal_render.h create mode 100644 openbox/engine_interface.c create mode 100644 openbox/engine_interface.h delete mode 100644 openbox/frame.c delete mode 100644 openbox/frame.h delete mode 100644 openbox/framerender.c delete mode 100644 openbox/framerender.h diff --git a/Makefile.am b/Makefile.am index d8dba2c7..4b848429 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,11 @@ check_PROGRAMS = \ 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 \ @@ -94,6 +98,144 @@ render_libobrender_la_SOURCES = \ 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 ## @@ -230,10 +372,8 @@ openbox_openbox_SOURCES = \ 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 \ diff --git a/configure.ac b/configure.ac index 463e7fb3..4c5d2114 100644 --- a/configure.ac +++ b/configure.ac @@ -110,6 +110,14 @@ PKG_CHECK_MODULES(XML, [libxml-2.0 >= 2.6.0]) 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], diff --git a/engines/concept/config.c b/engines/concept/config.c new file mode 100644 index 00000000..b88348ba --- /dev/null +++ b/engines/concept/config.c @@ -0,0 +1,432 @@ +/* -*- 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 + +#include +#include +#include + +#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; +} diff --git a/engines/concept/config.h b/engines/concept/config.h new file mode 100644 index 00000000..d328fb7b --- /dev/null +++ b/engines/concept/config.h @@ -0,0 +1,92 @@ +/* -*- 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 +#include +#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_*/ diff --git a/engines/concept/plugin.c b/engines/concept/plugin.c new file mode 100644 index 00000000..30f52e61 --- /dev/null +++ b/engines/concept/plugin.c @@ -0,0 +1,1158 @@ +/* -*- 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; +} diff --git a/engines/concept/plugin.h b/engines/concept/plugin.h new file mode 100644 index 00000000..0f22499c --- /dev/null +++ b/engines/concept/plugin.h @@ -0,0 +1,198 @@ +/* -*- 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_*/ diff --git a/engines/concept2/frame_concept2_config.c b/engines/concept2/frame_concept2_config.c new file mode 100644 index 00000000..de77cc82 --- /dev/null +++ b/engines/concept2/frame_concept2_config.c @@ -0,0 +1,421 @@ +/* -*- 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 + +#include +#include +#include + +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; +} diff --git a/engines/concept2/frame_concept2_config.h b/engines/concept2/frame_concept2_config.h new file mode 100644 index 00000000..d7d18b46 --- /dev/null +++ b/engines/concept2/frame_concept2_config.h @@ -0,0 +1,52 @@ +/* -*- 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 +#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_*/ diff --git a/engines/concept2/frame_concept2_plugin.c b/engines/concept2/frame_concept2_plugin.c new file mode 100644 index 00000000..585dbbfb --- /dev/null +++ b/engines/concept2/frame_concept2_plugin.c @@ -0,0 +1,1144 @@ +/* -*- 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; +} diff --git a/engines/concept2/frame_concept2_plugin.h b/engines/concept2/frame_concept2_plugin.h new file mode 100644 index 00000000..e392188b --- /dev/null +++ b/engines/concept2/frame_concept2_plugin.h @@ -0,0 +1,181 @@ +/* -*- 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_*/ diff --git a/engines/concept2/frame_concept2_render.c b/engines/concept2/frame_concept2_render.c new file mode 100644 index 00000000..ce4a5734 --- /dev/null +++ b/engines/concept2/frame_concept2_render.c @@ -0,0 +1,95 @@ +/* -*- 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); +} diff --git a/engines/concept2/frame_concept2_render.h b/engines/concept2/frame_concept2_render.h new file mode 100644 index 00000000..deab47c2 --- /dev/null +++ b/engines/concept2/frame_concept2_render.h @@ -0,0 +1,26 @@ +/* -*- 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 diff --git a/engines/default/config.c b/engines/default/config.c new file mode 100644 index 00000000..893f8c21 --- /dev/null +++ b/engines/default/config.c @@ -0,0 +1,1552 @@ +/* -*- 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 + +#include +#include +#include + +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; +} diff --git a/engines/default/config.h b/engines/default/config.h new file mode 100644 index 00000000..56016047 --- /dev/null +++ b/engines/default/config.h @@ -0,0 +1,250 @@ +/* -*- 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 +#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_*/ diff --git a/engines/default/plugin.c b/engines/default/plugin.c new file mode 100644 index 00000000..a8adc866 --- /dev/null +++ b/engines/default/plugin.c @@ -0,0 +1,1830 @@ +/* -*- 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; +} diff --git a/engines/default/plugin.h b/engines/default/plugin.h new file mode 100644 index 00000000..b2c3a7df --- /dev/null +++ b/engines/default/plugin.h @@ -0,0 +1,225 @@ +/* -*- 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_*/ diff --git a/engines/default/render.c b/engines/default/render.c new file mode 100644 index 00000000..43fe0de7 --- /dev/null +++ b/engines/default/render.c @@ -0,0 +1,385 @@ +/* -*- 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); +} diff --git a/engines/default/render.h b/engines/default/render.h new file mode 100644 index 00000000..29bdc6ad --- /dev/null +++ b/engines/default/render.h @@ -0,0 +1,26 @@ +/* -*- 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 diff --git a/engines/minimal/frame_minimal_config.c b/engines/minimal/frame_minimal_config.c new file mode 100644 index 00000000..283df34c --- /dev/null +++ b/engines/minimal/frame_minimal_config.c @@ -0,0 +1,1430 @@ +/* -*- 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 + +#include +#include +#include + +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; +} diff --git a/engines/minimal/frame_minimal_config.h b/engines/minimal/frame_minimal_config.h new file mode 100644 index 00000000..8e832bdc --- /dev/null +++ b/engines/minimal/frame_minimal_config.h @@ -0,0 +1,251 @@ +/* -*- 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 +#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_*/ diff --git a/engines/minimal/frame_minimal_plugin.c b/engines/minimal/frame_minimal_plugin.c new file mode 100644 index 00000000..862e4fd2 --- /dev/null +++ b/engines/minimal/frame_minimal_plugin.c @@ -0,0 +1,1895 @@ +/* -*- 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; +} diff --git a/engines/minimal/frame_minimal_plugin.h b/engines/minimal/frame_minimal_plugin.h new file mode 100644 index 00000000..1ceec261 --- /dev/null +++ b/engines/minimal/frame_minimal_plugin.h @@ -0,0 +1,207 @@ +/* -*- 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_*/ diff --git a/engines/minimal/frame_minimal_render.c b/engines/minimal/frame_minimal_render.c new file mode 100644 index 00000000..abfc4d62 --- /dev/null +++ b/engines/minimal/frame_minimal_render.c @@ -0,0 +1,378 @@ +/* -*- 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); +} diff --git a/engines/minimal/frame_minimal_render.h b/engines/minimal/frame_minimal_render.h new file mode 100644 index 00000000..7996540d --- /dev/null +++ b/engines/minimal/frame_minimal_render.h @@ -0,0 +1,26 @@ +/* -*- 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 diff --git a/openbox/actions.h b/openbox/actions.h index 7975d4eb..a4e0a128 100644 --- a/openbox/actions.h +++ b/openbox/actions.h @@ -17,7 +17,7 @@ */ #include "misc.h" -#include "frame.h" +#include "engine_interface.h" #include "obt/parse.h" #include diff --git a/openbox/actions/growtoedge.c b/openbox/actions/growtoedge.c index a37e3a26..fdc01ca8 100644 --- a/openbox/actions/growtoedge.c +++ b/openbox/actions/growtoedge.c @@ -1,7 +1,7 @@ #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 diff --git a/openbox/actions/if.c b/openbox/actions/if.c index 63a7fbcd..dce885a3 100644 --- a/openbox/actions/if.c +++ b/openbox/actions/if.c @@ -1,7 +1,7 @@ #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 diff --git a/openbox/actions/moverelative.c b/openbox/actions/moverelative.c index ccdff545..3f72bac7 100644 --- a/openbox/actions/moverelative.c +++ b/openbox/actions/moverelative.c @@ -1,7 +1,7 @@ #include "openbox/actions.h" #include "openbox/client.h" #include "openbox/screen.h" -#include "openbox/frame.h" +#include "openbox/engine_interface.h" #include /* for atoi */ typedef struct { diff --git a/openbox/actions/moveresizeto.c b/openbox/actions/moveresizeto.c index d355dafd..faeeb0fe 100644 --- a/openbox/actions/moveresizeto.c +++ b/openbox/actions/moveresizeto.c @@ -1,7 +1,9 @@ #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 /* for atoi */ enum { @@ -124,27 +126,29 @@ static gboolean run_func(ObActionsData *data, gpointer options) 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); diff --git a/openbox/actions/movetoedge.c b/openbox/actions/movetoedge.c index f360ddd0..7875e131 100644 --- a/openbox/actions/movetoedge.c +++ b/openbox/actions/movetoedge.c @@ -1,7 +1,7 @@ #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 diff --git a/openbox/actions/resize.c b/openbox/actions/resize.c index 47f45f5b..3590c1d1 100644 --- a/openbox/actions/resize.c +++ b/openbox/actions/resize.c @@ -1,7 +1,10 @@ #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 { @@ -64,21 +67,23 @@ static gboolean run_func(ObActionsData *data, gpointer options) 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); } diff --git a/openbox/actions/resizerelative.c b/openbox/actions/resizerelative.c index 5742e1fc..0887e186 100644 --- a/openbox/actions/resizerelative.c +++ b/openbox/actions/resizerelative.c @@ -1,7 +1,7 @@ #include "openbox/actions.h" #include "openbox/client.h" #include "openbox/screen.h" -#include "openbox/frame.h" +#include "openbox/engine_interface.h" #include /* for atoi */ typedef struct { diff --git a/openbox/client.c b/openbox/client.c index dd1f5e72..c6b57814 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -25,7 +25,7 @@ #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" @@ -42,6 +42,7 @@ #include "gettext.h" #include "obt/display.h" #include "obt/prop.h" +#include "window.h" #ifdef HAVE_UNISTD_H # include @@ -228,9 +229,8 @@ void client_manage(Window window, ObPrompt *prompt) 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 */ @@ -274,8 +274,13 @@ void client_manage(Window window, ObPrompt *prompt) /* 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; @@ -355,9 +360,10 @@ void client_manage(Window window, ObPrompt *prompt) { 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); @@ -366,8 +372,8 @@ void client_manage(Window window, ObPrompt *prompt) 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); } @@ -404,7 +410,7 @@ void client_manage(Window window, ObPrompt *prompt) 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, @@ -551,7 +557,7 @@ void client_manage(Window window, ObPrompt *prompt) 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); } @@ -575,12 +581,13 @@ ObClient *client_fake_manage(Window window) 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); @@ -601,7 +608,7 @@ void client_unmanage(ObClient *self) 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); @@ -614,7 +621,7 @@ void client_unmanage(ObClient *self) 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); @@ -700,8 +707,8 @@ void client_unmanage(ObClient *self) } /* 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) { @@ -750,7 +757,7 @@ void client_fake_unmanage(ObClient *self) { /* this is all that got allocated to get the decorations */ - frame_free(self->frame); + render_plugin->frame_free(self->frame); g_free(self); } @@ -877,6 +884,9 @@ static void client_restore_session_state(ObClient *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) @@ -927,14 +937,16 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, 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 */ @@ -943,9 +955,10 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, 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); @@ -1031,7 +1044,7 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, } /* get where the client should be */ - frame_frame_gravity(self->frame, x, y); + frame_frame_gravity(self, x, y); return ox != *x || oy != *y; } @@ -1797,6 +1810,8 @@ static void client_change_allowed_actions(ObClient *self) 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); } } @@ -1931,7 +1946,7 @@ void client_update_title(ObClient *self) 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; @@ -2152,9 +2167,10 @@ void client_update_icons(ObClient *self) 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) @@ -2332,7 +2348,7 @@ static void client_change_state(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) @@ -2514,7 +2530,7 @@ gboolean client_show(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, @@ -2559,7 +2575,7 @@ gboolean client_hide(ObClient *self) 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, @@ -2640,6 +2656,7 @@ static void client_apply_startup_state(ObClient *self, /* 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.. */ @@ -2672,6 +2689,11 @@ static void client_apply_startup_state(ObClient *self, 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 */ @@ -2749,15 +2771,16 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, 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 */ @@ -2787,14 +2810,15 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, 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 @@ -2804,7 +2828,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, } /* 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)) { @@ -2921,11 +2945,14 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, 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); @@ -2939,9 +2966,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, 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 */ @@ -2951,10 +2980,8 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* 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 */ @@ -2978,7 +3005,8 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, 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); @@ -2990,9 +3018,9 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* 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; @@ -3042,16 +3070,16 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, 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); @@ -3157,7 +3185,7 @@ static void client_iconify_recursive(ObClient *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); } @@ -3243,6 +3271,9 @@ void client_maximize(ObClient *self, gboolean max, gint dir) 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); @@ -3259,7 +3290,8 @@ void client_shade(ObClient *self, gboolean shade) 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) @@ -3386,9 +3418,9 @@ void client_hilite(ObClient *self, gboolean hilite) 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); } } @@ -3411,7 +3443,8 @@ static void client_set_desktop_recursive(ObClient *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); @@ -3685,7 +3718,7 @@ gboolean client_can_focus(ObClient *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)) @@ -3771,7 +3804,7 @@ static void client_present(ObClient *self, gboolean here, gboolean raise, 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; @@ -3908,7 +3941,8 @@ void client_set_undecorated(ObClient *self, gboolean undecorated) 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) @@ -4103,10 +4137,13 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, 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: @@ -4154,7 +4191,7 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, 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); @@ -4171,30 +4208,33 @@ void client_find_move_directional(ObClient *self, ObDirection dir, 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(); @@ -4202,33 +4242,33 @@ void client_find_move_directional(ObClient *self, ObDirection dir, 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, @@ -4240,33 +4280,36 @@ 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: @@ -4277,39 +4320,39 @@ void client_find_resize_directional(ObClient *self, ObDirection side, 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) @@ -4322,15 +4365,15 @@ 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; diff --git a/openbox/client_menu.c b/openbox/client_menu.c index 04f50e85..c7617e47 100644 --- a/openbox/client_menu.c +++ b/openbox/client_menu.c @@ -24,7 +24,7 @@ #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" @@ -296,21 +296,24 @@ static void client_menu_place(ObMenuFrame *frame, gint *x, gint *y, 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); } diff --git a/openbox/engine_interface.c b/openbox/engine_interface.c new file mode 100644 index 00000000..b271762c --- /dev/null +++ b/openbox/engine_interface.c @@ -0,0 +1,420 @@ +/* -*- 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); +} diff --git a/openbox/engine_interface.h b/openbox/engine_interface.h new file mode 100644 index 00000000..e7d4c670 --- /dev/null +++ b/openbox/engine_interface.h @@ -0,0 +1,224 @@ +/* -*- 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 +#include + +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_*/ diff --git a/openbox/event.c b/openbox/event.c index cedac2e3..dbc7058d 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -26,7 +26,7 @@ #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" @@ -527,7 +527,9 @@ static void event_process(const XEvent *ec, gpointer data) /* 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 || @@ -590,7 +592,9 @@ static void event_process(const XEvent *ec, gpointer data) } 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); @@ -635,7 +639,9 @@ static void event_process(const XEvent *ec, gpointer data) } 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 */ } @@ -671,10 +677,11 @@ static void event_process(const XEvent *ec, gpointer data) 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); @@ -707,7 +714,7 @@ static void event_process(const XEvent *ec, gpointer data) 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 @@ -868,38 +875,38 @@ static void event_handle_client(ObClient *client, XEvent *e) !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: @@ -907,104 +914,64 @@ static void event_handle_client(ObClient *client, XEvent *e) 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, @@ -1031,28 +998,23 @@ static void event_handle_client(ObClient *client, XEvent *e) 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()) @@ -1107,8 +1069,7 @@ static void event_handle_client(ObClient *client, XEvent *e) 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) @@ -1202,11 +1163,13 @@ static void event_handle_client(ObClient *client, XEvent *e) 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) @@ -1265,7 +1228,7 @@ static void event_handle_client(ObClient *client, XEvent *e) 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. @@ -1607,7 +1570,7 @@ static void event_handle_client(ObClient *client, XEvent *e) 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 } @@ -1906,7 +1869,7 @@ static void event_handle_user_input(ObClient *client, XEvent *e) /* 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; @@ -1917,10 +1880,10 @@ static void event_handle_user_input(ObClient *client, XEvent *e) { /* 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); } } @@ -1942,7 +1905,7 @@ static gboolean focus_delay_func(gpointer data) 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; @@ -2030,7 +1993,7 @@ void event_cancel_all_key_grabs(void) 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"); } diff --git a/openbox/focus_cycle.c b/openbox/focus_cycle.c index dbf79c9a..af68c37f 100644 --- a/openbox/focus_cycle.c +++ b/openbox/focus_cycle.c @@ -20,7 +20,7 @@ #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" @@ -29,7 +29,7 @@ #include #include -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; @@ -54,7 +54,7 @@ void focus_cycle_stop(ObClient *ifclient) { /* 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, @@ -80,7 +80,7 @@ ObClient* focus_cycle(gboolean forward, gboolean 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; @@ -97,14 +97,14 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops, } - 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); @@ -126,8 +126,8 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops, 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 */ @@ -137,9 +137,9 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops, 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; } @@ -147,10 +147,10 @@ ObClient* focus_cycle(gboolean forward, gboolean all_desktops, } 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; @@ -177,9 +177,10 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir, 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; @@ -194,12 +195,13 @@ static ObClient *focus_find_directional(ObClient *c, ObDirection dir, 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) @@ -269,7 +271,7 @@ ObClient* focus_directional_cycle(ObDirection dir, gboolean dock_windows, 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; @@ -277,7 +279,7 @@ ObClient* focus_directional_cycle(ObDirection dir, gboolean dock_windows, 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; @@ -286,8 +288,8 @@ ObClient* focus_directional_cycle(ObDirection dir, gboolean 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); @@ -303,26 +305,26 @@ ObClient* focus_directional_cycle(ObDirection dir, gboolean dock_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(); diff --git a/openbox/focus_cycle.h b/openbox/focus_cycle.h index c31abc81..97ac8467 100644 --- a/openbox/focus_cycle.h +++ b/openbox/focus_cycle.h @@ -29,7 +29,7 @@ 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); diff --git a/openbox/focus_cycle_indicator.c b/openbox/focus_cycle_indicator.c index 495a7230..4639cb1a 100644 --- a/openbox/focus_cycle_indicator.c +++ b/openbox/focus_cycle_indicator.c @@ -21,7 +21,7 @@ #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" @@ -151,6 +151,7 @@ void focus_cycle_draw_indicator(ObClient *c) visible = FALSE; } else if (c) { + Rect area = render_plugin->frame_get_window_area(c->frame); /* if (c) frame_adjust_focus(c->frame, FALSE); @@ -162,9 +163,9 @@ void focus_cycle_draw_indicator(ObClient *c) 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 */ @@ -191,10 +192,10 @@ void focus_cycle_draw_indicator(ObClient *c) 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); @@ -217,10 +218,10 @@ void focus_cycle_draw_indicator(ObClient *c) 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); @@ -243,9 +244,9 @@ void focus_cycle_draw_indicator(ObClient *c) 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, diff --git a/openbox/frame.c b/openbox/frame.c deleted file mode 100644 index 0975214c..00000000 --- a/openbox/frame.c +++ /dev/null @@ -1,1811 +0,0 @@ -/* -*- 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); - } -} diff --git a/openbox/frame.h b/openbox/frame.h deleted file mode 100644 index 02be17a0..00000000 --- a/openbox/frame.h +++ /dev/null @@ -1,249 +0,0 @@ -/* -*- 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 diff --git a/openbox/framerender.c b/openbox/framerender.c deleted file mode 100644 index 87706b2b..00000000 --- a/openbox/framerender.c +++ /dev/null @@ -1,408 +0,0 @@ -/* -*- 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); -} diff --git a/openbox/framerender.h b/openbox/framerender.h deleted file mode 100644 index 162fa578..00000000 --- a/openbox/framerender.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- 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 diff --git a/openbox/keyboard.c b/openbox/keyboard.c index 02ae6a30..aa374c5d 100644 --- a/openbox/keyboard.c +++ b/openbox/keyboard.c @@ -19,7 +19,7 @@ #include "focus.h" #include "screen.h" -#include "frame.h" +#include "engine_interface.h" #include "openbox.h" #include "event.h" #include "grab.h" diff --git a/openbox/keyboard.h b/openbox/keyboard.h index 995cdbc5..5b354e22 100644 --- a/openbox/keyboard.h +++ b/openbox/keyboard.h @@ -21,7 +21,7 @@ #define ob__keybaord_h #include "keytree.h" -#include "frame.h" +#include "engine_interface.h" #include #include diff --git a/openbox/mouse.c b/openbox/mouse.c index 071a23b2..bed0fcb6 100644 --- a/openbox/mouse.c +++ b/openbox/mouse.c @@ -23,7 +23,7 @@ #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" @@ -117,7 +117,7 @@ void mouse_grab_for_client(ObClient *client, gboolean grab) 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)) { @@ -224,7 +224,7 @@ void mouse_event(ObClient *client, XEvent *e) 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); @@ -273,7 +273,7 @@ void mouse_event(ObClient *client, XEvent *e) 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); @@ -338,7 +338,7 @@ void mouse_event(ObClient *client, XEvent *e) 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 || diff --git a/openbox/mouse.h b/openbox/mouse.h index a862fe5b..41ba5b16 100644 --- a/openbox/mouse.h +++ b/openbox/mouse.h @@ -19,7 +19,7 @@ #ifndef ob__mouse_h #define ob__mouse_h -#include "frame.h" +#include "engine_interface.h" #include "misc.h" #include diff --git a/openbox/moveresize.c b/openbox/moveresize.c index ddc518ad..91eb7bb6 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -18,10 +18,9 @@ */ #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" @@ -41,7 +40,7 @@ /* 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; @@ -86,7 +85,7 @@ void moveresize_startup(gboolean reconfig) 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); } @@ -99,17 +98,19 @@ static void popup_coords(ObClient *c, const gchar *format, gint a, gint b) { 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(); @@ -172,7 +173,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) 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))) @@ -221,7 +222,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) return; } - frame_end_iconify_animation(c->frame); + render_plugin->frame_end_iconify_animation(c->frame); moving = mv; moveresize_client = c; @@ -252,7 +253,7 @@ void moveresize_start(ObClient *c, gint x, gint y, guint b, guint32 cnr) 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 && @@ -330,7 +331,7 @@ void moveresize_end(gboolean cancel) /* dont edge warp after its ended */ cancel_edge_warp(); - moveresize_in_progress = FALSE; + render_plugin->moveresize_in_progress = FALSE; moveresize_client = NULL; } @@ -348,8 +349,8 @@ static void do_move(gboolean keyboard, gint keydist) 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); } @@ -480,11 +481,13 @@ static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh, 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; @@ -492,10 +495,10 @@ static void calc_resize(gboolean keyboard, gint keydist, gint *dw, gint *dh, 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; @@ -827,7 +830,7 @@ gboolean moveresize_event(XEvent *e) { gboolean used = FALSE; - if (!moveresize_in_progress) return FALSE; + if (!render_plugin->moveresize_in_progress) return FALSE; if (e->type == ButtonPress) { if (!button) { diff --git a/openbox/moveresize.h b/openbox/moveresize.h index 2d0f7dce..ad222558 100644 --- a/openbox/moveresize.h +++ b/openbox/moveresize.h @@ -33,7 +33,7 @@ typedef enum { 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; diff --git a/openbox/openbox.c b/openbox/openbox.c index a6a81cef..55be9d79 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -32,8 +32,7 @@ #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" @@ -93,6 +92,7 @@ gchar *ob_sm_id = NULL; 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; @@ -255,7 +255,14 @@ gint main(gint argc, gchar **argv) } /* 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, @@ -280,9 +287,9 @@ gint main(gint argc, gchar **argv) /* 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 */ @@ -330,7 +337,7 @@ gint main(gint argc, gchar **argv) /* 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); @@ -372,9 +379,11 @@ gint main(gint argc, gchar **argv) 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); diff --git a/openbox/openbox.h b/openbox/openbox.h index 47d92042..bc6bf21b 100644 --- a/openbox/openbox.h +++ b/openbox/openbox.h @@ -23,6 +23,7 @@ #include "render/render.h" #include "render/theme.h" +#include "engine_interface.h" #include "obt/mainloop.h" #include "obt/display.h" @@ -46,6 +47,9 @@ extern gboolean ob_sm_restore; 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(); diff --git a/openbox/place.c b/openbox/place.c index aac40e8a..8c186134 100644 --- a/openbox/place.c +++ b/openbox/place.c @@ -20,11 +20,12 @@ #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; @@ -148,14 +149,16 @@ static gboolean place_random(ObClient *client, gint *x, gint *y) 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; @@ -310,7 +313,8 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) */ /* 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) { @@ -319,11 +323,12 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) 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; @@ -338,8 +343,8 @@ static gboolean place_nooverlap(ObClient *c, gint *x, gint *y) *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; } @@ -363,18 +368,21 @@ static gboolean place_under_mouse(ObClient *client, gint *x, gint *y) 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; @@ -411,10 +419,11 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y, 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; @@ -422,7 +431,7 @@ static gboolean place_per_app_setting(ObClient *client, gint *x, gint *y, 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; @@ -439,23 +448,24 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y) 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; } } @@ -465,12 +475,13 @@ static gboolean place_transient_splash(ObClient *client, gint *x, gint *y) 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]); @@ -506,6 +517,6 @@ gboolean place_client(ObClient *client, gint *x, gint *y, g_assert(ret); /* get where the client should be */ - frame_frame_gravity(client->frame, x, y); + frame_frame_gravity(client, x, y); return !userplaced; } diff --git a/openbox/popup.c b/openbox/popup.c index 02c87848..bbd05c31 100644 --- a/openbox/popup.c +++ b/openbox/popup.c @@ -20,7 +20,7 @@ #include "popup.h" #include "openbox.h" -#include "frame.h" +#include "engine_interface.h" #include "client.h" #include "stacking.h" #include "event.h" diff --git a/openbox/resist.c b/openbox/resist.c index 3bcb95ff..5e88326a 100644 --- a/openbox/resist.c +++ b/openbox/resist.c @@ -19,11 +19,12 @@ #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 @@ -104,10 +105,11 @@ void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) 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; @@ -117,20 +119,21 @@ void resist_move_windows(ObClient *c, gint resist, gint *x, gint *y) 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) @@ -144,29 +147,31 @@ 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; } @@ -205,7 +210,7 @@ void resist_move_monitors(ObClient *c, gint resist, gint *x, gint *y) 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, @@ -297,6 +302,7 @@ void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h, 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)) { @@ -305,18 +311,19 @@ void resist_size_windows(ObClient *c, gint resist, gint *w, gint *h, 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); } @@ -332,12 +339,14 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, 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; @@ -347,7 +356,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, 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; } @@ -373,7 +382,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, 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) @@ -382,7 +391,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, 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; @@ -399,7 +408,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, 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) @@ -408,7 +417,7 @@ void resist_size_monitors(ObClient *c, gint resist, gint *w, gint *h, 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; diff --git a/openbox/screen.c b/openbox/screen.c index 90f8b27c..b525c57f 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -27,7 +27,7 @@ #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" @@ -571,7 +571,9 @@ static void screen_fallback_focus(void) 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); @@ -1226,7 +1228,9 @@ void screen_show_desktop(gboolean show, ObClient *show_only) 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); } } } diff --git a/openbox/stacking.c b/openbox/stacking.c index 3c05df49..d9e8d40d 100644 --- a/openbox/stacking.c +++ b/openbox/stacking.c @@ -22,7 +22,7 @@ #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" @@ -544,6 +544,7 @@ static gboolean stacking_occluded(ObClient *client, ObClient *sibling) 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; @@ -557,7 +558,8 @@ static gboolean stacking_occluded(ObClient *client, ObClient *sibling) 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) { @@ -588,6 +590,8 @@ static gboolean stacking_occludes(ObClient *client, ObClient *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; @@ -600,7 +604,8 @@ static gboolean stacking_occludes(ObClient *client, ObClient *sibling) 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) { diff --git a/openbox/window.c b/openbox/window.c index c8951741..4c6b998b 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -21,13 +21,13 @@ #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; } @@ -55,7 +55,7 @@ Window window_top(ObWindow *self) 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: diff --git a/openbox/window.h b/openbox/window.h index 24a7d07b..76303b3c 100644 --- a/openbox/window.h +++ b/openbox/window.h @@ -90,4 +90,6 @@ void window_manage_all(void); void window_manage(Window win); void window_unmanage_all(void); +extern GHashTable *window_map; + #endif diff --git a/render/theme.c b/render/theme.c index a6931be6..f44d68a0 100644 --- a/render/theme.c +++ b/render/theme.c @@ -24,6 +24,7 @@ #include "theme.h" #include "icon.h" #include "obt/paths.h" +#include "openbox/engine_interface.h" #include #include @@ -46,6 +47,50 @@ 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 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, diff --git a/render/theme.h b/render/theme.h index 9f51fabd..0363050f 100644 --- a/render/theme.h +++ b/render/theme.h @@ -21,6 +21,7 @@ #define __theme_h #include "render.h" +#include "openbox/engine_interface.h" G_BEGIN_DECLS @@ -240,6 +241,14 @@ struct _RrTheme { 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, -- 2.39.2