From dfe7e255b20c2117dd5ba18a87801325060f7477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:27 +0200 Subject: [PATCH 01/20] Deleted useless test If btn->omnipresent, then btn->dock is precisely scr->workspaces[scr->current_workspace]->clip (cf. wWorkspaceForceChange() calling wClipUpdateForWorkspaceChange()) --- src/dock.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dock.c b/src/dock.c index 21d6aeec..6b6c1849 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3796,10 +3796,7 @@ static void clipEnterNotify(WObjDescriptor *desc, XEvent *event) return; scr = btn->icon->core->screen_ptr; - if (!btn->omnipresent) - dock = btn->dock; - else - dock = scr->workspaces[scr->current_workspace]->clip; + dock = btn->dock; if (!dock || dock->type != WM_CLIP) return; From be95172c951639cb1c92c15ea147bb5750406162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:28 +0200 Subject: [PATCH 02/20] Avoid clip flickering when docking an appicon In handleIconMove, when moving an appicon near the clip, all clips were systematically shown each time the mouse moved, causing some flickering (perhaps only perceptible on a low-end machine?). This patch introduces a showed_all_clips boolean to expand clips only once. --- src/dock.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dock.c b/src/dock.c index 6b6c1849..8b75a167 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3429,6 +3429,7 @@ static Bool handleIconMove(WDock *dock, WAppIcon *aicon, XEvent *event) Bool docked; int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ int omnipresent = aicon->omnipresent; /* this must be cached!!! */ + Bool showed_all_clips = False; Bool hasMoved = False; if (wPreferences.flags.noupdates) @@ -3489,13 +3490,17 @@ static Bool handleIconMove(WDock *dock, WAppIcon *aicon, XEvent *event) } } - if (omnipresent) { + if (omnipresent && !showed_all_clips) { int i; for (i = 0; i < scr->workspace_count; i++) { if (i == scr->current_workspace) continue; wDockShowIcons(scr->workspaces[i]->clip); + /* Note: if dock is collapsed (for instance, + because it auto-collapses), its icons + still won't show up */ } + showed_all_clips = True; /* To prevent flickering */ } x = ev.xmotion.x_root - ofs_x; @@ -3605,7 +3610,7 @@ static Bool handleIconMove(WDock *dock, WAppIcon *aicon, XEvent *event) XFreePixmap(dpy, ghost); XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel); } - if (omnipresent) { + if (showed_all_clips) { int i; for (i = 0; i < scr->workspace_count; i++) { if (i == scr->current_workspace) From cc02023e3e55c39f7fa1f1e88bd8e83139b54d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:29 +0200 Subject: [PATCH 03/20] BF for "some obscured windows briefly appears when switching workspaces" When changing workspace, mapped windows are unmapped from top to bottom (referring to their stacking order), causing mapped but obscured windows to briefly appear when the obscuring window is unmapped and until they are themselves unmapped. [This might not be visible on recent hardware]. The fix is to unmap windows in reverse stacking order when changing workspace. --- src/workspace.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/workspace.c b/src/workspace.c index 491452b3..2fd3925c 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -462,6 +462,8 @@ void wWorkspaceRelativeChange(WScreen * scr, int amount) void wWorkspaceForceChange(WScreen * scr, int workspace) { WWindow *tmp, *foc = NULL, *foc2 = NULL; + WWindow **toUnmap; + int toUnmapSize, toUnmapCount; if (workspace >= MAX_WORKSPACES || workspace < 0) return; @@ -480,6 +482,10 @@ void wWorkspaceForceChange(WScreen * scr, int workspace) wWorkspaceMenuUpdate(scr, scr->clip_ws_menu); + toUnmapSize = 16; + toUnmapCount = 0; + toUnmap = wmalloc(toUnmapSize * sizeof(WWindow *)); + if ((tmp = scr->focused_window) != NULL) { if ((IS_OMNIPRESENT(tmp) && (tmp->flags.mapped || tmp->flags.shaded) && !WFLAGP(tmp, no_focusable)) || tmp->flags.changing_workspace) { @@ -494,7 +500,12 @@ void wWorkspaceForceChange(WScreen * scr, int workspace) /* unmap windows not on this workspace */ if ((tmp->flags.mapped || tmp->flags.shaded) && !IS_OMNIPRESENT(tmp) && !tmp->flags.changing_workspace) { - wWindowUnmap(tmp); + if (toUnmapCount == toUnmapSize) + { + toUnmapSize *= 2; + toUnmap = wrealloc(toUnmap, toUnmapSize * sizeof(WWindow *)); + } + toUnmap[toUnmapCount++] = tmp; } /* also unmap miniwindows not on this workspace */ if (!wPreferences.sticky_icons && tmp->flags.miniaturized && @@ -543,6 +554,12 @@ void wWorkspaceForceChange(WScreen * scr, int workspace) tmp = tmp->prev; } + while (toUnmapCount > 0) + { + wWindowUnmap(toUnmap[--toUnmapCount]); + } + wfree(toUnmap); + /* Gobble up events unleashed by our mapping & unmapping. * These may trigger various grab-initiated focus & * crossing events. However, we don't care about them, From 9548c42b71893bb27bf747276eb7ce2046658758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:30 +0200 Subject: [PATCH 04/20] Fix leading spaces in comment (trivial) --- src/appicon.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/appicon.c b/src/appicon.c index 573344c2..e969d39f 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -764,12 +764,12 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) WMHandleEvent(&ev); break; - case EnterNotify: - /* It means the cursor moved so fast that it entered - * something else (if moving slowly, it would have - * stayed in the appIcon that is being moved. Ignore - * such "spurious" EnterNotifiy's */ - break; + case EnterNotify: + /* It means the cursor moved so fast that it entered + * something else (if moving slowly, it would have + * stayed in the appIcon that is being moved. Ignore + * such "spurious" EnterNotifiy's */ + break; case MotionNotify: hasMoved = True; From 4b440204887478ba9f4709bacbb01def3f20da5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:31 +0200 Subject: [PATCH 05/20] WPrefs: consolidate the 2 createImages static functions into a global one --- WPrefs.app/Configurations.c | 41 +----------- WPrefs.app/WPrefs.c | 55 ++++++++++++++++ WPrefs.app/WPrefs.h | 7 ++ WPrefs.app/Workspace.c | 126 +++++++++++------------------------- 4 files changed, 100 insertions(+), 129 deletions(-) diff --git a/WPrefs.app/Configurations.c b/WPrefs.app/Configurations.c index e64d8c11..55b15375 100644 --- a/WPrefs.app/Configurations.c +++ b/WPrefs.app/Configurations.c @@ -111,43 +111,6 @@ static void updateLabel(WMWidget *self, void *data) WMSetLabelText(panel->dithL, buffer); } -static void -createImages(WMScreen *scr, RContext *rc, RImage *xis, char *file, - WMPixmap **icon1, WMPixmap **icon2) -{ - RImage *icon; - char *path; - RColor gray = { 0xae, 0xaa, 0xae, 0 }; - - *icon1 = NULL; - *icon2 = NULL; - - path = LocateImage(file); - if (!path) - return; - - *icon1 = WMCreatePixmapFromFile(scr, path); - if (!*icon1) { - wwarning(_("could not load icon %s"), path); - wfree(path); - return; - } - icon = RLoadImage(rc, path, 0); - if (!icon) { - wwarning(_("could not load icon %s"), path); - wfree(path); - return; - } - RCombineImageWithColor(icon, &gray); - if (xis) { - RCombineImagesWithOpaqueness(icon, xis, 180); - if (!(*icon2 = WMCreatePixmapFromRImage(scr, icon, 127))) - wwarning(_("could not process icon %s: %s"), file, RMessageForError(RErrorCode)); - } - RReleaseImage(icon); - wfree(path); -} - static void createPanel(Panel *p) { _Panel *panel = (_Panel *) p; @@ -342,7 +305,7 @@ static void createPanel(Panel *p) WMSetButtonFont(panel->animB, font); WMSetButtonText(panel->animB, _("Animations")); WMSetButtonImagePosition(panel->animB, WIPAbove); - createImages(scr, rc, xis, ANIM_IMAGE, &altIcon, &icon); + CreateImages(scr, rc, xis, ANIM_IMAGE, &altIcon, &icon); if (icon) { WMSetButtonImage(panel->animB, icon); WMReleasePixmap(icon); @@ -360,7 +323,7 @@ static void createPanel(Panel *p) WMSetButtonFont(panel->supB, font); WMSetButtonText(panel->supB, _("Superfluous")); WMSetButtonImagePosition(panel->supB, WIPAbove); - createImages(scr, rc, xis, SUPERF_IMAGE, &altIcon, &icon); + CreateImages(scr, rc, xis, SUPERF_IMAGE, &altIcon, &icon); if (icon) { WMSetButtonImage(panel->supB, icon); WMReleasePixmap(icon); diff --git a/WPrefs.app/WPrefs.c b/WPrefs.app/WPrefs.c index 2b69b51f..17ef8640 100644 --- a/WPrefs.app/WPrefs.c +++ b/WPrefs.app/WPrefs.c @@ -392,6 +392,61 @@ char *LocateImage(char *name) return path; } +void CreateImages(WMScreen *scr, RContext *rc, RImage *xis, char *file, + WMPixmap **icon_normal, WMPixmap **icon_greyed) +{ + RImage *icon; + char *path; + RColor gray = { 0xae, 0xaa, 0xae, 0 }; + + path = LocateImage(file); + if (!path) + { + *icon_normal = NULL; + if (icon_greyed) + *icon_greyed = NULL; + return; + } + + *icon_normal = WMCreatePixmapFromFile(scr, path); + if (!*icon_normal) + { + wwarning(_("could not load icon %s"), path); + if (icon_greyed) + *icon_greyed = NULL; + wfree(path); + return; + } + + if (!icon_greyed) // Greyed-out version not requested, we are done + { + wfree(path); + return; + } + + icon = RLoadImage(rc, path, 0); + if (!icon) + { + wwarning(_("could not load icon %s"), path); + *icon_greyed = NULL; + wfree(path); + return; + } + RCombineImageWithColor(icon, &gray); + if (xis) + { + RCombineImagesWithOpaqueness(icon, xis, 180); + } + *icon_greyed = WMCreatePixmapFromRImage(scr, icon, 127); + if (!*icon_greyed) + { + wwarning(_("could not process icon %s: %s"), path, RMessageForError(RErrorCode)); + } + RReleaseImage(icon); + wfree(path); +} + + static WMPixmap *makeTitledIcon(WMScreen * scr, WMPixmap * icon, char *title1, char *title2) { return WMRetainPixmap(icon); diff --git a/WPrefs.app/WPrefs.h b/WPrefs.app/WPrefs.h index 900afdcb..5100ef66 100644 --- a/WPrefs.app/WPrefs.h +++ b/WPrefs.app/WPrefs.h @@ -76,6 +76,13 @@ char *LocateImage(char *name); void SetButtonAlphaImage(WMScreen *scr, WMButton *bPtr, char *file, char *title1, char *title2); +/* Loads `file' into `icon_normal'. If `icon_greyed' is not NULL, + * combine `icon_normal' with some grey and then optionally with image + * `xis', and store it in `icon_greyed' (typically to produce a + * greyed-out, red-crossed version of `icon_normal') */ +void CreateImages(WMScreen *scr, RContext *rc, RImage *xis, char *file, + WMPixmap **icon_normal, WMPixmap **icon_greyed); + WMWindow *GetWindow(Panel *panel); /* manipulate the dictionary for the WindowMaker domain */ diff --git a/WPrefs.app/Workspace.c b/WPrefs.app/Workspace.c index 6ba26fcd..83cdccdc 100644 --- a/WPrefs.app/Workspace.c +++ b/WPrefs.app/Workspace.c @@ -71,40 +71,6 @@ static char *WSNamePositions[] = { "bottomright" }; -static void -createImages(WMScreen * scr, RContext * rc, RImage * xis, char *file, WMPixmap ** icon1, WMPixmap ** icon2) -{ - RImage *icon; - RColor gray = { 0xae, 0xaa, 0xae, 0 }; - - *icon1 = WMCreatePixmapFromFile(scr, file); - if (!*icon1) { - wwarning(_("could not load icon %s"), file); - if (icon2) - *icon2 = NULL; - return; - } - - if (!icon2) - return; - - icon = RLoadImage(rc, file, 0); - if (!icon) { - wwarning(_("could not load icon %s"), file); - *icon2 = NULL; - return; - } - RCombineImageWithColor(icon, &gray); - if (xis) { - RCombineImagesWithOpaqueness(icon, xis, 180); - if (!(*icon2 = WMCreatePixmapFromRImage(scr, icon, 127))) { - wwarning(_("could not process icon %s: %s"), file, RMessageForError(RErrorCode)); - *icon2 = NULL; - } - } - RReleaseImage(icon); -} - static void showData(_Panel * panel) { int i, idx; @@ -170,14 +136,11 @@ static void createPanel(Panel * p) WMResizeWidget(panel->cyclL, 60, 60); WMMoveWidget(panel->cyclL, 10, 15); WMSetLabelImagePosition(panel->cyclL, WIPImageOnly); - path = LocateImage(CYCLE_FILE); - if (path) { - createImages(scr, rc, xis, path, &icon1, NULL); - if (icon1) { - WMSetLabelImage(panel->cyclL, icon1); - WMReleasePixmap(icon1); - } - wfree(path); + CreateImages(scr, rc, xis, CYCLE_FILE, &icon1, NULL); + if (icon1) + { + WMSetLabelImage(panel->cyclL, icon1); + WMReleasePixmap(icon1); } /**/ panel->linkB = WMCreateSwitchButton(panel->navF); @@ -189,14 +152,11 @@ static void createPanel(Panel * p) WMResizeWidget(panel->linkL, 60, 40); WMMoveWidget(panel->linkL, 10, 80); WMSetLabelImagePosition(panel->linkL, WIPImageOnly); - path = LocateImage(DONT_LINK_FILE); - if (path) { - createImages(scr, rc, xis, path, &icon1, NULL); - if (icon1) { - WMSetLabelImage(panel->linkL, icon1); - WMReleasePixmap(icon1); - } - wfree(path); + CreateImages(scr, rc, xis, DONT_LINK_FILE, &icon1, NULL); + if (icon1) + { + WMSetLabelImage(panel->linkL, icon1); + WMReleasePixmap(icon1); } /**/ panel->newB = WMCreateSwitchButton(panel->navF); @@ -208,14 +168,11 @@ static void createPanel(Panel * p) WMResizeWidget(panel->newL, 60, 20); WMMoveWidget(panel->newL, 10, 130); WMSetLabelImagePosition(panel->newL, WIPImageOnly); - path = LocateImage(ADVANCE_FILE); - if (path) { - createImages(scr, rc, xis, path, &icon1, NULL); - if (icon1) { - WMSetLabelImage(panel->newL, icon1); - WMReleasePixmap(icon1); - } - wfree(path); + CreateImages(scr, rc, xis, ADVANCE_FILE, &icon1, NULL); + if (icon1) + { + WMSetLabelImage(panel->newL, icon1); + WMReleasePixmap(icon1); } /**/ panel->posL = WMCreateLabel(panel->navF); @@ -228,14 +185,11 @@ static void createPanel(Panel * p) WMResizeWidget(panel->posiL, 60, 40); WMMoveWidget(panel->posiL, 10, 160); WMSetLabelImagePosition(panel->posiL, WIPImageOnly); - path = LocateImage(WSNAME_FILE); - if (path) { - createImages(scr, rc, xis, path, &icon1, NULL); - if (icon1) { - WMSetLabelImage(panel->posiL, icon1); - WMReleasePixmap(icon1); - } - wfree(path); + CreateImages(scr, rc, xis, WSNAME_FILE, &icon1, NULL); + if (icon1) + { + WMSetLabelImage(panel->posiL, icon1); + WMReleasePixmap(icon1); } panel->posP = WMCreatePopUpButton(panel->navF); @@ -262,18 +216,14 @@ static void createPanel(Panel * p) WMResizeWidget(panel->dockB, 64, 64); WMMoveWidget(panel->dockB, 25, 35); WMSetButtonImagePosition(panel->dockB, WIPImageOnly); - path = LocateImage(DOCK_FILE); - if (path) { - createImages(scr, rc, xis, path, &icon1, &icon2); - if (icon2) { - WMSetButtonImage(panel->dockB, icon2); - WMReleasePixmap(icon2); - } - if (icon1) { - WMSetButtonAltImage(panel->dockB, icon1); - WMReleasePixmap(icon1); - } - wfree(path); + CreateImages(scr, rc, xis, DOCK_FILE, &icon1, &icon2); + if (icon2) { + WMSetButtonImage(panel->dockB, icon2); + WMReleasePixmap(icon2); + } + if (icon1) { + WMSetButtonAltImage(panel->dockB, icon1); + WMReleasePixmap(icon1); } WMSetBalloonTextForView(_("Disable/enable the application Dock (the\n" "vertical icon bar in the side of the screen)."), WMWidgetView(panel->dockB)); @@ -282,18 +232,14 @@ static void createPanel(Panel * p) WMResizeWidget(panel->clipB, 64, 64); WMMoveWidget(panel->clipB, 25, 120); WMSetButtonImagePosition(panel->clipB, WIPImageOnly); - path = LocateImage(CLIP_FILE); - if (path) { - createImages(scr, rc, xis, path, &icon1, &icon2); - if (icon2) { - WMSetButtonImage(panel->clipB, icon2); - WMReleasePixmap(icon2); - } - if (icon1) { - WMSetButtonAltImage(panel->clipB, icon1); - WMReleasePixmap(icon1); - } - wfree(path); + CreateImages(scr, rc, xis, CLIP_FILE, &icon1, &icon2); + if (icon2) { + WMSetButtonImage(panel->clipB, icon2); + WMReleasePixmap(icon2); + } + if (icon1) { + WMSetButtonAltImage(panel->clipB, icon1); + WMReleasePixmap(icon1); } WMSetBalloonTextForView(_("Disable/enable the Clip (that thing with\n" "a paper clip icon)."), WMWidgetView(panel->clipB)); From 6f44be87fc3a956ae32a0d5ffd0aba7e2dcf225b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:32 +0200 Subject: [PATCH 06/20] Consolidated all code checking whether a tile is fully on screen in one static function The function existed before, but had all kinds of unneeded arguments and wasn't called everywhere. --- src/dock.c | 54 +++++++++++++++++------------------------------------- 1 file changed, 17 insertions(+), 37 deletions(-) diff --git a/src/dock.c b/src/dock.c index 8b75a167..443c09e3 100644 --- a/src/dock.c +++ b/src/dock.c @@ -118,6 +118,8 @@ static void clipAutoRaise(void *cdata); static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y); static WAppIcon *mainIconCreate(WScreen *scr, int type); +static int onScreen(WScreen *scr, int x, int y); + static void make_keys(void) { if (dCommand != NULL) @@ -1477,19 +1479,11 @@ WAppIcon *wClipRestoreState(WScreen *scr, WMPropList *clip_state) if (!WMIsPLString(value)) { COMPLAIN("Position"); } else { - WMRect rect; - int flags; - if (sscanf(WMGetFromPLString(value), "%i,%i", &icon->x_pos, &icon->y_pos) != 2) COMPLAIN("Position"); /* check position sanity */ - rect.pos.x = icon->x_pos; - rect.pos.y = icon->y_pos; - rect.size.width = rect.size.height = ICON_SIZE; - - wGetRectPlacementInfo(scr, rect, &flags); - if (flags & (XFLAG_DEAD | XFLAG_PARTIAL)) + if (!onScreen(scr, icon->x_pos, icon->y_pos)) wScreenKeepInside(scr, &icon->x_pos, &icon->y_pos, ICON_SIZE, ICON_SIZE); } } @@ -1529,19 +1523,11 @@ WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) if (!WMIsPLString(value)) { COMPLAIN("Position"); } else { - WMRect rect; - int flags; - if (sscanf(WMGetFromPLString(value), "%i,%i", &dock->x_pos, &dock->y_pos) != 2) COMPLAIN("Position"); /* check position sanity */ - rect.pos.x = dock->x_pos; - rect.pos.y = dock->y_pos; - rect.size.width = rect.size.height = ICON_SIZE; - - wGetRectPlacementInfo(scr, rect, &flags); - if (flags & (XFLAG_DEAD | XFLAG_PARTIAL)) { + if (!onScreen(scr, dock->x_pos, dock->y_pos)) { int x = dock->x_pos; wScreenKeepInside(scr, &x, &dock->y_pos, ICON_SIZE, ICON_SIZE); } @@ -2228,18 +2214,8 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x ex_x = (req_x + offset - dx) / ICON_SIZE; /* check if the icon is outside the screen boundaries */ - { - WMRect rect; - int flags; - - rect.pos.x = dx + ex_x * ICON_SIZE; - rect.pos.y = dy + ex_y * ICON_SIZE; - rect.size.width = rect.size.height = ICON_SIZE; - - wGetRectPlacementInfo(scr, rect, &flags); - if (flags & (XFLAG_DEAD | XFLAG_PARTIAL)) - return False; - } + if (!onScreen(scr, dx + ex_x * ICON_SIZE, dy + ex_y * ICON_SIZE)) + return False; if (dock->type == WM_DOCK) { if (icon->dock != dock && ex_x != 0) @@ -2365,11 +2341,15 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x return False; } -static int onScreen(WScreen *scr, int x, int y, int sx, int ex, int sy, int ey) +static int onScreen(WScreen *scr, int x, int y) { - WMRect rect = wmkrect(x, y, ICON_SIZE, ICON_SIZE); + WMRect rect; int flags; + rect.pos.x = x; + rect.pos.y = y; + rect.size.width = rect.size.height = ICON_SIZE; + wGetRectPlacementInfo(scr, rect, &flags); return !(flags & (XFLAG_DEAD | XFLAG_PARTIAL)); @@ -2391,7 +2371,7 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) int x, y; int i, done = False; int corner; - int sx = 0, sy = 0, ex = scr->scr_width, ey = scr->scr_height; + int sx = 0, ex = scr->scr_width, ey = scr->scr_height; int extra_count = 0; if (dock->type == WM_CLIP && dock != scr->workspaces[scr->current_workspace]->clip) @@ -2603,7 +2583,7 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) tx = dock->x_pos + x * ICON_SIZE; y = -i; ty = dock->y_pos + y * ICON_SIZE; - if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty, sx, ex, sy, ey)) { + if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty)) { *x_pos = x; *y_pos = y; done = 1; @@ -2611,7 +2591,7 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) } y = i; ty = dock->y_pos + y * ICON_SIZE; - if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty, sx, ex, sy, ey)) { + if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty)) { *x_pos = x; *y_pos = y; done = 1; @@ -2623,7 +2603,7 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) ty = dock->y_pos + y * ICON_SIZE; x = -i; tx = dock->x_pos + x * ICON_SIZE; - if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty, sx, ex, sy, ey)) { + if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty)) { *x_pos = x; *y_pos = y; done = 1; @@ -2631,7 +2611,7 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) } x = i; tx = dock->x_pos + x * ICON_SIZE; - if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty, sx, ex, sy, ey)) { + if (slot_map[XY2OFS(x, y)] == 0 && onScreen(scr, tx, ty)) { *x_pos = x; *y_pos = y; done = 1; From d24cbc79eea3c8782cb77bfa28805de0b0570612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:33 +0200 Subject: [PATCH 07/20] Make the clip's auto-delays configurable The options are ClipAutoraiseDelay, ClipAutolowerDelay, ClipAutoexpandDelay, ClipAutocollapseDelay The default values are weird but merely represent the previously hard-coded ones. They are repeated in Defaults/WindowMaker to avoid a WPrefs crash (but it's a good idea to make them "visible", too) WPrefs change coming up --- WindowMaker/Defaults/WindowMaker.in | 4 ++++ src/WindowMaker.h | 6 ++++++ src/defaults.c | 8 ++++++++ src/dock.c | 8 ++++---- src/wconfig.h.in | 14 -------------- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/WindowMaker/Defaults/WindowMaker.in b/WindowMaker/Defaults/WindowMaker.in index 3e576bea..500046e9 100644 --- a/WindowMaker/Defaults/WindowMaker.in +++ b/WindowMaker/Defaults/WindowMaker.in @@ -131,4 +131,8 @@ MenuTitleBack = (solid, black); MenuTextBack = (solid, "rgb:aa/aa/aa"); IconBack = (dgradient, "rgb:a6/a6/b6", "rgb:51/55/61"); + ClipAutocollapseDelay = 1000; + ClipAutolowerDelay = 1000; + ClipAutoexpandDelay = 600; + ClipAutoraiseDelay = 600; } diff --git a/src/WindowMaker.h b/src/WindowMaker.h index 039a67ba..25e1a757 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -419,6 +419,12 @@ typedef struct WPreferences { char cycle_active_head_only; /* Cycle only windows on the active head */ char cycle_ignore_minimized; /* Ignore minimized windows when cycling */ + /* All delays here are in ms. 0 means instant auto-action. */ + int clip_auto_raise_delay; /* Delay after which the clip will be raised when entered */ + int clip_auto_lower_delay; /* Delay after which the clip will be lowered when leaved */ + int clip_auto_expand_delay; /* Delay after which the clip will expand when entered */ + int clip_auto_collapse_delay; /* Delay after which the clip will collapse when leaved */ + RImage *swtileImage; RImage *swbackImage[9]; diff --git a/src/defaults.c b/src/defaults.c index f04e9be5..3119aebc 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -394,6 +394,14 @@ WDefaultEntry optionList[] = { &wPreferences.do_not_make_appicons_bounce, getBool, NULL, NULL, NULL}, {"DoubleClickTime", "250", (void *)&wPreferences.dblclick_time, &wPreferences.dblclick_time, getInt, setDoubleClick, NULL, NULL}, + {"ClipAutoraiseDelay", "600", NULL, + &wPreferences.clip_auto_raise_delay, getInt, NULL, NULL, NULL}, + {"ClipAutolowerDelay", "1000", NULL, + &wPreferences.clip_auto_lower_delay, getInt, NULL, NULL, NULL}, + {"ClipAutoexpandDelay", "600", NULL, + &wPreferences.clip_auto_expand_delay, getInt, NULL, NULL, NULL}, + {"ClipAutocollapseDelay", "1000", NULL, + &wPreferences.clip_auto_collapse_delay, getInt, NULL, NULL, NULL}, {"AlignSubmenus", "NO", NULL, &wPreferences.align_menus, getBool, NULL, NULL, NULL}, {"ViKeyMenus", "NO", NULL, diff --git a/src/dock.c b/src/dock.c index 443c09e3..9c2f35e8 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3792,7 +3792,7 @@ static void clipEnterNotify(WObjDescriptor *desc, XEvent *event) dock->auto_lower_magic = NULL; } if (dock->auto_raise_lower && !dock->auto_raise_magic) - dock->auto_raise_magic = WMAddTimerHandler(AUTO_RAISE_DELAY, clipAutoRaise, (void *)dock); + dock->auto_raise_magic = WMAddTimerHandler(wPreferences.clip_auto_raise_delay, clipAutoRaise, (void *)dock); /* The auto expand/collapse code */ if (dock->auto_collapse_magic) { @@ -3800,7 +3800,7 @@ static void clipEnterNotify(WObjDescriptor *desc, XEvent *event) dock->auto_collapse_magic = NULL; } if (dock->auto_collapse && !dock->auto_expand_magic) - dock->auto_expand_magic = WMAddTimerHandler(AUTO_EXPAND_DELAY, clipAutoExpand, (void *)dock); + dock->auto_expand_magic = WMAddTimerHandler(wPreferences.clip_auto_expand_delay, clipAutoExpand, (void *)dock); } static void clipLeave(WDock *dock) @@ -3832,14 +3832,14 @@ static void clipLeave(WDock *dock) dock->auto_raise_magic = NULL; } if (dock->auto_raise_lower && !dock->auto_lower_magic) - dock->auto_lower_magic = WMAddTimerHandler(AUTO_LOWER_DELAY, clipAutoLower, (void *)dock); + dock->auto_lower_magic = WMAddTimerHandler(wPreferences.clip_auto_lower_delay, clipAutoLower, (void *)dock); if (dock->auto_expand_magic) { WMDeleteTimerHandler(dock->auto_expand_magic); dock->auto_expand_magic = NULL; } if (dock->auto_collapse && !dock->auto_collapse_magic) - dock->auto_collapse_magic = WMAddTimerHandler(AUTO_COLLAPSE_DELAY, clipAutoCollapse, (void *)dock); + dock->auto_collapse_magic = WMAddTimerHandler(wPreferences.clip_auto_collapse_delay, clipAutoCollapse, (void *)dock); } static void clipLeaveNotify(WObjDescriptor *desc, XEvent *event) diff --git a/src/wconfig.h.in b/src/wconfig.h.in index c21638d3..58b00444 100644 --- a/src/wconfig.h.in +++ b/src/wconfig.h.in @@ -301,20 +301,6 @@ * a docked icon must be dragged out to detach it */ #define DOCK_DETTACH_THRESHOLD 3 -/* Delay (in ms) after which the clip will autocollapse when leaved */ -#define AUTO_COLLAPSE_DELAY 1000 - -/* Delay (in ms) after which the clip will autoexpand when entered. - * Set this to zero if you want instant expanding. */ -#define AUTO_EXPAND_DELAY 600 - -/* Delay (in ms) after which the clip will be lowered when leaved */ -#define AUTO_LOWER_DELAY 1000 - -/* Delay (in ms) after which the clip will be raised when entered. - * Set this to zero if you want instant raise. */ -#define AUTO_RAISE_DELAY 600 - /* Max. number of icons the dock and clip can have */ #define DOCK_MAX_ICONS 32 From 5a6e1653acdce6e65e7c4af7b647b11c0cbc4046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:34 +0200 Subject: [PATCH 08/20] WPrefs: new Docks pannel, to change auto-expand/collapse/etc delays --- WPrefs.app/Docks.c | 292 +++++++++ WPrefs.app/Makefile.am | 1 + WPrefs.app/WPrefs.c | 3 + WPrefs.app/Workspace.c | 69 +- WPrefs.app/tiff/Makefile.am | 1 + WPrefs.app/tiff/dockclipsection.tiff | Bin 0 -> 7248 bytes WPrefs.app/xpm/Makefile.am | 1 + WPrefs.app/xpm/dockclipsection.xpm | 946 +++++++++++++++++++++++++++ 8 files changed, 1252 insertions(+), 61 deletions(-) create mode 100644 WPrefs.app/Docks.c create mode 100644 WPrefs.app/tiff/dockclipsection.tiff create mode 100644 WPrefs.app/xpm/dockclipsection.xpm diff --git a/WPrefs.app/Docks.c b/WPrefs.app/Docks.c new file mode 100644 index 00000000..b3b821c1 --- /dev/null +++ b/WPrefs.app/Docks.c @@ -0,0 +1,292 @@ +/* Workspace.c- workspace options + * + * WPrefs - Window Maker Preferences Program + * + * Copyright (c) 2012 Daniel Déchelotte (heavily inspired from file (c) 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "WPrefs.h" + +typedef struct _Panel { + WMBox *box; + + char *sectionName; + + char *description; + + CallbackRec callbacks; + + WMWidget *parent; + + WMFrame *autoDelayF[2]; + WMLabel *autoDelayL[4]; + WMButton *autoDelayB[4][5]; + WMTextField *autoDelayT[4]; + + WMFrame *dockF; + WMButton *dockB; + WMButton *clipB; +} _Panel; + +#define ICON_FILE "dockclipsection" + +#define ARQUIVO_XIS "xis" +#define DELAY_ICON "timer%i" +#define DELAY_ICON_S "timer%is" +#define DOCK_FILE "dock" +#define CLIP_FILE "clip" + +static char *autoDelayStrings[4]; +static char *autoDelayKeys[4] = { "ClipAutoexpandDelay", "ClipAutocollapseDelay", "ClipAutoraiseDelay", "ClipAutolowerDelay" }; +static char *autoDelayPresetValues[5] = { "0", "100", "250", "600", "1000" }; + +static void showData(_Panel *panel); +static void storeData(_Panel *panel); + + +static void pushAutoDelayButton(WMWidget *w, void *data) +{ + _Panel *panel = (_Panel *) data; + int i, j; + for (i = 0; i < 4; i++) + { + for (j = 0; j < 5; j++) + { + if (w == panel->autoDelayB[i][j]) + { + WMSetTextFieldText(panel->autoDelayT[i], autoDelayPresetValues[j]); + return; + } + } + } +} + +static void adjustButtonSelectionBasedOnValue(_Panel *panel, int row, char *value) +{ + int j; + for (j = 0; j < 5; j++) + { + int isThatOne = !strcmp(autoDelayPresetValues[j], value); + WMSetButtonSelected(panel->autoDelayB[row][j], isThatOne); + if (isThatOne) + return; + } +} + +static void autoDelayChanged(void *observerData, WMNotification *notification) +{ + _Panel *panel = (_Panel *) observerData; + int row; + WMTextField *anAutoDelayT = (WMTextField *) WMGetNotificationObject(notification); + for (row = 0; row < 4; row++) + { + if (anAutoDelayT != panel->autoDelayT[row]) + { + continue; + } + char *value = WMGetTextFieldText(anAutoDelayT); + adjustButtonSelectionBasedOnValue(panel, row, value); + return; + } +} + +static void createPanel(Panel *p) +{ + _Panel *panel = (_Panel *) p; + WMScreen *scr = WMWidgetScreen(panel->parent); + WMPixmap *icon1, *icon2; + RImage *xis = NULL; + RContext *rc = WMScreenRContext(scr); + char *path; + int i, j, k; + char *buf1, *buf2; + + path = LocateImage(ARQUIVO_XIS); + if (path) { + xis = RLoadImage(rc, path, 0); + if (!xis) { + wwarning(_("could not load image file %s"), path); + } + wfree(path); + } + + panel->box = WMCreateBox(panel->parent); + WMSetViewExpandsToParent(WMWidgetView(panel->box), 2, 2, 2, 2); + + /***************** Auto-delays *****************/ + buf1 = wmalloc(strlen(DELAY_ICON) + 1); + buf2 = wmalloc(strlen(DELAY_ICON_S) + 1); + + for (k = 0; k < 2; k++) + { + panel->autoDelayF[k] = WMCreateFrame(panel->box); + WMResizeWidget(panel->autoDelayF[k], 365, 100); + WMMoveWidget(panel->autoDelayF[k], 15, 10 + k * 110); + if (k == 0) + WMSetFrameTitle(panel->autoDelayF[k], _("Delays in milliseconds for autocollapsing clips")); + else + WMSetFrameTitle(panel->autoDelayF[k], _("Delays in milliseconds for autoraising clips")); + + for (i = 0; i < 2; i++) + { + panel->autoDelayL[i + k * 2] = WMCreateLabel(panel->autoDelayF[k]); + WMResizeWidget(panel->autoDelayL[i + k * 2], 165, 20); + WMMoveWidget(panel->autoDelayL[i + k * 2], 10, 27 + 40 * i); + WMSetLabelText(panel->autoDelayL[i + k * 2], autoDelayStrings[i + k * 2]); + WMSetLabelTextAlignment(panel->autoDelayL[i + k * 2], WARight); + + for (j = 0; j < 5; j++) + { + panel->autoDelayB[i + k * 2][j] = WMCreateCustomButton(panel->autoDelayF[k], WBBStateChangeMask); + WMResizeWidget(panel->autoDelayB[i + k * 2][j], 25, 25); + WMMoveWidget(panel->autoDelayB[i + k * 2][j], 175 + (25 * j), 25 + 40 * i); + WMSetButtonBordered(panel->autoDelayB[i + k * 2][j], False); + WMSetButtonImagePosition(panel->autoDelayB[i + k * 2][j], WIPImageOnly); + WMSetButtonAction(panel->autoDelayB[i + k * 2][j], pushAutoDelayButton, panel); + if (j > 0) + WMGroupButtons(panel->autoDelayB[i + k * 2][0], panel->autoDelayB[i + k * 2][j]); + sprintf(buf1, DELAY_ICON, j); + CreateImages(scr, rc, NULL, buf1, &icon1, NULL); + if (icon1) { + WMSetButtonImage(panel->autoDelayB[i + k * 2][j], icon1); + WMReleasePixmap(icon1); + } else { + wwarning(_("could not load icon file %s"), buf1); + } + sprintf(buf2, DELAY_ICON_S, j); + CreateImages(scr, rc, NULL, buf2, &icon2, NULL); + if (icon2) { + WMSetButtonAltImage(panel->autoDelayB[i + k * 2][j], icon2); + WMReleasePixmap(icon2); + } else { + wwarning(_("could not load icon file %s"), buf2); + } + } + + panel->autoDelayT[i + k * 2] = WMCreateTextField(panel->autoDelayF[k]); + WMResizeWidget(panel->autoDelayT[i + k * 2], 36, 20); + WMMoveWidget(panel->autoDelayT[i + k * 2], 310, 27 + 40 * i); + WMAddNotificationObserver(autoDelayChanged, panel, WMTextDidChangeNotification, panel->autoDelayT[i + k * 2]); + } + + WMMapSubwidgets(panel->autoDelayF[k]); + } + wfree(buf1); + wfree(buf2); + + /***************** Enable/disable clip/dock *****************/ + panel->dockF = WMCreateFrame(panel->box); + WMResizeWidget(panel->dockF, 115, 210); + WMMoveWidget(panel->dockF, 390, 10); + WMSetFrameTitle(panel->dockF, _("Dock/Clip")); + + panel->dockB = WMCreateButton(panel->dockF, WBTToggle); + WMResizeWidget(panel->dockB, 64, 64); + WMMoveWidget(panel->dockB, 25, 35); + WMSetButtonImagePosition(panel->dockB, WIPImageOnly); + CreateImages(scr, rc, xis, DOCK_FILE, &icon1, &icon2); + if (icon2) { + WMSetButtonImage(panel->dockB, icon2); + WMReleasePixmap(icon2); + } + if (icon1) { + WMSetButtonAltImage(panel->dockB, icon1); + WMReleasePixmap(icon1); + } + WMSetBalloonTextForView(_("Disable/enable the application Dock (the\n" + "vertical icon bar in the side of the screen)."), WMWidgetView(panel->dockB)); + + panel->clipB = WMCreateButton(panel->dockF, WBTToggle); + WMResizeWidget(panel->clipB, 64, 64); + WMMoveWidget(panel->clipB, 25, 120); + WMSetButtonImagePosition(panel->clipB, WIPImageOnly); + CreateImages(scr, rc, xis, CLIP_FILE, &icon1, &icon2); + if (icon2) { + WMSetButtonImage(panel->clipB, icon2); + WMReleasePixmap(icon2); + } + if (icon1) { + WMSetButtonAltImage(panel->clipB, icon1); + WMReleasePixmap(icon1); + } + WMSetBalloonTextForView(_("Disable/enable the Clip (that thing with\n" + "a paper clip icon)."), WMWidgetView(panel->clipB)); + + WMMapSubwidgets(panel->dockF); + + if (xis) + RReleaseImage(xis); + + WMRealizeWidget(panel->box); + WMMapSubwidgets(panel->box); + + showData(panel); +} + +static void storeData(_Panel *panel) +{ + int i; + for (i = 0; i < 4; i++) + { + SetStringForKey(WMGetTextFieldText(panel->autoDelayT[i]), autoDelayKeys[i]); + } + + SetBoolForKey(!WMGetButtonSelected(panel->dockB), "DisableDock"); + SetBoolForKey(!WMGetButtonSelected(panel->clipB), "DisableClip"); +} + +static void showData(_Panel *panel) +{ + char *value; + int i; + for (i = 0; i < 4; i++) + { + value = GetStringForKey(autoDelayKeys[i]); + WMSetTextFieldText(panel->autoDelayT[i], value); + adjustButtonSelectionBasedOnValue(panel, i, value); + } + + WMSetButtonSelected(panel->dockB, !GetBoolForKey("DisableDock")); + WMSetButtonSelected(panel->clipB, !GetBoolForKey("DisableClip")); +} + +Panel *InitDocks(WMScreen *scr, WMWidget *parent) +{ + _Panel *panel; + + autoDelayStrings[0] = _("Delay before auto-expansion"); + autoDelayStrings[1] = _("Delay before auto-collapsing"); + autoDelayStrings[2] = _("Delay before auto-raise"); + autoDelayStrings[3] = _("Delay before auto-lowering"); + + panel = wmalloc(sizeof(_Panel)); + memset(panel, 0, sizeof(_Panel)); + + panel->sectionName = _("Dock Preferences"); + + panel->description = _("Dock and clip features.\n" + "Enable/disable the Dock and Clip, and tune some delays."); + + panel->parent = parent; + + panel->callbacks.createWidgets = createPanel; + panel->callbacks.updateDomain = storeData; + + AddSection(panel, ICON_FILE); + + return panel; +} diff --git a/WPrefs.app/Makefile.am b/WPrefs.app/Makefile.am index 7929f4a1..15f0b6e8 100644 --- a/WPrefs.app/Makefile.am +++ b/WPrefs.app/Makefile.am @@ -18,6 +18,7 @@ WPrefs_SOURCES = \ WPrefs.h \ Appearance.c \ Configurations.c \ + Docks.c \ Expert.c \ Focus.c \ FontSimple.c \ diff --git a/WPrefs.app/WPrefs.c b/WPrefs.app/WPrefs.c index 17ef8640..94b248fe 100644 --- a/WPrefs.app/WPrefs.c +++ b/WPrefs.app/WPrefs.c @@ -32,6 +32,8 @@ extern Panel *InitKeyboardShortcuts(WMScreen * scr, WMWidget * parent); extern Panel *InitWorkspace(WMScreen * scr, WMWidget * parent); +extern Panel *InitDocks(WMScreen *scr, WMWidget *parent); + extern Panel *InitFocus(WMScreen * scr, WMWidget * parent); extern Panel *InitPreferences(WMScreen * scr, WMWidget * parent); @@ -663,6 +665,7 @@ void Initialize(WMScreen * scr) InitPreferences(scr, WPrefs.banner); InitPaths(scr, WPrefs.banner); + InitDocks(scr, WPrefs.banner); InitWorkspace(scr, WPrefs.banner); InitConfigurations(scr, WPrefs.banner); diff --git a/WPrefs.app/Workspace.c b/WPrefs.app/Workspace.c index 83cdccdc..24064a48 100644 --- a/WPrefs.app/Workspace.c +++ b/WPrefs.app/Workspace.c @@ -44,10 +44,6 @@ typedef struct _Panel { WMLabel *posiL; WMLabel *posL; WMPopUpButton *posP; - - WMFrame *dockF; - WMButton *dockB; - WMButton *clipB; } _Panel; #define ICON_FILE "workspace" @@ -57,8 +53,6 @@ typedef struct _Panel { #define CYCLE_FILE "cycleworkspaces" #define ADVANCE_FILE "advancetonewworkspace" #define WSNAME_FILE "workspacename" -#define DOCK_FILE "dock" -#define CLIP_FILE "clip" static char *WSNamePositions[] = { "none", @@ -82,10 +76,6 @@ static void showData(_Panel * panel) WMSetButtonSelected(panel->newB, GetBoolForKey("AdvanceToNewWorkspace")); - WMSetButtonSelected(panel->dockB, !GetBoolForKey("DisableDock")); - - WMSetButtonSelected(panel->clipB, !GetBoolForKey("DisableClip")); - str = GetStringForKey("WorkspaceNameDisplayPosition"); if (!str) str = "center"; @@ -123,12 +113,12 @@ static void createPanel(Panel * p) /***************** Workspace Navigation *****************/ panel->navF = WMCreateFrame(panel->box); - WMResizeWidget(panel->navF, 365, 210); + WMResizeWidget(panel->navF, 490, 210); WMMoveWidget(panel->navF, 15, 10); WMSetFrameTitle(panel->navF, _("Workspace Navigation")); panel->cyclB = WMCreateSwitchButton(panel->navF); - WMResizeWidget(panel->cyclB, 280, 34); + WMResizeWidget(panel->cyclB, 410, 34); WMMoveWidget(panel->cyclB, 75, 30); WMSetButtonText(panel->cyclB, _("Wrap to the first workspace from the last workspace.")); @@ -144,7 +134,7 @@ static void createPanel(Panel * p) } /**/ panel->linkB = WMCreateSwitchButton(panel->navF); - WMResizeWidget(panel->linkB, 280, 34); + WMResizeWidget(panel->linkB, 410, 34); WMMoveWidget(panel->linkB, 75, 75); WMSetButtonText(panel->linkB, _("Switch workspaces while dragging windows.")); @@ -160,7 +150,7 @@ static void createPanel(Panel * p) } /**/ panel->newB = WMCreateSwitchButton(panel->navF); - WMResizeWidget(panel->newB, 280, 34); + WMResizeWidget(panel->newB, 410, 34); WMMoveWidget(panel->newB, 75, 120); WMSetButtonText(panel->newB, _("Automatically create new workspaces.")); @@ -176,10 +166,10 @@ static void createPanel(Panel * p) } /**/ panel->posL = WMCreateLabel(panel->navF); - WMResizeWidget(panel->posL, 140, 30); + WMResizeWidget(panel->posL, 200, 30); WMMoveWidget(panel->posL, 75, 165); - WMSetLabelTextAlignment(panel->posL, WARight); - WMSetLabelText(panel->posL, _("Position of workspace\nname display")); + // WMSetLabelTextAlignment(panel->posL, WARight); + WMSetLabelText(panel->posL, _("Position of workspace name display")); panel->posiL = WMCreateLabel(panel->navF); WMResizeWidget(panel->posiL, 60, 40); @@ -194,7 +184,7 @@ static void createPanel(Panel * p) panel->posP = WMCreatePopUpButton(panel->navF); WMResizeWidget(panel->posP, 125, 20); - WMMoveWidget(panel->posP, 225, 175); + WMMoveWidget(panel->posP, 290, 170); WMAddPopUpButtonItem(panel->posP, _("Disable")); WMAddPopUpButtonItem(panel->posP, _("Center")); WMAddPopUpButtonItem(panel->posP, _("Top")); @@ -206,46 +196,6 @@ static void createPanel(Panel * p) WMMapSubwidgets(panel->navF); - /***************** Dock/Clip *****************/ - panel->dockF = WMCreateFrame(panel->box); - WMResizeWidget(panel->dockF, 115, 210); - WMMoveWidget(panel->dockF, 390, 10); - WMSetFrameTitle(panel->dockF, _("Dock/Clip")); - - panel->dockB = WMCreateButton(panel->dockF, WBTToggle); - WMResizeWidget(panel->dockB, 64, 64); - WMMoveWidget(panel->dockB, 25, 35); - WMSetButtonImagePosition(panel->dockB, WIPImageOnly); - CreateImages(scr, rc, xis, DOCK_FILE, &icon1, &icon2); - if (icon2) { - WMSetButtonImage(panel->dockB, icon2); - WMReleasePixmap(icon2); - } - if (icon1) { - WMSetButtonAltImage(panel->dockB, icon1); - WMReleasePixmap(icon1); - } - WMSetBalloonTextForView(_("Disable/enable the application Dock (the\n" - "vertical icon bar in the side of the screen)."), WMWidgetView(panel->dockB)); - - panel->clipB = WMCreateButton(panel->dockF, WBTToggle); - WMResizeWidget(panel->clipB, 64, 64); - WMMoveWidget(panel->clipB, 25, 120); - WMSetButtonImagePosition(panel->clipB, WIPImageOnly); - CreateImages(scr, rc, xis, CLIP_FILE, &icon1, &icon2); - if (icon2) { - WMSetButtonImage(panel->clipB, icon2); - WMReleasePixmap(icon2); - } - if (icon1) { - WMSetButtonAltImage(panel->clipB, icon1); - WMReleasePixmap(icon1); - } - WMSetBalloonTextForView(_("Disable/enable the Clip (that thing with\n" - "a paper clip icon)."), WMWidgetView(panel->clipB)); - - WMMapSubwidgets(panel->dockF); - if (xis) RReleaseImage(xis); @@ -261,9 +211,6 @@ static void storeData(_Panel * panel) SetBoolForKey(WMGetButtonSelected(panel->cyclB), "CycleWorkspaces"); SetBoolForKey(WMGetButtonSelected(panel->newB), "AdvanceToNewWorkspace"); - SetBoolForKey(!WMGetButtonSelected(panel->dockB), "DisableDock"); - SetBoolForKey(!WMGetButtonSelected(panel->clipB), "DisableClip"); - SetStringForKey(WSNamePositions[WMGetPopUpButtonSelectedItem(panel->posP)], "WorkspaceNameDisplayPosition"); } diff --git a/WPrefs.app/tiff/Makefile.am b/WPrefs.app/tiff/Makefile.am index fe21243a..76fced4a 100644 --- a/WPrefs.app/tiff/Makefile.am +++ b/WPrefs.app/tiff/Makefile.am @@ -8,6 +8,7 @@ EXTRA_DIST = \ configs.tiff \ cycleworkspaces.tiff \ dock.tiff \ + dockclipsection.tiff \ dontlinkworkspaces.tiff \ ergonomic.tiff \ expert.tiff \ diff --git a/WPrefs.app/tiff/dockclipsection.tiff b/WPrefs.app/tiff/dockclipsection.tiff new file mode 100644 index 0000000000000000000000000000000000000000..22801e112d7790f31c6dd6ca9c351a13a89a6214 GIT binary patch literal 7248 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 c #E9E9F1", +", c #E8E8F0", +"' c #E7E8EF", +") c #E6E7EE", +"! c #E5E6ED", +"~ c #E4E5EC", +"{ c #E3E4EB", +"] c #E2E3EA", +"^ c #E1E2E9", +"/ c #E0E1E8", +"( c #B1B1B3", +"_ c #DEDEE2", +": c #F2F2F8", +"< c #F0F1F8", +"[ c #EEEEF6", +"} c #EDEDF5", +"| c #ECECF4", +"1 c #EBEBF3", +"2 c #E9EAF1", +"3 c #E4E4EC", +"4 c #E3E3EB", +"5 c #E1E1E9", +"6 c #9A9A9B", +"7 c #FFFFFF", +"8 c #9798A8", +"9 c #9A9AAA", +"0 c #9999A9", +"a c #9697A6", +"b c #9595A5", +"c c #9393A3", +"d c #9192A1", +"e c #8F909F", +"f c #8D8E9D", +"g c #8B8C9B", +"h c #8A8B9A", +"i c #888998", +"j c #868796", +"k c #848594", +"l c #828492", +"m c #818291", +"n c #7F808F", +"o c #7D7F8D", +"p c #7B7D8B", +"q c #797B89", +"r c #777987", +"s c #2D2E34", +"t c #EEEEF0", +"u c #9B9BAB", +"v c #9798A7", +"w c #9596A5", +"x c #9394A3", +"y c #9293A2", +"z c #9091A0", +"A c #8E8F9E", +"B c #8C8D9C", +"C c #898A99", +"D c #878897", +"E c #858695", +"F c #838593", +"G c #818391", +"H c #7F818F", +"I c #7E7F8E", +"J c #7C7D8C", +"K c #7A7C8A", +"L c #787A88", +"M c #3B3C43", +"N c #F1F1F9", +"O c #9D9DAD", +"P c #9A9BAA", +"Q c #888A99", +"R c #868896", +"S c #2E2F35", +"T c #DDDDE3", +"U c #9D9EAD", +"V c #9B9CAB", +"W c #999AA9", +"X c #9495A4", +"Y c #8A8C9A", +"Z c #878997", +"` c #858795", +" . c #808190", +".. c #7E808E", +"+. c #7C7E8C", +"@. c #3D3E45", +"#. c #9898A8", +"$. c #9D9DAA", +"%. c #9E9FAB", +"&. c #9C9DA7", +"*. c #A6A7B0", +"=. c #ABACB4", +"-. c #A2A3AA", +";. c #A4A4A9", +">. c #ABABAD", +",. c #AAAAAA", +"'. c #B8B8B4", +"). c #ACADA7", +"!. c #9D9F94", +"~. c #7D8073", +"{. c #474745", +"]. c #747682", +"^. c #DCDCE3", +"/. c #9698A6", +"(. c #8E8F9D", +"_. c #7D7E8A", +":. c #6F707A", +"<. c #6C6D78", +"[. c #6B6C77", +"}. c #81828F", +"|. c #7D808D", +"1. c #A2A3AB", +"2. c #F2F2F2", +"3. c #F8F8F5", +"4. c #FAFBF6", +"5. c #FFFFFA", +"6. c #FEFEF3", +"7. c #E9EADD", +"8. c #D2D3C6", +"9. c #BABAAD", +"0. c #A1A293", +"a. c #888780", +"b. c #6F7072", +"c. c #5E615C", +"d. c #989986", +"e. c #242516", +"f. c #56575C", +"g. c #767886", +"h. c #2C2D33", +"i. c #DBDBE2", +"j. c #9394A2", +"k. c #9597A6", +"l. c #6E6F75", +"m. c #242426", +"n. c #0E0E0F", +"o. c #060607", +"p. c #060606", +"q. c #070707", +"r. c #111113", +"s. c #4F5057", +"t. c #828392", +"u. c #A8A9B0", +"v. c #C2C2BE", +"w. c #574B77", +"x. c #42385D", +"y. c #241B41", +"z. c #08003A", +"A. c #070039", +"B. c #070034", +"C. c #02002E", +"D. c #000027", +"E. c #000023", +"F. c #00001E", +"G. c #090A25", +"H. c #BAB9AD", +"I. c #2E2E1E", +"J. c #747684", +"K. c #2B2C32", +"L. c #DADBE1", +"M. c #9696A6", +"N. c #9192A2", +"O. c #525258", +"P. c #010102", +"Q. c #212123", +"R. c #737581", +"S. c #717380", +"T. c #6F717E", +"U. c #767887", +"V. c #757785", +"W. c #3A3B42", +"X. c #AAABB2", +"Y. c #A1A09D", +"Z. c #060048", +"`. c #14014E", +" + c #312755", +".+ c #1D1931", +"++ c #1D192E", +"@+ c #191821", +"#+ c #282639", +"$+ c #2A2746", +"%+ c #171636", +"&+ c #010222", +"*+ c #0C0E27", +"=+ c #BBBBAE", +"-+ c #353525", +";+ c #585A5D", +">+ c #727482", +",+ c #DADAE1", +"'+ c #49494E", +")+ c #202021", +"!+ c #B3B3B3", +"~+ c #A8A8A8", +"{+ c #919191", +"]+ c #050507", +"^+ c #787A89", +"/+ c #737583", +"(+ c #393A41", +"_+ c #8F90A0", +":+ c #A8A8AE", +"<+ c #A3A29F", +"[+ c #0D004D", +"}+ c #3C305E", +"|+ c #0F0E0F", +"1+ c #121212", +"2+ c #A9A9A9", +"3+ c #7E7E80", +"4+ c #191927", +"5+ c #060727", +"6+ c #BCBCAE", +"7+ c #3F3F2E", +"8+ c #414239", +"9+ c #747685", +"0+ c #717381", +"a+ c #292B30", +"b+ c #D9D9E0", +"c+ c #747581", +"d+ c #2B2B2B", +"e+ c #FEFEFE", +"f+ c #FDFDFD", +"g+ c #818183", +"h+ c #767987", +"i+ c #383940", +"j+ c #8D8E9E", +"k+ c #A1A29C", +"l+ c #160057", +"m+ c #1E1A2A", +"n+ c #121112", +"o+ c #D2D2D2", +"p+ c #F5F5F5", +"q+ c #3F3F4A", +"r+ c #070727", +"s+ c #BEBFB1", +"t+ c #4D4E3B", +"u+ c #404033", +"v+ c #6F7180", +"w+ c #6E717E", +"x+ c #292A30", +"y+ c #D8D9DF", +"z+ c #9899A9", +"A+ c #19191C", +"B+ c #D7D7D8", +"C+ c #0C0C0C", +"D+ c #6F727F", +"E+ c #37383F", +"F+ c #8B8C9C", +"G+ c #A7A7AD", +"H+ c #A09F9B", +"I+ c #1C065C", +"J+ c #0B0814", +"K+ c #161616", +"L+ c #373737", +"M+ c #4E4D4E", +"N+ c #D9D9D9", +"O+ c #FBFBFB", +"P+ c #6F6F79", +"Q+ c #0C0E28", +"R+ c #C3C4B7", +"S+ c #5F614C", +"T+ c #4D4F3F", +"U+ c #6C6F7C", +"V+ c #6D6F7D", +"W+ c #28292F", +"X+ c #D7D8DE", +"Y+ c #82838F", +"Z+ c #FAFAFA", +"`+ c #292827", +" @ c #737683", +".@ c #6D707D", +"+@ c #36373E", +"@@ c #8E8E9E", +"#@ c #A4A5AB", +"$@ c #A0A09B", +"%@ c #1B055B", +"&@ c #0F0C18", +"*@ c #656565", +"=@ c #FCFCFC", +"-@ c #61616A", +";@ c #080929", +">@ c #0D0F28", +",@ c #CACBBD", +"'@ c #6B7158", +")@ c #5A594B", +"!@ c #6A6C7B", +"~@ c #6A6D7A", +"{@ c #27282E", +"]@ c #D7D7DD", +"^@ c #55555F", +"/@ c #2A2A2A", +"(@ c #6A6A69", +"_@ c #6B6E7B", +":@ c #35363D", +"<@ c #878998", +"[@ c #A3A4AA", +"}@ c #140055", +"|@ c #302B41", +"1@ c #090909", +"2@ c #696969", +"3@ c #F6F6F6", +"4@ c #1D1D26", +"5@ c #0C0D2C", +"6@ c #0D0F29", +"7@ c #CFD0C3", +"8@ c #797B63", +"9@ c #5E6152", +"0@ c #676A79", +"a@ c #696C79", +"b@ c #26272D", +"c@ c #D6D6DD", +"d@ c #55565E", +"e@ c #464647", +"f@ c #575757", +"g@ c #565656", +"h@ c #555555", +"i@ c #787878", +"j@ c #686867", +"k@ c #6D707E", +"l@ c #6A6C7A", +"m@ c #34353C", +"n@ c #A2A3A8", +"o@ c #A09F9A", +"p@ c #19035A", +"q@ c #110D1A", +"r@ c #CECECD", +"s@ c #C5C5C5", +"t@ c #252526", +"u@ c #0F0F15", +"v@ c #0E0F2D", +"w@ c #D5D5CA", +"x@ c #808369", +"y@ c #606253", +"z@ c #666877", +"A@ c #676A77", +"B@ c #25272D", +"C@ c #D5D6DC", +"D@ c #53535C", +"E@ c #B9B9B9", +"F@ c #F9F9F9", +"G@ c #6B6E7C", +"H@ c #686A78", +"I@ c #33353B", +"J@ c #838694", +"K@ c #A1A2A7", +"L@ c #A5A3A0", +"M@ c #200C5A", +"N@ c #2C2641", +"O@ c #2D2838", +"P@ c #43414F", +"Q@ c #757380", +"R@ c #666470", +"S@ c #312F3B", +"T@ c #26252F", +"U@ c #242432", +"V@ c #0E0E2B", +"W@ c #14162D", +"X@ c #DDDED2", +"Y@ c #7F836A", +"Z@ c #67685D", +"`@ c #646775", +" # c #656875", +".# c #25262C", +"+# c #D4D5DB", +"@# c #888A98", +"## c #7D7D8A", +"$# c #BBBBBB", +"%# c #30302F", +"&# c #666976", +"*# c #32343A", +"=# c #9C9DA2", +"-# c #E9E9E4", +";# c #CBC8D0", +"># c #CFCCD3", +",# c #CDCBD1", +"'# c #C8C7CC", +")# c #C3C2C6", +"!# c #C1C0C3", +"~# c #C2C1C3", +"{# c #C0C0C1", +"]# c #BBBBBC", +"^# c #B5B6B5", +"/# c #B5B6B2", +"(# c #CFCEC3", +"_# c #7B8067", +":# c #6F7171", +"<# c #636673", +"[# c #24252B", +"}# c #D3D4DA", +"|# c #8C8E9D", +"1# c #18181B", +"2# c #D6D6D6", +"3# c #0C0C0B", +"4# c #696C7A", +"5# c #646774", +"6# c #313339", +"7# c #818491", +"8# c #808291", +"9# c #8E8F97", +"0# c #D1D1CF", +"a# c #D1D1CE", +"b# c #DBDCD5", +"c# c #E1E1DA", +"d# c #E7E7E0", +"e# c #EBECE5", +"f# c #EDEDE8", +"g# c #ECEBE5", +"h# c #E8E8E2", +"i# c #E4E4DC", +"j# c #DFDED6", +"k# c #C3C3B5", +"l# c #6D6F58", +"m# c #656868", +"n# c #636674", +"o# c #616471", +"p# c #23252A", +"q# c #D2D3DA", +"r# c #848694", +"s# c #838594", +"t# c #686B78", +"u# c #626572", +"v# c #313239", +"w# c #80818F", +"x# c #7C7E8D", +"y# c #767883", +"z# c #8D8D89", +"A# c #8C8E86", +"B# c #909088", +"C# c #88897C", +"D# c #828173", +"E# c #7E7E71", +"F# c #7E7F72", +"G# c #6D6E62", +"H# c #4E4E3E", +"I# c #696B5C", +"J# c #6E716B", +"K# c #5D5F66", +"L# c #5F626F", +"M# c #606370", +"N# c #222429", +"O# c #D1D2D9", +"P# c #848695", +"Q# c #6B6C78", +"R# c #45454D", +"S# c #151518", +"T# c #434344", +"U# c #545454", +"V# c #454545", +"W# c #D3D3D3", +"X# c #969696", +"Y# c #656876", +"Z# c #606470", +"`# c #2F3137", +" $ c #808290", +".$ c #6E707E", +"+$ c #828389", +"@$ c #7E7E75", +"#$ c #6E6E5B", +"$$ c #565747", +"%$ c #2E2F20", +"&$ c #1B1B0F", +"*$ c #2F2F21", +"=$ c #5F5F4C", +"-$ c #4F5054", +";$ c #57585E", +">$ c #606371", +",$ c #5F636F", +"'$ c #5E616E", +")$ c #222328", +"!$ c #D1D1D8", +"~$ c #4E4F57", +"{$ c #0A0A0A", +"]$ c #C0C0C0", +"^$ c #707072", +"/$ c #040404", +"($ c #5E626E", +"_$ c #2F3037", +":$ c #7F808E", +"<$ c #9A9B9E", +"[$ c #D7D8D6", +"}$ c #D5D5D3", +"|$ c #D7D8D5", +"1$ c #D6D6D1", +"2$ c #B2B2AA", +"3$ c #88887F", +"4$ c #67675E", +"5$ c #3C3C32", +"6$ c #454739", +"7$ c #6F706A", +"8$ c #616470", +"9$ c #5D616D", +"0$ c #5C5F6C", +"a$ c #212227", +"b$ c #D0D1D7", +"c$ c #838493", +"d$ c #4C4D55", +"e$ c #4C4C4C", +"f$ c #DBDBDB", +"g$ c #E4E4E4", +"h$ c #ACACAC", +"i$ c #282828", +"j$ c #616572", +"k$ c #5D606D", +"l$ c #2D2F35", +"m$ c #E2E2EA", +"n$ c #757684", +"o$ c #6C6E7C", +"p$ c #676977", +"q$ c #646672", +"r$ c #636672", +"s$ c #636571", +"t$ c #61636F", +"u$ c #5E606C", +"v$ c #5A5D6A", +"w$ c #202127", +"x$ c #CFD0D6", +"y$ c #6B6D79", +"z$ c #4F5059", +"A$ c #4E4F58", +"B$ c #4C4E57", +"C$ c #464851", +"D$ c #40414B", +"E$ c #5A5C64", +"F$ c #6B6D76", +"G$ c #6A6C74", +"H$ c #4B4C55", +"I$ c #3B3D46", +"J$ c #40424A", +"K$ c #42444C", +"L$ c #40424B", +"M$ c #3F414A", +"N$ c #3C3E46", +"O$ c #5B5E6B", +"P$ c #2D2E35", +"Q$ c #707280", +"R$ c #696B79", +"S$ c #595C69", +"T$ c #1F2126", +"U$ c #CECFD5", +"V$ c #727582", +"W$ c #5A5E6A", +"X$ c #2C2E34", +"Y$ c #7A7C8B", +"Z$ c #7D7F8E", +"`$ c #7B7D8C", +" % c #797B8A", +".% c #777A88", +"+% c #757886", +"@% c #707381", +"#% c #6C6F7D", +"$% c #6A6D7B", +"%% c #5F6370", +"&% c #595D6A", +"*% c #202126", +"=% c #D0D1D8", +"-% c #787B89", +";% c #767986", +">% c #727583", +",% c #6F717F", +"'% c #6B6D7B", +")% c #676A78", +"!% c #5C5F6D", +"~% c #2C2E35", +"{% c #989898", +"]% c #19191D", +"^% c #191A1E", +"/% c #18191D", +"(% c #17181C", +"_% c #16171B", +":% c #15161A", +"<% c #141519", +"[% c #131418", +"}% c #131417", +"|% c #121317", +"1% c #121316", +"2% c #111216", +"3% c #111215", +"4% c #101115", +"5% c #101114", +"6% c #0F1014", +"7% c #050607", +"8% c #131317", +"9% c #121216", +"0% c #101014", +"a% c #0F0F13", +"b% c #0E0F13", +"c% c #0E0E12", +"d% c #0F1013", +"e% c #0C0D10", +"f% c #0B0D10", +"g% c #0B0C0F", +"h% c #0A0C0F", +"i% c #0A0B0E", +"j% c #090A0E", +"k% c #5D627C", +"l% c #E7E8EB", +"m% c #FBFBFF", +"n% c #F8F8FF", +"o% c #F7F7FF", +"p% c #F6F6FF", +"q% c #F5F6FE", +"r% c #F4F5FD", +"s% c #F3F3FB", +"t% c #F2F2FA", +"u% c #F1F2F9", +"v% c #EFF0F7", +"w% c #CACAD0", +"x% c #EAEBF3", +"y% c #E9EAF2", +"z% c #E8E9F1", +"A% c #E7E8F0", +"B% c #737477", +"C% c #E6E7ED", +"D% c #747480", +"E% c #62626C", +"F% c #878898", +"G% c #858793", +"H% c #595A65", +"I% c #666875", +"J% c #444550", +"K% c #43454F", +"L% c #545560", +"M% c #E6E6ED", +"N% c #9192A0", +"O% c #2E2E33", +"P% c #676772", +"Q% c #8D8E9A", +"R% c #2A2B2D", +"S% c #3C3D43", +"T% c #E5E5ED", +"U% c #9899A8", +"V% c #828390", +"W% c #0D0D0D", +"X% c #9A9BAC", +"Y% c #898B99", +"Z% c #7F8190", +"`% c #8A8B97", +" & c #545561", +".& c #2A2A31", +"+& c #27272A", +"@& c #3B3C42", +"#& c #E4E5ED", +"$& c #9495A3", +"%& c #858593", +"&& c #7F818D", +"*& c #4C4E59", +"=& c #5D5F69", +"-& c #E3E5ED", +";& c #82818F", +">& c #7B7781", +",& c #747278", +"'& c #85848C", +")& c #3E3F49", +"!& c #E3E4ED", +"~& c #8B899B", +"{& c #8F8A9B", +"]& c #888393", +"^& c #807A87", +"/& c #7F7985", +"(& c #7F7B85", +"_& c #9A919A", +":& c #727179", +"<& c #52545F", +"[& c #E2E3ED", +"}& c #7D7F8B", +"|& c #908DA3", +"1& c #8A8494", +"2& c #A8A5B7", +"3& c #B3ADBA", +"4& c #7F7B80", +"5& c #575A62", +"6& c #5D5E66", +"7& c #726E79", +"8& c #686870", +"9& c #7A7C89", +"0& c #1F2025", +"a& c #E1E3EC", +"b& c #828592", +"c& c #878796", +"d& c #9B91A6", +"e& c #827985", +"f& c #797381", +"g& c #4F4E54", +"h& c #46484D", +"i& c #8D858D", +"j& c #6B676E", +"k& c #60616A", +"l& c #72717B", +"m& c #696B77", +"n& c #6E717F", +"o& c #3D3E44", +"p& c #E0E1EB", +"q& c #7B7E8B", +"r& c #A29CAF", +"s& c #918895", +"t& c #87808D", +"u& c #5D5A64", +"v& c #3D3E43", +"w& c #48494F", +"x& c #5C5E66", +"y& c #706E78", +"z& c #67656C", +"A& c #62626B", +"B& c #E0E1EA", +"C& c #858694", +"D& c #ADA4B4", +"E& c #7B757B", +"F& c #898390", +"G& c #494A50", +"H& c #3E3E43", +"I& c #52535A", +"J& c #6A6B75", +"K& c #70727E", +"L& c #7B7883", +"M& c #666771", +"N& c #71717E", +"O& c #55565D", +"P& c #61646E", +"Q& c #E0E0EA", +"R& c #80828F", +"S& c #9D9BAA", +"T& c #9B929D", +"U& c #908892", +"V& c #737079", +"W& c #3E4045", +"X& c #46464C", +"Y& c #5D5E67", +"Z& c #6F707C", +"`& c #6E717D", +" * c #7E7C8D", +".* c #777481", +"+* c #777584", +"@* c #4E4F55", +"#* c #626570", +"$* c #DFDFE9", +"%* c #848593", +"&* c #A9A3AF", +"** c #8C848C", +"=* c #9A949F", +"-* c #505057", +";* c #404045", +">* c #505158", +",* c #686974", +"'* c #727481", +")* c #737682", +"!* c #988FA4", +"~* c #7A7484", +"{* c #6B6873", +"]* c #44454B", +"^* c #45474C", +"/* c #585A62", +"(* c #666975", +"_* c #D4D5DE", +":* c #8B8D9B", +"<* c #8F8F9C", +"[* c #A69EA6", +"}* c #9C949C", +"|* c #827F88", +"1* c #424449", +"2* c #6E707C", +"3* c #817F8D", +"4* c #958D9E", +"5* c #7E7787", +"6* c #615F69", +"7* c #3E3F45", +"8* c #44464C", +"9* c #595A63", +"0* c #666977", +"a* c #C2C3CA", +"b* c #4F505D", +"c* c #8B8E9D", +"d* c #B3A8B0", +"e* c #99929A", +"f* c #606068", +"g* c #414248", +"h* c #4D4F55", +"i* c #656670", +"j* c #727581", +"k* c #767885", +"l* c #98919E", +"m* c #948C9A", +"n* c #73707B", +"o* c #3F4146", +"p* c #5F616B", +"q* c #666874", +"r* c #DEDFE7", +"s* c #81828D", +"t* c #535561", +"u* c #89838F", +"v* c #7E7377", +"w* c #484A51", +"x* c #6D6E7A", +"y* c #787883", +"z* c #A9A0AD", +"A* c #918B97", +"B* c #5B5C63", +"C* c #414147", +"D* c #45464D", +"E* c #DBDDE6", +"F* c #73747F", +"G* c #535661", +"H* c #978A95", +"I* c #6D686C", +"J* c #63646E", +"K* c #767682", +"L* c #958F9A", +"M* c #AAA3AE", +"N* c #736F79", +"O* c #4C4D54", +"P* c #404147", +"Q* c #60626C", +"R* c #676A76", +"S* c #DBDCE6", +"T* c #7B7C87", +"U* c #978C92", +"V* c #7A757B", +"W* c #BAB3BF", +"X* c #928D97", +"Y* c #5A5A62", +"Z* c #43454A", +"`* c #45474D", +" = c #595B63", +".= c #656873", +"+= c #DADCE5", +"@= c #7D7E8C", +"#= c #383943", +"$= c #777988", +"%= c #51505A", +"&= c #B2A5AB", +"*= c #7A7982", +"== c #4D4E53", +"-= c #323438", +";= c #5C5E68", +">= c #565862", +",= c #454751", +"'= c #2E3036", +")= c #DADBE4", +"!= c #23242A", +"~= c #44444D", +"{= c #606169", +"]= c #2A2B2F", +"^= c #17171B", +"/= c #323339", +"(= c #50535D", +"_= c #24262A", +":= c #0C0D0E", +"<= c #50535E", +"[= c #2A2C32", +"}= c #474953", +"|= c #121315", +"1= c #DADAE3", +"2= c #797B88", +"3= c #1A1B1F", +"4= c #797A85", +"5= c #393A46", +"6= c #53555F", +"7= c #1F2024", +"8= c #121214", +"9= c #51535E", +"0= c #33343B", +"a= c #121215", +"b= c #4D505A", +"c= c #34363D", +"d= c #777884", +"e= c #757681", +"f= c #797C89", +"g= c #4C4E5A", +"h= c #5F626E", +"i= c #5A5D68", +"j= c #5E616D", +"k= c #4E515A", +"l= c #626573", +"m= c #595C68", +"n= c #555864", +"o= c #555863", +"p= c #43454E", +"q= c #515460", +"r= c #0D0E10", +"s= c #939395", +"t= c #1A1A1E", +"u= c #19191E", +"v= c #18181C", +"w= c #0E0E11", +"x= c #0F0F12", +"y= c #141518", +"z= c #121417", +"A= c #111316", +"B= c #0D0E11", +" ", +" . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / / ( _ : @ < $ % [ } | 1 ; 2 , ' ) ! ~ 3 4 ] 5 / 6 7 ", +" : 8 9 0 a b c d e f g h i j k l m n o p q r s t u u 0 v w x y z A B h C D E F G H I J K L M 7 ", +" N 9 O P 0 a w x d z A B h Q R E l G H o p K S T U O V W v a X y d A f Y C Z ` F l ...+.K @.7 ", +" < #.P #.x $.%.&.*.=.-.;.>.,.'.).!.~.{.].K L s ^.u V W /.w x x (._.:.<.[.[.}.R G H |.p K q M 7 ", +" # a 0 w 1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.K g.h.i.W W v w j.k.l.m.n.o.p.p.q.r.s.t.o p q q g.M 7 ", +" % X a x u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.f.L J.K.L.v v M.x N.O. P. Q.R.S.T.U.V.W.7 ", +" [ y w d X.Y.Z.`. +.+++@+#+$+%+&+*+=+-+;+g.>+K.,+w a x z '+ )+!+~+{+]+q.^+/+(+7 ", +" * d x _+:+<+[+}+|+ 1+2+3+4+5+*+6+7+8+9+0+a+b+X X x c+ d+7 e+f+g+ h+0+i+7 ", +" | A d j+:+k+l+m+ n+o+p+q+r+*+s+t+u+v+w+x+y+y y z+A+ d+7 e+f+B+C+V.D+E+7 ", +" 1 f e F+G+H+I+J+ K+L+M+N+O+P+5+Q+R+S+T+U+V+W+X+z N.Y+ d+7 e+e+Z+`+ @.@+@7 ", +" ; g @@h #@$@%@&@ *@O+7 =@O+-@;@>@,@'@)@!@~@{@]@A y ^@ /@7 e+e+7 (@D+_@:@7 ", +" > C B <@[@$@}@|@1@2@3@Z+7 o+4@5@6@7@8@9@0@a@b@c@B z d@ e@f@g@g@h@i@7 e+e+7 j@k@l@m@7 ", +" , Z h j n@o@p@q@L+r@f+e+s@t@u@v@6@w@x@y@z@A@B@C@g A D@ E@e+F@F@F@O+e+e+e+7 (@G@H@I@7 ", +" ' ` i J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@ #.#+#@#h ## $#7 e+e+e+e+e+e+e+7 %#G@&#*#7 ", +" ) k R t.=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#:#`@<#[#}#D R |#1# $#7 e+e+e+e+e+e+f+2#3#4#5#6#7 ", +" ! 7#E 8#9#0#a#b#c#d#e#f#f#g#h#i#j#k#l#m#n#o#p#q#r#` s#[. $#7 e+e+e+e+f+e+f+g+ t#u#v#7 ", +" ~ .l w#x#U.y#z#A#B#C#D#E#F#G#H#I#J#K#L#o#M#N#O#F P#Q#R#S#T#U#V#W#7 e+e+e+e+e+7 X# Y#Z#`#7 ", +" { ..m $+.K L .$+$@$#$$$%$&$*$=$-$;$o#>$,$'$)$!$G E ~$ {$]$7 f+e+e+e+f+7 7 ^$/$ 5#($_$7 ", +" ] +...:$K L 9+<$[$}$|$1$2$3$4$5$6$7$8$L#9$0$a$b$H c$d$ e$]$f$g$g$2#h$i$ j$k$l$7 ", +" m$K o K L g.n$0+o$p$5#q$r$s$t$u$o#>$($k$0$v$w$x$o H y$z$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$'$O$P$7 ", +" / q p q r V.J.>+Q$w+V+~@R$&# #<#o#M#'$0$v$S$T$U$p +.K L g.V.V$0+w+.@_@a@A@#u#o#($k$W$S$X$7 ", +" { Y$Z$`$ %.%+%J.V$@%w+#%$%a@A@ #<#o#%%9$0$&%*%=%....+.K -%;%V.>%0+,%.@'%a@)%Y#5#j$M#'$!%W$~%7 ", +" {%]%^%]%/%(%(%_%_%:%:%<%<%[%}%|%1%2%3%4%5%6%7%{+[%[%8%|%9%2%3%4%0%6%a%b%c%d%6%e%e%f%g%h%i%j%7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%l%m%n%o%p%q%r%s%t%u%# v%[ $ ]@w%x%y%> z%A%) B%7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%C%u u 0 w D%E%w z A B h C R F%G%H%F I%J%K%L%M 7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%M%U O V N%O%P%v y d A f Y C Z ` Q%J%k W+ R%S%7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%T%u V U%w V%W%X%e f B Y%i R r#l Z%`% &`$.&+&@&7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%#&W W a $&%&:$d f B Y%i R r#l m n Z$&&*&p =&W.7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%-&v v w x d e f B Y%i R r#l s#%&;&>&,&'&)&L W.7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%!&w a x d e f B Y%i R E G ~&{&]&^&/&(&_&:&<&i+7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%[&X X d e f B Y%i R E }&|&1&2&3&4&5&6&7&8&9&0&7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%a&y y e f B Y%i R b&c&d&e&f&g&h&i&j&k&l&m&n&o&7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%p&z z f B Y%i R q&r&s&t&u&v&w&x&y&z&A&P%I%w++@7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%B&A A B Y%i ` C&D&E&F&G&H&I&J&K&L&M&N&O&P&#%:@7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%Q&B f Y%i R&S&T&U&V&W&X&Y&Z&`& *.*+*@*s.#*~@m@7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%$*g Y i %*&***=*-*;*>*,*'*)*!*~*{*]*^*/*(*H@I@7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%_*:*i <*[*}*|*1*]*E$2*>+3*4*5*6*7*8*9*q$0*&#*#7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%a*b*c*d*e*f*g*h*i*j*k*l*m*n*G&o*s.p*q*&# #5#6#7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%r*s*t*u*v*w*O&x*k*y*z*A*B*C*D*9*q$t#&# #<#u#v#7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%E*s#F*G*H*I*J*K*L*M*N*O*P*~$Q*R*H@p$ #<#o#o#`#7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%S* $J T*)&U*V*W*X*Y*Z*`* =.=t#t#&##o#M#($_$7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%+=@=#=$=y#%=&=*===-=D*;=>=_@$%A@4#,=*&o#,$'$'=7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%)=K i%!=`$<.~={=s.r.]=E+^=B$/=(=_=:=I@<=[=}=|=7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%1=2=c% 3=9+4=5=g.6=7=8=9=I@K.'=N$0=a=b=c=a$/$7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%E*Z$d=y#e=f=h+Z&g=J.h=i=w+j=k=l=m=n=o=o=p=q=r=7 ", +" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%s=t=3=^%u=/%v=v=w=x=_%:%<%<%y=[%z=|%A=2%3%4%B=7 ", +" 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 "}; From 525ab89d01f78685d4ee26923542677d044ac08c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:35 +0200 Subject: [PATCH 09/20] Increase MAX_WINDOWLIST_WIDTH from 160 to 400 (in pixels) --- src/wconfig.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wconfig.h.in b/src/wconfig.h.in index 58b00444..2e3c8da0 100644 --- a/src/wconfig.h.in +++ b/src/wconfig.h.in @@ -315,7 +315,7 @@ #define MAX_WORKSPACENAME_WIDTH 64 /* max width of window title in window list */ -#define MAX_WINDOWLIST_WIDTH 160 +#define MAX_WINDOWLIST_WIDTH 400 #ifndef HAVE_INOTIFY /* Check defaults database for changes every this many milliseconds */ From f93f847b3369857dcbfc8dc662009a338f2c2a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:36 +0200 Subject: [PATCH 10/20] Bring back some "About" information when double-clicking the dock When dock is double-clicked and no application is defined to be launched, show the information panel (instead of doing nothing). --- src/dock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dock.c b/src/dock.c index 9c2f35e8..476f59e1 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3242,6 +3242,8 @@ static void iconDblClick(WObjDescriptor *desc, XEvent *event) } else if (btn->command) { if (!btn->launching && (!btn->running || (event->xbutton.state & ControlMask))) launchDockedApplication(btn, False); + } else if (btn->xindex == 0 && btn->yindex == 0 && btn->dock->type == WM_DOCK) { + wShowInfoPanel(dock->screen_ptr); } } } From 8b6ff01d39a0c5ad5ca381a131983e5e838936c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:37 +0200 Subject: [PATCH 11/20] Move code that removes icons from a dock to new removeIcons function Code taken from removeIconsCallback. --- src/dock.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/dock.c b/src/dock.c index 476f59e1..41c9efbe 100644 --- a/src/dock.c +++ b/src/dock.c @@ -446,14 +446,35 @@ static void omnipresentCallback(WMenu *menu, WMenuEntry *entry) } } +static void removeIcons(WMArray *icons, WDock *dock) +{ + WAppIcon *aicon; + int keepit; + WMArrayIterator it; + + WM_ITERATE_ARRAY(icons, aicon, it) { + keepit = aicon->running && wApplicationOf(aicon->main_window); + wDockDetach(dock, aicon); + if (keepit) { + /* XXX: can: aicon->icon == NULL ? */ + PlaceIcon(dock->screen_ptr, &aicon->x_pos, &aicon->y_pos, + wGetHeadForWindow(aicon->icon->owner)); + XMoveWindow(dpy, aicon->icon->core->window, aicon->x_pos, aicon->y_pos); + if (!dock->mapped || dock->collapsed) + XMapWindow(dpy, aicon->icon->core->window); + } + } + WMFreeArray(icons); + + if (wPreferences.auto_arrange_icons) + wArrangeIcons(dock->screen_ptr, True); +} + static void removeIconsCallback(WMenu *menu, WMenuEntry *entry) { WAppIcon *clickedIcon = (WAppIcon *) entry->clientdata; WDock *dock; - WAppIcon *aicon; WMArray *selectedIcons; - int keepit; - WMArrayIterator it; assert(clickedIcon != NULL); @@ -476,22 +497,7 @@ static void removeIconsCallback(WMenu *menu, WMenuEntry *entry) WMAddToArray(selectedIcons, clickedIcon); } - WM_ITERATE_ARRAY(selectedIcons, aicon, it) { - keepit = aicon->running && wApplicationOf(aicon->main_window); - wDockDetach(dock, aicon); - if (keepit) { - /* XXX: can: aicon->icon == NULL ? */ - PlaceIcon(dock->screen_ptr, &aicon->x_pos, &aicon->y_pos, - wGetHeadForWindow(aicon->icon->owner)); - XMoveWindow(dpy, aicon->icon->core->window, aicon->x_pos, aicon->y_pos); - if (!dock->mapped || dock->collapsed) - XMapWindow(dpy, aicon->icon->core->window); - } - } - WMFreeArray(selectedIcons); - - if (wPreferences.auto_arrange_icons) - wArrangeIcons(dock->screen_ptr, True); + removeIcons(selectedIcons, dock); } static void keepIconsCallback(WMenu *menu, WMenuEntry *entry) From 9fae35fbc40a28cda7776a23155627b69e2a3e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:38 +0200 Subject: [PATCH 12/20] Merging appicon.c:appIconMouseDown and dock.c:handleIconMove into appicon.c:wHandleAppIconMove Behaves essentially the same, only a bit more consistently. Known differences: 1. An AppIcon will now always end up undocked if moved while Mod1 is pressed. 2. Moving a docked AppIcon with Mod1 pressed (undocking it) used to auto-expand the clip, as clip expansion happened first, while looking for a snapping position, and the test on Mod1 being pressed happened only later --- src/appicon.c | 352 ++++++++++++++++++++++++++++++++------------------ src/appicon.h | 1 + src/dock.c | 226 +------------------------------- src/dock.h | 2 + 4 files changed, 235 insertions(+), 346 deletions(-) diff --git a/src/appicon.c b/src/appicon.c index e969d39f..bc02216e 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -63,6 +63,7 @@ extern WDDomain *WDWindowAttributes; extern XContext wWinContext; #define MOD_MASK wPreferences.modifier_mask +#define ICON_SIZE wPreferences.icon_size void appIconMouseDown(WObjDescriptor * desc, XEvent * event); static void iconDblClick(WObjDescriptor * desc, XEvent * event); @@ -667,24 +668,8 @@ static void iconDblClick(WObjDescriptor *desc, XEvent *event) void appIconMouseDown(WObjDescriptor * desc, XEvent * event) { WAppIcon *aicon = desc->parent; - WIcon *icon = aicon->icon; - XEvent ev; - int x = aicon->x_pos, y = aicon->y_pos; - int dx = event->xbutton.x, dy = event->xbutton.y; - int grabbed = 0; - int done = 0; - int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ - WScreen *scr = icon->core->screen_ptr; - WWorkspace *workspace = scr->workspaces[scr->current_workspace]; - int shad_x = 0, shad_y = 0, docking = 0, dockable, collapsed = 0; - int ix, iy; - int clickButton = event->xbutton.button; - Pixmap ghost = None; - Window wins[2]; - Bool movingSingle = False; - int oldX = x; - int oldY = y; - Bool hasMoved = False; + WScreen *scr = aicon->icon->core->screen_ptr; + Bool hasMoved; if (aicon->editing || WCHECK_STATE(WSTATE_MODAL)) return; @@ -729,24 +714,92 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) return; } - if (event->xbutton.state & MOD_MASK) - wLowerFrame(icon->core); - else + hasMoved = wHandleAppIconMove(aicon, event); + if (wPreferences.single_click && !hasMoved && aicon->dock != NULL) + { + iconDblClick(desc, event); + } +} + +Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) +{ + WDock *originalDock = aicon->dock; /* can be NULL */ + WDock *lastDock = originalDock; + WDock *allDocks[2]; /* clip and dock (order to be determined at runtime) */ + Bool done = False, dockable, ondock; + Bool grabbed = False; + Bool collapsed = False; /* Stores the collapsed state of lastDock, before the moving appicon entered it */ + int superfluous = wPreferences.superfluous; /* we cache it to avoid problems */ + int omnipresent = aicon->omnipresent; /* this must be cached */ + Bool showed_all_clips = False; + + WIcon *icon = aicon->icon; + WScreen *scr = icon->core->screen_ptr; + int clickButton = event->xbutton.button; + Pixmap ghost = None; + Window wins[2]; /* Managing shadow window */ + XEvent ev; + + int x = aicon->x_pos, y = aicon->y_pos; + int ofs_x = event->xbutton.x, ofs_y = event->xbutton.y; + int shad_x = x, shad_y = y; + int ix = aicon->xindex, iy = aicon->yindex; + int i; + int oldX = x; + int oldY = y; + Bool hasMoved = False; + + if (wPreferences.flags.noupdates && originalDock != NULL) + return False; + + if (!(event->xbutton.state & MOD_MASK)) wRaiseFrame(icon->core); + else { + /* If Mod is pressed for an docked appicon, assume it is to undock it, + * so don't lower it */ + if (originalDock == NULL) + wLowerFrame(icon->core); + } if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None, CurrentTime) != GrabSuccess) - wwarning("pointer grab failed for appicon move"); + GrabModeAsync, None, None, CurrentTime) != GrabSuccess) { + wwarning("Pointer grab failed in wHandleAppIconMove"); + } + + if (originalDock != NULL) { + dockable = True; + ondock = True; + } + else { + ondock = False; + if (wPreferences.flags.nodock && wPreferences.flags.noclip) + dockable = 0; + else + dockable = canBeDocked(icon->owner); + } + + /* We try the various docks in that order: + * - First, the dock the appicon comes from, if any + * - Then, the "dock" (WM_DOCK) + * - Finally, the clip + */ + i = 0; + if (originalDock != NULL) + allDocks[ i++ ] = originalDock; + if (!wPreferences.flags.nodock && scr->dock != originalDock) + allDocks[ i++ ] = scr->dock; + if (!wPreferences.flags.noclip && + originalDock != scr->workspaces[scr->current_workspace]->clip) + allDocks[ i++ ] = scr->workspaces[scr->current_workspace]->clip; + for ( ; i < 2; i++) /* In case the clip, the dock, or both, are disabled */ + allDocks[ i ] = NULL; - if (wPreferences.flags.nodock && wPreferences.flags.noclip) - dockable = 0; - else - dockable = canBeDocked(icon->owner); wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); + XMoveResizeWindow(dpy, scr->dock_shadow, aicon->x_pos, aicon->y_pos, ICON_SIZE, ICON_SIZE); if (superfluous) { if (icon->pixmap != None) ghost = MakeGhostIcon(scr, icon->pixmap); @@ -755,6 +808,8 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); XClearWindow(dpy, scr->dock_shadow); } + if (ondock) + XMapWindow(dpy, scr->dock_shadow); while (!done) { WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask @@ -774,8 +829,8 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) case MotionNotify: hasMoved = True; if (!grabbed) { - if (abs(dx - ev.xmotion.x) >= MOVE_THRESHOLD - || abs(dy - ev.xmotion.y) >= MOVE_THRESHOLD) { + if (abs(ofs_x - ev.xmotion.x) >= MOVE_THRESHOLD + || abs(ofs_y - ev.xmotion.y) >= MOVE_THRESHOLD) { XChangeActivePointerGrab(dpy, ButtonMotionMask | ButtonReleaseMask | ButtonPressMask, wCursor[WCUR_MOVE], CurrentTime); @@ -784,68 +839,87 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) break; } } - x = ev.xmotion.x_root - dx; - y = ev.xmotion.y_root - dy; - if (movingSingle) - XMoveWindow(dpy, icon->core->window, x, y); - else - wAppIconMove(aicon, x, y); - - if (dockable) { - if (scr->dock && wDockSnapIcon(scr->dock, aicon, x, y, &ix, &iy, False)) { - shad_x = scr->dock->x_pos + ix * wPreferences.icon_size; - shad_y = scr->dock->y_pos + iy * wPreferences.icon_size; - - if (scr->last_dock != scr->dock && collapsed) { - scr->last_dock->collapsed = 1; - wDockHideIcons(scr->last_dock); - collapsed = 0; - } - if (!collapsed && (collapsed = scr->dock->collapsed)) { - scr->dock->collapsed = 0; - wDockShowIcons(scr->dock); - } - - if (scr->dock->auto_raise_lower) - wDockRaise(scr->dock); - - scr->last_dock = scr->dock; - - XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); - if (!docking) - XMapWindow(dpy, scr->dock_shadow); - - docking = 1; - } else if (workspace->clip && - wDockSnapIcon(workspace->clip, aicon, x, y, &ix, &iy, False)) { - shad_x = workspace->clip->x_pos + ix * wPreferences.icon_size; - shad_y = workspace->clip->y_pos + iy * wPreferences.icon_size; - - if (scr->last_dock != workspace->clip && collapsed) { - scr->last_dock->collapsed = 1; - wDockHideIcons(scr->last_dock); - collapsed = 0; - } - if (!collapsed && (collapsed = workspace->clip->collapsed)) { - workspace->clip->collapsed = 0; - wDockShowIcons(workspace->clip); - } - - if (workspace->clip->auto_raise_lower) - wDockRaise(workspace->clip); - - scr->last_dock = workspace->clip; - - XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); - if (!docking) - XMapWindow(dpy, scr->dock_shadow); - - docking = 1; - } else if (docking) { - XUnmapWindow(dpy, scr->dock_shadow); - docking = 0; + if (omnipresent && !showed_all_clips) { + int i; + for (i = 0; i < scr->workspace_count; i++) { + if (i == scr->current_workspace) + continue; + wDockShowIcons(scr->workspaces[i]->clip); + /* Note: if dock is collapsed (for instance, because it + auto-collapses), its icons still won't show up */ } + showed_all_clips = True; /* To prevent flickering */ + } + + x = ev.xmotion.x_root - ofs_x; + y = ev.xmotion.y_root - ofs_y; + wAppIconMove(aicon, x, y); + + /* At a high level, this if-block is about setting theNewDock to + * the first dock that could snap the appicon at the current + * position, and the next if-block uses that and other info to + * determine whether to dock/undock. + */ + WDock *theNewDock = NULL; + for (i = 0; dockable && i < 2; i++) { + WDock *theDock = allDocks[i]; + if (theDock == NULL) + break; + if (wDockSnapIcon(theDock, aicon, x, y, &ix, &iy, (theDock == originalDock))) { + theNewDock = theDock; + break; + } + } + if (originalDock != NULL && theNewDock == NULL && + (aicon->launching || aicon->lock || aicon->running)) { + /* In those cases, stay in lastDock if no dock really wants us */ + theNewDock = lastDock; + } + if (theNewDock != NULL && !aicon->launching && !aicon->lock && ev.xmotion.state & MOD_MASK) + /* Mod is pressed: do not dock */ + theNewDock = NULL; + if (lastDock != NULL && lastDock != theNewDock) { + /* Leave lastDock in the state we found it */ + if (collapsed) { + lastDock->collapsed = 1; + wDockHideIcons(lastDock); + collapsed = False; + } + if (lastDock->auto_raise_lower) { + wDockLower(lastDock); + } + } + if (theNewDock != NULL) { + if (lastDock != theNewDock) { + collapsed = theNewDock->collapsed; + if (collapsed) { + theNewDock->collapsed = 0; + wDockShowIcons(theNewDock); + } + if (theNewDock->auto_raise_lower) { + wDockRaise(theNewDock); + /* And raise the moving tile above it */ + wRaiseFrame(aicon->icon->core); + } + lastDock = theNewDock; + } + + shad_x = lastDock->x_pos + ix*wPreferences.icon_size; + shad_y = lastDock->y_pos + iy*wPreferences.icon_size; + + XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); + + if (!ondock) { + XMapWindow(dpy, scr->dock_shadow); + } + ondock = 1; + } else { + lastDock = theNewDock; // i.e., NULL + if (ondock) { + XUnmapWindow(dpy, scr->dock_shadow); + } + ondock = 0; } break; @@ -857,41 +931,63 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) break; XUngrabPointer(dpy, CurrentTime); - if (docking) { - Bool docked; - - /* icon is trying to be docked */ + Bool docked = False; + if (ondock) { SlideWindow(icon->core->window, x, y, shad_x, shad_y); XUnmapWindow(dpy, scr->dock_shadow); - docked = wDockAttachIcon(scr->last_dock, aicon, ix, iy, False); - if (scr->last_dock->auto_collapse) + if (originalDock == NULL) { // docking an undocked appicon + docked = wDockAttachIcon(lastDock, aicon, ix, iy, False); + if (!docked) { + /* AppIcon got rejected (happens only when we can't get the + command for that appicon, and the user cancels the + wInputDialog asking for one). Make the rejection obvious by + sliding the icon to its old position */ + SlideWindow(icon->core->window, x, y, oldX, oldY); + } + } + else { // moving a docked appicon to a dock + if (originalDock == lastDock) { + docked = True; + wDockReattachIcon(originalDock, aicon, ix, iy); + } + else { + docked = wDockMoveIconBetweenDocks(originalDock, lastDock, aicon, ix, iy); + if (!docked) { + /* Possible scenario: user moved an auto-attracted appicon + from the clip to the dock, and cancelled the wInputDialog + asking for a command */ + SlideWindow(icon->core->window, x, y, oldX, oldY); + wDockReattachIcon(originalDock, aicon, aicon->xindex, aicon->yindex); + } + } + } + // No matter what happened above, check to lower lastDock + if (lastDock->auto_raise_lower) + wDockLower(lastDock); + /* If docked (or tried to dock) to a auto_collapsing dock, unset + * collapsed, so that wHandleAppIconMove doesn't collapse it + * right away (the timer will take care of it) */ + if (lastDock->auto_collapse) collapsed = 0; - - if (workspace->clip && - workspace->clip != scr->last_dock && workspace->clip->auto_raise_lower) - wDockLower(workspace->clip); - - if (!docked) { - /* If icon could not be docked, slide it back to the old - * position */ - SlideWindow(icon->core->window, x, y, oldX, oldY); + } + else { + if (originalDock != NULL) { /* Detaching a docked appicon */ + if (superfluous) { + if (!aicon->running && !wPreferences.no_animations) { + /* We need to deselect it, even if is deselected in + * wDockDetach(), because else DoKaboom() will fail. + */ + if (aicon->icon->selected) + wIconSelect(aicon->icon); + DoKaboom(scr, aicon->icon->core->window, x, y); + } + } + wDockDetach(originalDock, aicon); } - } else { - if (movingSingle) { - /* move back to its place */ - SlideWindow(icon->core->window, x, y, oldX, oldY); - wAppIconMove(aicon, oldX, oldY); - } else { - XMoveWindow(dpy, icon->core->window, x, y); - aicon->x_pos = x; - aicon->y_pos = y; - } - if (workspace->clip && workspace->clip->auto_raise_lower) - wDockLower(workspace->clip); } if (collapsed) { - scr->last_dock->collapsed = 1; - wDockHideIcons(scr->last_dock); + lastDock->collapsed = 1; + wDockHideIcons(lastDock); collapsed = 0; } if (superfluous) { @@ -899,17 +995,21 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) XFreePixmap(dpy, ghost); XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel); } - - if (wPreferences.auto_arrange_icons) + if (showed_all_clips) { + int i; + for (i = 0; i < scr->workspace_count; i++) { + if (i == scr->current_workspace) + continue; + wDockHideIcons(scr->workspaces[i]->clip); + } + } + if (wPreferences.auto_arrange_icons && !(originalDock != NULL && docked)) + /* Need to rearrange unless moving from dock to dock */ wArrangeIcons(scr, True); - - if (wPreferences.single_click && !hasMoved) - iconDblClick(desc, event); - - done = 1; - break; + return hasMoved; } } + return False; /* Never reached */ } /* This function save the application icon and store the path in the Dictionary */ diff --git a/src/appicon.h b/src/appicon.h index d63d9a7f..f5aa0d58 100644 --- a/src/appicon.h +++ b/src/appicon.h @@ -71,6 +71,7 @@ typedef struct WAppIcon { WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance, char *wm_class, int tile); +Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event); void wAppIconDestroy(WAppIcon *aicon); void wAppIconPaint(WAppIcon *aicon); diff --git a/src/dock.c b/src/dock.c index 41c9efbe..e2352fd4 100644 --- a/src/dock.c +++ b/src/dock.c @@ -105,8 +105,6 @@ static void clipLeave(WDock *dock); static void handleClipChangeWorkspace(WScreen *scr, XEvent *event); -static Bool moveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y); - static void clipEnterNotify(WObjDescriptor *desc, XEvent *event); static void clipLeaveNotify(WObjDescriptor *desc, XEvent *event); static void clipAutoCollapse(void *cdata); @@ -115,7 +113,6 @@ static void launchDockedApplication(WAppIcon *btn, Bool withSelection); static void clipAutoLower(void *cdata); static void clipAutoRaise(void *cdata); -static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y); static WAppIcon *mainIconCreate(WScreen *scr, int type); static int onScreen(WScreen *scr, int x, int y); @@ -781,13 +778,13 @@ static void switchWSCommand(WMenu *menu, WMenuEntry *entry) WM_ITERATE_ARRAY(selectedIcons, btn, iter) { if (wDockFindFreeSlot(dest, &x, &y)) { - moveIconBetweenDocks(src, dest, btn, x, y); + wDockMoveIconBetweenDocks(src, dest, btn, x, y); XUnmapWindow(dpy, btn->icon->core->window); } } } else if (icon != scr->clip_icon) { if (wDockFindFreeSlot(dest, &x, &y)) { - moveIconBetweenDocks(src, dest, icon, x, y); + wDockMoveIconBetweenDocks(src, dest, icon, x, y); XUnmapWindow(dpy, icon->icon->core->window); } } @@ -1961,7 +1958,7 @@ Bool wDockAttachIcon(WDock *dock, WAppIcon *icon, int x, int y, Bool update_icon return True; } -static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y) +void wDockReattachIcon(WDock *dock, WAppIcon *icon, int x, int y) { int index; @@ -1978,7 +1975,7 @@ static void reattachIcon(WDock *dock, WAppIcon *icon, int x, int y) icon->y_pos = dock->y_pos + y * ICON_SIZE; } -static Bool moveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y) +Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y) { WWindow *wwin; char *command = NULL; @@ -2941,7 +2938,7 @@ void wClipUpdateForWorkspaceChange(WScreen *scr, int workspace) WAppIconChain *chain = scr->global_icons; while (chain) { - moveIconBetweenDocks(chain->aicon->dock, + wDockMoveIconBetweenDocks(chain->aicon->dock, scr->workspaces[workspace]->clip, chain->aicon, chain->aicon->xindex, chain->aicon->yindex); if (scr->workspaces[workspace]->clip->collapsed) @@ -3400,217 +3397,6 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) } } -static Bool handleIconMove(WDock *dock, WAppIcon *aicon, XEvent *event) -{ - WScreen *scr = dock->screen_ptr; - Window wins[2]; - WIcon *icon = aicon->icon; - WDock *dock2 = NULL, *last_dock = dock, *clip = NULL; - int ondock, grabbed = 0, change_dock = 0, collapsed = 0; - XEvent ev; - int x = aicon->x_pos, y = aicon->y_pos; - int ofs_x = event->xbutton.x, ofs_y = event->xbutton.y; - int shad_x = x, shad_y = y; - int ix = aicon->xindex, iy = aicon->yindex; - int tmp; - Pixmap ghost = None; - Bool docked; - int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ - int omnipresent = aicon->omnipresent; /* this must be cached!!! */ - Bool showed_all_clips = False; - Bool hasMoved = False; - - if (wPreferences.flags.noupdates) - return hasMoved; - - if (XGrabPointer(dpy, icon->core->window, True, ButtonMotionMask - | ButtonReleaseMask | ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None, CurrentTime) != GrabSuccess) { - } - - if (!(event->xbutton.state & MOD_MASK)) - wRaiseFrame(icon->core); - - if (!wPreferences.flags.noclip) - clip = scr->workspaces[scr->current_workspace]->clip; - - if (dock == scr->dock && !wPreferences.flags.noclip) - dock2 = clip; - else if (dock != scr->dock && !wPreferences.flags.nodock) - dock2 = scr->dock; - - wins[0] = icon->core->window; - wins[1] = scr->dock_shadow; - XRestackWindows(dpy, wins, 2); - XMoveResizeWindow(dpy, scr->dock_shadow, aicon->x_pos, aicon->y_pos, ICON_SIZE, ICON_SIZE); - if (superfluous) { - if (icon->pixmap != None) - ghost = MakeGhostIcon(scr, icon->pixmap); - else - ghost = MakeGhostIcon(scr, icon->core->window); - - XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); - XClearWindow(dpy, scr->dock_shadow); - } - XMapWindow(dpy, scr->dock_shadow); - - ondock = 1; - - while (1) { - XMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask - | ButtonMotionMask | ExposureMask, &ev); - switch (ev.type) { - case Expose: - WMHandleEvent(&ev); - break; - - case MotionNotify: - hasMoved = True; - if (!grabbed) { - if (abs(ofs_x - ev.xmotion.x) >= MOVE_THRESHOLD - || abs(ofs_y - ev.xmotion.y) >= MOVE_THRESHOLD) { - XChangeActivePointerGrab(dpy, ButtonMotionMask - | ButtonReleaseMask | ButtonPressMask, - wCursor[WCUR_MOVE], CurrentTime); - grabbed = 1; - } else { - break; - } - } - - if (omnipresent && !showed_all_clips) { - int i; - for (i = 0; i < scr->workspace_count; i++) { - if (i == scr->current_workspace) - continue; - wDockShowIcons(scr->workspaces[i]->clip); - /* Note: if dock is collapsed (for instance, - because it auto-collapses), its icons - still won't show up */ - } - showed_all_clips = True; /* To prevent flickering */ - } - - x = ev.xmotion.x_root - ofs_x; - y = ev.xmotion.y_root - ofs_y; - tmp = wDockSnapIcon(dock, aicon, x, y, &ix, &iy, True); - if (tmp && dock2) { - change_dock = 0; - if (last_dock != dock && collapsed) { - last_dock->collapsed = 1; - wDockHideIcons(last_dock); - collapsed = 0; - } - if (!collapsed && (collapsed = dock->collapsed)) { - dock->collapsed = 0; - wDockShowIcons(dock); - } - if (dock->auto_raise_lower) - wDockRaise(dock); - last_dock = dock; - } else if (dock2) { - tmp = wDockSnapIcon(dock2, aicon, x, y, &ix, &iy, False); - if (tmp) { - change_dock = 1; - if (last_dock != dock2 && collapsed) { - last_dock->collapsed = 1; - wDockHideIcons(last_dock); - collapsed = 0; - } - if (!collapsed && (collapsed = dock2->collapsed)) { - dock2->collapsed = 0; - wDockShowIcons(dock2); - } - if (dock2->auto_raise_lower) - wDockRaise(dock2); - last_dock = dock2; - } - } - if (aicon->launching || aicon->lock || (aicon->running && !(ev.xmotion.state & MOD_MASK)) - || (!aicon->running && tmp)) { - shad_x = last_dock->x_pos + ix * wPreferences.icon_size; - shad_y = last_dock->y_pos + iy * wPreferences.icon_size; - - XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); - - if (!ondock) - XMapWindow(dpy, scr->dock_shadow); - - ondock = 1; - } else { - if (ondock) - XUnmapWindow(dpy, scr->dock_shadow); - - ondock = 0; - } - XMoveWindow(dpy, icon->core->window, x, y); - break; - - case ButtonPress: - break; - - case ButtonRelease: - if (ev.xbutton.button != event->xbutton.button) - break; - XUngrabPointer(dpy, CurrentTime); - if (ondock) { - SlideWindow(icon->core->window, x, y, shad_x, shad_y); - XUnmapWindow(dpy, scr->dock_shadow); - if (!change_dock) { - reattachIcon(dock, aicon, ix, iy); - if (clip && dock != clip && clip->auto_raise_lower) - wDockLower(clip); - } else { - docked = moveIconBetweenDocks(dock, dock2, aicon, ix, iy); - if (!docked) { - /* Slide it back if dock rejected it */ - SlideWindow(icon->core->window, x, y, aicon->x_pos, aicon->y_pos); - reattachIcon(dock, aicon, aicon->xindex, aicon->yindex); - } - if (last_dock->type == WM_CLIP && last_dock->auto_collapse) - collapsed = 0; - } - } else { - aicon->x_pos = x; - aicon->y_pos = y; - if (superfluous) { - if (!aicon->running && !wPreferences.no_animations) { - /* We need to deselect it, even if is deselected in - * wDockDetach(), because else DoKaboom() will fail. - */ - if (aicon->icon->selected) - wIconSelect(aicon->icon); - - DoKaboom(scr, aicon->icon->core->window, x, y); - } - } - if (clip && clip->auto_raise_lower) - wDockLower(clip); - wDockDetach(dock, aicon); - } - if (collapsed) { - last_dock->collapsed = 1; - wDockHideIcons(last_dock); - collapsed = 0; - } - if (superfluous) { - if (ghost != None) - XFreePixmap(dpy, ghost); - XSetWindowBackground(dpy, scr->dock_shadow, scr->white_pixel); - } - if (showed_all_clips) { - int i; - for (i = 0; i < scr->workspace_count; i++) { - if (i == scr->current_workspace) - continue; - wDockHideIcons(scr->workspaces[i]->clip); - } - } - return hasMoved;; - } - } - return False; /* never reached */ -} static int getClipButton(int px, int py) { @@ -3730,7 +3516,7 @@ static void iconMouseDown(WObjDescriptor *desc, XEvent *event) else handleDockMove(dock, aicon, event); } else { - Bool hasMoved = handleIconMove(dock, aicon, event); + Bool hasMoved = wHandleAppIconMove(aicon, event); if (wPreferences.single_click && !hasMoved) iconDblClick(desc, event); } diff --git a/src/dock.h b/src/dock.h index 47d963d4..8cc68429 100644 --- a/src/dock.h +++ b/src/dock.h @@ -82,6 +82,8 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x, int *ret_y, int redocking); Bool wDockFindFreeSlot(WDock *dock, int *req_x, int *req_y); void wDockDetach(WDock *dock, WAppIcon *icon); +Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y); +void wDockReattachIcon(WDock *dock, WAppIcon *icon, int x, int y); void wDockFinishLaunch(WDock *dock, WAppIcon *icon); void wDockTrackWindowLaunch(WDock *dock, Window window); From 95a73e27839f66055a4e47acb844c716b4855548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:39 +0200 Subject: [PATCH 13/20] Added wDefaultPurgeInfo to remove what we stored about a given instance-class couple. This function is not used for now, but will be for drawers --- src/defaults.h | 3 +++ src/wdefaults.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/defaults.h b/src/defaults.h index a2b9f24b..2f82fd6c 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -54,4 +54,7 @@ char *get_icon_filename(WScreen *scr, char *winstance, char *wclass, char *comma int wDefaultGetStartWorkspace(WScreen *scr, char *instance, char *class); void wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file); RImage *get_rimage_from_file(WScreen *scr, char *file_name, int max_size); + +void wDefaultPurgeInfo(WScreen *scr, char *instance, char *class); + #endif /* WMDEFAULTS_H_ */ diff --git a/src/wdefaults.c b/src/wdefaults.c index 0e7d6cdb..ce9af5f8 100644 --- a/src/wdefaults.c +++ b/src/wdefaults.c @@ -597,6 +597,37 @@ void wDefaultChangeIcon(WScreen * scr, char *instance, char *class, char *file) WMPLSetCaseSensitive(False); } +void wDefaultPurgeInfo(WScreen *scr, char *instance, char *class) +{ + WMPropList *value, *key, *dict; + char *buffer; + + if (!AIcon) { /* Unnecessary precaution */ + init_wdefaults(); + } + + WMPLSetCaseSensitive(True); + + buffer = wmalloc(strlen(class) + strlen(instance) + 2); + sprintf(buffer, "%s.%s", instance, class); + key = WMCreatePLString(buffer); + + dict = WMGetFromPLDictionary(WDWindowAttributes->dictionary, key); + + if (dict) { + value = WMGetFromPLDictionary(dict, AIcon); + if (value) { + WMRemoveFromPLDictionary(dict, AIcon); + } + WMRemoveFromPLDictionary(WDWindowAttributes->dictionary, key); + UpdateDomainFile(WDWindowAttributes); + } + + wfree(buffer); + WMReleasePropList(key); + WMPLSetCaseSensitive(False); +} + /* --------------------------- Local ----------------------- */ static int getBool(WMPropList * key, WMPropList * value) From 707ce34a5e2adfb2f13b7ac9387940f7e0c80e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:40 +0200 Subject: [PATCH 14/20] Added a SlideWindows function to handle horizontally-aligned array of windows The existing SlideWindow() function is changed to call SlideWindows() with an array of 1 window --- src/funcs.h | 1 + src/misc.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/funcs.h b/src/funcs.h index a7df6cbe..ac5b4645 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -77,6 +77,7 @@ WWindow * NextToFocusBefore(WWindow *wwin); void move_window(Window win, int from_x, int from_y, int to_x, int to_y); void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y); +void SlideWindows(Window *wins[], int n, int from_x, int from_y, int to_x, int to_y); RImage * wGetImageForWindowName(WScreen *scr, char *winstance, char *wclass); diff --git a/src/misc.c b/src/misc.c index 9922ea23..4e2cae6a 100644 --- a/src/misc.c +++ b/src/misc.c @@ -49,6 +49,7 @@ /**** global variables *****/ extern WPreferences wPreferences; +#define ICON_SIZE wPreferences.icon_size /* XFetchName Wrapper */ Bool wFetchName(Display *dpy, Window win, char **winname) @@ -142,11 +143,21 @@ void move_window(Window win, int from_x, int from_y, int to_x, int to_y) } void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y) +{ + Window *wins[1] = { &win }; + SlideWindows(wins, 1, from_x, from_y, to_x, to_y); +} + +/* wins is an array of Window, sorted from left to right, the first is + * going to be moved from (from_x,from_y) to (to_x,to_y) and the + * following windows are going to be offset by (ICON_SIZE*i,0) */ +void SlideWindows(Window *wins[], int n, int from_x, int from_y, int to_x, int to_y) { time_t time0 = time(NULL); float dx, dy, x = from_x, y = from_y, sx, sy, px, py; int dx_is_bigger = 0; int slide_delay, slide_steps, slide_slowdown; + int i; /* animation parameters */ static struct { @@ -214,7 +225,9 @@ void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y) px = (sy == 0 ? 0 : py * dx / dy); } - XMoveWindow(dpy, win, (int)x, (int)y); + for (i = 0; i < n; i++) { + XMoveWindow(dpy, *wins[i], (int)x + i * ICON_SIZE, (int)y); + } XFlush(dpy); if (slide_delay > 0) { wusleep(slide_delay * 1000L); @@ -224,7 +237,9 @@ void SlideWindow(Window win, int from_x, int from_y, int to_x, int to_y) if (time(NULL) - time0 > MAX_ANIMATION_TIME) break; } - XMoveWindow(dpy, win, to_x, to_y); + for (i = 0; i < n; i++) { + XMoveWindow(dpy, *wins[i], to_x + i * ICON_SIZE, to_y); + } XSync(dpy, 0); /* compress expose events */ From e14e6b3da8a97d282dc71d07beb6febf0f1dd26d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:41 +0200 Subject: [PATCH 15/20] Add drawers to wmaker! Drawers are horizontal docks, and they can themselves only live in the dock To use them, right click on the dock or a docked appicon and select "Add a drawer". Then move appicons into the drawer (drag them with the mouse). You may change the icon of the drawer. By default, drawers auto-expand and -collapse, and auto-raise/lower. This can be customized in the same way as for the clip. Set DisableDrawers to YES in G/D/WindowMaker if you do not want to see the menu entry to add a drawer. Just discovered this bug: the auto-attract icon functionality will not work (to be precise, it crashes WM!) if the clip is disabled (NoClip=YES). Will fix shortly, of course. --- WindowMaker/Defaults/WindowMaker.in | 1 + WindowMaker/Icons/Drawer.png | Bin 0 -> 1420 bytes WindowMaker/Icons/Makefile.am | 1 + debian/debianfiles/conf/WMWindowAttributes | 1 + src/WindowMaker.h | 1 + src/appicon.c | 141 +- src/defaults.c | 18 + src/dock.c | 1429 +++++++++++++++++--- src/dock.h | 19 +- src/dockedapp.c | 3 + src/icon.c | 14 +- src/icon.h | 1 + src/main.c | 3 + src/screen.c | 15 + src/screen.h | 14 +- src/session.c | 38 +- src/startup.c | 8 + src/superfluous.c | 71 +- src/workspace.c | 2 +- 19 files changed, 1560 insertions(+), 220 deletions(-) create mode 100644 WindowMaker/Icons/Drawer.png diff --git a/WindowMaker/Defaults/WindowMaker.in b/WindowMaker/Defaults/WindowMaker.in index 500046e9..d2f3d58d 100644 --- a/WindowMaker/Defaults/WindowMaker.in +++ b/WindowMaker/Defaults/WindowMaker.in @@ -43,6 +43,7 @@ NewStyle = "new"; DisableDock = NO; DisableClip = NO; + DisableDrawers = NO; Superfluous = YES; StickyIcons = NO; SaveSessionOnExit = NO; diff --git a/WindowMaker/Icons/Drawer.png b/WindowMaker/Icons/Drawer.png new file mode 100644 index 0000000000000000000000000000000000000000..8a33abe14904ff0b07692b80ede5fe79a6afb2c2 GIT binary patch literal 1420 zcmV;71#|j|P)aIZdIAo53pjFi=(Lnf<=LU z_Q8N$fQEeF?KN8ncipCgkwPcr#eTDQ`(Rf1U=iRhpn2N!@#a~;7SulH;UfT`#Rd5M z!!^q0fOSn?b@jQ2k8dj|2Ve5cD&Tc|)8+S81f(K#LO$hAhHvlfgdB0IXS8h#boXyv zt+cX**I#NQ$p~>q@JW(NS}1mW`%_5>12)4;Q^L*76x+keJxUXlUciMO>?yQctn|T) zQ0Cchc%-L!QUMS5C9d5`aPoLq3BFQ*;YeeYG8`rZBAN@R6uigPY+lQ9mrM~732bgj z?8X`=$KW5!g#bWP?!QLkb%VJKtQ$9hV32yceq40q%19iaP+Kd1I-L~*nTDw?vx&uH10Y##~-@vH*R`TWL9SbI7lpV6}2({#qgOeWRfl_qFvC_r6W?FaxsZ)IWu_-}p4mCz`GF239@W$1A-D*`JH?n}6=cOW? zTI~Y6G0+l_dnv+p8~1k<)>k=#79kAFHSZQtRU;6BqXHiY1|q_hn_GC{xhFtGc(|M3 z$E#b|-p|e7>uL-J;Y@4d(>PIe57bD2vLY1-h6|VP;Khxn(eJL{`t3b@^Yc9@38Wc7 ztOY4^OEJd0+K*EWr3sA93gwH9peb-WRZ2w|MlpW+C(35?r815(8!6i%i5rw8nK{l{Ah?1tBz&jL>c|toPgKblT|l`bZCVW@2YDB#nm} zC%xz<7N`Q>>#t1;Sc`**&|!q9IALuN6yR36Jq!i|bh|6~=dZh7@PS~+G!Q!IwI=9A z2b#K??_pHT+VSCdNFjnC3+8$8qhZQM(y;x*C=IOWfW^L#=sb>-0!OcoaL@$YrSz6 zs`FCH_3e2IF!5ur&jVds0Hq0uBpk-N0I!^;OM0rY3*HvqbezWLqtSFwRJqGSK^&!o z-J!;VJ%v%K3r&;_8}q8B;H+rK#5f?`{em-amM4x(HXLZK-cE4qUWQ?$$C+hzkKqyJ zAI7GyzP*h3*G-rhc9a08pKUM?oIVla^og+6;BB`7QV|kM(`D8%Jlhh67X}<*z_FJc z;XqUMI#DVrz`KEGK=}l4UCCUHt0~Qz3*Z~b-JrDtb86iw|Ebj83=;+%qf`}d{RB6{ zOrLk@hGGi|;2W^Nyco?K^6^_M}vrX#1ex0gVzTh zsQ8EGlebsN$=AKSIl%J(_5d6J7<}>l@K2v0Uth}qN%`oFcELM;IVpYKxikF$0K2g{ zOpR;BB%n0mhwHNRzFGqKwBCfyo#}^|Bpq#iX8_v2{Sid~5R<^gYuS-Ldr3=L(vp@m aMgIa0;@_`hHx~2&0000main_window_desc->screen_ptr; - WDock *clip = scr->workspaces[scr->current_workspace]->clip; + WDock *attracting_dock; int x = 0, y = 0; Bool update_icon = False; @@ -213,13 +213,17 @@ void paint_app_icon(WApplication *wapp) if (wapp->app_icon->docked) return; - if (clip && clip->attract_icons && wDockFindFreeSlot(clip, &x, &y)) { + attracting_dock = scr->attracting_drawer != NULL ? + scr->attracting_drawer : + scr->workspaces[scr->current_workspace]->clip; + if (attracting_dock && attracting_dock->attract_icons && + wDockFindFreeSlot(attracting_dock, &x, &y)) { wapp->app_icon->attracted = 1; if (!icon->shadowed) { icon->shadowed = 1; update_icon = True; } - wDockAttachIcon(clip, wapp->app_icon, x, y, update_icon); + wDockAttachIcon(attracting_dock, wapp->app_icon, x, y, update_icon); } else { /* We must know if the icon is painted in the screen, * because if painted, then PlaceIcon will return the next @@ -238,7 +242,7 @@ void paint_app_icon(WApplication *wapp) wapp->app_icon->next == NULL && wapp->app_icon->prev == NULL) add_to_appicon_list(scr, wapp->app_icon); - if (!clip || !wapp->app_icon->attracted || !clip->collapsed) + if (!attracting_dock || !wapp->app_icon->attracted || !attracting_dock->collapsed) XMapWindow(dpy, icon->core->window); if (wPreferences.auto_arrange_icons && !wapp->app_icon->attracted) @@ -270,6 +274,9 @@ void removeAppIconFor(WApplication *wapp) wAppIconPaint(wapp->app_icon); } else if (wapp->app_icon->docked) { wapp->app_icon->running = 0; + if (wapp->app_icon->dock->type == WM_DRAWER) { + wDrawerFillTheGap(wapp->app_icon->dock, wapp->app_icon, True); + } wDockDetach(wapp->app_icon->dock, wapp->app_icon); } else { wAppIconDestroy(wapp->app_icon); @@ -723,9 +730,12 @@ void appIconMouseDown(WObjDescriptor * desc, XEvent * event) Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) { + WIcon *icon = aicon->icon; + WScreen *scr = icon->core->screen_ptr; WDock *originalDock = aicon->dock; /* can be NULL */ WDock *lastDock = originalDock; - WDock *allDocks[2]; /* clip and dock (order to be determined at runtime) */ + WDock *allDocks[scr->drawer_count + 2]; /* clip, dock and drawers (order determined at runtime) */ + WDrawerChain *dc; Bool done = False, dockable, ondock; Bool grabbed = False; Bool collapsed = False; /* Stores the collapsed state of lastDock, before the moving appicon entered it */ @@ -733,8 +743,6 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) int omnipresent = aicon->omnipresent; /* this must be cached */ Bool showed_all_clips = False; - WIcon *icon = aicon->icon; - WScreen *scr = icon->core->screen_ptr; int clickButton = event->xbutton.button; Pixmap ghost = None; Window wins[2]; /* Managing shadow window */ @@ -773,7 +781,7 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) } else { ondock = False; - if (wPreferences.flags.nodock && wPreferences.flags.noclip) + if (wPreferences.flags.nodock && wPreferences.flags.noclip && wPreferences.flags.nodrawer) dockable = 0; else dockable = canBeDocked(icon->owner); @@ -781,21 +789,26 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) /* We try the various docks in that order: * - First, the dock the appicon comes from, if any + * - Then, the drawers * - Then, the "dock" (WM_DOCK) * - Finally, the clip */ i = 0; if (originalDock != NULL) allDocks[ i++ ] = originalDock; + /* Testing scr->drawers is enough, no need to test wPreferences.flags.nodrawer */ + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + if (dc->adrawer != originalDock) + allDocks[ i++ ] = dc->adrawer; + } if (!wPreferences.flags.nodock && scr->dock != originalDock) allDocks[ i++ ] = scr->dock; if (!wPreferences.flags.noclip && originalDock != scr->workspaces[scr->current_workspace]->clip) allDocks[ i++ ] = scr->workspaces[scr->current_workspace]->clip; - for ( ; i < 2; i++) /* In case the clip, the dock, or both, are disabled */ + for ( ; i < scr->drawer_count + 2; i++) /* In case the clip, the dock, or both, are disabled */ allDocks[ i ] = NULL; - wins[0] = icon->core->window; wins[1] = scr->dock_shadow; XRestackWindows(dpy, wins, 2); @@ -856,31 +869,28 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) y = ev.xmotion.y_root - ofs_y; wAppIconMove(aicon, x, y); - /* At a high level, this if-block is about setting theNewDock to - * the first dock that could snap the appicon at the current - * position, and the next if-block uses that and other info to - * determine whether to dock/undock. - */ WDock *theNewDock = NULL; - for (i = 0; dockable && i < 2; i++) { - WDock *theDock = allDocks[i]; - if (theDock == NULL) - break; - if (wDockSnapIcon(theDock, aicon, x, y, &ix, &iy, (theDock == originalDock))) { - theNewDock = theDock; - break; + if (!(ev.xmotion.state & MOD_MASK) || aicon->launching || aicon->lock) { + for (i = 0; dockable && i < scr->drawer_count + 2; i++) { + WDock *theDock = allDocks[i]; + if (theDock == NULL) + break; + if (wDockSnapIcon(theDock, aicon, x, y, &ix, &iy, (theDock == originalDock))) { + theNewDock = theDock; + break; + } + } + if (originalDock != NULL && theNewDock == NULL && + (aicon->launching || aicon->lock || aicon->running)) { + /* In those cases, stay in lastDock if no dock really wants us */ + theNewDock = lastDock; } } - if (originalDock != NULL && theNewDock == NULL && - (aicon->launching || aicon->lock || aicon->running)) { - /* In those cases, stay in lastDock if no dock really wants us */ - theNewDock = lastDock; - } - if (theNewDock != NULL && !aicon->launching && !aicon->lock && ev.xmotion.state & MOD_MASK) - /* Mod is pressed: do not dock */ - theNewDock = NULL; if (lastDock != NULL && lastDock != theNewDock) { /* Leave lastDock in the state we found it */ + if (lastDock->type == WM_DRAWER) { + wDrawerFillTheGap(lastDock, aicon, (lastDock == originalDock)); + } if (collapsed) { lastDock->collapsed = 1; wDockHideIcons(lastDock); @@ -918,6 +928,14 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) lastDock = theNewDock; // i.e., NULL if (ondock) { XUnmapWindow(dpy, scr->dock_shadow); + /* + * Leaving that weird comment for now. + * But if we see no gap, there is no need to fill one! + * We could test ondock first and the lastDock to NULL afterwards + if (lastDock_before_it_was_null->type == WM_DRAWER) { + wDrawerFillTheGap(lastDock, aicon, (lastDock == originalDock)); + } */ + } ondock = 0; } @@ -942,6 +960,10 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) command for that appicon, and the user cancels the wInputDialog asking for one). Make the rejection obvious by sliding the icon to its old position */ + if (lastDock->type == WM_DRAWER) { + // Also fill the gap left in the drawer + wDrawerFillTheGap(lastDock, aicon, False); + } SlideWindow(icon->core->window, x, y, oldX, oldY); } } @@ -956,14 +978,45 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) /* Possible scenario: user moved an auto-attracted appicon from the clip to the dock, and cancelled the wInputDialog asking for a command */ + if (lastDock->type == WM_DRAWER) { + wDrawerFillTheGap(lastDock, aicon, False); + } + /* If aicon comes from a drawer, make some room to reattach it */ + if (originalDock->type == WM_DRAWER) { + WAppIcon *aiconsToShift[ originalDock->icon_count ]; + int j = 0; + + for (i = 0; i < originalDock->max_icons; i++) { + WAppIcon *ai = originalDock->icon_array[ i ]; + if (ai && ai != aicon && + abs(ai->xindex) >= abs(aicon->xindex)) + aiconsToShift[j++] = ai; + } + if (j != originalDock->icon_count - abs(aicon->xindex) - 1) + // Trust this never happens? + wwarning("Shifting j=%d appicons (instead of %d!) to reinsert aicon at index %d.", + j, originalDock->icon_count - abs(aicon->xindex) - 1, aicon->xindex); + wSlideAppicons(aiconsToShift, j, originalDock->on_right_side); + // Trust the appicon is inserted at exactly the same place, so its oldX/oldY are consistent with its "new" location? + } + SlideWindow(icon->core->window, x, y, oldX, oldY); wDockReattachIcon(originalDock, aicon, aicon->xindex, aicon->yindex); } + else { + if (originalDock->auto_collapse && !originalDock->collapsed) { + originalDock->collapsed = 1; + wDockHideIcons(originalDock); + } + if (originalDock->auto_raise_lower) + wDockLower(originalDock); + } } } // No matter what happened above, check to lower lastDock - if (lastDock->auto_raise_lower) - wDockLower(lastDock); + // Don't see why I commented out the following 2 lines + /* if (lastDock->auto_raise_lower) + wDockLower(lastDock); */ /* If docked (or tried to dock) to a auto_collapsing dock, unset * collapsed, so that wHandleAppIconMove doesn't collapse it * right away (the timer will take care of it) */ @@ -983,13 +1036,23 @@ Bool wHandleAppIconMove(WAppIcon *aicon, XEvent *event) } } wDockDetach(originalDock, aicon); + if (originalDock->auto_collapse && !originalDock->collapsed) { + originalDock->collapsed = 1; + wDockHideIcons(originalDock); + } + if (originalDock->auto_raise_lower) + wDockLower(originalDock); } } - if (collapsed) { + // Can't remember why the icon hiding is better done above than below (commented out) + // Also, lastDock is quite different from originalDock + /* + if (collapsed) { lastDock->collapsed = 1; wDockHideIcons(lastDock); collapsed = 0; } + */ if (superfluous) { if (ghost != None) XFreePixmap(dpy, ghost); @@ -1076,7 +1139,7 @@ static void create_appicon_from_dock(WWindow *wwin, WApplication *wapp, Window m if (!wapp->app_icon && scr->dock) wapp->app_icon = findDockIconFor(scr->dock, main_window); - /* finally check clips */ + /* check clips */ if (!wapp->app_icon) { int i; for (i = 0; i < scr->workspace_count; i++) { @@ -1088,6 +1151,16 @@ static void create_appicon_from_dock(WWindow *wwin, WApplication *wapp, Window m } } + /* Finally check drawers */ + if (!wapp->app_icon) { + WDrawerChain *dc; + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + wapp->app_icon = findDockIconFor(dc->adrawer, main_window); + if (wapp->app_icon) + break; + } + } + /* If created, then set some flags */ if (wapp->app_icon) { WWindow *mainw = wapp->main_window_desc; diff --git a/src/defaults.c b/src/defaults.c index 3119aebc..053551d1 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -325,6 +325,8 @@ WDefaultEntry staticOptionList[] = { NULL, getBool, setIfDockPresent, NULL, NULL}, {"DisableClip", "NO", (void *)WM_CLIP, NULL, getBool, setIfDockPresent, NULL, NULL}, + {"DisableDrawers", "NO", (void *)WM_DRAWER, + NULL, getBool, setIfDockPresent, NULL, NULL}, {"DisableMiniwindows", "NO", NULL, &wPreferences.disable_miniwindows, getBool, NULL, NULL, NULL} }; @@ -1132,6 +1134,7 @@ void wReadDefaults(WScreen * scr, WMPropList * new_dict) void wDefaultUpdateIcons(WScreen *scr) { WAppIcon *aicon = scr->app_icon_list; + WDrawerChain *dc; WWindow *wwin = scr->focused_window; while (aicon) { @@ -1144,6 +1147,9 @@ void wDefaultUpdateIcons(WScreen *scr) if (!wPreferences.flags.noclip) wClipIconPaint(scr->clip_icon); + for (dc = scr->drawers; dc != NULL; dc = dc->next) + wDrawerIconPaint(dc->adrawer->icon_array[0]); + while (wwin) { if (wwin->icon && wwin->flags.miniaturized) wIconChangeImageFile(wwin->icon, NULL); @@ -2325,10 +2331,15 @@ static int setIfDockPresent(WScreen * scr, WDefaultEntry * entry, char *flag, lo switch (which) { case WM_DOCK: wPreferences.flags.nodock = wPreferences.flags.nodock || *flag; + // Drawers require the dock + wPreferences.flags.nodrawer = wPreferences.flags.nodrawer || wPreferences.flags.nodock; break; case WM_CLIP: wPreferences.flags.noclip = wPreferences.flags.noclip || *flag; break; + case WM_DRAWER: + wPreferences.flags.nodrawer = wPreferences.flags.nodrawer || *flag; + break; default: break; } @@ -2379,6 +2390,13 @@ static int setIconTile(WScreen * scr, WDefaultEntry * entry, WTexture ** texture scr->clip_tile = wClipMakeTile(scr, img); } + if (!wPreferences.flags.nodrawer) { + if (scr->drawer_tile) { + RReleaseImage(scr->drawer_tile); + } + scr->drawer_tile = wDrawerMakeTile(scr, img); + } + scr->icon_tile_pixmap = pixmap; if (scr->def_icon_rimage) { diff --git a/src/dock.c b/src/dock.c index e2352fd4..130f548a 100644 --- a/src/dock.c +++ b/src/dock.c @@ -85,6 +85,8 @@ static WMPropList *dPosition, *dApplications, *dLowered, *dCollapsed; static WMPropList *dAutoCollapse, *dAutoRaiseLower, *dOmnipresent; +static WMPropList *dDrawers = NULL; + static void dockIconPaint(WAppIcon *btn); static void iconMouseDown(WObjDescriptor *desc, XEvent *event); @@ -113,7 +115,17 @@ static void launchDockedApplication(WAppIcon *btn, Bool withSelection); static void clipAutoLower(void *cdata); static void clipAutoRaise(void *cdata); -static WAppIcon *mainIconCreate(WScreen *scr, int type); +static WAppIcon *mainIconCreate(WScreen *scr, int type, char *name); + +static void drawerIconExpose(WObjDescriptor *desc, XEvent *event); +static void removeDrawerCallback(WMenu *menu, WMenuEntry *entry); +static void drawerAppendToChain(WScreen *scr, WDock *drawer); +static char *findUniqueName(WScreen *scr, char *instance_basename); +static void addADrawerCallback(WMenu *menu, WMenuEntry *entry); +static void swapDrawers(WScreen *scr, int on_right_side, int new_x); +static WDock* getDrawer(WScreen *scr, int y_index); +static int indexOfHole(WDock *drawer, WAppIcon *moving_aicon, int redocking); +static void drawerConsolidateIcons(WDock *drawer); static int onScreen(WScreen *scr, int x, int y); @@ -148,6 +160,7 @@ static void make_keys(void) dDock = WMCreatePLString("Dock"); dClip = WMCreatePLString("Clip"); + dDrawers = WMCreatePLString("Drawers"); } static void renameCallback(WMenu *menu, WMenuEntry *entry) @@ -480,9 +493,10 @@ static void removeIconsCallback(WMenu *menu, WMenuEntry *entry) selectedIcons = getSelected(dock); if (WMGetArrayItemCount(selectedIcons)) { - if (wMessageDialog(dock->screen_ptr, _("Workspace Clip"), - _("All selected icons will be removed!"), - _("OK"), _("Cancel"), NULL) != WAPRDefault) { + if (wMessageDialog(dock->screen_ptr, + dock->type == WM_CLIP ? _("Workspace Clip") : _("Drawer"), + _("All selected icons will be removed!"), + _("OK"), _("Cancel"), NULL) != WAPRDefault) { WMFreeArray(selectedIcons); return; } @@ -495,6 +509,10 @@ static void removeIconsCallback(WMenu *menu, WMenuEntry *entry) } removeIcons(selectedIcons, dock); + + if (dock->type == WM_DRAWER) { + drawerConsolidateIcons(dock); + } } static void keepIconsCallback(WMenu *menu, WMenuEntry *entry) @@ -560,14 +578,64 @@ static void keepIconsCallback(WMenu *menu, WMenuEntry *entry) static void toggleAutoAttractCallback(WMenu *menu, WMenuEntry *entry) { WDock *dock = (WDock *) entry->clientdata; + WScreen *scr = dock->screen_ptr; assert(entry->clientdata != NULL); + /* Setting a clip as autoattracting will disable an autoattracting drawer, + * and reciprocally. Ask for confirmation? */ +#ifdef CONFIRM_AUTOATTRACT_CHANGE + if (dock->type == WM_CLIP && scr->attracting_drawer) { + if (wMessageDialog(scr, _("Workspace Clip"), + _("The drawer that auto-attracted icons so far won't do so anymore!"), + _("OK"), _("Cancel"), NULL) != WAPRDefault) + return; + } else if (dock->type == WM_DRAWER) { + /* check if at least one clip already auto attracts icons */ + int i, ask_for_confirmation = False; + for (i = 0; i < scr->workspace_count; i++) { + if (scr->workspaces[ i ]->clip->attract_icons) { + ask_for_confirmation = True; + break; + } + } + if (ask_for_confirmation) { + if (wMessageDialog(scr, _("Drawer"), + _("Any clips that auto-attracted icons so far won't do so anymore!"), + _("OK"), _("Cancel"), NULL) != WAPRDefault) + return; + } + } +#endif + dock->attract_icons = !dock->attract_icons; entry->flags.indicator_on = dock->attract_icons; wMenuPaint(menu); + + if (dock->attract_icons) { + if (dock->type == WM_DRAWER) { + /* The newly auto-attracting dock is a drawer: disable any clip and + * previously attracting drawer */ + int i; + for (i = 0; i < scr->workspace_count; i++) { + scr->workspaces[ i ]->clip->attract_icons = False; + /* dock menu will be updated later, when opened */ + } + if (scr->attracting_drawer != NULL) + scr->attracting_drawer->attract_icons = False; + scr->attracting_drawer = dock; + } else { + /* The newly auto-attracting dock is a clip: disable + * previously attracting drawer, if applicable */ + if (scr->attracting_drawer != NULL) { + scr->attracting_drawer->attract_icons = False; + /* again, its menu will be updated, later. */ + scr->attracting_drawer = NULL; + } + } + } } static void selectCallback(WMenu *menu, WMenuEntry *entry) @@ -584,7 +652,7 @@ static void selectCallback(WMenu *menu, WMenuEntry *entry) static void colectIconsCallback(WMenu *menu, WMenuEntry *entry) { WAppIcon *clickedIcon = (WAppIcon *) entry->clientdata; - WDock *clip; + WDock *clip; /* clip... is a WM_CLIP or a WM_DRAWER */ WAppIcon *aicon; int x, y, x_pos, y_pos; Bool update_icon = False; @@ -669,6 +737,19 @@ static void toggleAutoCollapseCallback(WMenu *menu, WMenuEntry *entry) wMenuPaint(menu); } +static void toggleAutoRaiseLower(WDock *dock) +{ + WDrawerChain *dc; + + dock->auto_raise_lower = !dock->auto_raise_lower; + if (dock->type == WM_DOCK) + { + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) { + toggleAutoRaiseLower(dc->adrawer); + } + } +} + static void toggleAutoRaiseLowerCallback(WMenu *menu, WMenuEntry *entry) { WDock *dock; @@ -676,7 +757,7 @@ static void toggleAutoRaiseLowerCallback(WMenu *menu, WMenuEntry *entry) dock = (WDock *) entry->clientdata; - dock->auto_raise_lower = !dock->auto_raise_lower; + toggleAutoRaiseLower(dock); entry->flags.indicator_on = ((WDock *) entry->clientdata)->auto_raise_lower; @@ -724,28 +805,41 @@ static void unhideHereCallback(WMenu *menu, WMenuEntry *entry) wUnhideApplication(wapp, False, True); } -static WAppIcon *mainIconCreate(WScreen *scr, int type) +/* Name is only used when type == WM_DRAWER and when restoring a specific + * drawer, with a specific name. When creating a drawer, leave name to NULL + * and mainIconCreate will find the first unused unique name */ +WAppIcon *mainIconCreate(WScreen *scr, int type, char *name) { WAppIcon *btn; int x_pos; - if (type == WM_CLIP) { + switch(type) { + case WM_CLIP: if (scr->clip_icon) return scr->clip_icon; btn = wAppIconCreateForDock(scr, NULL, "Logo", "WMClip", TILE_CLIP); btn->icon->core->descriptor.handle_expose = clipIconExpose; - btn->icon->core->descriptor.handle_enternotify = clipEnterNotify; - btn->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; x_pos = 0; - } else { + break; + case WM_DOCK: + default: /* to avoid a warning about btn and x_pos, basically */ btn = wAppIconCreateForDock(scr, NULL, "Logo", "WMDock", TILE_NORMAL); x_pos = scr->scr_width - ICON_SIZE - DOCK_EXTRA_SPACE; + break; + case WM_DRAWER: + if (name == NULL) + name = findUniqueName(scr, "Drawer"); + btn = wAppIconCreateForDock(scr, NULL, name, "WMDrawer", TILE_DRAWER); + btn->icon->core->descriptor.handle_expose = drawerIconExpose; + x_pos = 0; } btn->xindex = 0; btn->yindex = 0; btn->icon->core->descriptor.handle_mousedown = iconMouseDown; + btn->icon->core->descriptor.handle_enternotify = clipEnterNotify; + btn->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; btn->icon->core->descriptor.parent_type = WCLASS_DOCK_ICON; btn->icon->core->descriptor.parent = btn; XMapWindow(dpy, btn->icon->core->window); @@ -898,6 +992,7 @@ static void updateClipOptionsMenu(WMenu *menu, WDock *dock) entry = menu->entries[index]; entry->flags.indicator_on = !dock->lowered; entry->clientdata = dock; + wMenuSetEnabled(menu, index, dock->type == WM_CLIP); /* collapsed */ entry = menu->entries[++index]; @@ -913,7 +1008,7 @@ static void updateClipOptionsMenu(WMenu *menu, WDock *dock) entry = menu->entries[++index]; entry->flags.indicator_on = dock->auto_raise_lower; entry->clientdata = dock; - wMenuSetEnabled(menu, index, dock->lowered); + wMenuSetEnabled(menu, index, dock->lowered && (dock->type == WM_CLIP)); /* attract icons */ entry = menu->entries[++index]; @@ -924,6 +1019,7 @@ static void updateClipOptionsMenu(WMenu *menu, WDock *dock) wMenuRealize(menu); } + static WMenu *makeClipOptionsMenu(WScreen *scr) { WMenu *menu; @@ -966,6 +1062,121 @@ static WMenu *makeClipOptionsMenu(WScreen *scr) return menu; } + +static void setDockPositionNormalCallback(WMenu *menu, WMenuEntry *entry) +{ + WDock *dock = (WDock *) entry->clientdata; + WDrawerChain *dc; + if (entry->flags.indicator_on) // already set, nothing to do + return; + // Do we come from auto raise lower or keep on top? + if (dock->auto_raise_lower) + { + dock->auto_raise_lower = 0; + // Only for aesthetic purposes, can be removed when Autoraise status is no longer exposed in drawer option menu + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) { + dc->adrawer->auto_raise_lower = 0; + } + } + else + { + // Will take care of setting lowered = 0 in drawers + toggleLowered(dock); + } + entry->flags.indicator_on = 1; +} + +static void setDockPositionAutoRaiseLowerCallback(WMenu *menu, WMenuEntry *entry) +{ + WDock *dock = (WDock *) entry->clientdata; + WDrawerChain *dc; + if (entry->flags.indicator_on) // already set, nothing to do + return; + // Do we come from normal or keep on top? + if (!dock->lowered) + { + toggleLowered(dock); + } + dock->auto_raise_lower = 1; + // Only for aesthetic purposes, can be removed when Autoraise status is no longer exposed in drawer option menu + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) { + dc->adrawer->auto_raise_lower = 1; + } + entry->flags.indicator_on = 1; +} + +static void setDockPositionKeepOnTopCallback(WMenu *menu, WMenuEntry *entry) +{ + WDock *dock = (WDock *) entry->clientdata; + WDrawerChain *dc; + if (entry->flags.indicator_on) // already set, nothing to do + return; + dock->auto_raise_lower = 0; + // Only for aesthetic purposes, can be removed when Autoraise status is no longer exposed in drawer option menu + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) { + dc->adrawer->auto_raise_lower = 0; + } + toggleLowered(dock); + entry->flags.indicator_on = 1; +} + +static void updateDockPositionMenu(WMenu *menu, WDock *dock) +{ + WMenuEntry *entry; + int index = 0; + + assert(menu); + assert(dock); + + /* Normal level */ + entry = menu->entries[index++]; + entry->flags.indicator_on = (dock->lowered && !dock->auto_raise_lower); + entry->clientdata = dock; + + /* Auto-raise/lower */ + entry = menu->entries[index++]; + entry->flags.indicator_on = dock->auto_raise_lower; + entry->clientdata = dock; + + /* Keep on top */ + entry = menu->entries[index++]; + entry->flags.indicator_on = !dock->lowered; + entry->clientdata = dock; +} + +static WMenu *makeDockPositionMenu(WScreen *scr) +{ + /* When calling this, the dock is being created, so scr->dock is still not set + * Therefore the callbacks' clientdata and the indicators can't be set, + * they will be updated when the dock menu is opened. */ + WMenu *menu; + WMenuEntry *entry; + + menu = wMenuCreate(scr, NULL, False); + if (!menu) { + wwarning(_("could not create options submenu for dock position menu")); + return NULL; + } + + entry = wMenuAddCallback(menu, _("Normal"), setDockPositionNormalCallback, NULL); + entry->flags.indicator = 1; + entry->flags.indicator_type = MI_DIAMOND; + + entry = wMenuAddCallback(menu, _("Auto raise & lower"), setDockPositionAutoRaiseLowerCallback, NULL); + entry->flags.indicator = 1; + entry->flags.indicator_type = MI_DIAMOND; + + entry = wMenuAddCallback(menu, _("Keep on Top"), setDockPositionKeepOnTopCallback, NULL); + entry->flags.indicator = 1; + entry->flags.indicator_type = MI_DIAMOND; + + menu->flags.realized = 0; + wMenuRealize(menu); + + return menu; +} + + static WMenu *dockMenuCreate(WScreen *scr, int type) { WMenu *menu; @@ -974,21 +1185,38 @@ static WMenu *dockMenuCreate(WScreen *scr, int type) if (type == WM_CLIP && scr->clip_menu) return scr->clip_menu; - menu = wMenuCreate(scr, NULL, False); - if (type != WM_CLIP) { - entry = wMenuAddCallback(menu, _("Keep on Top"), toggleLoweredCallback, NULL); - entry->flags.indicator = 1; - entry->flags.indicator_on = 1; - entry->flags.indicator_type = MI_CHECK; - } else { - entry = wMenuAddCallback(menu, _("Clip Options"), NULL, NULL); - scr->clip_options = makeClipOptionsMenu(scr); - if (scr->clip_options) - wMenuEntrySetCascade(menu, entry, scr->clip_options); + if (type == WM_DRAWER && scr->drawer_menu) + return scr->drawer_menu; - entry = wMenuAddCallback(menu, _("Rename Workspace"), renameCallback, NULL); - wfree(entry->text); - entry->text = _("Rename Workspace"); + menu = wMenuCreate(scr, NULL, False); + if (type == WM_DOCK) { + entry = wMenuAddCallback(menu, _("Dock position"), NULL, NULL); + if (scr->dock_pos_menu == NULL) + scr->dock_pos_menu = makeDockPositionMenu(scr); + wMenuEntrySetCascade(menu, entry, scr->dock_pos_menu); + + if (!wPreferences.flags.nodrawer) { + entry = wMenuAddCallback(menu, _("Add a drawer"), addADrawerCallback, NULL); + } + } else { + if (type == WM_CLIP) + entry = wMenuAddCallback(menu, _("Clip Options"), NULL, NULL); + else /* if (type == WM_DRAWER) */ + entry = wMenuAddCallback(menu, _("Drawer options"), NULL, NULL); + + if (scr->clip_options == NULL) + scr->clip_options = makeClipOptionsMenu(scr); + wMenuEntrySetCascade(menu, entry, scr->clip_options); + + /* The same menu is used for the dock and its appicons. If the menu + * entry text is different between the two contexts, or if it can + * change depending on some state, free the duplicated string (from + * wMenuInsertCallback) and use gettext's string */ + if (type == WM_CLIP) { + entry = wMenuAddCallback(menu, _("Rename Workspace"), renameCallback, NULL); + wfree(entry->text); + entry->text = _("Rename Workspace"); /* can be: (Toggle) Omnipresent */ + } entry = wMenuAddCallback(menu, _("Selected"), selectCallback, NULL); entry->flags.indicator = 1; @@ -997,22 +1225,24 @@ static WMenu *dockMenuCreate(WScreen *scr, int type) entry = wMenuAddCallback(menu, _("Select All Icons"), selectIconsCallback, NULL); wfree(entry->text); - entry->text = _("Select All Icons"); + entry->text = _("Select All Icons"); /* can be: Unselect all icons */ entry = wMenuAddCallback(menu, _("Keep Icon"), keepIconsCallback, NULL); wfree(entry->text); - entry->text = _("Keep Icon"); + entry->text = _("Keep Icon"); /* can be: Keep Icons */ - entry = wMenuAddCallback(menu, _("Move Icon To"), NULL, NULL); - wfree(entry->text); - entry->text = _("Move Icon To"); - scr->clip_submenu = makeWorkspaceMenu(scr); - if (scr->clip_submenu) - wMenuEntrySetCascade(menu, entry, scr->clip_submenu); + if (type == WM_CLIP) { + entry = wMenuAddCallback(menu, _("Move Icon To"), NULL, NULL); + wfree(entry->text); + entry->text = _("Move Icon To"); /* can be: Move Icons to */ + scr->clip_submenu = makeWorkspaceMenu(scr); + if (scr->clip_submenu) + wMenuEntrySetCascade(menu, entry, scr->clip_submenu); + } entry = wMenuAddCallback(menu, _("Remove Icon"), removeIconsCallback, NULL); wfree(entry->text); - entry->text = _("Remove Icon"); + entry->text = _("Remove Icon"); /* can be: Remove Icons */ wMenuAddCallback(menu, _("Attract Icons"), colectIconsCallback, NULL); } @@ -1023,19 +1253,24 @@ static WMenu *dockMenuCreate(WScreen *scr, int type) entry = wMenuAddCallback(menu, _("Hide"), hideCallback, NULL); wfree(entry->text); - entry->text = _("Hide"); + entry->text = _("Hide"); /* can be: Unhide */ wMenuAddCallback(menu, _("Settings..."), settingsCallback, NULL); - wMenuAddCallback(menu, _("Kill"), killCallback, NULL); + entry = wMenuAddCallback(menu, _("Kill"), killCallback, NULL); + wfree(entry->text); + entry->text = _("Kill"); /* can be: Remove drawer */ if (type == WM_CLIP) scr->clip_menu = menu; + if (type == WM_DRAWER) + scr->drawer_menu = menu; + return menu; } -WDock *wDockCreate(WScreen *scr, int type) +WDock *wDockCreate(WScreen *scr, int type, char *name) { WDock *dock; WAppIcon *btn; @@ -1044,11 +1279,21 @@ WDock *wDockCreate(WScreen *scr, int type) dock = wmalloc(sizeof(WDock)); - dock->max_icons = DOCK_MAX_ICONS; + switch (type) { + case WM_CLIP: + dock->max_icons = DOCK_MAX_ICONS; + break; + case WM_DRAWER: + dock->max_icons = scr->scr_width / wPreferences.icon_size; + break; + case WM_DOCK: + default: + dock->max_icons = scr->scr_height / wPreferences.icon_size; + } dock->icon_array = wmalloc(sizeof(WAppIcon *) * dock->max_icons); - btn = mainIconCreate(scr, type); + btn = mainIconCreate(scr, type, name); btn->dock = dock; @@ -1057,7 +1302,10 @@ WDock *wDockCreate(WScreen *scr, int type) dock->screen_ptr = scr; dock->type = type; dock->icon_count = 1; - dock->on_right_side = 1; + if (type == WM_DRAWER) + dock->on_right_side = scr->dock->on_right_side; + else + dock->on_right_side = 1; dock->collapsed = 0; dock->auto_collapse = 0; dock->auto_collapse_magic = NULL; @@ -1073,6 +1321,11 @@ WDock *wDockCreate(WScreen *scr, int type) /* create dock menu */ dock->menu = dockMenuCreate(scr, type); + if (type == WM_DRAWER) { + drawerAppendToChain(scr, dock); + dock->auto_collapse = 1; + } + return dock; } @@ -1158,6 +1411,8 @@ static void dockIconPaint(WAppIcon *btn) { if (btn == btn->icon->core->screen_ptr->clip_icon) { wClipIconPaint(btn); + } else if (wIsADrawer(btn->icon->core->screen_ptr, btn)) { + wDrawerIconPaint(btn); } else { wAppIconPaint(btn); save_appicon(btn, True); @@ -1266,23 +1521,25 @@ static WMPropList *dockSaveState(WDock *dock) } WMReleasePropList(list); - value = (dock->lowered ? dYes : dNo); - WMPutInPLDictionary(dock_state, dLowered, value); - - if (dock->type == WM_CLIP) { + if (dock->type == WM_CLIP || dock->type == WM_DRAWER) { value = (dock->collapsed ? dYes : dNo); WMPutInPLDictionary(dock_state, dCollapsed, value); value = (dock->auto_collapse ? dYes : dNo); WMPutInPLDictionary(dock_state, dAutoCollapse, value); - value = (dock->auto_raise_lower ? dYes : dNo); - WMPutInPLDictionary(dock_state, dAutoRaiseLower, value); - value = (dock->attract_icons ? dYes : dNo); WMPutInPLDictionary(dock_state, dAutoAttractIcons, value); } + if (dock->type == WM_DOCK || dock->type == WM_CLIP) { + value = (dock->lowered ? dYes : dNo); + WMPutInPLDictionary(dock_state, dLowered, value); + + value = (dock->auto_raise_lower ? dYes : dNo); + WMPutInPLDictionary(dock_state, dAutoRaiseLower, value); + } + return dock_state; } @@ -1393,10 +1650,8 @@ static WAppIcon *restore_icon_state(WScreen *scr, WMPropList *info, int type, in wfree(command); aicon->icon->core->descriptor.handle_mousedown = iconMouseDown; - if (type == WM_CLIP) { - aicon->icon->core->descriptor.handle_enternotify = clipEnterNotify; - aicon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; - } + aicon->icon->core->descriptor.handle_enternotify = clipEnterNotify; + aicon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; aicon->icon->core->descriptor.parent_type = WCLASS_DOCK_ICON; aicon->icon->core->descriptor.parent = aicon; @@ -1467,7 +1722,7 @@ WAppIcon *wClipRestoreState(WScreen *scr, WMPropList *clip_state) WAppIcon *icon; WMPropList *value; - icon = mainIconCreate(scr, WM_CLIP); + icon = mainIconCreate(scr, WM_CLIP, NULL); if (!clip_state) return icon; @@ -1513,7 +1768,7 @@ WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) WAppIcon *aicon, *old_top; int count, i; - dock = wDockCreate(scr, type); + dock = wDockCreate(scr, type, NULL); if (!dock_state) return dock; @@ -1918,10 +2173,8 @@ Bool wDockAttachIcon(WDock *dock, WAppIcon *icon, int x, int y, Bool update_icon icon->docked = 1; icon->dock = dock; icon->icon->core->descriptor.handle_mousedown = iconMouseDown; - if (dock->type == WM_CLIP) { - icon->icon->core->descriptor.handle_enternotify = clipEnterNotify; - icon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; - } + icon->icon->core->descriptor.handle_enternotify = clipEnterNotify; + icon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; icon->icon->core->descriptor.parent_type = WCLASS_DOCK_ICON; icon->icon->core->descriptor.parent = icon; @@ -2023,7 +2276,7 @@ Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, i } } - if (dest->type == WM_DOCK) + if (dest->type == WM_DOCK || dest->type == WM_DRAWER) wClipMakeIconOmnipresent(icon, False); for (index = 1; index < src->max_icons; index++) { @@ -2049,18 +2302,13 @@ Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, i if (icon->icon->selected) wIconSelect(icon->icon); - if (dest->type == WM_DOCK) { - icon->icon->core->descriptor.handle_enternotify = NULL; - icon->icon->core->descriptor.handle_leavenotify = NULL; - } else { - icon->icon->core->descriptor.handle_enternotify = clipEnterNotify; - icon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; - } + icon->icon->core->descriptor.handle_enternotify = clipEnterNotify; + icon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify; /* set it to be kept when moving to dock. * Unless the icon does not have a command set */ - if (icon->command && dest->type == WM_DOCK) { + if (icon->command && (dest->type == WM_DOCK || dest->type == WM_DRAWER)) { icon->attracted = 0; if (icon->icon->shadowed) { icon->icon->shadowed = 0; @@ -2182,6 +2430,8 @@ void wDockDetach(WDock *dock, WAppIcon *icon) * Note: this function should NEVER alter ret_x or ret_y, unless it will * return True. -Dan */ +/* Redocking == true means either icon->dock == dock (normal case) + * or we are called from handleDockMove for a drawer */ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x, int *ret_y, int redocking) { WScreen *scr = dock->screen_ptr; @@ -2220,8 +2470,21 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x if (!onScreen(scr, dx + ex_x * ICON_SIZE, dy + ex_y * ICON_SIZE)) return False; - if (dock->type == WM_DOCK) { - if (icon->dock != dock && ex_x != 0) + switch (dock->type) { + case WM_DOCK: + /* We can return False right away if + * - we do not come from this dock (which is a WM_DOCK), + * - we are not right over it, and + * - we are not the main tile of a drawer. + * In the latter case, we are called from handleDockMove. */ + if (icon->dock != dock && ex_x != 0 && + !(icon->dock && icon->dock->type == WM_DRAWER && icon == icon->dock->icon_array[0])) + return False; + + if (!redocking && ex_x != 0) + return False; + + if (getDrawer(scr, ex_y)) /* Return false so that the drawer gets it. */ return False; aicon = NULL; @@ -2239,6 +2502,7 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x /* Possible cases when redocking: * * icon dragged out of range of any slot -> false + * icon dragged on a drawer -> false (to open the drawer) * icon dragged to range of free slot * icon dragged to range of same slot * icon dragged to range of different icon @@ -2270,19 +2534,21 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x if (closest >= 0) { for (j = 0; j < dock->max_icons; j++) { if (dock->icon_array[j] - && dock->icon_array[j]->yindex == closest) { + && dock->icon_array[j]->yindex == closest) { /* slot is used by someone else */ if (dock->icon_array[j] != icon) done = 0; break; } } + /* slot is used by a drawer */ + done = done && !getDrawer(scr, closest); } sig = -sig; } if (done && closest >= 0 && closest <= max_y_icons && - ((ex_y >= closest && ex_y - closest < DOCK_DETTACH_THRESHOLD + 1) - || (ex_y < closest && closest - ex_y <= DOCK_DETTACH_THRESHOLD + 1))) { + ((ex_y >= closest && ex_y - closest < DOCK_DETTACH_THRESHOLD + 1) + || (ex_y < closest && closest - ex_y <= DOCK_DETTACH_THRESHOLD + 1))) { *ret_x = 0; *ret_y = closest; return True; @@ -2296,7 +2562,9 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x return True; } } - } else { /* CLIP */ + break; + case WM_CLIP: + { int neighbours = 0; int start, stop, k; @@ -2340,6 +2608,50 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x *ret_y = ex_y; return True; } + break; + } + case WM_DRAWER: + { + WAppIcon *aicons_to_shift[ dock->icon_count ]; + int index_of_hole, j; + + if (ex_y != 0 || + abs(ex_x) - dock->icon_count > DOCK_DETTACH_THRESHOLD || + (ex_x < 0 && !dock->on_right_side) || + (ex_x > 0 && dock->on_right_side)) { + return False; + } + + if (ex_x == 0) + ex_x = (dock->on_right_side ? -1 : 1); + + /* "Reduce" ex_x but keep its sign */ + if (redocking) { + if (abs(ex_x) > dock->icon_count - 1) /* minus 1: do not take icon_array[0] into account */ + ex_x = ex_x * (dock->icon_count - 1) / abs(ex_x); /* don't use *= ! */ + } else { + if (abs(ex_x) > dock->icon_count) + ex_x = ex_x * dock->icon_count / abs(ex_x); + } + index_of_hole = indexOfHole(dock, icon, redocking); + + /* Find the appicons between where icon was (index_of_hole) and where + * it wants to be (ex_x) and slide them. */ + j = 0; + for (i = 1; i < dock->max_icons; i++) { + if ((aicon = dock->icon_array[ i ]) && aicon != icon && + ((ex_x <= aicon->xindex && aicon->xindex < index_of_hole) || + (index_of_hole < aicon->xindex && aicon->xindex <= ex_x))) + aicons_to_shift[ j++ ] = aicon; + } + assert(j == abs(ex_x - index_of_hole)); + + wSlideAppicons(aicons_to_shift, j, (index_of_hole < ex_x)); + + *ret_x = ex_x; + *ret_y = ex_y; + return True; + } } return False; } @@ -2377,6 +2689,15 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) int sx = 0, ex = scr->scr_width, ey = scr->scr_height; int extra_count = 0; + if (dock->type == WM_DRAWER) { + if (dock->icon_count >= dock->max_icons) { /* drawer is full */ + return False; + } + *x_pos = dock->icon_count * (dock->on_right_side ? -1 : 1); + *y_pos = 0; + return True; + } + if (dock->type == WM_CLIP && dock != scr->workspaces[scr->current_workspace]->clip) extra_count = scr->global_icon_count; @@ -2630,8 +2951,14 @@ Bool wDockFindFreeSlot(WDock *dock, int *x_pos, int *y_pos) static void moveDock(WDock *dock, int new_x, int new_y) { WAppIcon *btn; + WDrawerChain *dc; int i; + if (dock->type == WM_DOCK) { + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) + moveDock(dc->adrawer, new_x, dc->adrawer->y_pos - dock->y_pos + new_y); + } + dock->x_pos = new_x; dock->y_pos = new_y; for (i = 0; i < dock->max_icons; i++) { @@ -2655,6 +2982,8 @@ static void swapDock(WDock *dock) else x = dock->x_pos = DOCK_EXTRA_SPACE; + swapDrawers(scr, dock->on_right_side, x); + for (i = 0; i < dock->max_icons; i++) { btn = dock->icon_array[i]; if (btn) { @@ -2723,7 +3052,7 @@ static pid_t execCommand(WAppIcon *btn, char *command, WSavedState *state) state->hidden = -1; state->miniaturized = -1; state->shaded = -1; - if (btn->dock == scr->dock || btn->omnipresent) + if (btn->dock == scr->dock || btn->dock->type == WM_DRAWER || btn->omnipresent) state->workspace = -1; else state->workspace = scr->current_workspace; @@ -2755,7 +3084,7 @@ void wDockHideIcons(WDock *dock) void wDockShowIcons(WDock *dock) { - int i, newlevel; + int i; WAppIcon *btn; if (dock == NULL) @@ -2764,15 +3093,8 @@ void wDockShowIcons(WDock *dock) btn = dock->icon_array[0]; moveDock(dock, btn->x_pos, btn->y_pos); - newlevel = dock->lowered ? WMNormalLevel : WMDockLevel; - ChangeStackingLevel(btn->icon->core, newlevel); - - for (i = 1; i < dock->max_icons; i++) { - if (dock->icon_array[i]) { - MoveInStackListAbove(dock->icon_array[i]->icon->core, btn->icon->core); - break; - } - } + /* Deleting any change in stacking level, this function is now only about + mapping icons */ if (!dock->collapsed) { for (i = 1; i < dock->max_icons; i++) { @@ -2788,7 +3110,12 @@ void wDockShowIcons(WDock *dock) void wDockLower(WDock *dock) { int i; + WDrawerChain *dc; + if (dock->type == WM_DOCK) { + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) + wDockLower(dc->adrawer); + } for (i = 0; i < dock->max_icons; i++) { if (dock->icon_array[i]) wLowerFrame(dock->icon_array[i]->icon->core); @@ -2798,11 +3125,16 @@ void wDockLower(WDock *dock) void wDockRaise(WDock *dock) { int i; + WDrawerChain *dc; for (i = dock->max_icons - 1; i >= 0; i--) { if (dock->icon_array[i]) wRaiseFrame(dock->icon_array[i]->icon->core); } + if (dock->type == WM_DOCK) { + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) + wDockRaise(dc->adrawer); + } } void wDockRaiseLower(WDock *dock) @@ -3006,12 +3338,16 @@ static void trackDeadProcess(pid_t pid, unsigned char status, WDock *dock) } } +/* This function is called when the dock switches state between + * "normal" (including auto-raise/lower) and "keep on top". It is + * therefore clearly distinct from wDockLower/Raise, which are called + * each time a not-kept-on-top dock is lowered/raised. */ static void toggleLowered(WDock *dock) { WAppIcon *tmp; + WDrawerChain *dc; int newlevel, i; - /* lower/raise Dock */ if (!dock->lowered) { newlevel = WMNormalLevel; dock->lowered = 1; @@ -3026,12 +3362,20 @@ static void toggleLowered(WDock *dock) continue; ChangeStackingLevel(tmp->icon->core, newlevel); + + /* When the dock is no longer "on top", explicitly lower it as well. + * It saves some CPU cycles (probably) to do it ourselves here + * rather than calling wDockLower at the end of toggleLowered */ if (dock->lowered) wLowerFrame(tmp->icon->core); } - if (dock->type == WM_DOCK) + if (dock->type == WM_DOCK) { + for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next) { + toggleLowered(dc->adrawer); + } wScreenUpdateUsableArea(dock->screen_ptr); + } } static void toggleCollapsed(WDock *dock) @@ -3057,36 +3401,42 @@ static void openDockMenu(WDock *dock, WAppIcon *aicon, XEvent *event) int appIsRunning = aicon->running && aicon->icon && aicon->icon->owner; if (dock->type == WM_DOCK) { - /* keep on top */ - entry = dock->menu->entries[index]; - entry->flags.indicator_on = !dock->lowered; - entry->clientdata = dock; + /* Dock position menu */ + updateDockPositionMenu(scr->dock_pos_menu, dock); dock->menu->flags.realized = 0; + if (!wPreferences.flags.nodrawer) { + /* add a drawer */ + entry = dock->menu->entries[++index]; + entry->clientdata = aicon; + wMenuSetEnabled(dock->menu, index, True); + } } else { - /* clip options */ + /* clip/drawer options */ if (scr->clip_options) updateClipOptionsMenu(scr->clip_options, dock); n_selected = numberOfSelectedIcons(dock); - /* Rename Workspace */ - entry = dock->menu->entries[++index]; - if (aicon == scr->clip_icon) { - entry->callback = renameCallback; - entry->clientdata = dock; - entry->flags.indicator = 0; - entry->text = _("Rename Workspace"); - } else { - entry->callback = omnipresentCallback; - entry->clientdata = aicon; - if (n_selected > 0) { + if (dock->type == WM_CLIP) { + /* Rename Workspace */ + entry = dock->menu->entries[++index]; + if (aicon == scr->clip_icon) { + entry->callback = renameCallback; + entry->clientdata = dock; entry->flags.indicator = 0; - entry->text = _("Toggle Omnipresent"); + entry->text = _("Rename Workspace"); } else { - entry->flags.indicator = 1; - entry->flags.indicator_on = aicon->omnipresent; - entry->flags.indicator_type = MI_CHECK; - entry->text = _("Omnipresent"); + entry->callback = omnipresentCallback; + entry->clientdata = aicon; + if (n_selected > 0) { + entry->flags.indicator = 0; + entry->text = _("Toggle Omnipresent"); + } else { + entry->flags.indicator = 1; + entry->flags.indicator_on = aicon->omnipresent; + entry->flags.indicator_type = MI_CHECK; + entry->text = _("Omnipresent"); + } } } @@ -3094,7 +3444,7 @@ static void openDockMenu(WDock *dock, WAppIcon *aicon, XEvent *event) entry = dock->menu->entries[++index]; entry->clientdata = aicon; entry->flags.indicator_on = aicon->icon->selected; - wMenuSetEnabled(dock->menu, index, aicon != scr->clip_icon); + wMenuSetEnabled(dock->menu, index, aicon != scr->clip_icon && !wIsADrawer(scr, aicon)); /* select/unselect all icons */ entry = dock->menu->entries[++index]; @@ -3116,17 +3466,19 @@ static void openDockMenu(WDock *dock, WAppIcon *aicon, XEvent *event) wMenuSetEnabled(dock->menu, index, dock->icon_count > 1); - /* this is the workspace submenu part */ - entry = dock->menu->entries[++index]; - if (n_selected > 1) - entry->text = _("Move Icons To"); - else - entry->text = _("Move Icon To"); + if (dock->type == WM_CLIP) { + /* this is the workspace submenu part */ + entry = dock->menu->entries[++index]; + if (n_selected > 1) + entry->text = _("Move Icons To"); + else + entry->text = _("Move Icon To"); - if (scr->clip_submenu) - updateWorkspaceMenu(scr->clip_submenu, aicon); + if (scr->clip_submenu) + updateWorkspaceMenu(scr->clip_submenu, aicon); - wMenuSetEnabled(dock->menu, index, !aicon->omnipresent); + wMenuSetEnabled(dock->menu, index, !aicon->omnipresent); + } /* remove icon(s) */ entry = dock->menu->entries[++index]; @@ -3181,15 +3533,23 @@ static void openDockMenu(WDock *dock, WAppIcon *aicon, XEvent *event) entry->clientdata = aicon; wMenuSetEnabled(dock->menu, index, !aicon->editing && !wPreferences.flags.noupdates); - /* kill */ + /* kill or remove drawer */ entry = dock->menu->entries[++index]; entry->clientdata = aicon; - wMenuSetEnabled(dock->menu, index, appIsRunning); + if (wIsADrawer(scr, aicon)) { + entry->callback = removeDrawerCallback; + entry->text = _("Remove drawer"); + wMenuSetEnabled(dock->menu, index, True); + } else { + entry->callback = killCallback; + entry->text = _("Kill"); + wMenuSetEnabled(dock->menu, index, appIsRunning); + } if (!dock->menu->flags.realized) wMenuRealize(dock->menu); - if (dock->type == WM_CLIP) { + if (dock->type == WM_CLIP || dock->type == WM_DRAWER) { /*x_pos = event->xbutton.x_root+2; */ x_pos = event->xbutton.x_root - dock->menu->frame->core->width / 2 - 1; if (x_pos < 0) { @@ -3242,6 +3602,8 @@ static void iconDblClick(WObjDescriptor *desc, XEvent *event) toggleCollapsed(dock); else handleClipChangeWorkspace(dock->screen_ptr, event); + } else if (wIsADrawer(dock->screen_ptr, btn)) { + toggleCollapsed(dock); } else if (btn->command) { if (!btn->launching && (!btn->running || (event->xbutton.state & ControlMask))) launchDockedApplication(btn, False); @@ -3256,7 +3618,9 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) { WScreen *scr = dock->screen_ptr; int ofs_x = event->xbutton.x, ofs_y = event->xbutton.y; - int x, y; + WIcon *icon = aicon->icon; + int x = aicon->x_pos, y = aicon->y_pos;; + int shad_x = x, shad_y = y; XEvent ev; int grabbed = 0, swapped = 0, done; Pixmap ghost = None; @@ -3267,13 +3631,39 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) GrabModeAsync, None, None, CurrentTime) != GrabSuccess) wwarning("pointer grab failed for dock move"); - y = 0; - for (x = 0; x < dock->max_icons; x++) { - if (dock->icon_array[x] != NULL && dock->icon_array[x]->yindex > y) - y = dock->icon_array[x]->yindex; + if (dock->type == WM_DRAWER) { + Window wins[2]; + wins[0] = icon->core->window; + wins[1] = scr->dock_shadow; + XRestackWindows(dpy, wins, 2); + XMoveResizeWindow(dpy, scr->dock_shadow, aicon->x_pos, aicon->y_pos, + ICON_SIZE, ICON_SIZE); + if (superfluous) { + if (icon->pixmap!=None) + ghost = MakeGhostIcon(scr, icon->pixmap); + else + ghost = MakeGhostIcon(scr, icon->core->window); + + XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); + XClearWindow(dpy, scr->dock_shadow); + } + XMapWindow(dpy, scr->dock_shadow); + } else { + int i; + WDrawerChain *dc; + /* Find out the actual height of the dock, to create its shadow */ + y = 0; + for (i = 0; i < dock->max_icons; i++) { + if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex > y) + y = dock->icon_array[i]->yindex; + } + for (dc = scr->drawers; dc; dc = dc->next) { + if ((dc->adrawer->y_pos - dock->y_pos) / ICON_SIZE > y) + y = (dc->adrawer->y_pos - dock->y_pos) / ICON_SIZE; + } + y++; + XResizeWindow(dpy, scr->dock_shadow, ICON_SIZE, ICON_SIZE * y); } - y++; - XResizeWindow(dpy, scr->dock_shadow, ICON_SIZE, ICON_SIZE * y); done = 0; while (!done) { @@ -3302,13 +3692,14 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) } break; } - if (dock->type == WM_CLIP) { + switch (dock->type) { + case WM_CLIP: x = ev.xmotion.x_root - ofs_x; y = ev.xmotion.y_root - ofs_y; wScreenKeepInside(scr, &x, &y, ICON_SIZE, ICON_SIZE); - moveDock(dock, x, y); - } else { + break; + case WM_DOCK: /* move vertically if pointer is inside the dock */ if ((dock->on_right_side && ev.xmotion.x_root >= dock->x_pos - ICON_SIZE) || (!dock->on_right_side && ev.xmotion.x_root <= dock->x_pos + ICON_SIZE * 2)) { @@ -3364,6 +3755,23 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) } } } + break; + case WM_DRAWER: + { + WDock *real_dock = dock->screen_ptr->dock; + Bool snapped; + int ix, iy; + x = ev.xmotion.x_root - ofs_x; + y = ev.xmotion.y_root - ofs_y; + snapped = wDockSnapIcon(real_dock, aicon, x, y, &ix, &iy, True); + if (snapped) { + shad_x = real_dock->x_pos + ix * wPreferences.icon_size; + shad_y = real_dock->y_pos + iy * wPreferences.icon_size; + XMoveWindow(dpy, scr->dock_shadow, shad_x, shad_y); + } + moveDock(dock, x, y); + break; + } } break; @@ -3374,7 +3782,26 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) if (ev.xbutton.button != event->xbutton.button) break; XUngrabPointer(dpy, CurrentTime); - XUnmapWindow(dpy, scr->dock_shadow); + if (dock->type == WM_DRAWER) { + int i; + Window *wins[dock->icon_count]; + WAppIcon *aicon; + + for (i = 0; i < dock->max_icons; i++) { + if ((aicon = dock->icon_array[i]) == NULL) + continue; + wins[ aicon->xindex + (dock->on_right_side ? dock->icon_count - 1 : 0) ] = &aicon->icon->core->window; + } + SlideWindows(wins, dock->icon_count, + (dock->on_right_side ? x - (dock->icon_count - 1) * ICON_SIZE : x), + y, + (dock->on_right_side ? shad_x - (dock->icon_count - 1) * ICON_SIZE : shad_x), + shad_y); + XUnmapWindow(dpy, scr->dock_shadow); + moveDock(dock, shad_x, shad_y); + } else { + XUnmapWindow(dpy, scr->dock_shadow); + } XResizeWindow(dpy, scr->dock_shadow, ICON_SIZE, ICON_SIZE); if (dock->type == WM_DOCK) { if (swapped != 0) { @@ -3566,7 +3993,7 @@ static void iconMouseDown(WObjDescriptor *desc, XEvent *event) static void clipEnterNotify(WObjDescriptor *desc, XEvent *event) { WAppIcon *btn = (WAppIcon *) desc->parent; - WDock *dock; + WDock *dock, *tmp; WScreen *scr; assert(event->type == EnterNotify); @@ -3577,16 +4004,20 @@ static void clipEnterNotify(WObjDescriptor *desc, XEvent *event) scr = btn->icon->core->screen_ptr; dock = btn->dock; - if (!dock || dock->type != WM_CLIP) + if (dock == NULL) return; /* The auto raise/lower code */ - if (dock->auto_lower_magic) { - WMDeleteTimerHandler(dock->auto_lower_magic); - dock->auto_lower_magic = NULL; + tmp = (dock->type == WM_DRAWER ? scr->dock : dock); + if (tmp->auto_lower_magic) { + WMDeleteTimerHandler(tmp->auto_lower_magic); + tmp->auto_lower_magic = NULL; } - if (dock->auto_raise_lower && !dock->auto_raise_magic) - dock->auto_raise_magic = WMAddTimerHandler(wPreferences.clip_auto_raise_delay, clipAutoRaise, (void *)dock); + if (tmp->auto_raise_lower && !tmp->auto_raise_magic) + tmp->auto_raise_magic = WMAddTimerHandler(wPreferences.clip_auto_raise_delay, clipAutoRaise, (void *) tmp); + + if (dock->type != WM_CLIP && dock->type != WM_DRAWER) + return; /* The auto expand/collapse code */ if (dock->auto_collapse_magic) { @@ -3601,16 +4032,17 @@ static void clipLeave(WDock *dock) { XEvent event; WObjDescriptor *desc = NULL; + WDock *tmp; - if (!dock || dock->type != WM_CLIP) + if (dock == NULL) return; if (XCheckTypedEvent(dpy, EnterNotify, &event) != False) { if (XFindContext(dpy, event.xcrossing.window, wWinContext, (XPointer *) & desc) != XCNOENT && desc && desc->parent_type == WCLASS_DOCK_ICON - && ((WAppIcon *) desc->parent)->dock && ((WAppIcon *) desc->parent)->dock->type == WM_CLIP) { - /* We didn't left the Clip yet */ + && ((WAppIcon *) desc->parent)->dock == dock) { + /* We haven't left the dock/clip/drawer yet */ XPutBackEvent(dpy, &event); return; } @@ -3621,12 +4053,16 @@ static void clipLeave(WDock *dock) return; } - if (dock->auto_raise_magic) { - WMDeleteTimerHandler(dock->auto_raise_magic); - dock->auto_raise_magic = NULL; + tmp = (dock->type == WM_DRAWER ? dock->screen_ptr->dock : dock); + if (tmp->auto_raise_magic) { + WMDeleteTimerHandler(tmp->auto_raise_magic); + tmp->auto_raise_magic = NULL; } - if (dock->auto_raise_lower && !dock->auto_lower_magic) - dock->auto_lower_magic = WMAddTimerHandler(wPreferences.clip_auto_lower_delay, clipAutoLower, (void *)dock); + if (tmp->auto_raise_lower && !tmp->auto_lower_magic) + tmp->auto_lower_magic = WMAddTimerHandler(wPreferences.clip_auto_lower_delay, clipAutoLower, (void *)tmp); + + if (dock->type != WM_CLIP && dock->type != WM_DRAWER) + return; if (dock->auto_expand_magic) { WMDeleteTimerHandler(dock->auto_expand_magic); @@ -3652,7 +4088,7 @@ static void clipAutoCollapse(void *cdata) { WDock *dock = (WDock *) cdata; - if (dock->type != WM_CLIP) + if (dock->type != WM_CLIP && dock->type != WM_DRAWER) return; if (dock->auto_collapse) { @@ -3666,7 +4102,7 @@ static void clipAutoExpand(void *cdata) { WDock *dock = (WDock *) cdata; - if (dock->type != WM_CLIP) + if (dock->type != WM_CLIP && dock->type != WM_DRAWER) return; if (dock->auto_collapse) { @@ -3680,9 +4116,6 @@ static void clipAutoLower(void *cdata) { WDock *dock = (WDock *) cdata; - if (dock->type != WM_CLIP) - return; - if (dock->auto_raise_lower) wDockLower(dock); @@ -3693,9 +4126,6 @@ static void clipAutoRaise(void *cdata) { WDock *dock = (WDock *) cdata; - if (dock->type != WM_CLIP) - return; - if (dock->auto_raise_lower) wDockRaise(dock); @@ -3778,3 +4208,694 @@ int wClipMakeIconOmnipresent(WAppIcon *aicon, int omnipresent) return status; } + +static void drawerAppendToChain(WScreen *scr, WDock *drawer) +{ + WDrawerChain **where_to_add; + + where_to_add = &scr->drawers; + while ((*where_to_add) != NULL) { + where_to_add = &(*where_to_add)->next; + } + + *where_to_add = wmalloc(sizeof(WDrawerChain)); + (*where_to_add)->adrawer = drawer; + (*where_to_add)->next = NULL; + scr->drawer_count++; +} + + +static void drawerRemoveFromChain(WScreen *scr, WDock *drawer) +{ + WDrawerChain *next, **to_remove; + + to_remove = &scr->drawers; + while (True) { + if (*to_remove == NULL) { + wwarning("The drawer to be removed can not be found."); + return; + } + if ((*to_remove)->adrawer == drawer) + break; + + to_remove = &(*to_remove)->next; + } + next = (*to_remove)->next; + wfree(*to_remove); + *to_remove = next; + scr->drawer_count--; +} + + +/* Don't free the returned string. Duplicate it. */ +static char * findUniqueName(WScreen *scr, char *instance_basename) +{ + static char buffer[128]; + WDrawerChain *dc; + int i; + Bool already_in_use = True; + +#define UNIQUE_NAME_WATCHDOG 128 + for (i = 0; already_in_use && i < UNIQUE_NAME_WATCHDOG; i++) { + snprintf(buffer, sizeof buffer, "%s%d", instance_basename, i); + + already_in_use = False; + + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + if (!strncmp(dc->adrawer->icon_array[0]->wm_instance, buffer, + sizeof buffer)) { + already_in_use = True; + break; + } + } + } + + if (i == UNIQUE_NAME_WATCHDOG) + wwarning("Couldn't find a unique name for drawer in %d attemps.", i); +#undef UNIQUE_NAME_WATCHDOG + + return buffer; +} + + +static void drawerIconExpose(WObjDescriptor *desc, XEvent *event) +{ + wDrawerIconPaint((WAppIcon *) desc->parent); +} + + +static int addADrawer(WScreen *scr) +{ + int i, y; + WDock *drawer, *dock = scr->dock; + WDrawerChain *dc; + char can_be_here[dock->max_icons]; + + if (dock->icon_count + scr->drawer_count >= dock->max_icons) + return -1; + + for (y = 0; y < dock->max_icons; y++) { + can_be_here[y] = True; + } + for (i = 0; i < dock->max_icons; i++) { + if (dock->icon_array[i] != NULL) + can_be_here[dock->icon_array[i]->yindex] = False; + } + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + y = (int) ((dc->adrawer->y_pos - dock->y_pos) / ICON_SIZE); + can_be_here[y] = False; + } + + for (y = 0; y < dock->max_icons; y++) { + if (can_be_here[y]) + break; + } + + drawer = wDockCreate(scr, WM_DRAWER, NULL); + drawer->lowered = scr->dock->lowered; + drawer->auto_raise_lower = scr->dock->auto_raise_lower; + drawer->x_pos = dock->x_pos; + drawer->y_pos = dock->y_pos + ICON_SIZE * y; + drawer->icon_array[0]->xindex = 0; + drawer->icon_array[0]->yindex = 0; + drawer->icon_array[0]->x_pos = drawer->x_pos; + drawer->icon_array[0]->y_pos = drawer->y_pos; + XMoveWindow(dpy, drawer->icon_array[0]->icon->core->window, + drawer->icon_array[0]->x_pos, drawer->icon_array[0]->y_pos); + + return 0; +} + + +static void addADrawerCallback(WMenu *menu, WMenuEntry *entry) +{ + assert(entry->clientdata!=NULL); + addADrawer(((WAppIcon *) entry->clientdata)->dock->screen_ptr); +} + + +static void drawerDestroy(WDock *drawer) +{ + WScreen *scr; + int i; + WAppIcon *aicon; + WMArray *icons; + + if (drawer == NULL) + return; + + scr = drawer->screen_ptr; + + /* Note regarding menus: we can't delete any dock/clip/drawer menu, because + * that would (attempt to) wfree some memory in gettext library (see menu + * entries that have several "versions", such like "Hide" and "Unhide"). */ + + wDefaultPurgeInfo(scr, drawer->icon_array[0]->wm_instance, + drawer->icon_array[0]->wm_class); + icons = WMCreateArray(drawer->icon_count - 1); + for (i = 1; i < drawer->max_icons; i++) { + if (!(aicon = drawer->icon_array[i])) + continue; + WMAddToArray(icons, aicon); + } + removeIcons(icons, drawer); + + if (drawer->auto_collapse_magic) { + WMDeleteTimerHandler(drawer->auto_collapse_magic); + drawer->auto_collapse_magic = NULL; + } + if (drawer->auto_lower_magic) { + WMDeleteTimerHandler(drawer->auto_lower_magic); + drawer->auto_lower_magic = NULL; + } + + wAppIconDestroy(drawer->icon_array[0]); + wfree(drawer->icon_array); + wfree(drawer); + + drawerRemoveFromChain(scr, drawer); + if (scr->last_dock == drawer) + scr->last_dock = NULL; + if (scr->attracting_drawer == drawer) + scr->attracting_drawer = NULL; +} + + +static void removeDrawerCallback(WMenu *menu, WMenuEntry *entry) +{ + WDock *dock = ((WAppIcon*)entry->clientdata)->dock; + assert(dock != NULL); + + if (dock->icon_count > 1) { + if (wMessageDialog(dock->screen_ptr, _("Drawer"), + _("All icons in this drawer will be detached!"), + _("OK"), _("Cancel"), NULL) != WAPRDefault) + return; + } + drawerDestroy(dock); +} + + +void wDrawerIconPaint(WAppIcon *dicon) +{ + Window win = dicon->icon->core->window; + WScreen *scr = dicon->icon->core->screen_ptr; + XPoint p[4]; + GC gc = scr->draw_gc; + WMColor *color; + + wIconPaint(dicon->icon); + + if (!dicon->dock->collapsed) + color = scr->clip_title_color[CLIP_NORMAL]; + else + color = scr->clip_title_color[CLIP_COLLAPSED]; + XSetForeground(dpy, gc, WMColorPixel(color)); + + if (dicon->dock->on_right_side) { + p[0].x = p[3].x = 10; + p[0].y = p[3].y = ICON_SIZE / 2 - 5; + p[1].x = 10; + p[1].y = ICON_SIZE / 2 + 5; + p[2].x = 5; + p[2].y = ICON_SIZE / 2; + } + else { + p[0].x = p[3].x = ICON_SIZE-1 - 10; + p[0].y = p[3].y = ICON_SIZE / 2 - 5; + p[1].x = ICON_SIZE-1 - 10; + p[1].y = ICON_SIZE / 2 + 5; + p[2].x = ICON_SIZE-1 - 5; + p[2].y = ICON_SIZE / 2; + } + XFillPolygon(dpy, win, gc, p,3,Convex,CoordModeOrigin); + XDrawLines(dpy, win, gc, p,4,CoordModeOrigin); +} + + +RImage* wDrawerMakeTile(WScreen *scr, RImage *normalTile) +{ + RImage *tile = RCloneImage(normalTile); + RColor dark; + RColor light; + + dark.alpha = 0; + dark.red = dark.green = dark.blue = 60; + + light.alpha = 0; + light.red = light.green = light.blue = 80; + + /* arrow bevel */ + if (!scr->dock || scr->dock->on_right_side) { + ROperateLine(tile, RSubtractOperation, 11, ICON_SIZE / 2 - 7, + 4, ICON_SIZE / 2, &dark); /* / */ + ROperateLine(tile, RSubtractOperation, 11, ICON_SIZE / 2 + 7, + 4, ICON_SIZE / 2, &dark); /* \ */ + ROperateLine(tile, RAddOperation, 11, ICON_SIZE / 2 - 7, + 11, ICON_SIZE / 2 + 7, &light); /* | */ + } + else { + ROperateLine(tile, RSubtractOperation, ICON_SIZE-1 - 11, ICON_SIZE / 2 - 7, + ICON_SIZE-1 - 4, ICON_SIZE / 2, &dark); /* \ */ + ROperateLine(tile, RAddOperation, ICON_SIZE-1 - 11, ICON_SIZE / 2 + 7, + ICON_SIZE-1 - 4, ICON_SIZE / 2, &light); /* / */ + ROperateLine(tile, RSubtractOperation, ICON_SIZE-1 - 11, ICON_SIZE / 2 - 7, + ICON_SIZE-1 - 11, ICON_SIZE / 2 + 7, &dark); /* | */ + } + return tile; +} + + +static void swapDrawer(WDock *drawer, int new_x) +{ + int i; + + drawer->on_right_side = !drawer->on_right_side; + drawer->x_pos = new_x; + + for (i = 0; i < drawer->max_icons; i++) { + WAppIcon *ai; + if ((ai = drawer->icon_array[i]) == NULL) + continue; + ai->xindex *= -1; /* so A B C becomes C B A */ + ai->x_pos = new_x + ai->xindex * ICON_SIZE; + + /* Update drawer's tile */ + if (i == 0) { + wIconUpdate(ai->icon, NULL); + wDrawerIconPaint(ai); + } + XMoveWindow(dpy, ai->icon->core->window, ai->x_pos, ai->y_pos); + } +} + + +static void swapDrawers(WScreen *scr, int on_right_side, int new_x) +{ + WDrawerChain *dc; + + if (scr->drawer_tile) { + RReleaseImage(scr->drawer_tile); + } + scr->drawer_tile = wDrawerMakeTile(scr, scr->icon_tile); + + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + swapDrawer(dc->adrawer, new_x); + assert(dc->adrawer->on_right_side == on_right_side); + } +} + + +int wIsADrawer(WScreen *scr, WAppIcon *aicon) +{ + return aicon && aicon->dock && + aicon->dock->type == WM_DRAWER && aicon->dock->icon_array[0] == aicon; +} + + +static WDock* getDrawer(WScreen *scr, int y_index) +{ + WDrawerChain *dc; + + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + if (dc->adrawer->y_pos - scr->dock->y_pos == y_index * ICON_SIZE) + return dc->adrawer; + } + return NULL; +} + + + +/* Find the "hole" a moving appicon created when snapped into the + * drawer. redocking is a boolean. If the moving appicon comes from the + * drawer, drawer->icon_count is correct. If not, redocking is then false and + * there are now drawer->icon_count plus one appicons in the drawer. */ +static int indexOfHole(WDock *drawer, WAppIcon *moving_aicon, int redocking) +{ + int index_of_hole, i; + + /* Classic interview question... + * + * We have n-1 (n = drawer->icon_count-1 or drawer->icon_count, see + * redocking) appicons, whose xindex are unique in [1..n]. One is missing: + * that's where the ghost of the moving appicon is, that's what the + * function should return. + * + * We compute 1+2+...+n (this sum is equal to n*(n+1)/2), we substract to + * this sum the xindex of each of the n-1 appicons, and we get the correct + * index! */ + + if (redocking) { + index_of_hole = (drawer->icon_count - 1) * drawer->icon_count / 2; + } else { + index_of_hole = drawer->icon_count * (drawer->icon_count + 1) / 2; + } + index_of_hole *= (drawer->on_right_side ? -1 : 1); + + for (i = 1; i < drawer->max_icons; i++) { + if (drawer->icon_array[i] && drawer->icon_array[i] != moving_aicon) + index_of_hole -= drawer->icon_array[i]->xindex; + } + /* wmessage(" Index of the moving appicon is %d (%sredocking)", index_of_hole, (redocking ? "" : "not ")); */ + if (abs(index_of_hole) > abs(drawer->icon_count) - (redocking ? 1 : 0)) + wwarning(" index_of_hole is too large ! (%d greater than %d)", + index_of_hole, abs(drawer->icon_count) - (redocking ? 1 : 0)); + if (index_of_hole == 0) + wwarning(" index_of_hole == 0 (%sredocking, icon_count == %d)", (redocking ? "" : "not "), drawer->icon_count); + + return index_of_hole; +} + + +void wSlideAppicons(WAppIcon **appicons, int n, int to_the_left) +{ + int i; + int leftmost = -1, min_index = 9999, from_x = -1; // leftmost and from_x initialized to avoid warning + Window *wins[n]; + WAppIcon *aicon; + + if (n < 1) + return; + + for (i = 0; i < n; i++) { + aicon = appicons[i]; + aicon->xindex += (to_the_left ? -1 : +1); + if (aicon->xindex < min_index) { + min_index = aicon->xindex; + leftmost = i; + from_x = aicon->x_pos; + } + aicon->x_pos += (to_the_left ? -ICON_SIZE : +ICON_SIZE); + } + + for (i = 0; i < n; i++) { + aicon = appicons[i]; + wins[aicon->xindex - min_index] = &aicon->icon->core->window; + } + aicon = appicons[leftmost]; + SlideWindows(wins, n, from_x, aicon->y_pos, aicon->x_pos, aicon->y_pos); +} + + +void wDrawerFillTheGap(WDock *drawer, WAppIcon *aicon, Bool redocking) +{ + int i, j; + int index_of_hole = indexOfHole(drawer, aicon, redocking); + WAppIcon *aicons_to_shift[drawer->icon_count]; + + j = 0; + for (i = 0; i < drawer->max_icons; i++) { + WAppIcon *ai = drawer->icon_array[i]; + if (ai && ai != aicon && + abs(ai->xindex) > abs(index_of_hole)) + aicons_to_shift[j++] = ai; + } + if (j != drawer->icon_count - abs(index_of_hole) - (redocking ? 1 : 0)) + wwarning("Removing aicon at index %d from %s: j=%d but should be %d", + index_of_hole, drawer->icon_array[0]->wm_instance, + j, drawer->icon_count - abs(index_of_hole) - (redocking ? 1 : 0)); + wSlideAppicons(aicons_to_shift, j, !drawer->on_right_side); +} + + +static void drawerConsolidateIcons(WDock *drawer) +{ + WAppIcon *aicons_to_shift[drawer->icon_count]; + int maxRemaining = 0; + int sum = 0; + int i; + for (i = 0; i < drawer->max_icons; i++) { + WAppIcon *ai = drawer->icon_array[i]; + if (ai == NULL) + continue; + sum += abs(ai->xindex); + if (abs(ai->xindex) > maxRemaining) + maxRemaining = abs(ai->xindex); + } + while (sum != maxRemaining * (maxRemaining + 1) / 2) { // while there is a hole + WAppIcon *ai; + int n; + // Look up for the hole at max position + int maxDeleted; + for (maxDeleted = maxRemaining - 1; maxDeleted > 0; maxDeleted--) { + Bool foundAppIconThere = False; + for (i = 0; i < drawer->max_icons; i++) { + WAppIcon *ai = drawer->icon_array[i]; + if (ai == NULL) + continue; + if (abs(ai->xindex) == maxDeleted) { + foundAppIconThere = True; + break; + } + } + if (!foundAppIconThere) + break; + } + assert(maxDeleted > 0); // would mean while test is wrong + n = 0; + for (i = 0; i < drawer->max_icons; i++) { + ai = drawer->icon_array[i]; + if (ai != NULL && abs(ai->xindex) > maxDeleted) + aicons_to_shift[n++] = ai; + } + assert(n == maxRemaining - maxDeleted); // for the code review ;-) + wSlideAppicons(aicons_to_shift, n, !drawer->on_right_side); + // Efficient beancounting + maxRemaining -= 1; + sum -= n; + } +} + + + +/* similar to wDockRestoreState, but a lot a specific stuff too... */ +static WDock * drawerRestoreState(WScreen *scr, WMPropList *drawer_state) +{ + WDock *drawer; + WMPropList *apps, *value, *dock_state; + WAppIcon *aicon; + int count, i; + + if (!drawer_state) + return NULL; + + make_keys(); + + WMRetainPropList(drawer_state); + + /* Get the instance name, and create a drawer */ + value = WMGetFromPLDictionary(drawer_state, dName); + drawer = wDockCreate(scr, WM_DRAWER, WMGetFromPLString(value)); + + /* restore DnD command and paste command */ +#ifdef XDND + value = WMGetFromPLDictionary(drawer_state, dDropCommand); + if (value && WMIsPLString(value)) + drawer->icon_array[0]->dnd_command = wstrdup(WMGetFromPLString(value)); +#endif /* XDND */ + + value = WMGetFromPLDictionary(drawer_state, dPasteCommand); + if (value && WMIsPLString(value)) + drawer->icon_array[0]->paste_command = wstrdup(WMGetFromPLString(value)); + + /* restore position */ + value = WMGetFromPLDictionary(drawer_state, dPosition); + if (!value || !WMIsPLString(value)) + COMPLAIN("Position"); + else { + int x, y, y_index; + if (sscanf(WMGetFromPLString(value), "%i,%i", &x, &y) != 2) + COMPLAIN("Position"); + + /* check position sanity */ + if (x != scr->dock->x_pos) { + x = scr->dock->x_pos; + } + y_index = (y - scr->dock->y_pos) / ICON_SIZE; + if (y_index <= 0) { + y_index = 1; + } + if (y_index >= scr->dock->max_icons) { + /* Here we should do something more intelligent, since it + * can happen even if the user hasn't hand-edited his + * G/D/State file (but uses a lower resolution). */ + y_index = scr->dock->max_icons - 1; + } + y = scr->dock->y_pos + y_index * ICON_SIZE; + moveDock(drawer, x, y); + } + + /* restore dock properties (applist and others) */ + dock_state = WMGetFromPLDictionary(drawer_state, dDock); + + /* restore lowered/raised state: same as scr->dock, no matter what */ + drawer->lowered = scr->dock->lowered; + if (!drawer->lowered) + ChangeStackingLevel(drawer->icon_array[0]->icon->core, WMDockLevel); + else + ChangeStackingLevel(drawer->icon_array[0]->icon->core, WMNormalLevel); + wRaiseFrame(drawer->icon_array[0]->icon->core); + + /* restore collapsed state */ + drawer->collapsed = 0; + value = WMGetFromPLDictionary(dock_state, dCollapsed); + if (value && strcasecmp(WMGetFromPLString(value), "YES") == 0) { + drawer->collapsed = 1; + } + /* restore auto-collapsed state */ + value = WMGetFromPLDictionary(dock_state, dAutoCollapse); + if (value && strcasecmp(WMGetFromPLString(value), "YES") == 0) { + drawer->auto_collapse = 1; + drawer->collapsed = 1; + } else { + drawer->auto_collapse = 0; // because wDockCreate sets it (drawers only) + } + + /* restore auto-raise/lower state: same as scr->dock, no matter what */ + drawer->auto_raise_lower = scr->dock->auto_raise_lower; + + /* restore attract icons state */ + drawer->attract_icons = 0; + value = WMGetFromPLDictionary(dock_state, dAutoAttractIcons); + if (value && strcasecmp(WMGetFromPLString(value), "YES") == 0) { + drawer->attract_icons = 1; + scr->attracting_drawer = drawer; + } + + /* application list */ + apps = WMGetFromPLDictionary(dock_state, dApplications); + + if (!apps) { + goto finish; + } + + count = WMGetPropListItemCount(apps); + + if (count == 0) + goto finish; + + for (i=0; iicon_count >= drawer->max_icons) { + wwarning(_("there are too many icons stored in drawer. Ignoring what doesn't fit")); + break; + } + + value = WMGetFromPLArray(apps, i); + aicon = restore_icon_state(scr, value, WM_DRAWER, drawer->icon_count); + + drawer->icon_array[drawer->icon_count] = aicon; + + if (aicon) { + aicon->dock = drawer; + aicon->x_pos = drawer->x_pos + (aicon->xindex * ICON_SIZE); + aicon->y_pos = drawer->y_pos + (aicon->yindex * ICON_SIZE); + + if (!drawer->lowered) + ChangeStackingLevel(aicon->icon->core, WMDockLevel); + else + ChangeStackingLevel(aicon->icon->core, WMNormalLevel); + + wCoreConfigure(aicon->icon->core, aicon->x_pos, aicon->y_pos, 0, 0); + + if (!drawer->collapsed) + XMapWindow(dpy, aicon->icon->core->window); + wRaiseFrame(aicon->icon->core); + + drawer->icon_count++; + } + } + +finish: + WMReleasePropList(drawer_state); + + return drawer; +} + + +/* Same kind of comment than for previous function: this function is + * very similar to make_icon_state, but has substential differences as + * well. */ +static WMPropList *drawerSaveState(WScreen *scr, WDock *drawer) +{ + WMPropList *pstr, *drawer_state; + WAppIcon *ai; + char buffer[64]; + + ai = drawer->icon_array[0]; + /* Store its name */ + pstr = WMCreatePLString(ai->wm_instance); + drawer_state = WMCreatePLDictionary(dName, pstr, NULL); /* we need this final NULL */ + WMReleasePropList(pstr); + + /* Store its position */ + snprintf(buffer, sizeof(buffer), "%hi,%hi", ai->x_pos, ai->y_pos); + pstr = WMCreatePLString(buffer); + WMPutInPLDictionary(drawer_state, dPosition, pstr); + WMReleasePropList(pstr); + +#ifdef XDND + /* Store its DnD command */ + if (ai->dnd_command) { + pstr = WMCreatePLString(ai->dnd_command); + WMPutInPLDictionary(drawer_state, dDropCommand, pstr); + WMReleasePropList(pstr); + } +#endif /* XDND */ + + /* Store its paste command */ + if (ai->paste_command) { + pstr = WMCreatePLString(ai->paste_command); + WMPutInPLDictionary(drawer_state, dPasteCommand, pstr); + WMReleasePropList(pstr); + } + + /* Store applications list and other properties */ + pstr = dockSaveState(drawer); + WMPutInPLDictionary(drawer_state, dDock, pstr); + WMReleasePropList(pstr); + + return drawer_state; +} + + +void wDrawersSaveState(WScreen *scr) +{ + WMPropList *all_drawers, *drawer_state; + int i; + WDrawerChain *dc; + + make_keys(); + + all_drawers = WMCreatePLArray(NULL); + for (i=0, dc = scr->drawers; + i < scr->drawer_count; + i++, dc = dc->next) { + drawer_state = drawerSaveState(scr, dc->adrawer); + WMAddToPLArray(all_drawers, drawer_state); + WMReleasePropList(drawer_state); + } + WMPutInPLDictionary(scr->session_state, dDrawers, all_drawers); + WMReleasePropList(all_drawers); +} + + +void wDrawersRestoreState(WScreen *scr) +{ + WMPropList *all_drawers, *drawer_state; + int i; + + make_keys(); + + if (scr->session_state == NULL) + return; + + all_drawers = WMGetFromPLDictionary(scr->session_state, dDrawers); + if (!all_drawers) + return; + + for (i = 0; i < WMGetPropListItemCount(all_drawers); i++) { + drawer_state = WMGetFromPLArray(all_drawers, i); + drawerRestoreState(scr, drawer_state); + // Note: scr->drawers was updated when the the drawer was created + } +} diff --git a/src/dock.h b/src/dock.h index 8cc68429..2c6c4bc4 100644 --- a/src/dock.h +++ b/src/dock.h @@ -39,6 +39,7 @@ typedef struct WDock { #define WM_DOCK 0 #define WM_CLIP 1 +#define WM_DRAWER 2 int type; WMagicNumber auto_expand_magic; @@ -66,7 +67,7 @@ typedef struct WDock { -WDock *wDockCreate(WScreen *scr, int type); +WDock *wDockCreate(WScreen *scr, int type, char *name); WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type); void wDockDestroy(WDock *dock); @@ -85,6 +86,9 @@ void wDockDetach(WDock *dock, WAppIcon *icon); Bool wDockMoveIconBetweenDocks(WDock *src, WDock *dest, WAppIcon *icon, int x, int y); void wDockReattachIcon(WDock *dock, WAppIcon *icon, int x, int y); +void wSlideAppicons(WAppIcon **appicons, int n, int to_the_left); +void wDrawerFillTheGap(WDock *drawer, WAppIcon *aicon, Bool redocking); + void wDockFinishLaunch(WDock *dock, WAppIcon *icon); void wDockTrackWindowLaunch(WDock *dock, Window window); WAppIcon *wDockFindIconForWindow(WDock *dock, Window window); @@ -100,14 +104,27 @@ void wClipSaveState(WScreen *scr); WMPropList *wClipSaveWorkspaceState(WScreen *scr, int workspace); WAppIcon *wClipRestoreState(WScreen *scr, WMPropList *clip_state); +void wDrawerIconPaint(WAppIcon *dicon); +void wDrawersSaveState(WScreen *scr); +void wDrawersRestoreState(WScreen *scr); +int wIsADrawer(WScreen *scr, WAppIcon *aicon); + void wClipUpdateForWorkspaceChange(WScreen *scr, int workspace); RImage *wClipMakeTile(WScreen *scr, RImage *normalTile); +RImage* wDrawerMakeTile(WScreen *scr, RImage *normalTile); #define WO_FAILED 0 #define WO_NOT_APPLICABLE 1 #define WO_SUCCESS 2 +typedef enum +{ + P_NORMAL = 0, + P_AUTO_RAISE_LOWER, + P_KEEP_ON_TOP, +} dockPosition; + int wClipMakeIconOmnipresent(WAppIcon *aicon, int omnipresent); #endif diff --git a/src/dockedapp.c b/src/dockedapp.c index 6c6d1f05..d7fc7b7c 100644 --- a/src/dockedapp.c +++ b/src/dockedapp.c @@ -177,8 +177,11 @@ static void panelBtnCallback(WMWidget * self, void *data) } else { WAppIcon *aicon = panel->editedIcon; + // Cf dock.c:dockIconPaint(WAppIcon *aicon)? if (aicon == aicon->icon->core->screen_ptr->clip_icon) wClipIconPaint(aicon); + else if (wIsADrawer(aicon->icon->core->screen_ptr, aicon)) + wDrawerIconPaint(aicon); else wAppIconPaint(aicon); diff --git a/src/icon.c b/src/icon.c index 2c9b27d9..f9ebd04a 100644 --- a/src/icon.c +++ b/src/icon.c @@ -248,11 +248,21 @@ static void icon_update_pixmap(WIcon *icon, RImage *image) WScreen *scr = icon->core->screen_ptr; int titled = icon->show_title; - if (icon->tile_type == TILE_NORMAL) { + switch (icon->tile_type) { + case TILE_NORMAL: tile = RCloneImage(scr->icon_tile); - } else { + break; + default: + wwarning("Unknown tileType: %d.\n", icon->tile_type); + // fallthrough to TILE_CLIP (emulate previous behaviour) + case TILE_CLIP: assert(scr->clip_tile); tile = RCloneImage(scr->clip_tile); + break; + case TILE_DRAWER: + assert(scr->drawer_tile); + tile = RCloneImage(scr->drawer_tile); + break; } if (image) { diff --git a/src/icon.h b/src/icon.h index 4e030a87..f0c76c65 100644 --- a/src/icon.h +++ b/src/icon.h @@ -28,6 +28,7 @@ #define TILE_NORMAL 0 #define TILE_CLIP 1 +#define TILE_DRAWER 2 typedef struct WIcon { WCoreWindow *core; diff --git a/src/main.c b/src/main.c index f63b1a6e..4559f868 100644 --- a/src/main.c +++ b/src/main.c @@ -686,8 +686,11 @@ static int real_main(int argc, char **argv) wPreferences.flags.norestore = 1; } else if (strcmp(argv[i], "-nodock") == 0 || strcmp(argv[i], "--no-dock") == 0) { wPreferences.flags.nodock = 1; + wPreferences.flags.nodrawer = 1; } else if (strcmp(argv[i], "-noclip") == 0 || strcmp(argv[i], "--no-clip") == 0) { wPreferences.flags.noclip = 1; + } else if (strcmp(argv[i], "-nodrawer") == 0 || strcmp(argv[i], "--no-drawer") == 0) { + wPreferences.flags.nodrawer = 1; } else if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "--version") == 0) { printf("Window Maker %s\n", VERSION); exit(0); diff --git a/src/screen.c b/src/screen.c index bc8f3faa..8d1c46c6 100644 --- a/src/screen.c +++ b/src/screen.c @@ -94,6 +94,7 @@ static WMPropList *dApplications = NULL; static WMPropList *dWorkspace; static WMPropList *dDock; static WMPropList *dClip; +static WMPropList *dDrawers = NULL; static void make_keys(void) { @@ -104,6 +105,7 @@ static void make_keys(void) dWorkspace = WMCreatePLString("Workspace"); dDock = WMCreatePLString("Dock"); dClip = WMCreatePLString("Clip"); + dDrawers = WMCreatePLString("Drawers"); } /* @@ -863,6 +865,10 @@ void wScreenRestoreState(WScreen * scr) state = WMGetFromPLDictionary(scr->session_state, dClip); scr->clip_icon = wClipRestoreState(scr, state); } + + if (!wPreferences.flags.nodrawer) { + wDrawersRestoreState(scr); + } wWorkspaceRestoreState(scr); @@ -910,6 +916,15 @@ void wScreenSaveState(WScreen * scr) wWorkspaceSaveState(scr, old_state); + if (!wPreferences.flags.nodrawer) { + wDrawersSaveState(scr); + } else { + if ((foo = WMGetFromPLDictionary(old_state, dDrawers)) != NULL) { + WMPutInPLDictionary(scr->session_state, dDrawers, foo); + } + } + + if (wPreferences.save_session_on_exit) { wSessionSaveState(scr); } else { diff --git a/src/screen.h b/src/screen.h index 52a0c42e..66af6d70 100644 --- a/src/screen.h +++ b/src/screen.h @@ -62,6 +62,12 @@ typedef struct WAppIconChain { } WAppIconChain; +/* Drawers, which are docks, really */ +typedef struct WDrawerChain { + struct WDock *adrawer; + struct WDrawerChain *next; +} WDrawerChain; + /* * each WScreen is saved into a context associated with it's root window */ @@ -213,6 +219,7 @@ typedef struct _WScreen { struct WMenu *workspace_submenu; /* workspace list for window_menu */ struct WDock *dock; /* the application dock */ + struct WMenu *dock_pos_menu; /* Dock position menu */ struct WPixmap *dock_dots; /* 3 dots for the Dock */ Window dock_shadow; /* shadow for dock buttons */ struct WAppIcon *clip_icon; /* The clip main icon */ @@ -220,9 +227,14 @@ typedef struct _WScreen { struct WMenu *clip_submenu; /* Workspace list for clips */ struct WMenu *clip_options; /* Options for Clip */ struct WMenu *clip_ws_menu; /* workspace menu for clip */ + struct WMenu *drawer_menu; /* Menu for drawers */ struct WDock *last_dock; WAppIconChain *global_icons; /* for omnipresent icons chain in clip */ int global_icon_count; /* How many global icons do we have */ + WDrawerChain *drawers; /* Chain of drawers */ + /* Cache the following two informations, as they are used quite a lot */ + int drawer_count; /* Nb of drawers that */ + struct WDock *attracting_drawer; /* The drawer that auto-attracts icons, or NULL */ Window clip_balloon; /* window for workspace name */ @@ -233,7 +245,7 @@ typedef struct _WScreen { struct RImage *icon_tile; struct RImage *clip_tile; - + struct RImage *drawer_tile; /* tile for a drawer (tile + arrow) */ Pixmap icon_tile_pixmap; /* For app supplied icons */ struct RImage *def_icon_rimage; /* Default RImage icon */ diff --git a/src/session.c b/src/session.c index 4fd11f89..065e769f 100644 --- a/src/session.c +++ b/src/session.c @@ -236,16 +236,28 @@ static WMPropList *makeWindowState(WWindow * wwin, WApplication * wapp) WMReleasePropList(shortcut); if (wapp && wapp->app_icon && wapp->app_icon->dock) { int i; - char *name; + char *name = NULL; if (wapp->app_icon->dock == scr->dock) { name = "Dock"; - } else { + } + if (name == NULL) // Try the clips + { for (i = 0; i < scr->workspace_count; i++) if (scr->workspaces[i]->clip == wapp->app_icon->dock) break; - assert(i < scr->workspace_count); - /*n = i+1; */ - name = scr->workspaces[i]->name; + if (i < scr->workspace_count) + name = scr->workspaces[i]->name; + } + if (name == NULL) // Try the drawers + { + WDrawerChain *dc; + for (dc = scr->drawers; dc != NULL; dc = dc->next) + { + if (dc->adrawer == wapp->app_icon->dock) + break; + } + assert(dc != NULL); + name = dc->adrawer->icon_array[0]->wm_instance; } dock = WMCreatePLString(name); WMPutInPLDictionary(win_state, sDock, dock); @@ -462,7 +474,9 @@ void wSessionRestoreState(WScreen *scr) if (sscanf(tmp, "%i", &n) != 1) { if (!strcasecmp(tmp, "DOCK")) { dock = scr->dock; - } else { + } + if (dock == NULL) // Try the clips + { for (j = 0; j < scr->workspace_count; j++) { if (strcmp(scr->workspaces[j]->name, tmp) == 0) { dock = scr->workspaces[j]->clip; @@ -470,6 +484,18 @@ void wSessionRestoreState(WScreen *scr) } } } + if (dock == NULL) // Try the drawers + { + WDrawerChain *dc; + for (dc = scr->drawers; dc != NULL; dc = dc->next) + { + if (strcmp(dc->adrawer->icon_array[0]->wm_instance, tmp) == 0) + { + dock = dc->adrawer; + break; + } + } + } } else { if (n == 0) { dock = scr->dock; diff --git a/src/startup.c b/src/startup.c index e1400264..1ade83dd 100644 --- a/src/startup.c +++ b/src/startup.c @@ -772,6 +772,14 @@ void StartUp(Bool defaultScreenOnly) } } } + /* auto-launch apps in drawers */ + if (!wPreferences.flags.nodrawer) { + WDrawerChain *dc; + for (dc = wScreen[j]->drawers; dc; dc = dc->next) { + wScreen[j]->last_dock = dc->adrawer; + wDockDoAutoLaunch(dc->adrawer, 0); + } + } } /* go to workspace where we were before restart */ diff --git a/src/superfluous.c b/src/superfluous.c index 135ce429..8df8ac24 100644 --- a/src/superfluous.c +++ b/src/superfluous.c @@ -137,11 +137,40 @@ void DoKaboom(WScreen * scr, Window win, int x, int y) #endif /* NORMAL_ICON_KABOOM */ } +static int addGhostTile(WScreen *scr, RImage *back, Pixmap which, int dy, int height, + unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask) +{ + XImage *img; + RImage *dock_image; + + img = XGetImage(dpy, which, 0, 0, wPreferences.icon_size, height, AllPlanes, ZPixmap); + if (!img) { + RReleaseImage(back); + return -1; + } + img->red_mask = red_mask; + img->green_mask = green_mask; + img->blue_mask = blue_mask; + + dock_image = RCreateImageFromXImage(scr->rcontext, img, NULL); + XDestroyImage(img); + if (!dock_image) { + RReleaseImage(back); + return -1; + } + RCombineAreaWithOpaqueness(back, dock_image, 0, 0, wPreferences.icon_size, + height, 0, dy, 30 * 256 / 100); + RReleaseImage(dock_image); + return 0; +} + Pixmap MakeGhostDock(WDock * dock, int sx, int dx, int y) { WScreen *scr = dock->screen_ptr; + WDrawerChain *dc; + WDock *drawer; XImage *img; - RImage *back, *dock_image; + RImage *back; Pixmap pixmap; int i, virtual_tiles, h, j, n; unsigned long red_mask, green_mask, blue_mask; @@ -151,6 +180,10 @@ Pixmap MakeGhostDock(WDock * dock, int sx, int dx, int y) if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex > virtual_tiles) virtual_tiles = dock->icon_array[i]->yindex; } + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + if (dc->adrawer->y_pos - dock->y_pos > virtual_tiles * wPreferences.icon_size) + virtual_tiles = (dc->adrawer->y_pos - dock->y_pos) / wPreferences.icon_size; + } virtual_tiles++; h = virtual_tiles * wPreferences.icon_size; h = (y + h > scr->scr_height) ? scr->scr_height - y : h; @@ -181,28 +214,24 @@ Pixmap MakeGhostDock(WDock * dock, int sx, int dx, int y) which = dock->icon_array[i]->icon->pixmap; else which = dock->icon_array[i]->icon->core->window; - - img = XGetImage(dpy, which, 0, 0, wPreferences.icon_size, n, AllPlanes, ZPixmap); - - if (!img) { - RReleaseImage(back); - return None; - } - img->red_mask = red_mask; - img->green_mask = green_mask; - img->blue_mask = blue_mask; - - dock_image = RCreateImageFromXImage(scr->rcontext, img, NULL); - XDestroyImage(img); - if (!dock_image) { - RReleaseImage(back); - return None; - } - RCombineAreaWithOpaqueness(back, dock_image, 0, 0, - wPreferences.icon_size, n, 0, j, 30 * 256 / 100); - RReleaseImage(dock_image); + if (addGhostTile(scr, back, which, j, n, red_mask, green_mask, blue_mask)) + return None; /* back is released by addGhostTile */ } } + for (dc = scr->drawers; dc != NULL; dc = dc->next) { + Pixmap which; + drawer = dc->adrawer; + if (drawer->y_pos >= scr->scr_height) + continue; + j = drawer->y_pos - dock->y_pos; + n = (h - j < wPreferences.icon_size) ? h - j : wPreferences.icon_size; + if (drawer->icon_array[0]->icon->pixmap) + which = drawer->icon_array[0]->icon->pixmap; + else + which = drawer->icon_array[0]->icon->core->window; + if (addGhostTile(scr, back, which, j, n, red_mask, green_mask, blue_mask)) + return None; /* back is released by addGhostTile */ + } RConvertImage(scr->rcontext, back, &pixmap); diff --git a/src/workspace.c b/src/workspace.c index 2fd3925c..23f2c19d 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -96,7 +96,7 @@ int wWorkspaceNew(WScreen *scr) } if (!wPreferences.flags.noclip) - wspace->clip = wDockCreate(scr, WM_CLIP); + wspace->clip = wDockCreate(scr, WM_CLIP, NULL); list = wmalloc(sizeof(WWorkspace *) * scr->workspace_count); From cf5fdca63de9612a3acadbde510f40f7aada0d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:42 +0200 Subject: [PATCH 16/20] WPrefs: adds possibility to disable drawers from Docks panel --- WPrefs.app/Docks.c | 106 +- WPrefs.app/tiff/Makefile.am | 2 +- WPrefs.app/tiff/dockclipdrawersection.tiff | Bin 0 -> 4188 bytes WPrefs.app/tiff/dockclipsection.tiff | Bin 7248 -> 0 bytes WPrefs.app/tiff/drawer.tiff | Bin 0 -> 9556 bytes WPrefs.app/xpm/Makefile.am | 2 +- WPrefs.app/xpm/dockclipdrawersection.xpm | 307 ++++++ WPrefs.app/xpm/dockclipsection.xpm | 946 ---------------- WPrefs.app/xpm/drawer.xpm | 1149 ++++++++++++++++++++ 9 files changed, 1520 insertions(+), 992 deletions(-) create mode 100644 WPrefs.app/tiff/dockclipdrawersection.tiff delete mode 100644 WPrefs.app/tiff/dockclipsection.tiff create mode 100644 WPrefs.app/tiff/drawer.tiff create mode 100644 WPrefs.app/xpm/dockclipdrawersection.xpm delete mode 100644 WPrefs.app/xpm/dockclipsection.xpm create mode 100644 WPrefs.app/xpm/drawer.xpm diff --git a/WPrefs.app/Docks.c b/WPrefs.app/Docks.c index b3b821c1..211462d1 100644 --- a/WPrefs.app/Docks.c +++ b/WPrefs.app/Docks.c @@ -38,21 +38,20 @@ typedef struct _Panel { WMTextField *autoDelayT[4]; WMFrame *dockF; - WMButton *dockB; - WMButton *clipB; + WMButton *docksB[3]; } _Panel; -#define ICON_FILE "dockclipsection" +#define ICON_FILE "dockclipdrawersection" #define ARQUIVO_XIS "xis" #define DELAY_ICON "timer%i" #define DELAY_ICON_S "timer%is" -#define DOCK_FILE "dock" -#define CLIP_FILE "clip" static char *autoDelayStrings[4]; static char *autoDelayKeys[4] = { "ClipAutoexpandDelay", "ClipAutocollapseDelay", "ClipAutoraiseDelay", "ClipAutolowerDelay" }; static char *autoDelayPresetValues[5] = { "0", "100", "250", "600", "1000" }; +static char *dockDisablingKeys[3] = { "DisableDock", "DisableClip", "DisableDrawers" }; +static char *dockFiles[3] = { "dock", "clip", "drawer" }; static void showData(_Panel *panel); static void storeData(_Panel *panel); @@ -104,6 +103,22 @@ static void autoDelayChanged(void *observerData, WMNotification *notification) } } +static void pushDockButton(WMWidget *w, void *data) +{ + _Panel *panel = (_Panel *) data; + WMButton *button = (WMButton *) w; + if (button == panel->docksB[0] && + !WMGetButtonSelected(panel->docksB[0])) + { + WMSetButtonSelected(panel->docksB[2], False); + } + if (button == panel->docksB[2] && + WMGetButtonSelected(panel->docksB[2])) + { + WMSetButtonSelected(panel->docksB[0], True); + } +} + static void createPanel(Panel *p) { _Panel *panel = (_Panel *) p; @@ -188,44 +203,45 @@ static void createPanel(Panel *p) wfree(buf1); wfree(buf2); - /***************** Enable/disable clip/dock *****************/ + /***************** Enable/disable clip/dock/drawers *****************/ panel->dockF = WMCreateFrame(panel->box); WMResizeWidget(panel->dockF, 115, 210); WMMoveWidget(panel->dockF, 390, 10); - WMSetFrameTitle(panel->dockF, _("Dock/Clip")); + WMSetFrameTitle(panel->dockF, _("Dock/Clip/Drawer")); - panel->dockB = WMCreateButton(panel->dockF, WBTToggle); - WMResizeWidget(panel->dockB, 64, 64); - WMMoveWidget(panel->dockB, 25, 35); - WMSetButtonImagePosition(panel->dockB, WIPImageOnly); - CreateImages(scr, rc, xis, DOCK_FILE, &icon1, &icon2); - if (icon2) { - WMSetButtonImage(panel->dockB, icon2); - WMReleasePixmap(icon2); + for (i = 0; i < 3; i++) + { + panel->docksB[i] = WMCreateButton(panel->dockF, WBTToggle); + WMResizeWidget(panel->docksB[i], 56, 56); + WMMoveWidget(panel->docksB[i], 30, 20 + 62 * i); + WMSetButtonImagePosition(panel->docksB[i], WIPImageOnly); + CreateImages(scr, rc, xis, dockFiles[i], &icon1, &icon2); + if (icon2) { + WMSetButtonImage(panel->docksB[i], icon2); + WMReleasePixmap(icon2); + } + if (icon1) { + WMSetButtonAltImage(panel->docksB[i], icon1); + WMReleasePixmap(icon1); + } + switch(i) + { + case 0: + WMSetBalloonTextForView(_("Disable/enable the application Dock (the\n" + "vertical icon bar in the side of the screen)."), WMWidgetView(panel->docksB[i])); + break; + case 1: + WMSetBalloonTextForView(_("Disable/enable the Clip (that thing with\n" + "a paper clip icon)."), WMWidgetView(panel->docksB[i])); + break; + case 2: + WMSetBalloonTextForView(_("Disable/enable Drawers (a dock that stores\n" + "application icons horizontally). The dock is required."), WMWidgetView(panel->docksB[i])); + break; + } + WMSetButtonAction(panel->docksB[i], pushDockButton, panel); } - if (icon1) { - WMSetButtonAltImage(panel->dockB, icon1); - WMReleasePixmap(icon1); - } - WMSetBalloonTextForView(_("Disable/enable the application Dock (the\n" - "vertical icon bar in the side of the screen)."), WMWidgetView(panel->dockB)); - - panel->clipB = WMCreateButton(panel->dockF, WBTToggle); - WMResizeWidget(panel->clipB, 64, 64); - WMMoveWidget(panel->clipB, 25, 120); - WMSetButtonImagePosition(panel->clipB, WIPImageOnly); - CreateImages(scr, rc, xis, CLIP_FILE, &icon1, &icon2); - if (icon2) { - WMSetButtonImage(panel->clipB, icon2); - WMReleasePixmap(icon2); - } - if (icon1) { - WMSetButtonAltImage(panel->clipB, icon1); - WMReleasePixmap(icon1); - } - WMSetBalloonTextForView(_("Disable/enable the Clip (that thing with\n" - "a paper clip icon)."), WMWidgetView(panel->clipB)); - + WMMapSubwidgets(panel->dockF); if (xis) @@ -244,9 +260,10 @@ static void storeData(_Panel *panel) { SetStringForKey(WMGetTextFieldText(panel->autoDelayT[i]), autoDelayKeys[i]); } - - SetBoolForKey(!WMGetButtonSelected(panel->dockB), "DisableDock"); - SetBoolForKey(!WMGetButtonSelected(panel->clipB), "DisableClip"); + for (i = 0; i < 3; i++) + { + SetBoolForKey(!WMGetButtonSelected(panel->docksB[i]), dockDisablingKeys[i]); + } } static void showData(_Panel *panel) @@ -259,9 +276,10 @@ static void showData(_Panel *panel) WMSetTextFieldText(panel->autoDelayT[i], value); adjustButtonSelectionBasedOnValue(panel, i, value); } - - WMSetButtonSelected(panel->dockB, !GetBoolForKey("DisableDock")); - WMSetButtonSelected(panel->clipB, !GetBoolForKey("DisableClip")); + for (i = 0; i < 3; i++) + { + WMSetButtonSelected(panel->docksB[i], !GetBoolForKey(dockDisablingKeys[i])); + } } Panel *InitDocks(WMScreen *scr, WMWidget *parent) diff --git a/WPrefs.app/tiff/Makefile.am b/WPrefs.app/tiff/Makefile.am index 76fced4a..c370b762 100644 --- a/WPrefs.app/tiff/Makefile.am +++ b/WPrefs.app/tiff/Makefile.am @@ -8,7 +8,7 @@ EXTRA_DIST = \ configs.tiff \ cycleworkspaces.tiff \ dock.tiff \ - dockclipsection.tiff \ + dockclipdrawersection.tiff \ dontlinkworkspaces.tiff \ ergonomic.tiff \ expert.tiff \ diff --git a/WPrefs.app/tiff/dockclipdrawersection.tiff b/WPrefs.app/tiff/dockclipdrawersection.tiff new file mode 100644 index 0000000000000000000000000000000000000000..4022abd01beb440d9219d6689e73bd5b0f9c9283 GIT binary patch literal 4188 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 literal 0 HcmV?d00001 diff --git a/WPrefs.app/tiff/dockclipsection.tiff b/WPrefs.app/tiff/dockclipsection.tiff deleted file mode 100644 index 22801e112d7790f31c6dd6ca9c351a13a89a6214..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7248 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 H2yy;D56zZP literal 0 HcmV?d00001 diff --git a/WPrefs.app/xpm/Makefile.am b/WPrefs.app/xpm/Makefile.am index 637fffc5..b0149b39 100644 --- a/WPrefs.app/xpm/Makefile.am +++ b/WPrefs.app/xpm/Makefile.am @@ -9,7 +9,7 @@ EXTRA_DIST = \ configs.xpm \ cycleworkspaces.xpm \ dock.xpm \ - dockclipsection.xpm \ + dockclipdrawersection.xpm \ dontlinkworkspaces.xpm \ ergonomic.xpm \ expert.xpm \ diff --git a/WPrefs.app/xpm/dockclipdrawersection.xpm b/WPrefs.app/xpm/dockclipdrawersection.xpm new file mode 100644 index 00000000..f482574d --- /dev/null +++ b/WPrefs.app/xpm/dockclipdrawersection.xpm @@ -0,0 +1,307 @@ +/* XPM */ +static char * dockclipdrawersection_xpm[] = { +"48 48 256 2", +" c #000100", +". c #000609", +"+ c #030601", +"@ c #0B080D", +"# c #070A06", +"$ c #080E10", +"% c #110E12", +"& c #131114", +"* c #0E1315", +"= c #121311", +"- c #161417", +"; c #18171A", +"> c #191A21", +", c #1C1A1D", +"' c #1C1C24", +") c #1E1F26", +"! c #232124", +"~ c #202426", +"{ c #222421", +"] c #22232B", +"^ c #252427", +"/ c #25252D", +"( c #27282F", +"_ c #29282B", +": c #2B2B33", +"< c #2B2D2A", +"[ c #2D2E36", +"} c #303038", +"| c #323034", +"1 c #2F3335", +"2 c #34353D", +"3 c #373538", +"4 c #383941", +"5 c #3C3A3D", +"6 c #393D4A", +"7 c #3D3E46", +"8 c #403E41", +"9 c #42424B", +"0 c #3F4350", +"a c #424441", +"b c #454346", +"c c #46464F", +"d c #464845", +"e c #4A484B", +"f c #434A51", +"g c #484951", +"h c #4D4B4F", +"i c #4D4D56", +"j c #4B4E5C", +"k c #505059", +"l c #515351", +"m c #53545D", +"n c #525563", +"o c #6C5612", +"p c #4F575E", +"q c #575760", +"r c #5A585C", +"s c #6F591D", +"t c #6C5B16", +"u c #5D5B59", +"v c #5B5B64", +"w c #585C6A", +"x c #725D20", +"y c #5F5D61", +"z c #5B5F6C", +"A c #72611F", +"B c #606069", +"C c #5D616F", +"D c #5E627B", +"E c #5F6371", +"F c #7A6327", +"G c #646563", +"H c #64646D", +"I c #5E666D", +"J c #5E6578", +"K c #616668", +"L c #616572", +"M c #7C6529", +"N c #676568", +"O c #6A646E", +"P c #636774", +"Q c #676770", +"R c #656876", +"S c #666983", +"T c #676B79", +"U c #816D19", +"V c #72696F", +"W c #726C57", +"X c #706A74", +"Y c #696D70", +"Z c #6B6C75", +"` c #6F6C70", +" . c #7D6E3B", +".. c #6A6E7C", +"+. c #837024", +"@. c #6B6F89", +"#. c #6D707F", +"$. c #70717A", +"%. c #887320", +"&. c #6E718C", +"*. c #797076", +"=. c #747276", +"-. c #927503", +";. c #8B7519", +">. c #87742F", +",. c #6F7381", +"'. c #7D7367", +"). c #767382", +"!. c #717583", +"~. c #6F768A", +"{. c #8D7825", +"]. c #78767A", +"^. c #737785", +"/. c #7A7772", +"(. c #8D792D", +"_. c #8C7933", +":. c #757988", +"<. c #7B797D", +"[. c #747B8F", +"}. c #7D798A", +"|. c #807984", +"1. c #7A7B84", +"2. c #787C8A", +"3. c #837A80", +"4. c #977C32", +"5. c #877986", +"6. c #917E3F", +"7. c #777E92", +"8. c #7A7E8C", +"9. c #807D8D", +"0. c #877D7A", +"a. c #7C808F", +"b. c #837F90", +"c. c #7B8296", +"d. c #7E8291", +"e. c #887F94", +"f. c #98843E", +"g. c #90826B", +"h. c #9E8339", +"i. c #828297", +"j. c #898471", +"k. c #9D862C", +"l. c #A38525", +"m. c #818593", +"n. c #A28534", +"o. c #8D8489", +"p. c #85868F", +"q. c #85859A", +"r. c #A5872F", +"s. c #8B8590", +"t. c #838796", +"u. c #918585", +"v. c #8D8875", +"w. c #8A8697", +"x. c #9D884E", +"y. c #868A99", +"z. c #8C8993", +"A. c #AD8932", +"B. c #8C8A8E", +"C. c #8A8A9F", +"D. c #A58D33", +"E. c #AB8C2C", +"F. c #928C79", +"G. c #858CA0", +"H. c #AA8C34", +"I. c #A58B4D", +"J. c #9089A1", +"K. c #A58E3B", +"L. c #898D9C", +"M. c #AC8E3D", +"N. c #A99036", +"O. c #938D98", +"P. c #8B8F9E", +"Q. c #9B8E7D", +"R. c #8E8EA4", +"S. c #AE9037", +"T. c #B09131", +"U. c #AB9145", +"V. c #8D91A0", +"W. c #AC9331", +"X. c #9390A0", +"Y. c #8F9396", +"Z. c #8F93A2", +"`. c #AE953B", +" + c #9592A3", +".+ c #B3943C", +"++ c #A19571", +"@+ c #9195A4", +"#+ c #A49194", +"$+ c #9B94A0", +"%+ c #9B93AB", +"&+ c #B1983E", +"*+ c #9497A6", +"=+ c #9996A6", +"-+ c #979996", +";+ c #9798A2", +">+ c #B5984D", +",+ c #B09A53", +"'+ c #9D99AA", +")+ c #979BAA", +"!+ c #A098B0", +"~+ c #BC9C43", +"{+ c #9A9FA1", +"]+ c #BBA03F", +"^+ c #C2A141", +"/+ c #9EA2B1", +"(+ c #AD9EB8", +"_+ c #ACA2A8", +":+ c #AFA1AF", +"<+ c #B9A66E", +"[+ c #A9A7AB", +"}+ c #A9ABA8", +"|+ c #B7A9B6", +"1+ c #B2ABB6", +"2+ c #AFACBD", +"3+ c #B0AEB2", +"4+ c #BCABB3", +"5+ c #C7B068", +"6+ c #BDAEC8", +"7+ c #CBB46B", +"8+ c #BBB1B8", +"9+ c #D3B56E", +"0+ c #D3B769", +"a+ c #CFB86F", +"b+ c #B5BABD", +"c+ c #B8BAB7", +"d+ c #BFBDC1", +"e+ c #BFBCCD", +"f+ c #BEC1BD", +"g+ c #C6C8C5", +"h+ c #C6CCCE", +"i+ c #E0CD7B", +"j+ c #D0CDD1", +"k+ c #D2D0D4", +"l+ c #D6D4D8", +"m+ c #D7D8E2", +"n+ c #DBD8DD", +"o+ c #DADCD9", +"p+ c #D8DDE0", +"q+ c #DCDDE7", +"r+ c #F4E08D", +"s+ c #E1E2EC", +"t+ c #E3E5E1", +"u+ c #E8E5EA", +"v+ c #E5E6F0", +"w+ c #ECE9EE", +"x+ c #E9EAF4", +"y+ c #EFEDF1", +"z+ c #EDEEF8", +"A+ c #F0F2EF", +"B+ c #F4F1F6", +"C+ c #F2F3FD", +"D+ c #F8F5FA", +"E+ c #FBF8FD", +"F+ c #FCFEFB", +"G+ c #FEFFFC", +"+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ", +"+ D D D D D D D D D D D D D D D D D D D D D D D E+B+B+B+y+y+z+y+y+y+x+x+x+w+w+u+u+u+s+s+s+s+[+G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D B+=+=+*+*+ +V.P.L.L.y.y.t.m.m.d.a.8.2.:.:.^.} G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D B+'+)+)+'+*+*+Z.V.P.L.L.y.y.t.m.m.d.a.8.2.2.2 G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D z+*+)+*+*+*+Z.*+Z.1.Z Z Z $.y.m.d.a.8.2.2.2.2 G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D z+=+*+*+*+Z.=+K @ # . . . + = ^.m.8.2.:.:.^.} G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D y+*+*+*+V.P._ + + + + + + + + + 4 #.#.,.^.^.} G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D y+ +*+Z./+, + + + + + + + + /.f+g+3 $ 2 !.!.} G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D y+X.Z.*+; + + + + + + + + + -+G+G+G+% _ !.,.} G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D y+P.V.2.@ + + + + + + + + + -+G+G+G+3+! ,.,.} G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D y+L.P.B + + + + + + + + + + -+G+G+G+o+5 #.#.[ G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D x+L.L.B + + + + + + + + + + -+G+G+G+A+y #...: G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D x+L.L.B + + + + % b d a l d f+G+G+G+A+y ....: G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D w+y.y.B + + + + = t+G+G+G+G+G+G+G+G+A+r ..T : G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D w+t.y.v + + + + = o+G+G+G+G+G+G+G+G+o+3 R R : G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D u+m.t.1.$ + + + = o+G+G+G+G+G+G+G+G+g+> R R ( G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D u+m.m.y.c + + + = o+G+G+G+G+G+G+G+D+= ~ R L ( G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D u+d.m.H ^ . l a l t+G+G+G+G+G+G+G+1 + ^ L E ( G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D s+a.d.q + + G t+G+G+G+G+G+G+G+p+b + + ! E C / G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D s+8.a.m + + + + u }+g+G+o+c+u # + + + ) z z / G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D s+2.8.,.q q q m k g c 7 9 c g g g c c j z z / G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D s+2.2.2.2.:.^.^.,.,.,.#.....R R P L E z z z ] G+", +"+ D D D D D D D D D D D D D D D D D D D D D D D s+:.2.:.:.!.!.,.#.#.....T R R L E C z z w w ] G+", +"+ &.&.&.&.&.&.&.&.&.&.&.&.&.@.@.&.@.@.@.@.@.@.S Y.} 2 } } } } } } } : : : : : ( ( ( ( / / ] ) G+", +"+ D+s+s+s+s+q+q+q+q+q+q+m+m+m+b+m+m+m+m+m+m+m+B.B+n+n+n+n+n+n+n+l+l+l+l+l+l+k+k+j+j+j+j+j+j+{+G+", +"+ B+=+)+'+*+Z.=+Z.V.P.L.L.y.t.V.h 2.a.E z z R ( D+'+'+)+'+*+=+Z.V.P.L.L.y.y.t.m.m.d.a.8.2.2.2 G+", +"+ B+=+'+'+,.@ H Z.V.P.L.L.y.y.t.y.q 2.z . + | ( C+)+'+)+*+*+=+Z.V.P.L.L.y.y.t.m.m.d.a.8.2.2.2 G+", +"+ B+=+)+=+y.t.i V.P.L.y.y.t.m.m.d.m.5 2.L + 3 / C+'+)+*+=+Z.Z.V.P.L.L.y.t.t.m.d.d.a.8.2.2.:.2 G+", +"+ B+Z.*+=+P.9 t.P.L.y.y.t.m.m.d.a.8.m.7 #.E 4 / C+*+*+=+Z.Z.R.P.Q.Q.F.v.v.v.v.j.j.j.j.1.:.:.} G+", +"+ y+X.*+Z.Z.Z.P.L.y.y.t.m.m.d.a.w.s.3.<.| ^.,.] C+=+*+Z.Z.R.++>+.+T.E.E.l.H.H.H.E.T.f.<.^.^.} G+", +"+ z+X.*+V.V.P.L.y.y.t.m.m.d.J.(+o.I v ].o.! ..] C+Z.*+Z.R.0+a+7+7+5+7+5+5+5+5+5+5+h.6.].!.!.} G+", +"+ z+P.Z.P.P.L.y.y.t.m.m.C.3.%+2+1+=.v B y ^.4 ' C+V.Z.V.R.a+^+^+^+^+^+]+]+]+^+~+A 4._.].,.,.} G+", +"+ z+L.V.P.L.y.y.t.m.m.9.e.6+f 8 c V B Z #.,.!.. C+P.V.P.G.a+~+~+~+~+~+&+&+&+`..+t (._.=.#.#.} G+", +"+ z+y.P.L.y.y.t.t.w.|.|+H b 8 k H O q $.v #.#.] z+L.P.a.q.a+~+~+`.r.H.N.E.,+`.`.t {._.=.#.#.[ G+", +"+ x+y.P.y.y.t.m.:.|+:+v 8 9 B #.$.}.q.p m ....) z+L.*+< [.a+~+~+&+H.i+r+N.>+`.H.t (.>.=.....: G+", +"+ x+t.L.y.t.d.=+_+|.h 8 i Q ,.2.Z 9.r i q ....) z+V.< < [.a+~+~+`.r.0+9++.,+N.H.t %.+.` ....: G+", +"+ w+t.y.t.b.8+O.|.8 b v ..,.}.e.*.q 8 k B T T ' z+L.$.{ [.a+~+&+.+U.>+6.x.<+E.D.t %.U Y R R : G+", +"+ u+m.t.;+u.1+k 8 h Q ,.,.!+5.).c 8 i B R R R ' z+t.y.Q ~.7+~+&+&+`.`.W.S.H.N.N.t U +.` R R : G+", +"+ d+,.m.4+O.c 9 q $...t.:+B X 7 9 q Q R R R R > x+t.t.m.c.7+M.K.K.D.k.k.n.k.k.k.t %.+.` R R ( G+", +"+ w+4 P.o.B b B ,.$.e+O s.g 8 i B R R R R P P > x+m.t.d.i.<+M F F F x s s s o o o %.+.N P L ( G+", +"+ u+)+: ).0.m Q P.$+s.H 8 9 q R R R R R L L L > x+d.m.d.7..+U.I.I.x.A.h.l._.6.(.-.;. .J L L ( G+", +"+ u+,.L.k $.#+_+X.].i 8 i B R R R R T L E E C > v+a.d.8.8.g.0.^.!.!./.=.'.....R W W J E C C / G+", +"+ v+6 L L./ |._+N 8 b q H ....R R R , R C z C > v+8.a.8.2.:.^.!.!.,.#.#.....R R R L E C z z / G+", +"+ s+0 + j L.g i i 5 4 + ^ B 2 k } _ . c 7 c c $ v+2.8.2.:.^.!.!.,.#.#.....R R R L E C z z z / G+", +"+ s+0 + + n :.7 :.,.* z , w - : + #.$ * z ] + % v+2.2.2.:.^.!.,.,.#.....T R R L L E z z w w ] G+", +"+ u+2.z.p.p.8.y.2 C B ,.R #.q R k R j E c c 9 @ x+8.a.8.2.:.:.^.!.,.#.#.....R R P L E z z z ] G+", +"+ f+; ; ; ; ; - , $ & - - - - & & & % % % % $ @ h+; , ; ; ; ; - - - - - - & & * & % % % % % . G+", +"+ G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+G+"}; diff --git a/WPrefs.app/xpm/dockclipsection.xpm b/WPrefs.app/xpm/dockclipsection.xpm deleted file mode 100644 index 9603fa2f..00000000 --- a/WPrefs.app/xpm/dockclipsection.xpm +++ /dev/null @@ -1,946 +0,0 @@ -/* XPM */ -static char * dockclipsection_xpm[] = { -"48 48 895 2", -" c #000000", -". c #FBFBFD", -"+ c #F1F2F8", -"@ c #F1F1F8", -"# c #F0F0F8", -"$ c #EFEFF7", -"% c #EEEFF6", -"& c #EDEEF5", -"* c #ECEDF4", -"= c #EBECF3", -"- c #EAEBF2", -"; c #EAEAF2", -"> c #E9E9F1", -", c #E8E8F0", -"' c #E7E8EF", -") c #E6E7EE", -"! c #E5E6ED", -"~ c #E4E5EC", -"{ c #E3E4EB", -"] c #E2E3EA", -"^ c #E1E2E9", -"/ c #E0E1E8", -"( c #B1B1B3", -"_ c #DEDEE2", -": c #F2F2F8", -"< c #F0F1F8", -"[ c #EEEEF6", -"} c #EDEDF5", -"| c #ECECF4", -"1 c #EBEBF3", -"2 c #E9EAF1", -"3 c #E4E4EC", -"4 c #E3E3EB", -"5 c #E1E1E9", -"6 c #9A9A9B", -"7 c #FFFFFF", -"8 c #9798A8", -"9 c #9A9AAA", -"0 c #9999A9", -"a c #9697A6", -"b c #9595A5", -"c c #9393A3", -"d c #9192A1", -"e c #8F909F", -"f c #8D8E9D", -"g c #8B8C9B", -"h c #8A8B9A", -"i c #888998", -"j c #868796", -"k c #848594", -"l c #828492", -"m c #818291", -"n c #7F808F", -"o c #7D7F8D", -"p c #7B7D8B", -"q c #797B89", -"r c #777987", -"s c #2D2E34", -"t c #EEEEF0", -"u c #9B9BAB", -"v c #9798A7", -"w c #9596A5", -"x c #9394A3", -"y c #9293A2", -"z c #9091A0", -"A c #8E8F9E", -"B c #8C8D9C", -"C c #898A99", -"D c #878897", -"E c #858695", -"F c #838593", -"G c #818391", -"H c #7F818F", -"I c #7E7F8E", -"J c #7C7D8C", -"K c #7A7C8A", -"L c #787A88", -"M c #3B3C43", -"N c #F1F1F9", -"O c #9D9DAD", -"P c #9A9BAA", -"Q c #888A99", -"R c #868896", -"S c #2E2F35", -"T c #DDDDE3", -"U c #9D9EAD", -"V c #9B9CAB", -"W c #999AA9", -"X c #9495A4", -"Y c #8A8C9A", -"Z c #878997", -"` c #858795", -" . c #808190", -".. c #7E808E", -"+. c #7C7E8C", -"@. c #3D3E45", -"#. c #9898A8", -"$. c #9D9DAA", -"%. c #9E9FAB", -"&. c #9C9DA7", -"*. c #A6A7B0", -"=. c #ABACB4", -"-. c #A2A3AA", -";. c #A4A4A9", -">. c #ABABAD", -",. c #AAAAAA", -"'. c #B8B8B4", -"). c #ACADA7", -"!. c #9D9F94", -"~. c #7D8073", -"{. c #474745", -"]. c #747682", -"^. c #DCDCE3", -"/. c #9698A6", -"(. c #8E8F9D", -"_. c #7D7E8A", -":. c #6F707A", -"<. c #6C6D78", -"[. c #6B6C77", -"}. c #81828F", -"|. c #7D808D", -"1. c #A2A3AB", -"2. c #F2F2F2", -"3. c #F8F8F5", -"4. c #FAFBF6", -"5. c #FFFFFA", -"6. c #FEFEF3", -"7. c #E9EADD", -"8. c #D2D3C6", -"9. c #BABAAD", -"0. c #A1A293", -"a. c #888780", -"b. c #6F7072", -"c. c #5E615C", -"d. c #989986", -"e. c #242516", -"f. c #56575C", -"g. c #767886", -"h. c #2C2D33", -"i. c #DBDBE2", -"j. c #9394A2", -"k. c #9597A6", -"l. c #6E6F75", -"m. c #242426", -"n. c #0E0E0F", -"o. c #060607", -"p. c #060606", -"q. c #070707", -"r. c #111113", -"s. c #4F5057", -"t. c #828392", -"u. c #A8A9B0", -"v. c #C2C2BE", -"w. c #574B77", -"x. c #42385D", -"y. c #241B41", -"z. c #08003A", -"A. c #070039", -"B. c #070034", -"C. c #02002E", -"D. c #000027", -"E. c #000023", -"F. c #00001E", -"G. c #090A25", -"H. c #BAB9AD", -"I. c #2E2E1E", -"J. c #747684", -"K. c #2B2C32", -"L. c #DADBE1", -"M. c #9696A6", -"N. c #9192A2", -"O. c #525258", -"P. c #010102", -"Q. c #212123", -"R. c #737581", -"S. c #717380", -"T. c #6F717E", -"U. c #767887", -"V. c #757785", -"W. c #3A3B42", -"X. c #AAABB2", -"Y. c #A1A09D", -"Z. c #060048", -"`. c #14014E", -" + c #312755", -".+ c #1D1931", -"++ c #1D192E", -"@+ c #191821", -"#+ c #282639", -"$+ c #2A2746", -"%+ c #171636", -"&+ c #010222", -"*+ c #0C0E27", -"=+ c #BBBBAE", -"-+ c #353525", -";+ c #585A5D", -">+ c #727482", -",+ c #DADAE1", -"'+ c #49494E", -")+ c #202021", -"!+ c #B3B3B3", -"~+ c #A8A8A8", -"{+ c #919191", -"]+ c #050507", -"^+ c #787A89", -"/+ c #737583", -"(+ c #393A41", -"_+ c #8F90A0", -":+ c #A8A8AE", -"<+ c #A3A29F", -"[+ c #0D004D", -"}+ c #3C305E", -"|+ c #0F0E0F", -"1+ c #121212", -"2+ c #A9A9A9", -"3+ c #7E7E80", -"4+ c #191927", -"5+ c #060727", -"6+ c #BCBCAE", -"7+ c #3F3F2E", -"8+ c #414239", -"9+ c #747685", -"0+ c #717381", -"a+ c #292B30", -"b+ c #D9D9E0", -"c+ c #747581", -"d+ c #2B2B2B", -"e+ c #FEFEFE", -"f+ c #FDFDFD", -"g+ c #818183", -"h+ c #767987", -"i+ c #383940", -"j+ c #8D8E9E", -"k+ c #A1A29C", -"l+ c #160057", -"m+ c #1E1A2A", -"n+ c #121112", -"o+ c #D2D2D2", -"p+ c #F5F5F5", -"q+ c #3F3F4A", -"r+ c #070727", -"s+ c #BEBFB1", -"t+ c #4D4E3B", -"u+ c #404033", -"v+ c #6F7180", -"w+ c #6E717E", -"x+ c #292A30", -"y+ c #D8D9DF", -"z+ c #9899A9", -"A+ c #19191C", -"B+ c #D7D7D8", -"C+ c #0C0C0C", -"D+ c #6F727F", -"E+ c #37383F", -"F+ c #8B8C9C", -"G+ c #A7A7AD", -"H+ c #A09F9B", -"I+ c #1C065C", -"J+ c #0B0814", -"K+ c #161616", -"L+ c #373737", -"M+ c #4E4D4E", -"N+ c #D9D9D9", -"O+ c #FBFBFB", -"P+ c #6F6F79", -"Q+ c #0C0E28", -"R+ c #C3C4B7", -"S+ c #5F614C", -"T+ c #4D4F3F", -"U+ c #6C6F7C", -"V+ c #6D6F7D", -"W+ c #28292F", -"X+ c #D7D8DE", -"Y+ c #82838F", -"Z+ c #FAFAFA", -"`+ c #292827", -" @ c #737683", -".@ c #6D707D", -"+@ c #36373E", -"@@ c #8E8E9E", -"#@ c #A4A5AB", -"$@ c #A0A09B", -"%@ c #1B055B", -"&@ c #0F0C18", -"*@ c #656565", -"=@ c #FCFCFC", -"-@ c #61616A", -";@ c #080929", -">@ c #0D0F28", -",@ c #CACBBD", -"'@ c #6B7158", -")@ c #5A594B", -"!@ c #6A6C7B", -"~@ c #6A6D7A", -"{@ c #27282E", -"]@ c #D7D7DD", -"^@ c #55555F", -"/@ c #2A2A2A", -"(@ c #6A6A69", -"_@ c #6B6E7B", -":@ c #35363D", -"<@ c #878998", -"[@ c #A3A4AA", -"}@ c #140055", -"|@ c #302B41", -"1@ c #090909", -"2@ c #696969", -"3@ c #F6F6F6", -"4@ c #1D1D26", -"5@ c #0C0D2C", -"6@ c #0D0F29", -"7@ c #CFD0C3", -"8@ c #797B63", -"9@ c #5E6152", -"0@ c #676A79", -"a@ c #696C79", -"b@ c #26272D", -"c@ c #D6D6DD", -"d@ c #55565E", -"e@ c #464647", -"f@ c #575757", -"g@ c #565656", -"h@ c #555555", -"i@ c #787878", -"j@ c #686867", -"k@ c #6D707E", -"l@ c #6A6C7A", -"m@ c #34353C", -"n@ c #A2A3A8", -"o@ c #A09F9A", -"p@ c #19035A", -"q@ c #110D1A", -"r@ c #CECECD", -"s@ c #C5C5C5", -"t@ c #252526", -"u@ c #0F0F15", -"v@ c #0E0F2D", -"w@ c #D5D5CA", -"x@ c #808369", -"y@ c #606253", -"z@ c #666877", -"A@ c #676A77", -"B@ c #25272D", -"C@ c #D5D6DC", -"D@ c #53535C", -"E@ c #B9B9B9", -"F@ c #F9F9F9", -"G@ c #6B6E7C", -"H@ c #686A78", -"I@ c #33353B", -"J@ c #838694", -"K@ c #A1A2A7", -"L@ c #A5A3A0", -"M@ c #200C5A", -"N@ c #2C2641", -"O@ c #2D2838", -"P@ c #43414F", -"Q@ c #757380", -"R@ c #666470", -"S@ c #312F3B", -"T@ c #26252F", -"U@ c #242432", -"V@ c #0E0E2B", -"W@ c #14162D", -"X@ c #DDDED2", -"Y@ c #7F836A", -"Z@ c #67685D", -"`@ c #646775", -" # c #656875", -".# c #25262C", -"+# c #D4D5DB", -"@# c #888A98", -"## c #7D7D8A", -"$# c #BBBBBB", -"%# c #30302F", -"&# c #666976", -"*# c #32343A", -"=# c #9C9DA2", -"-# c #E9E9E4", -";# c #CBC8D0", -"># c #CFCCD3", -",# c #CDCBD1", -"'# c #C8C7CC", -")# c #C3C2C6", -"!# c #C1C0C3", -"~# c #C2C1C3", -"{# c #C0C0C1", -"]# c #BBBBBC", -"^# c #B5B6B5", -"/# c #B5B6B2", -"(# c #CFCEC3", -"_# c #7B8067", -":# c #6F7171", -"<# c #636673", -"[# c #24252B", -"}# c #D3D4DA", -"|# c #8C8E9D", -"1# c #18181B", -"2# c #D6D6D6", -"3# c #0C0C0B", -"4# c #696C7A", -"5# c #646774", -"6# c #313339", -"7# c #818491", -"8# c #808291", -"9# c #8E8F97", -"0# c #D1D1CF", -"a# c #D1D1CE", -"b# c #DBDCD5", -"c# c #E1E1DA", -"d# c #E7E7E0", -"e# c #EBECE5", -"f# c #EDEDE8", -"g# c #ECEBE5", -"h# c #E8E8E2", -"i# c #E4E4DC", -"j# c #DFDED6", -"k# c #C3C3B5", -"l# c #6D6F58", -"m# c #656868", -"n# c #636674", -"o# c #616471", -"p# c #23252A", -"q# c #D2D3DA", -"r# c #848694", -"s# c #838594", -"t# c #686B78", -"u# c #626572", -"v# c #313239", -"w# c #80818F", -"x# c #7C7E8D", -"y# c #767883", -"z# c #8D8D89", -"A# c #8C8E86", -"B# c #909088", -"C# c #88897C", -"D# c #828173", -"E# c #7E7E71", -"F# c #7E7F72", -"G# c #6D6E62", -"H# c #4E4E3E", -"I# c #696B5C", -"J# c #6E716B", -"K# c #5D5F66", -"L# c #5F626F", -"M# c #606370", -"N# c #222429", -"O# c #D1D2D9", -"P# c #848695", -"Q# c #6B6C78", -"R# c #45454D", -"S# c #151518", -"T# c #434344", -"U# c #545454", -"V# c #454545", -"W# c #D3D3D3", -"X# c #969696", -"Y# c #656876", -"Z# c #606470", -"`# c #2F3137", -" $ c #808290", -".$ c #6E707E", -"+$ c #828389", -"@$ c #7E7E75", -"#$ c #6E6E5B", -"$$ c #565747", -"%$ c #2E2F20", -"&$ c #1B1B0F", -"*$ c #2F2F21", -"=$ c #5F5F4C", -"-$ c #4F5054", -";$ c #57585E", -">$ c #606371", -",$ c #5F636F", -"'$ c #5E616E", -")$ c #222328", -"!$ c #D1D1D8", -"~$ c #4E4F57", -"{$ c #0A0A0A", -"]$ c #C0C0C0", -"^$ c #707072", -"/$ c #040404", -"($ c #5E626E", -"_$ c #2F3037", -":$ c #7F808E", -"<$ c #9A9B9E", -"[$ c #D7D8D6", -"}$ c #D5D5D3", -"|$ c #D7D8D5", -"1$ c #D6D6D1", -"2$ c #B2B2AA", -"3$ c #88887F", -"4$ c #67675E", -"5$ c #3C3C32", -"6$ c #454739", -"7$ c #6F706A", -"8$ c #616470", -"9$ c #5D616D", -"0$ c #5C5F6C", -"a$ c #212227", -"b$ c #D0D1D7", -"c$ c #838493", -"d$ c #4C4D55", -"e$ c #4C4C4C", -"f$ c #DBDBDB", -"g$ c #E4E4E4", -"h$ c #ACACAC", -"i$ c #282828", -"j$ c #616572", -"k$ c #5D606D", -"l$ c #2D2F35", -"m$ c #E2E2EA", -"n$ c #757684", -"o$ c #6C6E7C", -"p$ c #676977", -"q$ c #646672", -"r$ c #636672", -"s$ c #636571", -"t$ c #61636F", -"u$ c #5E606C", -"v$ c #5A5D6A", -"w$ c #202127", -"x$ c #CFD0D6", -"y$ c #6B6D79", -"z$ c #4F5059", -"A$ c #4E4F58", -"B$ c #4C4E57", -"C$ c #464851", -"D$ c #40414B", -"E$ c #5A5C64", -"F$ c #6B6D76", -"G$ c #6A6C74", -"H$ c #4B4C55", -"I$ c #3B3D46", -"J$ c #40424A", -"K$ c #42444C", -"L$ c #40424B", -"M$ c #3F414A", -"N$ c #3C3E46", -"O$ c #5B5E6B", -"P$ c #2D2E35", -"Q$ c #707280", -"R$ c #696B79", -"S$ c #595C69", -"T$ c #1F2126", -"U$ c #CECFD5", -"V$ c #727582", -"W$ c #5A5E6A", -"X$ c #2C2E34", -"Y$ c #7A7C8B", -"Z$ c #7D7F8E", -"`$ c #7B7D8C", -" % c #797B8A", -".% c #777A88", -"+% c #757886", -"@% c #707381", -"#% c #6C6F7D", -"$% c #6A6D7B", -"%% c #5F6370", -"&% c #595D6A", -"*% c #202126", -"=% c #D0D1D8", -"-% c #787B89", -";% c #767986", -">% c #727583", -",% c #6F717F", -"'% c #6B6D7B", -")% c #676A78", -"!% c #5C5F6D", -"~% c #2C2E35", -"{% c #989898", -"]% c #19191D", -"^% c #191A1E", -"/% c #18191D", -"(% c #17181C", -"_% c #16171B", -":% c #15161A", -"<% c #141519", -"[% c #131418", -"}% c #131417", -"|% c #121317", -"1% c #121316", -"2% c #111216", -"3% c #111215", -"4% c #101115", -"5% c #101114", -"6% c #0F1014", -"7% c #050607", -"8% c #131317", -"9% c #121216", -"0% c #101014", -"a% c #0F0F13", -"b% c #0E0F13", -"c% c #0E0E12", -"d% c #0F1013", -"e% c #0C0D10", -"f% c #0B0D10", -"g% c #0B0C0F", -"h% c #0A0C0F", -"i% c #0A0B0E", -"j% c #090A0E", -"k% c #5D627C", -"l% c #E7E8EB", -"m% c #FBFBFF", -"n% c #F8F8FF", -"o% c #F7F7FF", -"p% c #F6F6FF", -"q% c #F5F6FE", -"r% c #F4F5FD", -"s% c #F3F3FB", -"t% c #F2F2FA", -"u% c #F1F2F9", -"v% c #EFF0F7", -"w% c #CACAD0", -"x% c #EAEBF3", -"y% c #E9EAF2", -"z% c #E8E9F1", -"A% c #E7E8F0", -"B% c #737477", -"C% c #E6E7ED", -"D% c #747480", -"E% c #62626C", -"F% c #878898", -"G% c #858793", -"H% c #595A65", -"I% c #666875", -"J% c #444550", -"K% c #43454F", -"L% c #545560", -"M% c #E6E6ED", -"N% c #9192A0", -"O% c #2E2E33", -"P% c #676772", -"Q% c #8D8E9A", -"R% c #2A2B2D", -"S% c #3C3D43", -"T% c #E5E5ED", -"U% c #9899A8", -"V% c #828390", -"W% c #0D0D0D", -"X% c #9A9BAC", -"Y% c #898B99", -"Z% c #7F8190", -"`% c #8A8B97", -" & c #545561", -".& c #2A2A31", -"+& c #27272A", -"@& c #3B3C42", -"#& c #E4E5ED", -"$& c #9495A3", -"%& c #858593", -"&& c #7F818D", -"*& c #4C4E59", -"=& c #5D5F69", -"-& c #E3E5ED", -";& c #82818F", -">& c #7B7781", -",& c #747278", -"'& c #85848C", -")& c #3E3F49", -"!& c #E3E4ED", -"~& c #8B899B", -"{& c #8F8A9B", -"]& c #888393", -"^& c #807A87", -"/& c #7F7985", -"(& c #7F7B85", -"_& c #9A919A", -":& c #727179", -"<& c #52545F", -"[& c #E2E3ED", -"}& c #7D7F8B", -"|& c #908DA3", -"1& c #8A8494", -"2& c #A8A5B7", -"3& c #B3ADBA", -"4& c #7F7B80", -"5& c #575A62", -"6& c #5D5E66", -"7& c #726E79", -"8& c #686870", -"9& c #7A7C89", -"0& c #1F2025", -"a& c #E1E3EC", -"b& c #828592", -"c& c #878796", -"d& c #9B91A6", -"e& c #827985", -"f& c #797381", -"g& c #4F4E54", -"h& c #46484D", -"i& c #8D858D", -"j& c #6B676E", -"k& c #60616A", -"l& c #72717B", -"m& c #696B77", -"n& c #6E717F", -"o& c #3D3E44", -"p& c #E0E1EB", -"q& c #7B7E8B", -"r& c #A29CAF", -"s& c #918895", -"t& c #87808D", -"u& c #5D5A64", -"v& c #3D3E43", -"w& c #48494F", -"x& c #5C5E66", -"y& c #706E78", -"z& c #67656C", -"A& c #62626B", -"B& c #E0E1EA", -"C& c #858694", -"D& c #ADA4B4", -"E& c #7B757B", -"F& c #898390", -"G& c #494A50", -"H& c #3E3E43", -"I& c #52535A", -"J& c #6A6B75", -"K& c #70727E", -"L& c #7B7883", -"M& c #666771", -"N& c #71717E", -"O& c #55565D", -"P& c #61646E", -"Q& c #E0E0EA", -"R& c #80828F", -"S& c #9D9BAA", -"T& c #9B929D", -"U& c #908892", -"V& c #737079", -"W& c #3E4045", -"X& c #46464C", -"Y& c #5D5E67", -"Z& c #6F707C", -"`& c #6E717D", -" * c #7E7C8D", -".* c #777481", -"+* c #777584", -"@* c #4E4F55", -"#* c #626570", -"$* c #DFDFE9", -"%* c #848593", -"&* c #A9A3AF", -"** c #8C848C", -"=* c #9A949F", -"-* c #505057", -";* c #404045", -">* c #505158", -",* c #686974", -"'* c #727481", -")* c #737682", -"!* c #988FA4", -"~* c #7A7484", -"{* c #6B6873", -"]* c #44454B", -"^* c #45474C", -"/* c #585A62", -"(* c #666975", -"_* c #D4D5DE", -":* c #8B8D9B", -"<* c #8F8F9C", -"[* c #A69EA6", -"}* c #9C949C", -"|* c #827F88", -"1* c #424449", -"2* c #6E707C", -"3* c #817F8D", -"4* c #958D9E", -"5* c #7E7787", -"6* c #615F69", -"7* c #3E3F45", -"8* c #44464C", -"9* c #595A63", -"0* c #666977", -"a* c #C2C3CA", -"b* c #4F505D", -"c* c #8B8E9D", -"d* c #B3A8B0", -"e* c #99929A", -"f* c #606068", -"g* c #414248", -"h* c #4D4F55", -"i* c #656670", -"j* c #727581", -"k* c #767885", -"l* c #98919E", -"m* c #948C9A", -"n* c #73707B", -"o* c #3F4146", -"p* c #5F616B", -"q* c #666874", -"r* c #DEDFE7", -"s* c #81828D", -"t* c #535561", -"u* c #89838F", -"v* c #7E7377", -"w* c #484A51", -"x* c #6D6E7A", -"y* c #787883", -"z* c #A9A0AD", -"A* c #918B97", -"B* c #5B5C63", -"C* c #414147", -"D* c #45464D", -"E* c #DBDDE6", -"F* c #73747F", -"G* c #535661", -"H* c #978A95", -"I* c #6D686C", -"J* c #63646E", -"K* c #767682", -"L* c #958F9A", -"M* c #AAA3AE", -"N* c #736F79", -"O* c #4C4D54", -"P* c #404147", -"Q* c #60626C", -"R* c #676A76", -"S* c #DBDCE6", -"T* c #7B7C87", -"U* c #978C92", -"V* c #7A757B", -"W* c #BAB3BF", -"X* c #928D97", -"Y* c #5A5A62", -"Z* c #43454A", -"`* c #45474D", -" = c #595B63", -".= c #656873", -"+= c #DADCE5", -"@= c #7D7E8C", -"#= c #383943", -"$= c #777988", -"%= c #51505A", -"&= c #B2A5AB", -"*= c #7A7982", -"== c #4D4E53", -"-= c #323438", -";= c #5C5E68", -">= c #565862", -",= c #454751", -"'= c #2E3036", -")= c #DADBE4", -"!= c #23242A", -"~= c #44444D", -"{= c #606169", -"]= c #2A2B2F", -"^= c #17171B", -"/= c #323339", -"(= c #50535D", -"_= c #24262A", -":= c #0C0D0E", -"<= c #50535E", -"[= c #2A2C32", -"}= c #474953", -"|= c #121315", -"1= c #DADAE3", -"2= c #797B88", -"3= c #1A1B1F", -"4= c #797A85", -"5= c #393A46", -"6= c #53555F", -"7= c #1F2024", -"8= c #121214", -"9= c #51535E", -"0= c #33343B", -"a= c #121215", -"b= c #4D505A", -"c= c #34363D", -"d= c #777884", -"e= c #757681", -"f= c #797C89", -"g= c #4C4E5A", -"h= c #5F626E", -"i= c #5A5D68", -"j= c #5E616D", -"k= c #4E515A", -"l= c #626573", -"m= c #595C68", -"n= c #555864", -"o= c #555863", -"p= c #43454E", -"q= c #515460", -"r= c #0D0E10", -"s= c #939395", -"t= c #1A1A1E", -"u= c #19191E", -"v= c #18181C", -"w= c #0E0E11", -"x= c #0F0F12", -"y= c #141518", -"z= c #121417", -"A= c #111316", -"B= c #0D0E11", -" ", -" . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / / ( _ : @ < $ % [ } | 1 ; 2 , ' ) ! ~ 3 4 ] 5 / 6 7 ", -" : 8 9 0 a b c d e f g h i j k l m n o p q r s t u u 0 v w x y z A B h C D E F G H I J K L M 7 ", -" N 9 O P 0 a w x d z A B h Q R E l G H o p K S T U O V W v a X y d A f Y C Z ` F l ...+.K @.7 ", -" < #.P #.x $.%.&.*.=.-.;.>.,.'.).!.~.{.].K L s ^.u V W /.w x x (._.:.<.[.[.}.R G H |.p K q M 7 ", -" # a 0 w 1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.K g.h.i.W W v w j.k.l.m.n.o.p.p.q.r.s.t.o p q q g.M 7 ", -" % X a x u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.f.L J.K.L.v v M.x N.O. P. Q.R.S.T.U.V.W.7 ", -" [ y w d X.Y.Z.`. +.+++@+#+$+%+&+*+=+-+;+g.>+K.,+w a x z '+ )+!+~+{+]+q.^+/+(+7 ", -" * d x _+:+<+[+}+|+ 1+2+3+4+5+*+6+7+8+9+0+a+b+X X x c+ d+7 e+f+g+ h+0+i+7 ", -" | A d j+:+k+l+m+ n+o+p+q+r+*+s+t+u+v+w+x+y+y y z+A+ d+7 e+f+B+C+V.D+E+7 ", -" 1 f e F+G+H+I+J+ K+L+M+N+O+P+5+Q+R+S+T+U+V+W+X+z N.Y+ d+7 e+e+Z+`+ @.@+@7 ", -" ; g @@h #@$@%@&@ *@O+7 =@O+-@;@>@,@'@)@!@~@{@]@A y ^@ /@7 e+e+7 (@D+_@:@7 ", -" > C B <@[@$@}@|@1@2@3@Z+7 o+4@5@6@7@8@9@0@a@b@c@B z d@ e@f@g@g@h@i@7 e+e+7 j@k@l@m@7 ", -" , Z h j n@o@p@q@L+r@f+e+s@t@u@v@6@w@x@y@z@A@B@C@g A D@ E@e+F@F@F@O+e+e+e+7 (@G@H@I@7 ", -" ' ` i J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@ #.#+#@#h ## $#7 e+e+e+e+e+e+e+7 %#G@&#*#7 ", -" ) k R t.=#-#;#>#,#'#)#!#~#{#]#^#/#(#_#:#`@<#[#}#D R |#1# $#7 e+e+e+e+e+e+f+2#3#4#5#6#7 ", -" ! 7#E 8#9#0#a#b#c#d#e#f#f#g#h#i#j#k#l#m#n#o#p#q#r#` s#[. $#7 e+e+e+e+f+e+f+g+ t#u#v#7 ", -" ~ .l w#x#U.y#z#A#B#C#D#E#F#G#H#I#J#K#L#o#M#N#O#F P#Q#R#S#T#U#V#W#7 e+e+e+e+e+7 X# Y#Z#`#7 ", -" { ..m $+.K L .$+$@$#$$$%$&$*$=$-$;$o#>$,$'$)$!$G E ~$ {$]$7 f+e+e+e+f+7 7 ^$/$ 5#($_$7 ", -" ] +...:$K L 9+<$[$}$|$1$2$3$4$5$6$7$8$L#9$0$a$b$H c$d$ e$]$f$g$g$2#h$i$ j$k$l$7 ", -" m$K o K L g.n$0+o$p$5#q$r$s$t$u$o#>$($k$0$v$w$x$o H y$z$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$'$O$P$7 ", -" / q p q r V.J.>+Q$w+V+~@R$&# #<#o#M#'$0$v$S$T$U$p +.K L g.V.V$0+w+.@_@a@A@#u#o#($k$W$S$X$7 ", -" { Y$Z$`$ %.%+%J.V$@%w+#%$%a@A@ #<#o#%%9$0$&%*%=%....+.K -%;%V.>%0+,%.@'%a@)%Y#5#j$M#'$!%W$~%7 ", -" {%]%^%]%/%(%(%_%_%:%:%<%<%[%}%|%1%2%3%4%5%6%7%{+[%[%8%|%9%2%3%4%0%6%a%b%c%d%6%e%e%f%g%h%i%j%7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%l%m%n%o%p%q%r%s%t%u%# v%[ $ ]@w%x%y%> z%A%) B%7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%C%u u 0 w D%E%w z A B h C R F%G%H%F I%J%K%L%M 7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%M%U O V N%O%P%v y d A f Y C Z ` Q%J%k W+ R%S%7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%T%u V U%w V%W%X%e f B Y%i R r#l Z%`% &`$.&+&@&7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%#&W W a $&%&:$d f B Y%i R r#l m n Z$&&*&p =&W.7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%-&v v w x d e f B Y%i R r#l s#%&;&>&,&'&)&L W.7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%!&w a x d e f B Y%i R E G ~&{&]&^&/&(&_&:&<&i+7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%[&X X d e f B Y%i R E }&|&1&2&3&4&5&6&7&8&9&0&7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%a&y y e f B Y%i R b&c&d&e&f&g&h&i&j&k&l&m&n&o&7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%p&z z f B Y%i R q&r&s&t&u&v&w&x&y&z&A&P%I%w++@7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%B&A A B Y%i ` C&D&E&F&G&H&I&J&K&L&M&N&O&P&#%:@7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%Q&B f Y%i R&S&T&U&V&W&X&Y&Z&`& *.*+*@*s.#*~@m@7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%$*g Y i %*&***=*-*;*>*,*'*)*!*~*{*]*^*/*(*H@I@7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%_*:*i <*[*}*|*1*]*E$2*>+3*4*5*6*7*8*9*q$0*&#*#7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%a*b*c*d*e*f*g*h*i*j*k*l*m*n*G&o*s.p*q*&# #5#6#7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%r*s*t*u*v*w*O&x*k*y*z*A*B*C*D*9*q$t#&# #<#u#v#7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%E*s#F*G*H*I*J*K*L*M*N*O*P*~$Q*R*H@p$ #<#o#o#`#7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%S* $J T*)&U*V*W*X*Y*Z*`* =.=t#t#&##o#M#($_$7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%+=@=#=$=y#%=&=*===-=D*;=>=_@$%A@4#,=*&o#,$'$'=7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%)=K i%!=`$<.~={=s.r.]=E+^=B$/=(=_=:=I@<=[=}=|=7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%1=2=c% 3=9+4=5=g.6=7=8=9=I@K.'=N$0=a=b=c=a$/$7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%E*Z$d=y#e=f=h+Z&g=J.h=i=w+j=k=l=m=n=o=o=p=q=r=7 ", -" k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%k%s=t=3=^%u=/%v=v=w=x=_%:%<%<%y=[%z=|%A=2%3%4%B=7 ", -" 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 "}; diff --git a/WPrefs.app/xpm/drawer.xpm b/WPrefs.app/xpm/drawer.xpm new file mode 100644 index 00000000..f207fcb0 --- /dev/null +++ b/WPrefs.app/xpm/drawer.xpm @@ -0,0 +1,1149 @@ +/* XPM */ +static char * drawer_xpm[] = { +"48 48 1098 2", +" c None", +". c #DEDFEE", +"+ c #9091A0", +"@ c #9293A2", +"# c #7D7E88", +"$ c #B2B2B2", +"% c #363838", +"& c #6D6E6D", +"* c #1D201F", +"= c #191D1B", +"- c #646665", +"; c #565857", +"> c #1E2220", +", c #3A3E3D", +"' c #565958", +") c #464847", +"! c #343636", +"~ c #3A3C3B", +"{ c #91928F", +"] c #707281", +"^ c #707380", +"/ c #727482", +"( c #303139", +"_ c #DCDDEC", +": c #8E8F9E", +"< c #7B7C86", +"[ c #B6B6B6", +"} c #363A39", +"| c #727574", +"1 c #2B2F2D", +"2 c #2F3533", +"3 c #616664", +"4 c #454B49", +"5 c #2B312F", +"6 c #575C5A", +"7 c #545857", +"8 c #464948", +"9 c #353837", +"0 c #3D403F", +"a c #8F8F8D", +"b c #6D707F", +"c c #6F717F", +"d c #6F727F", +"e c #2F3138", +"f c #DADBEA", +"g c #8C8D9C", +"h c #777983", +"i c #BBBBBB", +"j c #101414", +"k c #252B29", +"l c #373D3A", +"m c #4E5553", +"n c #595F5E", +"o c #3B4340", +"p c #414845", +"q c #5C6260", +"r c #505553", +"s c #424746", +"t c #333736", +"u c #3F4241", +"v c #8D8E8B", +"w c #6C6E7D", +"x c #6C6F7C", +"y c #6D707E", +"z c #2E2F37", +"A c #D8D9E8", +"B c #8A8C9A", +"C c #757780", +"D c #BEBEBE", +"E c #171C1B", +"F c #2E3533", +"G c #464D4B", +"H c #606865", +"I c #505856", +"J c #404A47", +"K c #58615E", +"L c #545C5A", +"M c #49514E", +"N c #3C4340", +"O c #424645", +"P c #8B8C88", +"Q c #696C7B", +"R c #6B6D7B", +"S c #6B6E7B", +"T c #2D2E36", +"U c #D6D8E6", +"V c #888998", +"W c #8A8B9A", +"X c #72737D", +"Y c #C3C3C3", +"Z c #1A211F", +"` c #343C39", +" . c #3B4441", +".. c #4A5451", +"+. c #4C5653", +"@. c #4F5B57", +"#. c #56605C", +"$. c #4D5854", +"%. c #434D49", +"&. c #39423F", +"*. c #333A38", +"=. c #474C4B", +"-. c #888987", +";. c #686B79", +">. c #696B79", +",. c #6A6D7A", +"'. c #2B2D35", +"). c #D4D6E4", +"!. c #868896", +"~. c #6F717A", +"{. c #C8C8C8", +"]. c #1D2321", +"^. c #38403E", +"/. c #404946", +"(. c #48524F", +"_. c #4E5A56", +":. c #55625E", +"<. c #53605B", +"[. c #4C5854", +"}. c #45504C", +"|. c #3D4643", +"1. c #363D3B", +"2. c #4C504F", +"3. c #878885", +"4. c #666977", +"5. c #676A77", +"6. c #676A78", +"7. c #2A2C34", +"8. c #D3D4E3", +"9. c #848694", +"0. c #868796", +"a. c #6C6E77", +"b. c #CDCDCD", +"c. c #1C2321", +"d. c #38413E", +"e. c #48534F", +"f. c #505C58", +"g. c #576460", +"h. c #4D5A55", +"i. c #46504D", +"j. c #3E4744", +"k. c #4F5352", +"l. c #848582", +"m. c #646775", +"n. c #656875", +"o. c #666976", +"p. c #292B33", +"q. c #D0D2E0", +"r. c #828492", +"s. c #696B75", +"t. c #D3D3D3", +"u. c #0A100E", +"v. c #232A28", +"w. c #29312E", +"x. c #2F3835", +"y. c #333E3B", +"z. c #36413E", +"A. c #36403E", +"B. c #323C39", +"C. c #2D3633", +"D. c #272F2D", +"E. c #212826", +"F. c #444848", +"G. c #828381", +"H. c #626574", +"I. c #636673", +"J. c #636674", +"K. c #282A31", +"L. c #CFD0DF", +"M. c #808290", +"N. c #828392", +"O. c #62636D", +"P. c #D8D8D8", +"Q. c #D5D6D6", +"R. c #D7D7D7", +"S. c #D7D8D7", +"T. c #D7D8D8", +"U. c #D8D9D8", +"V. c #DFDFDF", +"W. c #858684", +"X. c #555865", +"Y. c #616471", +"Z. c #626572", +"`. c #272930", +" + c #CCCEDC", +".+ c #7F808F", +"++ c #686A76", +"@+ c #2E3032", +"#+ c #2B2C2F", +"$+ c #2A2B2E", +"%+ c #292B2E", +"&+ c #292A2D", +"*+ c #282A2D", +"=+ c #28292C", +"-+ c #27292B", +";+ c #26282B", +">+ c #26272A", +",+ c #252729", +"'+ c #242629", +")+ c #4D4F5A", +"!+ c #5F626F", +"~+ c #5F6370", +"{+ c #26282F", +"]+ c #CBCCDB", +"^+ c #7C7E8C", +"/+ c #7F818F", +"(+ c #7A7B89", +"_+ c #727480", +":+ c #6F717E", +"<+ c #6D6F7C", +"[+ c #6C6E7B", +"}+ c #6A6D78", +"|+ c #686A77", +"1+ c #666975", +"2+ c #656773", +"3+ c #61646F", +"4+ c #5F616E", +"5+ c #5D606C", +"6+ c #5B5E6B", +"7+ c #5A5D69", +"8+ c #5D606D", +"9+ c #5D616D", +"0+ c #5E616E", +"a+ c #25272E", +"b+ c #C8CAD8", +"c+ c #7B7D8B", +"d+ c #7A7C8A", +"e+ c #787A88", +"f+ c #767886", +"g+ c #747784", +"h+ c #6E707E", +"i+ c #686B78", +"j+ c #646774", +"k+ c #5E626E", +"l+ c #5C5F6C", +"m+ c #23252D", +"n+ c #C7C9D7", +"o+ c #777987", +"p+ c #737583", +"q+ c #6C707C", +"r+ c #696C79", +"s+ c #595D69", +"t+ c #5A5D6A", +"u+ c #22242C", +"v+ c #C0C2D0", +"w+ c #747684", +"x+ c #757785", +"y+ c #717481", +"z+ c #707280", +"A+ c #6D707D", +"B+ c #6C6E7C", +"C+ c #656876", +"D+ c #606370", +"E+ c #5A5E6A", +"F+ c #585B68", +"G+ c #565A66", +"H+ c #545864", +"I+ c #545865", +"J+ c #202229", +"K+ c #7C7D84", +"L+ c #6B6C74", +"M+ c #696A73", +"N+ c #696973", +"O+ c #676871", +"P+ c #666770", +"Q+ c #65666F", +"R+ c #64656E", +"S+ c #62636C", +"T+ c #61626B", +"U+ c #60616A", +"V+ c #5F6069", +"W+ c #5D5F67", +"X+ c #5C5D66", +"Y+ c #5B5D65", +"Z+ c #5A5B64", +"`+ c #595A63", +" @ c #575961", +".@ c #565860", +"+@ c #565861", +"@@ c #2B2D31", +"#@ c #A5A7B5", +"$@ c #A3A5B3", +"%@ c #A2A4B2", +"&@ c #464851", +"*@ c #F7F7FF", +"=@ c #C3C4D2", +"-@ c #C4C4D3", +";@ c #C2C3D2", +">@ c #C0C1D0", +",@ c #BEBFCE", +"'@ c #BCBDCC", +")@ c #BABBCA", +"!@ c #B8B9C8", +"~@ c #B7B8C7", +"{@ c #B4B5C4", +"]@ c #B3B4C3", +"^@ c #B0B2C0", +"/@ c #AFB0BF", +"(@ c #ACAEBC", +"_@ c #ABACBB", +":@ c #A8ABB8", +"<@ c #A7A8B7", +"[@ c #3A3B44", +"}@ c #FFFFFF", +"|@ c #C8C8D7", +"1@ c #C6C7D6", +"2@ c #C4C5D4", +"3@ c #C2C2D2", +"4@ c #BEBECE", +"5@ c #BABBCB", +"6@ c #B6B8C7", +"7@ c #B2B4C3", +"8@ c #B0B1C0", +"9@ c #AEB0BF", +"0@ c #AAACBB", +"a@ c #A8AAB8", +"b@ c #A7A9B7", +"c@ c #A8AAB9", +"d@ c #404149", +"e@ c #7D7F8D", +"f@ c #797B89", +"g@ c #373841", +"h@ c #F4F4FF", +"i@ c #9898A9", +"j@ c #9B9CAB", +"k@ c #9D99AE", +"l@ c #9B97AC", +"m@ c #9995AA", +"n@ c #9793A8", +"o@ c #9591A6", +"p@ c #9390A4", +"q@ c #918DA2", +"r@ c #8F8CA0", +"s@ c #8D8A9E", +"t@ c #8B889C", +"u@ c #89869A", +"v@ c #878498", +"w@ c #858396", +"x@ c #838094", +"y@ c #807F92", +"z@ c #7F7D90", +"A@ c #7A7C8B", +"B@ c #2F3038", +"C@ c #9999AA", +"D@ c #999AA9", +"E@ c #9798A7", +"F@ c #9596A5", +"G@ c #9394A3", +"H@ c #9193A1", +"I@ c #848594", +"J@ c #808190", +"K@ c #7E808E", +"L@ c #363740", +"M@ c #F2F2FF", +"N@ c #9999A9", +"O@ c #9C9CAC", +"P@ c #5EAA64", +"Q@ c #61A768", +"R@ c #60A566", +"S@ c #60A364", +"T@ c #5FA163", +"U@ c #5F9F62", +"V@ c #5E9E61", +"W@ c #5D9C5F", +"X@ c #5D9B5E", +"Y@ c #5C995D", +"Z@ c #5C985C", +"`@ c #5B955A", +" # c #5B9459", +".# c #5A9258", +"+# c #589255", +"@# c #758081", +"## c #2E3038", +"$# c #9797A7", +"%# c #9495A4", +"&# c #9192A1", +"*# c #8D8E9D", +"=# c #898B99", +"-# c #858795", +";# c #818391", +"># c #36373F", +",# c #35373F", +"'# c #F0F1FF", +")# c #9A9AAA", +"!# c #729D78", +"~# c #605B65", +"{# c #615D65", +"]# c #75717E", +"^# c #7E8B86", +"/# c #7A8883", +"(# c #807D8C", +"_# c #93909D", +":# c #9794A0", +"<# c #7C7987", +"[# c #777683", +"}# c #618465", +"|# c #747280", +"1# c #716F7D", +"2# c #706D7A", +"3# c #65736A", +"4# c #707D7C", +"5# c #787A89", +"6# c #F0F0FF", +"7# c #9898A8", +"8# c #9697A6", +"9# c #9595A5", +"0# c #8D8FA2", +"a# c #8A8EA2", +"b# c #888CA0", +"c# c #878A9F", +"d# c #85889D", +"e# c #83869B", +"f# c #808498", +"g# c #7F8296", +"h# c #7C8094", +"i# c #7A7E92", +"j# c #787C90", +"k# c #797B8A", +"l# c #34363E", +"m# c #757885", +"n# c #34353F", +"o# c #EEEFFE", +"p# c #9899A8", +"q# c #729F79", +"r# c #212023", +"s# c #E9E9ED", +"t# c #333336", +"u# c #82938B", +"v# c #77887E", +"w# c #B9BABF", +"x# c #BDBEC5", +"y# c #BCBDC5", +"z# c #BCBDC1", +"A# c #888990", +"B# c #5D805F", +"C# c #70727B", +"D# c #6E6F78", +"E# c #6C6D77", +"F# c #617266", +"G# c #6F7C7B", +"H# c #767986", +"I# c #2C2D36", +"J# c #9696A6", +"K# c #8D8FA3", +"L# c #A89560", +"M# c #B29642", +"N# c #AD903E", +"O# c #A88C39", +"P# c #A58936", +"Q# c #A98D39", +"R# c #A98D3A", +"S# c #A78B38", +"T# c #A68A36", +"U# c #74788D", +"V# c #777A87", +"W# c #34353D", +"X# c #33343D", +"Y# c #ECECFC", +"Z# c #6C9871", +"`# c #7B7B85", +" $ c #4E4E51", +".$ c #A3A3A5", +"+$ c #3B433B", +"@$ c #707972", +"#$ c #38383A", +"$$ c #93939A", +"%$ c #BBBCC4", +"&$ c #B9BAC2", +"*$ c #C1C2C8", +"=$ c #AEACB5", +"-$ c #878990", +";$ c #6D6D77", +">$ c #686972", +",$ c #5F7064", +"'$ c #6D7A78", +")$ c #747685", +"!$ c #2B2C34", +"~$ c #9294A2", +"{$ c #AC9B72", +"]$ c #C09F40", +"^$ c #BC9D41", +"/$ c #B89B41", +"($ c #B5973E", +"_$ c #B4963C", +":$ c #B1933A", +"<$ c #B3943C", +"[$ c #B2953C", +"}$ c #B3953C", +"|$ c #B1923A", +"1$ c #977F34", +"2$ c #73778B", +"3$ c #757786", +"4$ c #32333C", +"5$ c #EAEBFA", +"6$ c #9191A1", +"7$ c #69966F", +"8$ c #85858F", +"9$ c #95969E", +"0$ c #1C1C1C", +"a$ c #AAAAAC", +"b$ c #101010", +"c$ c #030303", +"d$ c #7F8086", +"e$ c #B9BAC1", +"f$ c #B8B9C0", +"g$ c #B7B8C0", +"h$ c #B5B6BE", +"i$ c #B2B2B7", +"j$ c #7A7B83", +"k$ c #596B5F", +"l$ c #6C7877", +"m$ c #727582", +"n$ c #2A2B33", +"o$ c #9292A2", +"p$ c #8E8F9F", +"q$ c #D8BB65", +"r$ c #CEB25B", +"s$ c #CCB059", +"t$ c #CBAF59", +"u$ c #C9AC57", +"v$ c #C7AB57", +"w$ c #C5A955", +"x$ c #C8AC57", +"y$ c #C1A861", +"z$ c #7F6A29", +"A$ c #947C2F", +"B$ c #717689", +"C$ c #737683", +"D$ c #31333B", +"E$ c #717381", +"F$ c #30323A", +"G$ c #E8E8F8", +"H$ c #8F909F", +"I$ c #9393A3", +"J$ c #5E9860", +"K$ c #909A97", +"L$ c #343335", +"M$ c #000000", +"N$ c #141415", +"O$ c #959597", +"P$ c #6C6C71", +"Q$ c #BEBFC8", +"R$ c #B8B9C1", +"S$ c #B6B7BF", +"T$ c #B4B5BC", +"U$ c #B2B3BB", +"V$ c #BFC0C6", +"W$ c #8B9E8A", +"X$ c #6A7875", +"Y$ c #282A32", +"Z$ c #8C8E9E", +"`$ c #CCAE53", +" % c #B99D43", +".% c #B89C42", +"+% c #BA9D43", +"@% c #B99C43", +"#% c #B59940", +"$% c #B3973E", +"%% c #B4983F", +"&% c #B2973D", +"*% c #A18735", +"=% c #786723", +"-% c #907A2A", +";% c #707388", +">% c #717382", +",% c #2F3139", +"'% c #E6E7F6", +")% c #76AA77", +"!% c #252A24", +"~% c #131313", +"{% c #ACACAF", +"]% c #87888D", +"^% c #BFC0C8", +"/% c #BABBC4", +"(% c #B4B5BD", +"_% c #66666A", +":% c #5C6D59", +"<% c #6B7776", +"[% c #6E717E", +"}% c #272931", +"|% c #8A8C9C", +"1% c #CBAC52", +"2% c #BB9D44", +"3% c #A3882B", +"4% c #AA8E34", +"5% c #AA8F34", +"6% c #AC9139", +"7% c #B19747", +"8% c #B1963C", +"9% c #B2973C", +"0% c #9C832E", +"a% c #75641D", +"b% c #917A2B", +"c% c #6D7285", +"d% c #2E2F38", +"e% c #E4E5F5", +"f% c #8B8C9B", +"g% c #8F8F9F", +"h% c #5F885E", +"i% c #050405", +"j% c #0F0F0F", +"k% c #88888A", +"l% c #606164", +"m% c #7B7B80", +"n% c #B3B4BB", +"o% c #68686C", +"p% c #788878", +"q% c #667271", +"r% c #6D6F7D", +"s% c #262730", +"t% c #E4E5F4", +"u% c #818290", +"v% c #44454B", +"w% c #888A99", +"x% c #CAAC51", +"y% c #AA8F35", +"z% c #B89E45", +"A% c #E0C874", +"B% c #B79B45", +"C% c #B2984A", +"D% c #B0953B", +"E% c #AB9036", +"F% c #75641C", +"G% c #8C7525", +"H% c #6C7084", +"I% c #6A6C7A", +"J% c #2C2E37", +"K% c #E2E3F2", +"L% c #497246", +"M% c #64646B", +"N% c #656568", +"O% c #D3D4D7", +"P% c #D6D6D9", +"Q% c #7B7B7F", +"R% c #9E9FA5", +"S% c #494A4C", +"T% c #5B6A59", +"U% c #687372", +"V% c #25272F", +"W% c #E2E3F3", +"X% c #676875", +"Y% c #0E0E10", +"Z% c #2A2B2D", +"`% c #868897", +" & c #A88D33", +".& c #BCA049", +"+& c #F3D890", +"@& c #927D3E", +"#& c #AB9246", +"$& c #AD9238", +"%& c #AC9037", +"&& c #9B822D", +"*& c #716016", +"=& c #88731F", +"-& c #6A6E82", +";& c #E1E2F1", +">& c #878897", +",& c #8B8B9B", +"'& c #588056", +")& c #050506", +"!& c #8F9097", +"~& c #ACADB4", +"{& c #A8A9AC", +"]& c #DFDFE2", +"^& c #E0E0E3", +"/& c #E5E5E8", +"(& c #626264", +"_& c #606D5D", +":& c #64706F", +"<& c #24252D", +"[& c #E0E1F1", +"}& c #7C7D8B", +"|& c #1B1B20", +"1& c #2B2B2D", +"2& c #848696", +"3& c #CAAC52", +"4& c #B69A41", +"5& c #A98E34", +"6& c #B09643", +"7& c #937D34", +"8& c #877336", +"9& c #AC944E", +"0& c #AB8F35", +"a& c #9B812D", +"b& c #705F13", +"c& c #867018", +"d& c #686C81", +"e& c #696C7A", +"f& c #749875", +"g& c #070507", +"h& c #1E1E1F", +"i& c #999AA0", +"j& c #94949A", +"k& c #7D7E7F", +"l& c #E9EAEC", +"m& c #DFDFE3", +"n& c #DEDFE1", +"o& c #626364", +"p& c #121013", +"q& c #7A867D", +"r& c #616C6B", +"s& c #23242C", +"t& c #4D4D56", +"u& c #828493", +"v& c #C8AB51", +"w& c #B69A40", +"x& c #B39842", +"y& c #B29741", +"z& c #B09540", +"A& c #AD923E", +"B& c #AE9440", +"C& c #9E8430", +"D& c #6F5F12", +"E& c #867117", +"F& c #666A7F", +"G& c #292A33", +"H& c #DDDEED", +"I& c #838593", +"J& c #878797", +"K& c #499D41", +"L& c #789275", +"M& c #080809", +"N& c #98999E", +"O& c #7E7E84", +"P& c #A9AAAC", +"Q& c #DFE0E2", +"R& c #DEDEE1", +"S& c #E1E2E5", +"T& c #5D5C5F", +"U& c #768F6E", +"V& c #447933", +"W& c #5F6D67", +"X& c #21232B", +"Y& c #DCDDED", +"Z& c #818292", +"`& c #C4A74F", +" * c #AF933C", +".* c #B0943D", +"+* c #AC923A", +"@* c #AA8F37", +"#* c #A68B34", +"$* c #A58A32", +"%* c #726017", +"&* c #8A741F", +"** c #64687C", +"=* c #272932", +"-* c #DADCEA", +";* c #848695", +">* c #5F8362", +",* c #7D7C88", +"'* c #747679", +")* c #161615", +"!* c #111111", +"~* c #252627", +"{* c #0E0D0E", +"]* c #B1B1B4", +"^* c #E4E5E8", +"/* c #DDDEE0", +"(* c #DADBDD", +"_* c #66666B", +":* c #424E46", +"<* c #5F6969", +"[* c #626573", +"}* c #20222A", +"|* c #818291", +"1* c #7F8190", +"2* c #816925", +"3* c #806926", +"4* c #806922", +"5* c #7F6823", +"6* c #79611F", +"7* c #76601C", +"8* c #745E1B", +"9* c #735D17", +"0* c #8A731A", +"a* c #61667A", +"b* c #262931", +"c* c #D9DAE9", +"d* c #838393", +"e* c #5D835E", +"f* c #8C8D94", +"g* c #6F7072", +"h* c #10100F", +"i* c #B4B4B6", +"j* c #DDDEE1", +"k* c #DDDDE0", +"l* c #E3E4E7", +"m* c #3C4A39", +"n* c #5C6766", +"o* c #1F2129", +"p* c #D8D9E9", +"q* c #7D7F8E", +"r* c #B49239", +"s* c #B08F3B", +"t* c #918466", +"u* c #9A854F", +"v* c #A78834", +"w* c #A48533", +"x* c #9F812C", +"y* c #937B34", +"z* c #616574", +"A* c #616472", +"B* c #7E7F8E", +"C* c #808291", +"D* c #5C815D", +"E* c #65726B", +"F* c #7E8C84", +"G* c #88898F", +"H* c #262626", +"I* c #7B7C80", +"J* c #797B82", +"K* c #45603F", +"L* c #B7B8BA", +"M* c #E6E7EA", +"N* c #EAEBEE", +"O* c #3D4938", +"P* c #5B6565", +"Q* c #1E2027", +"R* c #96855C", +"S* c #767989", +"T* c #767885", +"U* c #707587", +"V* c #7A7777", +"W* c #6F7281", +"X* c #7B756A", +"Y* c #6C6F7D", +"Z* c #26272F", +"`* c #24262E", +" = c #D5D6E5", +".= c #5A805B", +"+= c #666871", +"@= c #5F6D65", +"#= c #5D6A62", +"$= c #5F626B", +"%= c #77797F", +"&= c #7D7E84", +"*= c #595B64", +"== c #555860", +"-= c #4E694B", +";= c #41434A", +">= c #646565", +",= c #353534", +"'= c #394639", +")= c #596463", +"!= c #1D1F26", +"~= c #D4D5E5", +"{= c #777988", +"]= c #6B6E7C", +"^= c #5D606E", +"/= c #5B5F6B", +"(= c #22252C", +"_= c #D2D4E2", +":= c #7D7E8D", +"<= c #578455", +"[= c #637667", +"}= c #617566", +"|= c #5F7364", +"1= c #5A755B", +"2= c #587459", +"3= c #5A6C5E", +"4= c #56685A", +"5= c #546658", +"6= c #536456", +"7= c #4D6F47", +"8= c #516254", +"9= c #4D5D50", +"0= c #4F5E52", +"a= c #4A6246", +"b= c #586262", +"c= c #1B1E25", +"d= c #5C606C", +"e= c #5B5F6C", +"f= c #585C68", +"g= c #21232C", +"h= c #D1D3E1", +"i= c #737D80", +"j= c #727C7F", +"k= c #707A7D", +"l= c #6F787C", +"m= c #6C7679", +"n= c #6B7478", +"o= c #697376", +"p= c #687174", +"q= c #656F72", +"r= c #646E70", +"s= c #626B6E", +"t= c #616A6D", +"u= c #5F686A", +"v= c #5D6669", +"w= c #5B6567", +"x= c #5A6265", +"y= c #595E68", +"z= c #1B1D24", +"A= c #D0D2E1", +"B= c #686C78", +"C= c #595D6A", +"D= c #565966", +"E= c #525663", +"F= c #737584", +"G= c #6F7180", +"H= c #6B6D7C", +"I= c #535663", +"J= c #191B23", +"K= c #C6C8D6", +"L= c #666876", +"M= c #5F6270", +"N= c #545764", +"O= c #525662", +"P= c #525562", +"Q= c #1F2229", +"R= c #16181C", +"S= c #16171C", +"T= c #15171B", +"U= c #09090C", +"V= c #37383D", +"W= c #212126", +"X= c #212227", +"Y= c #212226", +"Z= c #202126", +"`= c #1F2025", +" - c #1F1F24", +".- c #1E1F24", +"+- c #1D1E23", +"@- c #1D1D22", +"#- c #1C1D21", +"$- c #1B1C21", +"%- c #1A1C20", +"&- c #1A1B20", +"*- c #191A1F", +"=- c #191A1E", +"-- c #18191D", +";- c #17181D", +">- c #7D7D84", +",- c #6E6E76", +"'- c #6D6E76", +")- c #6C6C75", +"!- c #6A6B73", +"~- c #696972", +"{- c #676770", +"]- c #65666E", +"^- c #63646C", +"/- c #62636B", +"(- c #61626A", +"_- c #606169", +":- c #5F6068", +"<- c #5D5E67", +"[- c #5C5E66", +"}- c #5B5C64", +"|- c #5A5B63", +"1- c #2E2F33", +"2- c #F6F6FF", +"3- c #C7C7D6", +"4- c #C5C5D5", +"5- c #C3C3D3", +"6- c #C1C1D1", +"7- c #BFBFCF", +"8- c #BDBDCD", +"9- c #BBBCCB", +"0- c #B9BAC9", +"a- c #B6B7C7", +"b- c #B5B6C5", +"c- c #B1B2C1", +"d- c #ADAEBD", +"e- c #A9AAB9", +"f- c #A6A8B7", +"g- c #3F4049", +"h- c #E9EAF7", +"i- c #9494A4", +"j- c #8F919E", +"k- c #8E909C", +"l- c #8B8D9A", +"m- c #888A98", +"n- c #7B7D8C", +"o- c #E8E8F7", +"p- c #9495A3", +"q- c #8F90A1", +"r- c #8585A1", +"s- c #7675A2", +"t- c #726FA2", +"u- c #7675A0", +"v- c #81829A", +"w- c #E5E6F6", +"x- c #7574A4", +"y- c #605CA6", +"z- c #5955A9", +"A- c #5D59AB", +"B- c #5F5BAC", +"C- c #5955AA", +"D- c #514EA6", +"E- c #58569F", +"F- c #6E6E98", +"G- c #81838E", +"H- c #9394A2", +"I- c #6A67A6", +"J- c #5955A8", +"K- c #6360AD", +"L- c #6E6AB2", +"M- c #7571B6", +"N- c #7B78B9", +"O- c #A7A4D0", +"P- c #CECDE5", +"Q- c #D3D2E7", +"R- c #8B88C3", +"S- c #66659D", +"T- c #7C7E8B", +"U- c #E2E2F2", +"V- c #9495A2", +"W- c #6C6AA5", +"X- c #5652A8", +"Y- c #918EC5", +"Z- c #D4D3E8", +"`- c #D0CEE5", +" ; c #C5C3E0", +".; c #B5B4D7", +"+; c #A9A7D2", +"@; c #DEDDED", +"#; c #6B68B2", +"$; c #686797", +"%; c #32333B", +"&; c #E0E1F0", +"*; c #7F7EA3", +"=; c #5955A7", +"-; c #5C58A9", +";; c #6C69B2", +">; c #A3A1CE", +",; c #FEFEFE", +"'; c #FBFBFC", +"); c #E8E8F2", +"!; c #E6E6F1", +"~; c #F2F2F7", +"{; c #FFFFFE", +"]; c #615DAC", +"^; c #5854A7", +"/; c #747686", +"(; c #31323B", +"_; c #DEDEEE", +":; c #9192A2", +"<; c #6967A5", +"[; c #5D59AA", +"}; c #6F6BB4", +"|; c #8380BD", +"1; c #D9D8EA", +"2; c #F6F6F9", +"3; c #B1AED4", +"4; c #9D9ACA", +"5; c #8A86C1", +"6; c #7B77B9", +"7; c #6A66B0", +"8; c #5956A8", +"9; c #524FA6", +"0; c #636383", +"a; c #717380", +"b; c #8E8FA0", +"c; c #5D5AA6", +"d; c #5854A8", +"e; c #5B57A9", +"f; c #6A66B1", +"g; c #7875B8", +"h; c #8986C0", +"i; c #C5C3DF", +"j; c #F8F8FA", +"k; c #A4A1CE", +"l; c #8885BF", +"m; c #7975B7", +"n; c #6864AF", +"o; c #5451A3", +"p; c #494D85", +"q; c #35346B", +"r; c #747781", +"s; c #8C8D9E", +"t; c #5753A8", +"u; c #6764AF", +"v; c #A29FCE", +"w; c #D2D1E7", +"x; c #E3E2EF", +"y; c #E0DFED", +"z; c #EDEDF5", +"A; c #AAA8D2", +"B; c #6E6BB2", +"C; c #5653A6", +"D; c #49509D", +"E; c #383861", +"F; c #514D9E", +"G; c #6E707F", +"H; c #8A8B9C", +"I; c #5753A7", +"J; c #E5E5F0", +"K; c #ECECF5", +"L; c #B8B7DA", +"M; c #A5A2CF", +"N; c #9A98C9", +"O; c #8C89C3", +"P; c #625FAC", +"Q; c #6367AD", +"R; c #26275A", +"S; c #3D3B81", +"T; c #5753A9", +"U; c #6B6D7D", +" . + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( ", +" _ : + < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e ", +" f g : h i j k l m n o p q r s t u v w x y z ", +" A B g C D E F G H I J K L M N F O P Q R S T ", +" U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.,.'.", +" ).!.V ~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.", +" 8.9.0.a.b.c.d.J e.f.g.:.h.i.j.1.k.l.m.n.o.p.", +" q.r.9.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.", +" L.M.N.O.P.Q.R.S.T.P.U.U.P.T.R.R.V.W.X.Y.Z.`.", +" +.+M.++@+#+$+%+&+*+=+-+;+>+>+,+'+;+)+!+~+{+", +" ]+^+/+(+_+:+<+[+}+|+1+2+Z.3+4+5+6+7+8+9+0+a+", +" b+c+^+d+e+f+g+/ ^ h+x ,.i+o.j+Z.Y.k+8+6+l+m+", +" n+e+c+e+o+g+p+^ c q+R r+5.n.I.Y.!+9+6+s+t+u+", +" v+w+x+w+y+z+A+B+r+i+C+j+Z.D+0+l+E+F+G+H+I+J+", +" K+L+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+`+ @.@+@@@", +"#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@#@$@$@[@}@|@|@1@2@3@>@4@'@5@!@6@{@7@8@9@(@0@a@b@c@d@", +"e@d+f@g@h@i@j@k@l@m@n@o@p@q@r@s@t@u@v@w@x@y@z@A@d+B@h@C@j@D@E@F@G@H@+ : g W V 0.I@r.J@K@^+d+c+L@", +"^+c+f@g@M@N@O@P@Q@R@R@S@T@U@V@W@X@Y@Z@`@ #.#+#@#d+##M@D@j@D@$#F@%#&#+ *#g =#V -#I@;#M.K@^+c+c+>#", +"c+e+e+,#'#E@)#!#~#{#]#^#/#(#_#:#<#[#}#|#1#2#3#4#5#T 6#7#D@8#9#G@�#a#b#c#d#e#f#g#h#i#j#(+e+k#l#", +"e+o+m#n#o#9#p#q#r#s#t#u#v#w#x#y#z#A#B#C#D#E#F#G#H#I#o#J#E@%#G@&#K#L#M#N#O#P#Q#R#R#S#R#T#U#o+V#W#", +"o+x+w+X#Y#G@J#Z#`# $.$+$@$#$$$%$&$*$=$-$;$>$,$'$)$!$Y#%#J#~$&#{$]$^$/$($_$:$<$[$}$|$S#1$2$g+3$4$", +"x+p+y+4$5$6$%#7$8$9$0$a$b$c$d$%$e$f$g$h$i$j$k$l$m$n$5$o$%#&#p$q$r$s$t$t$t$u$v$w$x$y$z$A$B$p+C$D$", +"p+E$z+F$G$H$I$J$K$L$M$N$O$P$Q$R$f$S$h$T$U$V$W$X$] Y$G$+ @ : Z$`$ %.%+%@%.%#%$%%%&%*%=%-%;%^ >%( ", +"E$c A+,%'%*#+ )%!%M$M$M$~%{%]%^%/%S$(%T$e$_%:%<%[%}%'%: + 8#|%1%+%2%3%4%5%6%7%8%9%0%a%b%c%c d e ", +"c A+x d%e%f%g%h%i%M$M$M$M$j%k%l%m%T$(%n%o%M$p%q%r%s%t%: u%v%w%x%+%+%y%z%A%B%C%D%E%0%F%G%H%x y z ", +"A+S I%J%K%=#g L%M$M$M$M$M$M%N%O%P%Q%R%S%M$M$T%U%,.V%W%X%Y%Z%`%x%+% % &.&+&@&#&$&%&&&*&=&-&R S T ", +"S r+i+'.;&>&,&'&c$M$M$)&!&~&{&]&^&/&(&M$M$M$_&:&r+<&[&}&|&1&2&3&.%4&5&6&7&8&9&0& &a&b&c&d&i+e&'.", +"r+5.o.7.. -#V f&g&M$M$M$h&i&j&k&l&m&n&o&M$p&q&r&o.s&. >&-#t&u&v&w&%%x&y&z&A&B&}@}@C&D&E&F&5.5.7.", +"5.n.j+G&H&I&J&K&L&M$M$M$M$M&N&O&P&Q&R&S&T&U&V&W&n.X&Y&I@0.!.Z&`& *.*+*@*#*#*$*}@M$}@%*&***n.C+G&", +"n.I.Z.=*-*;#;*>*,*'*)*M$M$M$!*~*{*]*^*/*(*_*:*<*[*}*f r.9.|*1*2*3*4*5*6*7*8*9*}@M$M$}@0*a*I.I.K.", +"I.Y.D+b*c*/+d*e*C#D#f*g*h*M$M$M$M$N$i*j*k*l*m*n*Y.o*p*M.N./+q*r*s*t*u*v*w*x*y*}@M$M$M$}@z*Y.A*`.", +"Y.!+k+V%U B*C*D*D#E#O+E*F*G*H*b$I*J*K*L*M*N*O*P*!+Q*U K@M.e@c+R*S*T*U*V*W*X*Y*}@M$M$M$M$}@!+~+Z*", +"!+9+l+`* =c+/+.=E#M++=@=#=$=%=&=*===-=;=>=,='=)=8+!=~=^+/+c+d+{=f+C$/ d h+]=I%}@M$M$M$}@0+9+^=a+", +"0+/=E+(=_=d+:=<=[=}=|=1=2=3=4=5=5=6=7=8=9=0=a=b=6+c=_=c+^+d+o+f+w+/ z+h+B+,.i+}@}@}@M$}@d=6+e=m+", +"l+s+f=g=h=o+c+i=j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=s+z=A=e+c+e+o+g+p+^ c x R B=5.n.I.}@M$M$}@s+C=u+", +"D=H+E=o*n+p+x+F=y+G=A+H=r+6.n.J.Y.D+^=l+C=F+D=H+I=J=K=/ p+/ d h+S I%5.L=J.Z.M=0+l+t+}@}@N=O=P=Q=", +"R=S=T=U=V=W=X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;-R=S=T=M$>-,-'-)-L+!-~-O+{-]-R+^-/-(-_-:-<-[-}-|-}-1-", +" 2-1@3-4-5-6-7-8-9-0-a-b-7@c-9@d-0@e-f-#@f-g-", +" h-)#j@)#7#8#i-@ + j-k-l-m-0.9.r.M.K@e@d+n-L@", +" o-D@j@D@$#F@p-q-r-s-t-u-v-2&I@;#J@e@^+c+c+>#", +" w-7#D@8#%#@ x-y-z-A-B-C-D-E-F-G-e@c+f@e+f@l#", +" t%F@E@%#H-I-J-K-L-M-N-O-P-Q-R-S-T-d+o+o+V#W#", +" U-i-F@V-W-X-K-Y-Z-`- ;.;+;@;}@#;$;o+m#g+x+%;", +" &;o$p-*;=;-;;;>;,;';);!;~;}@{;];^;/;C$p+C$(;", +" _;+ :;<;^;[;};|;1;2;3;4;5;6;7;8;9;0;a;^ >%( ", +" _ : b;c;d;e;f;g;h;i;j;k;l;m;n;o;p;q;r;c d B@", +" f g s;t;^;u;v;w;x;y;z;}@A;B;C;D;E;F;G;x y z ", +" A W H;t;I;J;}@}@K;L;M;N;O;P;Q;R;S;T;U;R S T "}; From 5e004d5f117160becddc0256cc989ff2f40bf487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:43 +0200 Subject: [PATCH 17/20] Real-time dock left-right swapping No more ghost dock when switching sides: the real swap happens immediately, you can still adjust vertically afterwards. Removed two functions in superfluous that are no longer used --- src/dock.c | 106 +++++++++------------------------------------- src/superfluous.c | 103 -------------------------------------------- src/superfluous.h | 1 - 3 files changed, 21 insertions(+), 189 deletions(-) diff --git a/src/dock.c b/src/dock.c index 130f548a..69fb9a5a 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3622,7 +3622,7 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) int x = aicon->x_pos, y = aicon->y_pos;; int shad_x = x, shad_y = y; XEvent ev; - int grabbed = 0, swapped = 0, done; + int grabbed = 0, done, previously_on_right, now_on_right, previous_x_pos; Pixmap ghost = None; int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ @@ -3648,23 +3648,10 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) XClearWindow(dpy, scr->dock_shadow); } XMapWindow(dpy, scr->dock_shadow); - } else { - int i; - WDrawerChain *dc; - /* Find out the actual height of the dock, to create its shadow */ - y = 0; - for (i = 0; i < dock->max_icons; i++) { - if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex > y) - y = dock->icon_array[i]->yindex; - } - for (dc = scr->drawers; dc; dc = dc->next) { - if ((dc->adrawer->y_pos - dock->y_pos) / ICON_SIZE > y) - y = (dc->adrawer->y_pos - dock->y_pos) / ICON_SIZE; - } - y++; - XResizeWindow(dpy, scr->dock_shadow, ICON_SIZE, ICON_SIZE * y); } + previously_on_right = now_on_right = dock->on_right_side; + previous_x_pos = dock->x_pos; done = 0; while (!done) { WMMaskEvent(dpy, PointerMotionMask | ButtonReleaseMask | ButtonPressMask @@ -3700,61 +3687,25 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) moveDock(dock, x, y); break; case WM_DOCK: - /* move vertically if pointer is inside the dock */ - if ((dock->on_right_side && ev.xmotion.x_root >= dock->x_pos - ICON_SIZE) - || (!dock->on_right_side && ev.xmotion.x_root <= dock->x_pos + ICON_SIZE * 2)) { - - x = ev.xmotion.x_root - ofs_x; - y = ev.xmotion.y_root - ofs_y; - wScreenKeepInside(scr, &x, &y, ICON_SIZE, ICON_SIZE); - moveDock(dock, dock->x_pos, y); - } - /* move horizontally to change sides */ x = ev.xmotion.x_root - ofs_x; - if (!dock->on_right_side) { - - /* is on left */ - if (ev.xmotion.x_root > dock->x_pos + ICON_SIZE * 2) { - XMoveWindow(dpy, scr->dock_shadow, scr->scr_width - ICON_SIZE - - DOCK_EXTRA_SPACE - 1, dock->y_pos); - if (superfluous && ghost == None) { - ghost = MakeGhostDock(dock, dock->x_pos, - scr->scr_width - ICON_SIZE - - DOCK_EXTRA_SPACE - 1, dock->y_pos); - XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); - XClearWindow(dpy, scr->dock_shadow); - } - XMapRaised(dpy, scr->dock_shadow); - swapped = 1; - } else { - if (superfluous && ghost != None) { - XFreePixmap(dpy, ghost); - ghost = None; - } - XUnmapWindow(dpy, scr->dock_shadow); - swapped = 0; - } - } else { - /* is on right */ - if (ev.xmotion.x_root < dock->x_pos - ICON_SIZE) { - XMoveWindow(dpy, scr->dock_shadow, DOCK_EXTRA_SPACE, dock->y_pos); - if (superfluous && ghost == None) { - ghost = MakeGhostDock(dock, dock->x_pos, - DOCK_EXTRA_SPACE, dock->y_pos); - XSetWindowBackgroundPixmap(dpy, scr->dock_shadow, ghost); - XClearWindow(dpy, scr->dock_shadow); - } - XMapRaised(dpy, scr->dock_shadow); - swapped = -1; - } else { - XUnmapWindow(dpy, scr->dock_shadow); - swapped = 0; - if (superfluous && ghost != None) { - XFreePixmap(dpy, ghost); - ghost = None; - } - } + y = ev.xmotion.y_root - ofs_y; + if (previously_on_right) + { + now_on_right = (ev.xmotion.x_root >= previous_x_pos - ICON_SIZE); } + else + { + now_on_right = (ev.xmotion.x_root > previous_x_pos + ICON_SIZE * 2); + } + if (now_on_right != dock->on_right_side) + { + dock->on_right_side = now_on_right; + swapDock(dock); + wArrangeIcons(scr, False); + } + // Also perform the vertical move + wScreenKeepInside(scr, &x, &y, ICON_SIZE, ICON_SIZE); + moveDock(dock, dock->x_pos, y); break; case WM_DRAWER: { @@ -3799,19 +3750,7 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) shad_y); XUnmapWindow(dpy, scr->dock_shadow); moveDock(dock, shad_x, shad_y); - } else { - XUnmapWindow(dpy, scr->dock_shadow); - } - XResizeWindow(dpy, scr->dock_shadow, ICON_SIZE, ICON_SIZE); - if (dock->type == WM_DOCK) { - if (swapped != 0) { - if (swapped > 0) - dock->on_right_side = 1; - else - dock->on_right_side = 0; - swapDock(dock); - wArrangeIcons(scr, False); - } + XResizeWindow(dpy, scr->dock_shadow, ICON_SIZE, ICON_SIZE); } done = 1; break; @@ -4712,9 +4651,6 @@ static WDock * drawerRestoreState(WScreen *scr, WMPropList *drawer_state) x = scr->dock->x_pos; } y_index = (y - scr->dock->y_pos) / ICON_SIZE; - if (y_index <= 0) { - y_index = 1; - } if (y_index >= scr->dock->max_icons) { /* Here we should do something more intelligent, since it * can happen even if the user hasn't hand-edited his diff --git a/src/superfluous.c b/src/superfluous.c index 8df8ac24..0c95ed4d 100644 --- a/src/superfluous.c +++ b/src/superfluous.c @@ -137,109 +137,6 @@ void DoKaboom(WScreen * scr, Window win, int x, int y) #endif /* NORMAL_ICON_KABOOM */ } -static int addGhostTile(WScreen *scr, RImage *back, Pixmap which, int dy, int height, - unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask) -{ - XImage *img; - RImage *dock_image; - - img = XGetImage(dpy, which, 0, 0, wPreferences.icon_size, height, AllPlanes, ZPixmap); - if (!img) { - RReleaseImage(back); - return -1; - } - img->red_mask = red_mask; - img->green_mask = green_mask; - img->blue_mask = blue_mask; - - dock_image = RCreateImageFromXImage(scr->rcontext, img, NULL); - XDestroyImage(img); - if (!dock_image) { - RReleaseImage(back); - return -1; - } - RCombineAreaWithOpaqueness(back, dock_image, 0, 0, wPreferences.icon_size, - height, 0, dy, 30 * 256 / 100); - RReleaseImage(dock_image); - return 0; -} - -Pixmap MakeGhostDock(WDock * dock, int sx, int dx, int y) -{ - WScreen *scr = dock->screen_ptr; - WDrawerChain *dc; - WDock *drawer; - XImage *img; - RImage *back; - Pixmap pixmap; - int i, virtual_tiles, h, j, n; - unsigned long red_mask, green_mask, blue_mask; - - virtual_tiles = 0; - for (i = 0; i < dock->max_icons; i++) { - if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex > virtual_tiles) - virtual_tiles = dock->icon_array[i]->yindex; - } - for (dc = scr->drawers; dc != NULL; dc = dc->next) { - if (dc->adrawer->y_pos - dock->y_pos > virtual_tiles * wPreferences.icon_size) - virtual_tiles = (dc->adrawer->y_pos - dock->y_pos) / wPreferences.icon_size; - } - virtual_tiles++; - h = virtual_tiles * wPreferences.icon_size; - h = (y + h > scr->scr_height) ? scr->scr_height - y : h; - virtual_tiles = h / wPreferences.icon_size; /* The visible ones */ - if (h % wPreferences.icon_size) - virtual_tiles++; /* There is one partially visible tile at end */ - - img = XGetImage(dpy, scr->root_win, dx, y, wPreferences.icon_size, h, AllPlanes, ZPixmap); - if (!img) - return None; - - red_mask = img->red_mask; - green_mask = img->green_mask; - blue_mask = img->blue_mask; - - back = RCreateImageFromXImage(scr->rcontext, img, NULL); - XDestroyImage(img); - if (!back) { - return None; - } - - for (i = 0; i < dock->max_icons; i++) { - if (dock->icon_array[i] != NULL && dock->icon_array[i]->yindex < virtual_tiles) { - Pixmap which; - j = dock->icon_array[i]->yindex * wPreferences.icon_size; - n = (h - j < wPreferences.icon_size) ? h - j : wPreferences.icon_size; - if (dock->icon_array[i]->icon->pixmap) - which = dock->icon_array[i]->icon->pixmap; - else - which = dock->icon_array[i]->icon->core->window; - if (addGhostTile(scr, back, which, j, n, red_mask, green_mask, blue_mask)) - return None; /* back is released by addGhostTile */ - } - } - for (dc = scr->drawers; dc != NULL; dc = dc->next) { - Pixmap which; - drawer = dc->adrawer; - if (drawer->y_pos >= scr->scr_height) - continue; - j = drawer->y_pos - dock->y_pos; - n = (h - j < wPreferences.icon_size) ? h - j : wPreferences.icon_size; - if (drawer->icon_array[0]->icon->pixmap) - which = drawer->icon_array[0]->icon->pixmap; - else - which = drawer->icon_array[0]->icon->core->window; - if (addGhostTile(scr, back, which, j, n, red_mask, green_mask, blue_mask)) - return None; /* back is released by addGhostTile */ - } - - RConvertImage(scr->rcontext, back, &pixmap); - - RReleaseImage(back); - - return pixmap; -} - Pixmap MakeGhostIcon(WScreen * scr, Drawable drawable) { RImage *back; diff --git a/src/superfluous.h b/src/superfluous.h index b7b70b1a..b3424cd5 100644 --- a/src/superfluous.h +++ b/src/superfluous.h @@ -24,7 +24,6 @@ #include "dock.h" void DoKaboom(WScreen *scr, Window win, int x, int y); -Pixmap MakeGhostDock(WDock *dock, int sx, int dx, int y); Pixmap MakeGhostIcon(WScreen *scr, Drawable drawable); void DoWindowBirth(WWindow *wwin); #endif From 3c628d50d260af0b204a7fb4cb0735527b4e46b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:44 +0200 Subject: [PATCH 18/20] Allow appicons above the dock Previous, even the "anchor tile" of the dock could be moved down, it was not possible to dock anything above it. --- src/dock.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/dock.c b/src/dock.c index 69fb9a5a..352bf156 100644 --- a/src/dock.c +++ b/src/dock.c @@ -1692,12 +1692,9 @@ static WAppIcon *restore_icon_state(WScreen *scr, WMPropList *info, int type, in wwarning(_("bad value in docked icon state info %s"), WMGetFromPLString(dPosition)); /* check position sanity */ - /* incomplete section! */ + /* *Very* incomplete section! */ if (type == WM_DOCK) { aicon->xindex = 0; - if (aicon->yindex < 0) - wwarning(_("bad value in docked icon position %i,%i"), - aicon->xindex, aicon->yindex); } } else { aicon->yindex = index; @@ -2440,10 +2437,6 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x int i, offset = ICON_SIZE / 2; WAppIcon *aicon = NULL; WAppIcon *nicon = NULL; - int max_y_icons; - - /* TODO: XINERAMA, for these */ - max_y_icons = scr->scr_height / ICON_SIZE - 1; if (wPreferences.flags.noupdates) return False; @@ -2510,7 +2503,7 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x if (abs(ex_x) > DOCK_DETTACH_THRESHOLD) return False; - if (ex_y >= 0 && ex_y <= max_y_icons && (aicon == icon || !aicon)) { + if (aicon == icon || !aicon) { *ret_x = 0; *ret_y = ex_y; return True; @@ -2522,7 +2515,6 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x else sig = -1; - closest = -1; done = 0; /* look for closest free slot */ for (i = 0; i < (DOCK_DETTACH_THRESHOLD + 1) * 2 && !done; i++) { @@ -2530,8 +2522,8 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x done = 1; closest = sig * (i / 2) + ex_y; - /* check if this slot is used */ - if (closest >= 0) { + /* check if this slot is fully on the screen and not used */ + if (onScreen(scr, dx, dy + closest * ICON_SIZE)) { for (j = 0; j < dock->max_icons; j++) { if (dock->icon_array[j] && dock->icon_array[j]->yindex == closest) { @@ -2544,11 +2536,13 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x /* slot is used by a drawer */ done = done && !getDrawer(scr, closest); } + else // !onScreen + done = 0; sig = -sig; } - if (done && closest >= 0 && closest <= max_y_icons && - ((ex_y >= closest && ex_y - closest < DOCK_DETTACH_THRESHOLD + 1) - || (ex_y < closest && closest - ex_y <= DOCK_DETTACH_THRESHOLD + 1))) { + if (done && + ((ex_y >= closest && ex_y - closest < DOCK_DETTACH_THRESHOLD + 1) + || (ex_y < closest && closest - ex_y <= DOCK_DETTACH_THRESHOLD + 1))) { *ret_x = 0; *ret_y = closest; return True; @@ -2556,7 +2550,7 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x } else { /* !redocking */ /* if slot is free and the icon is close enough, return it */ - if (!aicon && ex_x == 0 && ex_y >= 0 && ex_y <= max_y_icons) { + if (!aicon && ex_x == 0) { *ret_x = 0; *ret_y = ex_y; return True; From 36bed6a77e2b601a759b785cffa209c2a01c5d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:45 +0200 Subject: [PATCH 19/20] Wrap appicons when dock is moved up and down Add WrapAppiconsInDock option to control that behaviour (default: YES) --- src/WindowMaker.h | 1 + src/defaults.c | 9 +++++ src/dock.c | 98 +++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/src/WindowMaker.h b/src/WindowMaker.h index 72b47480..6ab085fc 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -434,6 +434,7 @@ typedef struct WPreferences { unsigned int nodock:1; /* don't display the dock */ unsigned int noclip:1; /* don't display the clip */ unsigned int nodrawer:1; /* don't use drawers */ + unsigned int wrap_appicons_in_dock:1; /* Whether to wrap appicons when Dock is moved up and down */ unsigned int noupdates:1; /* don't require ~/GNUstep (-static) */ unsigned int noautolaunch:1; /* don't autolaunch apps */ unsigned int norestore:1; /* don't restore session */ diff --git a/src/defaults.c b/src/defaults.c index 053551d1..a018fd64 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -113,6 +113,7 @@ static int getPropList(); static int setJustify(); static int setClearance(); static int setIfDockPresent(); +static int setWrapAppiconsInDock(); static int setStickyIcons(); static int setWidgetColor(); static int setIconTile(); @@ -404,6 +405,8 @@ WDefaultEntry optionList[] = { &wPreferences.clip_auto_expand_delay, getInt, NULL, NULL, NULL}, {"ClipAutocollapseDelay", "1000", NULL, &wPreferences.clip_auto_collapse_delay, getInt, NULL, NULL, NULL}, + {"WrapAppiconsInDock", "YES", NULL, + NULL, getBool, setWrapAppiconsInDock, NULL, NULL}, {"AlignSubmenus", "NO", NULL, &wPreferences.align_menus, getBool, NULL, NULL, NULL}, {"ViKeyMenus", "NO", NULL, @@ -2346,6 +2349,12 @@ static int setIfDockPresent(WScreen * scr, WDefaultEntry * entry, char *flag, lo return 0; } +static int setWrapAppiconsInDock(WScreen *scr, WDefaultEntry *entry, char *flag, void *foo) +{ + wPreferences.flags.wrap_appicons_in_dock = *flag; + return 0; +} + static int setStickyIcons(WScreen * scr, WDefaultEntry * entry, void *bar, void *foo) { if (scr->workspaces) { diff --git a/src/dock.c b/src/dock.c index 352bf156..1625de94 100644 --- a/src/dock.c +++ b/src/dock.c @@ -2541,8 +2541,8 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int req_x, int req_y, int *ret_x sig = -sig; } if (done && - ((ex_y >= closest && ex_y - closest < DOCK_DETTACH_THRESHOLD + 1) - || (ex_y < closest && closest - ex_y <= DOCK_DETTACH_THRESHOLD + 1))) { + ((ex_y >= closest && ex_y - closest < DOCK_DETTACH_THRESHOLD + 1) + || (ex_y < closest && closest - ex_y <= DOCK_DETTACH_THRESHOLD + 1))) { *ret_x = 0; *ret_y = closest; return True; @@ -3613,10 +3613,12 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) WScreen *scr = dock->screen_ptr; int ofs_x = event->xbutton.x, ofs_y = event->xbutton.y; WIcon *icon = aicon->icon; + WAppIcon *tmpaicon; + WDrawerChain *dc; int x = aicon->x_pos, y = aicon->y_pos;; int shad_x = x, shad_y = y; XEvent ev; - int grabbed = 0, done, previously_on_right, now_on_right, previous_x_pos; + int grabbed = 0, done, previously_on_right, now_on_right, previous_x_pos, i; Pixmap ghost = None; int superfluous = wPreferences.superfluous; /* we catch it to avoid problems */ @@ -3700,6 +3702,57 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) // Also perform the vertical move wScreenKeepInside(scr, &x, &y, ICON_SIZE, ICON_SIZE); moveDock(dock, dock->x_pos, y); + if (wPreferences.flags.wrap_appicons_in_dock) + { + for (i = 0; i < dock->max_icons; i++) { + int new_y, new_index, j, ok; + if ((tmpaicon = dock->icon_array[i]) == NULL) + continue; + if (onScreen(scr, tmpaicon->x_pos, tmpaicon->y_pos)) + continue; + new_y = (tmpaicon->y_pos + ICON_SIZE * dock->max_icons) % (ICON_SIZE * dock->max_icons); + new_index = (new_y - dock->y_pos) / ICON_SIZE; + if (!onScreen(scr, tmpaicon->x_pos, new_y)) + continue; + ok = 1; + for (j = 0; j < dock->max_icons; j++) + { + if (dock->icon_array[j] != NULL && + dock->icon_array[j]->yindex == new_index) + { + ok = 0; + break; + } + } + if (!ok || getDrawer(scr, new_index) != NULL) + continue; + wDockReattachIcon(dock, tmpaicon, tmpaicon->xindex, new_index); + } + for (dc = scr->drawers; dc != NULL; dc = dc->next) + { + int new_y, new_index, j, ok; + tmpaicon = dc->adrawer->icon_array[0]; + if (onScreen(scr, tmpaicon->x_pos, tmpaicon->y_pos)) + continue; + new_y = (tmpaicon->y_pos + ICON_SIZE * dock->max_icons) % (ICON_SIZE * dock->max_icons); + new_index = (new_y - dock->y_pos) / ICON_SIZE; + if (!onScreen(scr, tmpaicon->x_pos, new_y)) + continue; + ok = 1; + for (j = 0; j < dock->max_icons; j++) + { + if (dock->icon_array[j] != NULL && + dock->icon_array[j]->yindex == new_index) + { + ok = 0; + break; + } + } + if (!ok || getDrawer(scr, new_index) != NULL) + continue; + moveDock(dc->adrawer, tmpaicon->x_pos, new_y); + } + } break; case WM_DRAWER: { @@ -3728,14 +3781,12 @@ static void handleDockMove(WDock *dock, WAppIcon *aicon, XEvent *event) break; XUngrabPointer(dpy, CurrentTime); if (dock->type == WM_DRAWER) { - int i; Window *wins[dock->icon_count]; - WAppIcon *aicon; for (i = 0; i < dock->max_icons; i++) { - if ((aicon = dock->icon_array[i]) == NULL) + if ((tmpaicon = dock->icon_array[i]) == NULL) continue; - wins[ aicon->xindex + (dock->on_right_side ? dock->icon_count - 1 : 0) ] = &aicon->icon->core->window; + wins[ tmpaicon->xindex + (dock->on_right_side ? dock->icon_count - 1 : 0) ] = &tmpaicon->icon->core->window; } SlideWindows(wins, dock->icon_count, (dock->on_right_side ? x - (dock->icon_count - 1) * ICON_SIZE : x), @@ -4219,30 +4270,45 @@ static void drawerIconExpose(WObjDescriptor *desc, XEvent *event) static int addADrawer(WScreen *scr) { - int i, y; + int i, y, sig, found_y; WDock *drawer, *dock = scr->dock; WDrawerChain *dc; - char can_be_here[dock->max_icons]; + char can_be_here[2 * dock->max_icons - 1]; if (dock->icon_count + scr->drawer_count >= dock->max_icons) return -1; - for (y = 0; y < dock->max_icons; y++) { - can_be_here[y] = True; + for (y = -dock->max_icons + 1; y < dock->max_icons; y++) { + can_be_here[y + dock->max_icons - 1] = True; } for (i = 0; i < dock->max_icons; i++) { if (dock->icon_array[i] != NULL) - can_be_here[dock->icon_array[i]->yindex] = False; + can_be_here[dock->icon_array[i]->yindex + dock->max_icons - 1] = False; } for (dc = scr->drawers; dc != NULL; dc = dc->next) { y = (int) ((dc->adrawer->y_pos - dock->y_pos) / ICON_SIZE); - can_be_here[y] = False; + can_be_here[y + dock->max_icons - 1] = False; } - for (y = 0; y < dock->max_icons; y++) { - if (can_be_here[y]) - break; + found_y = False; + for (sig = 1; !found_y && sig > -2; sig -= 2) // 1, then -1 + { + for (y = sig; sig * y < dock->max_icons; y += sig) + { + if (can_be_here[y + dock->max_icons - 1] && + onScreen(scr, dock->x_pos, dock->y_pos + y * ICON_SIZE)) + { + found_y = True; + break; + } + } } + + if (!found_y) + /* This can happen even when dock->icon_count + scr->drawer_count + * < dock->max_icons when the dock is not aligned on an + * ICON_SIZE multiple, as some space is lost above and under it */ + return -1; drawer = wDockCreate(scr, WM_DRAWER, NULL); drawer->lowered = scr->dock->lowered; From 878a57d7b2535fdb0a0838bd0b0c5894933a7986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A9chelotte?= Date: Fri, 12 Apr 2013 01:42:46 +0200 Subject: [PATCH 20/20] Add option to merge the workspace-switching functionality into the dock The dock will have the up-right and down-left arrows to change workspaces and the clip will be disabled. That is, if option ClipMergedInDock is set to yes in GNUstep/Defaults/WindowMaker. [not thoroughly tested] --- src/WindowMaker.h | 1 + src/appicon.c | 2 ++ src/defaults.c | 14 ++++++++++++-- src/dock.c | 35 +++++++++++++++++++++++++---------- src/screen.c | 2 ++ src/screen.h | 4 ++-- src/workspace.c | 17 ++++++++--------- 7 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/WindowMaker.h b/src/WindowMaker.h index 6ab085fc..50d5dc27 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -433,6 +433,7 @@ typedef struct WPreferences { struct { unsigned int nodock:1; /* don't display the dock */ unsigned int noclip:1; /* don't display the clip */ + unsigned int clip_merged_in_dock:1; /* disable clip, dock gets its workspace switching functionality */ unsigned int nodrawer:1; /* don't use drawers */ unsigned int wrap_appicons_in_dock:1; /* Whether to wrap appicons when Dock is moved up and down */ unsigned int noupdates:1; /* don't require ~/GNUstep (-static) */ diff --git a/src/appicon.c b/src/appicon.c index d4384d7f..b719d05d 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -129,6 +129,8 @@ WAppIcon *wAppIconCreateForDock(WScreen *scr, char *command, char *wm_instance, if (wm_instance) aicon->wm_instance = wstrdup(wm_instance); + if (strcmp(wm_class, "WMDock") == 0 && wPreferences.flags.clip_merged_in_dock) + tile = TILE_CLIP; aicon->icon = icon_create_for_dock(scr, command, wm_instance, wm_class, tile); #ifdef XDND diff --git a/src/defaults.c b/src/defaults.c index a018fd64..5de819ee 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -113,6 +113,7 @@ static int getPropList(); static int setJustify(); static int setClearance(); static int setIfDockPresent(); +static int setClipMergedInDock(); static int setWrapAppiconsInDock(); static int setStickyIcons(); static int setWidgetColor(); @@ -328,6 +329,8 @@ WDefaultEntry staticOptionList[] = { NULL, getBool, setIfDockPresent, NULL, NULL}, {"DisableDrawers", "NO", (void *)WM_DRAWER, NULL, getBool, setIfDockPresent, NULL, NULL}, + {"ClipMergedInDock", "NO", NULL, + NULL, getBool, setClipMergedInDock, NULL, NULL}, {"DisableMiniwindows", "NO", NULL, &wPreferences.disable_miniwindows, getBool, NULL, NULL, NULL} }; @@ -1147,7 +1150,7 @@ void wDefaultUpdateIcons(WScreen *scr) aicon = aicon->next; } - if (!wPreferences.flags.noclip) + if (!wPreferences.flags.noclip || wPreferences.flags.clip_merged_in_dock) wClipIconPaint(scr->clip_icon); for (dc = scr->drawers; dc != NULL; dc = dc->next) @@ -2349,6 +2352,13 @@ static int setIfDockPresent(WScreen * scr, WDefaultEntry * entry, char *flag, lo return 0; } +static int setClipMergedInDock(WScreen *scr, WDefaultEntry *entry, char *flag, void *foo) +{ + wPreferences.flags.clip_merged_in_dock = *flag; + wPreferences.flags.noclip = wPreferences.flags.noclip || *flag; + return 0; +} + static int setWrapAppiconsInDock(WScreen *scr, WDefaultEntry *entry, char *flag, void *foo) { wPreferences.flags.wrap_appicons_in_dock = *flag; @@ -2392,7 +2402,7 @@ static int setIconTile(WScreen * scr, WDefaultEntry * entry, WTexture ** texture /* put the icon in the noticeboard hint */ PropSetIconTileHint(scr, img); - if (!wPreferences.flags.noclip) { + if (!wPreferences.flags.noclip || wPreferences.flags.clip_merged_in_dock) { if (scr->clip_tile) { RReleaseImage(scr->clip_tile); } diff --git a/src/dock.c b/src/dock.c index 1625de94..b20bfe1e 100644 --- a/src/dock.c +++ b/src/dock.c @@ -824,6 +824,8 @@ WAppIcon *mainIconCreate(WScreen *scr, int type, char *name) case WM_DOCK: default: /* to avoid a warning about btn and x_pos, basically */ btn = wAppIconCreateForDock(scr, NULL, "Logo", "WMDock", TILE_NORMAL); + if (wPreferences.flags.clip_merged_in_dock) + btn->icon->core->descriptor.handle_expose = clipIconExpose; x_pos = scr->scr_width - ICON_SIZE - DOCK_EXTRA_SPACE; break; case WM_DRAWER: @@ -846,7 +848,8 @@ WAppIcon *mainIconCreate(WScreen *scr, int type, char *name) btn->x_pos = x_pos; btn->y_pos = 0; btn->docked = 1; - if (type == WM_CLIP) + if (type == WM_CLIP || + (type == WM_DOCK && wPreferences.flags.clip_merged_in_dock)) scr->clip_icon = btn; return btn; @@ -1377,7 +1380,7 @@ void wClipIconPaint(WAppIcon *aicon) snprintf(ws_number, sizeof(ws_number), "%i", scr->current_workspace + 1); nlength = strlen(ws_number); - if (!workspace->clip->collapsed) + if (wPreferences.flags.noclip || !workspace->clip->collapsed) color = scr->clip_title_color[CLIP_NORMAL]; else color = scr->clip_title_color[CLIP_COLLAPSED]; @@ -1447,7 +1450,7 @@ static WMPropList *make_icon_state(WAppIcon *btn) buggy = btn->buggy_app ? dYes : dNo; - if (btn == btn->icon->core->screen_ptr->clip_icon) + if (!wPreferences.flags.clip_merged_in_dock && btn == btn->icon->core->screen_ptr->clip_icon) snprintf(buffer, sizeof(buffer), "%i,%i", btn->x_pos, btn->y_pos); else snprintf(buffer, sizeof(buffer), "%hi,%hi", btn->xindex, btn->yindex); @@ -1958,7 +1961,7 @@ WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) * incremented in the loop above. */ } else if (old_top != dock->icon_array[0]) { - if (old_top == scr->clip_icon) + if (old_top == scr->clip_icon) // TODO dande: understand the logic scr->clip_icon = dock->icon_array[0]; wAppIconDestroy(old_top); @@ -3592,10 +3595,22 @@ static void iconDblClick(WObjDescriptor *desc, XEvent *event) /* raise/lower dock */ toggleLowered(dock); } else if (btn == dock->screen_ptr->clip_icon) { - if (getClipButton(event->xbutton.x, event->xbutton.y) == CLIP_IDLE) - toggleCollapsed(dock); - else + if (getClipButton(event->xbutton.x, event->xbutton.y) != CLIP_IDLE) handleClipChangeWorkspace(dock->screen_ptr, event); + else if (wPreferences.flags.clip_merged_in_dock) { + // Is actually the dock + if (btn->command) + { + if (!btn->launching && (!btn->running || (event->xbutton.state & ControlMask))) + launchDockedApplication(btn, False); + } + else + { + wShowInfoPanel(dock->screen_ptr); + } + } + else + toggleCollapsed(dock); } else if (wIsADrawer(dock->screen_ptr, btn)) { toggleCollapsed(dock); } else if (btn->command) { @@ -3921,8 +3936,8 @@ static void iconMouseDown(WObjDescriptor *desc, XEvent *event) } if (aicon->yindex == 0 && aicon->xindex == 0) { - if (getClipButton(event->xbutton.x, event->xbutton.y) != CLIP_IDLE - && dock->type == WM_CLIP) + if (getClipButton(event->xbutton.x, event->xbutton.y) != CLIP_IDLE && + (dock->type == WM_CLIP || (dock->type == WM_DOCK && wPreferences.flags.clip_merged_in_dock))) handleClipChangeWorkspace(scr, event); else handleDockMove(dock, aicon, event); @@ -3931,7 +3946,7 @@ static void iconMouseDown(WObjDescriptor *desc, XEvent *event) if (wPreferences.single_click && !hasMoved) iconDblClick(desc, event); } - } else if (event->xbutton.button == Button2 && dock->type == WM_CLIP && aicon == scr->clip_icon) { + } else if (event->xbutton.button == Button2 && aicon == scr->clip_icon) { if (!scr->clip_ws_menu) { scr->clip_ws_menu = wWorkspaceMenuMake(scr, False); } diff --git a/src/screen.c b/src/screen.c index 8d1c46c6..aa4662b5 100644 --- a/src/screen.c +++ b/src/screen.c @@ -859,6 +859,8 @@ void wScreenRestoreState(WScreen * scr) if (!wPreferences.flags.nodock) { state = WMGetFromPLDictionary(scr->session_state, dDock); scr->dock = wDockRestoreState(scr, state, WM_DOCK); + /* If clip_merged_in_dock, setting scr->clip_icon is done by + * wDockRestoreState()->wDockCreate()->mainIconCreate() */ } if (!wPreferences.flags.noclip) { diff --git a/src/screen.h b/src/screen.h index 66af6d70..5f817e39 100644 --- a/src/screen.h +++ b/src/screen.h @@ -222,7 +222,7 @@ typedef struct _WScreen { struct WMenu *dock_pos_menu; /* Dock position menu */ struct WPixmap *dock_dots; /* 3 dots for the Dock */ Window dock_shadow; /* shadow for dock buttons */ - struct WAppIcon *clip_icon; /* The clip main icon */ + struct WAppIcon *clip_icon; /* The clip main icon, or the dock's, if they are merged */ struct WMenu *clip_menu; /* Menu for clips */ struct WMenu *clip_submenu; /* Workspace list for clips */ struct WMenu *clip_options; /* Options for Clip */ @@ -244,7 +244,7 @@ typedef struct _WScreen { WMScreen *wmscreen; /* for widget library */ struct RImage *icon_tile; - struct RImage *clip_tile; + struct RImage *clip_tile; /* tile with arrows to change workspace */ struct RImage *drawer_tile; /* tile for a drawer (tile + arrow) */ Pixmap icon_tile_pixmap; /* For app supplied icons */ diff --git a/src/workspace.c b/src/workspace.c index 23f2c19d..dd4e2cd7 100644 --- a/src/workspace.c +++ b/src/workspace.c @@ -613,15 +613,14 @@ void wWorkspaceForceChange(WScreen * scr, int workspace) if (scr->dock) wAppIconPaint(scr->dock->icon_array[0]); - if (scr->clip_icon) { - if (scr->workspaces[workspace]->clip->auto_collapse || - scr->workspaces[workspace]->clip->auto_raise_lower) { - /* to handle enter notify. This will also */ - XUnmapWindow(dpy, scr->clip_icon->icon->core->window); - XMapWindow(dpy, scr->clip_icon->icon->core->window); - } else { - wClipIconPaint(scr->clip_icon); - } + if (!wPreferences.flags.noclip && (scr->workspaces[workspace]->clip->auto_collapse || + scr->workspaces[workspace]->clip->auto_raise_lower)) { + /* to handle enter notify. This will also */ + XUnmapWindow(dpy, scr->clip_icon->icon->core->window); + XMapWindow(dpy, scr->clip_icon->icon->core->window); + } + else if (scr->clip_icon != NULL) { + wClipIconPaint(scr->clip_icon); } wScreenUpdateUsableArea(scr); wNETWMUpdateDesktop(scr);