diff --git a/ChangeLog b/ChangeLog index 2b5f49b7..68a2e8d3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,7 @@ Changes since version 0.90.0: - added _NET_WM_NAME, _NET_WM_ICON_NAME and _NET_WM_ICON to WINGs - new WPrefs icon (thanks to Largo) - replaced VirtualEdgeThickness option, with EnableVirtualDesktop (boolean) - +- enhanced alt-tab panel, added theming ability Changes since version 0.80.2: ............................. diff --git a/NEWS b/NEWS index 2e84d106..b41dd20c 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,41 @@ NEWS for veteran Window Maker users ----------------------------------- +--- 0.91.0 + +Alt-Tab Window Switching +------------------------ + +You can change the appearance of the panel shown during Alt-Tab window switching +with the SwitchPanelImages option: + + (selected_icon_tile_image, background_image, width, height) + +selected_icon_tile_image is the image used to highlight the currently selected +window icon. It must be 64x64 pixels. + +background_image is the image used in the background of the panel. It must +be at least 64x80. + +width and height are the width and size of the central part of the image. +When drawing the panel, the image will be split as: + |W | + +--+--+--+ + | | | | + +--+--+--+ - + | | | | H + +--+--+--+ - + | | | | + +--+--+--+ + +The 4 corner images will be copied in their original sizes and the rest will +be scaled to the final panel size. + +background_image, width and height are optional. If you leave them out, +a gray panel will be used. If your machine is not very fast, you may want +to use it. + + --- 0.90.0 diff --git a/WINGs/WINGs/WINGs.h b/WINGs/WINGs/WINGs.h index 20556a87..3fdf4ed3 100644 --- a/WINGs/WINGs/WINGs.h +++ b/WINGs/WINGs/WINGs.h @@ -830,6 +830,8 @@ WMColor* WMCreateRGBAColor(WMScreen *scr, unsigned short red, WMColor* WMCreateNamedColor(WMScreen *scr, char *name, Bool exact); +RColor WMGetRColorFromColor(WMColor *color); + void WMSetColorAlpha(WMColor *color, unsigned short alpha); unsigned short WMRedComponentOfColor(WMColor *color); diff --git a/WINGs/wcolor.c b/WINGs/wcolor.c index bca13a7a..f35252bd 100644 --- a/WINGs/wcolor.c +++ b/WINGs/wcolor.c @@ -103,6 +103,19 @@ WMCreateRGBColor(WMScreen *scr, unsigned short red, unsigned short green, } +RColor WMGetRColorFromColor(WMColor *color) +{ + RColor rcolor; + + rcolor.red= color->color.red>>8; + rcolor.green= color->color.green>>8; + rcolor.blue= color->color.blue>>8; + rcolor.alpha= color->alpha>>8; + + return rcolor; +} + + WMColor* WMCreateRGBAColor(WMScreen *scr, unsigned short red, unsigned short green, unsigned short blue, unsigned short alpha, Bool exact) diff --git a/WindowMaker/Pixmaps/Makefile.am b/WindowMaker/Pixmaps/Makefile.am index 3d2ac702..f970ea4a 100644 --- a/WindowMaker/Pixmaps/Makefile.am +++ b/WindowMaker/Pixmaps/Makefile.am @@ -3,6 +3,7 @@ defsdatadir = $(pkgdatadir)/Pixmaps defsdata_DATA = tile.tiff \ tile.xpm \ - swtile.png + swtile.png \ + swback.png EXTRA_DIST = $(defsdata_DATA) diff --git a/WindowMaker/Pixmaps/swback.png b/WindowMaker/Pixmaps/swback.png new file mode 100644 index 00000000..fab56ac3 Binary files /dev/null and b/WindowMaker/Pixmaps/swback.png differ diff --git a/src/WindowMaker.h b/src/WindowMaker.h index 10a01c7a..342e244e 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -472,6 +472,9 @@ typedef struct WPreferences { unsigned int workspace_border_size; /* Size in pixels of the workspace border */ char workspace_border_position; /* Where to leave a workspace border */ + RImage *swtileImage; + RImage *swbackImage[9]; + struct { unsigned int nodock:1; /* don't display the dock */ unsigned int noclip:1; /* don't display the clip */ diff --git a/src/cycling.c b/src/cycling.c index 401a1082..8f01d6ce 100644 --- a/src/cycling.c +++ b/src/cycling.c @@ -47,10 +47,12 @@ extern WShortKey wKeyBindings[WKBD_LAST]; static void raiseWindow(WSwitchPanel *swpanel, WWindow *wwin) { + Window swwin= wSwitchPanelGetWindow(swpanel); + if (wwin->flags.mapped) { Window win[2]; - win[0]= wSwitchPanelGetWindow(swpanel); + win[0]= swwin; win[1]= wwin->frame->core->window; XRestackWindows(dpy, win, 2); @@ -249,9 +251,11 @@ StartWindozeCycle(WWindow *wwin, XEvent *event, Bool next) wSetFocusTo(scr, newFocused); } - if (swpanel) - wSwitchPanelDestroy(swpanel); - + if (!getenv("SWPDEBUG")) + { + if (swpanel) + wSwitchPanelDestroy(swpanel); + } scr->flags.doing_alt_tab = 0; if (somethingElse) diff --git a/src/defaults.c b/src/defaults.c index e5859dea..c4dd6771 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -129,7 +129,7 @@ static int getModMask(); #ifdef NEWSTUFF static int getRImage(); #endif - +static int getPLArray(); /* value setting functions */ static int setJustify(); @@ -173,11 +173,10 @@ static int setClipTitleFont(); static int setClipTitleColor(); static int setMenuStyle(); -#if 0 -static int setMultiByte(); -#endif +static int setSwPOptions(); static int updateUsableArea(); + extern Cursor wCursor[WCUR_LAST]; static int getCursor(); static int setCursor(); @@ -369,11 +368,6 @@ WDefaultEntry staticOptionList[] = { {"DisableMiniwindows", "NO", NULL, &wPreferences.disable_miniwindows, getBool, NULL } -#if 0 - ,{"MultiByteText", "NO", NULL, - &wPreferences.multi_byte_text, getBool, setMultiByte - } -#endif }; @@ -668,6 +662,9 @@ WDefaultEntry optionList[] = { {"IconTitleBack", "black", NULL, NULL, getColor, setIconTitleBack }, + {"SwitchPanelImages", "(\"swtile.png\")", &wPreferences, + NULL, getPLArray, setSwPOptions + }, /* keybindings */ #ifndef LITE {"RootMenuKey", "None", (void*)WKBD_ROOTMENU, @@ -1710,6 +1707,23 @@ again: } +static int +getPLArray(WScreen *scr, WDefaultEntry *entry, WMPropList *value, void *addr, + void **ret) +{ + if (!WMIsPLArray(value)) { + wwarning(_("Wrong value for key \"%s\". Should be an array."), + entry->key); + return False; + } + + WMRetainPropList(value); + + *ret= value; + + return True; +} + #if 0 /* This function is not used at the moment. */ static int @@ -3504,6 +3518,124 @@ setMenuStyle(WScreen *scr, WDefaultEntry *entry, int *value, void *foo) } +static RImage *chopOffImage(RImage *image, int x, int y, int w, int h) +{ + RImage *img= RCreateImage(w, h, image->format == RRGBAFormat); + + RCopyArea(img, image, x, y, w, h, 0, 0); + + return img; +} + +static int +setSwPOptions(WScreen *scr, WDefaultEntry *entry, WMPropList *array, void *foo) +{ + char *path; + RImage *bgimage; + int cwidth, cheight; + WPreferences *prefs= (WPreferences*)foo; + + switch (WMGetPropListItemCount(array)) + { + case 4: + path= FindImage(wPreferences.pixmap_path, WMGetFromPLString(WMGetFromPLArray(array, 1))); + if (!path) { + wwarning(_("Could not find image \"%s\" for option \"%s\""), + WMGetFromPLString(WMGetFromPLArray(array, 1)), + entry->key); + } else { + bgimage= RLoadImage(scr->rcontext, path, 0); + if (!bgimage) { + wwarning(_("Could not load image \"%s\" for option \"%s\""), + path, entry->key); + wfree(path); + } else { + wfree(path); + + cwidth= atoi(WMGetFromPLString(WMGetFromPLArray(array, 2))); + cheight= atoi(WMGetFromPLString(WMGetFromPLArray(array, 3))); + + if (cwidth <= 0 || cheight <= 0 || + cwidth >= bgimage->width - 2 || + cheight >= bgimage->height - 2) + wwarning(_("Invalid split sizes for SwitchPanel back image.")); + else { + int i; + int swidth, theight; + for (i= 0; i < 9; i++) { + if (prefs->swbackImage[i]) + RReleaseImage(prefs->swbackImage[i]); + prefs->swbackImage[i]= NULL; + } + swidth= (bgimage->width - cwidth) / 2; + theight= (bgimage->height - cheight) / 2; + + prefs->swbackImage[0]= chopOffImage(bgimage, 0, 0, + swidth, theight); + prefs->swbackImage[1]= chopOffImage(bgimage, swidth, 0, + cwidth, theight); + prefs->swbackImage[2]= chopOffImage(bgimage, swidth+cwidth, 0, + swidth, theight); + + prefs->swbackImage[3]= chopOffImage(bgimage, 0, theight, + swidth, cheight); + prefs->swbackImage[4]= chopOffImage(bgimage, swidth, theight, + cwidth, cheight); + prefs->swbackImage[5]= chopOffImage(bgimage, swidth+cwidth, theight, + swidth, cheight); + + prefs->swbackImage[6]= chopOffImage(bgimage, 0, theight+cheight, + swidth, theight); + prefs->swbackImage[7]= chopOffImage(bgimage, swidth, theight+cheight, + cwidth, theight); + prefs->swbackImage[8]= chopOffImage(bgimage, swidth+cwidth, theight+cheight, + swidth, theight); + + // check if anything failed + for (i= 0; i < 9; i++) { + if (!prefs->swbackImage[i]) { + for (; i>=0; --i) { + RReleaseImage(prefs->swbackImage[i]); + prefs->swbackImage[i]= NULL; + } + break; + } + } + } + RReleaseImage(bgimage); + } + } + + case 1: + path= FindImage(wPreferences.pixmap_path, WMGetFromPLString(WMGetFromPLArray(array, 0))); + if (!path) { + wwarning(_("Could not find image \"%s\" for option \"%s\""), + WMGetFromPLString(WMGetFromPLArray(array, 0)), + entry->key); + } else { + if (prefs->swtileImage) RReleaseImage(prefs->swtileImage); + + prefs->swtileImage= RLoadImage(scr->rcontext, path, 0); + if (!prefs->swtileImage) { + wwarning(_("Could not load image \"%s\" for option \"%s\""), + path, entry->key); + } + wfree(path); + } + break; + + default: + wwarning(_("Invalid number of arguments for option \"%s\""), + entry->key); + break; + } + + WMReleasePropList(array); + + return 0; +} + + /* static int setButtonImages(WScreen *scr, WDefaultEntry *entry, int *value, void *foo) @@ -3534,19 +3666,6 @@ setDoubleClick(WScreen *scr, WDefaultEntry *entry, int *value, void *foo) } -#if 0 -static int -setMultiByte(WScreen *scr, WDefaultEntry *entry, char *value, void *foo) -{ - extern _WINGsConfiguration WINGsConfiguration; - - WINGsConfiguration.useMultiByte = *value; - - return 0; -} -#endif - - static int setCursor(WScreen *scr, WDefaultEntry *entry, Cursor *cursor, long index) { diff --git a/src/misc.c b/src/misc.c index f7671a30..11a68709 100644 --- a/src/misc.c +++ b/src/misc.c @@ -424,9 +424,6 @@ ShrinkString(WMFont *font, char *string, int width) char *text; int p1, p2, t; - if (wPreferences.multi_byte_text) - return wstrdup(string); - p = strlen(string); w = WMWidthOfString(font, string, p); text = wmalloc(strlen(string)+8); diff --git a/src/switchpanel.c b/src/switchpanel.c index 531227ad..27643fef 100644 --- a/src/switchpanel.c +++ b/src/switchpanel.c @@ -23,6 +23,13 @@ #include #include +#include + +#ifdef SHAPE +#include + +extern Bool wShapeSupported; +#endif #include "WindowMaker.h" #include "screen.h" @@ -34,90 +41,28 @@ #include "funcs.h" #include "xinerama.h" - -static char * tile_xpm[] = { -"64 64 2 1", -" c None", -". c #FFFFFF", -" ................................................. ", -" ...................................................... ", -" ......................................................... ", -" ........................................................... ", -" ............................................................ ", -" .............................................................. ", -" .............................................................. ", -"............................................................... ", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -"................................................................", -" .............................................................. ", -" .............................................................. ", -" .............................................................. ", -" ............................................................ ", -" .......................................................... ", -" ........................................................ ", -" ...................................................... ", -" ................................................ "}; - - struct SwitchPanel { - WScreen *scr; - WMWindow *win; - WMBox *hbox; - WMLabel *label; - WMArray *icons; - WMArray *images; - WMArray *windows; - int current; + WScreen *scr; + WMWindow *win; + WMFrame *iconBox; - RImage *defIcon; - - RImage *tile; + WMArray *icons; + WMArray *images; + WMArray *windows; + RImage *bg; + int current; + int firstVisible; + int visibleCount; + + WMLabel *label; + + RImage *defIcon; + + RImage *tileTmp; + RImage *tile; + + WMFont *font; + WMColor *white; }; @@ -126,10 +71,12 @@ struct SwitchPanel { extern WPreferences wPreferences; -#define ICON_IDEAL_SIZE 48 -#define ICON_EXTRASPACE 16 +#define BORDER_SPACE 10 +#define ICON_SIZE 48 +#define ICON_TILE_SIZE 64 #define LABEL_HEIGHT 25 - +#define SCREEN_BORDER_SPACING 2*20 +#define SCROLL_STEPS (ICON_TILE_SIZE/2) static int canReceiveFocus(WWindow *wwin) { @@ -150,109 +97,310 @@ static int canReceiveFocus(WWindow *wwin) static void changeImage(WSwitchPanel *panel, int index, int selected) { - WMPixmap *pixmap= NULL; - WMLabel *label = WMGetFromArray(panel->icons, index); - RImage *image= WMGetFromArray(panel->images, index); + WMFrame *icon = WMGetFromArray(panel->icons, index); + RImage *image= WMGetFromArray(panel->images, index); - if (image && label) { - RColor bgColor; - RImage *back; - WMScreen *wscr= WMWidgetScreen(label); - int opaq= 255; - - if (canReceiveFocus(WMGetFromArray(panel->windows, index)) < 0) - opaq= 50; - - if (selected) { - back= RCloneImage(panel->tile); - RCombineAreaWithOpaqueness(back, image, 0, 0, image->width, image->height, - (back->width - image->width)/2, (back->height - image->height)/2, - opaq); - - pixmap= WMCreatePixmapFromRImage(wscr, back, -1); - RReleaseImage(back); - } else { - bgColor.alpha= opaq; - bgColor.red = WMRedComponentOfColor(WMGrayColor(wscr))>>8; - bgColor.green = WMGreenComponentOfColor(WMGrayColor(wscr))>>8; - bgColor.blue = WMBlueComponentOfColor(WMGrayColor(wscr))>>8; - - back= RCreateImage(image->width, image->height, 1); - RFillImage(back, &bgColor); - - RCombineImagesWithOpaqueness(back, image, opaq); - - pixmap= WMCreatePixmapFromRImage(wscr, back, -1); - RReleaseImage(back); + if (!panel->bg && !panel->tile) { + if (!selected) + WMSetFrameRelief(icon, WRFlat); } - } - if (pixmap && label) { - WMSetLabelImage(label, pixmap); - WMSetLabelImagePosition(label, WIPImageOnly); - WMReleasePixmap(pixmap); - } + if (image && icon) { + RImage *back; + int opaq= 255; + RImage *tile; + WMPoint pos; + Pixmap p; + + if (canReceiveFocus(WMGetFromArray(panel->windows, index)) < 0) + opaq= 50; + + pos= WMGetViewPosition(WMWidgetView(icon)); + back= panel->tileTmp; + if (panel->bg) + RCopyArea(back, panel->bg, + BORDER_SPACE+pos.x-panel->firstVisible*ICON_TILE_SIZE, BORDER_SPACE+pos.y, + back->width, back->height, + 0, 0); + else + { + RColor color; + WMScreen *wscr= WMWidgetScreen(icon); + color.red= 255; + color.red = WMRedComponentOfColor(WMGrayColor(wscr))>>8; + color.green = WMGreenComponentOfColor(WMGrayColor(wscr))>>8; + color.blue = WMBlueComponentOfColor(WMGrayColor(wscr))>>8; + RFillImage(back, &color); + } + if (selected) + { + tile= panel->tile; + RCombineArea(back, tile, 0, 0, tile->width, tile->height, + (back->width - tile->width)/2, (back->height - tile->height)/2); + } + RCombineAreaWithOpaqueness(back, image, 0, 0, image->width, image->height, + (back->width - image->width)/2, (back->height - image->height)/2, + opaq); + + RConvertImage(panel->scr->rcontext, back, &p); + XSetWindowBackgroundPixmap(dpy, WMWidgetXID(icon), p); + XClearWindow(dpy, WMWidgetXID(icon)); + XFreePixmap(dpy, p); + } + + if (!panel->bg && !panel->tile) { + if (selected) + WMSetFrameRelief(icon, WRSimple); + } } -static void addIconForWindow(WSwitchPanel *panel, WWindow *wwin, int iconWidth) +static RImage *scaleDownIfNeeded(RImage *image) { - WMLabel *label= WMCreateLabel(panel->hbox); - WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(label), False, True, iconWidth + ICON_EXTRASPACE, 0, 0); - RImage *image = NULL; + if (image && ((image->width - ICON_SIZE) > 2 || (image->height - ICON_SIZE) > 2)) { + RImage *nimage; + nimage= RScaleImage(image, ICON_SIZE, (image->height * ICON_SIZE / image->width)); + RReleaseImage(image); + image= nimage; + } + return image; +} - if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image) + +static void addIconForWindow(WSwitchPanel *panel, WMWidget *parent, WWindow *wwin, + int x, int y) +{ + WMFrame *icon= WMCreateFrame(parent); + RImage *image = NULL; + + WMSetFrameRelief(icon, WRFlat); + WMResizeWidget(icon, ICON_TILE_SIZE, ICON_TILE_SIZE); + WMMoveWidget(icon, x, y); + + if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image) image = RRetainImage(wwin->net_icon_image); - if (!image) + + // Make this use a caching thing. When there are many windows, + // it's very likely that most of them are instances of the same thing, + // so caching them should get performance acceptable in these cases. + if (!image) image = wDefaultGetImage(panel->scr, wwin->wm_instance, wwin->wm_class); - - if (!image && !panel->defIcon) - { - char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False); - if (file) { - char *path = FindImage(wPreferences.icon_path, file); - if (path) { - image = RLoadImage(panel->scr->rcontext, path, 0); - wfree(path); - } + + if (!image && !panel->defIcon) { + char *file = wDefaultGetIconFile(panel->scr, NULL, NULL, False); + if (file) { + char *path = FindImage(wPreferences.icon_path, file); + if (path) { + image = RLoadImage(panel->scr->rcontext, path, 0); + wfree(path); + } + } + if (image) + panel->defIcon= scaleDownIfNeeded(image); + image= NULL; } - } - if (!image && panel->defIcon) - image= RRetainImage(panel->defIcon); - - if (image && ((image->width - iconWidth) > 2 || (image->height - iconWidth) > 2)) { - RImage *nimage; - nimage= RScaleImage(image, iconWidth, (image->height * iconWidth / image->width)); - RReleaseImage(image); - image= nimage; - } - - WMAddToArray(panel->images, image); - WMAddToArray(panel->icons, label); + if (!image && panel->defIcon) + image= RRetainImage(panel->defIcon); + + image= scaleDownIfNeeded(image); + + WMAddToArray(panel->images, image); + WMAddToArray(panel->icons, icon); } -WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace) +static void scrollIcons(WSwitchPanel *panel, int delta) { - WWindow *wwin; - WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel)); + int nfirst= panel->firstVisible + delta; int i; - int width; - int height; - int iconWidth = ICON_IDEAL_SIZE; - WMBox *vbox; - int fl; - - memset(panel, 0, sizeof(WSwitchPanel)); + int count= WMGetArrayItemCount(panel->windows); +// int nx, ox; +// struct timeval tv1, tv2; - panel->scr= scr; - panel->windows= WMCreateArray(10); + if (count <= panel->visibleCount) + return; + + if (nfirst < 0) + nfirst= 0; + else if (nfirst >= count-panel->visibleCount) + nfirst= count-panel->visibleCount; + + if (nfirst == panel->firstVisible) + return; +/* + ox = -panel->firstVisible * ICON_TILE_SIZE; + nx = -nfirst * ICON_TILE_SIZE; + for (i= 0; i < SCROLL_STEPS; i++) { + unsigned int diff; + gettimeofday(&tv1, NULL); + WMMoveWidget(panel->iconBox, (nx*i + ox*(SCROLL_STEPS-i))/(SCROLL_STEPS-1), 0); + XSync(dpy, False); + gettimeofday(&tv2, NULL); + diff = (tv2.tv_sec-tv1.tv_sec)*10000+(tv2.tv_usec-tv1.tv_usec)/100; + if (diff < 200) + wusleep(300-diff); + } + */ + WMMoveWidget(panel->iconBox, -nfirst*ICON_TILE_SIZE, 0); + + panel->firstVisible= nfirst; + for (i= panel->firstVisible; i < panel->firstVisible+panel->visibleCount; i++) { + changeImage(panel, i, i == panel->current); + } +} + + +/* + * 0 1 2 + * 3 4 5 + * 6 7 8 + */ +static RImage *assemblePuzzleImage(RImage **images, int width, int height) +{ + RImage *img= RCreateImage(width, height, 1); + RImage *tmp; + int tw, th; + RColor color; + if (!img) + return NULL; + + color.red= 0; + color.green= 0; + color.blue= 0; + color.alpha= 255; + + RFillImage(img, &color); + + tw= width-images[0]->width-images[2]->width; + th= height-images[0]->height-images[6]->height; + + if (tw <= 0 || th <= 0) { + //XXX + return NULL; + } + + /* top */ + if (tw > 0) { + tmp= RSmoothScaleImage(images[1], tw, images[1]->height); + RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, + images[0]->width, 0); + RReleaseImage(tmp); + } + /* bottom */ + if (tw > 0) { + tmp= RSmoothScaleImage(images[7], tw, images[7]->height); + RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, + images[6]->width, height-images[6]->height); + RReleaseImage(tmp); + } + /* left */ + if (th > 0) { + tmp= RSmoothScaleImage(images[3], images[3]->width, th); + RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, + 0, images[0]->height); + RReleaseImage(tmp); + } + /* right */ + if (th > 0) { + tmp= RSmoothScaleImage(images[5], images[5]->width, th); + RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, + width-images[5]->width, images[2]->height); + RReleaseImage(tmp); + } + /* center */ + if (tw > 0 && th > 0) { + tmp= RSmoothScaleImage(images[4], tw, th); + RCopyArea(img, tmp, 0, 0, tmp->width, tmp->height, + images[0]->width, images[0]->height); + RReleaseImage(tmp); + } + + /* corners */ + RCopyArea(img, images[0], 0, 0, images[0]->width, images[0]->height, + 0, 0); + + RCopyArea(img, images[2], 0, 0, images[2]->width, images[2]->height, + width-images[2]->width, 0); + + RCopyArea(img, images[6], 0, 0, images[6]->width, images[6]->height, + 0, height-images[6]->height); + + RCopyArea(img, images[8], 0, 0, images[8]->width, images[8]->height, + width-images[8]->width, height-images[8]->height); + + return img; +} + +static RImage *createBackImage(WScreen *scr, int width, int height) +{ + return assemblePuzzleImage(wPreferences.swbackImage, width, height); +} + + +static RImage *getTile(WSwitchPanel *panel) +{ + RImage *stile; + + if (!wPreferences.swtileImage) + return NULL; + + stile = RScaleImage(wPreferences.swtileImage, ICON_TILE_SIZE, ICON_TILE_SIZE); + if (!stile) + return wPreferences.swtileImage; + + return stile; +} + + +static void +drawTitle(WSwitchPanel *panel, int index, char *title) +{ + char *ntitle; + int width= WMWidgetWidth(panel->win); + int x; + + ntitle= ShrinkString(panel->font, title, width-2*BORDER_SPACE); + + if (panel->bg) { + if (strcmp(ntitle, title)!=0) + x= BORDER_SPACE; + else + { + int w= WMWidthOfString(panel->font, ntitle, strlen(ntitle)); + + x= BORDER_SPACE+(index-panel->firstVisible)*ICON_TILE_SIZE + ICON_TILE_SIZE/2 - w/2; + if (x < BORDER_SPACE) + x= BORDER_SPACE; + else if (x + w > width-BORDER_SPACE) + x= width-BORDER_SPACE-w; + } + + XClearWindow(dpy, WMWidgetXID(panel->win)); + WMDrawString(panel->scr->wmscreen, + WMWidgetXID(panel->win), + panel->white, panel->font, + x, WMWidgetHeight(panel->win) - BORDER_SPACE - LABEL_HEIGHT + WMFontHeight(panel->font)/2, + ntitle, strlen(ntitle)); + } else { + WMSetLabelText(panel->label, ntitle); + } + free(ntitle); +} + + + +static WMArray *makeWindowListArray(WScreen *scr, WWindow *curwin, int workspace) +{ + WMArray *windows= WMCreateArray(10); + int fl; + WWindow *wwin; + for (fl= 0; fl < 2; fl++) { for (wwin= curwin; wwin; wwin= wwin->prev) { if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) && (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) { - WMInsertInArray(panel->windows, 0, wwin); + WMAddToArray(windows, wwin); } } wwin = curwin; @@ -263,112 +411,139 @@ WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace) for (wwin= curwin; wwin && wwin != curwin; wwin= wwin->prev) { if (((!fl && canReceiveFocus(wwin) > 0) || (fl && canReceiveFocus(wwin) < 0)) && (!WFLAGP(wwin, skip_window_list) || wwin->flags.internal_window)) { - WMInsertInArray(panel->windows, 0, wwin); + WMAddToArray(windows, wwin); } } } - width= (iconWidth + ICON_EXTRASPACE)*WMGetArrayItemCount(panel->windows); + return windows; +} + + + + + +WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace) +{ + WWindow *wwin; + WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel)); + WMFrame *viewport; + int i; + int width, height; + int iconsThatFitCount; + int count; + + memset(panel, 0, sizeof(WSwitchPanel)); + + panel->scr= scr; + + panel->windows= makeWindowListArray(scr, curwin, workspace); + count= WMGetArrayItemCount(panel->windows); - if (width > WMScreenWidth(scr->wmscreen)) - { - width= WMScreenWidth(scr->wmscreen) - 100; - iconWidth = width / WMGetArrayItemCount(panel->windows) - ICON_EXTRASPACE; - } - - if (WMGetArrayItemCount(panel->windows) == 0) { + if (count == 0) { WMFreeArray(panel->windows); wfree(panel); return NULL; } - - if (iconWidth < 16) { - /* if there are too many windows, don't bother trying to show the panel */ - return panel; + width= ICON_TILE_SIZE*count; + iconsThatFitCount= count; + + if (width > WMScreenWidth(scr->wmscreen)) { + iconsThatFitCount = (WMScreenWidth(scr->wmscreen)-SCREEN_BORDER_SPACING)/ICON_TILE_SIZE; + width= iconsThatFitCount*ICON_TILE_SIZE; } - height= iconWidth + LABEL_HEIGHT + 10 + ICON_EXTRASPACE + 10; - - panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows)); - panel->images= WMCreateArray(WMGetArrayItemCount(panel->windows)); - + panel->visibleCount= iconsThatFitCount; + + height= LABEL_HEIGHT + ICON_TILE_SIZE; + + panel->tileTmp= RCreateImage(ICON_TILE_SIZE, ICON_TILE_SIZE, 1); + panel->tile= getTile(panel); + if (panel->tile) { + panel->bg= createBackImage(scr, width+2*BORDER_SPACE, height+2*BORDER_SPACE); + } + if (!panel->tileTmp || !panel->tile) { + if (panel->bg) + RReleaseImage(panel->bg); + panel->bg= NULL; + if (panel->tile) + RReleaseImage(panel->tile); + panel->tile= NULL; + if (panel->tileTmp) + RReleaseImage(panel->tileTmp); + panel->tileTmp= NULL; + } + + panel->white= WMWhiteColor(scr->wmscreen); + panel->font= WMBoldSystemFontOfSize(scr->wmscreen, 12); + panel->icons= WMCreateArray(count); + panel->images= WMCreateArray(count); + panel->win = WMCreateWindow(scr->wmscreen, ""); - WMResizeWidget(panel->win, width + 10, height); - - { + + if (!panel->bg) { WMFrame *frame = WMCreateFrame(panel->win); WMSetFrameRelief(frame, WRSimple); WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0); - vbox = WMCreateBox(panel->win); - } - WMSetViewExpandsToParent(WMWidgetView(vbox), 5, 5, 5, 5); - WMSetBoxHorizontal(vbox, False); - - panel->label = WMCreateLabel(vbox); - WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->label), False, True, LABEL_HEIGHT, 0, 0); - if (scr->focused_window && scr->focused_window->frame->title) - WMSetLabelText(panel->label, scr->focused_window->frame->title); - else - WMSetLabelText(panel->label, ""); - - { - WMColor *color; - WMFont *boldFont= WMBoldSystemFontOfSize(scr->wmscreen, 12); - + panel->label = WMCreateLabel(panel->win); + WMResizeWidget(panel->label, width, LABEL_HEIGHT); + WMMoveWidget(panel->label, BORDER_SPACE, BORDER_SPACE+ICON_TILE_SIZE+5); WMSetLabelRelief(panel->label, WRSimple); - WMSetLabelFont(panel->label, boldFont); - color = WMDarkGrayColor(scr->wmscreen); - WMSetWidgetBackgroundColor(panel->label, color); - WMReleaseColor(color); - color = WMWhiteColor(scr->wmscreen); - WMSetLabelTextColor(panel->label, color); - WMReleaseColor(color); + WMSetWidgetBackgroundColor(panel->label, WMDarkGrayColor(scr->wmscreen)); + WMSetLabelFont(panel->label, panel->font); + WMSetLabelTextColor(panel->label, panel->white); - WMReleaseFont(boldFont); + height+= 5; } - - { - RImage *tmp= NULL; - RColor bgColor; - char *path = FindImage(wPreferences.pixmap_path, "swtile.png"); - if (path) { - tmp = RLoadImage(panel->scr->rcontext, path, 0); - wfree(path); - } - - if (!tmp) - tmp= RGetImageFromXPMData(scr->rcontext, tile_xpm); - - panel->tile = RScaleImage(tmp, iconWidth+ICON_EXTRASPACE, iconWidth+ICON_EXTRASPACE); - - bgColor.alpha = 255; - bgColor.red = WMRedComponentOfColor(WMGrayColor(scr->wmscreen))>>8; - bgColor.green = WMGreenComponentOfColor(WMGrayColor(scr->wmscreen))>>8; - bgColor.blue = WMBlueComponentOfColor(WMGrayColor(scr->wmscreen))>>8; - - RCombineImageWithColor(panel->tile, &bgColor); - - RReleaseImage(tmp); - } - - panel->hbox = WMCreateBox(vbox); - WMSetBoxHorizontal(panel->hbox, True); - WMAddBoxSubviewAtEnd(vbox, WMWidgetView(panel->hbox), True, True, 20, 0, 4); + + WMResizeWidget(panel->win, width + 2*BORDER_SPACE, height + 2*BORDER_SPACE); + + viewport= WMCreateFrame(panel->win); + WMResizeWidget(viewport, width, ICON_TILE_SIZE); + WMMoveWidget(viewport, BORDER_SPACE, BORDER_SPACE); + WMSetFrameRelief(viewport, WRFlat); + + panel->iconBox= WMCreateFrame(viewport); + WMMoveWidget(panel->iconBox, 0, 0); + WMResizeWidget(panel->iconBox, ICON_TILE_SIZE*count, ICON_TILE_SIZE); + WMSetFrameRelief(panel->iconBox, WRFlat); + + WM_ITERATE_ARRAY(panel->windows, wwin, i) { + addIconForWindow(panel, panel->iconBox, wwin, i*ICON_TILE_SIZE, 0); + } + + WMMapSubwidgets(panel->win); + WMRealizeWidget(panel->win); WM_ITERATE_ARRAY(panel->windows, wwin, i) { - addIconForWindow(panel, wwin, iconWidth); changeImage(panel, i, 0); } - WMMapSubwidgets(panel->win); - WMRealizeWidget(panel->win); + if (panel->bg) { + Pixmap pixmap, mask; + + RConvertImageMask(scr->rcontext, panel->bg, &pixmap, &mask, 254); + + XSetWindowBackgroundPixmap(dpy, WMWidgetXID(panel->win), pixmap); + +#ifdef SHAPE + if (mask && wShapeSupported) + XShapeCombineMask(dpy, WMWidgetXID(panel->win), + ShapeBounding, 0, 0, mask, ShapeSet); +#endif + + if (pixmap) + XFreePixmap(dpy, pixmap); + if (mask) + XFreePixmap(dpy, mask); + } + { WMPoint center; - center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), - width+10, height); + width+2*BORDER_SPACE, height+2*BORDER_SPACE); WMMoveWidget(panel->win, center.x, center.y); } @@ -384,86 +559,116 @@ WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace) void wSwitchPanelDestroy(WSwitchPanel *panel) { - int i; - RImage *image; + int i; + RImage *image; + + if (panel->win) + WMUnmapWidget(panel->win); - if (panel->images) { - WM_ITERATE_ARRAY(panel->images, image, i) { - if (image) - RReleaseImage(image); + if (panel->images) { + WM_ITERATE_ARRAY(panel->images, image, i) { + if (image) + RReleaseImage(image); + } + WMFreeArray(panel->images); } - WMFreeArray(panel->images); - } - if (panel->win) - WMDestroyWidget(panel->win); - if (panel->icons) - WMFreeArray(panel->icons); - WMFreeArray(panel->windows); - if (panel->defIcon) - RReleaseImage(panel->defIcon); - if (panel->tile) - RReleaseImage(panel->tile); - wfree(panel); + if (panel->win) + WMDestroyWidget(panel->win); + if (panel->icons) + WMFreeArray(panel->icons); + WMFreeArray(panel->windows); + if (panel->defIcon) + RReleaseImage(panel->defIcon); + if (panel->tile) + RReleaseImage(panel->tile); + if (panel->tileTmp) + RReleaseImage(panel->tileTmp); + if (panel->bg) + RReleaseImage(panel->bg); + if (panel->font) + WMReleaseFont(panel->font); + wfree(panel); } WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back) { - WWindow *wwin; - int count = WMGetArrayItemCount(panel->windows); + WWindow *wwin; + int count = WMGetArrayItemCount(panel->windows); + + if (count == 0) + return NULL; + + if (panel->win) + changeImage(panel, panel->current, 0); + + if (back) + panel->current--; + else + panel->current++; - if (count == 0) - return NULL; + wwin = WMGetFromArray(panel->windows, (count+panel->current)%count); - if (panel->win) - changeImage(panel, panel->current, 0); - - if (!back) - panel->current = (count + panel->current - 1) % count; - else - panel->current = (panel->current + 1) % count; + if (back) + { + if (panel->current < 0) + scrollIcons(panel, count); + else if (panel->current < panel->firstVisible) + scrollIcons(panel, -1); + } + else + { + if (panel->current >= count) + scrollIcons(panel, -count); + else if (panel->current - panel->firstVisible >= panel->visibleCount) + scrollIcons(panel, 1); + } - wwin = WMGetFromArray(panel->windows, panel->current); + panel->current= (count+panel->current)%count; - if (panel->win) { - WMSetLabelText(panel->label, wwin->frame->title); + if (panel->win) { + drawTitle(panel, panel->current, wwin->frame->title); - changeImage(panel, panel->current, 1); - } - return wwin; + changeImage(panel, panel->current, 1); + } + + return wwin; } WWindow *wSwitchPanelSelectFirst(WSwitchPanel *panel, int back) { - WWindow *wwin; - int count = WMGetArrayItemCount(panel->windows); + WWindow *wwin; + int count = WMGetArrayItemCount(panel->windows); - if (count == 0) - return NULL; + if (count == 0) + return NULL; - if (panel->win) - changeImage(panel, panel->current, 0); - - if (!back) - panel->current = count-1; - else - panel->current = 0; + if (panel->win) + changeImage(panel, panel->current, 0); + + if (back) { + panel->current = count-1; + scrollIcons(panel, count); + } else { + panel->current = 0; + scrollIcons(panel, -count); + } + + wwin = WMGetFromArray(panel->windows, panel->current); + + if (panel->win) { + drawTitle(panel, panel->current, wwin->frame->title); - wwin = WMGetFromArray(panel->windows, panel->current); - - if (panel->win) { - WMSetLabelText(panel->label, wwin->frame->title); - - changeImage(panel, panel->current, 1); - } - return wwin; + changeImage(panel, panel->current, 1); + } + return wwin; } WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event) { - WMLabel *label; + WMFrame *icon; int i; if (!panel->win) @@ -472,13 +677,16 @@ WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event) if (event->type == MotionNotify) { int focus= -1; - WM_ITERATE_ARRAY(panel->icons, label, i) { - if (WMWidgetXID(label) == event->xmotion.window) { + WM_ITERATE_ARRAY(panel->icons, icon, i) { + if (WMWidgetXID(icon) == event->xmotion.window) { focus= i; break; } } + if (focus < 0) + focus= 0; + if (focus >= 0 && panel->current != focus) { WWindow *wwin; @@ -488,7 +696,7 @@ WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event) wwin= WMGetFromArray(panel->windows, focus); - WMSetLabelText(panel->label, wwin->frame->title); + drawTitle(panel, panel->current, wwin->frame->title); return wwin; } @@ -500,5 +708,7 @@ WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event) Window wSwitchPanelGetWindow(WSwitchPanel *swpanel) { + if (!swpanel->win) + return None; return WMWidgetXID(swpanel->win); } diff --git a/wrlib/raster.c b/wrlib/raster.c index ac57a97e..5296232e 100644 --- a/wrlib/raster.c +++ b/wrlib/raster.c @@ -447,7 +447,12 @@ RCopyArea(RImage *image, RImage *src, int sx, int sy, unsigned width, } } else { for (y=0; y < height; y++) { - memcpy(d, s, width*3); + for (x=0; x < width; x++) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + s++; + } d += dwi; s += swi; }