]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix submenus and screen restoration.
authorEli Zaretskii <eliz@gnu.org>
Tue, 24 Sep 2013 16:07:35 +0000 (19:07 +0300)
committerEli Zaretskii <eliz@gnu.org>
Tue, 24 Sep 2013 16:07:35 +0000 (19:07 +0300)
lisp/menu-bar.el
src/keyboard.c
src/term.c
src/termchar.h

index 5cc79b9358e6bb82026be3a06bbf336702b4af8b..37cbd9f0490181e9af9ecbf76046b4370781e772 100644 (file)
@@ -2323,7 +2323,9 @@ If FRAME is nil or not given, use the selected frame."
      ((eq type 'x) (x-menu-bar-open frame))
      ((eq type 'w32) (w32-menu-bar-open frame))
      ((null tty-menu-open-use-tmm)
-      (popup-menu menu-bar-file-menu (posn-at-x-y 0 0 nil t)))
+      ;; FIXME: This should open the leftmost menu, and let the user
+      ;; move to others via C-f or right-arrow.
+      (popup-menu menu-bar-tools-menu (posn-at-x-y 30 0 nil t)))
      (t (with-selected-frame (or frame (selected-frame))
           (tmm-menubar))))))
 
index 4ace767484eb949d1ff0767c29b519a3a144ff6d..9faa3770cf3f8a9eb63a751fdcd5f5029d9ba160 100644 (file)
@@ -3903,7 +3903,18 @@ kbd_buffer_get_event (KBOARD **kbp,
            }
        }
       else
-       wait_reading_process_output (0, 0, -1, 1, Qnil, NULL, 0);
+       {
+         bool do_display = true;
+         struct tty_display_info *tty = CURTTY ();
+
+         /* When this TTY is displaying a menu, we must prevent any
+            redisplay, because we modify the frame's glyph matrix
+            behind the back of the display engine.  */
+         if (tty->showing_menu)
+           do_display = false;
+
+         wait_reading_process_output (0, 0, -1, do_display, Qnil, NULL, 0);
+       }
 
       if (!interrupt_input && kbd_fetch_ptr == kbd_store_ptr)
        gobble_input ();
index 4da5fd1390570f087dae4618faf66617d7790e7e..b408a4a0907efaa97231ad42d3fd6c49a2605703 100644 (file)
@@ -3075,6 +3075,53 @@ struct tty_menu_state
   int x, y;
 };
 
+/* Save away the contents of frame F's current frame matrix, and
+   enable all its rows.  Value is a glyph matrix holding the contents
+   of F's current frame matrix with all its glyph rows enabled.  */
+
+struct glyph_matrix *
+save_and_enable_current_matrix (struct frame *f)
+{
+  int i;
+  struct glyph_matrix *saved = xzalloc (sizeof *saved);
+  saved->nrows = f->current_matrix->nrows;
+  saved->rows = xzalloc (saved->nrows * sizeof *saved->rows);
+
+  for (i = 0; i < saved->nrows; ++i)
+    {
+      struct glyph_row *from = f->current_matrix->rows + i;
+      struct glyph_row *to = saved->rows + i;
+      ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
+      to->glyphs[TEXT_AREA] = xmalloc (nbytes);
+      memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
+      to->used[TEXT_AREA] = from->used[TEXT_AREA];
+      /* Make sure every row is enabled, or else update_frame will not
+        redraw them.  (Rows that are identical to what is already on
+        screen will not be redrawn anyway.)  */
+      to->enabled_p = 1;
+      to->hash = from->hash;
+      if (from->used[LEFT_MARGIN_AREA])
+       {
+         nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
+         to->glyphs[LEFT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
+         memcpy (to->glyphs[LEFT_MARGIN_AREA],
+                 from->glyphs[LEFT_MARGIN_AREA], nbytes);
+         to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
+       }
+      if (from->used[RIGHT_MARGIN_AREA])
+       {
+         nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
+         to->glyphs[RIGHT_MARGIN_AREA] = (struct glyph *) xmalloc (nbytes);
+         memcpy (to->glyphs[RIGHT_MARGIN_AREA],
+                 from->glyphs[RIGHT_MARGIN_AREA], nbytes);
+         to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
+       }
+    }
+
+  return saved;
+}
+
 /* Restore the contents of frame F's desired frame matrix from SAVED,
    and free memory associated with SAVED.  */
 
@@ -3094,7 +3141,6 @@ restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
       to->used[TEXT_AREA] = from->used[TEXT_AREA];
       to->enabled_p = from->enabled_p;
       to->hash = from->hash;
-      xfree (from->glyphs[TEXT_AREA]);
       nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
       if (nbytes)
        {
@@ -3102,7 +3148,6 @@ restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
          memcpy (to->glyphs[LEFT_MARGIN_AREA],
                  from->glyphs[LEFT_MARGIN_AREA], nbytes);
          to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
-         xfree (from->glyphs[LEFT_MARGIN_AREA]);
        }
       else
        to->used[LEFT_MARGIN_AREA] = 0;
@@ -3113,14 +3158,10 @@ restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
          memcpy (to->glyphs[RIGHT_MARGIN_AREA],
                  from->glyphs[RIGHT_MARGIN_AREA], nbytes);
          to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
-         xfree (from->glyphs[RIGHT_MARGIN_AREA]);
        }
       else
        to->used[RIGHT_MARGIN_AREA] = 0;
     }
-
-  xfree (saved->rows);
-  xfree (saved);
 }
 
 static void
@@ -3182,10 +3223,15 @@ read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
       Lisp_Object cmd;
       int usable_input = 1;
       int st = 0;
+      struct tty_display_info *tty = FRAME_TTY (sf);
 
+      /* Signal the keyboard reading routines we are displaying a menu
+        on this terminal.  */
+      tty->showing_menu = 1;
       do {
        cmd = read_menu_command ();
       } while NILP (cmd);
+      tty->showing_menu = 0;
 
       if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
        return -1;
@@ -3333,7 +3379,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
   update_frame_with_menu (sf);
   state[0].menu = menu;
   mouse_off ();        /* FIXME */
-  state[0].screen_behind = save_current_matrix (sf);
+  state[0].screen_behind = save_and_enable_current_matrix (sf);
 
   /* Turn off the cursor.  Otherwise it shows through the menu
      panes, which is ugly.  */
@@ -3383,7 +3429,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
            }
          leave = 1;
        }
-      else if (sf->mouse_moved)
+      if (sf->mouse_moved && input_status != -1)
        {
          sf->mouse_moved = 0;
          result = TTYM_IA_SELECT;
@@ -3425,7 +3471,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
                        state[statecount].pane = state[i].menu->panenumber[dy];
                        mouse_off (); /* FIXME */
                        state[statecount].screen_behind
-                         = save_current_matrix (sf);
+                         = save_and_enable_current_matrix (sf);
                        state[statecount].x
                          = state[i].x + state[i].menu->width + 2;
                        state[statecount].y = y;
@@ -3476,7 +3522,6 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
   /* FIXME: Since we set the fram's garbaged flag, do we need this
      call to screen_update?  */
   screen_update (sf, state[0].screen_behind);
-  state[0].screen_behind = NULL;
 #if 0
   /* We have a situation here.  ScreenUpdate has just restored the
      screen contents as it was before we started drawing this menu.
index 687f7fbd119233621637d6b1e67db9aeaeaaf98b..9dea46f0b76d2ff4e2b0114f29568ab3d93d0c99 100644 (file)
@@ -198,6 +198,9 @@ struct tty_display_info
   /* Nonzero means use ^S/^Q for flow control.  */
 
   unsigned flow_control : 1;
+
+  /* Non-zero means we are displaying a TTY menu on this tty.  */
+  unsigned showing_menu : 1;
 };
 
 /* A chain of structures for all tty devices currently in use. */