From cdc04b4509772f2324c4ca63732caed2858cedf3 Mon Sep 17 00:00:00 2001 From: Jeff Walsh Date: Sat, 15 Jun 2019 14:44:47 +1000 Subject: [PATCH] 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(-) create mode 100644 src/pgtkmenu.c diff --git a/configure.ac b/configure.ac index b168131f42a..ce9d0168476 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 c6ced689a67..e1dea884c76 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 769a852e733..42d93737b93 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 718c0f12a59..76d74200ac8 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 44749ade75a..baad4496e4d 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 ce702028348..140f29a473b 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 00000000000..bbe47ddad6b --- /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 . */ + +/* + */ + + +/* This should be the first include, as it may set up #defines affecting + interpretation of even the system includes. */ +#include + +#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 + + +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 a380c11eb15..ed8d7e841be 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 d14525e740c..10dc9fc9793 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 e722a757806..c523111fbd1 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; -- 2.39.5