summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorculler <culler>2019-01-13 18:02:47 (GMT)
committerculler <culler>2019-01-13 18:02:47 (GMT)
commit2f5b18681b5ac4100ef19d65ae31babbc0e840b4 (patch)
tree01a5c2191757eaa8202a1a2b8f0acf352362ac35 /unix
parent2d798f8f6006c84bc6f4042e618ce5d7e905412c (diff)
downloadtk-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.c91
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;
}
/*