/* -*-c-*- */
/* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This module is all original code
* by Rob Nation
* Copyright 1993, Robert Nation
* You may use this code for any purpose, as long as the original
* copyright remains in the source code and all documentation
*/
/* IMPORTANT NOTE:
*
* The functions in this module *must not* assume that the geometries in the
* FvwmWindow structure reflect the desired geometry of the window or its
* parts. While the window is resized or shaded, they may hold the old
* geometry instead of the new one (but you can not rely on this). Therefore,
* these geometries must not be accessed directly or indirectly (by the
* functions from geometry,c). Use the geometries that are passed in via
* structure pointers, e.d. "td".
*/
/* ---------------------------- included header files ---------------------- */
#include "config.h"
#include <stdio.h>
#include "libs/fvwmlib.h"
#include "libs/Parse.h"
#include "libs/Graphics.h"
#include "libs/Picture.h"
#include "libs/PictureGraphics.h"
#include "libs/FRenderInit.h"
#include "libs/charmap.h"
#include "libs/wcontext.h"
#include "fvwm.h"
#include "execcontext.h"
#include "externs.h"
#include "misc.h"
#include "screen.h"
#include "geometry.h"
#include "borders.h"
#include "builtins.h"
#include "icons.h"
#include "frame.h"
/* ---------------------------- local definitions -------------------------- */
/* ---------------------------- local macros ------------------------------- */
#define SWAP_ARGS(f,a1,a2) (f)?(a2):(a1),(f)?(a1):(a2)
/* ---------------------------- imports ------------------------------------ */
extern Window PressedW;
/* ---------------------------- included code files ------------------------ */
/* ---------------------------- local types -------------------------------- */
typedef struct
{
struct
{
unsigned use_pixmap : 1;
} flags;
Pixel pixel;
struct
{
Pixmap p;
Pixmap shape;
Pixmap alpha;
int depth;
FvwmRenderAttributes fra;
rectangle g;
int stretch_w;
int stretch_h;
struct
{
unsigned is_tiled : 1;
unsigned is_stretched : 1;
} flags;
} pixmap;
} pixmap_background_type;
typedef struct
{
Pixmap p;
FvwmPicture *mp_created_pic;
int cs;
FvwmPicture *mp_pic;
int mp_part;
Bool created;
} bar_pixmap;
typedef struct
{
int count;
bar_pixmap *bps;
} bar_bs_pixmaps; /* for UseTitleStyle & Colorset */
typedef struct
{
Pixmap frame_pixmap;
bar_bs_pixmaps bar_pixmaps[BS_MaxButtonState];
} dynamic_common_decorations;
typedef struct
{
int relief_width;
GC relief_gc;
GC shadow_gc;
Pixel fore_color;
Pixel back_color;
int cs;
int border_cs; /* for UseBorderStyle */
int bg_border_cs; /* for UseBorderStyle */
Pixmap back_pixmap;
XSetWindowAttributes attributes;
unsigned long valuemask;
Pixmap texture_pixmap;
int texture_pixmap_width;
int texture_pixmap_height;
XSetWindowAttributes notex_attributes;
unsigned long notex_valuemask;
dynamic_common_decorations dynamic_cd;
} common_decorations_type;
typedef struct
{
GC relief;
GC shadow;
GC transparent;
} draw_border_gcs;
typedef struct
{
int offset_tl;
int offset_br;
int thickness;
int length;
unsigned has_x_marks : 1;
unsigned has_y_marks : 1;
} border_marks_descr;
typedef struct
{
int w_dout;
int w_hiout;
int w_trout;
int w_c;
int w_trin;
int w_shin;
int w_din;
int sum;
int trim;
unsigned is_flat : 1;
} border_relief_size_descr;
typedef struct
{
rectangle sidebar_g;
border_relief_size_descr relief;
border_marks_descr marks;
draw_border_gcs gcs;
} border_relief_descr;
typedef struct
{
unsigned pressed_bmask : NUMBER_OF_TITLE_BUTTONS;
unsigned lit_bmask : NUMBER_OF_TITLE_BUTTONS;
unsigned toggled_bmask : NUMBER_OF_TITLE_BUTTONS;
unsigned clear_bmask : NUMBER_OF_TITLE_BUTTONS;
unsigned draw_bmask : NUMBER_OF_TITLE_BUTTONS;
unsigned max_bmask : NUMBER_OF_TITLE_BUTTONS;
ButtonState bstate[NUMBER_OF_TITLE_BUTTONS];
unsigned is_title_pressed : 1;
unsigned is_title_lit : 1;
unsigned do_clear_title : 1;
ButtonState tstate;
} border_titlebar_state;
typedef struct
{
GC rgc;
GC sgc;
FlocaleWinString fstr;
DecorFaceStyle *tstyle;
DecorFace *df;
unsigned is_toggled : 1;
} title_draw_descr;
typedef struct
{
common_decorations_type *cd;
rectangle frame_g;
rectangle bar_g; /* titlebar geo vs the frame */
rectangle left_buttons_g; /* vs the frame */
rectangle right_buttons_g; /* vs the frame */
frame_title_layout_t layout;
frame_title_layout_t old_layout;
border_titlebar_state tbstate;
int length; /* text */
int offset; /* text offset */
/* MultiPixmap Geometries */
rectangle under_text_g; /* vs the titlebar */
rectangle left_main_g; /* vs the titlebar */
rectangle right_main_g; /* vs the titlebar */
rectangle full_left_main_g; /* vs the frame */
rectangle full_right_main_g; /* vs the frame */
int left_end_length;
int left_of_text_length;
int right_end_length;
int right_of_text_length;
rotation_t draw_rotation;
rotation_t restore_rotation;
unsigned td_is_rotated : 1;
unsigned has_been_saved : 1;
unsigned has_vt : 1; /* vertical title ? */
unsigned has_an_upsidedown_rotation : 1; /* 270 || 180 */
} titlebar_descr;
/* ---------------------------- forward declarations ----------------------- */
/* forward declarations are not so good */
/* for grouping titlebar_descr computation */
static void border_rotate_titlebar_descr(FvwmWindow *fw, titlebar_descr *td);
/* for grouping the MultiPixmap stuff */
static Bool border_mp_get_use_title_style_parts_and_geometry(
titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs,
unsigned short sf, int is_left, rectangle *g, int *part);
/* ---------------------------- local variables ---------------------------- */
static const char ulgc[] = { 1, 0, 0, 0x7f, 2, 1, 1 };
static const char brgc[] = { 1, 1, 2, 0x7f, 0, 0, 3 };
/* ---------------------------- exported variables (globals) --------------- */
XGCValues Globalgcv;
unsigned long Globalgcm;
/* ---------------------------- local functions ---------------------------- */
static Bool is_button_toggled(
FvwmWindow *fw, int button)
{
mwm_flags mf;
if (!HAS_MWM_BUTTONS(fw))
{
return False;
}
mf = TB_MWM_DECOR_FLAGS(GetDecor(fw, buttons[button]));
if ((mf & MWM_DECOR_MAXIMIZE) && IS_MAXIMIZED(fw))
{
return True;
}
if ((mf & MWM_DECOR_SHADE) && IS_SHADED(fw))
{
return True;
}
if ((mf & MWM_DECOR_STICK) &&
(IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw)))
{
return True;
}
if (TB_FLAGS(fw->decor->buttons[button]).has_layer &&
fw->layer == TB_LAYER(fw->decor->buttons[button]))
{
return True;
}
return False;
}
/* rules to get button state */
static ButtonState border_flags_to_button_state(
int is_pressed, int is_lit, int is_toggled)
{
if (!is_lit && Scr.gs.use_inactive_buttons)
{
if (is_pressed && Scr.gs.use_inactive_down_buttons)
{
return (is_toggled) ?
BS_ToggledInactiveDown : BS_InactiveDown;
}
else
{
return (is_toggled) ?
BS_ToggledInactiveUp : BS_InactiveUp;
}
}
else
{
if (is_pressed && Scr.gs.use_active_down_buttons)
{
return (is_toggled) ?
BS_ToggledActiveDown : BS_ActiveDown;
}
else
{
return (is_toggled) ?
BS_ToggledActiveUp : BS_ActiveUp;
}
}
}
static void get_common_decorations(
common_decorations_type *cd, FvwmWindow *t,
window_parts draw_parts, Bool has_focus, Bool is_border,
Bool do_change_gcs)
{
DecorFace *df;
color_quad *draw_colors;
df = border_get_border_style(t, has_focus);
cd->bg_border_cs = -1;
cd->cs = -1;
if (has_focus)
{
/* are we using textured borders? */
if (DFS_FACE_TYPE(df->style) == TiledPixmapButton &&
GetDecor(t, BorderStyle.active.u.p->depth) == Pdepth)
{
cd->texture_pixmap = GetDecor(
t, BorderStyle.active.u.p->picture);
cd->texture_pixmap_width = GetDecor(
t, BorderStyle.active.u.p->width);
cd->texture_pixmap_height = GetDecor(
t, BorderStyle.active.u.p->height);
}
else if (DFS_FACE_TYPE(df->style) == ColorsetButton)
{
cd->bg_border_cs = GetDecor(
t, BorderStyle.active.u.acs.cs);
}
cd->back_pixmap = Scr.gray_pixmap;
if (is_border)
{
draw_colors = &(t->border_hicolors);
cd->cs = t->border_cs_hi;
}
else
{
draw_colors = &(t->hicolors);
cd->cs = t->cs_hi;
}
}
else
{
if (DFS_FACE_TYPE(df->style) == TiledPixmapButton &&
GetDecor(t, BorderStyle.inactive.u.p->depth) == Pdepth)
{
cd->texture_pixmap = GetDecor(
t, BorderStyle.inactive.u.p->picture);
cd->texture_pixmap_width = GetDecor(
t, BorderStyle.inactive.u.p->width);
cd->texture_pixmap_height = GetDecor(
t, BorderStyle.inactive.u.p->height);
}
else if (DFS_FACE_TYPE(df->style) == ColorsetButton)
{
cd->bg_border_cs = GetDecor(
t, BorderStyle.inactive.u.acs.cs);
}
if (IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t))
{
cd->back_pixmap = Scr.sticky_gray_pixmap;
}
else
{
cd->back_pixmap = Scr.light_gray_pixmap;
}
if (is_border)
{
draw_colors = &(t->border_colors);
cd->cs = t->border_cs;
}
else
{
draw_colors = &(t->colors);
cd->cs = t->cs;
}
}
cd->fore_color = draw_colors->fore;
cd->back_color = draw_colors->back;
if (do_change_gcs)
{
Globalgcv.foreground = draw_colors->hilight;
Globalgcm = GCForeground;
XChangeGC(dpy, Scr.ScratchGC1, Globalgcm, &Globalgcv);
Globalgcv.foreground = draw_colors->shadow;
XChangeGC(dpy, Scr.ScratchGC2, Globalgcm, &Globalgcv);
cd->relief_gc = Scr.ScratchGC1;
cd->shadow_gc = Scr.ScratchGC2;
}
/* MWMBorder style means thin 3d effects */
cd->relief_width = (HAS_MWM_BORDER(t) ? 1 : 2);
if (cd->texture_pixmap)
{
cd->attributes.background_pixmap = cd->texture_pixmap;
cd->valuemask = CWBackPixmap;
}
else
{
if (Pdepth < 2)
{
cd->attributes.background_pixmap = cd->back_pixmap;
cd->valuemask = CWBackPixmap;
}
else
{
cd->attributes.background_pixel = cd->back_color;
cd->valuemask = CWBackPixel;
}
}
if (Pdepth < 2)
{
cd->notex_attributes.background_pixmap = cd->back_pixmap;
cd->notex_valuemask = CWBackPixmap;
}
else
{
cd->notex_attributes.background_pixel = cd->back_color;
cd->notex_valuemask = CWBackPixel;
}
return;
}
static window_parts border_get_changed_border_parts(
FvwmWindow *fw, rectangle *old_sidebar_g, rectangle *new_sidebar_g,
int cs)
{
window_parts changed_parts;
changed_parts = PART_NONE;
if (!CSET_IS_TRANSPARENT_PR(cs) && CSET_HAS_PIXMAP(cs) &&
(old_sidebar_g->x != new_sidebar_g->x ||
old_sidebar_g->y != new_sidebar_g->y ||
old_sidebar_g->width != new_sidebar_g->width ||
old_sidebar_g->height != new_sidebar_g->height))
{
/* optimizable? */
changed_parts |= PART_FRAME;
return changed_parts;
}
if (old_sidebar_g->x != new_sidebar_g->x)
{
changed_parts |= (PART_FRAME & (~PART_BORDER_W));
}
if (old_sidebar_g->y != new_sidebar_g->y)
{
changed_parts |= (PART_FRAME & (~PART_BORDER_N));
}
if (old_sidebar_g->width != new_sidebar_g->width)
{
changed_parts |=
PART_BORDER_N | PART_BORDER_S;
if (DFS_FACE_TYPE(GetDecor(fw, BorderStyle.active.style)) ==
TiledPixmapButton)
{
changed_parts |=
PART_BORDER_NE | PART_BORDER_E | PART_BORDER_SE;
}
}
if (old_sidebar_g->height != new_sidebar_g->height)
{
changed_parts |=
PART_BORDER_W | PART_BORDER_E;
if (DFS_FACE_TYPE(GetDecor(fw, BorderStyle.active.style)) ==
TiledPixmapButton)
{
changed_parts |=
PART_BORDER_SW | PART_BORDER_S | PART_BORDER_SE;
}
}
return changed_parts;
}
static int border_get_parts_and_pos_to_draw(
common_decorations_type *cd, FvwmWindow *fw,
window_parts pressed_parts, window_parts force_draw_parts,
rectangle *old_g, rectangle *new_g, Bool do_hilight,
border_relief_descr *br)
{
window_parts draw_parts;
window_parts parts_to_light;
rectangle sidebar_g_old;
DecorFaceStyle *borderstyle;
Bool has_x_marks;
Bool has_x_marks_old;
Bool has_y_marks;
Bool has_y_marks_old;
int cs = cd->bg_border_cs;
draw_parts = 0;
borderstyle = (do_hilight) ?
&GetDecor(fw, BorderStyle.active.style) :
&GetDecor(fw, BorderStyle.inactive.style);
frame_get_sidebar_geometry(
fw, borderstyle, new_g, &br->sidebar_g, &has_x_marks,
&has_y_marks);
if (has_x_marks == True)
{
draw_parts |= PART_X_HANDLES;
br->marks.has_x_marks = 1;
}
else
{
br->marks.has_x_marks = 0;
}
if (has_y_marks == True)
{
draw_parts |= PART_Y_HANDLES;
br->marks.has_y_marks = 1;
}
else
{
br->marks.has_y_marks = 0;
}
draw_parts |= (pressed_parts ^ fw->decor_state.parts_inverted);
parts_to_light = (do_hilight == True) ? PART_FRAME : PART_NONE;
draw_parts |= (parts_to_light ^ fw->decor_state.parts_lit);
draw_parts |= (~(fw->decor_state.parts_drawn) & PART_FRAME);
draw_parts |= force_draw_parts;
if (old_g == NULL)
{
old_g = &fw->g.frame;
}
if ((draw_parts & PART_FRAME) == PART_FRAME)
{
draw_parts |= PART_FRAME;
return draw_parts;
}
frame_get_sidebar_geometry(
fw, borderstyle, old_g, &sidebar_g_old, &has_x_marks_old,
&has_y_marks_old);
if (has_x_marks_old != has_x_marks)
{
draw_parts |= (PART_FRAME & (~(PART_BORDER_N | PART_BORDER_S)));
}
if (has_y_marks_old != has_y_marks)
{
draw_parts |= (PART_FRAME & (~(PART_BORDER_W | PART_BORDER_E)));
}
draw_parts |= border_get_changed_border_parts(
fw, &sidebar_g_old, &br->sidebar_g, cs);
draw_parts &= (PART_FRAME | PART_HANDLES);
return draw_parts;
}
static window_parts border_get_tb_parts_to_draw(
FvwmWindow *fw, titlebar_descr *td, rectangle *old_g, rectangle *new_g,
window_parts force_draw_parts)
{
window_parts draw_parts;
ButtonState old_state;
int i;
DecorFace *df,*tdf;
td->tbstate.draw_bmask = 0;
draw_parts = PART_NONE;
/* first time? */
draw_parts |= (~(fw->decor_state.parts_drawn) & PART_TITLE);
td->tbstate.draw_bmask |= (~(fw->decor_state.buttons_drawn));
/* forced? */
draw_parts |= force_draw_parts;
td->tbstate.draw_bmask |= (force_draw_parts & PART_BUTTONS) ? ~0 : 0;
/* check if state changed */
old_state = border_flags_to_button_state(
(fw->decor_state.parts_inverted & PART_TITLE),
(fw->decor_state.parts_lit & PART_TITLE), 0);
if (old_state != td->tbstate.tstate)
{
draw_parts |= PART_TITLE;
}
/* size changed? */
if ((td->old_layout.title_g.width != td->layout.title_g.width ||
td->old_layout.title_g.height != td->layout.title_g.height) &&
td->layout.title_g.x >= 0 && td->layout.title_g.y >= 0)
{
draw_parts |= PART_TITLE;
}
/* same for buttons */
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
unsigned int mask = (1 << i);
if (FW_W_BUTTON(fw, i) == None)
{
continue;
}
old_state = border_flags_to_button_state(
(fw->decor_state.buttons_inverted & mask),
(fw->decor_state.buttons_lit & mask),
(fw->decor_state.buttons_toggled & mask));
if (old_state != td->tbstate.bstate[i])
{
draw_parts |= PART_BUTTONS;
td->tbstate.draw_bmask |= mask;
}
if ((td->old_layout.button_g[i].width !=
td->layout.button_g[i].width ||
td->old_layout.button_g[i].height !=
td->layout.button_g[i].height) &&
td->layout.button_g[i].x >= 0 &&
td->layout.button_g[i].y >= 0)
{
draw_parts |= PART_BUTTONS;
td->tbstate.draw_bmask |= mask;
}
}
/* position changed and background is tiled or a cset? */
if ((draw_parts & PART_TITLE) == PART_NONE &&
td->layout.title_g.x >= 0 &&
td->layout.title_g.y >= 0)
{
df = &TB_STATE(GetDecor(fw, titlebar))[td->tbstate.tstate];
if (DFS_USE_BORDER_STYLE(df->style) &&
(((td->old_layout.title_g.x != td->layout.title_g.x ||
td->old_layout.title_g.y != td->layout.title_g.y) &&
((td->cd->valuemask & CWBackPixmap) ||
CSET_PIXMAP_IS_TILED(td->cd->bg_border_cs)))
||
(old_g->width != new_g->width &&
CSET_PIXMAP_IS_X_STRETCHED(td->cd->bg_border_cs))
||
(old_g->height != new_g->height
&& CSET_PIXMAP_IS_Y_STRETCHED(td->cd->bg_border_cs))
||
((old_g->x != new_g->x || old_g->y != new_g->y)
&& CSET_IS_TRANSPARENT_ROOT(td->cd->bg_border_cs))))
{
draw_parts |= PART_TITLE;
}
if ((draw_parts & PART_TITLE) == PART_NONE &&
(old_g->x != new_g->x || old_g->y != new_g->y))
{
for (tdf = df; tdf != NULL; tdf = tdf->next)
{
if (DFS_FACE_TYPE(tdf->style) ==
ColorsetButton &&
CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs))
{
draw_parts |= PART_TITLE;
break;
}
}
}
}
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
unsigned int mask;
DecorFaceStyle *bs;
mask = (1 << i);
bs = &TB_STATE(
GetDecor(fw, buttons[i]))[td->tbstate.bstate[i]].style;
if ((td->tbstate.draw_bmask & mask) ||
td->layout.button_g[i].x < 0 ||
td->layout.button_g[i].y < 0)
{
continue;
}
if (DFS_USE_BORDER_STYLE(*bs) &&
(((td->old_layout.button_g[i].x !=
td->layout.button_g[i].x||
td->old_layout.button_g[i].y !=
td->layout.button_g[i].y)
&& ((td->cd->valuemask & CWBackPixmap) ||
CSET_PIXMAP_IS_TILED(td->cd->bg_border_cs)))
||
(old_g->width != new_g->width &&
CSET_PIXMAP_IS_X_STRETCHED(td->cd->bg_border_cs))
||
(old_g->height != new_g->height
&& CSET_PIXMAP_IS_Y_STRETCHED(td->cd->bg_border_cs))
||
((old_g->x != new_g->x || old_g->y != new_g->y)
&& CSET_IS_TRANSPARENT_ROOT(td->cd->bg_border_cs))))
{
td->tbstate.draw_bmask |= mask;
}
else if (DFS_USE_TITLE_STYLE(*bs))
{
df = &TB_STATE(GetDecor(
fw, titlebar))[td->tbstate.bstate[i]];
for(tdf = df; tdf != NULL; tdf = tdf->next)
{
int cs;
if (DFS_FACE_TYPE(tdf->style) == MultiPixmap)
{
/* can be improved */
td->tbstate.draw_bmask |= mask;
break;
}
if (DFS_FACE_TYPE(tdf->style) != ColorsetButton
|| !CSET_HAS_PIXMAP(tdf->u.acs.cs))
{
continue;
}
cs = tdf->u.acs.cs;
if(((td->old_layout.button_g[i].x !=
td->layout.button_g[i].x ||
td->old_layout.button_g[i].y !=
td->layout.button_g[i].y) ||
CSET_PIXMAP_IS_TILED(cs))
||
(old_g->width != new_g->width &&
CSET_PIXMAP_IS_X_STRETCHED(cs))
||
(old_g->height != new_g->height &&
CSET_PIXMAP_IS_Y_STRETCHED(cs))
||
((old_g->x != new_g->x ||
old_g->y != new_g->y)
&& CSET_IS_TRANSPARENT_ROOT(cs)))
{
td->tbstate.draw_bmask |= mask;
break;
}
}
}
if (td->tbstate.draw_bmask & mask)
{
continue;
}
if (old_g->x != new_g->x || old_g->y != new_g->y)
{
df = &TB_STATE(GetDecor(
fw, buttons[i]))[td->tbstate.bstate[i]];
for(tdf = df; tdf != NULL; tdf = tdf->next)
{
if (DFS_FACE_TYPE(tdf->style) ==
ColorsetButton &&
CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs))
{
td->tbstate.draw_bmask |= mask;
break;
}
}
}
}
td->tbstate.max_bmask = 0;
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
if (FW_W_BUTTON(fw, i) == None)
{
continue;
}
if ((i & 1) == 1 && i / 2 < Scr.nr_right_buttons)
{
td->tbstate.max_bmask |= (1 << i);
}
else if ((i & 1) == 0 && i / 2 < Scr.nr_left_buttons)
{
td->tbstate.max_bmask |= (1 << i);
}
}
td->tbstate.draw_bmask &= td->tbstate.max_bmask;
td->tbstate.pressed_bmask &= td->tbstate.max_bmask;
td->tbstate.lit_bmask &= td->tbstate.max_bmask;
td->tbstate.toggled_bmask &= td->tbstate.max_bmask;
td->tbstate.clear_bmask &= td->tbstate.max_bmask;
if (td->tbstate.draw_bmask == 0)
{
draw_parts &= ~PART_BUTTONS;
}
else
{
draw_parts |= PART_BUTTONS;
}
draw_parts &= PART_TITLEBAR;
return draw_parts;
}
static void border_get_border_gcs(
draw_border_gcs *ret_gcs, common_decorations_type *cd, FvwmWindow *fw,
Bool do_hilight)
{
static GC transparent_gc = None;
DecorFaceStyle *borderstyle;
Bool is_reversed = False;
if (transparent_gc == None && !HAS_NO_BORDER(fw) && !HAS_MWM_BORDER(fw))
{
XGCValues xgcv;
xgcv.function = GXnoop;
xgcv.plane_mask = 0;
transparent_gc = fvwmlib_XCreateGC(
dpy, Scr.NoFocusWin, GCFunction | GCPlaneMask, &xgcv);
}
ret_gcs->transparent = transparent_gc;
/* get the border style bits */
borderstyle = (do_hilight) ?
&GetDecor(fw, BorderStyle.active.style) :
&GetDecor(fw, BorderStyle.inactive.style);
if (borderstyle->flags.button_relief == DFS_BUTTON_IS_SUNK)
{
is_reversed = True;
}
if (is_reversed)
{
ret_gcs->shadow = cd->relief_gc;
ret_gcs->relief = cd->shadow_gc;
}
else
{
ret_gcs->relief = cd->relief_gc;
ret_gcs->shadow = cd->shadow_gc;
}
return;
}
static void trim_border_layout(
FvwmWindow *fw, DecorFaceStyle *borderstyle,
border_relief_size_descr *ret_size_descr)
{
/* If the border is too thin to accomodate the standard look, we remove
* parts of the border so that at least one pixel of the original
* colour is visible. We make an exception for windows with a border
* width of 2, though. */
if ((!IS_SHADED(fw) || HAS_TITLE(fw)) && fw->boundary_width == 2)
{
ret_size_descr->trim--;
}
if (ret_size_descr->trim < 0)
{
ret_size_descr->trim = 0;
}
for ( ; ret_size_descr->trim > 0; ret_size_descr->trim--)
{
if (ret_size_descr->w_hiout > 1)
{
ret_size_descr->w_hiout--;
}
else if (ret_size_descr->w_shin > 0)
{
ret_size_descr->w_shin--;
}
else if (ret_size_descr->w_hiout > 0)
{
ret_size_descr->w_hiout--;
}
else if (ret_size_descr->w_trout > 0)
{
ret_size_descr->w_trout = 0;
ret_size_descr->w_trin = 0;
ret_size_descr->w_din = 0;
ret_size_descr->w_hiout = 1;
}
ret_size_descr->sum--;
}
ret_size_descr->w_c = fw->boundary_width - ret_size_descr->sum;
return;
}
static void check_remove_inset(
DecorFaceStyle *borderstyle, border_relief_size_descr *ret_size_descr)
{
if (!DFS_HAS_NO_INSET(*borderstyle))
{
return;
}
ret_size_descr->w_shin = 0;
ret_size_descr->sum--;
ret_size_descr->trim--;
if (ret_size_descr->w_trin)
{
ret_size_descr->w_trout = 0;
ret_size_descr->w_trin = 0;
ret_size_descr->w_din = 0;
ret_size_descr->w_hiout = 1;
ret_size_descr->sum -= 2;
ret_size_descr->trim -= 2;
}
return;
}
static void border_fetch_mwm_layout(
FvwmWindow *fw, DecorFaceStyle *borderstyle,
border_relief_size_descr *ret_size_descr)
{
/* MWM borders look like this:
*
* HHCCCCS from outside to inside on the left and top border
* SSCCCCH from outside to inside on the bottom and right border
* |||||||
* |||||||__ w_shin (inner shadow area)
* ||||||___ w_c (transparent area)
* |||||____ w_c (transparent area)
* ||||_____ w_c (transparent area)
* |||______ w_c (transparent area)
* ||_______ w_hiout (outer hilight area)
* |________ w_hiout (outer hilight area)
*
*
* C = original colour
* H = hilight
* S = shadow
*/
ret_size_descr->w_dout = 0;
ret_size_descr->w_hiout = 2;
ret_size_descr->w_trout = 0;
ret_size_descr->w_trin = 0;
ret_size_descr->w_shin = 1;
ret_size_descr->w_din = 0;
ret_size_descr->sum = 3;
ret_size_descr->trim = ret_size_descr->sum - fw->boundary_width + 1;
check_remove_inset(borderstyle, ret_size_descr);
trim_border_layout(fw, borderstyle, ret_size_descr);
return;
}
static void border_fetch_fvwm_layout(
FvwmWindow *fw, DecorFaceStyle *borderstyle,
border_relief_size_descr *ret_size_descr)
{
/* Fvwm borders look like this:
*
* SHHCCSS from outside to inside on the left and top border
* SSCCHHS from outside to inside on the bottom and right border
* |||||||
* |||||||__ w_din (inner dark area)
* ||||||___ w_shin (inner shadow area)
* |||||____ w_trin (inner transparent/shadow area)
* ||||_____ w_c (transparent area)
* |||______ w_trout (outer transparent/hilight area)
* ||_______ w_hiout (outer hilight area)
* |________ w_dout (outer dark area)
*
* C = original colour
* H = hilight
* S = shadow
*
* reduced to 5 pixels it looks like this:
*
* SHHCS
* SSCHS
* |||||
* |||||__ w_din (inner dark area)
* ||||___ w_trin (inner transparent/shadow area)
* |||____ w_trout (outer transparent/hilight area)
* ||_____ w_hiout (outer hilight area)
* |______ w_dout (outer dark area)
*/
ret_size_descr->w_dout = 1;
ret_size_descr->w_hiout = 1;
ret_size_descr->w_trout = 1;
ret_size_descr->w_trin = 1;
ret_size_descr->w_shin = 1;
ret_size_descr->w_din = 1;
/* w_trout + w_trin counts only as one pixel of border because
* they let one pixel of the original colour shine through. */
ret_size_descr->sum = 6;
ret_size_descr->trim = ret_size_descr->sum - fw->boundary_width;
check_remove_inset(borderstyle, ret_size_descr);
trim_border_layout(fw, borderstyle, ret_size_descr);
return;
}
static void border_get_border_relief_size_descr(
border_relief_size_descr *ret_size_descr, FvwmWindow *fw,
Bool do_hilight)
{
DecorFaceStyle *borderstyle;
if (is_window_border_minimal(fw))
{
/* the border is too small, only a background but no relief */
ret_size_descr->is_flat = 1;
return;
}
borderstyle = (do_hilight) ?
&GetDecor(fw, BorderStyle.active.style) :
&GetDecor(fw, BorderStyle.inactive.style);
if (borderstyle->flags.button_relief == DFS_BUTTON_IS_FLAT)
{
ret_size_descr->is_flat = 1;
return;
}
ret_size_descr->is_flat = 0;
/* get the relief layout */
if (HAS_MWM_BORDER(fw))
{
border_fetch_mwm_layout(fw, borderstyle, ret_size_descr);
}
else
{
border_fetch_fvwm_layout(fw, borderstyle, ret_size_descr);
}
return;
}
static void border_get_border_marks_descr(
common_decorations_type *cd, border_relief_descr *br, FvwmWindow *fw)
{
int inset;
/* get mark's length and thickness */
inset = (br->relief.w_shin != 0 || br->relief.w_din != 0);
br->marks.length = fw->boundary_width - br->relief.w_dout - inset;
if (br->marks.length <= 0)
{
br->marks.has_x_marks = 0;
br->marks.has_y_marks = 0;
return;
}
br->marks.thickness = cd->relief_width;
if (br->marks.thickness > br->marks.length)
{
br->marks.thickness = br->marks.length;
}
/* get offsets from outer side of window */
br->marks.offset_tl = br->relief.w_dout;
br->marks.offset_br =
-br->relief.w_dout - br->marks.length - br->marks.offset_tl;
return;
}
static Pixmap border_create_decor_pixmap(
common_decorations_type *cd, rectangle *decor_g)
{
Pixmap p;
p = XCreatePixmap(
dpy, Scr.Root, decor_g->width, decor_g->height, Pdepth);
return p;
}
static void border_draw_part_relief(
border_relief_descr *br, rectangle *frame_g, rectangle *part_g,
Pixmap dest_pix, Bool is_inverted)
{
int i;
int off_x = 0;
int off_y = 0;
int width = frame_g->width - 1;
int height = frame_g->height - 1;
int w[7];
GC gc[4];
w[0] = br->relief.w_dout;
w[1] = br->relief.w_hiout;
w[2] = br->relief.w_trout;
w[3] = br->relief.w_c;
w[4] = br->relief.w_trin;
w[5] = br->relief.w_shin;
w[6] = br->relief.w_din;
gc[(is_inverted == True)] = br->gcs.relief;
gc[!(is_inverted == True)] = br->gcs.shadow;
gc[2] = br->gcs.transparent;
gc[3] = br->gcs.shadow;
off_x = -part_g->x;
off_y = -part_g->y;
width = frame_g->width - 1;
height = frame_g->height - 1;
for (i = 0; i < 7; i++)
{
if (ulgc[i] != 0x7f && w[i] > 0)
{
do_relieve_rectangle(
dpy, dest_pix, off_x, off_y,
width, height, gc[(int)ulgc[i]],
gc[(int)brgc[i]], w[i], False);
}
off_x += w[i];
off_y += w[i];
width -= 2 * w[i];
height -= 2 * w[i];
}
return;
}
static void border_draw_x_mark(
border_relief_descr *br, int x, int y, Pixmap dest_pix,
Bool do_draw_shadow)
{
int k;
int length;
GC gc;
if (br->marks.has_x_marks == 0)
{
return;
}
x += br->marks.offset_tl;
gc = (do_draw_shadow) ? br->gcs.shadow : br->gcs.relief;
/* draw it */
for (k = 0, length = br->marks.length - 1; k < br->marks.thickness;
k++, length--)
{
int x1;
int x2;
int y1;
int y2;
if (length < 0)
{
break;
}
if (do_draw_shadow)
{
x1 = x + k;
y1 = y - 1 - k;
}
else
{
x1 = x;
y1 = y + k;
}
x2 = x1 + length;
y2 = y1;
XDrawLine(dpy, dest_pix, gc, x1, y1, x2, y2);
}
return;
}
static void border_draw_y_mark(
border_relief_descr *br, int x, int y, Pixmap dest_pix,
Bool do_draw_shadow)
{
int k;
int length;
GC gc;
if (br->marks.has_y_marks == 0)
{
return;
}
y += br->marks.offset_tl;
gc = (do_draw_shadow) ? br->gcs.shadow : br->gcs.relief;
/* draw it */
for (k = 0, length = br->marks.length; k < br->marks.thickness;
k++, length--)
{
int x1;
int x2;
int y1;
int y2;
if (length <= 0)
{
break;
}
if (do_draw_shadow)
{
x1 = x - 1 - k;
y1 = y + k;
}
else
{
x1 = x + k;
y1 = y;
}
x2 = x1;
y2 = y1 + length - 1;
XDrawLine(dpy, dest_pix, gc, x1, y1, x2, y2);
}
return;
}
static void border_draw_part_marks(
border_relief_descr *br, rectangle *part_g, window_parts part,
Pixmap dest_pix)
{
int l;
int t;
int w;
int h;
int o;
l = br->sidebar_g.x;
t = br->sidebar_g.y;
w = part_g->width;
h = part_g->height;
o = br->marks.offset_br;
switch (part)
{
case PART_BORDER_N:
border_draw_y_mark(br, 0, 0, dest_pix, False);
border_draw_y_mark(br, w, 0, dest_pix, True);
break;
case PART_BORDER_S:
border_draw_y_mark(br, 0, h + o, dest_pix, False);
border_draw_y_mark(br, w, h + o, dest_pix, True);
break;
case PART_BORDER_E:
border_draw_x_mark(br, w + o, 0, dest_pix, False);
border_draw_x_mark(br, w + o, h, dest_pix, True);
break;
case PART_BORDER_W:
border_draw_x_mark(br, 0, 0, dest_pix, False);
border_draw_x_mark(br, 0, h, dest_pix, True);
break;
case PART_BORDER_NW:
border_draw_x_mark(br, 0, t, dest_pix, True);
border_draw_y_mark(br, l, 0, dest_pix, True);
break;
case PART_BORDER_NE:
border_draw_x_mark(br, l + o, t, dest_pix, True);
border_draw_y_mark(br, 0, 0, dest_pix, False);
break;
case PART_BORDER_SW:
border_draw_x_mark(br, 0, 0, dest_pix, False);
border_draw_y_mark(br, l, t + o, dest_pix, True);
break;
case PART_BORDER_SE:
border_draw_x_mark(br, l + o, 0, dest_pix, False);
border_draw_y_mark(br, 0, t + o, dest_pix, False);
break;
default:
return;
}
return;
}
inline static void border_set_part_background(
Window w, Pixmap pix)
{
XSetWindowAttributes xswa;
xswa.background_pixmap = pix;
XChangeWindowAttributes(dpy, w, CWBackPixmap, &xswa);
return;
}
/* render the an image into the pixmap */
static void border_fill_pixmap_background(
Pixmap dest_pix, rectangle *dest_g, pixmap_background_type *bg,
common_decorations_type *cd)
{
Bool do_tile;
Bool do_stretch;
XGCValues xgcv;
unsigned long valuemask;
Pixmap p = None, shape = None, alpha = None;
int src_width, src_height;
do_tile = (bg->flags.use_pixmap && bg->pixmap.flags.is_tiled) ?
True : False;
do_stretch = (bg->flags.use_pixmap && bg->pixmap.flags.is_stretched) ?
True : False;
xgcv.fill_style = FillSolid;
valuemask = GCFillStyle;
if (!bg->flags.use_pixmap)
{
/* solid pixel */
xgcv.foreground = bg->pixel;
xgcv.clip_x_origin = 0;
xgcv.clip_y_origin = 0;
xgcv.clip_mask = None;
valuemask |= GCForeground | GCClipMask | GCClipXOrigin |
GCClipYOrigin;
XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv);
XFillRectangle(
dpy, dest_pix, Scr.BordersGC, dest_g->x, dest_g->y,
dest_g->width - dest_g->x, dest_g->height - dest_g->y);
return;
}
if (do_stretch)
{
if (bg->pixmap.p)
{
p = CreateStretchPixmap(
dpy, bg->pixmap.p,
bg->pixmap.g.width, bg->pixmap.g.height,
bg->pixmap.depth,
bg->pixmap.stretch_w, bg->pixmap.stretch_h,
(bg->pixmap.depth == 1)?
Scr.MonoGC:Scr.BordersGC);
}
if (bg->pixmap.shape)
{
shape = CreateStretchPixmap(
dpy, bg->pixmap.shape,
bg->pixmap.g.width, bg->pixmap.g.height, 1,
bg->pixmap.stretch_w, bg->pixmap.stretch_h,
Scr.MonoGC);
}
if (bg->pixmap.alpha)
{
alpha = CreateStretchPixmap(
dpy, bg->pixmap.alpha,
bg->pixmap.g.width, bg->pixmap.g.height,
FRenderGetAlphaDepth(),
bg->pixmap.stretch_w, bg->pixmap.stretch_h,
Scr.AlphaGC);
}
src_width = bg->pixmap.stretch_w;
src_height = bg->pixmap.stretch_h;
}
else
{
p = bg->pixmap.p;
shape = bg->pixmap.shape;
alpha = bg->pixmap.alpha;
src_width = bg->pixmap.g.width;
src_height = bg->pixmap.g.height;
}
if (do_tile == False)
{
/* pixmap, offset stored in dest_g->x/y */
xgcv.foreground = cd->fore_color;
xgcv.background = cd->back_color;
valuemask |= GCForeground|GCBackground;
XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv);
PGraphicsRenderPixmaps(
dpy, Scr.NoFocusWin, p, shape, alpha,
bg->pixmap.depth, &(bg->pixmap.fra),
dest_pix, Scr.BordersGC, Scr.MonoGC, Scr.AlphaGC,
bg->pixmap.g.x, bg->pixmap.g.y,
src_width, src_height,
dest_g->x, dest_g->y, dest_g->width - dest_g->x,
dest_g->height - dest_g->y, False);
}
else
{
/* tiled pixmap */
xgcv.foreground = cd->fore_color;
xgcv.background = cd->back_color;
valuemask |= GCForeground|GCBackground;
XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv);
PGraphicsRenderPixmaps(
dpy, Scr.NoFocusWin, p, shape, alpha,
bg->pixmap.depth, &(bg->pixmap.fra),
dest_pix, Scr.BordersGC, Scr.MonoGC, Scr.AlphaGC,
bg->pixmap.g.x, bg->pixmap.g.y,
src_width, src_height,
dest_g->x, dest_g->y,
dest_g->width - dest_g->x,
dest_g->height - dest_g->y, True);
}
if (p && p != bg->pixmap.p)
{
XFreePixmap(dpy, p);
}
if (shape && shape != bg->pixmap.shape)
{
XFreePixmap(dpy, shape);
}
if (alpha && alpha != bg->pixmap.alpha)
{
XFreePixmap(dpy, alpha);
}
return;
}
/* create a root transparent colorset bg, we take in account a possible
* drawing rotation */
static Pixmap border_create_root_transparent_pixmap(
titlebar_descr *td, Window w, int width, int height, int cs)
{
int my_w, my_h;
Pixmap p;
if (!CSET_IS_TRANSPARENT_ROOT(cs))
{
return None;
}
if (td->td_is_rotated &&
(td->draw_rotation == ROTATION_90 ||
td->draw_rotation == ROTATION_270))
{
my_h = width;
my_w = height;
}
else
{
my_w = width;
my_h = height;
}
p = CreateBackgroundPixmap(
dpy, w, my_w, my_h, &Colorset[cs],
Pdepth, Scr.BordersGC, False);
if (p && td->td_is_rotated)
{
Pixmap tmp;
tmp = CreateRotatedPixmap(
dpy, p, my_w, my_h, Pdepth, Scr.BordersGC,
td->restore_rotation);
XFreePixmap(dpy, p);
p = tmp;
}
return p;
}
static void border_get_frame_pixmap(
common_decorations_type *cd, rectangle *frame_g)
{
dynamic_common_decorations *dcd = &(cd->dynamic_cd);
if (dcd->frame_pixmap != None)
{
/* should not happen */
fprintf(stderr, "Bad use of border_get_frame_pixmap!!\n");
dcd->frame_pixmap = None;
}
if (cd->bg_border_cs < 0 || CSET_IS_TRANSPARENT(cd->bg_border_cs))
{
/* should not happen */
}
else
{
dcd->frame_pixmap = CreateBackgroundPixmap(
dpy, Scr.NoFocusWin, frame_g->width, frame_g->height,
&Colorset[cd->bg_border_cs], Pdepth, Scr.BordersGC,
False);
}
return;
}
static void border_get_border_background(
pixmap_background_type *bg, common_decorations_type *cd,
rectangle *part_g, rectangle *relative_g, int *free_bg_pixmap, Window w)
{
*free_bg_pixmap = False;
if (cd->texture_pixmap)
{
bg->flags.use_pixmap = 1;
bg->pixmap.p = cd->texture_pixmap;
bg->pixmap.g.width = cd->texture_pixmap_width;
bg->pixmap.g.height = cd->texture_pixmap_height;
bg->pixmap.shape = None;
bg->pixmap.alpha = None;
bg->pixmap.depth = Pdepth;
bg->pixmap.flags.is_tiled = 1;
bg->pixmap.flags.is_stretched = 0;
bg->pixmap.fra.mask = 0;
}
else if (cd->bg_border_cs >= 0 &&
!CSET_IS_TRANSPARENT_PR(cd->bg_border_cs))
{
colorset_t *cs_t = &Colorset[cd->bg_border_cs];
XGCValues xgcv;
if (CSET_IS_TRANSPARENT_ROOT(cd->bg_border_cs))
{
bg->pixmap.p = CreateBackgroundPixmap(
dpy, w, part_g->width, part_g->height, cs_t,
Pdepth, Scr.BordersGC, False);
}
else
{
/* FIXME */
if (cd->dynamic_cd.frame_pixmap == None)
{
border_get_frame_pixmap(cd, relative_g);
}
bg->pixmap.p = XCreatePixmap(
dpy, cd->dynamic_cd.frame_pixmap, part_g->width,
part_g->height, Pdepth);
xgcv.fill_style = FillTiled;
xgcv.tile = cd->dynamic_cd.frame_pixmap;
xgcv.ts_x_origin = - relative_g->x;
xgcv.ts_y_origin = - relative_g->y;
XChangeGC(
dpy, Scr.BordersGC, GCTile | GCTileStipXOrigin |
GCTileStipYOrigin | GCFillStyle, &xgcv);
XFillRectangle(
dpy, bg->pixmap.p, Scr.BordersGC, 0, 0,
part_g->width, part_g->height);
xgcv.fill_style = FillSolid;
XChangeGC(dpy, Scr.BordersGC, GCFillStyle, &xgcv);
}
bg->pixmap.g.width = part_g->width;
bg->pixmap.g.height = part_g->height;
bg->flags.use_pixmap = 1;
bg->pixmap.shape = None;
bg->pixmap.alpha = None;
bg->pixmap.depth = Pdepth;
bg->pixmap.flags.is_tiled = 1;
bg->pixmap.flags.is_stretched = 0;
bg->pixmap.fra.mask = 0;
*free_bg_pixmap = True;
}
else
{
bg->flags.use_pixmap = 0;
bg->pixel = cd->attributes.background_pixel;
}
return;
}
static void border_draw_one_border_part(
common_decorations_type *cd, FvwmWindow *fw, rectangle *sidebar_g,
rectangle *frame_g, border_relief_descr *br, window_parts part,
window_parts draw_handles, Bool is_inverted, Bool do_clear)
{
pixmap_background_type bg;
rectangle part_g;
rectangle pix_g;
rectangle relative_g;
Pixmap p;
Window w;
Bool free_bg_pixmap = False;
/* make a pixmap */
border_get_part_geometry(fw, part, sidebar_g, &part_g, &w);
if (part_g.width <= 0 || part_g.height <= 0)
{
return;
}
p = border_create_decor_pixmap(cd, &part_g);
/* set the background tile */
relative_g.width = fw->g.frame.width;
relative_g.height = fw->g.frame.height;
relative_g.x = part_g.x;
relative_g.y = part_g.y;
border_get_border_background(
&bg, cd, &part_g, &relative_g, &free_bg_pixmap, w);
if (cd->texture_pixmap)
{
switch (part)
{
case PART_BORDER_E:
bg.pixmap.g.x = frame_g->width - fw->boundary_width;
break;
case PART_BORDER_NE:
case PART_BORDER_SE:
bg.pixmap.g.x = frame_g->width - fw->corner_width;
break;
case PART_BORDER_N:
case PART_BORDER_S:
bg.pixmap.g.x = fw->corner_width;
break;
default:
bg.pixmap.g.x = 0;
break;
}
switch (part)
{
case PART_BORDER_S:
bg.pixmap.g.y = frame_g->height - fw->boundary_width;
break;
case PART_BORDER_SW:
case PART_BORDER_SE:
bg.pixmap.g.y = frame_g->height - fw->corner_width;
break;
case PART_BORDER_W:
case PART_BORDER_E:
bg.pixmap.g.y = fw->corner_width;
break;
default:
bg.pixmap.g.y = 0;
break;
}
}
else
{
bg.pixmap.g.x = 0;
bg.pixmap.g.y = 0;
}
/* set the geometry for drawing the Tiled pixmap; maybe add the relief
* as offset? */
pix_g.x = 0;
pix_g.y = 0;
pix_g.width = part_g.width;
pix_g.height = part_g.height;
border_fill_pixmap_background(p, &pix_g, &bg, cd);
if (free_bg_pixmap && bg.pixmap.p)
{
XFreePixmap(dpy, bg.pixmap.p);
}
/* draw the relief over the background */
if (!br->relief.is_flat)
{
border_draw_part_relief(br, frame_g, &part_g, p, is_inverted);
/* draw the handle marks */
if (br->marks.has_x_marks || br->marks.has_y_marks)
{
border_draw_part_marks(br, &part_g, part, p);
}
}
/* apply the pixmap and destroy it */
border_set_part_background(w, p);
if (do_clear == True)
{
XClearWindow(dpy,w);
}
XFreePixmap(dpy, p);
return;
}
static void border_draw_all_border_parts(
common_decorations_type *cd, FvwmWindow *fw, border_relief_descr *br,
rectangle *frame_g, window_parts draw_parts,
window_parts pressed_parts, Bool do_hilight, Bool do_clear)
{
window_parts part;
window_parts draw_handles;
/* get the description of the drawing directives */
border_get_border_relief_size_descr(&br->relief, fw, do_hilight);
border_get_border_marks_descr(cd, br, fw);
/* fetch the gcs used to draw the border */
border_get_border_gcs(&br->gcs, cd, fw, do_hilight);
/* draw everything in a big loop */
draw_parts &= (PART_FRAME | PART_HANDLES);
draw_handles = (draw_parts & PART_HANDLES);
for (part = PART_BORDER_N; (part & PART_FRAME); part <<= 1)
{
if (part & draw_parts)
{
border_draw_one_border_part(
cd, fw, &br->sidebar_g, frame_g, br, part,
draw_handles,
(pressed_parts & part) ? True : False,
do_clear);
}
}
return;
}
/*
*
* Draws a little pattern within a window (more complex)
*
*/
static void border_draw_vector_to_pixmap(
Pixmap dest_pix, common_decorations_type *cd, int is_toggled,
struct vector_coords *coords, rectangle *pixmap_g)
{
GC gcs[4];
int i;
if (coords->use_fgbg == 1)
{
Globalgcv.foreground = cd->fore_color;
Globalgcm = GCForeground;
XChangeGC(dpy, Scr.ScratchGC3, Globalgcm, &Globalgcv);
Globalgcv.foreground = cd->back_color;
XChangeGC(dpy, Scr.ScratchGC4, Globalgcm, &Globalgcv);
gcs[3] = Scr.ScratchGC3; /* @3 is fg */
gcs[2] = Scr.ScratchGC4; /* @2 is bg */
}
if (is_toggled)
{
gcs[0] = cd->relief_gc;
gcs[1] = cd->shadow_gc;
}
else
{
gcs[0] = cd->shadow_gc;
gcs[1] = cd->relief_gc;
}
for (i = 1; i < coords->num; i++)
{
if (coords->c[i] < 0 || coords->c[i] >= 4)
{
/* don't draw a line */
continue;
}
XDrawLine(
dpy, dest_pix, gcs[coords->c[i]],
pixmap_g->width * coords->x[i-1] / 100 +
coords->xoff[i-1],
pixmap_g->height * coords->y[i-1] / 100 +
coords->yoff[i-1],
pixmap_g->width * coords->x[i] / 100 +
coords->xoff[i],
pixmap_g->height * coords->y[i] / 100 +
coords->yoff[i]);
}
return;
}
/*
*
* Handle Title pixmaps used for UseTitleStyle
*
*/
static void border_setup_bar_pixmaps(
titlebar_descr *td, dynamic_common_decorations *dcd, DecorFace *df,
ButtonState bs)
{
int count = dcd->bar_pixmaps[bs].count;
DecorFace *tsdf;
int i, j, mp_part_left, mp_part_right;
if (count != 0)
{
/* ok */
return;
}
for (tsdf = df; tsdf != NULL; tsdf = tsdf->next)
{
if (DFS_FACE_TYPE(tsdf->style) == ColorsetButton)
{
count++;
}
else if (DFS_FACE_TYPE(tsdf->style) == MultiPixmap)
{
border_mp_get_use_title_style_parts_and_geometry(
td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs,
tsdf->u.mp.solid_flags, True, NULL,
&mp_part_left);
border_mp_get_use_title_style_parts_and_geometry(
td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs,
tsdf->u.mp.solid_flags, False, NULL,
&mp_part_right);
for (j = 0; j < UTS_TBMP_NUM_PIXMAPS; j++)
{
if (j != mp_part_left && j != mp_part_right)
{
continue;
}
if (tsdf->u.mp.acs[j].cs >= 0 ||
tsdf->u.mp.pixmaps[j])
{
count++;
}
}
}
}
if (count == 0)
{
dcd->bar_pixmaps[bs].count = -1;
return;
}
else
{
dcd->bar_pixmaps[bs].bps =
(bar_pixmap *)safemalloc(count*sizeof(bar_pixmap));
}
dcd->bar_pixmaps[bs].count = count;
i = 0;
for (tsdf = df; tsdf != NULL; tsdf = tsdf->next)
{
if (DFS_FACE_TYPE(tsdf->style) == ColorsetButton)
{
dcd->bar_pixmaps[bs].bps[i].p = None;
dcd->bar_pixmaps[bs].bps[i].mp_created_pic = NULL;
dcd->bar_pixmaps[bs].bps[i].cs = tsdf->u.acs.cs;
dcd->bar_pixmaps[bs].bps[i].mp_pic = NULL;
dcd->bar_pixmaps[bs].bps[i].created = 0;
dcd->bar_pixmaps[bs].bps[i].mp_part = TBMP_NONE;
i++;
}
else if (DFS_FACE_TYPE(tsdf->style) == MultiPixmap)
{
border_mp_get_use_title_style_parts_and_geometry(
td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs,
tsdf->u.mp.solid_flags, True, NULL,
&mp_part_left);
border_mp_get_use_title_style_parts_and_geometry(
td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs,
tsdf->u.mp.solid_flags, False, NULL,
&mp_part_right);
for (j = 0; j < UTS_TBMP_NUM_PIXMAPS; j++)
{
if (j != mp_part_left && j != mp_part_right)
{
continue;
}
if (tsdf->u.mp.acs[j].cs >= 0 ||
tsdf->u.mp.pixmaps[j])
{
dcd->bar_pixmaps[bs].bps[i].p = None;
dcd->bar_pixmaps[bs].bps[i].
mp_created_pic = NULL;
dcd->bar_pixmaps[bs].bps[i].cs =
tsdf->u.mp.acs[j].cs;
dcd->bar_pixmaps[bs].bps[i].mp_pic =
tsdf->u.mp.pixmaps[j];
dcd->bar_pixmaps[bs].bps[i].created = 0;
dcd->bar_pixmaps[bs].bps[i].mp_part = j;
i++;
}
}
}
}
}
static Pixmap border_get_bar_pixmaps(
dynamic_common_decorations *dcd, rectangle *bar_g, ButtonState bs,
int cset, FvwmPicture *mp_pic, int mp_part, int stretch,
FvwmPicture **mp_ret_pic)
{
ButtonState b;
int i,j;
int count = dcd->bar_pixmaps[bs].count;
if (count <= 0)
{
return None;
}
i = 0;
while(i < count &&
(dcd->bar_pixmaps[bs].bps[i].cs != cset ||
dcd->bar_pixmaps[bs].bps[i].mp_part != mp_part ||
dcd->bar_pixmaps[bs].bps[i].mp_pic != mp_pic))
{
i++;
}
if (i == count)
{
return None;
}
if (mp_ret_pic)
{
*mp_ret_pic = dcd->bar_pixmaps[bs].bps[i].mp_created_pic;
}
if (dcd->bar_pixmaps[bs].bps[i].p == None)
{
/* see if we have it */
b = 0;
while (b < BS_MaxButtonState)
{
int c = dcd->bar_pixmaps[b].count;
j = 0;
while(j < c &&
(dcd->bar_pixmaps[b].bps[j].cs != cset ||
dcd->bar_pixmaps[b].bps[j].mp_part != mp_part ||
dcd->bar_pixmaps[b].bps[j].mp_pic != mp_pic))
{
j++;
}
if (j < c && dcd->bar_pixmaps[b].bps[j].p)
{
dcd->bar_pixmaps[bs].bps[i].p =
dcd->bar_pixmaps[b].bps[j].p;
if (mp_pic && mp_ret_pic)
{
*mp_ret_pic =
dcd->bar_pixmaps[bs].bps[i].
mp_created_pic =
dcd->bar_pixmaps[b].bps[j].
mp_created_pic;
}
break;
}
b++;
}
}
if (dcd->bar_pixmaps[bs].bps[i].p == None)
{
if (cset >= 0)
{
dcd->bar_pixmaps[bs].bps[i].p = CreateBackgroundPixmap(
dpy, Scr.NoFocusWin, bar_g->width, bar_g->height,
&Colorset[cset], Pdepth, Scr.BordersGC, False);
dcd->bar_pixmaps[bs].bps[i].created = True;
}
else if (mp_pic && mp_ret_pic)
{
if (stretch)
{
dcd->bar_pixmaps[bs].bps[i].mp_created_pic =
PGraphicsCreateStretchPicture(
dpy, Scr.NoFocusWin, mp_pic,
bar_g->width, bar_g->height,
Scr.BordersGC, Scr.MonoGC,
Scr.AlphaGC);
}
else
{
dcd->bar_pixmaps[bs].bps[i].mp_created_pic =
PGraphicsCreateTiledPicture(
dpy, Scr.NoFocusWin, mp_pic,
bar_g->width, bar_g->height,
Scr.BordersGC, Scr.MonoGC,
Scr.AlphaGC);
}
if (dcd->bar_pixmaps[bs].bps[i].mp_created_pic)
{
dcd->bar_pixmaps[bs].bps[i].created = True;
*mp_ret_pic =
dcd->bar_pixmaps[bs].bps[i].
mp_created_pic;
dcd->bar_pixmaps[bs].bps[i].p =
dcd->bar_pixmaps[bs].bps[i].
mp_created_pic->picture;
}
}
}
return dcd->bar_pixmaps[bs].bps[i].p;
}
static void border_free_bar_pixmaps(
dynamic_common_decorations *dcd)
{
ButtonState bs;
int i;
for (bs = 0; bs < BS_MaxButtonState; bs++)
{
if (dcd->bar_pixmaps[bs].count < 1)
{
continue;
}
for (i = 0; i < dcd->bar_pixmaps[bs].count; i++)
{
if (dcd->bar_pixmaps[bs].bps[i].mp_created_pic &&
dcd->bar_pixmaps[bs].bps[i].created)
{
PDestroyFvwmPicture(
dpy,
dcd->bar_pixmaps[bs].bps[i].
mp_created_pic);
}
else if (dcd->bar_pixmaps[bs].bps[i].p != None &&
dcd->bar_pixmaps[bs].bps[i].created)
{
XFreePixmap(
dpy, dcd->bar_pixmaps[bs].bps[i].p);
}
}
free(dcd->bar_pixmaps[bs].bps);
}
}
/*
*
* MultiPixmap (aka, fancy title bar) (tril@igs.net)
*
*/
#define TBMP_HAS_PART(p, pm, acs, sf) \
(pm[p] || acs[p].cs >= 0 || (sf & (1 << p)))
/* Tile or stretch src into dest, starting at the given location and
* continuing for the given width and height. This is a utility function used
* by border_mp_draw_mp_titlebar. (tril@igs.net) */
static void border_mp_render_into_pixmap(
titlebar_descr *td, common_decorations_type *cd, FvwmPicture **src,
FvwmAcs *acs, Pixel *pixels, unsigned short solid_flags,
unsigned short stretch_flags, int part, Pixmap dest, Window w,
rectangle *full_g, rectangle *title_g, ButtonState bs, rectangle *g)
{
int x = 0;
int y = 0;
pixmap_background_type bg;
rectangle dest_g;
dynamic_common_decorations *dcd;
dcd = &cd->dynamic_cd;
/* setup some default */
bg.pixmap.fra.mask = 0;
bg.pixmap.flags.is_stretched = 0;
bg.pixmap.flags.is_tiled = 0;
bg.flags.use_pixmap = 1;
bg.pixmap.p = bg.pixmap.alpha = bg.pixmap.shape = None;
bg.pixmap.g.x = 0;
bg.pixmap.g.y = 0;
dest_g.width = g->width + g->x;
dest_g.height = g->height + g->y;
dest_g.x = g->x;
dest_g.y = g->y;
if (solid_flags & (1 << part))
{
bg.flags.use_pixmap = 0;
bg.pixel = pixels[part];
border_fill_pixmap_background(dest, &dest_g, &bg, cd);
return;
}
else if (acs[part].cs >= 0)
{
Pixmap p = None;
bg.pixmap.fra.mask = FRAM_HAVE_ADDED_ALPHA;
bg.pixmap.fra.added_alpha_percent = acs[part].alpha_percent;
if (CSET_IS_TRANSPARENT_PR(acs[part].cs))
{
return;
}
if (CSET_IS_TRANSPARENT_ROOT(acs[part].cs))
{
p = border_create_root_transparent_pixmap(
td, w, g->width + g->x, g->height + g->y,
acs[part].cs);
bg.pixmap.p = p;
bg.pixmap.depth = Pdepth;
bg.pixmap.g.width = g->width;
bg.pixmap.g.height = g->height;
bg.pixmap.g.x = g->x;
bg.pixmap.g.y = g->y;
}
else if (full_g != NULL)
{
bg.pixmap.p = border_get_bar_pixmaps(
dcd, full_g, bs, acs[part].cs, NULL, part,
(stretch_flags & (1 << part)), NULL);
if (bg.pixmap.p)
{
if (part != TBMP_RIGHT_MAIN)
{
/* left buttons offset */
x = title_g->x - full_g->x;
y = title_g->y - full_g->y;
}
bg.pixmap.g.width = full_g->width;
bg.pixmap.g.height = full_g->height;
bg.pixmap.flags.is_tiled = 1;
bg.pixmap.g.x = x;
bg.pixmap.g.y = y;
bg.pixmap.depth = Pdepth;
}
}
if (!bg.pixmap.p)
{
int bg_w, bg_h;
p = CreateBackgroundPixmap(
dpy, w, g->width, g->height,
&Colorset[acs[part].cs], Pdepth, Scr.BordersGC,
False);
bg.pixmap.p = p;
GetWindowBackgroundPixmapSize(
&Colorset[acs[part].cs], g->width, g->height,
&bg_w, &bg_h);
bg.pixmap.g.width = bg_w;
bg.pixmap.g.height = bg_h;
bg.pixmap.depth = Pdepth;
bg.pixmap.flags.is_tiled = 1;
}
if (bg.pixmap.p)
{
border_fill_pixmap_background(dest, &dest_g, &bg, cd);
}
if (p)
{
XFreePixmap(dpy, p);
}
}
else if (src[part])
{
FvwmPicture *full_pic = NULL;
Pixmap p;
if (full_g != NULL)
{
p = border_get_bar_pixmaps(
dcd, full_g, bs, -1, src[part], part,
(stretch_flags & (1 << part)), &full_pic);
if (p && full_pic)
{
if (part != TBMP_RIGHT_MAIN)
{
/* left buttons offset */
x = title_g->x - full_g->x;
y = title_g->y - full_g->y;
}
bg.pixmap.p = full_pic->picture;
bg.pixmap.shape = full_pic->mask;
bg.pixmap.alpha = full_pic->alpha;
bg.pixmap.depth = full_pic->depth;
bg.pixmap.g.width = full_pic->width;
bg.pixmap.g.height = full_pic->height;
bg.pixmap.g.x = x;
bg.pixmap.g.y = y;
}
}
if (!bg.pixmap.p)
{
if (stretch_flags & (1 << part))
{
bg.pixmap.flags.is_stretched = 1;
}
else
{
bg.pixmap.flags.is_tiled = 1;
}
bg.pixmap.p = src[part]->picture;
bg.pixmap.shape = src[part]->mask;
bg.pixmap.alpha = src[part]->alpha;
bg.pixmap.depth = src[part]->depth;
bg.pixmap.g.width = src[part]->width;
bg.pixmap.g.height = src[part]->height;
bg.pixmap.stretch_w = dest_g.width - dest_g.x;
bg.pixmap.stretch_h = dest_g.height - dest_g.y;
}
if (bg.pixmap.p)
{
border_fill_pixmap_background(dest, &dest_g, &bg, cd);
}
}
return;
}
static int border_mp_get_length(
titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs,
unsigned int solid_flags, int part)
{
if (acs[part].cs >= 0 || (solid_flags & (1 << part)))
{
/* arbitrary */
if (td->has_vt)
{
return td->bar_g.width/2;
}
else
{
return td->bar_g.height/2;
}
}
if (pm[part] == NULL)
{
return 0;
}
else if (td->has_vt)
{
return pm[part]->height;
}
else
{
return pm[part]->width;
}
}
/* geometries relatively to the frame */
static void border_mp_get_titlebar_descr(
FvwmWindow *fw, titlebar_descr *td, DecorFace *df)
{
DecorFace *tsdf;
FvwmPicture **pm;
FvwmAcs *acs;
int add,tmpi;
int left_of_text = 0;
int right_of_text = 0;
int left_end = 0;
int right_end = 0;
int before_space, after_space, under_offset, under_width;
Bool has_mp = False;
JustificationType just;
unsigned short sf;
int is_start = 0;
just = TB_JUSTIFICATION(GetDecor(fw, titlebar));
/* first compute under text width */
if (td->length > 0)
{
under_width = td->length + 2*TBMP_TITLE_PADDING;
}
else
{
under_width = 0;
}
if (under_width > fw->title_length)
{
under_width = fw->title_length;
td->offset = (fw->title_length - td->length) / 2;
just = JUST_CENTER;
}
for (tsdf = df; tsdf != NULL; tsdf = tsdf->next)
{
if (tsdf->style.face_type != MultiPixmap)
{
continue;
}
has_mp = True;
acs = tsdf->u.mp.acs;
pm = tsdf->u.mp.pixmaps;
sf = tsdf->u.mp.solid_flags;
add = border_mp_get_length(
td, pm, acs, sf, TBMP_LEFT_OF_TEXT);
if (add > left_of_text &&
add + left_end + right_of_text + right_end + under_width +
2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length)
{
left_of_text = add;
}
add = border_mp_get_length(
td, pm, acs, sf, TBMP_RIGHT_OF_TEXT);
if (add > right_of_text &&
add + left_end + left_of_text + right_end + under_width +
2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length)
{
right_of_text = add;
}
add = border_mp_get_length(
td, pm, acs, sf, TBMP_LEFT_END);
if (add > left_end &&
add + right_of_text + left_of_text + right_end +
under_width + 2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length)
{
left_end = add;
}
add = border_mp_get_length(
td, pm, acs, sf, TBMP_RIGHT_END);
if (add > right_end &&
add + right_of_text + left_of_text + left_end +
under_width + 2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length)
{
right_end = add;
}
}
if (!has_mp)
{
return;
}
switch (just)
{
case JUST_LEFT:
is_start = 1;
/* fall through */
case JUST_RIGHT:
if (td->has_an_upsidedown_rotation)
{
is_start = !is_start;
}
if (is_start)
{
if (td->has_an_upsidedown_rotation)
{
td->offset = max(
td->offset, right_of_text + right_end +
TBMP_MIN_RL_TITLE_LENGTH +
TBMP_TITLE_PADDING);
}
else
{
td->offset = max(
td->offset, left_of_text + left_end +
TBMP_MIN_RL_TITLE_LENGTH +
TBMP_TITLE_PADDING);
}
}
else
{
if (td->has_an_upsidedown_rotation)
{
td->offset = min(
td->offset, fw->title_length -
(td->length + left_of_text +
left_end + TBMP_MIN_RL_TITLE_LENGTH +
TBMP_TITLE_PADDING));
}
else
{
td->offset = min(
td->offset, fw->title_length -
(td->length + right_of_text +
right_end + TBMP_MIN_RL_TITLE_LENGTH +
TBMP_TITLE_PADDING));
}
}
break;
case JUST_CENTER:
default:
break;
}
under_offset = td->offset - (under_width - td->length)/2;
before_space = under_offset;
if (td->has_vt)
{
after_space =
td->layout.title_g.height - before_space - under_width;
}
else
{
after_space =
td->layout.title_g.width - before_space - under_width;
}
if (td->has_an_upsidedown_rotation)
{
td->left_end_length = right_end;
td->left_of_text_length = right_of_text;
td->right_of_text_length = left_of_text;
td->right_end_length = left_end;
tmpi = before_space;
before_space = after_space;
after_space = tmpi;
}
else
{
td->left_end_length = left_end;
td->left_of_text_length = left_of_text;
td->right_of_text_length = right_of_text;
td->right_end_length = right_end;
}
if (td->has_vt)
{
td->under_text_g.width = td->bar_g.width;
td->under_text_g.height = under_width;
td->under_text_g.x = 0;
td->under_text_g.y = under_offset;
}
else
{
td->under_text_g.height = td->bar_g.height;
td->under_text_g.width = under_width;
td->under_text_g.x = under_offset;
td->under_text_g.y = 0;
}
/* width & height */
if (td->has_vt)
{
/* left */
td->full_left_main_g.width = td->bar_g.width;
td->full_left_main_g.height =
before_space + td->left_buttons_g.height;
td->left_main_g.width = td->bar_g.width;
td->left_main_g.height = before_space;
/* right */
td->full_right_main_g.width = td->bar_g.width;
td->full_right_main_g.height = after_space +
td->right_buttons_g.height;
td->right_main_g.width = td->bar_g.width;
td->right_main_g.height = after_space;
}
else
{
/* left */
td->full_left_main_g.height = td->bar_g.height;
td->full_left_main_g.width =
before_space + td->left_buttons_g.width;
td->left_main_g.height = td->bar_g.height;
td->left_main_g.width = before_space;
/* right */
td->full_right_main_g.height = td->bar_g.height;
td->full_right_main_g.width = after_space +
td->right_buttons_g.width;
td->right_main_g.height = td->bar_g.height;
td->right_main_g.width = after_space;
}
/* position */
if (td->has_an_upsidedown_rotation)
{
td->full_right_main_g.x = td->bar_g.x;
td->full_right_main_g.y = td->bar_g.y;
td->right_main_g.x = 0;
td->right_main_g.y = 0;
}
else
{
td->full_left_main_g.x = td->bar_g.x;
td->full_left_main_g.y = td->bar_g.y;
td->left_main_g.x = 0;
td->left_main_g.y = 0;
}
if (td->has_vt)
{
if (td->has_an_upsidedown_rotation)
{
td->full_left_main_g.x = td->bar_g.x;
td->full_left_main_g.y =
td->full_right_main_g.height + td->bar_g.y +
td->under_text_g.height;
td->left_main_g.y =
td->under_text_g.y + td->under_text_g.height;
td->left_main_g.x = 0;
}
else
{
td->full_right_main_g.x = td->bar_g.x;
td->full_right_main_g.y =
td->full_left_main_g.height + td->bar_g.y +
td->under_text_g.height;
td->right_main_g.y =
td->under_text_g.y + td->under_text_g.height;
td->right_main_g.x = 0;
}
}
else
{
if (td->has_an_upsidedown_rotation)
{
td->full_left_main_g.x =
td->full_right_main_g.width + td->bar_g.x +
td->under_text_g.width;
td->full_left_main_g.y = td->bar_g.y;
td->left_main_g.x =
td->under_text_g.x + td->under_text_g.width;
td->left_main_g.y = 0;
}
else
{
td->full_right_main_g.x =
td->full_left_main_g.width + td->bar_g.x +
td->under_text_g.width;
td->full_right_main_g.y = td->bar_g.y;
td->right_main_g.x =
td->under_text_g.x + td->under_text_g.width;
td->right_main_g.y = 0;
}
}
}
/* the returned geometries are relative to the titlebar (not the frame) */
static void border_mp_get_extreme_geometry(
titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs, unsigned short sf,
rectangle *left_of_text_g, rectangle *right_of_text_g,
rectangle *left_end_g, rectangle *right_end_g)
{
int left_of_text = 0;
int right_of_text = 0;
int left_end = 0;
int right_end = 0;
left_of_text = border_mp_get_length(
td, pm, acs, sf, TBMP_LEFT_OF_TEXT);
left_end = border_mp_get_length(
td, pm, acs, sf, TBMP_LEFT_END);
right_of_text = border_mp_get_length(
td, pm, acs, sf, TBMP_RIGHT_OF_TEXT);
right_end = border_mp_get_length(
td, pm, acs, sf, TBMP_RIGHT_END);
if (left_of_text > 0 && left_of_text <= td->left_of_text_length)
{
if (td->has_vt)
{
left_of_text_g->y = td->under_text_g.y - left_of_text;
left_of_text_g->x = 0;
left_of_text_g->height = left_of_text;
left_of_text_g->width = td->bar_g.width;
}
else
{
left_of_text_g->x = td->under_text_g.x - left_of_text;
left_of_text_g->y = 0;
left_of_text_g->width = left_of_text;
left_of_text_g->height = td->bar_g.height;
}
}
else
{
left_of_text_g->x = 0;
left_of_text_g->y = 0;
left_of_text_g->width = 0;
left_of_text_g->height = 0;
}
if (right_of_text > 0 && right_of_text <= td->right_of_text_length)
{
if (td->has_vt)
{
right_of_text_g->y =
td->under_text_g.y + td->under_text_g.height;
right_of_text_g->x = 0;
right_of_text_g->height = right_of_text;
right_of_text_g->width = td->bar_g.width;
}
else
{
right_of_text_g->x =
td->under_text_g.x + td->under_text_g.width;
right_of_text_g->y = 0;
right_of_text_g->width = right_of_text;
right_of_text_g->height = td->bar_g.height;
}
}
else
{
right_of_text_g->x = 0;
right_of_text_g->y = 0;
right_of_text_g->width = 0;
right_of_text_g->height = 0;
}
if (left_end > 0 && left_end <= td->left_end_length)
{
if (td->has_vt)
{
left_end_g->y = 0;
left_end_g->x = 0;
left_end_g->height = left_end;
left_end_g->width = td->bar_g.width;
}
else
{
left_end_g->x = 0;
left_end_g->y = 0;
left_end_g->width = left_end;
left_end_g->height = td->bar_g.height;
}
}
else
{
left_end_g->x = 0;
left_end_g->y = 0;
left_end_g->width = 0;
left_end_g->height = 0;
}
if (right_end > 0 && right_end <= td->right_end_length)
{
if (td->has_vt)
{
right_end_g->y =
td->layout.title_g.height - right_end;
right_end_g->x = 0;
right_end_g->height = right_end;
right_end_g->width = td->bar_g.width;
}
else
{
right_end_g->x =
td->layout.title_g.width - right_end;
right_end_g->y = 0;
right_end_g->width = right_end;
right_end_g->height = td->bar_g.height;
}
}
else
{
right_end_g->x = 0;
right_end_g->y = 0;
right_end_g->width = 0;
right_end_g->height = 0;
}
return;
}
static Bool border_mp_get_use_title_style_parts_and_geometry(
titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs,
unsigned short sf, int is_left, rectangle *g, int *part)
{
rectangle *tmp_g = NULL;
Bool g_ok = True;
if (is_left && TBMP_HAS_PART(TBMP_LEFT_BUTTONS, pm, acs, sf))
{
*part = TBMP_LEFT_BUTTONS;
tmp_g = &td->left_buttons_g;
}
else if (!is_left && TBMP_HAS_PART(TBMP_RIGHT_BUTTONS, pm, acs, sf))
{
*part = TBMP_RIGHT_BUTTONS;
tmp_g = &td->right_buttons_g;
}
else if (is_left && TBMP_HAS_PART(TBMP_LEFT_MAIN, pm, acs, sf))
{
*part = TBMP_LEFT_MAIN;
tmp_g = &td->full_left_main_g;
}
else if (!is_left && TBMP_HAS_PART(TBMP_RIGHT_MAIN, pm, acs, sf))
{
*part = TBMP_RIGHT_MAIN;
tmp_g = &td->full_right_main_g;
}
else if (TBMP_HAS_PART(TBMP_MAIN, pm, acs, sf))
{
*part = TBMP_MAIN;
tmp_g = &(td->bar_g);
}
else
{
*part = TBMP_NONE;
}
if (g && tmp_g)
{
g->x = tmp_g->x;
g->y = tmp_g->y;
g->width = tmp_g->width;
g->height = tmp_g->height;
g_ok = True;
}
return g_ok;
}
/* Redraws multi-pixmap titlebar (tril@igs.net) */
static void border_mp_draw_mp_titlebar(
FvwmWindow *fw, titlebar_descr *td, DecorFace *df, Pixmap dest_pix,
Window w)
{
FvwmPicture **pm;
FvwmAcs *acs;
Pixel *pixels;
unsigned short solid_flags;
unsigned short stretch_flags;
rectangle tmp_g, left_of_text_g,left_end_g,right_of_text_g,right_end_g;
dynamic_common_decorations *dcd;
ButtonState bs;
dcd = &(td->cd->dynamic_cd);
bs = td->tbstate.tstate;
pm = df->u.mp.pixmaps;
acs = df->u.mp.acs;
pixels = df->u.mp.pixels;
stretch_flags = df->u.mp.stretch_flags;
solid_flags = df->u.mp.solid_flags;
tmp_g.x = 0;
tmp_g.y = 0;
tmp_g.width = td->layout.title_g.width;
tmp_g.height = td->layout.title_g.height;
if (TBMP_HAS_PART(TBMP_MAIN, pm, acs, solid_flags))
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags, stretch_flags,
TBMP_MAIN, dest_pix, w, &td->bar_g, &td->layout.title_g,
bs, &tmp_g);
}
else if (td->length <= 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags, stretch_flags,
TBMP_LEFT_MAIN, dest_pix, w, NULL, &td->layout.title_g,
bs, &tmp_g);
}
border_mp_get_extreme_geometry(
td, pm, acs, solid_flags, &left_of_text_g, &right_of_text_g,
&left_end_g, &right_end_g);
if (td->length > 0)
{
if (TBMP_HAS_PART(TBMP_LEFT_MAIN, pm, acs, solid_flags) &&
td->left_main_g.width > 0 && td->left_main_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags,
stretch_flags, TBMP_LEFT_MAIN, dest_pix, w,
&td->full_left_main_g, &td->layout.title_g, bs,
&td->left_main_g);
}
if (TBMP_HAS_PART(TBMP_RIGHT_MAIN, pm, acs, solid_flags) &&
td->right_main_g.width > 0 && td->right_main_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags,
stretch_flags, TBMP_RIGHT_MAIN, dest_pix, w,
&td->full_right_main_g, &td->layout.title_g, bs,
&td->right_main_g);
}
if (TBMP_HAS_PART(TBMP_UNDER_TEXT, pm, acs, solid_flags) &&
td->under_text_g.width > 0 && td->under_text_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags,
stretch_flags, TBMP_UNDER_TEXT, dest_pix, w,
NULL, &td->layout.title_g, bs,
&td->under_text_g);
}
if (left_of_text_g.width > 0 && left_of_text_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags,
stretch_flags, TBMP_LEFT_OF_TEXT, dest_pix, w,
NULL, &td->layout.title_g, bs, &left_of_text_g);
}
if (right_of_text_g.width > 0 && right_of_text_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags,
stretch_flags, TBMP_RIGHT_OF_TEXT, dest_pix, w,
NULL, &td->layout.title_g, bs, &right_of_text_g);
}
}
if (left_end_g.width > 0 && left_end_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags, stretch_flags,
TBMP_LEFT_END, dest_pix, w, NULL, &td->layout.title_g,
bs, &left_end_g);
}
if (right_end_g.width > 0 && right_end_g.height > 0)
{
border_mp_render_into_pixmap(
td, td->cd, pm, acs, pixels, solid_flags, stretch_flags,
TBMP_RIGHT_END, dest_pix, w, NULL, &td->layout.title_g,
bs, &right_end_g);
}
return;
}
/*
*
* draw title bar and buttons
*
*/
static void border_draw_decor_to_pixmap(
FvwmWindow *fw, Pixmap dest_pix, Window w,
pixmap_background_type *solid_bg, rectangle *w_g,
DecorFace *df, titlebar_descr *td, ButtonState bs,
int use_title_style, int is_toggled, int left1right0)
{
register DecorFaceType type = DFS_FACE_TYPE(df->style);
pixmap_background_type bg;
rectangle dest_g;
FvwmPicture *p;
int width,height;
int border;
int lr_just, tb_just;
common_decorations_type *cd;
cd = td->cd;
/* setup some default */
bg.pixmap.fra.mask = 0;
bg.pixmap.flags.is_stretched = 0;
bg.pixmap.flags.is_tiled = 0;
bg.flags.use_pixmap = 0;
bg.pixmap.g.x = 0;
bg.pixmap.g.y = 0;
if (DFS_BUTTON_RELIEF(df->style) == DFS_BUTTON_IS_FLAT)
{
border = 0;
}
else
{
border = HAS_MWM_BORDER(fw) ? 1 : 2;
}
dest_g.width = w_g->width;
dest_g.height = w_g->height;
dest_g.x = border;
dest_g.y = border;
switch (type)
{
case SimpleButton:
/* do nothing */
break;
case SolidButton:
/* overwrite with the default background */
dest_g.x = 0;
dest_g.y = 0;
border_fill_pixmap_background(dest_pix, &dest_g, solid_bg, cd);
break;
case VectorButton:
case DefaultVectorButton:
border_draw_vector_to_pixmap(
dest_pix, cd, is_toggled, &df->u.vector, w_g);
break;
case MiniIconButton:
case PixmapButton:
case ShrunkPixmapButton:
case StretchedPixmapButton:
if (w_g->width - 2*border <= 0 || w_g->height - 2*border <= 0)
{
break;
}
if (FMiniIconsSupported && type == MiniIconButton)
{
if (!fw->mini_icon)
{
break;
}
p = fw->mini_icon;
if (cd->cs >= 0)
{
bg.pixmap.fra.mask |= FRAM_HAVE_ICON_CSET;
bg.pixmap.fra.colorset = &Colorset[cd->cs];
}
}
else
{
p = df->u.p;
}
width = p->width;
height = p->height;
if ((type == ShrunkPixmapButton || type == MiniIconButton) &&
(p->width > w_g->width - 2*border ||
p->height > w_g->height - 2*border))
{
/* do so that the picture fit into the destination */
bg.pixmap.stretch_w = width =
min(w_g->width - 2*border, p->width);
bg.pixmap.stretch_h = height =
min(w_g->height - 2*border, p->height);
bg.pixmap.flags.is_stretched = 1;
}
else if (type == StretchedPixmapButton &&
(p->width < w_g->width - 2*border ||
p->height < w_g->height - 2*border))
{
/* do so that the picture fit into the destination */
bg.pixmap.stretch_w = width =
max(w_g->width - 2*border, p->width);
bg.pixmap.stretch_h = height =
max(w_g->height - 2*border, p->height);
bg.pixmap.flags.is_stretched = 1;
}
lr_just = DFS_H_JUSTIFICATION(df->style);
tb_just = DFS_V_JUSTIFICATION(df->style);
if (!td->td_is_rotated && fw->title_text_rotation != ROTATION_0)
{
if (fw->title_text_rotation == ROTATION_180)
{
switch (lr_just)
{
case JUST_LEFT:
lr_just = JUST_RIGHT;
break;
case JUST_RIGHT:
lr_just = JUST_LEFT;
break;
case JUST_CENTER:
default:
break;
}
switch (tb_just)
{
case JUST_TOP:
tb_just = JUST_BOTTOM;
break;
case JUST_BOTTOM:
tb_just = JUST_TOP;
break;
case JUST_CENTER:
default:
break;
}
}
else if (fw->title_text_rotation == ROTATION_90)
{
switch (lr_just)
{
case JUST_LEFT:
tb_just = JUST_TOP;
break;
case JUST_RIGHT:
tb_just = JUST_BOTTOM;
break;
case JUST_CENTER:
default:
tb_just = JUST_CENTER;
break;
}
switch (DFS_V_JUSTIFICATION(df->style))
{
case JUST_TOP:
lr_just = JUST_RIGHT;
break;
case JUST_BOTTOM:
lr_just = JUST_LEFT;
break;
case JUST_CENTER:
default:
lr_just = JUST_CENTER;
break;
}
}
else if (fw->title_text_rotation == ROTATION_270)
{
switch (lr_just)
{
case JUST_LEFT:
tb_just = JUST_BOTTOM;
break;
case JUST_RIGHT:
tb_just = JUST_TOP;
break;
case JUST_CENTER:
default:
tb_just = JUST_CENTER;
break;
}
switch (DFS_V_JUSTIFICATION(df->style))
{
case JUST_TOP:
lr_just = JUST_LEFT;
break;
case JUST_BOTTOM:
lr_just = JUST_RIGHT;
break;
case JUST_CENTER:
default:
lr_just = JUST_CENTER;
break;
}
}
}
switch (lr_just)
{
case JUST_LEFT:
dest_g.x = border;
break;
case JUST_RIGHT:
dest_g.x = (int)(w_g->width - width - border);
break;
case JUST_CENTER:
default:
/* round down */
dest_g.x = (int)(w_g->width - width) / 2;
break;
}
switch (tb_just)
{
case JUST_TOP:
dest_g.y = border;
break;
case JUST_BOTTOM:
dest_g.y = (int)(w_g->height - height - border);
break;
case JUST_CENTER:
default:
/* round down */
dest_g.y = (int)(w_g->height - height) / 2;
break;
}
if (dest_g.x < border)
{
dest_g.x = border;
}
if (dest_g.y < border)
{
dest_g.y = border;
}
bg.flags.use_pixmap = 1;
bg.pixmap.p = p->picture;
bg.pixmap.shape = p->mask;
bg.pixmap.alpha = p->alpha;
bg.pixmap.depth = p->depth;
bg.pixmap.g.width = p->width;
bg.pixmap.g.height = p->height;
border_fill_pixmap_background(dest_pix, &dest_g, &bg, cd);
break;
case TiledPixmapButton:
case AdjustedPixmapButton:
if (w_g->width - 2*border <= 0 || w_g->height - 2*border <= 0)
{
break;
}
p = df->u.p;
if (type == TiledPixmapButton)
{
bg.pixmap.flags.is_tiled = 1;
}
else
{
bg.pixmap.stretch_w = width = w_g->width - 2*dest_g.x;
bg.pixmap.stretch_h = height = w_g->height - 2*dest_g.y;
bg.pixmap.flags.is_stretched = 1;
}
bg.flags.use_pixmap = 1;
bg.pixmap.p = p->picture;
bg.pixmap.shape = p->mask;
bg.pixmap.alpha = p->alpha;
bg.pixmap.depth = p->depth;
bg.pixmap.g.width = p->width;
bg.pixmap.g.height = p->height;
border_fill_pixmap_background(dest_pix, &dest_g, &bg, cd);
break;
case MultiPixmap: /* for UseTitleStyle only */
{
int is_left = left1right0;
int part = TBMP_NONE;
int ap, cs;
unsigned int stretch;
Pixmap tmp = None;
FvwmPicture *full_pic = NULL;
rectangle g;
dynamic_common_decorations *dcd = &(cd->dynamic_cd);
FvwmPicture **pm;
FvwmAcs *acs;
Pixel *pixels;
unsigned short sf;
pm = df->u.mp.pixmaps;
acs = df->u.mp.acs;
pixels = df->u.mp.pixels;
sf = df->u.mp.solid_flags;
if (!border_mp_get_use_title_style_parts_and_geometry(
td, pm, acs, sf, is_left, &g, &part))
{
g.width = 0;
g.height = 0;
g.x = 0;
g.y = 0;
}
if (part == TBMP_NONE)
{
break;
}
if (sf & (1 << part))
{
bg.flags.use_pixmap = 0;
bg.pixel = pixels[part];
border_fill_pixmap_background(
dest_pix, &dest_g, &bg, cd);
break;
}
cs = acs[part].cs;
ap = acs[part].alpha_percent;
if (CSET_IS_TRANSPARENT_PR(cs))
{
break;
}
if (cs >= 0)
{
bg.pixmap.fra.mask = FRAM_HAVE_ADDED_ALPHA;
bg.pixmap.fra.added_alpha_percent = ap;
}
stretch = !!(df->u.mp.stretch_flags & (1 << part));
bg.flags.use_pixmap = 1;
dest_g.x = 0;
dest_g.y = 0;
if (cs >= 0 && use_title_style && g.width > 0 && g.height > 0 &&
!CSET_IS_TRANSPARENT_ROOT(cs) &&
(bg.pixmap.p = border_get_bar_pixmaps(
dcd, &g, bs, cs, NULL, part, stretch, NULL)) != None)
{
bg.pixmap.g.width = g.width;
bg.pixmap.g.height = g.height;
bg.pixmap.flags.is_tiled = 1;
bg.pixmap.g.x = w_g->x - g.x;
bg.pixmap.g.y = w_g->y - g.y;
bg.pixmap.shape = None;
bg.pixmap.alpha = None;
bg.pixmap.depth = Pdepth;
}
else if (CSET_IS_TRANSPARENT_ROOT(cs))
{
tmp = border_create_root_transparent_pixmap(
td, w, w_g->width, w_g->height, cs);
bg.pixmap.p = tmp;
bg.pixmap.g.width = w_g->width;
bg.pixmap.g.height = w_g->height;
bg.pixmap.shape = None;
bg.pixmap.alpha = None;
bg.pixmap.depth = Pdepth;
}
else if (cs >= 0)
{
int bg_w, bg_h;
tmp = CreateBackgroundPixmap(
dpy, w, w_g->width,
w_g->height, &Colorset[cs],
Pdepth, Scr.BordersGC, False);
bg.pixmap.p = tmp;
GetWindowBackgroundPixmapSize(
&Colorset[cs], w_g->width,
w_g->height, &bg_w, &bg_h);
bg.pixmap.g.width = bg_w;
bg.pixmap.g.height = bg_h;
bg.pixmap.shape = None;
bg.pixmap.alpha = None;
bg.pixmap.depth = Pdepth;
bg.pixmap.flags.is_tiled = 1;
}
else if (pm[part] && g.width > 0 && g.height > 0 &&
border_get_bar_pixmaps(
dcd, &g, bs, -1, pm[part], part, stretch,
&full_pic) != None && full_pic)
{
bg.pixmap.p = full_pic->picture;
bg.pixmap.shape = full_pic->mask;
bg.pixmap.alpha = full_pic->alpha;
bg.pixmap.depth = full_pic->depth;
bg.pixmap.g.width = full_pic->width;
bg.pixmap.g.height = full_pic->height;
bg.pixmap.g.x = w_g->x - g.x;
bg.pixmap.g.y = w_g->y - g.y;
}
else if (pm[part])
{
p = pm[part];
if (df->u.mp.stretch_flags & (1 << part))
{
bg.pixmap.flags.is_stretched = 1;
}
else
{
bg.pixmap.flags.is_tiled = 1;
}
bg.pixmap.p = p->picture;
bg.pixmap.shape = p->mask;
bg.pixmap.alpha = p->alpha;
bg.pixmap.depth = p->depth;
bg.pixmap.g.width = p->width;
bg.pixmap.g.height = p->height;
bg.pixmap.stretch_w = dest_g.width - dest_g.x;
bg.pixmap.stretch_h = dest_g.height - dest_g.y;
}
else
{
/* should not happen */
return;
}
if (bg.pixmap.p != None)
{
border_fill_pixmap_background(
dest_pix, &dest_g, &bg, cd);
}
if (tmp != None)
{
XFreePixmap(dpy, tmp);
}
break;
}
case ColorsetButton:
{
colorset_t *cs_t = &Colorset[df->u.acs.cs];
int cs = df->u.acs.cs;
Pixmap tmp = None;
int bg_w, bg_h;
if (CSET_IS_TRANSPARENT_PR(cs))
{
break;
}
dest_g.x = 0;
dest_g.y = 0;
if (use_title_style &&
!CSET_IS_TRANSPARENT_ROOT(cs) &&
(bg.pixmap.p = border_get_bar_pixmaps(
&(cd->dynamic_cd), &(td->bar_g), bs, cs, NULL,
TBMP_NONE, 0, NULL))
!= None)
{
bg.pixmap.g.width = td->bar_g.width;
bg.pixmap.g.height = td->bar_g.height;
bg.pixmap.g.x = w_g->x - td->bar_g.x;
bg.pixmap.g.y = w_g->y - td->bar_g.y;
}
else if (CSET_IS_TRANSPARENT_ROOT(cs))
{
tmp = border_create_root_transparent_pixmap(
td, w, w_g->width, w_g->height, cs);
if (tmp == None)
{
break;
}
bg.pixmap.p = tmp;
bg.pixmap.g.width = w_g->width;
bg.pixmap.g.height = w_g->height;
bg.pixmap.shape = None;
bg.pixmap.alpha = None;
bg.pixmap.depth = Pdepth;
}
else
{
tmp = CreateBackgroundPixmap(
dpy, w, w_g->width, w_g->height,
cs_t, Pdepth, Scr.BordersGC, False);
if (tmp == None)
{
break;
}
bg.pixmap.p = tmp;
GetWindowBackgroundPixmapSize(
cs_t, w_g->width, w_g->height,
&bg_w, &bg_h);
bg.pixmap.g.width = bg_w;
bg.pixmap.g.height = bg_h;
bg.pixmap.g.x = 0;
bg.pixmap.g.y = 0;
}
bg.flags.use_pixmap = 1;
bg.pixmap.shape = None;
bg.pixmap.alpha = None;
bg.pixmap.depth = Pdepth;
bg.pixmap.flags.is_tiled = 1;
bg.pixmap.fra.mask = FRAM_HAVE_ADDED_ALPHA;
bg.pixmap.fra.added_alpha_percent = df->u.acs.alpha_percent;
border_fill_pixmap_background(dest_pix, &dest_g, &bg, cd);
if (tmp)
{
XFreePixmap(dpy, tmp);
}
break;
}
case GradientButton:
/* draw the gradient into the pixmap */
CreateGradientPixmap(
dpy, dest_pix, Scr.TransMaskGC,
df->u.grad.gradient_type, 0, 0, df->u.grad.npixels,
df->u.grad.xcs, df->u.grad.do_dither,
&df->u.grad.d_pixels, &df->u.grad.d_npixels,
dest_pix, 0, 0, w_g->width, w_g->height, NULL);
break;
default:
fvwm_msg(ERR, "DrawButton", "unknown button type: %i", type);
break;
}
return;
}
static void border_set_button_pixmap(
FvwmWindow *fw, titlebar_descr *td, int button, Pixmap *dest_pix,
Window w)
{
pixmap_background_type bg;
unsigned int mask;
int is_left_button;
int do_reverse_relief;
ButtonState bs;
DecorFace *df;
rectangle *button_g;
GC rgc;
GC sgc;
Bool free_bg_pixmap = False;
rectangle pix_g;
/* prepare variables */
mask = (1 << button);
if (td->has_an_upsidedown_rotation)
{
is_left_button = (button & 1);
}
else
{
is_left_button = !(button & 1);
}
button_g = &td->layout.button_g[button];
bs = td->tbstate.bstate[button];
df = &TB_STATE(GetDecor(fw, buttons[button]))[bs];
rgc = td->cd->relief_gc;
sgc = td->cd->shadow_gc;
/* prepare background, either from the window colour or from the
* border style */
if (!DFS_USE_BORDER_STYLE(df->style))
{
/* fill with the button background colour */
bg.flags.use_pixmap = 0;
bg.pixel = td->cd->back_color;
pix_g.x = 0;
pix_g.y = 0;
pix_g.width = button_g->width;
pix_g.height = button_g->height;
border_fill_pixmap_background(*dest_pix, &pix_g, &bg, td->cd);
}
else
{
/* draw pixmap background inherited from border style */
rectangle relative_g;
relative_g.width = td->frame_g.width;
relative_g.height = td->frame_g.height;
relative_g.x = button_g->x;
relative_g.y = button_g->y;
border_get_border_background(
&bg, td->cd, button_g, &relative_g, &free_bg_pixmap, w);
bg.pixmap.g.x = 0;
bg.pixmap.g.y = 0;
/* set the geometry for drawing the Tiled pixmap;
* FIXME: maybe add the relief as offset? */
pix_g.x = 0;
pix_g.y = 0;
pix_g.width = button_g->width;
pix_g.height = button_g->height;
border_fill_pixmap_background(*dest_pix, &pix_g, &bg, td->cd);
if (free_bg_pixmap && bg.pixmap.p)
{
XFreePixmap(dpy, bg.pixmap.p);
}
}
/* handle title style */
if (DFS_USE_TITLE_STYLE(df->style))
{
/* draw background inherited from title style */
DecorFace *tsdf;
Pixmap tmp;
if (td->draw_rotation != ROTATION_0)
{
tmp = CreateRotatedPixmap(
dpy, *dest_pix,
td->layout.button_g[button].width,
td->layout.button_g[button].height,
Pdepth, Scr.BordersGC, td->restore_rotation);
XFreePixmap(dpy, *dest_pix);
*dest_pix = tmp;
border_rotate_titlebar_descr(fw, td);
button_g = &td->layout.button_g[button];
is_left_button = !(button & 1);
}
for (tsdf = &TB_STATE(GetDecor(fw, titlebar))[bs]; tsdf != NULL;
tsdf = tsdf->next)
{
bg.pixel = tsdf->u.back;
border_draw_decor_to_pixmap(
fw, *dest_pix, w, &bg, button_g, tsdf, td,
bs, True, (td->tbstate.toggled_bmask & mask),
is_left_button);
}
if (td->draw_rotation != ROTATION_0)
{
tmp = CreateRotatedPixmap(
dpy, *dest_pix,
td->layout.button_g[button].width,
td->layout.button_g[button].height,
Pdepth, Scr.BordersGC, td->draw_rotation);
XFreePixmap(dpy, *dest_pix);
*dest_pix = tmp;
border_rotate_titlebar_descr(fw, td);
button_g = &td->layout.button_g[button];
if (td->has_an_upsidedown_rotation)
{
is_left_button = (button & 1);
}
else
{
is_left_button = !(button & 1);
}
}
}
/* handle button style */
for ( ; df; df = df->next)
{
/* draw background from button style */
bg.pixel = df->u.back;
border_draw_decor_to_pixmap(
fw, *dest_pix, w, &bg, button_g, df, td, bs, False,
(td->tbstate.toggled_bmask & mask), is_left_button);
}
/* draw the button relief */
do_reverse_relief = !!(td->tbstate.pressed_bmask & mask);
switch (DFS_BUTTON_RELIEF(
TB_STATE(GetDecor(fw, buttons[button]))[bs].style))
{
case DFS_BUTTON_IS_SUNK:
do_reverse_relief ^= 1;
/* fall through*/
case DFS_BUTTON_IS_UP:
do_relieve_rectangle(
dpy, *dest_pix, 0, 0, button_g->width - 1,
button_g->height - 1,
(do_reverse_relief) ? sgc : rgc,
(do_reverse_relief) ? rgc : sgc,
td->cd->relief_width, True);
break;
default:
/* flat */
break;
}
return;
}
static void border_draw_one_button(
FvwmWindow *fw, titlebar_descr *td, int button)
{
Pixmap p;
/* make a pixmap */
if (td->layout.button_g[button].x < 0 ||
td->layout.button_g[button].y < 0)
{
return;
}
p = border_create_decor_pixmap(td->cd, &(td->layout.button_g[button]));
/* set the background tile */
border_set_button_pixmap(fw, td, button, &p, FW_W_BUTTON(fw, button));
/* apply the pixmap and destroy it */
border_set_part_background(FW_W_BUTTON(fw, button), p);
XFreePixmap(dpy, p);
if ((td->tbstate.clear_bmask & (1 << button)) != 0)
{
XClearWindow(dpy, FW_W_BUTTON(fw, button));
}
return;
}
static void border_draw_title_stick_lines(
FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd,
Pixmap dest_pix)
{
int i;
int num;
int min;
int max;
int left_x;
int left_w;
int right_x;
int right_w;
int under_text_length = 0;
int under_text_offset = 0;
int right_length = 0;
int left_length = 0;
rotation_t rotation;
if (!( (HAS_STICKY_STIPPLED_TITLE(fw) &&
(IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw)))
|| HAS_STIPPLED_TITLE(fw)))
{
return;
}
if (td->td_is_rotated)
{
rotation = td->restore_rotation;
}
else
{
rotation = ROTATION_0;
}
if (td->has_vt && td->under_text_g.height > 0)
{
under_text_length = td->under_text_g.height;
under_text_offset = td->under_text_g.y;
left_length = td->left_main_g.height - td->left_of_text_length
- td->left_end_length;
right_length = td->right_main_g.height -
td->right_of_text_length - td->right_end_length;
}
else if (!td->has_vt && td->under_text_g.width > 0)
{
under_text_length = td->under_text_g.width;
under_text_offset = td->under_text_g.x;
left_length = td->left_main_g.width - td->left_of_text_length
- td->left_end_length;
right_length = td->right_main_g.width -
td->right_of_text_length - td->right_end_length;
}
/* If the window is sticky either across pages or
* desks and it has a stippled title, but nothing for
* sticky_stippled_title, then don't bother drawing them, just
* return immediately. -- Thomas Adam
*/
if ( (IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw)) &&
(!HAS_STICKY_STIPPLED_TITLE(fw) && HAS_STIPPLED_TITLE(fw)) )
{
return;
}
num = (int)(fw->title_thickness / WINDOW_TITLE_STICK_VERT_DIST / 2) *
2 - 1;
min = fw->title_thickness / 2 - num * 2 + 1;
max = fw->title_thickness / 2 + num * 2 -
WINDOW_TITLE_STICK_VERT_DIST + 1;
left_x = WINDOW_TITLE_STICK_OFFSET + td->left_end_length;
left_w = ((under_text_length == 0)? td->offset:under_text_offset)
- left_x - WINDOW_TITLE_TO_STICK_GAP - td->left_of_text_length;
right_x = ((under_text_length == 0)?
td->offset + td->length :
under_text_offset + under_text_length)
+ td->right_of_text_length + WINDOW_TITLE_TO_STICK_GAP - 1;
right_w = fw->title_length - right_x - WINDOW_TITLE_STICK_OFFSET
- td->right_end_length;
/* an odd number of lines every WINDOW_TITLE_STICK_VERT_DIST pixels */
if (left_w < WINDOW_TITLE_STICK_MIN_WIDTH)
{
left_x = td->left_end_length +
((left_length > WINDOW_TITLE_STICK_MIN_WIDTH)?
(left_length - WINDOW_TITLE_STICK_MIN_WIDTH)/2 : 0);
left_w = WINDOW_TITLE_STICK_MIN_WIDTH;
}
if (right_w < WINDOW_TITLE_STICK_MIN_WIDTH)
{
right_w = WINDOW_TITLE_STICK_MIN_WIDTH;
right_x = fw->title_length - WINDOW_TITLE_STICK_MIN_WIDTH - 1
- td->right_end_length -
((right_length > WINDOW_TITLE_STICK_MIN_WIDTH)?
(right_length -
WINDOW_TITLE_STICK_MIN_WIDTH)/2 : 0);
}
for (i = min; i <= max; i += WINDOW_TITLE_STICK_VERT_DIST)
{
if (left_w > 0)
{
do_relieve_rectangle_with_rotation(
dpy, dest_pix,
SWAP_ARGS(td->has_vt, left_x, i),
SWAP_ARGS(td->has_vt, left_w, 1),
tdd->sgc, tdd->rgc, 1, False, rotation);
}
if (right_w > 0)
{
do_relieve_rectangle_with_rotation(
dpy, dest_pix,
SWAP_ARGS(td->has_vt, right_x, i),
SWAP_ARGS(td->has_vt, right_w, 1),
tdd->sgc, tdd->rgc, 1, False, rotation);
}
}
return;
}
static void border_draw_title_mono(
FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd,
FlocaleWinString *fstr, Pixmap dest_pix)
{
int has_vt;
has_vt = HAS_VERTICAL_TITLE(fw);
XFillRectangle(
dpy, dest_pix, td->cd->relief_gc,
td->offset - 2, 0, td->length+4, fw->title_thickness);
if (fw->visible_name != (char *)NULL)
{
FlocaleDrawString(dpy, fw->title_font, fstr, 0);
}
/* for mono, we clear an area in the title bar where the window
* title goes, so that its more legible. For color, no need */
do_relieve_rectangle(
dpy, dest_pix, 0, 0,
SWAP_ARGS(has_vt, td->offset - 3,
fw->title_thickness - 1),
tdd->rgc, tdd->sgc, td->cd->relief_width, False);
do_relieve_rectangle(
dpy, dest_pix,
SWAP_ARGS(has_vt, td->offset + td->length + 2, 0),
SWAP_ARGS(has_vt, fw->title_length - td->length -
td->offset - 3, fw->title_thickness - 1),
tdd->rgc, tdd->sgc, td->cd->relief_width, False);
XDrawLine(
dpy, dest_pix, tdd->sgc,
SWAP_ARGS(has_vt, 0, td->offset + td->length + 1),
SWAP_ARGS(has_vt, td->offset + td->length + 1,
fw->title_thickness));
return;
}
static void border_draw_title_relief(
FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd,
Pixmap dest_pix)
{
int reverse = 0;
rotation_t rotation;
if (td->td_is_rotated)
{
rotation = td->restore_rotation;
}
else
{
rotation = ROTATION_0;
}
/* draw title relief */
switch (DFS_BUTTON_RELIEF(*tdd->tstyle))
{
case DFS_BUTTON_IS_SUNK:
reverse = 1;
case DFS_BUTTON_IS_UP:
do_relieve_rectangle_with_rotation(
dpy, dest_pix, 0, 0,
SWAP_ARGS(
td->has_vt, fw->title_length - 1,
fw->title_thickness - 1),
(reverse) ? tdd->sgc : tdd->rgc,
(reverse) ? tdd->rgc : tdd->sgc, td->cd->relief_width,
True, rotation);
break;
default:
/* flat */
break;
}
return;
}
static void border_draw_title_deep(
FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd,
FlocaleWinString *fstr, Pixmap dest_pix, Window w)
{
DecorFace *df;
pixmap_background_type bg;
bg.flags.use_pixmap = 0;
for (df = tdd->df; df != NULL; df = df->next)
{
if (df->style.face_type == MultiPixmap)
{
border_mp_draw_mp_titlebar(
fw, td, df, dest_pix, w);
}
else
{
bg.pixel = df->u.back;
border_draw_decor_to_pixmap(
fw, dest_pix, w, &bg, &td->layout.title_g, df,
td, td->tbstate.tstate, True, tdd->is_toggled,
1);
}
}
FlocaleDrawString(dpy, fw->title_font, &tdd->fstr, 0);
return;
}
static void border_get_titlebar_draw_descr(
FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd,
Pixmap dest_pix)
{
rectangle *title_g;
memset(tdd, 0, sizeof(*tdd));
/* prepare the gcs and variables */
if (td->tbstate.is_title_pressed)
{
tdd->rgc = td->cd->shadow_gc;
tdd->sgc = td->cd->relief_gc;
}
else
{
tdd->rgc = td->cd->relief_gc;
tdd->sgc = td->cd->shadow_gc;
}
NewFontAndColor(fw->title_font, td->cd->fore_color, td->cd->back_color);
title_g = &td->layout.title_g;
tdd->tstyle = &TB_STATE(
GetDecor(fw, titlebar))[td->tbstate.tstate].style;
tdd->df = &TB_STATE(GetDecor(fw, titlebar))[td->tbstate.tstate];
/* fetch the title string */
tdd->fstr.str = fw->visible_name;
tdd->fstr.win = dest_pix;
if (td->td_is_rotated)
{
tdd->fstr.flags.text_rotation = ROTATION_0;
}
else
{
tdd->fstr.flags.text_rotation = fw->title_text_rotation;
}
if (td->has_vt)
{
tdd->fstr.y = td->offset;
tdd->fstr.x = fw->title_text_offset + 1;
}
else
{
tdd->fstr.x = td->offset;
tdd->fstr.y = fw->title_text_offset + 1;
}
if (td->cd->cs >= 0)
{
tdd->fstr.colorset = &Colorset[td->cd->cs];
tdd->fstr.flags.has_colorset = 1;
}
tdd->fstr.gc = Scr.TitleGC;
return;
}
static void border_set_title_pixmap(
FvwmWindow *fw, titlebar_descr *td, Pixmap *dest_pix, Window w)
{
pixmap_background_type bg;
title_draw_descr tdd;
FlocaleWinString fstr;
Bool free_bg_pixmap = False;
rectangle pix_g;
border_get_titlebar_draw_descr(fw, td, &tdd, *dest_pix);
/* prepare background, either from the window colour or from the
* border style */
if (!DFS_USE_BORDER_STYLE(*tdd.tstyle))
{
/* fill with the button background colour */
bg.flags.use_pixmap = 0;
bg.pixel = td->cd->back_color;
pix_g.x = 0;
pix_g.y = 0;
pix_g.width = td->layout.title_g.width;
pix_g.height = td->layout.title_g.height;
border_fill_pixmap_background(
*dest_pix, &pix_g, &bg, td->cd);
}
else
{
/* draw pixmap background inherited from border style */
rectangle relative_g;
Pixmap tmp;
if (td->draw_rotation != ROTATION_0)
{
tmp = CreateRotatedPixmap(
dpy, *dest_pix,
td->layout.title_g.width,
td->layout.title_g.height,
Pdepth, Scr.BordersGC, td->restore_rotation);
XFreePixmap(dpy, *dest_pix);
*dest_pix = tmp;
border_rotate_titlebar_descr(fw, td);
}
relative_g.width = td->frame_g.width;
relative_g.height = td->frame_g.height;
relative_g.x = td->layout.title_g.x;
relative_g.y = td->layout.title_g.y;
border_get_border_background(
&bg, td->cd, &td->layout.title_g, &relative_g,
&free_bg_pixmap, w);
bg.pixmap.g.x = 0;
bg.pixmap.g.y = 0;
/* set the geometry for drawing the Tiled pixmap;
* FIXME: maybe add the relief as offset? */
pix_g.x = 0;
pix_g.y = 0;
pix_g.width = td->layout.title_g.width;
pix_g.height = td->layout.title_g.height;
border_fill_pixmap_background(
*dest_pix, &pix_g, &bg, td->cd);
if (free_bg_pixmap && bg.pixmap.p)
{
XFreePixmap(dpy, bg.pixmap.p);
}
if (td->draw_rotation != ROTATION_0)
{
tmp = CreateRotatedPixmap(
dpy, *dest_pix,
td->layout.title_g.width,
td->layout.title_g.height,
Pdepth, Scr.BordersGC, td->draw_rotation);
XFreePixmap(dpy, *dest_pix);
*dest_pix = tmp;
border_rotate_titlebar_descr(fw, td);
}
}
if (Pdepth < 2)
{
border_draw_title_mono(fw, td, &tdd, &fstr, *dest_pix);
}
else
{
border_draw_title_deep(fw, td, &tdd, &fstr, *dest_pix, w);
}
border_draw_title_relief(fw, td, &tdd, *dest_pix);
border_draw_title_stick_lines(fw, td, &tdd, *dest_pix);
return;
}
static void border_draw_title(
FvwmWindow *fw, titlebar_descr *td)
{
Pixmap p;
if (td->layout.title_g.x < 0 || td->layout.title_g.y < 0)
{
return;
}
if (td->draw_rotation != ROTATION_0)
{
border_rotate_titlebar_descr(fw, td);
}
/* make a pixmap */
p = border_create_decor_pixmap(td->cd, &(td->layout.title_g));
/* set the background tile */
#if 0
fprintf(stderr,"drawing title\n");
#endif
border_set_title_pixmap(fw, td, &p, FW_W_TITLE(fw));
if (td->draw_rotation != ROTATION_0)
{
Pixmap tmp;
tmp = CreateRotatedPixmap(
dpy, p, td->layout.title_g.width,
td->layout.title_g.height, Pdepth, Scr.BordersGC,
td->draw_rotation);
XFreePixmap(dpy, p);
p = tmp;
border_rotate_titlebar_descr(fw, td);
}
/* apply the pixmap and destroy it */
border_set_part_background(FW_W_TITLE(fw), p);
XFreePixmap(dpy, p);
if (td->tbstate.do_clear_title)
{
XClearWindow(dpy, FW_W_TITLE(fw));
}
return;
}
static void border_draw_buttons(
FvwmWindow *fw, titlebar_descr *td)
{
int i;
/* draw everything in a big loop */
#if 0
fprintf(stderr, "drawing buttons 0x%04x\n", td->tbstate.draw_bmask);
#endif
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
unsigned int mask = (1 << i);
if ((td->tbstate.draw_bmask & mask) != 0)
{
border_draw_one_button(fw, td, i);
}
}
/* update the button states */
fw->decor_state.buttons_drawn |= td->tbstate.draw_bmask;
fw->decor_state.buttons_inverted = td->tbstate.pressed_bmask;
fw->decor_state.buttons_lit = td->tbstate.lit_bmask;
fw->decor_state.buttons_toggled = td->tbstate.toggled_bmask;
return;
}
static void border_setup_use_title_style(
FvwmWindow *fw, titlebar_descr *td)
{
int i;
DecorFace *df, *tsdf;
ButtonState bs, tsbs;
/* use a full bar pixmap (for Colorset) or non window size pixmaps
* (for MultiPixmap) under certain condition:
* - for the buttons which use title style
* - for title which have a button with UseTitle style
*/
tsbs = td->tbstate.tstate;
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
bs = td->tbstate.bstate[i];
df = &TB_STATE(GetDecor(fw, buttons[i]))[bs];
tsdf = &TB_STATE(GetDecor(fw, buttons[i]))[tsbs];
if (FW_W_BUTTON(fw, i) != None)
{
if (DFS_USE_TITLE_STYLE(df->style))
{
border_setup_bar_pixmaps(
td, &(td->cd->dynamic_cd),
&TB_STATE(GetDecor(fw, titlebar))[bs],
bs);
}
if (DFS_USE_TITLE_STYLE(tsdf->style))
{
border_setup_bar_pixmaps(
td, &(td->cd->dynamic_cd),
&TB_STATE(GetDecor(fw, titlebar))[tsbs],
tsbs);
}
}
}
return;
}
static void border_rotate_titlebar_descr(
FvwmWindow *fw, titlebar_descr *td)
{
rotation_t rotation;
int i, tmpi;
static titlebar_descr saved_td;
if (td->draw_rotation == ROTATION_0)
{
return;
}
if (!td->has_been_saved)
{
td->has_been_saved = True;
memcpy(&saved_td, td, sizeof(titlebar_descr));
}
if (!td->td_is_rotated)
{
/* make the bar horizontal */
switch(td->draw_rotation)
{
case ROTATION_90: /* cw */
rotation = ROTATION_270;
break;
case ROTATION_270: /* ccw */
rotation = ROTATION_90;
break;
case ROTATION_180:
rotation = ROTATION_180;
break;
default:
return;
}
td->has_vt = 0;
td->has_an_upsidedown_rotation = 0;
td->td_is_rotated = 1;
}
else
{
/* restore */
memcpy(td, &saved_td, sizeof(titlebar_descr));
td->td_is_rotated = 0;
return;
}
#define ROTATE_RECTANGLE(rot, r, vs_frame, vs_titlebar, vs_title) \
{ \
rectangle tr; \
tr.x = r->x; \
tr.y = r->y; \
tr.width = r->width; \
tr.height = r->height; \
switch(rot) \
{ \
case ROTATION_270: /* ccw */ \
tr.x = r->y; \
if (vs_frame) \
{ \
tr.y = td->frame_g.width - (r->x+r->width); \
} \
else if (vs_titlebar) \
{ \
tr.y = td->bar_g.width - \
(r->x+r->width); \
} \
else if (vs_title) \
{ \
tr.y = td->layout.title_g.width - \
(r->x+r->width); \
} \
else \
{ \
tr.y = r->x; \
} \
tr.width = r->height; \
tr.height = r->width; \
break; \
case ROTATION_90: /* cw */ \
if (vs_frame) \
{ \
tr.x = td->frame_g.height - (r->y+r->height); \
} \
else if (vs_titlebar) \
{ \
tr.x = td->bar_g.height - \
(r->y+r->height); \
} \
else if (vs_title) \
{ \
tr.x = td->layout.title_g.height - \
(r->y+r->height); \
} \
else \
{ \
tr.x = r->y; \
} \
tr.y = r->x; \
tr.width = r->height; \
tr.height = r->width; \
break; \
case ROTATION_180: \
if (vs_frame) \
{ \
tr.x = td->frame_g.width - (r->x+r->width); \
} \
else if (vs_titlebar) \
{ \
tr.x = td->bar_g.width - \
(r->x + r->width); \
} \
else if (vs_title) \
{ \
tr.x = td->layout.title_g.width - \
(r->x + r->width); \
} \
else \
{ \
tr.x = r->x; \
} \
break; \
case ROTATION_0: \
break; \
} \
r->x = tr.x; \
r->y = tr.y; \
r->width = tr.width; \
r->height = tr.height; \
}
switch(rotation)
{
case ROTATION_90:
td->offset =
td->layout.title_g.height - td->offset - td->length;
tmpi = td->left_end_length;
td->left_end_length = td->right_end_length;
td->right_end_length = tmpi;
tmpi = td->left_of_text_length;
td->left_of_text_length = td->right_of_text_length;
td->right_of_text_length = tmpi;
break;
case ROTATION_270:
break;
case ROTATION_180:
td->offset = td->layout.title_g.width - td->offset - td->length;
tmpi = td->left_end_length;
td->left_end_length = td->right_end_length;
td->right_end_length = tmpi;
tmpi = td->left_of_text_length;
td->left_of_text_length = td->right_of_text_length;
td->right_of_text_length = tmpi;
break;
case ROTATION_0:
break;
}
ROTATE_RECTANGLE(rotation, (&td->left_buttons_g), True, False, False)
ROTATE_RECTANGLE(rotation, (&td->right_buttons_g), True, False, False)
for (i=0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
ROTATE_RECTANGLE(
rotation, (&td->layout.button_g[i]), True, False, False)
}
ROTATE_RECTANGLE(rotation, (&td->under_text_g), False, False, True)
ROTATE_RECTANGLE(rotation, (&td->left_main_g), False, False, True)
ROTATE_RECTANGLE(rotation, (&td->right_main_g), False, False, True)
ROTATE_RECTANGLE(rotation, (&td->full_left_main_g), True, False, False)
ROTATE_RECTANGLE(rotation, (&td->full_right_main_g), True, False, False)
ROTATE_RECTANGLE(rotation, (&td->layout.title_g), True, False, False)
ROTATE_RECTANGLE(rotation, (&td->bar_g), True, False, False)
ROTATE_RECTANGLE(rotation, (&td->frame_g), False, False, False);
#undef ROTATE_RECTANGLE
}
static void border_get_titlebar_descr_state(
FvwmWindow *fw, window_parts pressed_parts, int pressed_button,
clear_window_parts clear_parts, Bool do_hilight,
border_titlebar_state *tbstate)
{
int i;
if ((pressed_parts & PART_BUTTONS) != PART_NONE && pressed_button >= 0)
{
tbstate->pressed_bmask = (1 << pressed_button);
}
else
{
tbstate->pressed_bmask = 0;
}
if ((clear_parts & CLEAR_BUTTONS) != CLEAR_NONE)
{
tbstate->clear_bmask = ~0;
}
else
{
tbstate->clear_bmask = 0;
}
tbstate->lit_bmask = (do_hilight == True) ? ~0 : 0;
if ((pressed_parts & PART_TITLE) != PART_NONE)
{
tbstate->is_title_pressed = 1;
}
else
{
tbstate->is_title_pressed = 0;
}
if ((clear_parts & CLEAR_TITLE) != CLEAR_NONE)
{
tbstate->do_clear_title = 1;
}
else
{
tbstate->do_clear_title = 0;
}
tbstate->is_title_lit = (do_hilight == True) ? 1 : 0;
tbstate->toggled_bmask = 0;
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
unsigned int mask = (1 << i);
if (is_button_toggled(fw, i))
{
tbstate->toggled_bmask |= mask;
}
tbstate->bstate[i] = border_flags_to_button_state(
tbstate->pressed_bmask & mask,
tbstate->lit_bmask & mask,
tbstate->toggled_bmask & mask);
}
tbstate->tstate = border_flags_to_button_state(
tbstate->is_title_pressed, tbstate->is_title_lit, 0);
}
static window_parts border_get_titlebar_descr(
common_decorations_type *cd, FvwmWindow *fw,
window_parts pressed_parts, int pressed_button,
window_parts force_draw_parts, clear_window_parts clear_parts,
rectangle *old_g, rectangle *new_g, Bool do_hilight,
titlebar_descr *ret_td)
{
window_parts draw_parts;
int i;
DecorFace *df;
int is_start = 0;
JustificationType just;
int lbl = 0;
int rbl = 0;
ret_td->cd = cd;
ret_td->frame_g = *new_g;
if (old_g == NULL)
{
old_g = &fw->g.frame;
}
frame_get_titlebar_dimensions(fw, old_g, NULL, &ret_td->old_layout);
frame_get_titlebar_dimensions(fw, new_g, NULL, &ret_td->layout);
ret_td->has_vt = HAS_VERTICAL_TITLE(fw);
if (USE_TITLE_DECOR_ROTATION(fw))
{
ret_td->draw_rotation = fw->title_text_rotation;
switch(ret_td->draw_rotation)
{
case ROTATION_90:
ret_td->restore_rotation = ROTATION_270;
break;
case ROTATION_270: /* ccw */
ret_td->restore_rotation = ROTATION_90;
break;
case ROTATION_180:
ret_td->restore_rotation = ROTATION_180;
break;
default:
break;
}
}
if (fw->title_text_rotation == ROTATION_270 ||
fw->title_text_rotation == ROTATION_180)
{
ret_td->has_an_upsidedown_rotation = True;
}
/* geometry of the title bar title + buttons */
if (!ret_td->has_vt)
{
ret_td->bar_g.width = new_g->width - 2 * fw->boundary_width;
ret_td->bar_g.height = ret_td->layout.title_g.height;
ret_td->bar_g.x = fw->boundary_width;
ret_td->bar_g.y = ret_td->layout.title_g.y;
}
else
{
ret_td->bar_g.width = ret_td->layout.title_g.width;
ret_td->bar_g.height = new_g->height - 2 * fw->boundary_width;
ret_td->bar_g.y = fw->boundary_width;
ret_td->bar_g.x = ret_td->layout.title_g.x;
}
/* buttons geometries */
if (ret_td->has_vt)
{
ret_td->left_buttons_g.width = ret_td->bar_g.width;
ret_td->right_buttons_g.width = ret_td->bar_g.width;
}
else
{
ret_td->left_buttons_g.height = ret_td->bar_g.height;
ret_td->right_buttons_g.height = ret_td->bar_g.width;
}
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
if (FW_W_BUTTON(fw, i) == None)
{
continue;
}
if (ret_td->has_vt)
{
if (i & 1)
{
rbl += ret_td->layout.button_g[i].height;
}
else
{
lbl += ret_td->layout.button_g[i].height;
}
}
else
{
if (i & 1)
{
rbl += ret_td->layout.button_g[i].width;
}
else
{
lbl += ret_td->layout.button_g[i].width;
}
}
}
if (ret_td->has_an_upsidedown_rotation)
{
if (ret_td->has_vt)
{
ret_td->left_buttons_g.height = rbl;
ret_td->right_buttons_g.height = lbl;
ret_td->right_buttons_g.y = fw->boundary_width;
ret_td->right_buttons_g.x = ret_td->bar_g.x;
ret_td->left_buttons_g.y = ret_td->layout.title_g.y +
ret_td->layout.title_g.height;
ret_td->left_buttons_g.x = ret_td->bar_g.x;
}
else
{
ret_td->left_buttons_g.width = rbl;
ret_td->right_buttons_g.width = lbl;
ret_td->right_buttons_g.x = fw->boundary_width;
ret_td->right_buttons_g.y = ret_td->bar_g.y;
ret_td->left_buttons_g.x = ret_td->layout.title_g.x +
ret_td->layout.title_g.width;
ret_td->left_buttons_g.y = ret_td->bar_g.y;
}
}
else
{
if (ret_td->has_vt)
{
ret_td->left_buttons_g.height = lbl;
ret_td->right_buttons_g.height = rbl;
ret_td->left_buttons_g.y = fw->boundary_width;
ret_td->left_buttons_g.x = ret_td->bar_g.x;
ret_td->right_buttons_g.y = ret_td->layout.title_g.y +
ret_td->layout.title_g.height;
ret_td->right_buttons_g.x = ret_td->bar_g.x;
}
else
{
ret_td->left_buttons_g.width = lbl;
ret_td->right_buttons_g.width = rbl;
ret_td->left_buttons_g.x = fw->boundary_width;
ret_td->left_buttons_g.y = ret_td->bar_g.y;
ret_td->right_buttons_g.x = ret_td->layout.title_g.x +
ret_td->layout.title_g.width;
ret_td->right_buttons_g.y = ret_td->bar_g.y;
}
}
/* initialise flags */
border_get_titlebar_descr_state(
fw, pressed_parts, pressed_button, clear_parts, do_hilight,
&(ret_td->tbstate));
/* get the title string length and position
* This is not in "tdd" (titlebar_draw_descr), because these are needed
* to draw the buttons with UseTitleStyle */
just = TB_JUSTIFICATION(GetDecor(fw, titlebar));
if (fw->visible_name != (char *)NULL)
{
ret_td->length = FlocaleTextWidth(
fw->title_font, fw->visible_name,
(ret_td->has_vt) ? -strlen(fw->visible_name) :
strlen(fw->visible_name));
if (ret_td->length > fw->title_length -
2*MIN_WINDOW_TITLE_TEXT_OFFSET)
{
ret_td->length = fw->title_length -
2*MIN_WINDOW_TITLE_TEXT_OFFSET;
just = JUST_CENTER;
}
if (ret_td->length < 0)
{
ret_td->length = 0;
}
}
else
{
ret_td->length = 0;
}
if (ret_td->length == 0)
{
just = JUST_CENTER;
}
df = &TB_STATE(GetDecor(fw, titlebar))[ret_td->tbstate.tstate];
switch (just)
{
case JUST_LEFT:
is_start = 1;
/* fall through */
case JUST_RIGHT:
if (ret_td->has_an_upsidedown_rotation)
{
is_start = !is_start;
}
if (is_start)
{
if (WINDOW_TITLE_TEXT_OFFSET + ret_td->length <=
fw->title_length)
{
ret_td->offset = WINDOW_TITLE_TEXT_OFFSET;
}
else
{
ret_td->offset =
fw->title_length - ret_td->length;
}
}
else
{
ret_td->offset = fw->title_length - ret_td->length -
WINDOW_TITLE_TEXT_OFFSET;
}
break;
case JUST_CENTER:
default:
ret_td->offset = (fw->title_length - ret_td->length) / 2;
break;
}
if (ret_td->offset < MIN_WINDOW_TITLE_TEXT_OFFSET)
{
ret_td->offset = MIN_WINDOW_TITLE_TEXT_OFFSET;
}
/* setup MultiPixmap */
border_mp_get_titlebar_descr(fw, ret_td, df);
/* determine the parts to draw */
draw_parts = border_get_tb_parts_to_draw(
fw, ret_td, old_g, new_g, force_draw_parts);
return draw_parts;
}
static void border_draw_titlebar(
common_decorations_type *cd, FvwmWindow *fw,
window_parts pressed_parts, int pressed_button,
window_parts force_draw_parts, clear_window_parts clear_parts,
rectangle *old_g, rectangle *new_g, Bool do_hilight)
{
window_parts draw_parts;
titlebar_descr td;
if (!HAS_TITLE(fw))
{
/* just reset border states */
fw->decor_state.parts_drawn &= ~(PART_TITLE);
fw->decor_state.parts_lit &= ~(PART_TITLE);
fw->decor_state.parts_inverted &= ~(PART_TITLE);
fw->decor_state.buttons_drawn = 0;
fw->decor_state.buttons_lit = 0;
fw->decor_state.buttons_inverted = 0;
fw->decor_state.buttons_toggled = 0;
return;
}
memset(&td, 0, sizeof(td));
draw_parts = border_get_titlebar_descr(
cd, fw, pressed_parts, pressed_button, force_draw_parts,
clear_parts, old_g, new_g, do_hilight, &td);
if ((draw_parts & PART_TITLE) != PART_NONE ||
(draw_parts & PART_BUTTONS) != PART_NONE)
{
/* set up UseTitleStyle Colorset */
border_setup_use_title_style(fw, &td);
}
if ((draw_parts & PART_TITLE) != PART_NONE)
{
border_draw_title(fw, &td);
}
if ((draw_parts & PART_BUTTONS) != PART_NONE)
{
border_draw_buttons(fw, &td);
}
border_free_bar_pixmaps(&(td.cd->dynamic_cd));
/* update the decor states */
fw->decor_state.parts_drawn |= draw_parts;
if (do_hilight)
{
fw->decor_state.parts_lit |= draw_parts;
}
else
{
fw->decor_state.parts_lit &= ~draw_parts;
}
fw->decor_state.parts_inverted &= ~draw_parts;
fw->decor_state.parts_inverted |= (draw_parts & pressed_parts);
if (draw_parts & PART_BUTTONS)
{
fw->decor_state.buttons_drawn |= td.tbstate.draw_bmask;
fw->decor_state.parts_lit = (do_hilight) ? ~0 : 0;
if (td.tbstate.pressed_bmask)
{
fw->decor_state.buttons_inverted =
td.tbstate.pressed_bmask;
}
else
{
fw->decor_state.buttons_inverted &=
~td.tbstate.draw_bmask;
}
fw->decor_state.buttons_toggled =
(fw->decor_state.buttons_toggled &
~td.tbstate.max_bmask) | td.tbstate.toggled_bmask;
}
return;
}
/*
*
* Redraws the windows borders
*
*/
static void border_draw_border_parts(
common_decorations_type *cd, FvwmWindow *fw,
window_parts pressed_parts, window_parts force_draw_parts,
clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g,
Bool do_hilight)
{
border_relief_descr br;
window_parts draw_parts;
Bool do_clear;
if (HAS_NO_BORDER(fw))
{
/* just reset border states */
fw->decor_state.parts_drawn &= ~(PART_FRAME | PART_HANDLES);
fw->decor_state.parts_lit &= ~(PART_FRAME | PART_HANDLES);
fw->decor_state.parts_inverted &= ~(PART_FRAME | PART_HANDLES);
return;
}
do_clear = (clear_parts & CLEAR_FRAME) ? True : False;
/* determine the parts to draw and the position to place them */
if (HAS_DEPRESSABLE_BORDER(fw))
{
pressed_parts &= PART_FRAME;
}
else
{
pressed_parts = PART_NONE;
}
force_draw_parts &= PART_FRAME;
memset(&br, 0, sizeof(br));
draw_parts = border_get_parts_and_pos_to_draw(
cd, fw, pressed_parts, force_draw_parts, old_g, new_g,
do_hilight, &br);
if ((draw_parts & PART_FRAME) != PART_NONE)
{
border_draw_all_border_parts(
cd, fw, &br, new_g, draw_parts, pressed_parts,
do_hilight, do_clear);
}
/* update the decor states */
fw->decor_state.parts_drawn |= draw_parts;
if (do_hilight)
{
fw->decor_state.parts_lit |= draw_parts;
}
else
{
fw->decor_state.parts_lit &= ~draw_parts;
}
fw->decor_state.parts_inverted &= ~draw_parts;
fw->decor_state.parts_inverted |= (draw_parts & pressed_parts);
return;
}
/* ---------------------------- interface functions ------------------------ */
DecorFace *border_get_border_style(
FvwmWindow *fw, Bool has_focus)
{
DecorFace *df;
if (has_focus == True)
{
df = &(GetDecor(fw, BorderStyle.active));
}
else
{
df = &(GetDecor(fw, BorderStyle.inactive));
}
return df;
}
int border_is_using_border_style(
FvwmWindow *fw, Bool has_focus)
{
ButtonState bs;
int is_pressed;
int is_toggled;
int i;
/* title */
is_pressed = (FW_W_TITLE(fw) == PressedW);
bs = border_flags_to_button_state(is_pressed, has_focus, 0);
if (DFS_USE_BORDER_STYLE(TB_STATE(GetDecor(fw, titlebar))[bs].style))
{
return 1;
}
for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
if (FW_W_BUTTON(fw, i) == None)
{
continue;
}
is_pressed = (FW_W_BUTTON(fw, i) == PressedW);
is_toggled = (is_button_toggled(fw, i) == True);
bs = border_flags_to_button_state(
is_pressed, (has_focus == True), is_toggled);
if (DFS_USE_BORDER_STYLE(
TB_STATE(GetDecor(fw, buttons[i]))[bs].style))
{
return 1;
}
}
return 0;
}
int border_context_to_parts(
int context)
{
if (context == C_FRAME || context == C_SIDEBAR ||
context == (C_FRAME | C_SIDEBAR))
{
return PART_FRAME;
}
else if (context == C_F_TOPLEFT)
{
return PART_BORDER_NW;
}
else if (context == C_F_TOPRIGHT)
{
return PART_BORDER_NE;
}
else if (context == C_F_BOTTOMLEFT)
{
return PART_BORDER_SW;
}
else if (context == C_F_BOTTOMRIGHT)
{
return PART_BORDER_SE;
}
else if (context == C_SB_LEFT)
{
return PART_BORDER_W;
}
else if (context == C_SB_RIGHT)
{
return PART_BORDER_E;
}
else if (context == C_SB_TOP)
{
return PART_BORDER_N;
}
else if (context == C_SB_BOTTOM)
{
return PART_BORDER_S;
}
else if (context == C_TITLE)
{
return PART_TITLE;
}
else if (context & (C_LALL | C_RALL))
{
return PART_BUTTONS;
}
return PART_NONE;
}
void border_get_part_geometry(
FvwmWindow *fw, window_parts part, rectangle *sidebar_g,
rectangle *ret_g, Window *ret_w)
{
int bw;
bw = fw->boundary_width;
/* ret_g->x and ret->y is just an offset relatively to the w,
* maybe we can take the relief in account? */
switch (part)
{
case PART_BORDER_N:
ret_g->x = sidebar_g->x;
ret_g->y = 0;
*ret_w = FW_W_SIDE(fw, 0);
break;
case PART_BORDER_E:
ret_g->x = 2 * sidebar_g->x + sidebar_g->width - bw;
ret_g->y = sidebar_g->y;
*ret_w = FW_W_SIDE(fw, 1);
break;
case PART_BORDER_S:
ret_g->x = sidebar_g->x;
ret_g->y = 2 * sidebar_g->y + sidebar_g->height - bw;
*ret_w = FW_W_SIDE(fw, 2);
break;
case PART_BORDER_W:
ret_g->x = 0;
ret_g->y = sidebar_g->y;
*ret_w = FW_W_SIDE(fw, 3);
break;
case PART_BORDER_NW:
ret_g->x = 0;
ret_g->y = 0;
*ret_w = FW_W_CORNER(fw, 0);
break;
case PART_BORDER_NE:
ret_g->x = sidebar_g->x + sidebar_g->width;
ret_g->y = 0;
*ret_w = FW_W_CORNER(fw, 1);
break;
case PART_BORDER_SW:
ret_g->x = 0;
ret_g->y = sidebar_g->y + sidebar_g->height;
*ret_w = FW_W_CORNER(fw, 2);
break;
case PART_BORDER_SE:
ret_g->x = sidebar_g->x + sidebar_g->width;
ret_g->y = sidebar_g->y + sidebar_g->height;
*ret_w = FW_W_CORNER(fw, 3);
break;
default:
break;
}
switch (part)
{
case PART_BORDER_N:
case PART_BORDER_S:
ret_g->width = sidebar_g->width;
ret_g->height = bw;
break;
case PART_BORDER_E:
case PART_BORDER_W:
ret_g->width = bw;
ret_g->height = sidebar_g->height;
break;
case PART_BORDER_NW:
case PART_BORDER_NE:
case PART_BORDER_SW:
case PART_BORDER_SE:
ret_g->width = sidebar_g->x;
ret_g->height = sidebar_g->y;
break;
default:
return;
}
return;
}
int get_button_number(int context)
{
int i;
for (i = 0; (C_L1 << i) & (C_LALL | C_RALL); i++)
{
if (context & (C_L1 << i))
{
return i;
}
}
return -1;
}
void border_draw_decorations(
FvwmWindow *fw, window_parts draw_parts, Bool has_focus, Bool do_force,
clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g)
{
common_decorations_type cd;
Bool do_redraw_titlebar = False;
window_parts pressed_parts;
window_parts force_parts;
int context;
int item;
if (fw == NULL)
{
return;
}
if (WAS_NEVER_DRAWN(fw))
{
/* force drawing everything */
do_force = True;
draw_parts = PART_ALL;
SET_WAS_NEVER_DRAWN(fw, 0);
}
memset(&cd, 0, sizeof(cd));
/* can't compare with True here, old code calls this with value "2" */
if (do_force != False)
{
force_parts = draw_parts;
}
else
{
force_parts = PART_NONE;
}
if (has_focus)
{
/* don't re-draw just for kicks */
if (Scr.Hilite != fw && Scr.Hilite != NULL)
{
FvwmWindow *t = Scr.Hilite;
Scr.Hilite = NULL;
/* make sure that the previously highlighted
* window got unhighlighted */
border_draw_decorations(
t, PART_ALL, False, True, CLEAR_ALL, NULL,
NULL);
}
Scr.Hilite = fw;
}
else if (fw == Scr.Hilite)
{
Scr.Hilite = NULL;
}
if (fw->Desk != Scr.CurrentDesk)
{
return;
}
if (IS_ICONIFIED(fw))
{
DrawIconWindow(fw, True, True, True, False, NULL);
return;
}
/* calculate some values and flags */
if ((draw_parts & PART_TITLEBAR) && HAS_TITLE(fw))
{
do_redraw_titlebar = True;
}
get_common_decorations(
&cd, fw, draw_parts, has_focus, False, do_redraw_titlebar);
/* redraw */
context = frame_window_id_to_context(fw, PressedW, &item);
if ((context & (C_LALL | C_RALL)) == 0)
{
item = -1;
}
pressed_parts = border_context_to_parts(context);
if (new_g == NULL)
{
new_g = &fw->g.frame;
}
if (do_redraw_titlebar)
{
border_draw_titlebar(
&cd, fw, pressed_parts & PART_TITLEBAR, item,
force_parts & PART_TITLEBAR,
clear_parts, old_g, new_g, has_focus);
}
if (draw_parts & PART_FRAME)
{
Pixmap save_pix = cd.dynamic_cd.frame_pixmap;
memset(&cd, 0, sizeof(cd));
get_common_decorations(
&cd, fw, draw_parts, has_focus, True, True);
cd.dynamic_cd.frame_pixmap = save_pix;
border_draw_border_parts(
&cd, fw,
(pressed_parts & (PART_FRAME | PART_HANDLES)),
(force_parts & (PART_FRAME | PART_HANDLES)),
clear_parts, old_g, new_g, has_focus);
}
if (cd.dynamic_cd.frame_pixmap != None)
{
XFreePixmap(dpy, cd.dynamic_cd.frame_pixmap);
}
return;
}
void border_undraw_decorations(
FvwmWindow *fw)
{
memset(&fw->decor_state, 0, sizeof(fw->decor_state));
return;
}
/*
*
* redraw the decoration when style change
*
*/
void border_redraw_decorations(
FvwmWindow *fw)
{
FvwmWindow *u = Scr.Hilite;
/* domivogt (6-Jun-2000): Don't check if the window is visible here.
* If we do, some updates are not applied and when the window becomes
* visible again, the X Server may not redraw the window. */
border_draw_decorations(
fw, PART_ALL, (Scr.Hilite == fw), True, CLEAR_ALL, NULL, NULL);
Scr.Hilite = u;
return;
}
/*
*
* get the the root transparent parts of the decoration
*
*/
unsigned int border_get_transparent_decorations_part(FvwmWindow *fw)
{
DecorFace *df,*tdf;
unsigned int draw_parts = PART_NONE;
int i;
window_parts pressed_parts;
int context;
int item;
border_titlebar_state tbstate;
Bool title_use_borderstyle = False;
Bool buttons_use_borderstyle = False;
Bool buttons_use_titlestyle = False;
context = frame_window_id_to_context(fw, PressedW, &item);
if ((context & (C_LALL | C_RALL)) == 0)
{
item = -1;
}
pressed_parts = border_context_to_parts(context);
memset(&tbstate, 0, sizeof(tbstate));
border_get_titlebar_descr_state(
fw, pressed_parts & PART_TITLEBAR, item,
CLEAR_ALL, (Scr.Hilite == fw), &tbstate);
for(i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++)
{
df = &TB_STATE(GetDecor(fw, buttons[i]))[tbstate.bstate[i]];
if (DFS_USE_TITLE_STYLE(df->style))
{
buttons_use_titlestyle = True;
}
if (DFS_USE_BORDER_STYLE(df->style))
{
buttons_use_borderstyle = True;
}
for(tdf = df; tdf != NULL; tdf = tdf->next)
{
if (DFS_FACE_TYPE(tdf->style) == ColorsetButton &&
CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs))
{
draw_parts |= PART_BUTTONS;
break;
}
}
}
df = &TB_STATE(GetDecor(fw, titlebar))[tbstate.tstate];
if (DFS_USE_BORDER_STYLE(df->style))
{
title_use_borderstyle = True;
}
for(tdf = df; tdf != NULL; tdf = tdf->next)
{
if (DFS_FACE_TYPE(tdf->style) == ColorsetButton &&
CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs))
{
draw_parts |= PART_TITLE;
break;
}
else if (DFS_FACE_TYPE(tdf->style) == MultiPixmap)
{
int i;
for (i = 0; i < TBMP_NUM_PIXMAPS; i++)
{
if (CSET_IS_TRANSPARENT_ROOT(
tdf->u.mp.acs[i].cs))
{
draw_parts |= PART_TITLE;
break;
}
}
}
}
df = border_get_border_style(fw, (Scr.Hilite == fw));
if (DFS_FACE_TYPE(df->style) == ColorsetButton &&
CSET_IS_TRANSPARENT_ROOT(df->u.acs.cs))
{
draw_parts |= PART_FRAME|PART_HANDLES;
}
if (draw_parts & PART_FRAME)
{
if (title_use_borderstyle)
{
draw_parts |= PART_TITLE;
}
if (buttons_use_borderstyle)
{
draw_parts |= PART_BUTTONS;
}
}
if ((draw_parts & PART_TITLE) && buttons_use_titlestyle)
{
draw_parts |= PART_BUTTONS;
}
#if 0
fprintf(stderr,"Transparant Part: %u\n", draw_parts);
#endif
return draw_parts;
}
/* ---------------------------- builtin commands --------------------------- */
/*
*
* Sets the allowed button states
*
*/
void CMD_ButtonState(F_CMD_ARGS)
{
char *token;
while ((token = PeekToken(action, &action)))
{
static char first = True;
if (!token && first)
{
Scr.gs.use_active_down_buttons =
DEFAULT_USE_ACTIVE_DOWN_BUTTONS;
Scr.gs.use_inactive_buttons =
DEFAULT_USE_INACTIVE_BUTTONS;
Scr.gs.use_inactive_down_buttons =
DEFAULT_USE_INACTIVE_DOWN_BUTTONS;
return;
}
first = False;
if (StrEquals("activedown", token))
{
Scr.gs.use_active_down_buttons = ParseToggleArgument(
action, &action,
DEFAULT_USE_ACTIVE_DOWN_BUTTONS, True);
}
else if (StrEquals("inactive", token))
{
Scr.gs.use_inactive_buttons = ParseToggleArgument(
action, &action,
DEFAULT_USE_INACTIVE_BUTTONS, True);
}
else if (StrEquals("inactivedown", token))
{
Scr.gs.use_inactive_down_buttons = ParseToggleArgument(
action, &action,
DEFAULT_USE_INACTIVE_DOWN_BUTTONS, True);
}
else
{
Scr.gs.use_active_down_buttons =
DEFAULT_USE_ACTIVE_DOWN_BUTTONS;
Scr.gs.use_inactive_buttons =
DEFAULT_USE_INACTIVE_BUTTONS;
Scr.gs.use_inactive_down_buttons =
DEFAULT_USE_INACTIVE_DOWN_BUTTONS;
fvwm_msg(ERR, "cmd_button_state",
"Unknown button state %s", token);
return;
}
}
return;
}
/*
*
* Sets the border style (veliaa@rpi.edu)
*
*/
void CMD_BorderStyle(F_CMD_ARGS)
{
char *parm;
char *prev;
#ifdef USEDECOR
FvwmDecor *decor = Scr.cur_decor ? Scr.cur_decor : &Scr.DefaultDecor;
#else
FvwmDecor *decor = &Scr.DefaultDecor;
#endif
Scr.flags.do_need_window_update = 1;
decor->flags.has_changed = 1;
for (prev = action; (parm = PeekToken(action, &action)); prev = action)
{
if (StrEquals(parm, "active") || StrEquals(parm, "inactive"))
{
int len;
char *end, *tmp;
DecorFace tmpdf, *df;
memset(&tmpdf.style, 0, sizeof(tmpdf.style));
DFS_FACE_TYPE(tmpdf.style) = SimpleButton;
tmpdf.next = NULL;
if (FMiniIconsSupported)
{
tmpdf.u.p = NULL;
}
if (StrEquals(parm,"active"))
{
df = &decor->BorderStyle.active;
}
else
{
df = &decor->BorderStyle.inactive;
}
df->flags.has_changed = 1;
while (isspace(*action))
{
++action;
}
if (*action != '(')
{
if (!*action)
{
fvwm_msg(
ERR, "SetBorderStyle",
"error in %s border"
" specification", parm);
return;
}
while (isspace(*action))
{
++action;
}
if (ReadDecorFace(action, &tmpdf,-1,True))
{
FreeDecorFace(dpy, df);
*df = tmpdf;
}
break;
}
end = strchr(++action, ')');
if (!end)
{
fvwm_msg(
ERR, "SetBorderStyle",
"error in %s border specification",
parm);
return;
}
len = end - action + 1;
tmp = safemalloc(len);
strncpy(tmp, action, len - 1);
tmp[len - 1] = 0;
ReadDecorFace(tmp, df,-1,True);
free(tmp);
action = end + 1;
}
else if (strcmp(parm,"--")==0)
{
if (ReadDecorFace(
prev, &decor->BorderStyle.active,-1,True))
{
ReadDecorFace(
prev, &decor->BorderStyle.inactive, -1,
False);
}
decor->BorderStyle.active.flags.has_changed = 1;
decor->BorderStyle.inactive.flags.has_changed = 1;
break;
}
else
{
DecorFace tmpdf;
memset(&tmpdf.style, 0, sizeof(tmpdf.style));
DFS_FACE_TYPE(tmpdf.style) = SimpleButton;
tmpdf.next = NULL;
if (FMiniIconsSupported)
{
tmpdf.u.p = NULL;
}
if (ReadDecorFace(prev, &tmpdf,-1,True))
{
FreeDecorFace(dpy,&decor->BorderStyle.active);
decor->BorderStyle.active = tmpdf;
ReadDecorFace(
prev, &decor->BorderStyle.inactive, -1,
False);
decor->BorderStyle.active.flags.has_changed = 1;
decor->BorderStyle.inactive.flags.has_changed =
1;
}
break;
}
}
return;
}
syntax highlighted by Code2HTML, v. 0.9.1