emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/pgtk cdc04b4 010/100: Implement menubar for pgtk emacs


From: Yuuki Harano
Subject: feature/pgtk cdc04b4 010/100: Implement menubar for pgtk emacs
Date: Tue, 24 Nov 2020 08:02:26 -0500 (EST)

branch: feature/pgtk
commit cdc04b4509772f2324c4ca63732caed2858cedf3
Author: Jeff Walsh <fejfighter@gmail.com>
Commit: Jeff Walsh <fejfighter@gmail.com>

    Implement menubar for pgtk emacs
    
        * src/xdisp.c (display_menu_bar): add pgtk case
    
        * ../src/pgtkterm.c (pgtk_create_terminal): update hooks
        (pgtk_menu_show): delete
    
        * src/pgtkterm.h: add decls
    
        * src/pgtkmenu.c: new file
    
        * ../src/pgtkfns.c (x_set_menu_bar_lines)
        (x_change_tool_bar_height, x_set_tool_bar_lines)
        (Fx_create_frame):
---
 configure.ac     |   2 +-
 lisp/menu-bar.el |   1 +
 src/emacs.c      |   1 +
 src/lisp.h       |   2 +-
 src/menu.h       |   6 +
 src/pgtkfns.c    | 117 +++++---------
 src/pgtkmenu.c   | 476 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/pgtkterm.c   |  11 +-
 src/pgtkterm.h   |   6 +
 src/xdisp.c      |   5 +
 10 files changed, 543 insertions(+), 84 deletions(-)

diff --git a/configure.ac b/configure.ac
index b168131..ce9d016 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2827,7 +2827,7 @@ LIBS=$OLD_LIBS
 PGTK_OBJ=
 PGTK_LIBS=
 if test "$window_system" = "pgtk"; then
-  PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o xsettings.o"
+  PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o xsettings.o"
   PGTK_LIBS="$GTK_LIBS -ldl"
   AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.])
 fi
diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el
index c6ced68..e1dea88 100644
--- a/lisp/menu-bar.el
+++ b/lisp/menu-bar.el
@@ -2506,6 +2506,7 @@ See `menu-bar-mode' for more information."
 
 (declare-function x-menu-bar-open "term/x-win" (&optional frame))
 (declare-function w32-menu-bar-open "term/w32-win" (&optional frame))
+(declare-function pgtk-menu-bar-open "term/pgtk-win" (&optional frame))
 
 (defun lookup-key-ignore-too-long (map key)
   "Call `lookup-key' and convert numeric values to nil."
diff --git a/src/emacs.c b/src/emacs.c
index 769a852..42d9373 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1921,6 +1921,7 @@ Using an Emacs configured with --with-x-toolkit=lucid 
does not have this problem
       syms_of_pgtkterm();
       syms_of_pgtkfns();
       syms_of_pgtkselect ();
+      syms_of_pgtkmenu ();
       syms_of_fontset ();
       syms_of_xsettings ();
       syms_of_xwidget ();
diff --git a/src/lisp.h b/src/lisp.h
index 718c0f1..76d7420 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3298,7 +3298,7 @@ struct frame;
 #endif
 
 /* Define if the windowing system provides a tool-bar.  */
-#if (defined (USE_GTK) && !defined(HAVE_PGTK)) || defined (HAVE_NS)
+#if defined (USE_GTK) || defined (HAVE_NS)
 #define HAVE_EXT_TOOL_BAR true
 #endif
 
diff --git a/src/menu.h b/src/menu.h
index 44749ad..baad449 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -59,6 +59,12 @@ extern Lisp_Object ns_menu_show (struct frame *, int, int, 
int,
                                 Lisp_Object, const char **);
 extern void ns_activate_menubar (struct frame *);
 #endif
+#ifdef HAVE_PGTK
+extern Lisp_Object pgtk_menu_show (struct frame *, int, int, int,
+                                Lisp_Object, const char **);
+extern void pgtk_activate_menubar (struct frame *);
+#endif
+
 extern Lisp_Object tty_menu_show (struct frame *, int, int, int,
                                  Lisp_Object, const char **);
 extern ptrdiff_t menu_item_width (const unsigned char *);
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index ce70202..140f29a 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -465,31 +465,63 @@ pgtk_set_doc_edited (void)
 static void
 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 {
-#if 0
   int nlines;
-  if (FRAME_MINIBUF_ONLY_P (f))
+  /* Right now, menu bars don't work properly in minibuf-only frames;
+     most of the commands try to apply themselves to the minibuffer
+     frame itself, and get an error because you can't switch buffers
+     in or split the minibuffer window.  */
+  if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
     return;
 
-  if (TYPE_RANGED_INTEGERP (int, value))
+  if (TYPE_RANGED_FIXNUMP (int, value))
     nlines = XFIXNUM (value);
   else
     nlines = 0;
 
+  /* Make sure we redisplay all windows in this frame.  */
+  fset_redisplay (f);
+
   FRAME_MENU_BAR_LINES (f) = 0;
+  FRAME_MENU_BAR_HEIGHT (f) = 0;
   if (nlines)
     {
       FRAME_EXTERNAL_MENU_BAR (f) = 1;
-      /* does for all frames, whereas we just want for one frame
-        [NSMenu setMenuBarVisible: YES]; */
+      if (FRAME_PGTK_P (f) && f->output_data.pgtk->menubar_widget == 0)
+       /* Make sure next redisplay shows the menu bar.  */
+       XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
     }
   else
     {
       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
-        free_frame_menubar (f);
-      /*      [NSMenu setMenuBarVisible: NO]; */
+       free_frame_menubar (f);
       FRAME_EXTERNAL_MENU_BAR (f) = 0;
+      if (FRAME_X_P (f))
+       f->output_data.pgtk->menubar_widget = 0;
+    }
+
+  adjust_frame_glyphs (f);
+}
+
+/* Set the pixel height of the tool bar of frame F to HEIGHT.  */
+static void
+x_change_tool_bar_height (struct frame *f, int height)
+{
+  FRAME_TOOL_BAR_LINES (f) = 0;
+  FRAME_TOOL_BAR_HEIGHT (f) = 0;
+  if (height)
+    {
+      FRAME_EXTERNAL_TOOL_BAR (f) = true;
+      if (FRAME_X_P (f) && f->output_data.pgtk->toolbar_widget == 0)
+       /* Make sure next redisplay shows the tool bar.  */
+       XWINDOW (FRAME_SELECTED_WINDOW (f))->update_mode_line = true;
+      update_frame_tool_bar (f);
+    }
+  else
+    {
+      if (FRAME_EXTERNAL_TOOL_BAR (f))
+        free_frame_tool_bar (f);
+      FRAME_EXTERNAL_TOOL_BAR (f) = false;
     }
-#endif
 }
 
 
@@ -497,70 +529,20 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, 
Lisp_Object oldval)
 static void
 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 {
-#if 0
-  /* Currently, when the tool bar change state, the frame is resized.
-
-     TODO: It would be better if this didn't occur when 1) the frame
-     is full height or maximized or 2) when specified by
-     `frame-inhibit-implied-resize'. */
   int nlines;
 
-  NSTRACE ("x_set_tool_bar_lines");
-
+  /* Treat tool bars like menu bars.  */
   if (FRAME_MINIBUF_ONLY_P (f))
     return;
 
-  if (RANGED_INTEGERP (0, value, INT_MAX))
+  /* Use VALUE only if an int >= 0.  */
+  if (RANGED_FIXNUMP (0, value, INT_MAX))
     nlines = XFIXNAT (value);
   else
     nlines = 0;
 
-  if (nlines)
-    {
-      FRAME_EXTERNAL_TOOL_BAR (f) = 1;
-      update_frame_tool_bar (f);
-    }
-  else
-    {
-      if (FRAME_EXTERNAL_TOOL_BAR (f))
-        {
-          free_frame_tool_bar (f);
-          FRAME_EXTERNAL_TOOL_BAR (f) = 0;
-
-          {
-            EmacsView *view = FRAME_PGTK_VIEW (f);
-            int fs_state = [view fullscreenState];
-
-            if (fs_state == FULLSCREEN_MAXIMIZED)
-              {
-                [view setFSValue:FULLSCREEN_WIDTH];
-              }
-            else if (fs_state == FULLSCREEN_HEIGHT)
-              {
-                [view setFSValue:FULLSCREEN_NONE];
-              }
-          }
-       }
-    }
+  x_change_tool_bar_height (f, nlines * FRAME_LINE_HEIGHT (f));
 
-  {
-    int inhibit
-      = ((f->after_make_frame
-         && !f->tool_bar_resized
-         && (EQ (frame_inhibit_implied_resize, Qt)
-             || (CONSP (frame_inhibit_implied_resize)
-                 && !NILP (Fmemq (Qtool_bar_lines,
-                                  frame_inhibit_implied_resize))))
-         && NILP (get_frame_param (f, Qfullscreen)))
-        ? 0
-        : 2);
-
-    NSTRACE_MSG ("inhibit:%d", inhibit);
-
-    frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
-    adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
-  }
-#endif
 }
 
 
@@ -1327,25 +1309,14 @@ This function is an internal primitive--use 
`make-frame' instead.  */)
   gui_default_parameter (f, parms, Qno_accept_focus, Qnil,
                       NULL, NULL, RES_TYPE_BOOLEAN);
 
-#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   /* Create the menu bar.  */
   if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
     {
-#if 0
       /* If this signals an error, we haven't set size hints for the
         frame and we didn't make it visible.  */
       initialize_frame_menubar (f);
-#endif
 
-#ifndef USE_GTK
-      /* This is a no-op, except under Motif where it arranges the
-        main window for the widgets on it.  */
-      lw_set_main_areas (FRAME_X_OUTPUT(f)->column_widget,
-                        FRAME_X_OUTPUT(f)->menubar_widget,
-                        FRAME_X_OUTPUT(f)->edit_widget);
-#endif /* not USE_GTK */
     }
-#endif /* USE_X_TOOLKIT || USE_GTK */
 
   /* Consider frame official, now.  */
   f->can_set_window_size = true;
diff --git a/src/pgtkmenu.c b/src/pgtkmenu.c
new file mode 100644
index 0000000..bbe47dd
--- /dev/null
+++ b/src/pgtkmenu.c
@@ -0,0 +1,476 @@
+/* Pure GTK3 menu and toolbar module.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs 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.
+
+GNU Emacs 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 GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/*
+ */
+
+
+/* This should be the first include, as it may set up #defines affecting
+   interpretation of even the system includes.  */
+#include <config.h>
+
+#include "lisp.h"
+#include "frame.h"
+#include "window.h"
+#include "character.h"
+#include "buffer.h"
+#include "keymap.h"
+#include "coding.h"
+#include "commands.h"
+#include "blockinput.h"
+#include "termhooks.h"
+#include "keyboard.h"
+#include "menu.h"
+#include "pdumper.h"
+
+#include "gtkutil.h"
+#include <gtk/gtk.h>
+
+
+Lisp_Object
+pgtk_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
+{
+  return Qnil;
+}
+
+
+
+/* Gtk calls callbacks just because we tell it what item should be
+   selected in a radio group.  If this variable is set to a non-zero
+   value, we are creating menus and don't want callbacks right now.
+*/
+static bool xg_crazy_callback_abort;
+
+/* This callback is called from the menu bar pulldown menu
+   when the user makes a selection.
+   Figure out what the user chose
+   and put the appropriate events into the keyboard buffer.  */
+static void
+menubar_selection_callback (GtkWidget *widget, gpointer client_data)
+{
+  xg_menu_item_cb_data *cb_data = client_data;
+
+  if (xg_crazy_callback_abort)
+    return;
+
+  if (! cb_data || ! cb_data->cl_data || ! cb_data->cl_data->f)
+    return;
+
+  /* For a group of radio buttons, GTK calls the selection callback first
+     for the item that was active before the selection and then for the one 
that
+     is active after the selection.  For C-h k this means we get the help on
+     the deselected item and then the selected item is executed.  Prevent that
+     by ignoring the non-active item.  */
+  if (GTK_IS_RADIO_MENU_ITEM (widget)
+      && ! gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)))
+    return;
+
+  /* When a menu is popped down, X generates a focus event (i.e. focus
+     goes back to the frame below the menu).  Since GTK buffers events,
+     we force it out here before the menu selection event.  Otherwise
+     sit-for will exit at once if the focus event follows the menu selection
+     event.  */
+
+  block_input ();
+  while (gtk_events_pending ())
+    gtk_main_iteration ();
+  unblock_input ();
+
+  find_and_call_menu_selection (cb_data->cl_data->f,
+                                cb_data->cl_data->menu_bar_items_used,
+                                cb_data->cl_data->menu_bar_vector,
+                                cb_data->call_data);
+}
+
+static void
+menu_highlight_callback (GtkWidget *widget, gpointer call_data)
+{
+  xg_menu_item_cb_data *cb_data;
+  Lisp_Object help;
+
+  cb_data = g_object_get_data (G_OBJECT (widget), XG_ITEM_DATA);
+  if (! cb_data) return;
+
+  help = call_data ? cb_data->help : Qnil;
+}
+
+
+/* This callback is invoked when a dialog or menu is finished being
+   used and has been unposted.  */
+
+static void
+popup_deactivate_callback (GtkWidget *widget, gpointer client_data)
+{
+}
+
+
+
+
+/* Set the contents of the menubar widgets of frame F.
+   The argument FIRST_TIME is currently ignored;
+   it is set the first time this is called, from initialize_frame_menubar.  */
+
+void
+set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
+{
+  GtkWidget * menubar_widget;
+  Lisp_Object items;
+  widget_value *wv, *first_wv, *prev_wv = 0;
+  int i;
+  int *submenu_start, *submenu_end;
+  bool *submenu_top_level_items;
+  int *submenu_n_panes;
+
+
+  menubar_widget = f->output_data.pgtk->menubar_widget;
+
+  XSETFRAME(Vmenu_updating_frame, f);
+
+  if (! menubar_widget)
+    deep_p = true;
+
+  if (deep_p)
+    {
+      struct buffer *prev = current_buffer;
+      Lisp_Object buffer;
+      ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+      int previous_menu_items_used = f->menu_bar_items_used;
+      Lisp_Object *previous_items
+       = alloca (previous_menu_items_used * sizeof *previous_items);
+      int subitems;
+
+      /* If we are making a new widget, its contents are empty,
+        do always reinitialize them.  */
+      if (! menubar_widget)
+       previous_menu_items_used = 0;
+
+      buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
+      specbind (Qinhibit_quit, Qt);
+      /* Don't let the debugger step into this code
+        because it is not reentrant.  */
+      specbind (Qdebug_on_next_call, Qnil);
+
+      record_unwind_save_match_data ();
+      if (NILP (Voverriding_local_map_menu_flag))
+       {
+         specbind (Qoverriding_terminal_local_map, Qnil);
+         specbind (Qoverriding_local_map, Qnil);
+       }
+
+      set_buffer_internal_1 (XBUFFER (buffer));
+
+      /* Run the Lucid hook.  */
+      safe_run_hooks (Qactivate_menubar_hook);
+
+      /* If it has changed current-menubar from previous value,
+        really recompute the menubar from the value.  */
+      if (! NILP (Vlucid_menu_bar_dirty_flag))
+       call0 (Qrecompute_lucid_menubar);
+      safe_run_hooks (Qmenu_bar_update_hook);
+      fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
+
+      items = FRAME_MENU_BAR_ITEMS (f);
+
+      /* Save the frame's previous menu bar contents data.  */
+      if (previous_menu_items_used)
+       memcpy (previous_items, XVECTOR (f->menu_bar_vector)->contents,
+               previous_menu_items_used * word_size);
+
+      /* Fill in menu_items with the current menu bar contents.
+        This can evaluate Lisp code.  */
+      save_menu_items ();
+
+      menu_items = f->menu_bar_vector;
+      menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
+      subitems = ASIZE (items) / 4;
+      submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
+      submenu_end = alloca (subitems * sizeof *submenu_end);
+      submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
+      submenu_top_level_items = alloca (subitems
+                                       * sizeof *submenu_top_level_items);
+      init_menu_items ();
+      for (i = 0; i < subitems; i++)
+       {
+         Lisp_Object key, string, maps;
+
+         key = AREF (items, 4 * i);
+         string = AREF (items, 4 * i + 1);
+         maps = AREF (items, 4 * i + 2);
+         if (NILP (string))
+           break;
+
+         submenu_start[i] = menu_items_used;
+
+         menu_items_n_panes = 0;
+         submenu_top_level_items[i]
+           = parse_single_submenu (key, string, maps);
+         submenu_n_panes[i] = menu_items_n_panes;
+
+         submenu_end[i] = menu_items_used;
+       }
+
+      submenu_start[i] = -1;
+      finish_menu_items ();
+
+      /* Convert menu_items into widget_value trees
+        to display the menu.  This cannot evaluate Lisp code.  */
+
+      wv = make_widget_value ("menubar", NULL, true, Qnil);
+      wv->button_type = BUTTON_TYPE_NONE;
+      first_wv = wv;
+
+      for (i = 0; submenu_start[i] >= 0; i++)
+       {
+         menu_items_n_panes = submenu_n_panes[i];
+         wv = digest_single_submenu (submenu_start[i], submenu_end[i],
+                                     submenu_top_level_items[i]);
+         if (prev_wv)
+           prev_wv->next = wv;
+         else
+           first_wv->contents = wv;
+         /* Don't set wv->name here; GC during the loop might relocate it.  */
+         wv->enabled = true;
+         wv->button_type = BUTTON_TYPE_NONE;
+         prev_wv = wv;
+       }
+
+      set_buffer_internal_1 (prev);
+
+      /* If there has been no change in the Lisp-level contents
+        of the menu bar, skip redisplaying it.  Just exit.  */
+
+      /* Compare the new menu items with the ones computed last time.  */
+      for (i = 0; i < previous_menu_items_used; i++)
+       if (menu_items_used == i
+           || (!EQ (previous_items[i], AREF (menu_items, i))))
+         break;
+      if (i == menu_items_used && i == previous_menu_items_used && i != 0)
+       {
+         /* The menu items have not changed.  Don't bother updating
+            the menus in any form, since it would be a no-op.  */
+         free_menubar_widget_value_tree (first_wv);
+         discard_menu_items ();
+         unbind_to (specpdl_count, Qnil);
+         return;
+       }
+
+      /* The menu items are different, so store them in the frame.  */
+      fset_menu_bar_vector (f, menu_items);
+      f->menu_bar_items_used = menu_items_used;
+
+      /* This undoes save_menu_items.  */
+      unbind_to (specpdl_count, Qnil);
+
+      /* Now GC cannot happen during the lifetime of the widget_value,
+        so it's safe to store data from a Lisp_String.  */
+      wv = first_wv->contents;
+      for (i = 0; i < ASIZE (items); i += 4)
+       {
+         Lisp_Object string;
+         string = AREF (items, i + 1);
+         if (NILP (string))
+            break;
+          wv->name = SSDATA (string);
+          update_submenu_strings (wv->contents);
+          wv = wv->next;
+       }
+
+    }
+  else
+    {
+      /* Make a widget-value tree containing
+        just the top level menu bar strings.  */
+
+      wv = make_widget_value ("menubar", NULL, true, Qnil);
+      wv->button_type = BUTTON_TYPE_NONE;
+      first_wv = wv;
+
+      items = FRAME_MENU_BAR_ITEMS (f);
+      for (i = 0; i < ASIZE (items); i += 4)
+       {
+         Lisp_Object string;
+
+         string = AREF (items, i + 1);
+         if (NILP (string))
+           break;
+
+         wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
+         wv->button_type = BUTTON_TYPE_NONE;
+         /* This prevents lwlib from assuming this
+            menu item is really supposed to be empty.  */
+         /* The intptr_t cast avoids a warning.
+            This value just has to be different from small integers.  */
+         wv->call_data = (void *) (intptr_t) (-1);
+
+         if (prev_wv)
+           prev_wv->next = wv;
+         else
+           first_wv->contents = wv;
+         prev_wv = wv;
+       }
+
+      /* Forget what we thought we knew about what is in the
+        detailed contents of the menu bar menus.
+        Changing the top level always destroys the contents.  */
+      f->menu_bar_items_used = 0;
+    }
+
+  block_input();
+
+  xg_crazy_callback_abort = true;
+  if (menubar_widget)
+    {
+      /* The fourth arg is DEEP_P, which says to consider the entire
+        menu trees we supply, rather than just the menu bar item names.  */
+      xg_modify_menubar_widgets (menubar_widget,
+                                 f,
+                                 first_wv,
+                                 deep_p,
+                                 G_CALLBACK (menubar_selection_callback),
+                                 G_CALLBACK (popup_deactivate_callback),
+                                 G_CALLBACK (menu_highlight_callback));
+    }
+  else
+    {
+      menubar_widget
+        = xg_create_widget ("menubar", "menubar", f, first_wv,
+                            G_CALLBACK (menubar_selection_callback),
+                            G_CALLBACK (popup_deactivate_callback),
+                            G_CALLBACK (menu_highlight_callback));
+
+      f->output_data.pgtk->menubar_widget = menubar_widget;
+    }
+
+  free_menubar_widget_value_tree (first_wv);
+  xg_update_frame_menubar (f);
+
+  xg_crazy_callback_abort = false;
+
+  unblock_input ();
+}
+
+
+
+/* Called from Fx_create_frame to create the initial menubar of a frame
+   before it is mapped, so that the window is mapped with the menubar already
+   there instead of us tacking it on later and thrashing the window after it
+   is visible.  */
+
+void
+initialize_frame_menubar (struct frame *f)
+{
+  /* This function is called before the first chance to redisplay
+     the frame.  It has to be, so the frame will have the right size.  */
+  fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
+  set_frame_menubar (f, true, true);
+}
+
+
+void pgtk_activate_menubar (struct frame *f)
+{
+  set_frame_menubar(f, false, false);
+
+  /* f->output_data.pgtk->menubar_active = 1; */
+}
+
+
+Lisp_Object
+pgtk_menu_show (struct frame *f, int x, int y, int menuflags,
+            Lisp_Object title, const char **error_name)
+{
+  Lisp_Object tem;
+
+  block_input ();
+
+
+  unblock_input ();
+
+  // not implemented.
+  return Qnil;
+}
+
+DEFUN ("x-menu-bar-open-internal", Fx_menu_bar_open_internal, 
Sx_menu_bar_open_internal, 0, 1, "i",
+       doc: /* Start key navigation of the menu bar in FRAME.
+This initially opens the first menu bar item and you can then navigate with the
+arrow keys, select a menu entry with the return key or cancel with the
+escape key.  If FRAME has no menu bar this function does nothing.
+
+If FRAME is nil or not given, use the selected frame.  */)
+  (Lisp_Object frame)
+{
+  GtkWidget *menubar;
+  struct frame *f;
+
+  block_input ();
+  f = decode_window_system_frame (frame);
+
+  if (FRAME_EXTERNAL_MENU_BAR (f))
+    set_frame_menubar (f, false, true);
+
+  menubar = FRAME_X_OUTPUT (f)->menubar_widget;
+  if (menubar)
+    {
+      /* Activate the first menu.  */
+      GList *children = gtk_container_get_children (GTK_CONTAINER (menubar));
+
+      if (children)
+        {
+          g_signal_emit_by_name (children->data, "activate_item");
+          g_list_free (children);
+        }
+    }
+  unblock_input ();
+
+  return Qnil;
+}
+
+
+static const char * button_names [] = {
+  "button1", "button2", "button3", "button4", "button5",
+  "button6", "button7", "button8", "button9", "button10" };
+
+extern Lisp_Object
+pgtk_dialog_show (struct frame *f, Lisp_Object title,
+                Lisp_Object header, char **error)
+{
+  return Qnil;
+}
+
+/* The following is used by delayed window autoselection.  */
+
+DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, 
Smenu_or_popup_active_p, 0, 0, 0,
+       doc: /* SKIP: real doc in xmenu.c.  */)
+  (void)
+{
+  struct frame *f;
+  f = SELECTED_FRAME ();
+  //  return (f->output_data.pgtk->menubar_active > 0) ? Qt : Qnil;
+  return Qnil;
+}
+
+void
+syms_of_pgtkmenu (void)
+{
+  // current_popup_menu = NULL;
+  // PDUMPER_IGNORE (current_popup_menu);
+
+  DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
+  DEFSYM (Qunsupported__w32_dialog, "unsupported--w32-dialog");
+
+  defsubr (&Smenu_or_popup_active_p);
+}
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index a380c11..ed8d7e8 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -4253,14 +4253,6 @@ pgtk_fullscreen_hook (struct frame *f)
     }
 }
 
-static Lisp_Object
-pgtk_menu_show (struct frame *f, int x, int y, int menuflags,
-            Lisp_Object title, const char **error_name)
-{
-  // not implemented.
-  return Qnil;
-}
-
 /* This function is called when the last frame on a display is deleted. */
 void
 pgtk_delete_terminal (struct terminal *terminal)
@@ -4332,7 +4324,8 @@ pgtk_create_terminal (struct pgtk_display_info *dpyinfo)
   // terminal->frame_raise_lower_hook = pgtk_frame_raise_lower;
   terminal->fullscreen_hook = pgtk_fullscreen_hook;
   terminal->menu_show_hook = pgtk_menu_show;
-  // terminal->popup_dialog_hook = pgtk_popup_dialog;
+  terminal->activate_menubar_hook = pgtk_activate_menubar;
+  terminal->popup_dialog_hook = pgtk_popup_dialog;
   terminal->set_vertical_scroll_bar_hook = pgtk_set_vertical_scroll_bar;
   terminal->set_horizontal_scroll_bar_hook = pgtk_set_horizontal_scroll_bar;
   terminal->condemn_scroll_bars_hook = pgtk_condemn_scroll_bars;
diff --git a/src/pgtkterm.h b/src/pgtkterm.h
index d14525e..10dc9fc 100644
--- a/src/pgtkterm.h
+++ b/src/pgtkterm.h
@@ -548,6 +548,12 @@ extern void pgtk_set_cr_source_with_color (struct frame 
*f, unsigned long color)
 extern void pgtk_cr_draw_frame (cairo_t *cr, struct frame *f);
 extern void pgtk_cr_destroy_surface(struct frame *f);
 
+/* Defined in pgtkmenu.c */
+extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, 
Lisp_Object contents);
+extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, 
Lisp_Object header, char **error);
+extern void initialize_frame_menubar (struct frame *);
+
+
 /* Symbol initializations implemented in each pgtk sources. */
 extern void syms_of_pgtkterm (void);
 extern void syms_of_pgtkfns (void);
diff --git a/src/xdisp.c b/src/xdisp.c
index e722a75..c523111 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -25028,6 +25028,11 @@ display_menu_bar (struct window *w)
   if (FRAME_W32_P (f))
     return;
 #endif
+#if defined (HAVE_PGTK)
+  if (FRAME_PGTK_P (f))
+    return;
+#endif
+
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   if (FRAME_X_P (f))
     return;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]