diff options
author | culler <culler> | 2019-01-13 18:02:47 (GMT) |
---|---|---|
committer | culler <culler> | 2019-01-13 18:02:47 (GMT) |
commit | 2f5b18681b5ac4100ef19d65ae31babbc0e840b4 (patch) | |
tree | 01a5c2191757eaa8202a1a2b8f0acf352362ac35 /unix | |
parent | 2d798f8f6006c84bc6f4042e618ce5d7e905412c (diff) | |
download | tk-2f5b18681b5ac4100ef19d65ae31babbc0e840b4.zip tk-2f5b18681b5ac4100ef19d65ae31babbc0e840b4.tar.gz tk-2f5b18681b5ac4100ef19d65ae31babbc0e840b4.tar.bz2 |
Add TkpPostTearoffMenu, called by TkPostTearoffMenu and used in the menu post
command; eliminates #ifdef in the generic code.
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tkUnixMenu.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/unix/tkUnixMenu.c b/unix/tkUnixMenu.c index f701819..c5c83ce 100644 --- a/unix/tkUnixMenu.c +++ b/unix/tkUnixMenu.c @@ -909,13 +909,102 @@ TkpPostMenu( TkMenu *menuPtr, int x, int y, int entry) { + return TkpPostTearoffMenu(interp, menuPtr, x, y, entry); +} + +/* + *---------------------------------------------------------------------- + * + * 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 entry 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 entry) /* The root X,Y coordinates where the + * specified entry will be posted */ +{ + int vRootX, vRootY, vRootWidth, vRootHeight; + int result; + if (entry >= menuPtr->numEntries) { entry = menuPtr->numEntries - 1; } if (entry >= 0) { y -= menuPtr->entries[entry]->y; } - return TkPostTearoffMenu(interp, menuPtr, x, 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; } /* |