diff --git a/pd/nw/dialog_prefs.html b/pd/nw/dialog_prefs.html
index d92a02242c4f7e899911f19b5529897130f2fe74..9a8b89d7d9e5c02de1375a2c0f97d2a0e1ba22cb 100644
--- a/pd/nw/dialog_prefs.html
+++ b/pd/nw/dialog_prefs.html
@@ -398,6 +398,11 @@ td {
               </option>
             </select>
             <br/>
+            <label data-i18n="[title]prefs.gui.grid.show_grid_tt">
+              <input type="checkbox" id="show_grid" name="show_grid">
+              <span data-i18n="prefs.gui.grid.show_grid"></span>
+            </label>
+            <br/>
             <label data-i18n="[title]prefs.gui.zoom.save_zoom_tt">
               <input type="checkbox" id="save_zoom" name="save_zoom">
               <span data-i18n="prefs.gui.zoom.save_zoom"></span>
@@ -757,16 +762,19 @@ function apply(save_prefs) {
     );
 
     // Send the gui prefs (currently just the name of the gui preset, the
-    // status of the save-zoom toggle and various options related to the help
-    // browser) to Pd
+    // status of the show_grid and save_zoom toggles and various options
+    // related to the help browser) to Pd
     pdgui.pdsend("pd gui-prefs",
         get_gui_preset(),
+        get_bool_elem("show_grid"),
         get_bool_elem("save_zoom"),
         get_bool_elem("browser_doc"),
         get_bool_elem("browser_path"),
         get_bool_elem("browser_init"),
         get_autopatch_yoffset()
     );
+    // Update the grid on all open windows.
+    pdgui.update_grid(get_bool_elem("show_grid"));
 
     // Send the startup config data to Pd
     pdgui.pdsend.apply(null, ["pd path-dialog", startup_use_stdpath, startup_verbose].concat(get_path_array()));
@@ -1010,7 +1018,7 @@ function autopatch_yoffset_toggle(checked) {
     document.getElementById("autopatch_yoffset").checked = checked;
 }
 
-function gui_prefs_callback(name, save_zoom, browser_doc, browser_path,
+function gui_prefs_callback(name, show_grid, save_zoom, browser_doc, browser_path,
     browser_init, autopatch_yoffset) {
     var s = document.getElementById("gui_preset"),
         i;
@@ -1020,6 +1028,7 @@ function gui_prefs_callback(name, save_zoom, browser_doc, browser_path,
             break;
         }
     }
+    document.getElementById("show_grid").checked = !!show_grid;
     document.getElementById("save_zoom").checked = !!save_zoom;
     document.getElementById("browser_doc").checked = !!browser_doc;
     document.getElementById("browser_path").checked = !!browser_path;
diff --git a/pd/nw/locales/de/translation.json b/pd/nw/locales/de/translation.json
index e8ea50b449ef3ea5e46a003a298305d63623501a..69265bfb63f1c1b15d03fda5505a0f7f4b0606cb 100644
--- a/pd/nw/locales/de/translation.json
+++ b/pd/nw/locales/de/translation.json
@@ -423,6 +423,10 @@
         "c64": "C64",
         "footgun": "Fusspistole"
       },
+      "grid": {
+        "show_grid": "Gitter-Hintergrund im Edit-Modus",
+        "show_grid_tt": "Gitter-Hintergrund im Edit-Modus anzeigen"
+      },
       "zoom": {
         "save_zoom": "Speichern/Laden der Vergrößerung im Patch",
         "save_zoom_tt": "Speichere die aktuelle Vergrößerung mit dem Patch und stelle diese beim Laden des Patches wieder her"
diff --git a/pd/nw/locales/en/translation.json b/pd/nw/locales/en/translation.json
index 213156285b68f039f8e56b0db848b872e7b94139..5a161dce5dfecc453737810408be61c45e06f961 100644
--- a/pd/nw/locales/en/translation.json
+++ b/pd/nw/locales/en/translation.json
@@ -423,6 +423,10 @@
         "c64": "C64",
         "footgun": "Footgun"
       },
+      "grid": {
+        "show_grid": "grid background in edit mode",
+        "show_grid_tt": "Show the grid background in edit mode"
+      },
       "zoom": {
         "save_zoom": "save/load zoom level with patch",
         "save_zoom_tt": "Save the current zoom level with the patch and restore it when reloading the patch"
diff --git a/pd/nw/locales/fr/translation.json b/pd/nw/locales/fr/translation.json
index 604f5f6edaed00c1683ea0161c3f583b78db4226..8a34087870ad86fb7a26f84036bff88fba8ce153 100644
--- a/pd/nw/locales/fr/translation.json
+++ b/pd/nw/locales/fr/translation.json
@@ -423,6 +423,10 @@
         "c64":       "C64",
         "footgun":   "Footgun"
       },
+      "grid": {
+        "show_grid": "Fond de grille en mode Édition",
+        "show_grid_tt": "Afficher l'arrière-plan de la grille en mode Édition"
+      },
       "zoom": {
         "save_zoom":    "Sauver/Charger niveau zoom avec patch",
         "save_zoom_tt": "Enregistrer le niveau de zoom actuel avec le patch et le restaurer lors du chargement du patch"
diff --git a/pd/nw/pd_canvas.js b/pd/nw/pd_canvas.js
index 55c3c8ada412d4f70b7be14b8e0a6f4a9237978c..9e074b5447676c96e17b8ddb2f06144f5d34fe12 100644
--- a/pd/nw/pd_canvas.js
+++ b/pd/nw/pd_canvas.js
@@ -1455,6 +1455,10 @@ function set_edit_menu_modals(state) {
     canvas_menu.edit.font.enabled = state;
 }
 
+function get_editmode_checkbox() {
+    return canvas_menu.edit.editmode.checked;
+}
+
 function set_editmode_checkbox(state) {
     canvas_menu.edit.editmode.checked = state;
 }
@@ -2107,4 +2111,4 @@ function init_menu_font_size(size) {
 // LATER: we can use this to also update the undo state appropriately
 function update_menu_items(cid) {
     pdgui.pdsend(cid, "updatemenu");
-}
\ No newline at end of file
+}
diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index c358b3271508f7143549df7ebb0b43e39b65fd28..ffcc1f52684b948813611fd20fc5fe0b02d15dc9 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -1246,14 +1246,52 @@ function menu_send(name) {
     }
 }
 
+/*
+ico@vt.edu 20200907: added svg tiled background to reflect edit mode and
+integrated it into the canvas_set_editmode below.
+
+LATER: consider adding an interim version that reflects only the ctrl button press
+*/
+var gui_editmode_svg_background = "url(\"data:image/svg+xml,%3Csvg " +
+        "xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 " +
+        " 100 100'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%239C92AC' fill-opacity" +
+        "='0.4'%3E%3Cpath opacity='.5' d='M96 95h4v1h-4v4h-1v-4h-9v4h-1v-4h-9v4h-1" +
+        "v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4H0v-" +
+        "1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9" +
+        "H0v-1h15v-9H0v-1h15V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9" +
+        "V0h1v15h9V0h1v15h9V0h1v15h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v" +
+        "1h-4v9h4v1h-4v9h4v1h-4v9zm-1 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h" +
+        "9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-1" +
+        "0 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9" +
+        "h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-" +
+        "10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9" +
+        "h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9" +
+        "v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h" +
+        "9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h" +
+        "9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-1" +
+        "0 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-" +
+        "9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm1" +
+        "0 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9" +
+        "h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9" +
+        "h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0" +
+        "h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9z'/%3E%3Cpath d" +
+        "='M6 5V0H5v5H0v1h5v94h1V6h94V5H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E\")";
+
 // requires nw.js API (Menuitem)
 function canvas_set_editmode(cid, state) {
     gui(cid).get_elem("patchsvg", function(patchsvg, w) {
         w.set_editmode_checkbox(state !== 0 ? true : false);
         if (state !== 0) {
             patchsvg.classList.add("editmode");
+            if (showgrid[cid]) {
+                //post("editmode:" + gui_editmode_svg_background);
+                patchwin[cid].window.document.body.style.setProperty
+                ("background-image", gui_editmode_svg_background);
+            }
         } else {
             patchsvg.classList.remove("editmode");
+            patchwin[cid].window.document.body.style.setProperty("background-image",
+                "none");  
         }
     });
 }
@@ -1264,6 +1302,25 @@ function gui_canvas_set_editmode(cid, state) {
     canvas_set_editmode(cid, state);
 }
 
+function update_grid(grid) {
+    // Update the grid background of all canvas windows when the corresponding
+    // option in the gui prefs changes.
+    var bg = grid != 0 ? gui_editmode_svg_background : "none";
+    for (var cid in patchwin) {
+	gui(cid).get_elem("patchsvg", function(patchsvg, w) {
+            var editmode = patchsvg.classList.contains("editmode");
+            if (editmode) {
+                patchwin[cid].window.document.body.style.setProperty
+                ("background-image", bg);
+            }
+	});
+    }
+    // Also update the showgrid flags.
+    set_showgrid(grid);
+}
+
+exports.update_grid = update_grid;
+
 // requires nw.js API (Menuitem)
 function gui_canvas_set_cordinspector(cid, state) {
     patchwin[cid].window.set_cord_inspector_checkbox(state !== 0 ? true : false);
@@ -1520,6 +1577,7 @@ var scroll = {},
     redo = {},
     font = {},
     doscroll = {},
+    showgrid = {},
     last_loaded, // last loaded canvas
     last_focused, // last focused canvas (doesn't include Pd window or dialogs)
     loading = {},
@@ -1530,6 +1588,12 @@ var scroll = {},
     var patchwin = {}; // object filled with cid: [Window object] pairs
     var dialogwin = {}; // object filled with did: [Window object] pairs
 
+var set_showgrid = function(grid) {
+    for (var cid in showgrid) {
+	showgrid[cid] = grid;
+    }
+}
+
 exports.get_patchwin = function(name) {
     return patchwin[name];
 }
@@ -1689,7 +1753,7 @@ function create_window(cid, type, width, height, xpos, ypos, attr_array) {
 }
 
 // create a new canvas
-function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir, dirty_flag, hide_scroll, hide_menu, has_toplevel_scalars, cargs) {
+function gui_canvas_new(cid, width, height, geometry, grid, zoom, editmode, name, dir, dirty_flag, hide_scroll, hide_menu, has_toplevel_scalars, cargs) {
     // hack for buggy tcl popups... should go away for node-webkit
     //reset_ctrl_on_popup_window
     
@@ -1716,6 +1780,7 @@ function gui_canvas_new(cid, width, height, geometry, zoom, editmode, name, dir,
     redo[cid] = false;
     font[cid] = 10;
     doscroll[cid] = 0;
+    showgrid[cid] = grid != 0;
     toplevel_scalars[cid] = has_toplevel_scalars;
     // geometry is just the x/y screen offset "+xoff+yoff"
     geometry = geometry.slice(1);   // remove the leading "+"
@@ -5873,10 +5938,10 @@ function gui_midi_properties(gfxstub, sys_indevs, sys_outdevs,
     }
 }
 
-function gui_gui_properties(dummy, name, save_zoom, browser_doc, browser_path,
+function gui_gui_properties(dummy, name, show_grid, save_zoom, browser_doc, browser_path,
     browser_init, autopatch_yoffset) {
     if (dialogwin["prefs"] !== null) {
-        dialogwin["prefs"].window.gui_prefs_callback(name, save_zoom,
+        dialogwin["prefs"].window.gui_prefs_callback(name, show_grid, save_zoom,
             browser_doc, browser_path, browser_init, autopatch_yoffset);
     }
 }
@@ -6784,4 +6849,4 @@ function gui_osx_dialog_appearance(id)
     var close_button = dialogwin[id].window.document.getElementById("titlebar_close_button");
     close_button.style.setProperty("line-height", "14px");
     close_button.style.setProperty("border-radius", "10px");
-}
\ No newline at end of file
+}
diff --git a/pd/src/g_editor.c b/pd/src/g_editor.c
index 7fd76c20b489a79bd3092d1187cd456fb2c28e51..b41086d47cdd1da592724244e2728b3fa9192de0 100644
--- a/pd/src/g_editor.c
+++ b/pd/src/g_editor.c
@@ -2696,6 +2696,7 @@ void canvas_vis(t_canvas *x, t_floatarg f)
 
     t_gobj *g;
     t_int properties;
+    extern int sys_grid;
 
     int flag = (f != 0);
     if (flag)
@@ -2751,11 +2752,12 @@ void canvas_vis(t_canvas *x, t_floatarg f)
                We may need to expand this to include scalars, as well. */
             canvas_create_editor(x);
             canvas_args_to_string(argsbuf, x);
-            gui_vmess("gui_canvas_new", "xiisiissiiiis",
+            gui_vmess("gui_canvas_new", "xiisiiissiiiis",
                 x,
                 (int)(x->gl_screenx2 - x->gl_screenx1),
                 (int)(x->gl_screeny2 - x->gl_screeny1),
                 geobuf,
+                sys_grid,
                 x->gl_zoom,
                 x->gl_edit,
                 x->gl_name->s_name,
diff --git a/pd/src/m_glob.c b/pd/src/m_glob.c
index a67a4f61f263fb4af01a7fb64f6af90514c10dbe..2147047271868a021bb4f899b9aefdeecf56f6a2 100644
--- a/pd/src/m_glob.c
+++ b/pd/src/m_glob.c
@@ -79,12 +79,13 @@ static void glob_perf(t_pd *dummy, float f)
     sys_perf = (f != 0);
 }
 
-extern int sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init,
+extern int sys_grid, sys_zoom, sys_browser_doc, sys_browser_path, sys_browser_init,
     sys_autopatch_yoffset;
 extern t_symbol *sys_gui_preset;
 static void glob_gui_prefs(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
 {
     sys_gui_preset = atom_getsymbolarg(0, argc--, argv++);
+    sys_grid = !!atom_getintarg(0, argc--, argv++);
     sys_zoom = !!atom_getintarg(0, argc--, argv++);
     sys_browser_doc = !!atom_getintarg(0, argc--, argv++);
     sys_browser_path = !!atom_getintarg(0, argc--, argv++);
@@ -95,9 +96,10 @@ static void glob_gui_prefs(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
 /* just the gui-preset, the save-zoom toggle and various help browser options for now */
 static void glob_gui_properties(t_pd *dummy)
 {
-    gui_vmess("gui_gui_properties", "xsiiiii",
+    gui_vmess("gui_gui_properties", "xsiiiiii",
         dummy,
         sys_gui_preset->s_name,
+        sys_grid,
         sys_zoom,
         sys_browser_doc,
         sys_browser_path,
diff --git a/pd/src/s_file.c b/pd/src/s_file.c
index be8b87958b361b1f40424a41f4e3030f43047b12..df4f75d17db45cef34ca04e06bf428ca0a53fefc 100644
--- a/pd/src/s_file.c
+++ b/pd/src/s_file.c
@@ -40,7 +40,7 @@
 #define snprintf sprintf_s
 #endif
 
-int sys_defeatrt, sys_autopatch_yoffset, sys_zoom, sys_browser_doc = 1,
+int sys_defeatrt, sys_autopatch_yoffset, sys_grid = 1, sys_zoom, sys_browser_doc = 1,
     sys_browser_path, sys_browser_init;
 t_symbol *sys_flags = &s_;
 void sys_doflags( void);
@@ -668,6 +668,8 @@ void sys_loadpreferences( void)
     }
     if (sys_getpreference("defeatrt", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &sys_defeatrt);
+    if (sys_getpreference("showgrid", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &sys_grid);
     if (sys_getpreference("savezoom", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &sys_zoom);
     if (sys_getpreference("browser_doc", prefbuf, MAXPDSTRING))
@@ -815,6 +817,8 @@ void glob_savepreferences(t_pd *dummy)
     sys_putpreference("nloadlib", buf1);
     sprintf(buf1, "%d", sys_defeatrt);
     sys_putpreference("defeatrt", buf1);
+    sprintf(buf1, "%d", sys_grid);
+    sys_putpreference("showgrid", buf1);
     sprintf(buf1, "%d", sys_zoom);
     sys_putpreference("savezoom", buf1);
     sprintf(buf1, "%d", sys_browser_doc);