summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
Diffstat (limited to 'unix')
-rw-r--r--unix/tkUnixMenu.c105
1 files changed, 101 insertions, 4 deletions
diff --git a/unix/tkUnixMenu.c b/unix/tkUnixMenu.c
index 38b6c58..d7ed873 100644
--- a/unix/tkUnixMenu.c
+++ b/unix/tkUnixMenu.c
@@ -889,7 +889,10 @@ DrawMenuUnderline(
*
* TkpPostMenu --
*
- * Posts a menu on the screen
+ * Posts a menu on the screen so that the top left corner of the
+ * specified entry is located at the point (x, y) in screen coordinates.
+ * If the entry parameter is negative, the upper left corner of the
+ * menu itself is placed at the point.
*
* Results:
* None.
@@ -904,9 +907,104 @@ int
TkpPostMenu(
Tcl_Interp *interp,
TkMenu *menuPtr,
- int x, int y)
+ int x, int y, int index)
{
- return TkPostTearoffMenu(interp, menuPtr, x, y);
+ return TkpPostTearoffMenu(interp, menuPtr, x, y, index);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpPostTearoffMenu --
+ *
+ * Posts a tearoff menu on the screen so that the top left corner of the
+ * specified entry is located at the point (x, y) in screen coordinates.
+ * If the index parameter is negative, the upper left corner of the menu
+ * itself is placed at the point. On unix this is called when posting
+ * any menu. Adjusts the menu's position so that it fits on the screen,
+ * and maps and raises the menu.
+ *
+ * Results:
+ * Returns a standard Tcl Error.
+ *
+ * Side effects:
+ * The menu is posted.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkpPostTearoffMenu(
+ Tcl_Interp *interp, /* The interpreter of the menu */
+ TkMenu *menuPtr, /* The menu we are posting */
+ int x, int y, int index) /* The root X,Y coordinates where the
+ * specified entry will be posted */
+{
+ int vRootX, vRootY, vRootWidth, vRootHeight;
+ int result;
+
+ if (index >= menuPtr->numEntries) {
+ index = menuPtr->numEntries - 1;
+ }
+ if (index >= 0) {
+ y -= menuPtr->entries[index]->y;
+ }
+
+ TkActivateMenuEntry(menuPtr, -1);
+ TkRecomputeMenu(menuPtr);
+ result = TkPostCommand(menuPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ /*
+ * The post commands could have deleted the menu, which means we are dead
+ * and should go away.
+ */
+
+ if (menuPtr->tkwin == NULL) {
+ return TCL_OK;
+ }
+
+ /*
+ * Adjust the position of the menu if necessary to keep it visible on the
+ * screen. There are two special tricks to make this work right:
+ *
+ * 1. If a virtual root window manager is being used then the coordinates
+ * are in the virtual root window of menuPtr's parent; since the menu
+ * uses override-redirect mode it will be in the *real* root window for
+ * the screen, so we have to map the coordinates from the virtual root
+ * (if any) to the real root. Can't get the virtual root from the menu
+ * itself (it will never be seen by the wm) so use its parent instead
+ * (it would be better to have an an option that names a window to use
+ * for this...).
+ * 2. The menu may not have been mapped yet, so its current size might be
+ * the default 1x1. To compute how much space it needs, use its
+ * requested size, not its actual size.
+ */
+
+ Tk_GetVRootGeometry(Tk_Parent(menuPtr->tkwin), &vRootX, &vRootY,
+ &vRootWidth, &vRootHeight);
+ vRootWidth -= Tk_ReqWidth(menuPtr->tkwin);
+ if (x > vRootX + vRootWidth) {
+ x = vRootX + vRootWidth;
+ }
+ if (x < vRootX) {
+ x = vRootX;
+ }
+ vRootHeight -= Tk_ReqHeight(menuPtr->tkwin);
+ if (y > vRootY + vRootHeight) {
+ y = vRootY + vRootHeight;
+ }
+ if (y < vRootY) {
+ y = vRootY;
+ }
+ Tk_MoveToplevelWindow(menuPtr->tkwin, x, y);
+ if (!Tk_IsMapped(menuPtr->tkwin)) {
+ Tk_MapWindow(menuPtr->tkwin);
+ }
+ TkWmRestackToplevel((TkWindow *) menuPtr->tkwin, Above, NULL);
+ return TCL_OK;
}
/*
@@ -1721,7 +1819,6 @@ TkpComputeStandardMenuGeometry(
}
windowWidth = x + indicatorSpace + labelWidth + accelWidth
+ 2 * activeBorderWidth + borderWidth;
-
windowHeight += borderWidth;
/*