From f274afdd1d6e11455089b10f79b599de64b18ef7 Mon Sep 17 00:00:00 2001 From: kojima Date: Mon, 25 Oct 2004 00:07:51 +0000 Subject: [PATCH] added themable, pixmap background switch panel --- ChangeLog | 2 +- NEWS | 35 ++ WINGs/WINGs/WINGs.h | 2 + WINGs/wcolor.c | 13 + WindowMaker/Pixmaps/Makefile.am | 3 +- WindowMaker/Pixmaps/swback.png | Bin 0 -> 4192 bytes src/WindowMaker.h | 3 + src/cycling.c | 12 +- src/defaults.c | 163 +++++- src/misc.c | 3 - src/switchpanel.c | 1218 +++++++++++++++++++++++---------------- wrlib/raster.c | 7 +- 12 files changed, 925 insertions(+), 536 deletions(-) create mode 100644 WindowMaker/Pixmaps/swback.png rewrite src/switchpanel.c (69%) 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 0000000000000000000000000000000000000000..fab56ac3322352511bfcdbeb73de05fc27fef520 GIT binary patch literal 4192 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.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 dissimilarity index 69% index 531227ad..27643fef 100644 --- a/src/switchpanel.c +++ b/src/switchpanel.c @@ -1,504 +1,714 @@ -/* - * Window Maker window manager - * - * Copyright (c) 1997-2004 Alfredo K. Kojima - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -#include "wconfig.h" - -#include -#include - -#include "WindowMaker.h" -#include "screen.h" -#include "wcore.h" -#include "framewin.h" -#include "window.h" -#include "defaults.h" -#include "switchpanel.h" -#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; - - RImage *defIcon; - - RImage *tile; -}; - - - - - -extern WPreferences wPreferences; - -#define ICON_IDEAL_SIZE 48 -#define ICON_EXTRASPACE 16 -#define LABEL_HEIGHT 25 - - -static int canReceiveFocus(WWindow *wwin) -{ - if (wwin->frame->workspace != wwin->screen_ptr->current_workspace) - return 0; - if (!wwin->flags.mapped) - { - if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden) - return 0; - else - return -1; - } - if (WFLAGP(wwin, no_focusable)) - return 0; - return 1; -} - - -static void changeImage(WSwitchPanel *panel, int index, int selected) -{ - WMPixmap *pixmap= NULL; - WMLabel *label = 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 (pixmap && label) { - WMSetLabelImage(label, pixmap); - WMSetLabelImagePosition(label, WIPImageOnly); - WMReleasePixmap(pixmap); - } -} - - -static void addIconForWindow(WSwitchPanel *panel, WWindow *wwin, int iconWidth) -{ - WMLabel *label= WMCreateLabel(panel->hbox); - WMAddBoxSubviewAtEnd(panel->hbox, WMWidgetView(label), False, True, iconWidth + ICON_EXTRASPACE, 0, 0); - RImage *image = NULL; - - if (!WFLAGP(wwin, always_user_icon) && wwin->net_icon_image) - image = RRetainImage(wwin->net_icon_image); - 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) - 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); -} - - -WSwitchPanel *wInitSwitchPanel(WScreen *scr, WWindow *curwin, int workspace) -{ - WWindow *wwin; - WSwitchPanel *panel= wmalloc(sizeof(WSwitchPanel)); - int i; - int width; - int height; - int iconWidth = ICON_IDEAL_SIZE; - WMBox *vbox; - int fl; - - memset(panel, 0, sizeof(WSwitchPanel)); - - panel->scr= scr; - panel->windows= WMCreateArray(10); - - 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); - } - } - wwin = curwin; - /* start over from the beginning of the list */ - while (wwin->next) - wwin = wwin->next; - - 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); - } - } - } - - width= (iconWidth + ICON_EXTRASPACE)*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) { - 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; - } - - height= iconWidth + LABEL_HEIGHT + 10 + ICON_EXTRASPACE + 10; - - panel->icons= WMCreateArray(WMGetArrayItemCount(panel->windows)); - panel->images= WMCreateArray(WMGetArrayItemCount(panel->windows)); - - panel->win = WMCreateWindow(scr->wmscreen, ""); - WMResizeWidget(panel->win, width + 10, height); - - { - 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); - - 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); - - WMReleaseFont(boldFont); - } - - { - 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); - - WM_ITERATE_ARRAY(panel->windows, wwin, i) { - addIconForWindow(panel, wwin, iconWidth); - changeImage(panel, i, 0); - } - - WMMapSubwidgets(panel->win); - WMRealizeWidget(panel->win); - { - WMPoint center; - - center= wGetPointToCenterRectInHead(scr, wGetHeadForPointerLocation(scr), - width+10, height); - WMMoveWidget(panel->win, center.x, center.y); - } - - panel->current= WMGetFirstInArray(panel->windows, curwin); - if (panel->current >= 0) - changeImage(panel, panel->current, 1); - - WMMapWidget(panel->win); - - return panel; -} - - -void wSwitchPanelDestroy(WSwitchPanel *panel) -{ - int i; - RImage *image; - - if (panel->images) { - WM_ITERATE_ARRAY(panel->images, image, i) { - if (image) - RReleaseImage(image); - } - 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); -} - - -WWindow *wSwitchPanelSelectNext(WSwitchPanel *panel, int back) -{ - WWindow *wwin; - int count = WMGetArrayItemCount(panel->windows); - - if (count == 0) - return NULL; - - if (panel->win) - changeImage(panel, panel->current, 0); - - if (!back) - panel->current = (count + panel->current - 1) % count; - else - panel->current = (panel->current + 1) % count; - - wwin = WMGetFromArray(panel->windows, panel->current); - - if (panel->win) { - WMSetLabelText(panel->label, wwin->frame->title); - - changeImage(panel, panel->current, 1); - } - return wwin; -} - - -WWindow *wSwitchPanelSelectFirst(WSwitchPanel *panel, int back) -{ - WWindow *wwin; - int count = WMGetArrayItemCount(panel->windows); - - if (count == 0) - return NULL; - - if (panel->win) - changeImage(panel, panel->current, 0); - - if (!back) - panel->current = count-1; - else - panel->current = 0; - - wwin = WMGetFromArray(panel->windows, panel->current); - - if (panel->win) { - WMSetLabelText(panel->label, wwin->frame->title); - - changeImage(panel, panel->current, 1); - } - return wwin; -} - - -WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event) -{ - WMLabel *label; - int i; - - if (!panel->win) - return NULL; - - if (event->type == MotionNotify) { - int focus= -1; - - WM_ITERATE_ARRAY(panel->icons, label, i) { - if (WMWidgetXID(label) == event->xmotion.window) { - focus= i; - break; - } - } - - if (focus >= 0 && panel->current != focus) { - WWindow *wwin; - - changeImage(panel, panel->current, 0); - changeImage(panel, focus, 1); - panel->current= focus; - - wwin= WMGetFromArray(panel->windows, focus); - - WMSetLabelText(panel->label, wwin->frame->title); - - return wwin; - } - } - - return NULL; -} - - -Window wSwitchPanelGetWindow(WSwitchPanel *swpanel) -{ - return WMWidgetXID(swpanel->win); -} +/* + * Window Maker window manager + * + * Copyright (c) 1997-2004 Alfredo K. Kojima + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "wconfig.h" + +#include +#include +#include + +#ifdef SHAPE +#include + +extern Bool wShapeSupported; +#endif + +#include "WindowMaker.h" +#include "screen.h" +#include "wcore.h" +#include "framewin.h" +#include "window.h" +#include "defaults.h" +#include "switchpanel.h" +#include "funcs.h" +#include "xinerama.h" + +struct SwitchPanel { + WScreen *scr; + WMWindow *win; + WMFrame *iconBox; + + 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; +}; + + + + + +extern WPreferences wPreferences; + +#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) +{ + if (wwin->frame->workspace != wwin->screen_ptr->current_workspace) + return 0; + if (!wwin->flags.mapped) + { + if (!wwin->flags.shaded && !wwin->flags.miniaturized && !wwin->flags.hidden) + return 0; + else + return -1; + } + if (WFLAGP(wwin, no_focusable)) + return 0; + return 1; +} + + +static void changeImage(WSwitchPanel *panel, int index, int selected) +{ + WMFrame *icon = WMGetFromArray(panel->icons, index); + RImage *image= WMGetFromArray(panel->images, index); + + if (!panel->bg && !panel->tile) { + if (!selected) + WMSetFrameRelief(icon, WRFlat); + } + + 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 RImage *scaleDownIfNeeded(RImage *image) +{ + 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; +} + + +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); + + // 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= scaleDownIfNeeded(image); + image= NULL; + } + if (!image && panel->defIcon) + image= RRetainImage(panel->defIcon); + + image= scaleDownIfNeeded(image); + + WMAddToArray(panel->images, image); + WMAddToArray(panel->icons, icon); +} + + +static void scrollIcons(WSwitchPanel *panel, int delta) +{ + int nfirst= panel->firstVisible + delta; + int i; + int count= WMGetArrayItemCount(panel->windows); +// int nx, ox; +// struct timeval tv1, tv2; + + 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)) { + WMAddToArray(windows, wwin); + } + } + wwin = curwin; + /* start over from the beginning of the list */ + while (wwin->next) + wwin = wwin->next; + + 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)) { + WMAddToArray(windows, wwin); + } + } + } + + 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 (count == 0) { + WMFreeArray(panel->windows); + wfree(panel); + return NULL; + } + + 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; + } + + 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, ""); + + if (!panel->bg) { + WMFrame *frame = WMCreateFrame(panel->win); + WMSetFrameRelief(frame, WRSimple); + WMSetViewExpandsToParent(WMWidgetView(frame), 0, 0, 0, 0); + + 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); + WMSetWidgetBackgroundColor(panel->label, WMDarkGrayColor(scr->wmscreen)); + WMSetLabelFont(panel->label, panel->font); + WMSetLabelTextColor(panel->label, panel->white); + + height+= 5; + } + + 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) { + changeImage(panel, i, 0); + } + + 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+2*BORDER_SPACE, height+2*BORDER_SPACE); + WMMoveWidget(panel->win, center.x, center.y); + } + + panel->current= WMGetFirstInArray(panel->windows, curwin); + if (panel->current >= 0) + changeImage(panel, panel->current, 1); + + WMMapWidget(panel->win); + + return panel; +} + + +void wSwitchPanelDestroy(WSwitchPanel *panel) +{ + int i; + RImage *image; + + if (panel->win) + WMUnmapWidget(panel->win); + + if (panel->images) { + WM_ITERATE_ARRAY(panel->images, image, i) { + if (image) + RReleaseImage(image); + } + 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); + 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); + + if (count == 0) + return NULL; + + if (panel->win) + changeImage(panel, panel->current, 0); + + if (back) + panel->current--; + else + panel->current++; + + wwin = WMGetFromArray(panel->windows, (count+panel->current)%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); + } + + panel->current= (count+panel->current)%count; + + if (panel->win) { + drawTitle(panel, panel->current, wwin->frame->title); + + changeImage(panel, panel->current, 1); + } + + return wwin; +} + + +WWindow *wSwitchPanelSelectFirst(WSwitchPanel *panel, int back) +{ + WWindow *wwin; + int count = WMGetArrayItemCount(panel->windows); + + if (count == 0) + return NULL; + + 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); + + changeImage(panel, panel->current, 1); + } + return wwin; +} + + +WWindow *wSwitchPanelHandleEvent(WSwitchPanel *panel, XEvent *event) +{ + WMFrame *icon; + int i; + + if (!panel->win) + return NULL; + + if (event->type == MotionNotify) { + int focus= -1; + + 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; + + changeImage(panel, panel->current, 0); + changeImage(panel, focus, 1); + panel->current= focus; + + wwin= WMGetFromArray(panel->windows, focus); + + drawTitle(panel, panel->current, wwin->frame->title); + + return wwin; + } + } + + return NULL; +} + + +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; } -- 2.11.4.GIT