This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project wmaker-crm.git.

The branch, next has been updated
  discards  577481d76af08197214a24039281efd0f4c33fe0 (commit)
  discards  f464856f55ddf8d29b7e1d2ee1b71640bcc694c8 (commit)
  discards  1b0ecc4e40f73a8bf7a5e3793a5ef5b0231cd327 (commit)
  discards  f9d517d0371e94f1293c334f1db4d678f55d0977 (commit)
  discards  441b561c814767c1b70eea5a7391d5bcc678ccac (commit)
  discards  120a0b992716fa5fb320844219a6ef323b5a2b64 (commit)
  discards  213606b61c518e5c29a285660f7505c031fe034b (commit)
  discards  faf52eec57064bff3602379d2f2a5e05906cecf9 (commit)
  discards  1e1bf8c54c137d2e260422dcdd6a4c634cd1fa0a (commit)
       via  d387ccd49a63ad6ef696239a8d1cd602eb5980a7 (commit)
       via  a864f1988fd7fd044633b319c40a8f0ab1b85658 (commit)
       via  c94fc4ba39f2b3a0b8e3ed5e56a35c42cc36cd01 (commit)
       via  467b7ee4560f124f7469a2a630cb35d477cc0444 (commit)
       via  c10469264d70075a26a13ac2db5281822a2a2210 (commit)
       via  47ac986b5336869236fefb748a066d936c590f19 (commit)
       via  12babda9e7050a95789cc4173b072e2e815e1fbc (commit)
       via  80f18f60d239499d3d266bf3a6a7e5e78374aca7 (commit)
       via  10371836ed5637c2faf718873b5866c7a8314134 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (577481d76af08197214a24039281efd0f4c33fe0)
                         N -- N -- N (d387ccd49a63ad6ef696239a8d1cd602eb5980a7)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://repo.or.cz/w/wmaker-crm.git/commit/d387ccd49a63ad6ef696239a8d1cd602eb5980a7

commit d387ccd49a63ad6ef696239a8d1cd602eb5980a7
Author: David Maciejak <david.macie...@gmail.com>
Date:   Thu Dec 4 13:37:36 2014 +0700

    wmaker: add core workspace pager functions
    
    This patch is adding the core code needed to run the workspace pager.
    
    Currently when called, a new frame presenting mini workspace images
    are displayed at the bottom of the screen above other windows.
    When clicking on one of the miniatures, the workspace is switched and
    the frame is closed.
    
    Drawbacks: a screenshot of the workspace is used for the miniatures.
    This screenshot is taken only when a workspace switched event occurs.
    
    First, it means that the workspace switching process can be longer than
    usual. Secondly, updated minitatures can only be available when the
    workspace is "opened" (cause windows have to be mapped to be able to
    be copied).
    
    So when wmaker is (re)started or when for example a window is moved to
    another workspace the corresponding miniature is NOT updated.
    (I did not find a clean and easy way to do so, feel free to share if
    you have some ideas)

diff --git a/src/Makefile.am b/src/Makefile.am
index 6c20e63a..a7aa1d09 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -107,7 +107,9 @@ wmaker_SOURCES =            wmspec.h        wmspec.c        
workspace.c -   workspace.h
+       workspace.h +   wsmap.c +       wsmap.h
 
 if WM_OSDEP_BSD
 wmaker_SOURCES += osdep_bsd.c
diff --git a/src/event.c b/src/event.c
index 9a8a3e3f..6b2e0db0 100644
--- a/src/event.c
+++ b/src/event.c
@@ -77,6 +77,7 @@
 #include "event.h"
 #include "winmenu.h"
 #include "switchmenu.h"
+#include "wsmap.h"
 
 
 #define MOD_MASK wPreferences.modifier_mask
@@ -1606,6 +1607,12 @@ static void handleKeyPress(XEvent * event)
                        wSelectWindow(wwin, !wwin->flags.selected);
                }
                break;
+
+       case WKBD_WORKSPACEMAP:
+               if (!wPreferences.disable_workspace_pager)
+                       StartWorkspaceMap(scr);
+               break;
+
        case WKBD_FOCUSNEXT:
                StartWindozeCycle(wwin, event, True, False);
                break;
diff --git a/src/misc.c b/src/misc.c
index 3b9299d4..a12a97de 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -245,7 +245,7 @@ void SlideWindows(Window *wins[], int n, int from_x, int 
from_y, int to_x, int t
                if (slide_delay > 0) {
                        wusleep(slide_delay * 1000L);
                } else {
-                       wusleep(10);
+                       wusleep(1000L);
                }
                if (time(NULL) - time0 > MAX_ANIMATION_TIME)
                        break;
diff --git a/src/workspace.c b/src/workspace.c
index 107db2aa..165e3011 100644
--- a/src/workspace.c
+++ b/src/workspace.c
@@ -49,6 +49,7 @@
 #include "wmspec.h"
 #include "xinerama.h"
 #include "event.h"
+#include "wsmap.h"
 
 #define MC_NEW          0
 #define MC_DESTROY_LAST 1
@@ -160,6 +161,8 @@ Bool wWorkspaceDelete(WScreen * scr, int workspace)
                } else {
                        if (scr->workspaces[i]->name)
                                wfree(scr->workspaces[i]->name);
+                       if (scr->workspaces[i]->map)
+                               RReleaseImage(scr->workspaces[i]->map);
                        wfree(scr->workspaces[i]);
                }
        }
@@ -473,6 +476,9 @@ void wWorkspaceForceChange(WScreen * scr, int workspace)
        if (workspace >= MAX_WORKSPACES || workspace < 0)
                return;
 
+       if (!wPreferences.disable_workspace_pager && 
!process_workspacemap_event)
+               wWorkspaceMapUpdate(scr);
+
        SendHelperMessage(scr, 'C', workspace + 1, NULL);
 
        if (workspace > scr->workspace_count - 1)
diff --git a/src/workspace.h b/src/workspace.h
index 69d1b187..0c93a2fc 100644
--- a/src/workspace.h
+++ b/src/workspace.h
@@ -27,6 +27,7 @@
 typedef struct WWorkspace {
     char *name;
     struct WDock *clip;
+    RImage *map;
 } WWorkspace;
 
 void wWorkspaceMake(WScreen *scr, int count);
diff --git a/src/wsmap.c b/src/wsmap.c
new file mode 100755
index 00000000..e1064fc6
--- /dev/null
+++ b/src/wsmap.c
@@ -0,0 +1,566 @@
+/*  wsmap.c - worskpace map
+ *
+ *  Window Maker window manager
+ *
+ *  Copyright (c) 2014 Window Maker Team - David Maciejak
+ *
+ *  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 "wconfig.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#ifdef USE_XSHAPE
+#include <X11/extensions/shape.h>
+#endif
+
+#include "screen.h"
+#include "window.h"
+#include "misc.h"
+#include "workspace.h"
+#include "wsmap.h"
+
+#include "WINGs/WINGsP.h"
+
+
+static const int WORKSPACE_MAP_RATIO  = 10;
+static const int WORKSPACE_SEPARATOR_WIDTH = 12;
+static const int mini_workspace_per_line = 5;
+
+/*
+ * Used to store the index of the tenth displayed mini workspace
+ * will be 0 for workspaces number 0 to 9
+ * 1 for workspaces number 10 -> 19
+ */
+int wsmap_bulk_index;
+WMPixmap *frame_bg_focused;
+WMPixmap *frame_bg_unfocused;
+
+typedef struct {
+       WScreen *scr;
+       WMWindow *win;
+       int xcount, ycount;
+       int wswidth, wsheight;
+       int mini_workspace_width, mini_workspace_height;
+       int edge;
+       int border_width;
+} WWorkspaceMap;
+
+typedef struct {
+       WMButton *workspace_img_button;
+       WMLabel *workspace_label;
+} W_WorkspaceMap;
+
+void wWorkspaceMapUpdate(WScreen *scr)
+{
+       XImage *pimg;
+
+       pimg = XGetImage(dpy, scr->root_win, 0, 0,
+                        scr->scr_width, scr->scr_height,
+                        AllPlanes, ZPixmap);
+       if (pimg) {
+               RImage *apercu;
+
+               apercu = RCreateImageFromXImage(scr->rcontext, pimg, NULL);
+               XDestroyImage(pimg);
+
+               if (apercu) {
+                       RImage *tmp = 
scr->workspaces[scr->current_workspace]->map;
+
+                       if (tmp)
+                               RReleaseImage(tmp);
+
+                       scr->workspaces[scr->current_workspace]->map =
+                               RSmoothScaleImage(apercu,
+                                                 scr->scr_width / 
WORKSPACE_MAP_RATIO,
+                                                 scr->scr_height / 
WORKSPACE_MAP_RATIO);
+                       RReleaseImage(apercu);
+               }
+       }
+}
+
+static void workspace_map_slide(WWorkspaceMap *wsmap)
+{
+       if (wsmap->edge == WD_TOP)
+               SlideWindow(WMWidgetXID(wsmap->win), 0, -1 *wsmap->wsheight, 
wsmap->xcount, wsmap->ycount);
+       else
+               SlideWindow(WMWidgetXID(wsmap->win), 0, wsmap->scr->scr_height, 
wsmap->xcount, wsmap->ycount);
+}
+
+static void workspace_map_unslide(WWorkspaceMap *wsmap)
+{
+       if (wsmap->edge == WD_TOP)
+               SlideWindow(WMWidgetXID(wsmap->win), wsmap->xcount, 
wsmap->ycount, 0, -1 * wsmap->wsheight);
+       else
+               SlideWindow(WMWidgetXID(wsmap->win), wsmap->xcount, 
wsmap->ycount, 0, wsmap->scr->scr_height);
+}
+
+static void workspace_map_destroy(WWorkspaceMap *wsmap)
+{
+       workspace_map_unslide(wsmap);
+       WMUnmapWidget(wsmap->win);
+
+       if (wsmap->win) {
+               Window info_win = wsmap->scr->info_window;
+               XEvent ev;
+
+               ev.xclient.type = ClientMessage;
+               ev.xclient.message_type = w_global.atom.wm.ignore_focus_events;
+               ev.xclient.format = 32;
+               ev.xclient.data.l[0] = True;
+
+               XSendEvent(dpy, info_win, True, EnterWindowMask, &ev);
+               WMUnmapWidget(wsmap->win);
+
+               ev.xclient.data.l[0] = False;
+               XSendEvent(dpy, info_win, True, EnterWindowMask, &ev);
+               WMDestroyWidget(wsmap->win);
+
+               if (frame_bg_focused)
+                       WMReleasePixmap(frame_bg_focused);
+               if (frame_bg_unfocused)
+                       WMReleasePixmap(frame_bg_unfocused);
+       }
+       wfree(wsmap);
+}
+
+static void selected_workspace_callback(WMWidget *w, void *data)
+{
+       WWorkspaceMap *wsmap = (WWorkspaceMap *) data;
+       WMButton *click_button = w;
+
+       if (w && wsmap) {
+               int workspace_id = atoi(WMGetButtonText(click_button));
+
+               wWorkspaceChange(wsmap->scr, workspace_id);
+               process_workspacemap_event = False;
+       }
+}
+
+static void set_workspace_map_background_image(WWorkspaceMap *wsmap)
+{
+       Pixmap pixmap, mask;
+
+       if (wPreferences.wsmbackTexture->any.type == WTEX_PIXMAP) {
+               RImage *tmp = wTextureRenderImage(wPreferences.wsmbackTexture, 
wsmap->wswidth, wsmap->wsheight, WREL_FLAT);
+
+               if (!tmp)
+                       return;
+
+               RConvertImageMask(wsmap->scr->rcontext, tmp, &pixmap, &mask, 
250);
+               RReleaseImage(tmp);
+
+               if (!pixmap)
+                       return;
+
+               XSetWindowBackgroundPixmap(dpy, WMWidgetXID(wsmap->win), 
pixmap);
+
+#ifdef USE_XSHAPE
+               if (mask && w_global.xext.shape.supported)
+                       XShapeCombineMask(dpy, WMWidgetXID(wsmap->win), 
ShapeBounding, 0, 0, mask, ShapeSet);
+#endif
+
+               if (pixmap)
+                       XFreePixmap(dpy, pixmap);
+               if (mask)
+                       XFreePixmap(dpy, mask);
+       }
+}
+
+static void workspace_map_show(WWorkspaceMap *wsmap)
+{
+       WMMapSubwidgets(wsmap->win);
+       WMMapWidget(wsmap->win);
+       workspace_map_slide(wsmap);
+}
+
+static WMPixmap *get_frame_background_color(WWorkspaceMap *wsmap, unsigned int 
width, unsigned int height, int type)
+{
+       RImage *img;
+       WMPixmap *pix;
+
+       if (!wsmap->scr->window_title_texture[type])
+               return NULL;
+
+       img = wTextureRenderImage(wsmap->scr->window_title_texture[type], 
width, height, WREL_FLAT);
+       if (!img)
+               return NULL;
+
+       pix = WMCreatePixmapFromRImage(wsmap->scr->wmscreen, img, 128);
+       RReleaseImage(img);
+
+       return pix;
+}
+
+static void workspace_map_realize(WWorkspaceMap *wsmap, WMFrame *frame_border, 
W_WorkspaceMap *wsmap_array)
+{
+       int i, mini_workspace_cnt, general_index;
+       WMPixmap *frame_border_pixmap;
+       WMSize label_size;
+
+       WMRealizeWidget(wsmap->win);
+       set_workspace_map_background_image(wsmap);
+
+       frame_border_pixmap = get_frame_background_color(wsmap, wsmap->wswidth, 
wsmap->border_width, WS_FOCUSED);
+       WMSetWidgetBackgroundPixmap(frame_border, frame_border_pixmap);
+       WMReleasePixmap(frame_border_pixmap);
+
+       label_size = WMGetViewSize(W_VIEW(wsmap_array[0].workspace_label));
+       frame_bg_focused = get_frame_background_color(wsmap, label_size.width, 
label_size.height, WS_FOCUSED);
+       frame_bg_unfocused = get_frame_background_color(wsmap, 
label_size.width, label_size.height, WS_UNFOCUSED);
+
+       mini_workspace_cnt = (wsmap->scr->workspace_count <= 2 * 
mini_workspace_per_line) ? wsmap->scr->workspace_count : 2 * 
mini_workspace_per_line;
+       for (i = 0; i < mini_workspace_cnt; i++) {
+               general_index = i + wsmap_bulk_index * 2 * 
mini_workspace_per_line;
+               if (general_index == wsmap->scr->current_workspace) {
+                       
WMSetWidgetBackgroundPixmap(wsmap_array[i].workspace_label, frame_bg_focused);
+                       WMSetLabelTextColor(wsmap_array[i].workspace_label, 
wsmap->scr->window_title_color[WS_FOCUSED]);
+               } else {
+                       
WMSetWidgetBackgroundPixmap(wsmap_array[i].workspace_label, frame_bg_unfocused);
+                       WMSetLabelTextColor(wsmap_array[i].workspace_label, 
wsmap->scr->window_title_color[WS_UNFOCUSED]);
+               }
+       }
+}
+
+static WMPixmap *enlight_workspace(WScreen *scr, RImage *mini_wkspace_map)
+{
+       RImage *tmp = RCloneImage(mini_wkspace_map);
+       RColor color;
+       WMPixmap *icon;
+
+       color.red = color.green = color.blue = 0;
+       color.alpha = 160;
+       RLightImage(tmp, &color);
+       icon = WMCreatePixmapFromRImage(scr->wmscreen, tmp, 128);
+       RReleaseImage(tmp);
+
+       return icon;
+}
+
+static WMPixmap *dummy_background_pixmap(WWorkspaceMap *wsmap)
+{
+       RImage *img;
+       WMPixmap *icon;
+
+       img = RCreateImage(wsmap->wswidth, wsmap->wsheight, 0);
+
+       if (!img)
+               return NULL;
+
+       /* the workspace texture is not saved anywhere, so just using the 
default unfocus color */
+       if (wsmap->scr->window_title_texture[WS_UNFOCUSED]) {
+               RColor frame_bg_color;
+
+               frame_bg_color.red = 
wsmap->scr->window_title_texture[WS_UNFOCUSED]->solid.normal.red;
+               frame_bg_color.green = 
wsmap->scr->window_title_texture[WS_UNFOCUSED]->solid.normal.green;
+               frame_bg_color.blue = 
wsmap->scr->window_title_texture[WS_UNFOCUSED]->solid.normal.blue;
+               RFillImage(img, &frame_bg_color);
+       }
+
+       icon = WMCreatePixmapFromRImage(wsmap->scr->wmscreen, img, 128);
+       RReleaseImage(img);
+
+       return icon;
+}
+
+static void show_mini_workspace(WWorkspaceMap *wsmap, W_WorkspaceMap 
*wsmap_array, int max_mini_workspace)
+{
+       int index, space_width;
+       int border_width_adjustement = (wsmap->edge == WD_TOP) ? 0 : 
wsmap->border_width;
+       int font_height = WMFontHeight(wsmap->scr->info_text_font);
+
+       if (max_mini_workspace > mini_workspace_per_line)
+               space_width = (wsmap->wswidth - mini_workspace_per_line * 
wsmap->mini_workspace_width) / (mini_workspace_per_line + 1);
+       else
+               space_width = (wsmap->wswidth - max_mini_workspace * 
wsmap->mini_workspace_width) / (max_mini_workspace + 1);
+
+       for (index = 0; index <  max_mini_workspace; index++) {
+               int i , j;
+
+               j = index;
+
+               if (index >= mini_workspace_per_line) {
+                       i = 1;
+                       j -= mini_workspace_per_line;
+               } else {
+                       i = 0;
+               }
+               if (wsmap_array[index].workspace_img_button) {
+                       WMResizeWidget(wsmap_array[index].workspace_img_button, 
wsmap->mini_workspace_width, wsmap->mini_workspace_height);
+                       WMMoveWidget(wsmap_array[index].workspace_img_button, j 
* wsmap->mini_workspace_width + (j + 1) * space_width,
+                                    border_width_adjustement + 
WORKSPACE_SEPARATOR_WIDTH +
+                                    i * (wsmap->mini_workspace_height + 2 * 
WORKSPACE_SEPARATOR_WIDTH) + font_height);
+                       WMMapWidget(wsmap_array[index].workspace_img_button);
+               }
+               if (wsmap_array[index].workspace_label) {
+                       WMResizeWidget(wsmap_array[index].workspace_label, 
wsmap->mini_workspace_width, font_height);
+                       WMMoveWidget(wsmap_array[index].workspace_label, j * 
wsmap->mini_workspace_width + (j + 1) * space_width,
+                                    border_width_adjustement + 
WORKSPACE_SEPARATOR_WIDTH +
+                                    i * (wsmap->mini_workspace_height + 2 * 
WORKSPACE_SEPARATOR_WIDTH));
+                       WMMapWidget(wsmap_array[index].workspace_label);
+               }
+       }
+}
+
+static void hide_mini_workspace(W_WorkspaceMap *wsmap_array, int i)
+{
+       if (wsmap_array[i].workspace_img_button)
+               WMUnmapWidget(wsmap_array[i].workspace_img_button);
+       if (wsmap_array[i].workspace_label)
+               WMUnmapWidget(wsmap_array[i].workspace_label);
+}
+
+static  WMPixmap *get_mini_workspace(WWorkspaceMap *wsmap, int index) {
+       if (!wsmap->scr->workspaces[index]->map)
+               return dummy_background_pixmap(wsmap);
+
+       if (index == wsmap->scr->current_workspace)
+               return enlight_workspace(wsmap->scr,  
wsmap->scr->workspaces[index]->map);
+
+       return WMCreatePixmapFromRImage(wsmap->scr->wmscreen, wsmap-> 
scr->workspaces[index]->map, 128);
+}
+
+static void create_mini_workspace(WScreen *scr, WWorkspaceMap *wsmap, 
W_WorkspaceMap *wsmap_array)
+{
+       int workspace_index;
+       int mini_workspace_cnt;
+       char name[10];
+       WMButton *mini_workspace_btn;
+       WMPixmap *icon;
+
+       /* by default display the 10 first mini workspaces */
+       wsmap_bulk_index = 0;
+       mini_workspace_cnt = (scr->workspace_count <= 2 * 
mini_workspace_per_line) ? scr->workspace_count : 2 * mini_workspace_per_line;
+       for (workspace_index = 0; workspace_index < mini_workspace_cnt; 
workspace_index++) {
+               mini_workspace_btn = WMCreateButton(wsmap->win, WBTOnOff);
+               WMSetButtonBordered(mini_workspace_btn, 0);
+               WMLabel *workspace_name_label = WMCreateLabel(wsmap->win);
+               WMSetLabelFont(workspace_name_label, scr->info_text_font);
+               WMSetLabelText(workspace_name_label,  
scr->workspaces[workspace_index]->name);
+
+               wsmap_array[workspace_index].workspace_img_button = 
mini_workspace_btn;
+               wsmap_array[workspace_index].workspace_label = 
workspace_name_label;
+
+               WMSetButtonImagePosition(mini_workspace_btn, WIPImageOnly);
+               icon = get_mini_workspace(wsmap, workspace_index);
+               if (icon) {
+                       WMSetButtonImage(mini_workspace_btn, icon);
+                       WMReleasePixmap(icon);
+               }
+
+               snprintf(name, sizeof(name), "%d", workspace_index);
+               WMSetButtonText(mini_workspace_btn, name);
+               WMSetButtonAction(mini_workspace_btn, 
selected_workspace_callback, wsmap);
+       }
+       show_mini_workspace(wsmap, wsmap_array, mini_workspace_cnt);
+}
+
+static WWorkspaceMap *create_workspace_map(WScreen *scr, W_WorkspaceMap 
*wsmap_array, int edge)
+{
+       WWorkspaceMap *wsmap = wmalloc(sizeof(WWorkspaceMap));
+
+       wsmap->border_width = 5;
+       wsmap->edge = edge;
+       wsmap->mini_workspace_width = scr->scr_width / WORKSPACE_MAP_RATIO;
+       wsmap->mini_workspace_height = scr->scr_height / WORKSPACE_MAP_RATIO;
+
+        if (scr->workspace_count == 0)
+                return NULL;
+
+       wsmap->scr = scr;
+       wsmap->win = WMCreateWindow(scr->wmscreen, "wsmap");
+       wsmap->wswidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
+       wsmap->wsheight = WMFontHeight(scr->info_text_font) + 
(wsmap->mini_workspace_height + 2 * WORKSPACE_SEPARATOR_WIDTH) *
+                                                               
(scr->workspace_count > mini_workspace_per_line ? 2 : 1);
+
+       if (wPreferences.wsmbackTexture->any.type == WTEX_SOLID) {
+               WMColor *tmp = WMCreateRGBColor(scr->wmscreen,
+                                                       
wPreferences.wsmbackTexture->any.color.red,
+                                                       
wPreferences.wsmbackTexture->any.color.green,
+                                                       
wPreferences.wsmbackTexture->any.color.blue,
+                                                       False);
+               WMSetWidgetBackgroundColor(wsmap->win, tmp);
+               WMReleaseColor(tmp);
+       }
+       WMResizeWidget(wsmap->win, wsmap->wswidth, wsmap->wsheight + 
wsmap->border_width);
+
+       WMFrame *framel = WMCreateFrame(wsmap->win);
+       WMResizeWidget(framel, wsmap->wswidth, wsmap->border_width);
+       WMSetFrameRelief(framel, WRSimple);
+       wWorkspaceMapUpdate(scr);
+
+       wsmap->xcount = 0;
+       if (edge == WD_TOP) {
+               wsmap->ycount = 0;
+               WMMoveWidget(framel, 0, wsmap->wsheight);
+       } else {
+               wsmap->ycount = scr->scr_height - wsmap->wsheight - 
wsmap->border_width;
+               WMMoveWidget(framel, 0, 0);
+       }
+
+       create_mini_workspace(scr, wsmap, wsmap_array);
+       workspace_map_realize(wsmap, framel, wsmap_array);
+
+       return wsmap;
+}
+
+static void update_mini_workspace(WWorkspaceMap *wsmap, W_WorkspaceMap 
*wsmap_array, int bulk_of_ten)
+{
+       int local_index, general_index;
+       int mini_workspace_cnt;
+       char name[10];
+       WMPixmap *icon;
+
+       if (bulk_of_ten == wsmap_bulk_index)
+               return;
+
+       if (bulk_of_ten < 0)
+               return;
+
+       if (wsmap->scr->workspace_count <= bulk_of_ten * 2 * 
mini_workspace_per_line)
+               return;
+
+       wsmap_bulk_index = bulk_of_ten;
+
+       mini_workspace_cnt = wsmap->scr->workspace_count - wsmap_bulk_index * 2 
* mini_workspace_per_line;
+       if (mini_workspace_cnt > 2 * mini_workspace_per_line)
+               mini_workspace_cnt = 2 * mini_workspace_per_line;
+
+       for (local_index = 0; local_index <  2 * mini_workspace_per_line; 
local_index++) {
+               general_index = local_index + wsmap_bulk_index * 2 * 
mini_workspace_per_line;
+               if (general_index < wsmap->scr->workspace_count) {
+                       /* updating label */
+                       
WMSetLabelText(wsmap_array[local_index].workspace_label, wsmap-> 
scr->workspaces[general_index]->name);
+                       snprintf(name, sizeof(name), "%d", general_index);
+                       
WMSetButtonText(wsmap_array[local_index].workspace_img_button, name);
+
+                       /* updating label background*/
+                       if (general_index == wsmap->scr->current_workspace) {
+                               
WMSetWidgetBackgroundPixmap(wsmap_array[local_index].workspace_label, 
frame_bg_focused);
+                               
WMSetLabelTextColor(wsmap_array[local_index].workspace_label, 
wsmap->scr->window_title_color[WS_FOCUSED]);
+                       } else {
+                               
WMSetWidgetBackgroundPixmap(wsmap_array[local_index].workspace_label, 
frame_bg_unfocused);
+                               
WMSetLabelTextColor(wsmap_array[local_index].workspace_label, 
wsmap->scr->window_title_color[WS_UNFOCUSED]);
+                       }
+
+                       icon = get_mini_workspace(wsmap, general_index);
+                       if (icon) {
+                               
WMSetButtonImage(wsmap_array[local_index].workspace_img_button, icon);
+                               WMReleasePixmap(icon);
+                       }
+               } else {
+                       if (local_index < wsmap->scr->workspace_count)
+                               hide_mini_workspace(wsmap_array, local_index);
+               }
+       }
+       show_mini_workspace(wsmap, wsmap_array, mini_workspace_cnt);
+}
+
+static void handle_event(WWorkspaceMap *wsmap, W_WorkspaceMap *wsmap_array)
+{
+       XEvent ev;
+       int modifiers;
+       KeyCode escKey = XKeysymToKeycode(dpy, XK_Escape);
+
+       XGrabKeyboard(dpy, WMWidgetXID(wsmap->win), False, GrabModeAsync, 
GrabModeAsync, CurrentTime);
+       XGrabPointer(dpy, WMWidgetXID(wsmap->win), True,
+                    ButtonMotionMask | ButtonReleaseMask | ButtonPressMask,
+                    GrabModeAsync, GrabModeAsync, WMWidgetXID(wsmap->win), 
None, CurrentTime);
+
+       process_workspacemap_event = True;
+       while (process_workspacemap_event) {
+               WMMaskEvent(dpy, KeyPressMask | KeyReleaseMask | ExposureMask
+                           | PointerMotionMask | ButtonPressMask | 
ButtonReleaseMask | EnterWindowMask, &ev);
+
+               if (!wsmap)
+                       break;
+               modifiers = ev.xkey.state & w_global.shortcut.modifiers_mask;
+
+               switch (ev.type) {
+               case KeyPress:
+                       if (ev.xkey.keycode == escKey || 
(wKeyBindings[WKBD_WORKSPACEMAP].keycode != 0 &&
+                                                         
wKeyBindings[WKBD_WORKSPACEMAP].keycode == ev.xkey.keycode &&
+                                                         
wKeyBindings[WKBD_WORKSPACEMAP].modifier == modifiers)) {
+                               process_workspacemap_event = False;
+                       } else {
+                               KeySym ks;
+                               int bulk_id;
+
+                               XLookupString(&ev.xkey, NULL, 16, &ks, NULL);
+
+                               bulk_id = -1;
+                               if (ks >= 0x30 && ks <= 0x39)
+                                       bulk_id = ks - 0x30;
+                               else
+                                       if (ks == XK_Left)
+                                               bulk_id = wsmap_bulk_index - 1;
+                                       else if (ks == XK_Right)
+                                                       bulk_id = 
wsmap_bulk_index + 1;
+
+                               if (bulk_id >= 0)
+                                       update_mini_workspace(wsmap, 
wsmap_array, bulk_id);
+                       }
+                       break;
+
+               case ButtonPress:
+                       switch (ev.xbutton.button) {
+                       case Button6:
+                               update_mini_workspace(wsmap, wsmap_array, 
wsmap_bulk_index - 1);
+                               break;
+                       case Button7:
+                               update_mini_workspace(wsmap, wsmap_array, 
wsmap_bulk_index + 1);
+                               break;
+                       default:
+                               WMHandleEvent(&ev);
+                       }
+                       break;
+
+               default:
+                       WMHandleEvent(&ev);
+                       break;
+               }
+       }
+
+       XUngrabPointer(dpy, CurrentTime);
+       XUngrabKeyboard(dpy, CurrentTime);
+
+       if (wsmap)
+               workspace_map_destroy(wsmap);
+}
+
+static WWorkspaceMap *init_workspace_map(WScreen *scr, W_WorkspaceMap 
*wsmap_array)
+{
+       WWorkspaceMap *wsmap;
+
+       wsmap = create_workspace_map(scr, wsmap_array, WD_BOTTOM);
+       return wsmap;
+}
+
+void StartWorkspaceMap(WScreen *scr)
+{
+       WWorkspaceMap *wsmap;
+       W_WorkspaceMap wsmap_array[2 * mini_workspace_per_line];
+
+       /* save the current screen before displaying the workspace map */
+       wWorkspaceMapUpdate(scr);
+
+       wsmap = init_workspace_map(scr, wsmap_array);
+       if (wsmap) {
+               workspace_map_show(wsmap);
+               handle_event(wsmap, wsmap_array);
+       }
+}
diff --git a/src/wsmap.h b/src/wsmap.h
new file mode 100644
index 00000000..2133bd52
--- /dev/null
+++ b/src/wsmap.h
@@ -0,0 +1,28 @@
+/*
+ *  Window Maker window manager
+ *
+ *  Copyright (c) 2014 Window Maker Team
+ *
+ *  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, see the file COPYING.
+ */
+
+#ifndef WSMAP_H
+#define WSMAP_H
+
+Bool process_workspacemap_event;
+
+void wWorkspaceMapUpdate(WScreen *scr);
+void StartWorkspaceMap(WScreen *scr);
+
+#endif

http://repo.or.cz/w/wmaker-crm.git/commit/a864f1988fd7fd044633b319c40a8f0ab1b85658

commit a864f1988fd7fd044633b319c40a8f0ab1b85658
Author: David Maciejak <david.macie...@gmail.com>
Date:   Thu Dec 4 13:34:56 2014 +0700

    wmaker: add workspace pager underlying configuration
    
    This path is adding the functions and variables needed for workspace pager 
preferences.
    An option to enable/disable the workspace pager, and one to set a default 
background image.

diff --git a/WindowMaker/Defaults/WindowMaker.in 
b/WindowMaker/Defaults/WindowMaker.in
index 5b6203b3..c68feeff 100644
--- a/WindowMaker/Defaults/WindowMaker.in
+++ b/WindowMaker/Defaults/WindowMaker.in
@@ -3,6 +3,7 @@
   PopupSwitchMenu = NO;
   MenuStyle = normal;
   DisableMiniwindows = NO;
+  DisableWorkspacePager = NO;
   OpenTransientOnOwnerWorkspace = NO;
   EdgeResistance = 30;
   WorkspaceBorderSize = 0;
diff --git a/src/WindowMaker.h b/src/WindowMaker.h
index 0663b546..ce0a86c9 100644
--- a/src/WindowMaker.h
+++ b/src/WindowMaker.h
@@ -393,6 +393,8 @@ extern struct WPreferences {
        char sticky_icons;                 /* If miniwindows will be 
onmipresent */
        char dont_confirm_kill;            /* do not confirm Kill application */
        char disable_miniwindows;
+       char disable_workspace_pager;
+
        char dont_blink;                   /* do not blink icon selection */
 
        /* Appearance options */
@@ -455,6 +457,8 @@ extern struct WPreferences {
        RImage *swtileImage;
        RImage *swbackImage[9];
 
+       union WTexture *wsmbackTexture;
+
        int show_clip_title;
 
        struct {
diff --git a/src/defaults.c b/src/defaults.c
index fff239f2..b1b5050a 100644
--- a/src/defaults.c
+++ b/src/defaults.c
@@ -4,6 +4,8 @@
  *
  *  Copyright (c) 1997-2003 Alfredo K. Kojima
  *  Copyright (c) 1998-2003 Dan Pascu
+ *  Copyright (c) 2014 Window Maker Team
+
  *
  *  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
@@ -144,6 +146,7 @@ static WDECallbackUpdate setHightlightText;
 static WDECallbackUpdate setKeyGrab;
 static WDECallbackUpdate setDoubleClick;
 static WDECallbackUpdate setIconPosition;
+static WDECallbackUpdate setWorkspaceMapBackground;
 
 static WDECallbackUpdate setClipTitleFont;
 static WDECallbackUpdate setClipTitleColor;
@@ -348,7 +351,9 @@ WDefaultEntry staticOptionList[] = {
        {"ClipMergedInDock", "NO", NULL,
            NULL, getBool, setClipMergedInDock, NULL, NULL},
        {"DisableMiniwindows", "NO", NULL,
-           &wPreferences.disable_miniwindows, getBool, NULL, NULL, NULL}
+           &wPreferences.disable_miniwindows, getBool, NULL, NULL, NULL},
+       {"DisableWorkspacePager", "NO", NULL,
+           &wPreferences.disable_workspace_pager, getBool, NULL, NULL, NULL}
 };
 
 #define NUM2STRING_(x) #x
@@ -598,6 +603,8 @@ WDefaultEntry optionList[] = {
            NULL, getColor, setFrameFocusedBorderColor, NULL, NULL},
        {"FrameSelectedBorderColor", "white", NULL,
            NULL, getColor, setFrameSelectedBorderColor, NULL, NULL},
+       {"WorkspaceMapBack", "(solid, black)", NULL,
+           NULL, getTexture, setWorkspaceMapBackground, NULL, NULL},
 
        /* keybindings */
 
@@ -659,6 +666,8 @@ WDefaultEntry optionList[] = {
            NULL, getKeybind, setKeyGrab, NULL, NULL},
        {"SelectKey", "None", (void *)WKBD_SELECT,
            NULL, getKeybind, setKeyGrab, NULL, NULL},
+       {"WorkspaceMapKey", "None", (void *)WKBD_WORKSPACEMAP,
+           NULL, getKeybind, setKeyGrab, NULL, NULL},
        {"FocusNextKey", "None", (void *)WKBD_FOCUSNEXT,
            NULL, getKeybind, setKeyGrab, NULL, NULL},
        {"FocusPrevKey", "None", (void *)WKBD_FOCUSPREV,
@@ -3242,6 +3251,22 @@ static int updateUsableArea(WScreen * scr, WDefaultEntry 
* entry, void *bar, voi
        return 0;
 }
 
+static int setWorkspaceMapBackground(WScreen *scr, WDefaultEntry *entry, void 
*tdata, void *foo)
+{
+       WTexture **texture = tdata;
+
+       /* Parameter not used, but tell the compiler that it is ok */
+       (void) entry;
+       (void) foo;
+
+       if (wPreferences.wsmbackTexture)
+               wTextureDestroy(scr, wPreferences.wsmbackTexture);
+
+       wPreferences.wsmbackTexture = *texture;
+
+       return REFRESH_WINDOW_TEXTURES;
+}
+
 static int setMenuStyle(WScreen * scr, WDefaultEntry * entry, void *tdata, 
void *foo)
 {
        /* Parameter not used, but tell the compiler that it is ok */
diff --git a/src/keybind.h b/src/keybind.h
index 4aaadd47..87a5cdc3 100644
--- a/src/keybind.h
+++ b/src/keybind.h
@@ -69,6 +69,7 @@ enum {
        WKBD_RAISELOWER,
        WKBD_MOVERESIZE,
        WKBD_SHADE,
+       WKBD_WORKSPACEMAP,
        WKBD_FOCUSNEXT,
        WKBD_FOCUSPREV,
        WKBD_GROUPNEXT,

http://repo.or.cz/w/wmaker-crm.git/commit/c94fc4ba39f2b3a0b8e3ed5e56a35c42cc36cd01

commit c94fc4ba39f2b3a0b8e3ed5e56a35c42cc36cd01
Author: David Maciejak <david.macie...@gmail.com>
Date:   Thu Dec 4 13:30:27 2014 +0700

    WPrefs: add workspace pager configuration
    
    This patch is adding a checkbox in the expert zone to disable
    completely the workspace pager and add an entry in keyshortcut
    preference to set the shortcut used to open the pager with the
    action "Open workspace pager".
    
    The default frame background can be configured by setting an optional
    variable "WorkspaceMapBack" from WindowMaker conf file as in:
    
    WorkspaceMapBack = (tpixmap, "/tmp/testme.png", gray20);
    
    or
    
    WorkspaceMapBack = (solid, "#2c2482");

diff --git a/WPrefs.app/Expert.c b/WPrefs.app/Expert.c
index 84e4eb40..dc455dd8 100644
--- a/WPrefs.app/Expert.c
+++ b/WPrefs.app/Expert.c
@@ -43,6 +43,9 @@ static const struct {
        { N_("Disable miniwindows (icons for minimized windows). For use with 
KDE/GNOME."),
          /* default: */ False, OPTION_WMAKER, "DisableMiniwindows" },
 
+       { N_("Disable workspace pager"),
+         /* default: */ False, OPTION_WMAKER, "DisableWorkspacePager" },
+
        { N_("Do not set non-WindowMaker specific parameters (do not use 
xset)."),
          /* default: */ False, OPTION_USERDEF, "NoXSetStuff" },
 
diff --git a/WPrefs.app/KeyboardShortcuts.c b/WPrefs.app/KeyboardShortcuts.c
index 414d479f..6984a918 100644
--- a/WPrefs.app/KeyboardShortcuts.c
+++ b/WPrefs.app/KeyboardShortcuts.c
@@ -102,6 +102,7 @@ static const struct {
        { "GroupPrevKey",   N_("Focus previous group window") },
 
        /* Workspace Related */
+       { "WorkspaceMapKey",  N_("Open workspace pager") },
        { "NextWorkspaceKey", N_("Switch to next workspace") },
        { "PrevWorkspaceKey", N_("Switch to previous workspace") },
        { "LastWorkspaceKey", N_("Switch to last used workspace") },

http://repo.or.cz/w/wmaker-crm.git/commit/467b7ee4560f124f7469a2a630cb35d477cc0444

commit 467b7ee4560f124f7469a2a630cb35d477cc0444
Author: David Maciejak <david.macie...@gmail.com>
Date:   Fri Dec 5 06:08:48 2014 +0700

    WINGs: increment version
    
    This patch is incrementing version number as the API changed.

diff --git a/WINGs/WINGs/WINGs.h b/WINGs/WINGs/WINGs.h
index ca7be553..47981744 100644
--- a/WINGs/WINGs/WINGs.h
+++ b/WINGs/WINGs/WINGs.h
@@ -26,7 +26,7 @@
 #include <WINGs/WUtil.h>
 #include <X11/Xlib.h>
 
-#define WINGS_H_VERSION  20140612
+#define WINGS_H_VERSION  20141205
 
 
 #ifdef __cplusplus
diff --git a/configure.ac b/configure.ac
index d7ccdaec..65b12c42 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,7 +47,7 @@ 
WRASTER_VERSION=$WRASTER_CURRENT:$WRASTER_REVISION:$WRASTER_AGE
 AC_SUBST(WRASTER_VERSION)
 dnl
 dnl libWINGs
-WINGS_CURRENT=3
+WINGS_CURRENT=4
 WINGS_REVISION=0
 WINGS_AGE=0
 WINGS_VERSION=$WINGS_CURRENT:$WINGS_REVISION:$WINGS_AGE

http://repo.or.cz/w/wmaker-crm.git/commit/c10469264d70075a26a13ac2db5281822a2a2210

commit c10469264d70075a26a13ac2db5281822a2a2210
Author: David Maciejak <david.macie...@gmail.com>
Date:   Thu Dec 4 13:25:55 2014 +0700

    WINGs: add functions to set widget background image
    
    With this patch we can set widget background image.
    As now, only background color was available.

diff --git a/WINGs/WINGs/WINGs.h b/WINGs/WINGs/WINGs.h
index e460ef43..ca7be553 100644
--- a/WINGs/WINGs/WINGs.h
+++ b/WINGs/WINGs/WINGs.h
@@ -930,6 +930,10 @@ void WMSetWidgetBackgroundColor(WMWidget *w, WMColor 
*color);
 
 WMColor* WMGetWidgetBackgroundColor(WMWidget *w);
 
+void WMSetWidgetBackgroundPixmap(WMWidget *w, WMPixmap *pix);
+
+WMPixmap *WMGetWidgetBackgroundPixmap(WMWidget *w);
+
 void WMMapSubwidgets(WMWidget *w);
 
 void WMUnmapSubwidgets(WMWidget *w);
diff --git a/WINGs/WINGs/WINGsP.h b/WINGs/WINGs/WINGsP.h
index 2484b25d..fc18b1cb 100644
--- a/WINGs/WINGs/WINGsP.h
+++ b/WINGs/WINGs/WINGsP.h
@@ -572,6 +572,8 @@ struct W_View {
     void *hangedData;                  /* data holder for user program */
 
     WMColor *backColor;
+    WMPixmap *backImage;
+
 
     Cursor cursor;
 
@@ -664,6 +666,8 @@ void W_ResizeView(W_View *view, unsigned int width, 
unsigned int height);
 
 void W_SetViewBackgroundColor(W_View *view, WMColor *color);
 
+void W_SetViewBackgroundPixmap(W_View *view, WMPixmap *pix);
+
 void W_SetViewCursor(W_View *view, Cursor cursor);
 
 void W_SetFocusOfTopLevel(W_View *toplevel, W_View *view);
diff --git a/WINGs/widgets.c b/WINGs/widgets.c
index 75b44e70..87fa9d62 100644
--- a/WINGs/widgets.c
+++ b/WINGs/widgets.c
@@ -960,6 +960,21 @@ WMColor *WMGetWidgetBackgroundColor(WMWidget * w)
        return W_VIEW(w)->backColor;
 }
 
+void WMSetWidgetBackgroundPixmap(WMWidget *w, WMPixmap *pix)
+{
+       if (!pix)
+               return;
+
+       W_SetViewBackgroundPixmap(W_VIEW(w), pix);
+       if (W_VIEW(w)->flags.mapped)
+               WMRedisplayWidget(w);
+}
+
+WMPixmap *WMGetWidgetBackgroundPixmap(WMWidget *w)
+{
+       return W_VIEW(w)->backImage;
+}
+
 void WMRaiseWidget(WMWidget * w)
 {
        W_RaiseView(W_VIEW(w));
diff --git a/WINGs/wmisc.c b/WINGs/wmisc.c
index 331dc401..ba4c8a6a 100644
--- a/WINGs/wmisc.c
+++ b/WINGs/wmisc.c
@@ -220,12 +220,20 @@ W_PaintTextAndImage(W_View * view, int wrap, WMColor * 
textColor, W_Font * font,
                XFillRectangle(screen->display, d, WMColorGC(backColor),
                               0, 0, view->size.width, view->size.height);
        } else {
+               if (view->attribs.background_pixmap) {
 #ifndef DOUBLE_BUFFER
-               XClearWindow(screen->display, d);
+                       XClearWindow(screen->display, d);
 #else
-               XSetForeground(screen->display, screen->copyGC, 
view->attribs.background_pixel);
-               XFillRectangle(screen->display, d, screen->copyGC, 0, 0, 
view->size.width, view->size.height);
+                       XCopyArea(screen->display, 
view->attribs.background_pixmap, d, screen->copyGC, 0, 0, view->size.width, 
view->size.height, 0, 0);
 #endif
+               } else {
+#ifndef DOUBLE_BUFFER
+                       XClearWindow(screen->display, d);
+#else
+                       XSetForeground(screen->display, screen->copyGC, 
view->attribs.background_pixel);
+                       XFillRectangle(screen->display, d, screen->copyGC, 0, 
0, view->size.width, view->size.height);
+#endif
+               }
        }
 
        if (relief == WRFlat) {
diff --git a/WINGs/wview.c b/WINGs/wview.c
index 20662447..610e640a 100644
--- a/WINGs/wview.c
+++ b/WINGs/wview.c
@@ -100,7 +100,8 @@ static W_View *createView(W_Screen * screen, W_View * 
parent)
                view->attribFlags = CWEventMask | CWBitGravity;
                view->attribs = defAtts;
 
-               view->attribFlags |= CWBackPixel | CWColormap | CWBorderPixel;
+                view->attribFlags |= CWBackPixel | CWColormap | CWBorderPixel 
| CWBackPixmap;
+                view->attribs.background_pixmap = None;
                view->attribs.background_pixel = W_PIXEL(screen->gray);
                view->attribs.border_pixel = W_PIXEL(screen->black);
                view->attribs.colormap = screen->colormap;
@@ -496,6 +497,20 @@ void W_SetViewBackgroundColor(W_View * view, WMColor * 
color)
        }
 }
 
+void W_SetViewBackgroundPixmap(W_View *view, WMPixmap *pix)
+{
+       if (view->backImage)
+               WMReleasePixmap(view->backImage);
+       view->backImage = WMRetainPixmap(pix);
+
+       view->attribFlags |= CWBackPixmap;
+       view->attribs.background_pixmap = pix->pixmap;
+       if (view->flags.realized) {
+               XSetWindowBackgroundPixmap(view->screen->display, view->window, 
pix->pixmap);
+               XClearWindow(view->screen->display, view->window);
+       }
+}
+
 void W_SetViewCursor(W_View * view, Cursor cursor)
 {
        view->cursor = cursor;

http://repo.or.cz/w/wmaker-crm.git/commit/47ac986b5336869236fefb748a066d936c590f19

commit 47ac986b5336869236fefb748a066d936c590f19
Author: Christophe CURIS <christophe.cu...@free.fr>
Date:   Fri Dec 5 18:02:43 2014 +0100

    Make sub-directories visible the automake's "dist*" targets
    
    We have a few directories with source codes that we tell configure to
    prepare, but we do not actually want them built during normal operations
    (tests and examples only).
    
    However, there are some special targets brought by automake which still
    need to see them, so this patch adds these directories to the list, but
    only for these rules, we keep them unvisited by the normal build process.
    
    The wanted side effect of this is that now "make distcheck" works untill
    the end as expectable.
    
    Signed-off-by: Christophe CURIS <christophe.cu...@free.fr>

diff --git a/WINGs/Makefile.am b/WINGs/Makefile.am
index 03c6e289..017f1d7e 100644
--- a/WINGs/Makefile.am
+++ b/WINGs/Makefile.am
@@ -3,6 +3,7 @@
 AUTOMAKE_OPTIONS =
 
 SUBDIRS = WINGs . po Documentation Resources
+DIST_SUBDIRS = $(SUBDIRS) Tests Examples Extras
 
 libWINGs_la_LDFLAGS = -version-info @WINGS_VERSION@
 libWUtil_la_LDFLAGS = -version-info @WUTIL_VERSION@
diff --git a/wrlib/Makefile.am b/wrlib/Makefile.am
index a9e6e83d..c21c0ced 100644
--- a/wrlib/Makefile.am
+++ b/wrlib/Makefile.am
@@ -1,6 +1,7 @@
 ## automake input file for wrlib
 
 SUBDIRS = .
+DIST_SUBDIRS = $(SUBDIRS) tests
 
 AUTOMAKE_OPTIONS =
 

http://repo.or.cz/w/wmaker-crm.git/commit/12babda9e7050a95789cc4173b072e2e815e1fbc

commit 12babda9e7050a95789cc4173b072e2e815e1fbc
Author: Christophe CURIS <christophe.cu...@free.fr>
Date:   Fri Dec 5 18:02:42 2014 +0100

    WPrefs: link against math library because it is used in a few places
    
    The code is making use of a few of the libm functions, but it looks like
    gcc adds automatically the libm dependency (either by trying to be smart or
    as an inherited dependency?).
    
    Apparently, when compiling with clang-3.5 the function 'round' still needs
    the use of math library (the others do not seem to), so this patch adds it
    to the list of link libraries, which is more portable.
    
    Signed-off-by: Christophe CURIS <christophe.cu...@free.fr>

diff --git a/WPrefs.app/Makefile.am b/WPrefs.app/Makefile.am
index c1424262..f77ddd4a 100644
--- a/WPrefs.app/Makefile.am
+++ b/WPrefs.app/Makefile.am
@@ -57,5 +57,6 @@ WPrefs_LDADD =        $(top_builddir)/WINGs/libWUtil.la       
$(top_builddir)/wrlib/libwraster.la     @XLFLAGS@ @XLIBS@ +     @LIBM@          
@FCLIBS@        @INTLIBS@

http://repo.or.cz/w/wmaker-crm.git/commit/80f18f60d239499d3d266bf3a6a7e5e78374aca7

commit 80f18f60d239499d3d266bf3a6a7e5e78374aca7
Author: Christophe CURIS <christophe.cu...@free.fr>
Date:   Fri Dec 5 18:02:41 2014 +0100

    WPrefs: Use standard C declaration of array instead of GNU syntax
    
    As pointed by Clang, the declaration of array was using the GNU old syntax,
    not the standard C.

diff --git a/WPrefs.app/Appearance.c b/WPrefs.app/Appearance.c
index 9e0e8a6a..c8cbc75e 100644
--- a/WPrefs.app/Appearance.c
+++ b/WPrefs.app/Appearance.c
@@ -97,9 +97,9 @@ static const struct {
        const char *db_value;
        const char *file_name;
 } menu_style[] = {
-       [MSTYLE_NORMAL] { "normal",        "msty1" },
-       [MSTYLE_SINGLE] { "singletexture", "msty2" },
-       [MSTYLE_FLAT]   { "flat",          "msty3" }
+       [MSTYLE_NORMAL] = { "normal",        "msty1" },
+       [MSTYLE_SINGLE] = { "singletexture", "msty2" },
+       [MSTYLE_FLAT]   = { "flat",          "msty3" }
 };
 
 /********************************************************************/
@@ -107,9 +107,9 @@ static const struct {
        const char *label;
        const char *db_value;
 } wintitle_align[] = {
-       [WALeft]   { N_("Left"),   "left"   },
-       [WACenter] { N_("Center"), "center" },
-       [WARight]  { N_("Right"),  "right"  }
+       [WALeft]   = { N_("Left"),   "left"   },
+       [WACenter] = { N_("Center"), "center" },
+       [WARight]  = { N_("Right"),  "right"  }
 };
 
 /********************************************************************/

http://repo.or.cz/w/wmaker-crm.git/commit/10371836ed5637c2faf718873b5866c7a8314134

commit 10371836ed5637c2faf718873b5866c7a8314134
Author: Christophe CURIS <christophe.cu...@free.fr>
Date:   Fri Dec 5 18:02:40 2014 +0100

    wmaker: work around compilers that do not support nested functions
    
    There are a few cases in which nested functions are an helpful way to write
    code, as this is explained in 'script/nested-func-to-macro.sh'. However,
    some compiler do not support them (like clang), so this patch proposes an
    elegant solution, where developers can get the benefit of them, but for
    users they are automatically converted to C macro if needed.
    
    The advantage of this solution is that we keep the code simple, there is no
    hack in the source (like #ifdef and code duplication), yet still having the
    full advantages.
    
    The translation is done according to what have been detected by configure
    (see the WM_PROG_CC_NESTEDFUNC macro) so that user has nothing to do.
    
    Signed-off-by: Christophe CURIS <christophe.cu...@free.fr>

diff --git a/Makefile.am b/Makefile.am
index 7fd4174b..34038cb7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -36,7 +36,8 @@ EXTRA_DIST = TODO BUGS BUGFORM FAQ FAQ.I18N INSTALL   
INSTALL-WMAKER README.definable-cursor          
The-perfect-Window-Maker-patch.txt      README COPYING.WTFPL autogen.sh -       
email-clients.txt checkpatch.pl update-changelog.pl
+       email-clients.txt checkpatch.pl update-changelog.pl +   
script/nested-func-to-macro.sh
 
 if USE_LCOV
 coverage-reset:
diff --git a/configure.ac b/configure.ac
index 7097e9d9..d7ccdaec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -158,6 +158,12 @@ AS_IF([test "x$debug" = "xyes"],
      AX_CFLAGS_GCC_OPTION([-Wno-deprecated-declarations])
 ])
 
+
+dnl Support for Nested Functions by the compiler
+dnl ============================================
+WM_PROG_CC_NESTEDFUNC
+
+
 dnl Posix thread
 dnl =================
 AX_PTHREAD
@@ -905,6 +911,9 @@ AS_IF([test "x$debug" = "xyes"],
     [AS_ECHO(["Debug enabled: CFLAGS = $CFLAGS"]) ])
 echo
 
+AS_IF([test "x$wm_cv_prog_cc_nestedfunc" != "xyes"],
+    [AC_MSG_WARN([[Your compiler does not support Nested Function, work-around 
enabled]])])
+
 dnl WM_PRINT_REDCRAP_BUG_STATUS
 
 AS_IF([test "x$enable_jpeg" = xno], [dnl
diff --git a/m4/wm_prog_cc_c11.m4 b/m4/wm_prog_cc_c11.m4
index fbdbffb7..cf846998 100644
--- a/m4/wm_prog_cc_c11.m4
+++ b/m4/wm_prog_cc_c11.m4
@@ -46,3 +46,41 @@ AS_CASE([$wm_cv_prog_cc_c11],
     [no|native], [],
     [CFLAGS="$CFLAGS $wm_cv_prog_cc_c11"])
 ])
+
+
+# WM_PROG_CC_NESTEDFUNC
+# ---------------------
+#
+# Check if the compiler support declaring Nested Functions (that means
+# declaring a function inside another function).
+#
+# If the compiler does not support them, then the Automake conditional
+# USE_NESTED_FUNC will be set to false, in which case the Makefile will
+# use the script 'scripts/nested-func-to-macro.sh' to generate a modified
+# source with the nested function transformed into a Preprocessor Macro.
+AC_DEFUN_ONCE([WM_PROG_CC_NESTEDFUNC],
+[AC_CACHE_CHECK([if compiler supports nested functions], 
[wm_cv_prog_cc_nestedfunc],
+    [AC_COMPILE_IFELSE(
+        [AC_LANG_SOURCE([[
+int main(int narg, char **argv)
+{
+       int local_variable;
+
+       int nested_function(int argument)
+       {
+               /* Checking we have access to upper level's scope, otherwise it 
is of no use */
+               return local_variable + argument;
+       }
+
+       /* To avoid a warning for unused parameter, that may falsely fail */
+       (void) argv;
+
+       /* Initialise using the parameter to main so the compiler won't be 
tempted to optimise too much */
+       local_variable = narg + 1;
+
+       return nested_function(2);
+}]]) ],
+        [wm_cv_prog_cc_nestedfunc=yes],
+        [wm_cv_prog_cc_nestedfunc=no]) ])
+AM_CONDITIONAL([USE_NESTED_FUNC], [test "x$wm_cv_prog_cc_nestedfunc" != 
"xno"])dnl
+])
diff --git a/script/nested-func-to-macro.sh b/script/nested-func-to-macro.sh
new file mode 100755
index 00000000..416400fd
--- /dev/null
+++ b/script/nested-func-to-macro.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+###########################################################################
+#
+#  Window Maker window manager
+#
+#  Copyright (c) 2014 Christophe CURIS
+#  Copyright (c) 2014 Window Maker Team
+#
+#  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.
+#
+###########################################################################
+#
+# nested-func-to-macro.sh:
+#   from a C source file specified with "-i", convert the functions
+#   specified with "-f" into preprocessor macros ("#define") and save the
+#   result as the file specified with "-o"
+#
+# The goal is to process nested functions (functions defined inside other
+# functions), because some compilers do not support that, despite the
+# advantages against macros:
+#   - there is no side effect on arguments, like what macros does;
+#   - the compiler can check the type used for arguments;
+#   - the compiler can decide wether it is best to inline them or not;
+#   - they are better handled by text editors, mainly for indentation but
+# also because there is no more '' at end of lines;
+#   - generaly, error message from the compiler are a lot clearer.
+#
+# As opposed to simple static functions, there is a strong benefit because
+# they can access the local variables of the function in which they are
+# defined without needing extra arguments that may get complicated.
+#
+# These added values are important for developpement because they help keep
+# code simple (and so maintainable and with lower bug risk).
+#
+# Because this script convert them to macros (only if 'configure' detected
+# that the compiler does not support nested functions, see the macro
+# WM_PROG_CC_NESTEDFUNC), there are a few constraints when writing such
+# nested functions in the code:
+#
+#   - you cannot use the function's address (example: callback), but that
+# would be a bad idea anyway (in best case there's a penalty issue, in
+# worst case it can crash the program);
+#
+#   - you should be careful on what you're doing with the arguments of the
+# function, otherwise the macro's side effects will re-appear;
+#
+#   - you may need some extra '{}' when calling the function in an
+# if/for/while/... construct, because of the difference between a function
+# call and the macro that will be replaced (the macro will contain its own
+# pair of '{}' which will be followed by the ';' you use for the function
+# call;
+#
+#   - the prototype of the function must be on a single line, it must not
+# spread across multiple lines or replace will fail;
+#
+#   - you should follow the project's coding style, as hacky stuff may
+# make the script generate crap. And you don't want that to happen.
+#
+###########################################################################
+#
+# Please note that this script is writen in sh+awk on purpose: this script
+# is gonna be run on the machine of the person who is trying to compile
+# WindowMaker, and as such we cannot be sure to find any scripting language
+# in a known version and that works (python/ruby/tcl/perl/php/you-name-it).
+#
+# So for portability, we stick to the same sh+awk constraint as Autotools
+# to limit the problem, see for example:
+#   
http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Portable-Shell.html
+#
+###########################################################################
+
+# Report an error on stderr and exit with status 1 to tell make could not work
+arg_error() {
+    echo "$0: $@" >&2
+    exit 1
+}
+
+# print help and exit with success status
+print_help() {
+    echo "$0: convert nested functions into macros in C source"
+    echo "Usage: $0 [options...] input_file"
+    echo "valid options are:"
+    echo "  -f name : add 'name' to the list of function to process"
+    echo "  -o file : set output file"
+    exit 0
+}
+
+# Extract command line arguments
+while [ $# -gt 0 ]; do
+    case $1 in
+       -f)
+           shift
+           echo "$1" | grep -q '^[A-Z_a-z][A-Z_a-z0-9]*$' || arg_error 
"function name "$1" is not valid"
+           function_list="$function_list $1"
+         ;;
+
+       -h|-help|--help) print_help ;;
+       -o) shift ; output_file="$1" ;;
+       -*) arg_error "unknow option '$1'" ;;
+
+       *)
+           [ "x$input_file" = "x" ] || arg_error "only 1 input file can be 
specified, not "$input_file" and "$1""
+           input_file="$1"
+         ;;
+    esac
+    shift
+done
+
+# Check consistency of command-line
+[ "x$input_file" = "x" ] && arg_error "no source file given"
+[ "x$function_list" = "x" ] && arg_error "no function name were given, nothing 
to do"
+[ "x$output_file" = "x" ] && arg_error "no output file name specified"
+
+[ -r "$input_file" ] || arg_error "source file "$input_file" is not readable"
+
+# Declare a function that takes care of converting the function code into a
+# macro definition. All the code is considered part of the C function's body
+# until we have matched the right number of {} pairs
+awk_function_handler='
+function replace_definition(func_name)
+{
+   # Isolate the list of arguments from the rest of the line
+   # This code could be updated to handle arg list over multiple lines, but
+   # it would add unnecessary complexity because a function that big should
+   # probably be global static
+   arg_start = index($0, "(");
+   arg_end   = index($0, ")");
+   argsubstr = substr($0, arg_start + 1, arg_end - arg_start - 1);
+   remain    = substr($0, arg_end);
+
+   $0 = "#define " func_name "("
+
+   # Remove the types from the list of arguments
+   split(argsubstr, arglist, /,/);
+   separator = "";
+   for (i = 1; i <= length(arglist); i++) {
+      argname = substr(arglist[i], match(arglist[i], 
/[A-Z_a-z][A-Z_a-z0-9]*$/));
+      $0 = $0 separator argname;
+      separator = ", ";
+   }
+   delete arglist;
+   $0 = $0 remain;
+
+   # Count the number of pairs of {} and take next line until we get our 
matching count
+   is_first_line = 1;
+   nb_pair = 0;
+   while (1) {
+      # Count the opening braces
+      split($0, dummy, /{/);
+      nb_pair = nb_pair + (length(dummy) - 1);
+      delete dummy;
+
+      # Count the closing braces
+      split($0, dummy, /}/);
+      nb_pair = nb_pair - (length(dummy) - 1);
+      delete dummy;
+
+      # If we found the end of the function, stop now
+      if (nb_pair <= 0 && !is_first_line) {
+         # Note that we count on awk that is always executing the match-all
+         # pattern to print the current line in the $0 pattern
+         break;
+      }
+
+      # Otherwise, print current line with the macro continuation mark and grab
+      # next line to process it
+      $0 = $0 " \";
+      print;
+      getline;
+      is_first_line = 0;
+   }
+
+   # We mark the current macro as defined so it can be undefined at the end
+   func_defined[func_name] = 1;
+}'
+
+# Build the list of awk pattern matching for each function:
+# The regular expression matches function definition by the name of the 
function
+# that must be preceeded by at least one keyword (likely the return type), but
+# nothing like a math operator or other esoteric sign
+for function in $function_list ; do
+    awk_function_handler="$awk_function_handler
+/^[     ]*([A-Za-z][A-Za-z_0-9]*[       ])+${function}[         ]*\(/ {
+   replace_definition("${function}");
+}"
+done
+
+# Finishing, undefine the macro at the most appropriate place we can easily
+# guess
+awk_function_handler="$awk_function_handler
+/^\}/ {
+   # If we are at the end of a function definition, undefine all macros that
+   # have been defined so far
+   for (func_name in func_defined) {
+      print "#undef " func_name;
+      delete func_defined[func_name];
+   }
+}
+# Print all other lines as-is
+{ print }
+"
+
+# Find the specified functions and transform them into macros
+awk "$awk_function_handler" < "$input_file" > "$output_file"
diff --git a/src/Makefile.am b/src/Makefile.am
index 41a7e83e..6c20e63a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,7 +49,6 @@ wmaker_SOURCES =              main.h          menu.c          
menu.h -        misc.c          misc.h          monitor.c       monitor.h @@ 
-123,6 +122,20 @@ if WM_OSDEP_GENERIC
 wmaker_SOURCES += osdep_stub.c
 endif
 
+if USE_NESTED_FUNC
+wmaker_SOURCES += misc.c
+else
+nodist_wmaker_SOURCES = misc.hack_nf.c
+
+CLEANFILES = $(nodist_wmaker_SOURCES)
+
+misc.hack_nf.c: misc.c $(top_srcdir)/script/nested-func-to-macro.sh
+       $(top_srcdir)/script/nested-func-to-macro.sh +          
$(srcdir)/misc.c -o $(builddir)/misc.hack_nf.c +                -f 
"append_string" -f "append_modifier"
+endif
+
+
 AM_CFLAGS =
 
 AM_CPPFLAGS = diff --git a/src/misc.c b/src/misc.c
index 51eb1ee6..3b9299d4 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -763,8 +763,10 @@ char *GetShortcutKey(WShortKey key)
        char buffer[256];
        char *wr;
 
-       void append_string(const char *string)
+       void append_string(const char *text)
        {
+               const char *string = text;
+
                while (*string) {
                        if (wr >= buffer + sizeof(buffer) - 1)
                                break;
@@ -774,10 +776,11 @@ char *GetShortcutKey(WShortKey key)
 
        void append_modifier(int modifier_index, const char *fallback_name)
        {
-               if (wPreferences.modifier_labels[modifier_index])
+               if (wPreferences.modifier_labels[modifier_index]) {
                        
append_string(wPreferences.modifier_labels[modifier_index]);
-               else
+               } else {
                        append_string(fallback_name);
+               }
        }
 
        key_name = XKeysymToString(XkbKeycodeToKeysym(dpy, key.keycode, 0, 0));

-----------------------------------------------------------------------

Summary of changes:
 WINGs/WINGs/WINGs.h            |    2 +-
 WPrefs.app/Expert.c            |    4 +-
 WPrefs.app/KeyboardShortcuts.c |    2 +-
 src/Makefile.am                |    2 +
 src/WindowMaker.h              |    4 +-
 src/defaults.c                 |   32 ++++++++--------
 src/event.c                    |   10 +++--
 src/workspace.c                |    8 ++--
 src/wsmap.c                    |   82 +++++++++++++++++++++++++---------------
 src/wsmap.h                    |   25 ++++++++++++
 10 files changed, 110 insertions(+), 61 deletions(-)


repo.or.cz automatic notification. Contact project admin crma...@gmail.com
if you want to unsubscribe, or site admin ad...@repo.or.cz if you receive
no reply.
-- 
wmaker-crm.git ("The Window Maker window manager")


-- 
To unsubscribe, send mail to wmaker-dev-unsubscr...@lists.windowmaker.org.

Reply via email to