mirror of
https://github.com/gryf/wmaker.git
synced 2026-03-25 14:13:31 +01:00
wmaker: revamp titlebar language button
This patch is replacing the modelock legacy hardcoded language dropdown icons with a compact titlebar button based on the current locale. (it adds also a detection to xkbfile library which is required to get the short name of the locale). Now supports up to 4 layouts, clicking on the language button will cycle through them (XKB officially supports up to four groups).
This commit is contained in:
committed by
Carlos R. Mafra
parent
29177f94ed
commit
ec115fedf7
198
src/framewin.c
198
src/framewin.c
@@ -54,7 +54,7 @@ static void resizebarMouseDown(WObjDescriptor * desc, XEvent * event);
|
||||
static void checkTitleSize(WFrameWindow * fwin);
|
||||
|
||||
static void paintButton(WCoreWindow * button, WTexture * texture,
|
||||
unsigned long color, WPixmap * image, int pushed);
|
||||
unsigned long color, WPixmap * image, int pushed, int from_xpm);
|
||||
|
||||
static void updateTitlebar(WFrameWindow * fwin);
|
||||
|
||||
@@ -98,6 +98,7 @@ WFrameWindow *wFrameWindowCreate(WScreen * scr, int wlevel, int x, int y,
|
||||
#ifdef KEEP_XKB_LOCK_STATUS
|
||||
fwin->languagemode = XkbGroup1Index;
|
||||
fwin->last_languagemode = XkbGroup2Index;
|
||||
wWindowGetLanguageLabel(fwin->languagemode, fwin->language_label);
|
||||
#endif
|
||||
|
||||
fwin->depth = depth;
|
||||
@@ -145,6 +146,7 @@ void wFrameWindowUpdateBorders(WFrameWindow * fwin, int flags)
|
||||
theight = *fwin->title_min_height;
|
||||
} else {
|
||||
theight = 0;
|
||||
fwin->flags.titlebar = 0;
|
||||
}
|
||||
|
||||
if (wPreferences.new_style == TS_NEW) {
|
||||
@@ -536,6 +538,8 @@ static void updateTitlebar(WFrameWindow * fwin)
|
||||
#ifdef XKB_BUTTON_HINT
|
||||
else {
|
||||
int bsize = theight - 7;
|
||||
if (wPreferences.new_style == TS_NEXT)
|
||||
bsize -= 1;
|
||||
if (fwin->flags.hide_left_button || !fwin->left_button || fwin->flags.lbutton_dont_fit) {
|
||||
if (fwin->language_button)
|
||||
wCoreConfigure(fwin->language_button, 3, (theight - bsize) / 2,
|
||||
@@ -950,6 +954,10 @@ void wFrameWindowPaint(WFrameWindow * fwin)
|
||||
remakeTexture(fwin, i);
|
||||
}
|
||||
}
|
||||
#ifdef XKB_BUTTON_HINT
|
||||
if (wPreferences.modelock)
|
||||
wFrameWindowUpdateLanguageButton(fwin);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (fwin->flags.need_texture_change) {
|
||||
@@ -1023,7 +1031,8 @@ void wFrameWindowPaint(WFrameWindow * fwin)
|
||||
allButtons = 0;
|
||||
}
|
||||
#ifdef XKB_BUTTON_HINT
|
||||
fwin->languagebutton_image = scr->b_pixmaps[WBUT_XKBGROUP1 + fwin->languagemode];
|
||||
if (fwin->flags.language_button && !fwin->languagebutton_image[0])
|
||||
wFrameWindowUpdateLanguageButton(fwin);
|
||||
#endif
|
||||
|
||||
if (fwin->title) {
|
||||
@@ -1228,10 +1237,145 @@ int wFrameWindowChangeTitle(WFrameWindow *fwin, const char *new_title)
|
||||
}
|
||||
|
||||
#ifdef XKB_BUTTON_HINT
|
||||
|
||||
static int wFrameWindowSetLanguageButtonImages(WFrameWindow *fwin, Pixmap *pixmaps, int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
WPixmap *wp = wPixmapCreate(pixmaps[i], None);
|
||||
if (!wp) {
|
||||
int j;
|
||||
XFreePixmap(dpy, pixmaps[i]);
|
||||
for (j = i + 1; j < count; j++)
|
||||
XFreePixmap(dpy, pixmaps[j]);
|
||||
return 0;
|
||||
}
|
||||
wp->client_owned = 0;
|
||||
wp->client_owned_mask = 0;
|
||||
if (fwin->languagebutton_image[i] && !fwin->languagebutton_image[i]->shared)
|
||||
wPixmapDestroy(fwin->languagebutton_image[i]);
|
||||
fwin->languagebutton_image[i] = wp;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wFrameWindowUpdateLanguageButton(WFrameWindow * fwin)
|
||||
{
|
||||
paintButton(fwin->language_button, fwin->title_texture[fwin->flags.state],
|
||||
WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->languagebutton_image, True);
|
||||
WScreen *scr = fwin->screen_ptr;
|
||||
WCoreWindow *button = fwin->language_button;
|
||||
GC gc = scr->copy_gc;
|
||||
int i, text_width, text_height;
|
||||
int border_thickness = 3;
|
||||
int key_width, key_height;
|
||||
int group_index;
|
||||
Pixmap tmp[2]; /* focused, unfocused */
|
||||
|
||||
if (!fwin->flags.titlebar || fwin->core->descriptor.parent_type != WCLASS_WINDOW)
|
||||
return;
|
||||
|
||||
if (!button || fwin->language_label[0] == '\0')
|
||||
return;
|
||||
|
||||
group_index = fwin->languagemode;
|
||||
if (group_index < 0 || group_index >= 4)
|
||||
return;
|
||||
|
||||
/* Calculate text dimensions */
|
||||
int small_px = WMFontHeight(*fwin->font) * 55 / 100;
|
||||
WMFont *small = WMBoldSystemFontOfSize(scr->wmscreen, small_px);
|
||||
text_width = WMWidthOfString(small, fwin->language_label, strlen(fwin->language_label));
|
||||
text_height = WMFontHeight(small);
|
||||
|
||||
key_width = button->width - border_thickness;
|
||||
key_height = button->height - border_thickness;
|
||||
|
||||
/* Ensure dimensions are valid */
|
||||
if (key_width < 1 || key_height < 1) {
|
||||
WMReleaseFont(small);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create temporary pixmaps for immediate drawing */
|
||||
tmp[0] = XCreatePixmap(dpy, button->window, 2*key_width, key_height, scr->w_depth);
|
||||
if (tmp[0] == None) {
|
||||
WMReleaseFont(small);
|
||||
return;
|
||||
}
|
||||
|
||||
tmp[1] = None;
|
||||
if (wPreferences.new_style == TS_NEW) {
|
||||
tmp[1] = XCreatePixmap(dpy, button->window, 2*key_width, key_height, scr->w_depth);
|
||||
if (tmp[1] == None) {
|
||||
XFreePixmap(dpy, tmp[0]);
|
||||
WMReleaseFont(small);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset GC to ensure clean state for drawing */
|
||||
XSetClipMask(dpy, gc, None);
|
||||
|
||||
/* Draw the language label centered in the button */
|
||||
int text_x = (key_width - text_width) / 2;
|
||||
int text_y = (key_height - text_height) / 2;
|
||||
|
||||
/* Fill the color pixmap depending on the style */
|
||||
if (wPreferences.new_style == TS_NEW) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (fwin->title_texture[i]->any.type != WTEX_SOLID && fwin->title_back[i] != None) {
|
||||
XCopyArea(dpy, fwin->languagebutton_back[i], tmp[i], scr->copy_gc,
|
||||
0, 0, button->width, button->height, -1, -1);
|
||||
} else {
|
||||
unsigned long bg_pixel = fwin->title_texture[i]->solid.normal.pixel;
|
||||
XSetForeground(dpy, gc, bg_pixel);
|
||||
XFillRectangle(dpy, tmp[i], gc, 0, 0, key_width, key_height);
|
||||
}
|
||||
WMDrawString(scr->wmscreen, tmp[i], fwin->title_color[i],
|
||||
small, text_x, text_y, fwin->language_label, strlen(fwin->language_label));
|
||||
}
|
||||
} else if (wPreferences.new_style == TS_OLD) {
|
||||
unsigned long bg_pixel = scr->widget_texture->normal.pixel;
|
||||
XSetForeground(dpy, gc, bg_pixel);
|
||||
XFillRectangle(dpy, tmp[0], gc, 0, 0, key_width, key_height);
|
||||
WMDrawString(scr->wmscreen, tmp[0], WMBlackColor(scr->wmscreen),
|
||||
small, text_x, text_y, fwin->language_label, strlen(fwin->language_label));
|
||||
} else {
|
||||
unsigned long bg_pixel = scr->widget_texture->dark.pixel;
|
||||
XSetForeground(dpy, gc, bg_pixel);
|
||||
XFillRectangle(dpy, tmp[0], gc, 0, 0, key_width, key_height);
|
||||
WMColor *silver = WMCreateRGBColor(scr->wmscreen, 0xc0c0, 0xc0c0, 0xc0c0, True);
|
||||
WMDrawString(scr->wmscreen, tmp[0], silver,
|
||||
small, text_x, text_y, fwin->language_label, strlen(fwin->language_label));
|
||||
WMReleaseColor(silver);
|
||||
}
|
||||
|
||||
/* pushed button next to normal for easy access when painting */
|
||||
text_x = key_width + (key_width - text_width) / 2;
|
||||
if (wPreferences.new_style == TS_NEW) {
|
||||
XSetForeground(dpy, gc, scr->white_pixel);
|
||||
for (i = 0; i < 2; i++) {
|
||||
XFillRectangle(dpy, tmp[i], gc, key_width, 0, key_width, key_height);
|
||||
WMDrawString(scr->wmscreen, tmp[i], WMBlackColor(scr->wmscreen),
|
||||
small, text_x, text_y, fwin->language_label, strlen(fwin->language_label));
|
||||
}
|
||||
} else if (wPreferences.new_style == TS_OLD) {
|
||||
XSetForeground(dpy, gc, scr->white_pixel);
|
||||
XFillRectangle(dpy, tmp[0], gc, key_width, 0, key_width, key_height);
|
||||
WMDrawString(scr->wmscreen, tmp[0], WMDarkGrayColor(scr->wmscreen),
|
||||
small, text_x, text_y, fwin->language_label, strlen(fwin->language_label));
|
||||
} else {
|
||||
unsigned long bg_pixel = scr->widget_texture->dark.pixel;
|
||||
WMColor *silver = WMCreateRGBColor(scr->wmscreen, 0xc0c0, 0xc0c0, 0xc0c0, True);
|
||||
XSetForeground(dpy, gc, bg_pixel);
|
||||
XFillRectangle(dpy, tmp[0], gc, key_width, 0, key_width, key_height);
|
||||
WMDrawString(scr->wmscreen, tmp[0], silver,
|
||||
small, text_x, text_y, fwin->language_label, strlen(fwin->language_label));
|
||||
WMReleaseColor(silver);
|
||||
}
|
||||
|
||||
WMReleaseFont(small);
|
||||
|
||||
wFrameWindowSetLanguageButtonImages(fwin, tmp, (wPreferences.new_style == TS_NEW) ? 2 : 1);
|
||||
}
|
||||
#endif /* XKB_BUTTON_HINT */
|
||||
|
||||
@@ -1286,7 +1430,7 @@ static void checkTitleSize(WFrameWindow * fwin)
|
||||
fwin->flags.incomplete_title = 0;
|
||||
}
|
||||
|
||||
static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed)
|
||||
static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long color, WPixmap * image, int pushed, int from_xpm)
|
||||
{
|
||||
WScreen *scr = button->screen_ptr;
|
||||
GC copy_gc = scr->copy_gc;
|
||||
@@ -1364,8 +1508,12 @@ static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long
|
||||
} else {
|
||||
if (wPreferences.new_style == TS_OLD) {
|
||||
XSetForeground(dpy, copy_gc, scr->dark_pixel);
|
||||
XFillRectangle(dpy, button->window, copy_gc, 0, 0,
|
||||
button->width, button->height);
|
||||
if (from_xpm)
|
||||
XFillRectangle(dpy, button->window, copy_gc, 0, 0,
|
||||
button->width, button->height);
|
||||
else
|
||||
XCopyArea(dpy, image->image, button->window, copy_gc,
|
||||
left, 0, width, image->height, x, y);
|
||||
} else {
|
||||
XSetForeground(dpy, copy_gc, scr->black_pixel);
|
||||
XCopyArea(dpy, image->image, button->window, copy_gc,
|
||||
@@ -1379,7 +1527,11 @@ static void paintButton(WCoreWindow * button, WTexture * texture, unsigned long
|
||||
XSetForeground(dpy, copy_gc, color);
|
||||
XSetBackground(dpy, copy_gc, texture->any.color.pixel);
|
||||
}
|
||||
XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
|
||||
if (from_xpm)
|
||||
XFillRectangle(dpy, button->window, copy_gc, 0, 0, button->width, button->height);
|
||||
else
|
||||
XCopyArea(dpy, image->image, button->window, copy_gc,
|
||||
left, 0, width, image->height, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1394,18 +1546,23 @@ static void handleButtonExpose(WObjDescriptor * desc, XEvent * event)
|
||||
|
||||
#ifdef XKB_BUTTON_HINT
|
||||
if (button == fwin->language_button) {
|
||||
if (!fwin->flags.hide_language_button)
|
||||
if (!fwin->flags.hide_language_button) {
|
||||
/* map focused and pfocused states to focus language button image */
|
||||
int lb_index = wPreferences.new_style == TS_NEW && (fwin->flags.state == 1) ? 1 : 0;
|
||||
|
||||
paintButton(button, fwin->title_texture[fwin->flags.state],
|
||||
WMColorPixel(fwin->title_color[fwin->flags.state]),
|
||||
fwin->languagebutton_image, False);
|
||||
fwin->languagebutton_image[lb_index],
|
||||
False, False);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (button == fwin->left_button)
|
||||
paintButton(button, fwin->title_texture[fwin->flags.state],
|
||||
WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False);
|
||||
WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->lbutton_image, False, True);
|
||||
else
|
||||
paintButton(button, fwin->title_texture[fwin->flags.state],
|
||||
WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False);
|
||||
WMColorPixel(fwin->title_color[fwin->flags.state]), fwin->rbutton_image, False, True);
|
||||
}
|
||||
|
||||
static void titlebarMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
@@ -1437,7 +1594,7 @@ static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
WCoreWindow *button = desc->self;
|
||||
WPixmap *image;
|
||||
XEvent ev;
|
||||
int done = 0, execute = 1;
|
||||
int done = 0, execute = 1, from_xpm = True;
|
||||
WTexture *texture;
|
||||
unsigned long pixel;
|
||||
int clickButton = event->xbutton.button;
|
||||
@@ -1458,13 +1615,18 @@ static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
if (button == fwin->language_button) {
|
||||
if (!wPreferences.modelock)
|
||||
return;
|
||||
image = fwin->languagebutton_image;
|
||||
|
||||
/* map focused and pfocused states to focus language button image */
|
||||
int lb_index = wPreferences.new_style == TS_NEW && (fwin->flags.state == 1) ? 1 : 0;
|
||||
|
||||
image = fwin->languagebutton_image[lb_index];
|
||||
from_xpm = False;
|
||||
}
|
||||
#endif
|
||||
|
||||
pixel = WMColorPixel(fwin->title_color[fwin->flags.state]);
|
||||
texture = fwin->title_texture[fwin->flags.state];
|
||||
paintButton(button, texture, pixel, image, True);
|
||||
paintButton(button, texture, pixel, image, True, from_xpm);
|
||||
|
||||
while (!done) {
|
||||
WMMaskEvent(dpy, LeaveWindowMask | EnterWindowMask | ButtonReleaseMask
|
||||
@@ -1472,12 +1634,12 @@ static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
switch (ev.type) {
|
||||
case LeaveNotify:
|
||||
execute = 0;
|
||||
paintButton(button, texture, pixel, image, False);
|
||||
paintButton(button, texture, pixel, image, False, from_xpm);
|
||||
break;
|
||||
|
||||
case EnterNotify:
|
||||
execute = 1;
|
||||
paintButton(button, texture, pixel, image, True);
|
||||
paintButton(button, texture, pixel, image, True, from_xpm);
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
@@ -1492,7 +1654,7 @@ static void buttonMouseDown(WObjDescriptor * desc, XEvent * event)
|
||||
WMHandleEvent(&ev);
|
||||
}
|
||||
}
|
||||
paintButton(button, texture, pixel, image, False);
|
||||
paintButton(button, texture, pixel, image, False, from_xpm);
|
||||
|
||||
if (execute) {
|
||||
if (button == fwin->left_button) {
|
||||
|
||||
Reference in New Issue
Block a user