]> code.delx.au - gnu-emacs/blobdiff - oldXMenu/Activate.c
Cleanup basic allocation variables and functions.
[gnu-emacs] / oldXMenu / Activate.c
index 2c36cc850337731cfbd36a5f52b8f3bd5435c652..d4683da87f2211e1c183a57a576f9f77d4c9fcfc 100644 (file)
@@ -1,8 +1,23 @@
-/* $Header: /gd/gnu/cvsroot/emacs/oldXMenu/Activate.c,v 1.2 2000/01/27 15:31:20 gerd Exp $ */
 /* Copyright    Massachusetts Institute of Technology    1985  */
 
 #include "copyright.h"
 
+/*
+Copyright (C) 2001-2012  Free Software Foundation, Inc.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
 /*
  * XMenu:      MIT Project Athena, X Window system menu package
  *
@@ -28,7 +43,7 @@
  *
  *                     1)      If at any time an error occurs the data
  *                             pointer is left untouched and XM_FAILURE
- *                             is returned.  
+ *                             is returned.
  *
  *                     2)      When a selection request is received (i.e.,
  *                             when the specified mouse event occurs) the
@@ -42,7 +57,7 @@
  *                             will be left untouched and XM_NO_SELECT will
  *                             be returned.
  *
- *                     4)      If the selection that was current at the time 
+ *                     4)      If the selection that was current at the time
  *                             a selection request is made is not an active
  *                             selection the data pointer will be left
  *                             untouched and XM_IA_SELECT will be returned.
@@ -63,7 +78,7 @@
  *
  *                     3)      The application has enabled asynchronous event
  *                             queuing mode.  In this mode all foreign events
- *                             will be queued up untill XMenuActivate
+ *                             will be queued up until XMenuActivate
  *                             terminates; at which time they will be
  *                             returned to the X event queue.  As long as
  *                             AEQ mode is enabled any asynchronous event
 
 #include <config.h>
 #include "XMenuInt.h"
+#include <X11/keysym.h>
+
+/* For debug, set this to 0 to not grab the keyboard on menu popup */
+int x_menu_grab_keyboard = 1;
+
+static Wait_func wait_func;
+static void* wait_data;
+
+void
+XMenuActivateSetWaitFunction (Wait_func func, void *data)
+{
+  wait_func = func;
+  wait_data = data;
+}
 
 int
-XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
-             help_callback)
-    register Display *display;         /* Display to put menu on. */
-    register XMenu *menu;              /* Menu to activate. */
-    int *p_num;                                /* Pane number selected. */
-    int *s_num;                                /* Selection number selected. */
-    int x_pos;                         /* X coordinate of menu position. */
-    int y_pos;                         /* Y coordinate of menu position. */
-    unsigned int event_mask;           /* Mouse button event mask. */
-    char **data;                       /* Pointer to return data value. */
-    void (* help_callback) ();         /* Help callback.  */
+XMenuActivate(
+    register Display *display,         /* Display to put menu on. */
+    register XMenu *menu,              /* Menu to activate. */
+    int *p_num,                                /* Pane number selected. */
+    int *s_num,                                /* Selection number selected. */
+    int x_pos,                         /* X coordinate of menu position. */
+    int y_pos,                         /* Y coordinate of menu position. */
+    unsigned int event_mask,           /* Mouse button event mask. */
+    char **data,                       /* Pointer to return data value. */
+    void (*help_callback) (char const *, int, int)) /* Help callback.  */
 {
     int status;                                /* X routine call status. */
     int orig_x;                                /* Upper left menu origin X coord. */
@@ -115,6 +143,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
     Window root, child;
     int root_x, root_y, win_x, win_y;
     unsigned int mask;
+    KeySym keysym;
 
     /*
      * Define and allocate a foreign event queue to hold events
@@ -128,7 +157,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
 
     XMEventQue *feq = NULL;                    /* Foreign event queue. */
     XMEventQue *feq_tmp;               /* Foreign event queue temporary. */
-    
+
     /*
      * If there are no panes in the menu then return failure
      * because the menu is not initialized.
@@ -159,14 +188,14 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
      * Compute origin of menu so that cursor is in
      * Correct pane and selection.
      */
-    _XMTransToOrigin(display, 
-                    menu, 
-                    cur_p, cur_s, 
-                    x_pos, y_pos, 
+    _XMTransToOrigin(display,
+                    menu,
+                    cur_p, cur_s,
+                    x_pos, y_pos,
                     &orig_x, &orig_y);
     menu->x_pos = orig_x;      /* Store X and Y coords of menu. */
     menu->y_pos = orig_y;
-    
+
     if (XMenuRecompute(display, menu) == XM_FAILURE) {
        return(XM_FAILURE);
     }
@@ -209,11 +238,11 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
      * not provided an event handler.
      */
     XSync(display, 0);
-    
+
     /*
      * Grab the mouse for menu input.
      */
-    
+
     status = XGrabPointer(
                          display,
                          menu->parent,
@@ -225,6 +254,18 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
                          menu->mouse_cursor,
                          CurrentTime
                          );
+    if (status == Success && x_menu_grab_keyboard)
+      {
+        status = XGrabKeyboard (display,
+                                menu->parent,
+                                False,
+                                GrabModeAsync,
+                                GrabModeAsync,
+                                CurrentTime);
+        if (status != Success)
+          XUngrabPointer(display, CurrentTime);
+      }
+
     if (status == _X_FAILURE) {
        _XMErrorCode = XME_GRAB_MOUSE;
        return(XM_FAILURE);
@@ -235,7 +276,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
      */
     XMapWindow(display, cur_p->window);
     for (p_ptr = menu->p_list->next;
-        p_ptr != cur_p; 
+        p_ptr != cur_p;
         p_ptr = p_ptr->next)
       XMapWindow(display, p_ptr->window);
     for (p_ptr = cur_p->next;
@@ -245,18 +286,19 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
 
     XRaiseWindow(display, cur_p->window);      /* Make sure current */
                                                /* pane is on top. */
-    
+
     cur_s = NULL;                      /* Clear current selection. */
 
     /*
      * Begin event processing loop.
      */
     while (1) {
+        if (wait_func) (*wait_func) (wait_data);
        XNextEvent(display, &event);    /* Get next event. */
        switch (event.type) {           /* Dispatch on the event type. */
     case Expose:
            event_xmp = (XMPane *)XLookUpAssoc(display,
-                                              menu->assoc_tab, 
+                                              menu->assoc_tab,
                                               event.xexpose.window);
            if (event_xmp == NULL) {
                /*
@@ -277,7 +319,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
            }
            if (event_xmp->activated) {
                XSetWindowBackground(display,
-                                    event_xmp->window, 
+                                    event_xmp->window,
                                     menu->bkgnd_color);
            }
            else {
@@ -288,13 +330,13 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
            _XMRefreshPane(display, menu, event_xmp);
            break;
     case EnterNotify:
-           /* 
+           /*
             * First wait a small period of time, and see
             * if another EnterNotify event follows hard on the
             * heels of this one. i.e., the user is simply
             * "passing through". If so, ignore this one.
             */
-       
+
            event_xmw = (XMWindow *)XLookUpAssoc(display,
                                                 menu->assoc_tab,
                                                 event.xcrossing.window);
@@ -309,11 +351,11 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
                    if(peek_event.type == LeaveNotify) {
                        break;
                    }
-               }                         
+               }
                cur_s = (XMSelect *)event_xmw;
                help_callback (cur_s->help_string,
                               cur_p->serial, cur_s->serial);
-               
+
                /*
                 * If the pane we are in is active and the
                 * selection entered is active then activate
@@ -370,7 +412,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
                 * take it from here.  -- caveh@eng.sun.com.
                 */
                XSetWindowBackground(display,
-                                    event_xmp->window, 
+                                    event_xmp->window,
                                     menu->bkgnd_color);
                _XMRefreshPane(display, menu, event_xmp);
 #endif
@@ -385,7 +427,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
                                                 );
            if (event_xmw == NULL) break;
            if(cur_s == NULL) break;
-           
+
            /*
             * If the current selection was activated then
             * deactivate it.
@@ -396,7 +438,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
            }
            cur_s = NULL;
            break;
-       
+
     case ButtonPress:
     case ButtonRelease:
                *p_num = cur_p->serial;
@@ -429,6 +471,18 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
                }
                selection = True;
                break;
+        case KeyPress:
+        case KeyRelease:
+                keysym = XLookupKeysym (&event.xkey, 0);
+
+                /* Pop down on C-g and Escape.  */
+                if ((keysym == XK_g && (event.xkey.state & ControlMask) != 0)
+                    || keysym == XK_Escape) /* Any escape, ignore modifiers.  */
+                  {
+                    ret_val = XM_NO_SELECT;
+                    selection = True;
+                  }
+               break;
            default:
                /*
                 * If AEQ mode is enabled then queue the event.
@@ -456,7 +510,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
      */
     for ( p_ptr = menu->p_list->next;
         p_ptr != menu->p_list;
-        p_ptr = p_ptr->next) 
+        p_ptr = p_ptr->next)
       {
          XUnmapWindow(display, p_ptr->window);
       }
@@ -465,8 +519,9 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
      * Ungrab the mouse.
      */
     XUngrabPointer(display, CurrentTime);
+    XUngrabKeyboard(display, CurrentTime);
 
-    /* 
+    /*
      * Restore bits under where the menu was if we managed
      * to save them and free the pixmap.
      */
@@ -486,7 +541,7 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
      * Synchronize the X buffers and the X event queue.
      */
     XSync(display, 0);
-    
+
     /*
      * Dispatch any events remaining on the queue.
      */
@@ -541,7 +596,9 @@ XMenuActivate(display, menu, p_num, s_num, x_pos, y_pos, event_mask, data,
        feq = feq_tmp->next;
        free((char *)feq_tmp);
     }
-    
+
+    wait_func = 0;
+
     /*
      * Return successfully.
      */