mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-19 12:28:22 +01:00
The number of calls to WMRetainColor for a color in use should the same as the number of calls to WMReleaseColor to free that color. In case of discrepancy, random crashes can happen and memory is not freed properly. To debug that issue I checked the retained colors when the switchpanel is opened and then checked if those colors are properly released once the panel is closed. This patch fixes the issue mentioned at https://github.com/window-maker/wmaker/issues/22
264 lines
5.1 KiB
C
264 lines
5.1 KiB
C
|
|
#include "WINGsP.h"
|
|
|
|
typedef struct W_Frame {
|
|
W_Class widgetClass;
|
|
W_View *view;
|
|
|
|
char *caption;
|
|
WMColor *textColor;
|
|
|
|
struct {
|
|
WMReliefType relief:4;
|
|
WMTitlePosition titlePosition:4;
|
|
} flags;
|
|
} Frame;
|
|
|
|
#define DEFAULT_RELIEF WRGroove
|
|
#define DEFAULT_TITLE_POSITION WTPAtTop
|
|
#define DEFAULT_WIDTH 40
|
|
#define DEFAULT_HEIGHT 40
|
|
|
|
static void destroyFrame(Frame * fPtr);
|
|
static void paintFrame(Frame * fPtr);
|
|
static void repaintFrame(Frame * fPtr);
|
|
|
|
void WMSetFrameTitlePosition(WMFrame * fPtr, WMTitlePosition position)
|
|
{
|
|
fPtr->flags.titlePosition = position;
|
|
|
|
if (fPtr->view->flags.realized) {
|
|
repaintFrame(fPtr);
|
|
}
|
|
}
|
|
|
|
void WMSetFrameRelief(WMFrame * fPtr, WMReliefType relief)
|
|
{
|
|
fPtr->flags.relief = relief;
|
|
|
|
if (fPtr->view->flags.realized) {
|
|
repaintFrame(fPtr);
|
|
}
|
|
}
|
|
|
|
void WMSetFrameTitle(WMFrame * fPtr, const char *title)
|
|
{
|
|
if (fPtr->caption)
|
|
wfree(fPtr->caption);
|
|
|
|
if (title)
|
|
fPtr->caption = wstrdup(title);
|
|
else
|
|
fPtr->caption = NULL;
|
|
|
|
if (fPtr->view->flags.realized) {
|
|
repaintFrame(fPtr);
|
|
}
|
|
}
|
|
|
|
static void repaintFrame(Frame * fPtr)
|
|
{
|
|
W_View *view = fPtr->view;
|
|
W_Screen *scrPtr = view->screen;
|
|
|
|
XClearWindow(scrPtr->display, view->window);
|
|
paintFrame(fPtr);
|
|
}
|
|
|
|
static void paintFrame(Frame * fPtr)
|
|
{
|
|
W_View *view = fPtr->view;
|
|
W_Screen *scrPtr = view->screen;
|
|
WMFont *font = scrPtr->normalFont;
|
|
Display *display = scrPtr->display;
|
|
int tx, ty, tw, th, tlen;
|
|
int fy, fh;
|
|
Bool drawTitle;
|
|
|
|
if (fPtr->caption != NULL) {
|
|
th = WMFontHeight(font);
|
|
tlen = strlen(fPtr->caption);
|
|
} else {
|
|
th = 0;
|
|
tlen = 0;
|
|
}
|
|
|
|
switch (fPtr->flags.titlePosition) {
|
|
case WTPAboveTop:
|
|
ty = 0;
|
|
fy = th + 4;
|
|
fh = view->size.height - fy;
|
|
break;
|
|
|
|
case WTPAtTop:
|
|
ty = 0;
|
|
fy = th / 2;
|
|
fh = view->size.height - fy;
|
|
break;
|
|
|
|
case WTPBelowTop:
|
|
ty = 4;
|
|
fy = 0;
|
|
fh = view->size.height;
|
|
break;
|
|
|
|
case WTPAboveBottom:
|
|
ty = view->size.height - th - 4;
|
|
fy = 0;
|
|
fh = view->size.height;
|
|
break;
|
|
|
|
case WTPAtBottom:
|
|
ty = view->size.height - th;
|
|
fy = 0;
|
|
fh = view->size.height - th / 2;
|
|
break;
|
|
|
|
case WTPBelowBottom:
|
|
ty = view->size.height - th;
|
|
fy = 0;
|
|
fh = view->size.height - th - 4;
|
|
break;
|
|
|
|
default:
|
|
ty = 0;
|
|
fy = 0;
|
|
fh = view->size.height;
|
|
}
|
|
|
|
if (tlen > 0 && fPtr->flags.titlePosition != WTPNoTitle) {
|
|
tw = WMWidthOfString(font, fPtr->caption, tlen);
|
|
|
|
tx = (view->size.width - tw) / 2;
|
|
|
|
drawTitle = True;
|
|
} else {
|
|
tw = tx = 0;
|
|
drawTitle = False;
|
|
}
|
|
|
|
{
|
|
XRectangle rect;
|
|
Region region, tmp;
|
|
GC gc[4];
|
|
int i;
|
|
|
|
region = XCreateRegion();
|
|
|
|
rect.x = 0;
|
|
rect.y = 0;
|
|
rect.width = view->size.width;
|
|
rect.height = view->size.height;
|
|
XUnionRectWithRegion(&rect, region, region);
|
|
if (drawTitle) {
|
|
tmp = XCreateRegion();
|
|
rect.x = tx;
|
|
rect.y = ty;
|
|
rect.width = tw;
|
|
rect.height = th;
|
|
XUnionRectWithRegion(&rect, tmp, tmp);
|
|
XSubtractRegion(region, tmp, region);
|
|
XDestroyRegion(tmp);
|
|
}
|
|
gc[0] = WMColorGC(scrPtr->black);
|
|
gc[1] = WMColorGC(scrPtr->darkGray);
|
|
gc[2] = WMColorGC(scrPtr->gray);
|
|
gc[3] = WMColorGC(scrPtr->white);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
XSetRegion(display, gc[i], region);
|
|
}
|
|
XDestroyRegion(region);
|
|
|
|
W_DrawReliefWithGC(scrPtr, view->window, 0, fy, view->size.width, fh,
|
|
fPtr->flags.relief, gc[0], gc[1], gc[2], gc[3]);
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
XSetClipMask(display, gc[i], None);
|
|
}
|
|
}
|
|
|
|
if (drawTitle) {
|
|
/* can't draw AA text over and over again because it gets messed */
|
|
/* // TODO create the dbl buffer pixmap when create/set frame title */
|
|
if (scrPtr->antialiasedText) {
|
|
Drawable d;
|
|
|
|
d = XCreatePixmap(display, view->window, tw, th, scrPtr->depth);
|
|
XFillRectangle(display, d, WMColorGC(view->backColor), 0, 0, tw, th);
|
|
|
|
WMDrawString(scrPtr, d, fPtr->textColor ? fPtr->textColor : scrPtr->black, font, 0, 0, fPtr->caption, tlen);
|
|
XCopyArea(display, d, view->window, scrPtr->copyGC, 0, 0, tw, th, tx, ty);
|
|
XFreePixmap(display, d);
|
|
} else {
|
|
WMDrawString(scrPtr, view->window, scrPtr->black, font, tx, ty, fPtr->caption, tlen);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void handleEvents(XEvent * event, void *data)
|
|
{
|
|
Frame *fPtr = (Frame *) data;
|
|
|
|
CHECK_CLASS(data, WC_Frame);
|
|
|
|
switch (event->type) {
|
|
case Expose:
|
|
if (event->xexpose.count == 0)
|
|
paintFrame(fPtr);
|
|
break;
|
|
|
|
case DestroyNotify:
|
|
destroyFrame(fPtr);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WMSetFrameTitleColor(WMFrame *fPtr, WMColor *color)
|
|
{
|
|
if (fPtr->textColor)
|
|
WMReleaseColor(fPtr->textColor);
|
|
fPtr->textColor = WMRetainColor(color);
|
|
|
|
if (fPtr->view->flags.realized) {
|
|
repaintFrame(fPtr);
|
|
}
|
|
}
|
|
|
|
WMFrame *WMCreateFrame(WMWidget * parent)
|
|
{
|
|
Frame *fPtr;
|
|
|
|
fPtr = wmalloc(sizeof(Frame));
|
|
|
|
fPtr->widgetClass = WC_Frame;
|
|
|
|
fPtr->view = W_CreateView(W_VIEW(parent));
|
|
if (!fPtr->view) {
|
|
wfree(fPtr);
|
|
return NULL;
|
|
}
|
|
fPtr->view->self = fPtr;
|
|
fPtr->textColor = WMRetainColor(fPtr->view->screen->black);
|
|
|
|
WMCreateEventHandler(fPtr->view, ExposureMask | StructureNotifyMask, handleEvents, fPtr);
|
|
|
|
fPtr->flags.relief = DEFAULT_RELIEF;
|
|
fPtr->flags.titlePosition = DEFAULT_TITLE_POSITION;
|
|
|
|
WMResizeWidget(fPtr, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
|
|
|
return fPtr;
|
|
}
|
|
|
|
static void destroyFrame(Frame * fPtr)
|
|
{
|
|
if (fPtr->textColor)
|
|
WMReleaseColor(fPtr->textColor);
|
|
|
|
if (fPtr->caption)
|
|
wfree(fPtr->caption);
|
|
|
|
wfree(fPtr);
|
|
}
|