--- ./src/wconfig.h.in.orig-mapmenu	Mon Aug 13 03:26:17 2001
+++ ./src/wconfig.h.in	Mon Aug 13 03:33:39 2001
@@ -555,6 +555,9 @@
 
 #define MAX_MENU_TEXT_LENGTH 512
 
+#define MAX_MENU_RELPOS		1000
+#define DEF_MENU_RELPOS		(MAX_MENU_RELPOS / 2)
+
 #define MAX_RESTART_ARGS	16
 
 #define MAX_COMMAND_SIZE	1024
--- ./src/menu.h.orig-mapmenu	Mon Mar  6 15:52:43 2000
+++ ./src/menu.h	Mon Aug 13 03:31:48 2001
@@ -133,6 +133,8 @@
 WMenu *wMenuUnderPointer(WScreen *screen);
 void wMenuSaveState(WScreen *scr);
 void wMenuRestoreState(WScreen *scr);
+void wMenuCalculatePosition(WMenu *menu, int x, int y, int relpos,
+			    int *mx, int *my);
 
 
 #endif
--- ./src/menu.c.orig-mapmenu	Mon Jul 23 15:17:58 2001
+++ ./src/menu.c	Mon Aug 13 03:37:09 2001
@@ -2731,6 +2731,65 @@
 }
 
 
+/* Calculate the optimal position at which to map the given menu,
+ * if the cursor position is (<x>,<y>) and the percentage * 10 of the
+ * menu that should be to the left of the cursor is given by
+ * <relpos>.  Return the calculated position in <menux> and <menuy>.
+ * 
+ * If <relpos> is less than 0, the calculated position will be
+ * (<x>+delta, <y>) where `delta' is some small number of pixels. If
+ * <relpos> is greater than 1000, the calculated position will be
+ * (<x>-(w + delta), <y>), where `w' is the width of the menu.
+ * Otherwise, the calculated position is equivalent to
+ * (<x>-(w * <relpos> / 1000), <y>).
+ * 
+ * After the above calculation, the position is adjusted for appearing
+ * off the screen horizontally, with a bias toward the lefthand edge.
+ * That is, if w is less than or equal to the width of the screen, the
+ * menu position is adjusted so the that menu appears entirely on the
+ * screen.  If w is greater than the width of the screen, the menu
+ * position is adjusted such that the left edge of the menu appears at
+ * the left edge of the screen.
+ */
+#define DELTA_X		2
+void
+wMenuCalculatePosition(WMenu *menu, int x, int y, int relpos, int *mx, int *my)
+{
+   WScreen *wscr;
+   int sw;
+   int mw;
+   int dx;
+
+   *mx = x;
+   *my = y;
+
+   if ((NULL == menu) || (NULL == menu->frame) ||
+       (NULL == menu->frame->core) || (NULL == menu->frame->screen_ptr)) {
+      return;
+   }
+   wscr = menu->frame->screen_ptr;
+   sw = wscr->scr_width;
+   mw = menu->frame->core->width + (2 * FRAME_BORDER_WIDTH);
+
+   if (relpos < 0) {
+      *mx = x + DELTA_X;
+   } else if (relpos > MAX_MENU_RELPOS) {
+      *mx = x - (mw + DELTA_X);
+   } else {
+      *mx = x - (mw * relpos) / MAX_MENU_RELPOS;
+   }
+
+   dx = sw - (*mx + mw);
+   if (dx < 0) {
+      *mx += dx;
+   }
+   if (*mx < 0) {
+      *mx = 0;
+   }
+}
+#undef DELTA_X
+
+
 void
 OpenWorkspaceMenu(WScreen *scr, int x, int y)
 {
--- ./src/rootmenu.c.orig-mapmenu	Mon Jul 23 15:22:34 2001
+++ ./src/rootmenu.c	Mon Aug 13 04:09:21 2001
@@ -1760,6 +1760,7 @@
 OpenRootMenu(WScreen *scr, int x, int y, int keyboard)
 {
     WMenu *menu=NULL;
+    int mx, my;
     proplist_t definition;
     /*
     static proplist_t domain=NULL;
@@ -1782,8 +1783,10 @@
 	    
 	    if (keyboard)
 		wMenuMapAt(menu, 0, 0, True);
-	    else
-		wMenuMapCopyAt(menu, x-menu->frame->core->width/2, y);
+	    else {
+		wMenuCalculatePosition(menu, x, y, DEF_MENU_RELPOS, &mx, &my);
+		wMenuMapCopyAt(menu, mx, my);
+	    }
 	}
 	return;
     }
@@ -1838,8 +1841,7 @@
             newx = x - menu->frame->core->width/2;
             newy = y - menu->frame->core->height/2;
         } else {
-            newx = x - menu->frame->core->width/2;
-            newy = y;
+	    wMenuCalculatePosition(menu, x, y, DEF_MENU_RELPOS, &newx, &newy);
         }
         wMenuMapAt(menu, newx, newy, keyboard);
     }
--- ./src/appicon.c.orig-mapmenu	Mon Jul 23 13:32:46 2001
+++ ./src/appicon.c	Mon Aug 13 04:11:47 2001
@@ -608,6 +608,7 @@
 {
     WMenu *menu;
     WScreen *scr = wapp->main_window_desc->screen_ptr;
+    int mx, my;
     int i;
 
     if (!scr->icon_menu) {
@@ -632,17 +633,13 @@
     menu->flags.realized = 0;
     wMenuRealize(menu);
 
-    x -= menu->frame->core->width/2;
-    if (x + menu->frame->core->width > scr->scr_width)
-	x = scr->scr_width - menu->frame->core->width;
-    if (x < 0)
-	x = 0;
+    wMenuCalculatePosition(menu, x, y, DEF_MENU_RELPOS, &mx, &my);
 
     /* set client data */
     for (i = 0; i < menu->entry_no; i++) {
 	menu->entries[i]->clientdata = wapp;
     }
-    wMenuMapAt(menu, x, y, False);
+    wMenuMapAt(menu, mx, my, False);
 }
 
 
--- ./src/switchmenu.c.orig-mapmenu	Mon Jul 23 12:55:39 2001
+++ ./src/switchmenu.c	Mon Aug 13 04:17:50 2001
@@ -91,6 +91,7 @@
 {
     WMenu *switchmenu = scr->switch_menu;
     WWindow *wwin;
+    int mx, my;
 
     if (switchmenu) {
 	if (switchmenu->flags.mapped) {
@@ -101,13 +102,15 @@
 		
 		if (keyboard)
 		    wMenuMapAt(switchmenu, 0, 0, True);
-		else
-		    wMenuMapCopyAt(switchmenu, 
-				   x-switchmenu->frame->core->width/2, y);
+		else {
+		    wMenuCalculatePosition(switchmenu, x, y, DEF_MENU_RELPOS,
+					   &mx, &my);
+		    wMenuMapCopyAt(switchmenu, mx, my);
+		}
 	    }
 	} else {
-	    wMenuMapAt(switchmenu, x-switchmenu->frame->core->width/2, y,
-		       keyboard);
+	    wMenuCalculatePosition(switchmenu, x, y, DEF_MENU_RELPOS, &mx, &my);
+	    wMenuMapAt(switchmenu, mx, my, keyboard);
 	}
 	return;
     }
@@ -134,8 +137,8 @@
             newx = x - switchmenu->frame->core->width/2;
             newy = y - switchmenu->frame->core->height/2;
         } else {
-            newx = x - switchmenu->frame->core->width/2;
-            newy = y;
+	    wMenuCalculatePosition(switchmenu, x, y, DEF_MENU_RELPOS,
+				   &newx, &newy);
         }
         wMenuMapAt(switchmenu, newx, newy, keyboard);
     }
--- ./src/dock.c.orig-mapmenu	Mon Jul 23 13:37:25 2001
+++ ./src/dock.c	Mon Aug 13 04:25:04 2001
@@ -3303,6 +3303,7 @@
     WApplication *wapp = NULL;
     int index = 0;
     int x_pos;
+    int mx, my;
     int n_selected;
     int appIsRunning = aicon->running && aicon->icon && aicon->icon->owner;
 
@@ -3437,14 +3438,9 @@
     if (!dock->menu->flags.realized)
 	wMenuRealize(dock->menu);
 
-    if (dock->type == WM_CLIP) {
-	x_pos = event->xbutton.x_root+2;
-    } else {
-	x_pos = dock->on_right_side ?
-	    scr->scr_width - dock->menu->frame->core->width - 2 : 0;
-    }
-
-    wMenuMapAt(dock->menu, x_pos, event->xbutton.y_root+2, False);
+    wMenuCalculatePosition(dock->menu, event->xbutton.x_root,
+			   event->xbutton.y_root+2, DEF_MENU_RELPOS, &mx, &my);
+    wMenuMapAt(dock->menu, mx, my, False);
 
     /* allow drag select */
     event->xany.send_event = True;
@@ -3456,11 +3452,14 @@
 static void
 openClipWorkspaceMenu(WScreen *scr, int x, int y)
 {
+    int mx, my;
+   
     if (!scr->clip_ws_menu) {
 	scr->clip_ws_menu = wWorkspaceMenuMake(scr, False);
     }
     wWorkspaceMenuUpdate(scr, scr->clip_ws_menu);
-    wMenuMapAt(scr->clip_ws_menu, x, y, False);
+    wMenuCalculatePosition(scr->clip_ws_menu, x, y, DEF_MENU_RELPOS, &mx, &my);
+    wMenuMapAt(scr->clip_ws_menu, mx, my, False);
 }
 
 
--- ./src/winmenu.c.orig-mapmenu	Mon Jul 23 12:51:49 2001
+++ ./src/winmenu.c	Mon Aug 13 04:22:27 2001
@@ -629,6 +629,7 @@
 {
     WMenu *menu;
     WScreen *scr = wwin->screen_ptr;
+    int mx, my;
 
     wwin->flags.menu_open_for_me = 1;
 
@@ -653,14 +654,14 @@
 
     updateMenuForWindow(menu, wwin);
     
-    x -= menu->frame->core->width/2;
-    if (x + menu->frame->core->width > wwin->frame_x+wwin->frame->core->width)
-	x = wwin->frame_x+wwin->frame->core->width - menu->frame->core->width;
-    if (x < wwin->frame_x) 
-	x = wwin->frame_x;
+    wMenuCalculatePosition(menu, x, y, DEF_MENU_RELPOS, &mx, &my);
+    if (mx + menu->frame->core->width > wwin->frame_x+wwin->frame->core->width)
+	mx = wwin->frame_x+wwin->frame->core->width - menu->frame->core->width;
+    if (mx < wwin->frame_x) 
+	mx = wwin->frame_x;
 
     if (!wwin->flags.internal_window)
-	wMenuMapAt(menu, x, y, keyboard);
+	wMenuMapAt(menu, mx, my, keyboard);
 }
 
 
@@ -669,6 +670,7 @@
 {
     WMenu *menu;
     WScreen *scr = wwin->screen_ptr;
+    int mx, my;
 
     wwin->flags.menu_open_for_me = 1;
 
@@ -693,8 +695,7 @@
 
     updateMenuForWindow(menu, wwin);
     
-    x -= menu->frame->core->width/2;
-
-    wMenuMapAt(menu, x, y, False);
+    wMenuCalculatePosition(menu, x, y, DEF_MENU_RELPOS, &mx, &my);
+    wMenuMapAt(menu, mx, my, False);
 }
 
