1612 lines
46 KiB
C
1612 lines
46 KiB
C
/****************************************************************************
|
|
* 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
|
|
****************************************************************************/
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* fvwm window border drawing code
|
|
*
|
|
***********************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
|
|
#include "fvwm.h"
|
|
#include "misc.h"
|
|
#include "parse.h"
|
|
#include "screen.h"
|
|
#include "module.h"
|
|
|
|
#ifdef SHAPE
|
|
#include <X11/extensions/shape.h>
|
|
#endif
|
|
|
|
void DrawButton(FvwmWindow *t,
|
|
Window win,
|
|
int W,
|
|
int H,
|
|
ButtonFace *bf,
|
|
GC ReliefGC, GC ShadowGC,
|
|
Boolean inverted,
|
|
int stateflags);
|
|
|
|
#ifdef VECTOR_BUTTONS
|
|
void DrawLinePattern(Window win,
|
|
GC ReliefGC,
|
|
GC ShadowGC,
|
|
struct vector_coords *coords,
|
|
int w, int h);
|
|
#endif
|
|
|
|
/* macro rules to get button state */
|
|
#if defined(ACTIVEDOWN_BTNS) && defined(INACTIVE_BTNS)
|
|
#define GetButtonState(window) \
|
|
(onoroff ? ((PressedW == (window)) ? ActiveDown : ActiveUp) \
|
|
: Inactive)
|
|
#else
|
|
#ifdef ACTIVEDOWN_BTNS
|
|
#define GetButtonState(window) \
|
|
((PressedW == (window)) ? ActiveDown : ActiveUp)
|
|
#endif
|
|
#ifdef INACTIVE_BTNS
|
|
#define GetButtonState(window) (onoroff ? ActiveUp : Inactive)
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(ACTIVEDOWN_BTNS) && !defined(INACTIVE_BTNS)
|
|
#define GetButtonState(window) ActiveUp
|
|
#endif
|
|
|
|
/* macro to change window background color/pixmap */
|
|
#define ChangeWindowColor(window,valuemask) { \
|
|
if(NewColor) \
|
|
{ \
|
|
XChangeWindowAttributes(dpy,window,valuemask, &attributes); \
|
|
XClearWindow(dpy,window); \
|
|
} \
|
|
}
|
|
|
|
extern Window PressedW;
|
|
XGCValues Globalgcv;
|
|
unsigned long Globalgcm;
|
|
/****************************************************************************
|
|
*
|
|
* Redraws the windows borders
|
|
*
|
|
****************************************************************************/
|
|
void SetBorder (FvwmWindow *t, Bool onoroff,Bool force,Bool Mapped,
|
|
Window expose_win)
|
|
{
|
|
int y, i, x;
|
|
GC ReliefGC,ShadowGC;
|
|
Pixel BorderColor,BackColor;
|
|
Pixmap BackPixmap,TextColor;
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
Pixmap TexturePixmap = None;
|
|
XSetWindowAttributes notex_attributes;
|
|
unsigned long notex_valuemask;
|
|
#endif
|
|
Bool NewColor = False;
|
|
XSetWindowAttributes attributes;
|
|
unsigned long valuemask;
|
|
static unsigned int corners[4];
|
|
Window w;
|
|
|
|
corners[0] = TOP_HILITE | LEFT_HILITE;
|
|
corners[1] = TOP_HILITE | RIGHT_HILITE;
|
|
corners[2] = BOTTOM_HILITE | LEFT_HILITE;
|
|
corners[3] = BOTTOM_HILITE | RIGHT_HILITE;
|
|
|
|
if(!t)
|
|
return;
|
|
|
|
if (onoroff)
|
|
{
|
|
/* don't re-draw just for kicks */
|
|
if((!force)&&(Scr.Hilite == t))
|
|
return;
|
|
|
|
if(Scr.Hilite != t)
|
|
NewColor = True;
|
|
|
|
/* make sure that the previously highlighted window got unhighlighted */
|
|
if((Scr.Hilite != t)&&(Scr.Hilite != NULL))
|
|
SetBorder(Scr.Hilite,False,False,True,None);
|
|
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
/* are we using textured borders? */
|
|
if ((GetDecor(t,BorderStyle.active.style)
|
|
& ButtonFaceTypeMask) == TiledPixmapButton)
|
|
TexturePixmap = GetDecor(t,BorderStyle.active.u.p->picture);
|
|
#endif
|
|
|
|
/* set the keyboard focus */
|
|
if((Mapped)&&(t->flags&MAPPED)&&(Scr.Hilite != t))
|
|
w = t->w;
|
|
else if((t->flags&ICONIFIED)&&
|
|
(Scr.Hilite !=t)&&(!(t->flags &SUPPRESSICON)))
|
|
w = t->icon_w;
|
|
Scr.Hilite = t;
|
|
|
|
TextColor = GetDecor(t,HiColors.fore);
|
|
BackPixmap= Scr.gray_pixmap;
|
|
BackColor = GetDecor(t,HiColors.back);
|
|
ReliefGC = GetDecor(t,HiReliefGC);
|
|
ShadowGC = GetDecor(t,HiShadowGC);
|
|
BorderColor = GetDecor(t,HiRelief.back);
|
|
}
|
|
else
|
|
{
|
|
/* don't re-draw just for kicks */
|
|
if((!force)&&(Scr.Hilite != t))
|
|
return;
|
|
|
|
if(Scr.Hilite == t)
|
|
{
|
|
Scr.Hilite = NULL;
|
|
NewColor = True;
|
|
}
|
|
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
if ((GetDecor(t,BorderStyle.inactive.style)
|
|
& ButtonFaceTypeMask) == TiledPixmapButton)
|
|
TexturePixmap = GetDecor(t,BorderStyle.inactive.u.p->picture);
|
|
#endif
|
|
|
|
TextColor =t->TextPixel;
|
|
BackPixmap = Scr.light_gray_pixmap;
|
|
if(t->flags & STICKY)
|
|
BackPixmap = Scr.sticky_gray_pixmap;
|
|
BackColor = t->BackPixel;
|
|
Globalgcv.foreground = t->ReliefPixel;
|
|
Globalgcm = GCForeground;
|
|
XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv);
|
|
ReliefGC = Scr.ScratchGC1;
|
|
|
|
Globalgcv.foreground = t->ShadowPixel;
|
|
XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv);
|
|
ShadowGC = Scr.ScratchGC2;
|
|
BorderColor = t->ShadowPixel;
|
|
}
|
|
|
|
if(t->flags & ICONIFIED)
|
|
{
|
|
DrawIconWindow(t);
|
|
return;
|
|
}
|
|
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
valuemask =
|
|
notex_valuemask =
|
|
CWBorderPixel;
|
|
attributes.border_pixel =
|
|
notex_attributes.border_pixel =
|
|
BorderColor;
|
|
#else
|
|
valuemask = CWBorderPixel;
|
|
attributes.border_pixel = BorderColor;
|
|
#endif
|
|
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
if (TexturePixmap)
|
|
{
|
|
attributes.background_pixmap = TexturePixmap;
|
|
valuemask |= CWBackPixmap;
|
|
if (Scr.d_depth < 2) {
|
|
notex_attributes.background_pixmap = BackPixmap;
|
|
notex_valuemask |= CWBackPixmap;
|
|
} else {
|
|
notex_attributes.background_pixel = BackColor;
|
|
notex_valuemask |= CWBackPixel;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if (Scr.d_depth < 2)
|
|
{
|
|
attributes.background_pixmap = BackPixmap;
|
|
valuemask |= CWBackPixmap;
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
notex_attributes.background_pixmap = BackPixmap;
|
|
notex_valuemask |= CWBackPixmap;
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
attributes.background_pixel = BackColor;
|
|
valuemask |= CWBackPixel;
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
notex_attributes.background_pixel = BackColor;
|
|
notex_valuemask |= CWBackPixel;
|
|
#endif
|
|
}
|
|
|
|
if(t->flags & (TITLE|BORDER))
|
|
{
|
|
XSetWindowBorder(dpy,t->Parent,BorderColor);
|
|
XSetWindowBorder(dpy,t->frame,BorderColor);
|
|
}
|
|
if(t->flags & TITLE)
|
|
{
|
|
ChangeWindowColor(t->title_w,valuemask);
|
|
for(i=0;i<Scr.nr_left_buttons;++i)
|
|
{
|
|
if(t->left_w[i] != None)
|
|
{
|
|
enum ButtonState bs = GetButtonState(t->left_w[i]);
|
|
ButtonFace *bf = &GetDecor(t,left_buttons[i].state[bs]);
|
|
#if !(defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE))
|
|
ChangeWindowColor(t->left_w[i],valuemask);
|
|
#endif
|
|
if(flush_expose(t->left_w[i])||(expose_win == t->left_w[i])||
|
|
(expose_win == None)
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
|| NewColor
|
|
#endif
|
|
)
|
|
{
|
|
int inverted = PressedW == t->left_w[i];
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
if (bf->style & UseBorderStyle)
|
|
XChangeWindowAttributes(dpy, t->left_w[i],
|
|
valuemask, &attributes);
|
|
else
|
|
XChangeWindowAttributes(dpy, t->left_w[i],
|
|
notex_valuemask, ¬ex_attributes);
|
|
XClearWindow(dpy, t->left_w[i]);
|
|
#endif
|
|
#ifdef EXTENDED_TITLESTYLE
|
|
if (bf->style & UseTitleStyle) {
|
|
ButtonFace *tsbf = &GetDecor(t,titlebar.state[bs]);
|
|
#ifdef MULTISTYLE
|
|
for (; tsbf; tsbf = tsbf->next)
|
|
#endif
|
|
DrawButton(t, t->left_w[i],
|
|
t->title_height, t->title_height,
|
|
tsbf, ReliefGC, ShadowGC,
|
|
inverted, GetDecor(t,left_buttons[i].flags));
|
|
}
|
|
#endif /* EXTENDED_TITLESTYLE */
|
|
#ifdef MULTISTYLE
|
|
for (; bf; bf = bf->next)
|
|
#endif
|
|
DrawButton(t, t->left_w[i],
|
|
t->title_height, t->title_height,
|
|
bf, ReliefGC, ShadowGC,
|
|
inverted, GetDecor(t,left_buttons[i].flags));
|
|
|
|
if (!(GetDecor(t,left_buttons[i].state[bs].style) & FlatButton)) {
|
|
if (GetDecor(t,left_buttons[i].state[bs].style) & SunkButton)
|
|
RelieveWindow(t,t->left_w[i],0,0,
|
|
t->title_height, t->title_height,
|
|
(inverted ? ReliefGC : ShadowGC),
|
|
(inverted ? ShadowGC : ReliefGC),
|
|
BOTTOM_HILITE);
|
|
else
|
|
RelieveWindow(t,t->left_w[i],0,0,
|
|
t->title_height, t->title_height,
|
|
(inverted ? ShadowGC : ReliefGC),
|
|
(inverted ? ReliefGC : ShadowGC),
|
|
BOTTOM_HILITE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for(i=0;i<Scr.nr_right_buttons;++i)
|
|
{
|
|
if(t->right_w[i] != None)
|
|
{
|
|
enum ButtonState bs = GetButtonState(t->right_w[i]);
|
|
ButtonFace *bf = &GetDecor(t,right_buttons[i].state[bs]);
|
|
#if !(defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE))
|
|
ChangeWindowColor(t->right_w[i],valuemask);
|
|
#endif
|
|
if(flush_expose(t->right_w[i])||(expose_win==t->right_w[i])||
|
|
(expose_win == None)
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
|| NewColor
|
|
#endif
|
|
)
|
|
{
|
|
int inverted = PressedW == t->right_w[i];
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
if (bf->style & UseBorderStyle)
|
|
XChangeWindowAttributes(dpy, t->right_w[i],
|
|
valuemask, &attributes);
|
|
else
|
|
XChangeWindowAttributes(dpy, t->right_w[i],
|
|
notex_valuemask, ¬ex_attributes);
|
|
XClearWindow(dpy, t->right_w[i]);
|
|
#endif
|
|
#ifdef EXTENDED_TITLESTYLE
|
|
if (bf->style & UseTitleStyle) {
|
|
ButtonFace *tsbf = &GetDecor(t,titlebar.state[bs]);
|
|
#ifdef MULTISTYLE
|
|
for (; tsbf; tsbf = tsbf->next)
|
|
#endif
|
|
DrawButton(t, t->right_w[i],
|
|
t->title_height, t->title_height,
|
|
tsbf, ReliefGC, ShadowGC,
|
|
inverted, GetDecor(t,right_buttons[i].flags));
|
|
}
|
|
#endif /* EXTENDED_TITLESTYLE */
|
|
#ifdef MULTISTYLE
|
|
for (; bf; bf = bf->next)
|
|
#endif
|
|
DrawButton(t, t->right_w[i],
|
|
t->title_height, t->title_height,
|
|
bf, ReliefGC, ShadowGC,
|
|
inverted, GetDecor(t,right_buttons[i].flags));
|
|
|
|
if (!(GetDecor(t,right_buttons[i].state[bs].style) & FlatButton)) {
|
|
if (GetDecor(t,right_buttons[i].state[bs].style) & SunkButton)
|
|
RelieveWindow(t,t->right_w[i],0,0,
|
|
t->title_height, t->title_height,
|
|
(inverted ? ReliefGC : ShadowGC),
|
|
(inverted ? ShadowGC : ReliefGC),
|
|
BOTTOM_HILITE);
|
|
else
|
|
RelieveWindow(t,t->right_w[i],0,0,
|
|
t->title_height, t->title_height,
|
|
(inverted ? ShadowGC : ReliefGC),
|
|
(inverted ? ReliefGC : ShadowGC),
|
|
BOTTOM_HILITE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SetTitleBar(t,onoroff, False);
|
|
|
|
}
|
|
|
|
if(t->flags & BORDER)
|
|
{
|
|
/* draw relief lines */
|
|
y= t->frame_height - 2*t->corner_width;
|
|
x = t->frame_width- 2*t->corner_width +t->bw;
|
|
|
|
for(i=0;i<4;i++)
|
|
{
|
|
int vertical = i % 2;
|
|
#ifdef BORDERSTYLE
|
|
int flags = onoroff
|
|
? GetDecor(t,BorderStyle.active.style)
|
|
: GetDecor(t,BorderStyle.inactive.style);
|
|
#endif /* BORDERSTYLE */
|
|
|
|
ChangeWindowColor(t->sides[i],valuemask);
|
|
if((flush_expose (t->sides[i]))||(expose_win == t->sides[i])||
|
|
(expose_win == None))
|
|
{
|
|
GC sgc,rgc;
|
|
|
|
sgc=ShadowGC;
|
|
rgc=ReliefGC;
|
|
if(!(t->flags & MWMButtons)&&(PressedW == t->sides[i]))
|
|
{
|
|
sgc = ReliefGC;
|
|
rgc = ShadowGC;
|
|
}
|
|
/* index side
|
|
* 0 TOP
|
|
* 1 RIGHT
|
|
* 2 BOTTOM
|
|
* 3 LEFT
|
|
*/
|
|
|
|
#ifdef BORDERSTYLE
|
|
if (flags&HiddenHandles) {
|
|
if (flags&NoInset)
|
|
RelieveWindowHH(t,t->sides[i],0,0,
|
|
((vertical)?t->boundary_width:x),
|
|
((vertical)?y:t->boundary_width),
|
|
rgc, sgc, vertical
|
|
? (i == 3 ? LEFT_HILITE : RIGHT_HILITE)
|
|
: (i ? BOTTOM_HILITE : TOP_HILITE),
|
|
(0x0001<<i)
|
|
);
|
|
else
|
|
RelieveWindowHH(t,t->sides[i],0,0,
|
|
((vertical)?t->boundary_width:x),
|
|
((vertical)?y:t->boundary_width),
|
|
rgc, sgc, vertical
|
|
? (LEFT_HILITE|RIGHT_HILITE)
|
|
: (TOP_HILITE|BOTTOM_HILITE),
|
|
(0x0001<<i)
|
|
);
|
|
} else
|
|
#endif /* BORDERSTYLE */
|
|
RelieveWindow(t,t->sides[i],0,0,
|
|
((i%2)?t->boundary_width:x),
|
|
((i%2)?y:t->boundary_width),
|
|
rgc, sgc, (0x0001<<i));
|
|
}
|
|
ChangeWindowColor(t->corners[i],valuemask);
|
|
if((flush_expose(t->corners[i]))||(expose_win==t->corners[i])||
|
|
(expose_win == None))
|
|
{
|
|
GC rgc,sgc;
|
|
|
|
rgc = ReliefGC;
|
|
sgc = ShadowGC;
|
|
if(!(t->flags & MWMButtons)&&(PressedW == t->corners[i]))
|
|
{
|
|
sgc = ReliefGC;
|
|
rgc = ShadowGC;
|
|
}
|
|
#ifdef BORDERSTYLE
|
|
if (flags&HiddenHandles) {
|
|
RelieveWindowHH(t,t->corners[i],0,0,t->corner_width,
|
|
((i/2)?t->corner_width+t->bw:t->corner_width),
|
|
rgc,sgc, corners[i], corners[i]);
|
|
|
|
if (!(flags&NoInset)) {
|
|
if (t->boundary_width > 1)
|
|
RelieveParts(t,i|HH_HILITE,
|
|
((i/2)?rgc:sgc),(vertical?rgc:sgc));
|
|
else
|
|
RelieveParts(t,i|HH_HILITE,
|
|
((i/2)?sgc:sgc),(vertical?sgc:sgc));
|
|
}
|
|
} else {
|
|
#endif /* ! BORDERSTYLE */
|
|
RelieveWindow(t,t->corners[i],0,0,t->corner_width,
|
|
((i/2)?t->corner_width+t->bw:t->corner_width),
|
|
rgc,sgc, corners[i]);
|
|
|
|
if(t->boundary_width > 1)
|
|
RelieveParts(t,i,((i/2)?rgc:sgc),(vertical?rgc:sgc));
|
|
else
|
|
RelieveParts(t,i,((i/2)?sgc:sgc),(vertical?sgc:sgc));
|
|
#ifdef BORDERSTYLE
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else /* no decorative border */
|
|
{
|
|
/* for mono - put a black border on
|
|
* for color, make it the color of the decoration background */
|
|
if(t->boundary_width < 2)
|
|
{
|
|
flush_expose (t->frame);
|
|
if(Scr.d_depth <2)
|
|
{
|
|
XSetWindowBorder(dpy,t->frame,TextColor);
|
|
XSetWindowBorder(dpy,t->Parent,TextColor);
|
|
XSetWindowBackgroundPixmap(dpy,t->frame,BackPixmap);
|
|
XClearWindow(dpy,t->frame);
|
|
XSetWindowBackgroundPixmap(dpy,t->Parent,BackPixmap);
|
|
XClearWindow(dpy,t->Parent);
|
|
}
|
|
else
|
|
{
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
XSetWindowBackgroundPixmap(dpy,t->frame,TexturePixmap);
|
|
#endif
|
|
XSetWindowBorder(dpy,t->frame,BorderColor);
|
|
XClearWindow(dpy,t->frame);
|
|
XSetWindowBackground(dpy,t->Parent,BorderColor);
|
|
XSetWindowBorder(dpy,t->Parent,BorderColor);
|
|
XClearWindow(dpy,t->Parent);
|
|
XSetWindowBorder(dpy,t->w,BorderColor);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GC rgc,sgc;
|
|
|
|
XSetWindowBorder(dpy,t->Parent,BorderColor);
|
|
XSetWindowBorder(dpy,t->frame,BorderColor);
|
|
|
|
rgc=ReliefGC;
|
|
sgc=ShadowGC;
|
|
if(!(t->flags & MWMButtons)&&(PressedW == t->frame))
|
|
{
|
|
sgc=ReliefGC;
|
|
rgc=ShadowGC;
|
|
}
|
|
ChangeWindowColor(t->frame, valuemask);
|
|
if((flush_expose(t->frame))||(expose_win == t->frame)||
|
|
(expose_win == None))
|
|
{
|
|
if(t->boundary_width > 2)
|
|
{
|
|
RelieveWindow(t,t->frame,t->boundary_width-1 - t->bw,
|
|
t->boundary_width-1-t->bw,
|
|
t->frame_width-
|
|
(t->boundary_width<<1)+2+3*t->bw,
|
|
t->frame_height-
|
|
(t->boundary_width<<1)+2+3*t->bw,
|
|
sgc,rgc,
|
|
TOP_HILITE|LEFT_HILITE|RIGHT_HILITE|
|
|
BOTTOM_HILITE);
|
|
RelieveWindow(t,t->frame,0,0,t->frame_width+t->bw,
|
|
t->frame_height+t->bw,rgc,sgc,
|
|
TOP_HILITE|LEFT_HILITE|RIGHT_HILITE|
|
|
BOTTOM_HILITE);
|
|
}
|
|
else
|
|
{
|
|
RelieveWindow(t,t->frame,0,0,t->frame_width+t->bw,
|
|
t->frame_height+t->bw,rgc,rgc,
|
|
TOP_HILITE|LEFT_HILITE|RIGHT_HILITE|
|
|
BOTTOM_HILITE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XSetWindowBackground(dpy,t->Parent,BorderColor);
|
|
}
|
|
}
|
|
}
|
|
/* Sync to make the border-color change look fast! */
|
|
XSync(dpy,0);
|
|
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Redraws buttons (veliaa@rpi.edu)
|
|
*
|
|
****************************************************************************/
|
|
void DrawButton(FvwmWindow *t, Window win, int w, int h,
|
|
ButtonFace *bf, GC ReliefGC, GC ShadowGC,
|
|
Boolean inverted, int stateflags)
|
|
{
|
|
register int type = bf->style & ButtonFaceTypeMask;
|
|
#ifdef PIXMAP_BUTTONS
|
|
Picture *p;
|
|
int border = 0;
|
|
int width, height, x, y;
|
|
#endif
|
|
|
|
switch (type)
|
|
{
|
|
case SimpleButton:
|
|
break;
|
|
|
|
case SolidButton:
|
|
XSetWindowBackground(dpy, win, bf->u.back);
|
|
flush_expose(win);
|
|
XClearWindow(dpy,win);
|
|
break;
|
|
|
|
#ifdef VECTOR_BUTTONS
|
|
case VectorButton:
|
|
if((t->flags & MWMButtons)
|
|
&& (stateflags & MWMDecorMaximize)
|
|
&& (t->flags & MAXIMIZED))
|
|
DrawLinePattern(win,
|
|
ShadowGC, ReliefGC,
|
|
&bf->vector,
|
|
w, h);
|
|
else
|
|
DrawLinePattern(win,
|
|
ReliefGC, ShadowGC,
|
|
&bf->vector,
|
|
w, h);
|
|
break;
|
|
#endif /* VECTOR_BUTTONS */
|
|
|
|
#ifdef PIXMAP_BUTTONS
|
|
#ifdef MINI_ICONS
|
|
case MiniIconButton:
|
|
case PixmapButton:
|
|
if (type == PixmapButton)
|
|
p = bf->u.p;
|
|
else {
|
|
if (!t->mini_icon)
|
|
break;
|
|
p = t->mini_icon;
|
|
}
|
|
#else
|
|
case PixmapButton:
|
|
p = bf->u.p;
|
|
#endif /* MINI_ICONS */
|
|
if (bf->style & FlatButton)
|
|
border = 0;
|
|
else
|
|
border = t->flags & MWMBorders ? 1 : 2;
|
|
width = w - border * 2; height = h - border * 2;
|
|
|
|
x = border;
|
|
if (bf->style&HOffCenter) {
|
|
if (bf->style&HRight)
|
|
x += (int)(width - p->width);
|
|
} else
|
|
x += (int)(width - p->width) / 2;
|
|
|
|
y = border;
|
|
if (bf->style&VOffCenter) {
|
|
if (bf->style&VBottom)
|
|
y += (int)(height - p->height);
|
|
} else
|
|
y += (int)(height - p->height) / 2;
|
|
|
|
if (x < border) x = border;
|
|
if (y < border) y = border;
|
|
if (width > p->width) width = p->width;
|
|
if (height > p->height) height = p->height;
|
|
if (width > w - x - border) width = w - x - border;
|
|
if (height > h - y - border) height = h - y - border;
|
|
|
|
XSetClipMask(dpy, Scr.TransMaskGC, p->mask);
|
|
XSetClipOrigin(dpy, Scr.TransMaskGC, x, y);
|
|
XCopyArea(dpy, p->picture, win, Scr.TransMaskGC,
|
|
0, 0, width, height, x, y);
|
|
break;
|
|
|
|
case TiledPixmapButton:
|
|
XSetWindowBackgroundPixmap(dpy, win, bf->u.p->picture);
|
|
flush_expose(win);
|
|
XClearWindow(dpy,win);
|
|
break;
|
|
#endif /* PIXMAP_BUTTONS */
|
|
|
|
#ifdef GRADIENT_BUTTONS
|
|
case HGradButton:
|
|
case VGradButton:
|
|
{
|
|
XRectangle bounds;
|
|
bounds.x = bounds.y = 0;
|
|
bounds.width = w;
|
|
bounds.height = h;
|
|
flush_expose(win);
|
|
|
|
#ifdef PIXMAP_BUTTONS
|
|
XSetClipMask(dpy, Scr.TransMaskGC, None);
|
|
#endif
|
|
if (type == HGradButton) {
|
|
register int i = 0, dw = bounds.width
|
|
/ bf->u.grad.npixels + 1;
|
|
while (i < bf->u.grad.npixels)
|
|
{
|
|
unsigned short x = i * bounds.width / bf->u.grad.npixels;
|
|
XSetForeground(dpy, Scr.TransMaskGC, bf->u.grad.pixels[ i++ ]);
|
|
XFillRectangle(dpy, win, Scr.TransMaskGC,
|
|
bounds.x + x, bounds.y,
|
|
dw, bounds.height);
|
|
}
|
|
} else {
|
|
register int i = 0, dh = bounds.height
|
|
/ bf->u.grad.npixels + 1;
|
|
while (i < bf->u.grad.npixels)
|
|
{
|
|
unsigned short y = i * bounds.height / bf->u.grad.npixels;
|
|
XSetForeground(dpy, Scr.TransMaskGC, bf->u.grad.pixels[ i++ ]);
|
|
XFillRectangle(dpy, win, Scr.TransMaskGC,
|
|
bounds.x, bounds.y + y,
|
|
bounds.width, dh);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
#endif /* GRADIENT_BUTTONS */
|
|
|
|
default:
|
|
fvwm_msg(ERR,"DrawButton","unknown button type");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Redraws just the title bar
|
|
*
|
|
****************************************************************************/
|
|
void SetTitleBar (FvwmWindow *t,Bool onoroff, Bool NewTitle)
|
|
{
|
|
int hor_off, w, i;
|
|
enum ButtonState title_state;
|
|
ButtonFaceStyle tb_style;
|
|
int tb_flags;
|
|
GC ReliefGC, ShadowGC, tGC;
|
|
Pixel Forecolor, BackColor;
|
|
|
|
if(!t)
|
|
return;
|
|
if(!(t->flags & TITLE))
|
|
return;
|
|
|
|
if (onoroff)
|
|
{
|
|
Forecolor = GetDecor(t,HiColors.fore);
|
|
BackColor = GetDecor(t,HiColors.back);
|
|
ReliefGC = GetDecor(t,HiReliefGC);
|
|
ShadowGC = GetDecor(t,HiShadowGC);
|
|
}
|
|
else
|
|
{
|
|
Forecolor =t->TextPixel;
|
|
BackColor = t->BackPixel;
|
|
Globalgcv.foreground = t->ReliefPixel;
|
|
Globalgcm = GCForeground;
|
|
XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv);
|
|
ReliefGC = Scr.ScratchGC1;
|
|
|
|
Globalgcv.foreground = t->ShadowPixel;
|
|
XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv);
|
|
ShadowGC = Scr.ScratchGC2;
|
|
}
|
|
if(PressedW==t->title_w)
|
|
{
|
|
tGC = ShadowGC;
|
|
ShadowGC = ReliefGC;
|
|
ReliefGC = tGC;
|
|
}
|
|
flush_expose(t->title_w);
|
|
|
|
if(t->name != (char *)NULL)
|
|
{
|
|
w=XTextWidth(GetDecor(t,WindowFont.font),t->name,strlen(t->name));
|
|
if(w > t->title_width-12)
|
|
w = t->title_width-4;
|
|
if(w < 0)
|
|
w = 0;
|
|
}
|
|
else
|
|
w = 0;
|
|
|
|
title_state = GetButtonState(t->title_w);
|
|
tb_style = GetDecor(t,titlebar.state[title_state].style);
|
|
tb_flags = GetDecor(t,titlebar.flags);
|
|
if (tb_flags & HOffCenter) {
|
|
if (tb_flags & HRight)
|
|
hor_off = t->title_width - w - 10;
|
|
else
|
|
hor_off = 10;
|
|
} else
|
|
hor_off = (t->title_width - w) / 2;
|
|
|
|
NewFontAndColor(GetDecor(t,WindowFont.font->fid),Forecolor, BackColor);
|
|
|
|
/* the next bit tries to minimize redraw based upon compilation options (veliaa@rpi.edu) */
|
|
#ifdef EXTENDED_TITLESTYLE
|
|
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
|
|
/* we need to check for UseBorderStyle for the titlebar */
|
|
{
|
|
ButtonFace *bf = onoroff
|
|
? &GetDecor(t,BorderStyle.active)
|
|
: &GetDecor(t,BorderStyle.inactive);
|
|
|
|
if ((tb_style & UseBorderStyle)
|
|
&& ((bf->style & ButtonFaceTypeMask) == TiledPixmapButton))
|
|
XSetWindowBackgroundPixmap(dpy,t->title_w,bf->u.p->picture);
|
|
}
|
|
#endif /* PIXMAP_BUTTONS && BORDERSTYLE */
|
|
XClearWindow(dpy,t->title_w);
|
|
#else /* ! EXTENDED_TITLESTYLE */
|
|
/* if no extended titlestyle, only clear when necessary */
|
|
if (NewTitle)
|
|
XClearWindow(dpy,t->title_w);
|
|
#endif /* EXTENDED_TITLESTYLE */
|
|
|
|
/* for mono, we clear an area in the title bar where the window
|
|
* title goes, so that its more legible. For color, no need */
|
|
if(Scr.d_depth<2)
|
|
{
|
|
RelieveWindow(t,t->title_w,0,0,hor_off-2,t->title_height,
|
|
ReliefGC, ShadowGC, BOTTOM_HILITE);
|
|
RelieveWindow(t,t->title_w,hor_off+w+2,0,
|
|
t->title_width - w - hor_off-2,t->title_height,
|
|
ReliefGC, ShadowGC, BOTTOM_HILITE);
|
|
XFillRectangle(dpy,t->title_w,
|
|
(PressedW==t->title_w?ShadowGC:ReliefGC),
|
|
hor_off - 2, 0, w+4,t->title_height);
|
|
|
|
XDrawLine(dpy,t->title_w,ShadowGC,hor_off+w+1,0,hor_off+w+1,
|
|
t->title_height);
|
|
if(t->name != (char *)NULL)
|
|
XDrawString (dpy, t->title_w,Scr.ScratchGC3,hor_off,
|
|
GetDecor(t,WindowFont.y)+1,
|
|
t->name, strlen(t->name));
|
|
}
|
|
else
|
|
{
|
|
#ifdef EXTENDED_TITLESTYLE
|
|
ButtonFace *bf = &GetDecor(t,titlebar.state[title_state]);
|
|
/* draw compound titlebar (veliaa@rpi.edu) */
|
|
if (PressedW == t->title_w) {
|
|
#ifdef MULTISTYLE
|
|
for (; bf; bf = bf->next)
|
|
#endif
|
|
DrawButton(t, t->title_w, t->title_width, t->title_height,
|
|
bf, ShadowGC, ReliefGC, True, 0);
|
|
} else {
|
|
#ifdef MULTISTYLE
|
|
for (; bf; bf = bf->next)
|
|
#endif
|
|
DrawButton(t, t->title_w, t->title_width, t->title_height,
|
|
bf, ReliefGC, ShadowGC, False, 0);
|
|
}
|
|
#endif /* EXTENDED_TITLESTYLE */
|
|
|
|
if (!(tb_style & FlatButton)) {
|
|
if (tb_style & SunkButton)
|
|
RelieveWindow(t,t->title_w,0,0,t->title_width,t->title_height,
|
|
ShadowGC, ReliefGC, BOTTOM_HILITE);
|
|
else
|
|
RelieveWindow(t,t->title_w,0,0,t->title_width,t->title_height,
|
|
ReliefGC, ShadowGC, BOTTOM_HILITE);
|
|
}
|
|
|
|
if(t->name != (char *)NULL)
|
|
XDrawString (dpy, t->title_w,Scr.ScratchGC3,hor_off,
|
|
GetDecor(t,WindowFont.y)+1,
|
|
t->name, strlen(t->name));
|
|
}
|
|
/* now, draw lines in title bar if it's a sticky window */
|
|
if(t->flags & STICKY || Scr.StipledTitles)
|
|
{
|
|
for(i=0 ;i< t->title_height/2-3;i+=4)
|
|
{
|
|
XDrawLine(dpy,t->title_w,ShadowGC,4,t->title_height/2 - i-1,
|
|
hor_off-6,t->title_height/2-i-1);
|
|
XDrawLine(dpy,t->title_w,ShadowGC,6+hor_off+w,t->title_height/2 -i-1,
|
|
t->title_width-5,t->title_height/2- i-1);
|
|
XDrawLine(dpy,t->title_w,ReliefGC,4,t->title_height/2 - i,
|
|
hor_off-6,t->title_height/2 - i);
|
|
XDrawLine(dpy,t->title_w,ReliefGC,6+hor_off+w,t->title_height/2-i,
|
|
t->title_width-5,t->title_height/2 - i);
|
|
|
|
XDrawLine(dpy,t->title_w,ShadowGC,4,t->title_height/2 + i-1,
|
|
hor_off-6,t->title_height/2+i-1);
|
|
XDrawLine(dpy,t->title_w,ShadowGC,6+hor_off+w,t->title_height/2+i-1,
|
|
t->title_width-5,t->title_height/2 + i-1);
|
|
XDrawLine(dpy,t->title_w,ReliefGC,4,t->title_height/2 + i,
|
|
hor_off-6,t->title_height/2 + i);
|
|
XDrawLine(dpy,t->title_w,ReliefGC,6+hor_off+w,t->title_height/2+i,
|
|
t->title_width-5,t->title_height/2 + i);
|
|
}
|
|
}
|
|
|
|
|
|
XFlush(dpy);
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Draws the relief pattern around a window
|
|
*
|
|
****************************************************************************/
|
|
void RelieveWindow(FvwmWindow *t,Window win, int x,int y,int w,int h,
|
|
GC ReliefGC, GC ShadowGC, int hilite)
|
|
{
|
|
XSegment seg[4];
|
|
int i;
|
|
int edge;
|
|
|
|
edge = 0;
|
|
if((win == t->sides[0])||(win == t->sides[1])||
|
|
(win == t->sides[2])||(win == t->sides[3]))
|
|
edge = -1;
|
|
if(win == t->corners[0])
|
|
edge = 1;
|
|
if(win == t->corners[1])
|
|
edge = 2;
|
|
if(win == t->corners[2])
|
|
edge = 3;
|
|
if(win == t->corners[3])
|
|
edge = 4;
|
|
|
|
i=0;
|
|
seg[i].x1 = x; seg[i].y1 = y;
|
|
seg[i].x2 = w+x-1; seg[i++].y2 = y;
|
|
|
|
seg[i].x1 = x; seg[i].y1 = y;
|
|
seg[i].x2 = x; seg[i++].y2 = h+y-1;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
((t->boundary_width > 3)||(edge < 1))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & TOP_HILITE))))
|
|
{
|
|
seg[i].x1 = x+1; seg[i].y1 = y+1;
|
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+1;
|
|
}
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
((t->boundary_width > 3)||(edge < 1))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & LEFT_HILITE))))
|
|
{
|
|
seg[i].x1 = x+1; seg[i].y1 = y+1;
|
|
seg[i].x2 = x+1; seg[i++].y2 = y+h-2;
|
|
}
|
|
XDrawSegments(dpy, win, ReliefGC, seg, i);
|
|
|
|
i=0;
|
|
seg[i].x1 = x; seg[i].y1 = y+h-1;
|
|
seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & BOTTOM_HILITE))))
|
|
{
|
|
seg[i].x1 = x+1; seg[i].y1 = y+h-2;
|
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2;
|
|
}
|
|
|
|
seg[i].x1 = x+w-1; seg[i].y1 = y;
|
|
seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & RIGHT_HILITE))))
|
|
{
|
|
seg[i].x1 = x+w-2; seg[i].y1 = y+1;
|
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+h-2;
|
|
}
|
|
XDrawSegments(dpy, win, ShadowGC, seg, i);
|
|
}
|
|
|
|
#ifdef BORDERSTYLE
|
|
/****************************************************************************
|
|
*
|
|
* Draws the relief pattern around a window for HiddenHandle borders
|
|
*
|
|
* (veliaa@rpi.edu)
|
|
*
|
|
****************************************************************************/
|
|
void RelieveWindowHH(FvwmWindow *t,Window win, int x,int y,int w,int h,
|
|
GC ReliefGC, GC ShadowGC, int draw, int hilite)
|
|
{
|
|
XSegment seg[4];
|
|
int i = 0;
|
|
int edge = 0, a = 0, b = 0;
|
|
|
|
if(win == t->sides[0]) {
|
|
edge = 5;
|
|
b = 1;
|
|
}
|
|
else if (win == t->sides[1]) {
|
|
a = 1;
|
|
edge = 6;
|
|
}
|
|
else if (win == t->sides[2]) {
|
|
edge = 7;
|
|
b = 1;
|
|
}
|
|
else if (win == t->sides[3]) {
|
|
edge = 8;
|
|
a = 1;
|
|
} else if (win == t->corners[0])
|
|
edge = 1;
|
|
else if (win == t->corners[1])
|
|
edge = 2;
|
|
else if (win == t->corners[2])
|
|
edge = 3;
|
|
else if (win == t->corners[3])
|
|
edge = 4;
|
|
|
|
if (draw & TOP_HILITE) {
|
|
seg[i].x1 = x; seg[i].y1 = y;
|
|
seg[i].x2 = w+x-1; seg[i++].y2 = y;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
((t->boundary_width > 3)||(edge < 1))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & TOP_HILITE))))
|
|
{
|
|
seg[i].x1 = x+((edge == 2)|| b ? 0 : 1); seg[i].y1 = y+1;
|
|
seg[i].x2 = x+w-1-((edge == 1)|| b ? 0 : 1); seg[i++].y2 = y+1;
|
|
}
|
|
}
|
|
|
|
if (draw & LEFT_HILITE) {
|
|
seg[i].x1 = x; seg[i].y1 = y;
|
|
seg[i].x2 = x; seg[i++].y2 = h+y-1;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
((t->boundary_width > 3)||(edge < 1))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & LEFT_HILITE))))
|
|
{
|
|
seg[i].x1 = x+1; seg[i].y1 = y+((edge == 3)|| a ? 0 : 1);
|
|
seg[i].x2 = x+1; seg[i++].y2 = y+h-1-((edge == 1)|| a ? 0 : 1);
|
|
}
|
|
}
|
|
XDrawSegments(dpy, win, ReliefGC, seg, i);
|
|
|
|
i=0;
|
|
|
|
if (draw & BOTTOM_HILITE) {
|
|
seg[i].x1 = x; seg[i].y1 = y+h-1;
|
|
seg[i].x2 = w+x-1; seg[i++].y2 = y+h-1;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & BOTTOM_HILITE))))
|
|
{
|
|
seg[i].x1 = x+(b ||(edge == 4) ? 0 : 1); seg[i].y1 = y+h-2;
|
|
seg[i].x2 = x+w-((edge == 3) ? 0 : 1); seg[i++].y2 = y+h-2;
|
|
}
|
|
}
|
|
|
|
if (draw & RIGHT_HILITE) {
|
|
seg[i].x1 = x+w-1; seg[i].y1 = y;
|
|
seg[i].x2 = x+w-1; seg[i++].y2 = y+h-1;
|
|
|
|
if(((t->boundary_width > 2)||(edge == 0))&&
|
|
(!(t->flags & MWMBorders)||
|
|
(((edge==0)||(t->boundary_width > 3))&&(hilite & RIGHT_HILITE))))
|
|
{
|
|
seg[i].x1 = x+w-2; seg[i].y1 = y+(a ||(edge == 4) ? 0 : 1);
|
|
seg[i].x2 = x+w-2; seg[i++].y2 = y+h-1-((edge == 2)|| a ? 0 : 1);
|
|
}
|
|
}
|
|
XDrawSegments(dpy, win, ShadowGC, seg, i);
|
|
}
|
|
#endif /* BORDERSTYLE */
|
|
|
|
void RelieveParts(FvwmWindow *t,int i,GC hor, GC vert)
|
|
{
|
|
XSegment seg[2];
|
|
int n = 0, hh = i & HH_HILITE;
|
|
i &= FULL_HILITE;
|
|
|
|
if((t->flags & MWMBorders)||(t->boundary_width < 3))
|
|
{
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
seg[0].x1 = t->boundary_width-1;
|
|
seg[0].x2 = t->corner_width;
|
|
seg[0].y1 = t->boundary_width-1;
|
|
seg[0].y2 = t->boundary_width-1;
|
|
n=1;
|
|
break;
|
|
case 1:
|
|
seg[0].x1 = 0;
|
|
seg[0].x2 = t->corner_width - t->boundary_width /* -1*/ ;
|
|
seg[0].y1 = t->boundary_width-1;
|
|
seg[0].y2 = t->boundary_width-1;
|
|
n=1;
|
|
break;
|
|
case 2:
|
|
seg[0].x1 = t->boundary_width-1;
|
|
seg[0].x2 = t->corner_width - (hh ? 1 : 2);
|
|
seg[0].y1 = t->corner_width - t->boundary_width+t->bw;
|
|
seg[0].y2 = t->corner_width - t->boundary_width+t->bw;
|
|
n=1;
|
|
break;
|
|
case 3:
|
|
seg[0].x1 = 0;
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
seg[0].y1 = t->corner_width - t->boundary_width+t->bw;
|
|
seg[0].y2 = t->corner_width - t->boundary_width+t->bw;
|
|
n=1;
|
|
break;
|
|
}
|
|
XDrawSegments(dpy, t->corners[i], hor, seg, n);
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
seg[0].y1 = t->boundary_width-1;
|
|
seg[0].y2 = t->corner_width;
|
|
seg[0].x1 = t->boundary_width-1;
|
|
seg[0].x2 = t->boundary_width-1;
|
|
n=1;
|
|
break;
|
|
case 1:
|
|
seg[0].y1 = t->boundary_width -1;
|
|
seg[0].y2 = t->corner_width - (hh ? 0 : 2);
|
|
seg[0].x1 = t->corner_width - t->boundary_width;
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
n=1;
|
|
break;
|
|
case 2:
|
|
seg[0].y1 = 0;
|
|
seg[0].y2 = t->corner_width - t->boundary_width;
|
|
seg[0].x1 = t->boundary_width-1;
|
|
seg[0].x2 = t->boundary_width-1;
|
|
n=1;
|
|
break;
|
|
case 3:
|
|
seg[0].y1 = 0;
|
|
seg[0].y2 = t->corner_width - t->boundary_width + t->bw;
|
|
seg[0].x1 = t->corner_width - t->boundary_width;
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
n=1;
|
|
break;
|
|
}
|
|
XDrawSegments(dpy, t->corners[i], vert, seg, 1);
|
|
}
|
|
else
|
|
{
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
seg[0].x1 = t->boundary_width-2;
|
|
seg[0].x2 = t->corner_width;
|
|
seg[0].y1 = t->boundary_width-2;
|
|
seg[0].y2 = t->boundary_width-2;
|
|
|
|
seg[1].x1 = t->boundary_width-2;
|
|
seg[1].x2 = t->corner_width;
|
|
seg[1].y1 = t->boundary_width-1;
|
|
seg[1].y2 = t->boundary_width-1;
|
|
n=2;
|
|
break;
|
|
case 1:
|
|
seg[0].x1 = (hh ? 0 : 1);
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
seg[0].y1 = t->boundary_width-2;
|
|
seg[0].y2 = t->boundary_width-2;
|
|
|
|
seg[1].x1 = 0;
|
|
seg[1].x2 = t->corner_width - t->boundary_width-1;
|
|
seg[1].y1 = t->boundary_width-1;
|
|
seg[1].y2 = t->boundary_width-1;
|
|
n=2;
|
|
break;
|
|
case 2:
|
|
seg[0].x1 = t->boundary_width-1;
|
|
seg[0].x2 = t->corner_width - (hh ? 1 : 2);
|
|
seg[0].y1 = t->corner_width - t->boundary_width+1;
|
|
seg[0].y2 = t->corner_width - t->boundary_width+1;
|
|
n=1;
|
|
if(t->boundary_width > 3)
|
|
{
|
|
seg[1].x1 = t->boundary_width-2;
|
|
seg[1].x2 = t->corner_width - (hh ? 1 : 3);
|
|
seg[1].y1 = t->corner_width - t->boundary_width + 2;
|
|
seg[1].y2 = t->corner_width - t->boundary_width + 2;
|
|
n=2;
|
|
}
|
|
break;
|
|
case 3:
|
|
seg[0].x1 = 0;
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
seg[0].y1 = t->corner_width - t->boundary_width+1;
|
|
seg[0].y2 = t->corner_width - t->boundary_width+1;
|
|
n=1;
|
|
if(t->boundary_width > 3)
|
|
{
|
|
seg[0].x2 = t->corner_width - t->boundary_width + 1;
|
|
|
|
seg[1].x1 = 0;
|
|
seg[1].x2 = t->corner_width - t->boundary_width + 1;
|
|
seg[1].y1 = t->corner_width - t->boundary_width + 2;
|
|
seg[1].y2 = t->corner_width - t->boundary_width + 2;
|
|
n=2;
|
|
}
|
|
break;
|
|
}
|
|
XDrawSegments(dpy, t->corners[i], hor, seg, n);
|
|
switch(i)
|
|
{
|
|
case 0:
|
|
seg[0].y1 = t->boundary_width-2;
|
|
seg[0].y2 = t->corner_width;
|
|
seg[0].x1 = t->boundary_width-2;
|
|
seg[0].x2 = t->boundary_width-2;
|
|
|
|
seg[1].y1 = t->boundary_width-2;
|
|
seg[1].y2 = t->corner_width;
|
|
seg[1].x1 = t->boundary_width-1;
|
|
seg[1].x2 = t->boundary_width-1;
|
|
n=2;
|
|
break;
|
|
case 1:
|
|
seg[0].y1 = t->boundary_width-1;
|
|
seg[0].y2 = t->corner_width - (hh ? 1 : 2);
|
|
seg[0].x1 = t->corner_width - t->boundary_width;
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
n=1;
|
|
if(t->boundary_width > 3)
|
|
{
|
|
seg[1].y1 = t->boundary_width-2;
|
|
seg[1].y2 = t->corner_width - (hh ? 1 : 3);
|
|
seg[1].x1 = t->corner_width - t->boundary_width+1;
|
|
seg[1].x2 = t->corner_width - t->boundary_width+1;
|
|
n=2;
|
|
}
|
|
break;
|
|
case 2:
|
|
seg[0].y1 = (hh ? 0 : 1);
|
|
seg[0].y2 = t->corner_width - t->boundary_width+1;
|
|
seg[0].x1 = t->boundary_width-2;
|
|
seg[0].x2 = t->boundary_width-2;
|
|
n=1;
|
|
|
|
if(t->boundary_width > 3)
|
|
{
|
|
seg[1].y1 = 0;
|
|
seg[1].y2 = t->corner_width - t->boundary_width;
|
|
seg[1].x1 = t->boundary_width-1;
|
|
seg[1].x2 = t->boundary_width-1;
|
|
}
|
|
break;
|
|
case 3:
|
|
seg[0].y1 = 0;
|
|
seg[0].y2 = t->corner_width - t->boundary_width + 1;
|
|
seg[0].x1 = t->corner_width - t->boundary_width;
|
|
seg[0].x2 = t->corner_width - t->boundary_width;
|
|
n=1;
|
|
|
|
if(t->boundary_width > 3)
|
|
{
|
|
seg[0].y2 = t->corner_width - t->boundary_width + 2;
|
|
seg[1].y1 = 0;
|
|
seg[1].y2 = t->corner_width - t->boundary_width + 2;
|
|
seg[1].x1 = t->corner_width - t->boundary_width + 1;
|
|
seg[1].x2 = t->corner_width - t->boundary_width + 1;
|
|
n=2;
|
|
}
|
|
break;
|
|
}
|
|
XDrawSegments(dpy, t->corners[i], vert, seg, n);
|
|
}
|
|
}
|
|
|
|
#ifdef VECTOR_BUTTONS
|
|
/****************************************************************************
|
|
*
|
|
* Draws a little pattern within a window (more complex)
|
|
*
|
|
****************************************************************************/
|
|
void DrawLinePattern(Window win,
|
|
GC ReliefGC,
|
|
GC ShadowGC,
|
|
struct vector_coords *coords,
|
|
int w, int h)
|
|
{
|
|
int i = 1;
|
|
for (; i < coords->num; ++i)
|
|
{
|
|
XDrawLine(dpy,win,
|
|
coords->line_style[i] ? ReliefGC : ShadowGC,
|
|
w * coords->x[i-1]/100,
|
|
h * coords->y[i-1]/100,
|
|
w * coords->x[i]/100,
|
|
h * coords->y[i]/100);
|
|
}
|
|
}
|
|
#endif /* VECTOR_BUTTONS */
|
|
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Procedure:
|
|
* Setupframe - set window sizes, this was called from either
|
|
* AddWindow, EndResize, or HandleConfigureNotify.
|
|
*
|
|
* Inputs:
|
|
* tmp_win - the FvwmWindow pointer
|
|
* x - the x coordinate of the upper-left outer corner of the frame
|
|
* y - the y coordinate of the upper-left outer corner of the frame
|
|
* w - the width of the frame window w/o border
|
|
* h - the height of the frame window w/o border
|
|
*
|
|
* Special Considerations:
|
|
* This routine will check to make sure the window is not completely
|
|
* off the display, if it is, it'll bring some of it back on.
|
|
*
|
|
* The tmp_win->frame_XXX variables should NOT be updated with the
|
|
* values of x,y,w,h prior to calling this routine, since the new
|
|
* values are compared against the old to see whether a synthetic
|
|
* ConfigureNotify event should be sent. (It should be sent if the
|
|
* window was moved but not resized.)
|
|
*
|
|
************************************************************************/
|
|
|
|
void SetupFrame(FvwmWindow *tmp_win,int x,int y,int w,int h,Bool sendEvent)
|
|
{
|
|
XEvent client_event;
|
|
XWindowChanges frame_wc, xwc;
|
|
unsigned long frame_mask, xwcm;
|
|
int cx,cy,i;
|
|
Bool Resized = False, Moved = False;
|
|
int xwidth,ywidth,left,right;
|
|
#ifdef WINDOWSHADE
|
|
int shaded = tmp_win->buttons & WSHADE;
|
|
#endif
|
|
|
|
#ifdef FVWM_DEBUG_MSGS
|
|
fvwm_msg(DBG,"SetupFrame",
|
|
"Routine Entered (x == %d, y == %d, w == %d, h == %d)",
|
|
x, y, w, h);
|
|
#endif
|
|
|
|
/* if windows is not being maximized, save size in case of maximization */
|
|
if (!(tmp_win->flags & MAXIMIZED)
|
|
#ifdef WINDOWSHADE
|
|
&& !shaded
|
|
#endif
|
|
)
|
|
{
|
|
tmp_win->orig_x = x;
|
|
tmp_win->orig_y = y;
|
|
tmp_win->orig_wd = w;
|
|
tmp_win->orig_ht = h;
|
|
}
|
|
|
|
if((w != tmp_win->frame_width) || (h != tmp_win->frame_height))
|
|
Resized = True;
|
|
if ((x != tmp_win->frame_x || y != tmp_win->frame_y))
|
|
Moved = True;
|
|
|
|
/*
|
|
* According to the July 27, 1988 ICCCM draft, we should send a
|
|
* "synthetic" ConfigureNotify event to the client if the window
|
|
* was moved but not resized.
|
|
*/
|
|
if (Moved && !Resized)
|
|
sendEvent = True;
|
|
|
|
if (Resized)
|
|
{
|
|
left = tmp_win->nr_left_buttons;
|
|
right = tmp_win->nr_right_buttons;
|
|
|
|
if (tmp_win->flags & TITLE)
|
|
tmp_win->title_height = GetDecor(tmp_win,TitleHeight) + tmp_win->bw;
|
|
|
|
tmp_win->title_width= w-
|
|
(left+right)*tmp_win->title_height
|
|
-2*tmp_win->boundary_width+tmp_win->bw;
|
|
|
|
|
|
if(tmp_win->title_width < 1)
|
|
tmp_win->title_width = 1;
|
|
|
|
if (tmp_win->flags & TITLE)
|
|
{
|
|
xwcm = CWWidth | CWX | CWY | CWHeight;
|
|
tmp_win->title_x = tmp_win->boundary_width+
|
|
(left)*tmp_win->title_height;
|
|
if(tmp_win->title_x >= w - tmp_win->boundary_width)
|
|
tmp_win->title_x = -10;
|
|
tmp_win->title_y = tmp_win->boundary_width;
|
|
|
|
xwc.width = tmp_win->title_width;
|
|
|
|
xwc.height = tmp_win->title_height;
|
|
xwc.x = tmp_win->title_x;
|
|
xwc.y = tmp_win->title_y;
|
|
XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc);
|
|
|
|
|
|
xwcm = CWX | CWY | CWHeight | CWWidth;
|
|
xwc.height = tmp_win->title_height;
|
|
xwc.width = tmp_win->title_height;
|
|
|
|
xwc.y = tmp_win->boundary_width;
|
|
xwc.x = tmp_win->boundary_width;
|
|
for(i=0;i<Scr.nr_left_buttons;i++)
|
|
{
|
|
if(tmp_win->left_w[i] != None)
|
|
{
|
|
if(xwc.x + tmp_win->title_height < w-tmp_win->boundary_width)
|
|
XConfigureWindow(dpy, tmp_win->left_w[i], xwcm, &xwc);
|
|
else
|
|
{
|
|
xwc.x = -tmp_win->title_height;
|
|
XConfigureWindow(dpy, tmp_win->left_w[i], xwcm, &xwc);
|
|
}
|
|
xwc.x += tmp_win->title_height;
|
|
}
|
|
}
|
|
|
|
xwc.x=w-tmp_win->boundary_width+tmp_win->bw;
|
|
for(i=0;i<Scr.nr_right_buttons;i++)
|
|
{
|
|
if(tmp_win->right_w[i] != None)
|
|
{
|
|
xwc.x -=tmp_win->title_height;
|
|
if(xwc.x > tmp_win->boundary_width)
|
|
XConfigureWindow(dpy, tmp_win->right_w[i], xwcm, &xwc);
|
|
else
|
|
{
|
|
xwc.x = -tmp_win->title_height;
|
|
XConfigureWindow(dpy, tmp_win->right_w[i], xwcm, &xwc);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(tmp_win->flags & BORDER)
|
|
{
|
|
tmp_win->corner_width = GetDecor(tmp_win,TitleHeight) + tmp_win->bw +
|
|
tmp_win->boundary_width ;
|
|
|
|
if(w < 2*tmp_win->corner_width)
|
|
tmp_win->corner_width = w/3;
|
|
if((h < 2*tmp_win->corner_width)
|
|
#ifdef WINDOWSHADE
|
|
&&!shaded
|
|
#endif
|
|
)
|
|
tmp_win->corner_width = h/3;
|
|
xwidth = w - 2*tmp_win->corner_width+tmp_win->bw;
|
|
ywidth = h - 2*tmp_win->corner_width;
|
|
xwcm = CWWidth | CWHeight | CWX | CWY;
|
|
if(xwidth<2)
|
|
xwidth = 2;
|
|
if(ywidth<2)
|
|
ywidth = 2;
|
|
|
|
for(i=0;i<4;i++)
|
|
{
|
|
if(i==0)
|
|
{
|
|
xwc.x = tmp_win->corner_width;
|
|
xwc.y = 0;
|
|
xwc.height = tmp_win->boundary_width;
|
|
xwc.width = xwidth;
|
|
}
|
|
else if (i==1)
|
|
{
|
|
xwc.x = w - tmp_win->boundary_width+tmp_win->bw;
|
|
xwc.y = tmp_win->corner_width;
|
|
xwc.width = tmp_win->boundary_width;
|
|
xwc.height = ywidth;
|
|
|
|
}
|
|
else if(i==2)
|
|
{
|
|
xwc.x = tmp_win->corner_width;
|
|
xwc.y = h - tmp_win->boundary_width+tmp_win->bw;
|
|
xwc.height = tmp_win->boundary_width+tmp_win->bw;
|
|
xwc.width = xwidth;
|
|
}
|
|
else
|
|
{
|
|
xwc.x = 0;
|
|
xwc.y = tmp_win->corner_width;
|
|
xwc.width = tmp_win->boundary_width;
|
|
xwc.height = ywidth;
|
|
}
|
|
#ifdef WINDOWSHADE
|
|
if (!shaded||(i!=2))
|
|
#endif
|
|
XConfigureWindow(dpy, tmp_win->sides[i], xwcm, &xwc);
|
|
}
|
|
|
|
xwcm = CWX|CWY|CWWidth|CWHeight;
|
|
xwc.width = tmp_win->corner_width;
|
|
xwc.height = tmp_win->corner_width;
|
|
for(i=0;i<4;i++)
|
|
{
|
|
if(i%2)
|
|
xwc.x = w - tmp_win->corner_width+tmp_win->bw;
|
|
else
|
|
xwc.x = 0;
|
|
|
|
if(i/2)
|
|
xwc.y = h - tmp_win->corner_width;
|
|
else
|
|
xwc.y = 0;
|
|
|
|
#ifdef WINDOWSHADE
|
|
if (!shaded||(i==0)||(i==1))
|
|
#endif
|
|
XConfigureWindow(dpy, tmp_win->corners[i], xwcm, &xwc);
|
|
}
|
|
|
|
}
|
|
}
|
|
tmp_win->attr.width = w - 2*tmp_win->boundary_width;
|
|
tmp_win->attr.height = h - tmp_win->title_height
|
|
- 2*tmp_win->boundary_width;
|
|
/* may need to omit the -1 for shaped windows, next two lines*/
|
|
cx = tmp_win->boundary_width-tmp_win->bw;
|
|
cy = tmp_win->title_height + tmp_win->boundary_width-tmp_win->bw;
|
|
|
|
#ifdef WINDOWSHADE
|
|
if (!shaded) {
|
|
#endif
|
|
XResizeWindow(dpy, tmp_win->w, tmp_win->attr.width,
|
|
tmp_win->attr.height);
|
|
XMoveResizeWindow(dpy, tmp_win->Parent, cx,cy,
|
|
tmp_win->attr.width, tmp_win->attr.height);
|
|
#ifdef WINDOWSHADE
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* fix up frame and assign size/location values in tmp_win
|
|
*/
|
|
frame_wc.x = tmp_win->frame_x = x;
|
|
frame_wc.y = tmp_win->frame_y = y;
|
|
frame_wc.width = tmp_win->frame_width = w;
|
|
frame_wc.height = tmp_win->frame_height = h;
|
|
frame_mask = (CWX | CWY | CWWidth | CWHeight);
|
|
XConfigureWindow (dpy, tmp_win->frame, frame_mask, &frame_wc);
|
|
#ifdef FVWM_DEBUG_MSGS
|
|
fvwm_msg(DBG,"SetupFrame",
|
|
"New frame dimensions (x == %d, y == %d, w == %d, h == %d)",
|
|
frame_wc.x, frame_wc.y, frame_wc.width, frame_wc.height);
|
|
#endif
|
|
|
|
#ifdef SHAPE
|
|
if (ShapesSupported)
|
|
{
|
|
if ((Resized)&&(tmp_win->wShaped))
|
|
{
|
|
SetShape(tmp_win,w);
|
|
}
|
|
}
|
|
#endif /* SHAPE */
|
|
XSync(dpy,0);
|
|
if (sendEvent
|
|
#ifdef WINDOWSHADE
|
|
&& !shaded
|
|
#endif
|
|
)
|
|
{
|
|
client_event.type = ConfigureNotify;
|
|
client_event.xconfigure.display = dpy;
|
|
client_event.xconfigure.event = tmp_win->w;
|
|
client_event.xconfigure.window = tmp_win->w;
|
|
|
|
client_event.xconfigure.x = x + tmp_win->boundary_width;
|
|
client_event.xconfigure.y = y + tmp_win->title_height+
|
|
tmp_win->boundary_width;
|
|
client_event.xconfigure.width = w-2*tmp_win->boundary_width;
|
|
client_event.xconfigure.height =h-2*tmp_win->boundary_width -
|
|
tmp_win->title_height;
|
|
|
|
client_event.xconfigure.border_width =tmp_win->bw;
|
|
/* Real ConfigureNotify events say we're above title window, so ... */
|
|
/* what if we don't have a title ????? */
|
|
client_event.xconfigure.above = tmp_win->frame;
|
|
client_event.xconfigure.override_redirect = False;
|
|
XSendEvent(dpy, tmp_win->w, False, StructureNotifyMask, &client_event);
|
|
#ifdef FVWM_DEBUG_MSGS
|
|
fvwm_msg(DBG,"SetupFrame","Sent ConfigureNotify (w == %d, h == %d)",
|
|
client_event.xconfigure.width,client_event.xconfigure.height);
|
|
#endif
|
|
}
|
|
XSync(dpy,0);
|
|
|
|
BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
*
|
|
* Sets up the shaped window borders
|
|
*
|
|
****************************************************************************/
|
|
void SetShape(FvwmWindow *tmp_win, int w)
|
|
{
|
|
#ifdef SHAPE
|
|
if (ShapesSupported)
|
|
{
|
|
XRectangle rect;
|
|
|
|
XShapeCombineShape (dpy, tmp_win->frame, ShapeBounding,
|
|
tmp_win->boundary_width,
|
|
tmp_win->title_height+tmp_win->boundary_width,
|
|
tmp_win->w,
|
|
ShapeBounding, ShapeSet);
|
|
if (tmp_win->title_w)
|
|
{
|
|
/* windows w/ titles */
|
|
rect.x = tmp_win->boundary_width;
|
|
rect.y = tmp_win->title_y;
|
|
rect.width = w - 2*tmp_win->boundary_width+tmp_win->bw;
|
|
rect.height = tmp_win->title_height;
|
|
|
|
|
|
XShapeCombineRectangles(dpy,tmp_win->frame,ShapeBounding,
|
|
0,0,&rect,1,ShapeUnion,Unsorted);
|
|
}
|
|
}
|
|
#endif
|
|
}
|