diff options
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tkUnixMenu.c | 105 |
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; /* |