From: Daniel Déchelotte <[email protected]>

Add WrapAppiconsInDock option to control that behaviour (default: YES)
---
 src/WindowMaker.h |    4 +-
 src/defaults.c    |    9 +++
 src/dock.c        |  210 +++++++++++++++++++++++++++++++++++------------------
 3 files changed, 150 insertions(+), 73 deletions(-)

diff --git a/src/WindowMaker.h b/src/WindowMaker.h
index c37c34a..7ec96d1 100644
--- a/src/WindowMaker.h
+++ b/src/WindowMaker.h
@@ -443,7 +443,9 @@ typedef struct WPreferences {
     struct {
         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 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 c2fceb6..3543f82 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 ef382e2..ebee9c3 100644
--- a/src/dock.c
+++ b/src/dock.c
@@ -2463,22 +2463,22 @@ 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;
 
-    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. */
+       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]))
+                       !(icon->dock && icon->dock->type == WM_DRAWER && icon 
== icon->dock->icon_array[0]))
                        return False;
 
                if (!redocking && ex_x != 0)
-            return False;
+                       return False;
 
-        if (getDrawer(scr, ex_y)) /* Return false so that the drawer gets it. 
*/
-            return False;
+               if (getDrawer(scr, ex_y)) /* Return false so that the drawer 
gets it. */
+                       return False;
 
                aicon = NULL;
                for (i = 0; i < dock->max_icons; i++) {
@@ -2495,7 +2495,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 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
@@ -2533,16 +2533,16 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int 
req_x, int req_y, int *ret_x
                                                        break;
                                                }
                                        }
-                    /* slot is used by a drawer */
-                    done = done && !getDrawer(scr, closest);
+                                       /* slot is used by a drawer */
+                                       done = done && !getDrawer(scr, closest);
                                }
                                else // !onScreen
                                        done = 0;
                                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;
@@ -2606,45 +2606,45 @@ Bool wDockSnapIcon(WDock *dock, WAppIcon *icon, int 
req_x, int req_y, int *ret_x
        }
        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;
+               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;
@@ -3126,9 +3126,9 @@ void wDockRaise(WDock *dock)
                        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);
-    }
+               for (dc = dock->screen_ptr->drawers; dc != NULL; dc = dc->next)
+                       wDockRaise(dc->adrawer);
+       }
 }
 
 void wDockRaiseLower(WDock *dock)
@@ -3611,10 +3611,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 */
 
@@ -3698,6 +3700,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:
                        {
@@ -3726,14 +3779,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),
@@ -4226,30 +4277,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;
-- 
1.7.10.4


-- 
To unsubscribe, send mail to [email protected].

Reply via email to